From a4f455cdcdfdbdeb229b6dc17a944cbe4e51b1b7 Mon Sep 17 00:00:00 2001 From: franklahm Date: Thu, 14 May 2009 13:46:08 +0000 Subject: [PATCH] dbd now does many things it should do in the end. In volinfo.c/h: translate vol options to ad options like afp/volume.c does it. Rename dbd.c to cmd_dbd.c. --- etc/cnid_dbd/.cvsignore | 1 + etc/cnid_dbd/Makefile.am | 5 +- etc/cnid_dbd/{dbd.c => cmd_dbd.c} | 71 ++--- etc/cnid_dbd/cmd_dbd.h | 13 + etc/cnid_dbd/cmd_dbd_lookup.c | 189 +++++++++++++ etc/cnid_dbd/cmd_dbd_scanvol.c | 438 ++++++++++++++++++++++-------- etc/cnid_dbd/dbd_add.c | 10 +- etc/cnid_dbd/dbd_lookup.c | 15 +- etc/cnid_dbd/dbif.c | 43 ++- etc/cnid_dbd/dbif.h | 6 +- etc/cnid_dbd/main.c | 4 +- include/atalk/volinfo.h | 3 +- libatalk/util/volinfo.c | 11 + 13 files changed, 621 insertions(+), 188 deletions(-) rename etc/cnid_dbd/{dbd.c => cmd_dbd.c} (87%) create mode 100644 etc/cnid_dbd/cmd_dbd_lookup.c diff --git a/etc/cnid_dbd/.cvsignore b/etc/cnid_dbd/.cvsignore index 33dffa14..8a362ee0 100644 --- a/etc/cnid_dbd/.cvsignore +++ b/etc/cnid_dbd/.cvsignore @@ -2,5 +2,6 @@ Makefile Makefile.in cnid_metad cnid_dbd +dbd .deps .libs diff --git a/etc/cnid_dbd/Makefile.am b/etc/cnid_dbd/Makefile.am index e5e237cb..eeb8b6f7 100644 --- a/etc/cnid_dbd/Makefile.am +++ b/etc/cnid_dbd/Makefile.am @@ -16,7 +16,10 @@ cnid_dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@ cnid_metad_SOURCES = cnid_metad.c usockfd.c db_param.c cnid_metad_LDADD = $(top_builddir)/libatalk/libatalk.la -dbd_SOURCES = dbd.c dbif.c pack.c cmd_dbd_scanvol.c +dbd_SOURCES = cmd_dbd.c cmd_dbd_scanvol.c cmd_dbd_lookup.c \ + dbif.c pack.c \ + dbd_delete.c dbd_update.c dbd_add.c dbd_lookup.c \ + dbd_rebuild_add.c dbd_getstamp.c dbd_CFLAGS = $(AM_CFLAGS) dbd_LDADD = $(top_builddir)/libatalk/libatalk.la @BDB_LIBS@ diff --git a/etc/cnid_dbd/dbd.c b/etc/cnid_dbd/cmd_dbd.c similarity index 87% rename from etc/cnid_dbd/dbd.c rename to etc/cnid_dbd/cmd_dbd.c index 39384ebf..337fea65 100644 --- a/etc/cnid_dbd/dbd.c +++ b/etc/cnid_dbd/cmd_dbd.c @@ -1,5 +1,5 @@ /* - $Id: dbd.c,v 1.3 2009-05-06 11:54:24 franklahm Exp $ + $Id: cmd_dbd.c,v 1.1 2009-05-14 13:46:08 franklahm Exp $ Copyright (c) 2009 Frank Lahm @@ -40,7 +40,7 @@ static DBD *dbd; -static volatile sig_atomic_t alarmed; +volatile sig_atomic_t alarmed; static int verbose; /* Logging flag */ static int exclusive; /* Exclusive volume access */ static struct db_param db_param = { @@ -76,8 +76,7 @@ void dbd_log(enum logtype lt, char *fmt, ...) /* SIGNAL handling: - ignore everything except SIGTERM which we catch and which causes - a clean exit. + catch SIGINT and SIGTERM which cause clean exit. Ignore anything else. */ static void sig_handler(int signo) @@ -93,20 +92,19 @@ void set_signal(void) sv.sa_handler = sig_handler; sv.sa_flags = SA_RESTART; sigemptyset(&sv.sa_mask); - sigaddset(&sv.sa_mask, SIGTERM); if (sigaction(SIGTERM, &sv, NULL) < 0) { dbd_log( LOGSTD, "error in sigaction(SIGTERM): %s", strerror(errno)); exit(EXIT_FAILURE); } + if (sigaction(SIGINT, &sv, NULL) < 0) { + dbd_log( LOGSTD, "error in sigaction(SIGINT): %s", strerror(errno)); + exit(EXIT_FAILURE); + } memset(&sv, 0, sizeof(struct sigaction)); sv.sa_handler = SIG_IGN; sigemptyset(&sv.sa_mask); - if (sigaction(SIGINT, &sv, NULL) < 0) { - dbd_log( LOGSTD, "error in sigaction(SIGINT): %s", strerror(errno)); - exit(EXIT_FAILURE); - } if (sigaction(SIGABRT, &sv, NULL) < 0) { dbd_log( LOGSTD, "error in sigaction(SIGABRT): %s", strerror(errno)); exit(EXIT_FAILURE); @@ -121,22 +119,6 @@ void set_signal(void) } } -#if 0 -static void block_sigs_onoff(int block) -{ - sigset_t set; - - sigemptyset(&set); - sigaddset(&set, SIGINT); - sigaddset(&set, SIGTERM); - if (block) - sigprocmask(SIG_BLOCK, &set, NULL); - else - sigprocmask(SIG_UNBLOCK, &set, NULL); - return; -} -#endif - int get_lock(void) { int lockfd; @@ -274,7 +256,7 @@ int main(int argc, char **argv) volpath = argv[optind]; /* Put "/.AppleDB" at end of volpath */ - if ( (strlen(volpath) + strlen("/.AppleDB")) > (PATH_MAX -1) ) { + if ( (strlen(volpath) + strlen("/.AppleDB")) > (PATH_MAX - 1) ) { dbd_log( LOGSTD, "Volume pathname too long"); exit(EXIT_FAILURE); } @@ -282,24 +264,20 @@ int main(int argc, char **argv) strncpy(dbpath, volpath, PATH_MAX - 1); strcat(dbpath, "/.AppleDB"); - /* cd to .AppleDB dir */ + /* Remember cwd */ int cdir; if ((cdir = open(".", O_RDONLY)) < 0) { dbd_log( LOGSTD, "Can't open dir: %s", strerror(errno)); exit(EXIT_FAILURE); } - if (chdir(dbpath) < 0) { - dbd_log( LOGSTD, "chdir to %s failed: %s", dbpath, strerror(errno)); - exit(EXIT_FAILURE); - } /* Before we do anything else, check if there is an instance of cnid_dbd running already and silently exit if yes. */ lockfd = get_lock(); - - /* Ignore everything except SIGTERM */ + + /* Setup signal handling */ set_signal(); /* Setup logging. Should be portable among *NIXes */ @@ -309,11 +287,11 @@ int main(int argc, char **argv) setuplog("default log_debug /dev/tty"); /* Load .volinfo file */ - if ( -1 == loadvolinfo(volpath, &volinfo)) { + if (loadvolinfo(volpath, &volinfo) == -1) { dbd_log( LOGSTD, "Unkown volume options!"); exit(EXIT_FAILURE); } - if ( -1 == vol_load_charsets(&volinfo)) { + if (vol_load_charsets(&volinfo) == -1) { dbd_log( LOGSTD, "Error loading charsets!"); exit(EXIT_FAILURE); } @@ -321,41 +299,42 @@ int main(int argc, char **argv) /* Lets start with the BerkeleyDB stuff */ - if (NULL == (dbd = dbif_init("cnid2.db"))) - exit(2); + if ((dbd = dbif_init(dbpath, "cnid2.db")) == NULL) + exit(EXIT_FAILURE); - if (dbif_env_open(dbd, &db_param, DBOPTIONS) < 0) { + if (dbif_env_open(dbd, &db_param, exclusive ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) { dbd_log( LOGSTD, "error opening database!"); exit(EXIT_FAILURE); } - dbd_log( LOGDEBUG, "Finished opening BerkeleyDB databases including recovery."); + if (exclusive) + dbd_log( LOGDEBUG, "Finished recovery."); if (dbif_open(dbd, &db_param, rebuildindexes) < 0) { dbif_close(dbd); exit(EXIT_FAILURE); } - if ((fchdir(cdir)) < 0) { - dbd_log(LOGSTD, "fchdir: %s", strerror(errno)); - goto cleanup; - } - if (dump) { if (dbif_dump(dbd, dumpindexes) < 0) { dbd_log( LOGSTD, "Error dumping database"); } } else if (rebuild || scan) { if (cmd_dbd_scanvol(dbd, &volinfo, flags) < 0) { - dbd_log( LOGSTD, "Fatal error repairing database. Please rm -r it."); + dbd_log( LOGSTD, "Error repairing database."); } } cleanup: - if (dbif_close(dbd) < 0) + if (dbif_close(dbd) < 0) { + dbd_log( LOGSTD, "Error closing database"); exit(EXIT_FAILURE); + } free_lock(lockfd); + if ((fchdir(cdir)) < 0) + dbd_log(LOGSTD, "fchdir: %s", strerror(errno)); + return 0; } diff --git a/etc/cnid_dbd/cmd_dbd.h b/etc/cnid_dbd/cmd_dbd.h index 70006fd3..2b4c5533 100644 --- a/etc/cnid_dbd/cmd_dbd.h +++ b/etc/cnid_dbd/cmd_dbd.h @@ -1,6 +1,9 @@ #ifndef CMD_DBD_H #define CMD_DBD_H +#include +#include + #include #include "dbif.h" @@ -18,7 +21,17 @@ typedef unsigned int dbd_flags_t; #define STRCMP(a,b,c) \ (strcmp(a,c) b 0) +extern volatile sig_atomic_t alarmed; +extern struct volinfo *volinfo; +extern char cwdbuf[MAXPATHLEN+1]; + extern void dbd_log(enum logtype lt, char *fmt, ...); extern int cmd_dbd_scanvol(DBD *dbd, struct volinfo *volinfo, dbd_flags_t flags); +/* + Functions for querying the database which couldn't be reused from the existing + funcs pool of dbd_* for one reason or another +*/ +extern int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag); +extern int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply); #endif /* CMD_DBD_H */ diff --git a/etc/cnid_dbd/cmd_dbd_lookup.c b/etc/cnid_dbd/cmd_dbd_lookup.c new file mode 100644 index 00000000..d2e4a9a2 --- /dev/null +++ b/etc/cnid_dbd/cmd_dbd_lookup.c @@ -0,0 +1,189 @@ +/* + * $Id: cmd_dbd_lookup.c,v 1.1 2009-05-14 13:46:08 franklahm Exp $ + * + * Copyright (C) Frank Lahm 2009 + * All Rights Reserved. See COPYING. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif /* HAVE_CONFIG_H */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "pack.h" +#include "dbif.h" +#include "dbd.h" +#include "cmd_dbd.h" + +/* Pull these in from dbd_add.c */ +extern int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply); +extern int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply); + +/* + * This returns the CNID corresponding to a particular file and logs any inconsitencies. + * If roflags == 1 we only scan, if roflag == 0, we modify, but we do _not_ *add* as does + * dbd_lookup. + */ + +int cmd_dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int roflag) +{ + unsigned char *buf; + DBT key, devdata, diddata; + uint64_t dev = 0; + int devino = 1, didname = 1; + int rc; + cnid_t id_devino, id_didname; + u_int32_t type_devino = (unsigned)-1; + u_int32_t type_didname = (unsigned)-1; + int update = 0; + + memset(&key, 0, sizeof(key)); + memset(&diddata, 0, sizeof(diddata)); + memset(&devdata, 0, sizeof(devdata)); + + rply->namelen = 0; + rply->cnid = 0; + + buf = pack_cnid_data(rqst); + + /* Look for a CNID. We have two options: dev/ino or did/name. If we + only get a match in one of them, that means a file has moved. */ + key.data = buf + CNID_DEVINO_OFS; + key.size = CNID_DEVINO_LEN; + + if ((rc = dbif_get(dbd, DBIF_IDX_DEVINO, &key, &devdata, 0)) < 0) { + dbd_log( LOGSTD, "dbd_search: Unable to get CNID %u, name %s", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (rc == 0) { + devino = 0; + } + else { + memcpy(&id_devino, devdata.data, sizeof(rply->cnid)); + memcpy(&type_devino, (char *)devdata.data +CNID_TYPE_OFS, sizeof(type_devino)); + type_devino = ntohl(type_devino); + } + + key.data = buf + CNID_DID_OFS; + key.size = CNID_DID_LEN + rqst->namelen + 1; + + if ((rc = dbif_get(dbd, DBIF_IDX_DIDNAME, &key, &diddata, 0)) < 0) { + dbd_log( LOGSTD, "dbd_search: Unable to get CNID %u, name %s", + ntohl(rqst->did), rqst->name); + rply->result = CNID_DBD_RES_ERR_DB; + return -1; + } + if (rc == 0) { + didname = 0; + } + else { + memcpy(&id_didname, diddata.data, sizeof(rply->cnid)); + memcpy(&type_didname, (char *)diddata.data +CNID_TYPE_OFS, sizeof(type_didname)); + type_didname = ntohl(type_didname); + } + + if (!devino && !didname) { + /* not found */ + dbd_log( LOGDEBUG, "name: '%s/%s', did: %u, dev/ino: 0x%llx/0x%llx is not in the CNID database", + cwdbuf, rqst->name, ntohl(rqst->did), (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + + if (devino && didname && id_devino == id_didname && type_devino == rqst->type) { + /* the same */ + rply->cnid = id_didname; + rply->result = CNID_DBD_RES_OK; + return 1; + } + + if (didname) { + dbd_log( LOGSTD, "CNID resolve problem: changed dev/ino for '%s/%s'", cwdbuf, rqst->name); + rqst->cnid = id_didname; + /* we have a did/name. + If it's the same dev or not the same type, e.g. a remove followed by a new file + with the same name */ + if (!memcmp(&dev, (char *)diddata.data + CNID_DEV_OFS, CNID_DEV_LEN) || + type_didname != rqst->type) { + if (! roflag) + if (dbd_delete(dbd, rqst, rply) < 0) + return -1; + } + else { + update = 1; + } + } + + if (devino) { + dbd_log( LOGSTD, "CNID resolve problem: server side rename oder reused inode for '%s/%s'", cwdbuf, rqst->name); + rqst->cnid = id_devino; + if (type_devino != rqst->type) { + /* same dev/inode but not same type: it's an inode reused, delete the record */ + if (! roflag) + if (dbd_delete(dbd, rqst, rply) < 0) + return -1; + } + else { + update = 1; + } + } + if (!update || roflag) { + rply->result = CNID_DBD_RES_NOTFOUND; + return 1; + } + /* Fix up the database. assume it was a file move and rename */ + rc = dbd_update(dbd, rqst, rply); + if (rc >0) { + rply->cnid = rqst->cnid; + } + + dbd_log( LOGSTD, "CNID database needed update: dev/ino: 0x%llx/0x%llx, did: %u, name: '%s/%s' --> CNID: %u", + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, + ntohl(rqst->did), cwdbuf, rqst->name, ntohl(rply->cnid)); + + return rc; +} + +/* + This is taken from dbd_add.c +*/ +int cmd_dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +{ + if (get_cnid(dbd, rply) < 0) { + if (rply->result == CNID_DBD_RES_ERR_MAX) { + dbd_log( LOGSTD, "FATAL: CNID database has reached its limit."); + /* This will cause an abort/rollback if transactions are used */ + return 0; + } else { + dbd_log( LOGSTD, "Failed to compute CNID for %s, error reading/updating Rootkey", rqst->name); + return -1; + } + } + + if (add_cnid(dbd, rqst, rply) < 0) { + if (rply->result == CNID_DBD_RES_ERR_DUPLCNID) { + dbd_log( LOGSTD, "Cannot add CNID %u. Corrupt/invalid Rootkey?.", ntohl(rply->cnid)); + /* abort/rollback, see above */ + return 0; + } else { + dbd_log( LOGSTD, "Failed to add CNID for %s to database", rqst->name); + return -1; + } + } + dbd_log( LOGDEBUG, "Add to CNID database: did: %u, cnid: %u, name: '%s', dev/ino: 0x%llx/0x%llx", + ntohl(rqst->did), ntohl(rply->cnid), rqst->name, + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino); + + rply->result = CNID_DBD_RES_OK; + return 1; +} diff --git a/etc/cnid_dbd/cmd_dbd_scanvol.c b/etc/cnid_dbd/cmd_dbd_scanvol.c index 07993ed1..3e3b5d69 100644 --- a/etc/cnid_dbd/cmd_dbd_scanvol.c +++ b/etc/cnid_dbd/cmd_dbd_scanvol.c @@ -1,42 +1,59 @@ -/* - $Id: cmd_dbd_scanvol.c,v 1.1 2009-05-06 11:54:24 franklahm Exp $ - - Copyright (c) 2009 Frank Lahm - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ +/* + $Id: cmd_dbd_scanvol.c,v 1.2 2009-05-14 13:46:08 franklahm Exp $ + + Copyright (c) 2009 Frank Lahm -/* - dbd specs and implementation progress - ===================================== - - St Type Check (Status of implementation progress, type: file/dir) - -- ---- ----- - OK D Make sure .AppleDouble dir exist, create if missing. Error creating - it is fatal as that shouldn't happen as root - OK F Make sure ad file exists - OK F/D Delete orphaned ad-files, log dirs in ad-dir - OK F/D Check name encoding by roundtripping, log on error - .. F/D try: read CNID from ad file (if cnid caching is on) - try: fetch CNID from database - on mismatch: keep CNID from file, update database - on no CNID id ad file: write CNID from database to ad file - on no CNID in database: add CNID from ad file to database - on no CNID at all: create one and store in both places + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. */ -/* FIXME: set id */ -#if 0 - ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp); -#endif +/* + dbd specs and implementation progress + ===================================== + + St := Status + + Force option + ------------ + + St Spec + -- ---- + -- If -f is requested, ensure -e is too. + Check if volumes is usign AFPVOL_CACHE, then wipe db from disk. + + 1st pass: Scan volume + -------------------- + + St Type Check + -- ---- ----- + OK F/D Make sure ad file exists + OK D Make sure .AppleDouble dir exist, create if missing. Error creating + it is fatal as that shouldn't happen as root. + OK F/D Delete orphaned ad-files, log dirs in ad-dir + OK F/D Check name encoding by roundtripping, log on error + OK F/D try: read CNID from ad file (if cnid caching is on) + try: fetch CNID from database + -> on mismatch: use CNID from file, update database (deleting both found CNIDs first) + -> if no CNID in ad file: write CNID from database to ad file + -> if no CNID in database: add CNID from ad file to database + -> on no CNID at all: create one and store in both places + OK F/D Add found CNID, DID, filename, dev/inode, stamp to rebuild database + + 2nd pass: Delete unused CNIDs + ----------------------------- + + St Spec + -- ---- + -- Step through dbd (the one on disk) and rebuild-db from pass 1 and delete any CNID from + dbd not in rebuild db. +*/ #ifdef HAVE_CONFIG_H #include "config.h" @@ -50,26 +67,39 @@ #include #include #include - +#include #include #include #include -#include "cmd_dbd.h" +#include +#include "cmd_dbd.h" #include "dbif.h" #include "db_param.h" +#include "dbd.h" + +/* Some defines to ease code parsing */ +#define ADDIR_OK (addir_ok == 0) +#define ADFILE_OK (adfile_ok == 0) + +/* These must be accessible for cmd_dbd_* funcs */ +struct volinfo *volinfo; +char cwdbuf[MAXPATHLEN+1]; +DBD *dbd; static DBD *dbd_rebuild; -static struct volinfo *volinfo; static dbd_flags_t dbd_flags; -static char cwdbuf[MAXPATHLEN+1]; +static char stamp[CNID_DEV_LEN]; static char *netatalk_dirs[] = { ".AppleDB", ".AppleDesktop", NULL }; +static struct cnid_dbd_rqst rqst; +static struct cnid_dbd_rply rply; +static jmp_buf jmp; -/* - Taken form afpd/desktop.c +/* + Taken form afpd/desktop.c */ static char *utompath(char *upath) { @@ -96,9 +126,9 @@ static char *utompath(char *upath) /* convert charsets */ if ((size_t)-1 == ( outlen = convert_charset(volinfo->v_volcharset, - CH_UTF8_MAC, + CH_UTF8_MAC, volinfo->v_maccharset, - u, outlen, mpath, MAXPATHLEN, &flags)) ) { + u, outlen, mpath, MAXPATHLEN, &flags)) ) { dbd_log( LOGSTD, "Conversion from %s to %s for %s failed.", volinfo->v_volcodepage, volinfo->v_maccodepage, u); return NULL; @@ -107,20 +137,20 @@ static char *utompath(char *upath) return(m); } -/* - Taken form afpd/desktop.c +/* + Taken form afpd/desktop.c */ static char *mtoupath(char *mpath) { static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */ - char *m, *u; + char *m, *u; size_t inplen; size_t outlen; - u_int16_t flags = 0; + u_int16_t flags = 0; if (!mpath) return NULL; - + if ( *mpath == '\0' ) { return( "." ); } @@ -152,15 +182,15 @@ static char *mtoupath(char *mpath) m, inplen, u, outlen, &flags)) ) { dbd_log( LOGSTD, "conversion from UTF8-MAC to %s for %s failed.", volinfo->v_volcodepage, mpath); - return NULL; + return NULL; } return( upath ); } -/* - Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS. - We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result. +/* + Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS. + We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result. */ static int check_name_encoding(char *uname) { @@ -168,12 +198,12 @@ static int check_name_encoding(char *uname) roundtripped = mtoupath(utompath(uname)); if (!roundtripped) { - dbd_log( LOGSTD, "Error checking encoding for %s/%s", cwdbuf, uname); + dbd_log( LOGSTD, "Error checking encoding for '%s/%s'", cwdbuf, uname); return -1; } if ( STRCMP(uname, !=, roundtripped)) { - dbd_log( LOGSTD, "Bad encoding for %s/%s", cwdbuf, uname); + dbd_log( LOGSTD, "Bad encoding for '%s/%s'", cwdbuf, uname); return -1; } @@ -187,7 +217,7 @@ static int check_name_encoding(char *uname) static const char *check_netatalk_dirs(const char *name) { int c; - + for (c=0; netatalk_dirs[c]; c++) { if ((strcmp(name, netatalk_dirs[c])) == 0) return netatalk_dirs[c]; @@ -195,16 +225,21 @@ static const char *check_netatalk_dirs(const char *name) return NULL; } -/* - Check for .AppleDouble file, create if missing +/* + Check for .AppleDouble file, create if missing */ static int check_adfile(const char *fname, const struct stat *st) { - int ret; + int ret, adflags; struct adouble ad; char *adname; - adname = volinfo->ad_path(fname, 0); + if (S_ISREG(st->st_mode)) + adflags = 0; + else + adflags = ADFLAGS_DIR; + + adname = volinfo->ad_path(fname, adflags); if ((ret = access( adname, F_OK)) != 0) { if (errno != ENOENT) { @@ -217,13 +252,13 @@ static int check_adfile(const char *fname, const struct stat *st) if (dbd_flags & DBD_FLAGS_SCAN) /* Scan only requested, dont change anything */ - return 0; + return -1; /* Create ad file */ - ad_init(&ad, volinfo->v_adouble, volinfo->v_flags); - - if ((ret = ad_open_metadata( fname, 0, O_CREAT, &ad)) != 0) { - dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s", + ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options); + + if ((ret = ad_open_metadata( fname, adflags, O_CREAT, &ad)) != 0) { + dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s", cwdbuf, adname, strerror(errno)); return -1; } @@ -242,31 +277,50 @@ static int check_adfile(const char *fname, const struct stat *st) return 0; } -/* - Check for .AppleDouble folder, create if missing +/* + Check for .AppleDouble folder and .Parent, create if missing */ static int check_addir(int volroot) { - int ret; + int addir_ok, adpar_ok; struct stat st; struct adouble ad; - if ((ret = access(ADv2_DIRNAME, F_OK)) != 0) { + /* Check for ad-dir */ + if ( (addir_ok = access(ADv2_DIRNAME, F_OK)) != 0) { if (errno != ENOENT) { dbd_log(LOGSTD, "Access error in directory %s: %s", cwdbuf, strerror(errno)); return -1; } - /* Missing. Log and create it */ - dbd_log(LOGSTD, "Missing %s directory %s", ADv2_DIRNAME, cwdbuf); + dbd_log(LOGSTD, "Missing %s for '%s'", ADv2_DIRNAME, cwdbuf); + } - if (dbd_flags & DBD_FLAGS_SCAN) - /* Scan only requested, dont change anything */ - return 0; + /* Check for ".Parent" */ + if ( (adpar_ok = access(volinfo->ad_path(".", ADFLAGS_DIR), F_OK)) != 0) { + if (errno != ENOENT) { + dbd_log(LOGSTD, "Access error on '%s/%s': %s", + cwdbuf, volinfo->ad_path(".", ADFLAGS_DIR), strerror(errno)); + return -1; + } + dbd_log(LOGSTD, "Missing .AppleDouble/.Parent for '%s'", cwdbuf); + } + + /* Is one missing ? */ + if ((addir_ok != 0) || (adpar_ok != 0)) { + /* Yes, but are we only scanning ? */ + if (dbd_flags & DBD_FLAGS_SCAN) { + /* Yes: missing .Parent is not a problem, but missing ad-dir + causes later checking of ad-files to fail. So we have to return appropiately */ + if (addir_ok != 0) + return -1; + else /* (adpar_ok != 0) */ + return 0; + } - /* Create ad dir and set name and id */ - ad_init(&ad, volinfo->v_adouble, volinfo->v_flags); - - if ((ret = ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad)) != 0) { + /* Create ad dir and set name */ + ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options); + + if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad) != 0) { dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno)); return -1; } @@ -278,7 +332,7 @@ static int check_addir(int volroot) ad_setname(&ad, mname); ad_flush(&ad); ad_close_metadata(&ad); - + /* Inherit owner/group from "." to ".AppleDouble" and ".Parent" */ if ((stat(".", &st)) != 0) { dbd_log( LOGSTD, "Couldnt stat %s: %s", cwdbuf, strerror(errno)); @@ -296,7 +350,7 @@ static int read_addir(void) DIR *dp; struct dirent *ep; struct stat st; - static char fname[NAME_MAX] = "../"; + static char fname[MAXPATHLEN] = "../"; if ((chdir(ADv2_DIRNAME)) != 0) { dbd_log(LOGSTD, "Couldn't chdir to '%s/%s': %s", @@ -314,9 +368,12 @@ static int read_addir(void) /* Check if its "." or ".." */ if (DIR_DOT_OR_DOTDOT(ep->d_name)) continue; + /* Skip ".Parent" */ + if (STRCMP(ep->d_name, ==, ".Parent")) + continue; if ((stat(ep->d_name, &st)) < 0) { - dbd_log( LOGSTD, "Lost file while reading dir '%s/%s/%s', probably removed: %s", + dbd_log( LOGSTD, "Lost file or dir while enumeratin dir '%s/%s/%s', probably removed: %s", cwdbuf, ADv2_DIRNAME, ep->d_name, strerror(errno)); continue; } @@ -328,15 +385,11 @@ static int read_addir(void) continue; } - /* Skip ".Parent" */ - if (STRCMP(ep->d_name, ==, ".Parent")) - continue; - /* Check for data file */ strcpy(fname+3, ep->d_name); if ((access( fname, F_OK)) != 0) { if (errno != ENOENT) { - dbd_log(LOGSTD, "Access error for file '%s/%s': %s", + dbd_log(LOGSTD, "Access error for file '%s/%s': %s", cwdbuf, ep->d_name, strerror(errno)); continue; } @@ -368,21 +421,146 @@ static int read_addir(void) return 0; } + +static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok, + int adflags) +{ + int ret; + cnid_t db_cnid, ad_cnid; + struct adouble ad; + + /* Get CNID from ad-file if volume is using AFPVOL_CACHE */ + ad_cnid = 0; + if ( (volinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) { + ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options); + if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) { + dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); + return 0; + } + ad_cnid = ad_getid(&ad, st->st_dev, st->st_ino, did, stamp); + if (ad_cnid == 0) + dbd_log( LOGSTD, "ZeroID '%s/%s'", cwdbuf, name); + ad_close_metadata(&ad); + } + + /* Get CNID from database */ + + /* Prepare request data */ + memset(&rqst, 0, sizeof(struct cnid_dbd_rqst)); + memset(&rply, 0, sizeof(struct cnid_dbd_rply)); + rqst.did = did; + if ( ! (volinfo->v_flags & AFPVOL_NODEV)) + rqst.dev = st->st_dev; + rqst.ino = st->st_ino; + rqst.type = S_ISDIR(st->st_mode)?1:0; + rqst.name = (char *)name; + rqst.namelen = strlen(name); + + /* Query the database */ + ret = cmd_dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0); + dbif_txn_close(dbd, ret); + if (rply.result == CNID_DBD_RES_OK) { + db_cnid = rply.cnid; + } else if (rply.result == CNID_DBD_RES_NOTFOUND) { + dbd_log( LOGSTD, "Missing CNID for: '%s/%s'", cwdbuf, name); + db_cnid = 0; + } else { + dbd_log( LOGSTD, "Fatal error resolving '%s/%s'", cwdbuf, name); + db_cnid = 0; + } + + /* Compare results from both CNID searches */ + if (ad_cnid && db_cnid && (ad_cnid == db_cnid)) { + /* Everything is fine */ + return db_cnid; + } else if (ad_cnid && db_cnid && (ad_cnid != db_cnid)) { + /* Mismatch ? Delete both from db and re-add data from file */ + dbd_log( LOGSTD, "CNID mismatch for '%s/%s', db: %u, ad-file: %u", cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid)); + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) { + rqst.cnid = db_cnid; + ret = dbd_delete(dbd, &rqst, &rply); + dbif_txn_close(dbd, ret); + + rqst.cnid = ad_cnid; + ret = dbd_delete(dbd, &rqst, &rply); + dbif_txn_close(dbd, ret); + + ret = dbd_rebuild_add(dbd, &rqst, &rply); + dbif_txn_close(dbd, ret); + } + return ad_cnid; + } else if (ad_cnid && (db_cnid == 0)) { + /* in ad-file but not in db */ + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) { + dbd_log( LOGSTD, "CNID rebuild add for '%s/%s', adding with CNID from ad-file: %u", cwdbuf, name, ntohl(ad_cnid)); + rqst.cnid = ad_cnid; + ret = dbd_delete(dbd, &rqst, &rply); + dbif_txn_close(dbd, ret); + ret = dbd_rebuild_add(dbd, &rqst, &rply); + dbif_txn_close(dbd, ret); + } + return ad_cnid; + } else if ((db_cnid == 0) && (ad_cnid == 0)) { + /* No CNID at all, we clearly have to allocat a fresh one... */ + /* Note: the next test will use this new CNID too! */ + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) { + /* add to db */ + dbd_log( LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(ad_cnid)); + ret = cmd_dbd_add(dbd, &rqst, &rply); + dbif_txn_close(dbd, ret); + db_cnid = rply.cnid; + } + } else if ((ad_cnid == 0) && db_cnid) { + /* in db but zeroID in ad-file, write it to ad-file if AFPVOL_CACHE */ + if ((volinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) { + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) { + dbd_log( LOGSTD, "Setting CNID for ZeroID '%s/%s' from db: %u", cwdbuf, name, ntohl(db_cnid)); + ad_init(&ad, volinfo->v_adouble, volinfo->v_ad_options); + if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) { + dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); + return 0; + } + ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp); + ad_flush(&ad); + ad_close_metadata(&ad); + } + } + return db_cnid; + } else { + dbd_log( LOGSTD, "Uncaught CNID mismatch for '%s/%s'", cwdbuf, name); + return 0; + } + /* Not reached */ + return 0; +} + +/* + This is called recursively for all dirs. + volroot=1 means we're in the volume root dir, 0 means we aren't. + We use this when checking for netatalk private folders like .AppleDB. + did is our parents CNID. +*/ static int dbd_readdir(int volroot, cnid_t did) { - int cwd, ret = 0, encoding_ok; + int cwd, ret = 0, adflags, adfile_ok, addir_ok, encoding_ok; + cnid_t cnid; const char *name; DIR *dp; struct dirent *ep; static struct stat st; /* Save some stack space */ - /* Check for .AppleDouble folder */ - if ((check_addir(volroot)) != 0) - return -1; + /* Check again for .AppleDouble folder, check_adfile also checks/creates it */ + if ((addir_ok = check_addir(volroot)) != 0) + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) + /* Fatal on rebuild run, continue if only scanning ! */ + return -1; - /* Check AppleDouble files in AppleDouble folder */ - if ((ret = read_addir()) != 0) - return -1; + /* Check AppleDouble files in AppleDouble folder, but only if it exists or could be created */ + if (ADDIR_OK) + if ((read_addir()) != 0) + if ( ! (dbd_flags & DBD_FLAGS_SCAN)) + /* Fatal on rebuild run, continue if only scanning ! */ + return -1; if ((dp = opendir (".")) == NULL) { dbd_log(LOGSTD, "Couldn't open the directory: %s",strerror(errno)); @@ -390,6 +568,10 @@ static int dbd_readdir(int volroot, cnid_t did) } while ((ep = readdir (dp))) { + /* Check if we got a termination signal */ + if (alarmed) + longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */ + /* Check if its "." or ".." */ if (DIR_DOT_OR_DOTDOT(ep->d_name)) continue; @@ -409,6 +591,10 @@ static int dbd_readdir(int volroot, cnid_t did) dbd_log( LOGSTD, "Lost file while reading dir '%s/%s', probably removed: %s", cwdbuf, ep->d_name, strerror(errno)); continue; } + if (S_ISREG(st.st_mode)) + adflags = 0; + else + adflags = ADFLAGS_DIR; /************************************************************************** Tests @@ -417,21 +603,33 @@ static int dbd_readdir(int volroot, cnid_t did) /* Check encoding */ if ( -1 == (encoding_ok = check_name_encoding(ep->d_name)) ) { /* If its a file: skipp all other tests now ! */ - /* For dirs we skip tests too, but later */ - if (S_ISREG(st.st_mode)) - continue; + /* For dirs we could try to get a CNID for it and recurse, but currently I prefer not to */ + continue; } - /* Check for appledouble file, create if missing */ - if (S_ISREG(st.st_mode)) { - if ( 0 != check_adfile(ep->d_name, &st)) - continue; + /* Check for appledouble file, create if missing, but only if we have addir */ + adfile_ok = -1; + if (ADDIR_OK) + adfile_ok = check_adfile(ep->d_name, &st); + + /* Check CNIDs */ + cnid = check_cnid(ep->d_name, did, &st, adfile_ok, adflags); + + /* Now add this object to our rebuild dbd */ + if (cnid) { + rqst.cnid = rply.cnid; + dbd_rebuild_add(dbd_rebuild, &rqst, &rply); + if (rply.result != CNID_DBD_RES_OK) { + dbd_log( LOGDEBUG, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db", + cnid, cwdbuf, ep->d_name); + exit(EXIT_FAILURE); + } } - + /************************************************************************** Recursion **************************************************************************/ - if (S_ISDIR(st.st_mode)) { + if (S_ISDIR(st.st_mode) && cnid) { /* If we have no cnid for it we cant recur */ strcat(cwdbuf, "/"); strcat(cwdbuf, ep->d_name); dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf); @@ -445,7 +643,7 @@ static int dbd_readdir(int volroot, cnid_t did) continue; } - ret = dbd_readdir(0, did); + ret = dbd_readdir(0, cnid); fchdir(cwd); close(cwd); @@ -455,12 +653,11 @@ static int dbd_readdir(int volroot, cnid_t did) } } - /* - Use results of previous checks + /* + Use results of previous checks */ -exit_cleanup: - closedir(dp); + closedir(dp); return ret; } @@ -486,37 +683,50 @@ static int scanvol(struct volinfo *vi, dbd_flags_t flags) chdir(volinfo->v_path); /* Start recursion */ - if (dbd_readdir(1, 2) < 0) /* 2 = volumeroot CNID */ + if (dbd_readdir(1, htonl(2)) < 0) /* 2 = volumeroot CNID */ return -1; return 0; } -int cmd_dbd_scanvol(DBD *dbd, struct volinfo *volinfo, dbd_flags_t flags) +int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *volinfo, dbd_flags_t flags) { int ret = 0; + /* Make it accessible for all funcs */ + dbd = dbd_ref; + /* We only support unicode volumes ! */ if ( volinfo->v_volcharset != CH_UTF8) { dbd_log( LOGSTD, "Not a Unicode volume: %s, %u != %u", volinfo->v_volcodepage, volinfo->v_volcharset, CH_UTF8); return -1; } - /* open/create dbd, copy rootinfo key */ - if (NULL == (dbd_rebuild = dbif_init(NULL))) + /* Get volume stamp */ + dbd_getstamp(dbd, &rqst, &rply); + if (rply.result != CNID_DBD_RES_OK) + goto exit_cleanup; + memcpy(stamp, rply.name, CNID_DEV_LEN); + + /* open/create rebuild dbd, copy rootinfo key */ + if (NULL == (dbd_rebuild = dbif_init(NULL, NULL))) return -1; if (0 != (dbif_open(dbd_rebuild, NULL, 0))) return -1; - if (0 != (ret = dbif_copy_rootinfokey(dbd, dbd_rebuild))) + if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) goto exit_cleanup; - dbd_log( LOGSTD, "dumping rebuilddb"); - dbif_dump(dbd_rebuild, 0); +// dbif_dump(dbd_rebuild, 0); + + if (setjmp(jmp) != 0) + goto exit_cleanup; /* Got signal, jump from dbd_readdir */ /* scanvol */ if ( (scanvol(volinfo, flags)) != 0) return -1; +// dbif_dump(dbd_rebuild, 0); + exit_cleanup: dbif_close(dbd_rebuild); return ret; diff --git a/etc/cnid_dbd/dbd_add.c b/etc/cnid_dbd/dbd_add.c index 0606bf45..7f66ca30 100644 --- a/etc/cnid_dbd/dbd_add.c +++ b/etc/cnid_dbd/dbd_add.c @@ -1,5 +1,5 @@ /* - * $Id: dbd_add.c,v 1.5 2009-05-06 11:54:24 franklahm Exp $ + * $Id: dbd_add.c,v 1.6 2009-05-14 13:46:08 franklahm Exp $ * * Copyright (C) Joerg Lenneis 2003 * All Rights Reserved. See COPYING. @@ -34,7 +34,7 @@ #include "pack.h" #include "dbd.h" -static int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) +int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) { DBT key, data; int rc; @@ -81,7 +81,7 @@ static int add_cnid(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply * } /* ---------------------- */ -static int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply) +int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply) { DBT rootinfo_key, rootinfo_data; int rc; @@ -194,8 +194,8 @@ int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) return -1; } } - LOG(log_info, logtype_cnid, "dbd_add: Added dev/ino 0x%llx/0x%llx did %u name %s cnid %u", - ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino), + LOG(log_debug, logtype_cnid, "dbd_add: Added dev/ino 0x%llx/0x%llx did %u name %s cnid %u", + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(rply->cnid)); rply->result = CNID_DBD_RES_OK; diff --git a/etc/cnid_dbd/dbd_lookup.c b/etc/cnid_dbd/dbd_lookup.c index c46b746d..7c8dfb54 100644 --- a/etc/cnid_dbd/dbd_lookup.c +++ b/etc/cnid_dbd/dbd_lookup.c @@ -1,5 +1,5 @@ /* - * $Id: dbd_lookup.c,v 1.6 2009-05-06 11:54:24 franklahm Exp $ + * $Id: dbd_lookup.c,v 1.7 2009-05-14 13:46:08 franklahm Exp $ * * Copyright (C) Joerg Lenneis 2003 * All Rights Reserved. See COPYING. @@ -32,9 +32,6 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) unsigned char *buf; DBT key, devdata, diddata; char dev[CNID_DEV_LEN]; -#if 0 - char ino[CNID_INO_LEN]; -#endif int devino = 1, didname = 1; int rc; cnid_t id_devino, id_didname; @@ -52,10 +49,6 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) buf = pack_cnid_data(rqst); memcpy(dev, buf + CNID_DEV_OFS, CNID_DEV_LEN); -#if 0 - /* FIXME: ino is not needed later on, remove? */ - memcpy(ino, buf + CNID_INO_OFS, CNID_INO_LEN); -#endif /* Look for a CNID. We have two options: dev/ino or did/name. If we only get a match in one of them, that means a file has moved. */ @@ -99,7 +92,7 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) /* not found */ LOG(log_debug, logtype_cnid, "cnid_lookup: dev/ino 0x%llx/0x%llx did %u name %s neither in devino nor didname", - ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino), ntohl(rqst->did), rqst->name); + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name); rply->result = CNID_DBD_RES_NOTFOUND; return 1; @@ -109,7 +102,7 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) /* the same */ LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u", - ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino), ntohl(rqst->did), rqst->name, ntohl(id_didname)); + (unsigned long long )rqst->dev, (unsigned long long )rqst->ino, ntohl(rqst->did), rqst->name, ntohl(id_didname)); rply->cnid = id_didname; rply->result = CNID_DBD_RES_OK; @@ -158,7 +151,7 @@ int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply) } LOG(log_debug, logtype_cnid, "cnid_lookup: Looked up dev/ino 0x%llx/0x%llx did %u name %s as %u (needed update)", - ntoh64((unsigned long long int)rqst->dev), ntoh64((unsigned long long int)rqst->ino), ntohl(rqst->did), rqst->name, ntohl(rply->cnid)); + (unsigned long long)rqst->dev, (unsigned long long)rqst->ino, ntohl(rqst->did), rqst->name, ntohl(rply->cnid)); return rc; } diff --git a/etc/cnid_dbd/dbif.c b/etc/cnid_dbd/dbif.c index 6b5f455a..ea378ad6 100644 --- a/etc/cnid_dbd/dbif.c +++ b/etc/cnid_dbd/dbif.c @@ -1,5 +1,5 @@ /* - * $Id: dbif.c,v 1.9 2009-05-10 08:08:28 franklahm Exp $ + * $Id: dbif.c,v 1.10 2009-05-14 13:46:08 franklahm Exp $ * * Copyright (C) Joerg Lenneis 2003 * Copyright (C) Frank Lahm 2009 @@ -71,7 +71,7 @@ int dbif_stamp(DBD *dbd, void *buffer, int size) } /* --------------- */ -DBD *dbif_init(const char *filename) +DBD *dbif_init(const char *envhome, const char *filename) { DBD *dbd; @@ -80,8 +80,18 @@ DBD *dbif_init(const char *filename) /* filename == NULL means in memory db */ if (filename) { + if (! envhome) + return NULL; + + dbd->db_envhome = strdup(envhome); + if (NULL == dbd->db_envhome) { + free(dbd); + return NULL; + } + dbd->db_filename = strdup(filename); if (NULL == dbd->db_filename) { + free(dbd->db_envhome); free(dbd); return NULL; } @@ -134,11 +144,10 @@ int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags) dbd->db_env->set_msgfile(dbd->db_env, dbd->db_errlog); } - dbd->db_env->set_verbose(dbd->db_env, DB_VERB_RECOVERY, 1); - if (dbenv_oflags & DB_RECOVER) { + dbd->db_env->set_verbose(dbd->db_env, DB_VERB_RECOVERY, 1); /* Open the database for recovery using DB_PRIVATE option which is faster */ - if ((ret = dbd->db_env->open(dbd->db_env, ".", dbenv_oflags | DB_PRIVATE, 0))) { + if ((ret = dbd->db_env->open(dbd->db_env, dbd->db_envhome, dbenv_oflags | DB_PRIVATE, 0))) { LOG(log_error, logtype_cnid, "error opening DB environment: %s", db_strerror(ret)); dbd->db_env->close(dbd->db_env, 0); @@ -177,7 +186,7 @@ int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags) dbd->db_env->set_errfile(dbd->db_env, dbd->db_errlog); dbd->db_env->set_msgfile(dbd->db_env, dbd->db_errlog); } - if ((ret = dbd->db_env->open(dbd->db_env, ".", dbenv_oflags, 0))) { + if ((ret = dbd->db_env->open(dbd->db_env, dbd->db_envhome, dbenv_oflags, 0))) { LOG(log_error, logtype_cnid, "error opening DB environment after recovery: %s", db_strerror(ret)); dbd->db_env->close(dbd->db_env, 0); @@ -526,6 +535,28 @@ int dbif_txn_abort(DBD *dbd) return 0; } +/* + ret = 1 -> commit txn + ret = 0 -> abort txn -> exit! + anything else -> exit! +*/ +void dbif_txn_close(DBD *dbd, int ret) +{ + if (ret == 0) { + if (dbif_txn_abort(dbd) < 0) { + LOG( log_error, logtype_cnid, "Fatal error aborting transaction. Exiting!"); + exit(EXIT_FAILURE); + } + } else if (ret == 1) { + ret = dbif_txn_commit(dbd); + if ( ret < 0) { + LOG( log_error, logtype_cnid, "Fatal error committing transaction. Exiting!"); + exit(EXIT_FAILURE); + } + } else + exit(EXIT_FAILURE); +} + int dbif_txn_checkpoint(DBD *dbd, u_int32_t kbyte, u_int32_t min, u_int32_t flags) { int ret; diff --git a/etc/cnid_dbd/dbif.h b/etc/cnid_dbd/dbif.h index ea6083d5..fcb8b0bd 100644 --- a/etc/cnid_dbd/dbif.h +++ b/etc/cnid_dbd/dbif.h @@ -1,5 +1,5 @@ /* - $Id: dbif.h,v 1.5 2009-05-06 11:54:24 franklahm Exp $ + $Id: dbif.h,v 1.6 2009-05-14 13:46:08 franklahm Exp $ Copyright (C) Joerg Lenneis 2003 Copyright (C) Frank Lahm 2009 @@ -68,13 +68,14 @@ typedef struct { typedef struct { DB_ENV *db_env; DB_TXN *db_txn; + char *db_envhome; char *db_filename; FILE *db_errlog; db_table db_table[3]; } DBD; /* Functions */ -extern DBD *dbif_init(const char *dbname); +extern DBD *dbif_init(const char *envhome, const char *dbname); extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags); extern int dbif_open(DBD *dbd, struct db_param *dbp, int do_truncate); extern int dbif_close(DBD *dbd); @@ -90,6 +91,7 @@ extern int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd); extern int dbif_txn_begin(DBD *); extern int dbif_txn_commit(DBD *); extern int dbif_txn_abort(DBD *); +extern void dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */ extern int dbif_txn_checkpoint(DBD *, u_int32_t, u_int32_t, u_int32_t); extern int dbif_dump(DBD *, int dumpindexes); diff --git a/etc/cnid_dbd/main.c b/etc/cnid_dbd/main.c index 0a3806f1..21b44379 100644 --- a/etc/cnid_dbd/main.c +++ b/etc/cnid_dbd/main.c @@ -1,5 +1,5 @@ /* - * $Id: main.c,v 1.6 2009-05-06 11:54:24 franklahm Exp $ + * $Id: main.c,v 1.7 2009-05-14 13:46:08 franklahm Exp $ * * Copyright (C) Joerg Lenneis 2003 * Copyright (c) Frank Lahm 2009 @@ -340,7 +340,7 @@ int main(int argc, char *argv[]) exit(1); LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file"); - if (NULL == (dbd = dbif_init("cnid2.db"))) + if (NULL == (dbd = dbif_init(".", "cnid2.db"))) exit(2); if (dbif_env_open(dbd, dbp, DBOPTIONS) < 0) diff --git a/include/atalk/volinfo.h b/include/atalk/volinfo.h index 2a3e2e14..0caa94ab 100644 --- a/include/atalk/volinfo.h +++ b/include/atalk/volinfo.h @@ -1,5 +1,5 @@ /* - * $Id: volinfo.h,v 1.4 2009-04-28 13:01:24 franklahm Exp $ + * $Id: volinfo.h,v 1.5 2009-05-14 13:46:08 franklahm Exp $ */ #ifndef _ATALK_VOLINFO_H @@ -60,6 +60,7 @@ struct volinfo { char *v_maccodepage; charset_t v_maccharset; int v_adouble; /* default adouble format */ + int v_ad_options; char *(*ad_path)(const char *, int); char *v_dbd_host; int v_dbd_port; diff --git a/libatalk/util/volinfo.c b/libatalk/util/volinfo.c index 262c240b..0c06c120 100644 --- a/libatalk/util/volinfo.c +++ b/libatalk/util/volinfo.c @@ -373,6 +373,17 @@ int loadvolinfo (char *path, struct volinfo *vol) lock.l_type = F_UNLCK; fcntl(fd, F_SETLK, &lock); + /* Translate vol options to ad options like afp/volume.c does it */ + vol->v_ad_options = 0; + if ((vol->v_flags & AFPVOL_NODEV)) + vol->v_ad_options |= ADVOL_NODEV; + if ((vol->v_flags & AFPVOL_CACHE)) + vol->v_ad_options |= ADVOL_CACHE; + if ((vol->v_flags & AFPVOL_UNIX_PRIV)) + vol->v_ad_options |= ADVOL_UNIXPRIV; + if ((vol->v_flags & AFPVOL_INV_DOTS)) + vol->v_ad_options |= ADVOL_INVDOTS; + fclose(fp); return 0; } -- 2.39.2