]> arthur.barton.de Git - netatalk.git/commitdiff
Rewrite dbd to use CNID IPC instead of opening the db directly
authorRalph Boehme <sloowfranklin@gmail.com>
Fri, 7 Dec 2012 17:33:32 +0000 (18:33 +0100)
committerRalph Boehme <sloowfranklin@gmail.com>
Mon, 17 Dec 2012 17:22:57 +0000 (18:22 +0100)
In order to fix buf #447 (race condition between dbd and cnid_dbd)
dbd must be converted to work over the network IPC channel with
cnid_dbd instead of directly working on the BerkeleyDB CNID database.

Add CNID db IPC command for wiping the db

12 files changed:
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/cmd_dbd.h
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/main.c
include/atalk/cnid.h
include/atalk/cnid_dbd_private.h
libatalk/cnid/cdb/cnid_cdb_open.c
libatalk/cnid/cnid.c
libatalk/cnid/dbd/cnid_dbd.c
libatalk/cnid/dbd/cnid_dbd.h
libatalk/cnid/last/cnid_last.c
libatalk/cnid/tdb/cnid_tdb_open.c

index eb53af7943a54c4396280c3f5d636574d751aaa5..8a12bfad0d2efa582e154a1b2145fecfc7175b09 100644 (file)
 #include <errno.h>
 
 #include <atalk/logger.h>
-#include <atalk/cnid_dbd_private.h>
 #include <atalk/globals.h>
 #include <atalk/netatalk_conf.h>
 #include <atalk/util.h>
+#include <atalk/errchk.h>
 
 #include "cmd_dbd.h"
-#include "dbd.h"
-#include "dbif.h"
-#include "db_param.h"
-#include "pack.h"
 
-#define DBOPTIONS (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN)
+enum dbd_cmd {dbd_scan, dbd_rebuild};
 
-int nocniddb = 0;               /* Dont open CNID database, only scan filesystem */
+/* Global variables */
 volatile sig_atomic_t alarmed;  /* flags for signals */
-int db_locked;                  /* have we got the fcntl lock on lockfile ? */
-
-static DBD *dbd;
-static int verbose;             /* Logging flag */
-static int exclusive;           /* Exclusive volume access */
-static struct db_param db_param = {
-    NULL,                       /* Volume dirpath */
-    1,                          /* bdb logfile autoremove */
-    64 * 1024,                  /* bdb cachesize (64 MB) */
-    DEFAULT_MAXLOCKS,           /* maxlocks */
-    DEFAULT_MAXLOCKOBJS,        /* maxlockobjs */
-    0,                          /* flush_interval */
-    0,                          /* flush_frequency */
-    0,                          /* usock_file */
-    -1,                         /* fd_table_size */
-    -1,                         /* idle_timeout */
-    -1                          /* max_vols */
-};
-static char dbpath[MAXPATHLEN+1];   /* Path to the dbd database */
 
-/* 
-   Provide some logging
- */
-void dbd_log(enum logtype lt, char *fmt, ...)
-{
-    int len;
-    static char logbuffer[1024];
-    va_list args;
+/* Local variables */
+static dbd_flags_t flags;
 
-    if ( (lt == LOGSTD) || (verbose == 1)) {
-        va_start(args, fmt);
-        len = vsnprintf(logbuffer, 1023, fmt, args);
-        va_end(args);
-        logbuffer[1023] = 0;
+/***************************************************************************
+ * Local functions
+ ***************************************************************************/
 
-        printf("%s\n", logbuffer);
-    }
-}
-
-/* 
-   SIGNAL handling:
-   catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
+/*
+ * SIGNAL handling:
+ * catch SIGINT and SIGTERM which cause clean exit. Ignore anything else.
  */
-
 static void sig_handler(int signo)
 {
     alarmed = 1;
@@ -128,99 +92,75 @@ static void set_signal(void)
 
 static void usage (void)
 {
-    printf("dbd (Netatalk %s)\n"
-           "Usage: dbd [-CeFtvx] -d [-i] | -s [-c|-n]| -r [-c|-f] | -u <path to netatalk volume>\n"
-           "dbd can dump, scan, reindex and rebuild Netatalk dbd CNID databases.\n"
-           "dbd must be run with appropiate permissions i.e. as root.\n\n"
-           "Main commands are:\n"
-           "   -d Dump CNID database\n"
-           "      Option: -i dump indexes too\n\n"
+    printf("Usage: dbd [-cfFstvV] <path to netatalk volume>\n"
+           "dbd scans or reindex Netatalk CNID databases of AFP volumes.\n"
+           "dbd must be run with appropiate permissions i.e. as root.\n"
+           "By default dbd rebuilds the CNID database of the volume.\n\n"
+           "Options:\n"
            "   -s Scan volume:\n"
-           "      Options: -c Don't check .AppleDouble stuff, only ckeck orphaned.\n"
-           "               -n Don't open CNID database, skip CNID checks.\n\n"
-           "   -r Rebuild volume:\n"
-           "      Options: -c Don't create .AppleDouble stuff, only cleanup orphaned.\n"
-           "               -f wipe database and rebuild from IDs stored in AppleDouble\n"
-           "                  metadata file or EA. Implies -e.\n\n"
-           "   -u Upgrade:\n"
-           "      Opens the database which triggers any necessary upgrades,\n"
-           "      then closes and exits.\n\n"
-           "General options:\n"
-           "   -C convert from adouble:v2 to adouble:ea (use with -r)\n"
+           "   -c convert from adouble:v2 to adouble:ea (use with -r)\n"
            "   -F location of the afp.conf config file\n"
-           "   -e only work on inactive volumes and lock them (exclusive)\n"
-           "   -x rebuild indexes (just for completeness, mostly useless!)\n"
+           "   -f delete and recreate CNID database\n"
            "   -t show statistics while running\n"
-           "   -v verbose\n\n"
-           , VERSION
+           "   -v verbose\n"
+           "   -V show version info\n\n"
         );
 }
 
-int main(int argc, char **argv)
+/***************************************************************************
+ * Global functions
+ ***************************************************************************/
+
+void dbd_log(enum logtype lt, char *fmt, ...)
 {
-    int c, lockfd, ret = -1;
-    int dump=0, scan=0, rebuild=0, prep_upgrade=0, rebuildindexes=0, dumpindexes=0, force=0;
-    dbd_flags_t flags = 0;
-    char *volpath;
-    int cdir;
-    AFPObj obj = { 0 };
-    struct vol *vol;
+    int len;
+    static char logbuffer[1024];
+    va_list args;
 
-    if (geteuid() != 0) {
-        usage();
-        exit(EXIT_FAILURE);
+    if ( (lt == LOGSTD) || (flags & DBD_FLAGS_VERBOSE)) {
+        va_start(args, fmt);
+        len = vsnprintf(logbuffer, 1023, fmt, args);
+        va_end(args);
+        logbuffer[1023] = 0;
+
+        printf("%s\n", logbuffer);
     }
-    /* Inhereting perms in ad_mkdir etc requires this */
-    ad_setfuid(0);
+}
+
+int main(int argc, char **argv)
+{
+    EC_INIT;
+    int dbd_cmd = dbd_rebuild;
+    int cdir = -1;
+    AFPObj obj = { 0 };
+    struct vol *vol = NULL;
+    const char *volpath = NULL;
 
-    while ((c = getopt(argc, argv, ":cCdefFinrstuvx")) != -1) {
+    int c;
+    while ((c = getopt(argc, argv, ":cfF:stvV")) != -1) {
         switch(c) {
         case 'c':
-            flags |= DBD_FLAGS_CLEANUP;
-            break;
-        case 'C':
             flags |= DBD_FLAGS_V2TOEA;
             break;
-        case 'd':
-            dump = 1;
+        case 'f':
+            flags |= DBD_FLAGS_FORCE;
             break;
-        case 'i':
-            dumpindexes = 1;
+        case 'F':
+            obj.cmdlineconfigfile = strdup(optarg);
             break;
         case 's':
-            scan = 1;
+            dbd_cmd = dbd_scan;
             flags |= DBD_FLAGS_SCAN;
             break;
-        case 'n':
-            nocniddb = 1; /* FIXME: this could/should be a flag too for consistency */
-            break;
-        case 'r':
-            rebuild = 1;
-            break;
         case 't':
             flags |= DBD_FLAGS_STATS;
             break;
-        case 'u':
-            prep_upgrade = 1;
-            break;
         case 'v':
-            verbose = 1;
-            break;
-        case 'e':
-            exclusive = 1;
-            flags |= DBD_FLAGS_EXCL;
-            break;
-        case 'x':
-            rebuildindexes = 1;
-            break;
-        case 'f':
-            force = 1;
-            exclusive = 1;
-            flags |= DBD_FLAGS_FORCE | DBD_FLAGS_EXCL;
-            break;
-        case 'F':
-            obj.cmdlineconfigfile = strdup(optarg);
+            flags |= DBD_FLAGS_VERBOSE;
             break;
+        case 'V':
+            printf("dbd %s\n", VERSION);
+            exit(0);
         case ':':
         case '?':
             usage();
@@ -229,16 +169,18 @@ int main(int argc, char **argv)
         }
     }
 
-    if ((dump + scan + rebuild + prep_upgrade) != 1) {
+    if ( (optind + 1) != argc ) {
         usage();
         exit(EXIT_FAILURE);
     }
+    volpath = argv[optind];
 
-    if ( (optind + 1) != argc ) {
+    if (geteuid() != 0) {
         usage();
         exit(EXIT_FAILURE);
     }
-    volpath = argv[optind];
+    /* Inhereting perms in ad_mkdir etc requires this */
+    ad_setfuid(0);
 
     setvbuf(stdout, (char *) NULL, _IONBF, 0);
 
@@ -257,11 +199,14 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);
     }
 
+    /* Initialize CNID subsystem */
+    cnid_init();
+
     /* Setup logging. Should be portable among *NIXes */
-    if (!verbose)
-        setuplog("default:info", "/dev/tty");
+    if (flags & DBD_FLAGS_VERBOSE)
+        setuplog("default:note, cnid:debug", "/dev/tty");
     else
-        setuplog("default:debug", "/dev/tty");
+        setuplog("default:note", "/dev/tty");
 
     if (load_volumes(&obj) != 0) {
         dbd_log( LOGSTD, "Couldn't load volumes");
@@ -278,7 +223,20 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);
     }
 
-    pack_setvol(vol);
+    /* open volume */
+    if (STRCMP(vol->v_cnidscheme, != , "dbd")) {
+        dbd_log(LOGSTD, "\"%s\" isn't a \"dbd\" CNID volume", vol->v_path);
+        exit(EXIT_FAILURE);
+    }
+    if ((vol->v_cdb = cnid_open(vol->v_path,
+                                0000,
+                                "dbd",
+                                flags,
+                                vol->v_cnidserver,
+                                vol->v_cnidport)) == NULL) {
+        dbd_log(LOGSTD, "Cant initialize CNID database connection for %s", vol->v_path);
+        exit(EXIT_FAILURE);
+    }
 
     if (vol->v_adouble == AD_VERSION_EA)
         dbd_log( LOGDEBUG, "adouble:ea volume");
@@ -301,145 +259,28 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);        
     }
 
-    /* Enuser dbpath is there, create if necessary */
-    struct stat st;
-    if (stat(vol->v_dbpath, &st) != 0) {
-        if (errno != ENOENT) {
-            dbd_log( LOGSTD, "Can't stat dbpath \"%s\": %s", vol->v_dbpath, strerror(errno));
-            exit(EXIT_FAILURE);        
-        }
-        if ((mkdir(vol->v_dbpath, 0755)) != 0) {
-            dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", vol->v_dbpath, strerror(errno));
-            exit(EXIT_FAILURE);
-        }        
-    }
-
-    /* Put "/.AppleDB" at end of volpath, get path from volinfo file */
-    if ( (strlen(vol->v_dbpath) + strlen("/.AppleDB")) > MAXPATHLEN ) {
-        dbd_log( LOGSTD, "Volume pathname too long");
-        exit(EXIT_FAILURE);        
-    }
-    strncpy(dbpath, vol->v_dbpath, MAXPATHLEN - strlen("/.AppleDB"));
-    strcat(dbpath, "/.AppleDB");
-
-    /* Check or create dbpath */
-    int dbdirfd = open(dbpath, O_RDONLY);
-    if (dbdirfd == -1 && errno == ENOENT) {
-        if (errno == ENOENT) {
-            if ((mkdir(dbpath, 0755)) != 0) {
-                dbd_log( LOGSTD, "Can't create .AppleDB for \"%s\": %s", dbpath, strerror(errno));
-                exit(EXIT_FAILURE);
-            }
-        } else {
-            dbd_log( LOGSTD, "Somethings wrong with .AppleDB for \"%s\", giving up: %s", dbpath, strerror(errno));
-            exit(EXIT_FAILURE);
-        }
-    } else {
-        close(dbdirfd);
-    }
-
-    /* Get db lock */
-    if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
-        goto exit_noenv;
-    if (db_locked != LOCK_EXCL) {
-        dbd_log(LOGDEBUG, "Database is in use, acquiring shared lock");
-        /* Couldn't get exclusive lock, try shared lock if -e wasn't requested */
-        if (exclusive) {
-            dbd_log(LOGSTD, "Database is in use and exlusive was requested");
-            goto exit_noenv;
-        }
-        if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD)
-            goto exit_noenv;
-    }
-
-    /* Check if -f is requested and wipe db if yes */
-    if ((flags & DBD_FLAGS_FORCE) && rebuild) {
-        char cmd[8 + MAXPATHLEN];
-        if ((db_locked = get_lock(LOCK_FREE, NULL)) != 0)
-            goto exit_noenv;
-
-        snprintf(cmd, 8 + MAXPATHLEN, "rm -rf \"%s\"", dbpath);
-        dbd_log( LOGDEBUG, "Removing old database of volume: '%s'", volpath);
-        system(cmd);
-        if ((mkdir(dbpath, 0755)) != 0) {
-            dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", dbpath, strerror(errno));
-            exit(EXIT_FAILURE);
-        }
-        dbd_log( LOGDEBUG, "Removed old database.");
-        if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
-            goto exit_noenv;
-    }
-
-    /* 
-       Lets start with the BerkeleyDB stuff
-    */
-    if ( ! nocniddb) {
-        if ((dbd = dbif_init(dbpath, "cnid2.db")) == NULL)
-            goto exit_noenv;
-        
-        if (dbif_env_open(dbd,
-                          &db_param,
-                          (db_locked == LOCK_EXCL) ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
-            dbd_log( LOGSTD, "error opening database!");
-            goto exit_noenv;
-        }
-
-        if (db_locked == LOCK_EXCL)
-            dbd_log( LOGDEBUG, "Finished recovery.");
-
-        if (dbif_open(dbd, NULL, rebuildindexes) < 0) {
-            dbif_close(dbd);
-            goto exit_failure;
-        }
-
-        /* Prepare upgrade ? We're done */
-        if (prep_upgrade) {
-            (void)dbif_txn_close(dbd, 1);
-            goto cleanup;
+    if (flags & DBD_FLAGS_FORCE) {
+        if (cnid_wipe(vol->v_cdb) != 0) {
+            dbd_log( LOGSTD, "Failed to wipe CNID db");
+            EC_FAIL;
         }
     }
 
-    /* Downgrade db lock if not running exclusive */
-    if (!exclusive && (db_locked == LOCK_EXCL)) {
-        if (get_lock(LOCK_UNLOCK, NULL) != 0)
-            goto exit_failure;
-        if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD)
-            goto exit_failure;
-    }
-
     /* Now execute given command scan|rebuild|dump */
-    if (dump && ! nocniddb) {
-        if (dbif_dump(dbd, dumpindexes) < 0) {
-            dbd_log( LOGSTD, "Error dumping database");
-        }
-    } else if ((rebuild && ! nocniddb) || scan) {
-        if (cmd_dbd_scanvol(dbd, vol, flags) < 0) {
+    switch (dbd_cmd) {
+    case dbd_scan:
+    case dbd_rebuild:
+        if (cmd_dbd_scanvol(vol, flags) < 0) {
             dbd_log( LOGSTD, "Error repairing database.");
         }
+        break;
     }
 
-cleanup:
-    /* Cleanup */
-    dbd_log(LOGDEBUG, "Closing db");
-    if (! nocniddb) {
-        if (dbif_close(dbd) < 0) {
-            dbd_log( LOGSTD, "Error closing database");
-            goto exit_failure;
-        }
-    }
-
-exit_success:
-    ret = 0;
-
-exit_failure:
-    if (dbif_env_remove(dbpath) < 0) {
-        dbd_log( LOGSTD, "Error removing BerkeleyDB database environment");
-        ret++;
-    }
-    get_lock(0, NULL);
+EC_CLEANUP:
+    if (vol)
+        cnid_close(vol->v_cdb);
 
-exit_noenv:    
-    if ((fchdir(cdir)) < 0)
+    if (cdir != -1 && (fchdir(cdir) < 0))
         dbd_log(LOGSTD, "fchdir: %s", strerror(errno));
 
     if (ret == 0)
index efec636b482e464f40a1bda7ebc469dd420acb70..9fcb3f4edbef4178feb1004a7864bab7cfd520c4 100644 (file)
@@ -12,29 +12,18 @@ typedef unsigned int dbd_flags_t;
 
 #define DBD_FLAGS_SCAN     (1 << 0)
 #define DBD_FLAGS_FORCE    (1 << 1)
-#define DBD_FLAGS_EXCL     (1 << 2)
-#define DBD_FLAGS_CLEANUP  (1 << 3) /* Dont create AD stuff, but cleanup orphaned */
-#define DBD_FLAGS_STATS    (1 << 4)
-#define DBD_FLAGS_V2TOEA   (1 << 5) /* Convert adouble:v2 to adouble:ea */
+#define DBD_FLAGS_STATS    (1 << 2)
+#define DBD_FLAGS_V2TOEA   (1 << 3) /* Convert adouble:v2 to adouble:ea */
+#define DBD_FLAGS_VERBOSE  (1 << 4)
 
 #define ADv2_DIRNAME ".AppleDouble"
 
 #define DIR_DOT_OR_DOTDOT(a) \
         ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
 
-#define STRCMP(a,b,c) \
-        (strcmp(a,c) b 0)
-
-extern int nocniddb; /* Dont open CNID database, only scan filesystem */
-extern int db_locked; /* have we got the fcntl lock on lockfd ? */
 extern volatile sig_atomic_t alarmed;
 
 extern void dbd_log(enum logtype lt, char *fmt, ...);
-extern int cmd_dbd_scanvol(DBD *dbd, struct vol *vol, dbd_flags_t flags);
+extern int cmd_dbd_scanvol(struct vol *vol, 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_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply);
 #endif /* CMD_DBD_H */
index dcbd4c74779161acb4be4f3b3feda12bc6bec771..37012f27d4b06cecc058ba8dae5549d7c313dd7d 100644 (file)
 #include <atalk/adouble.h>
 #include <atalk/unicode.h>
 #include <atalk/netatalk_conf.h>
-#include <atalk/cnid_dbd_private.h>
+//#include <atalk/cnid_dbd_private.h>
 #include <atalk/volume.h>
 #include <atalk/ea.h>
 #include <atalk/util.h>
 #include <atalk/acl.h>
 #include <atalk/compat.h>
+#include <atalk/cnid.h>
 
 #include "cmd_dbd.h"
 #include "dbif.h"
@@ -48,7 +49,7 @@
 
 static struct vol     *myvol;
 static char           cwdbuf[MAXPATHLEN+1];
-static DBD            *dbd;
+static struct vol     *vol;
 static DBD            *dbd_rebuild;
 static dbd_flags_t    dbd_flags;
 static char           stamp[CNID_DEV_LEN];
@@ -65,6 +66,7 @@ static struct cnid_dbd_rqst rqst;
 static struct cnid_dbd_rply rply;
 static jmp_buf jmp;
 static char pname[MAXPATHLEN] = "../";
+static char cnidResBuf[12 + MAXPATHLEN + 1];
 
 /*
   Taken form afpd/desktop.c
@@ -189,43 +191,13 @@ static int update_cnid(cnid_t did, const struct stat *sp, const char *oldname, c
     int ret;
     cnid_t id;
 
-    /* Prepare request data */
-    memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
-    memset(&rply, 0, sizeof(struct cnid_dbd_rply));
-    rqst.did = did;
-    rqst.cnid = 0;
-    if ( ! (myvol->v_flags & AFPVOL_NODEV))
-        rqst.dev = sp->st_dev;
-    rqst.ino = sp->st_ino;
-    rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
-    rqst.name = (char *)oldname;
-    rqst.namelen = strlen(oldname);
-
     /* Query the database */
-    ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
-    if (dbif_txn_close(dbd, ret) != 0)
-        return -1;
-    if (rply.result != CNID_DBD_RES_OK)
+    if ((id = cnid_lookup(vol->v_cdb, sp, did, (char *)oldname, strlen(oldname))) == CNID_INVALID)
+        /* not in db, no need to update */
         return 0;
-    id = rply.cnid;
-
-    /* Prepare request data */
-    memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
-    memset(&rply, 0, sizeof(struct cnid_dbd_rply));
-    rqst.did = did;
-    rqst.cnid = id;
-    if ( ! (myvol->v_flags & AFPVOL_NODEV))
-        rqst.dev = sp->st_dev;
-    rqst.ino = sp->st_ino;
-    rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
-    rqst.name = (char *)newname;
-    rqst.namelen = strlen(newname);
 
     /* Update the database */
-    ret = dbd_update(dbd, &rqst, &rply);
-    if (dbif_txn_close(dbd, ret) != 0)
-        return -1;
-    if (rply.result != CNID_DBD_RES_OK)
+    if (cnid_update(vol->v_cdb, id, sp, did, (char *)newname, strlen(newname)) < 0)
         return -1;
 
     return 0;
@@ -258,9 +230,6 @@ static int check_adfile(const char *fname, const struct stat *st, const char **n
         return 0;
     }
     
-    if (dbd_flags & DBD_FLAGS_CLEANUP)
-        return 0;
-
     if (S_ISDIR(st->st_mode))
         adflags |= ADFLAGS_DIR;
 
@@ -422,9 +391,6 @@ static int check_addir(int volroot)
     struct adouble ad;
     char *mname = NULL;
 
-    if (dbd_flags & DBD_FLAGS_CLEANUP)
-        return 0;
-
     if (myvol->v_adouble == AD_VERSION_EA)
         return 0;
 
@@ -644,31 +610,17 @@ static int read_addir(void)
 static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok)
 {
     int ret, adflags = ADFLAGS_HF;
-    cnid_t db_cnid, ad_cnid;
+    cnid_t db_cnid, ad_cnid, tmpid;
     struct adouble ad;
 
     adflags = ADFLAGS_HF | (S_ISDIR(st->st_mode) ? ADFLAGS_DIR : 0);
 
-    /* Force checkout every X items */
-    static int cnidcount = 0;
-    cnidcount++;
-    if (cnidcount > 10000) {
-        cnidcount = 0;
-        if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
-            dbd_log(LOGSTD, "Error checkpointing!");
-            return CNID_INVALID;
-        }
-    }
-
     /* Get CNID from ad-file */
-    ad_cnid = 0;
+    ad_cnid = CNID_INVALID;
     if (ADFILE_OK) {
         ad_init(&ad, myvol);
         if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) {
             
-            if (dbd_flags & DBD_FLAGS_CLEANUP)
-                return CNID_INVALID;
-
             if (myvol->v_adouble != AD_VERSION_EA) {
                 dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno));
                 return CNID_INVALID;
@@ -676,7 +628,6 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
             dbd_log( LOGDEBUG, "File without meta EA: \"%s/%s\"", cwdbuf, name);
             adfile_ok = 1;
         } else {
-
             if (dbd_flags & DBD_FLAGS_FORCE) {
                 ad_cnid = ad_forcegetid(&ad);
                 /* This ensures the changed stamp is written */
@@ -694,128 +645,26 @@ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfi
     }
 
     /* 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;
-    rqst.cnid = ad_cnid;
-    if ( ! (myvol->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 = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
-    if (dbif_txn_close(dbd, ret) != 0)
+    if ((db_cnid = cnid_add(vol->v_cdb, st, did, (char *)name, strlen(name), ad_cnid)) == CNID_INVALID)
         return CNID_INVALID;
-    if (rply.result == CNID_DBD_RES_OK) {
-        db_cnid = rply.cnid;
-    } else if (rply.result == CNID_DBD_RES_NOTFOUND) {
-        if ( ! (dbd_flags & DBD_FLAGS_FORCE))
-            dbd_log( LOGSTD, "No CNID for '%s/%s' in database", 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)) {
+    /* Compare CNID from db and adouble file */
+    if (ad_cnid != db_cnid && adfile_ok == 0) {
         /* Mismatch, overwrite ad file with value from db */
-        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)) {
-            dbd_log(LOGSTD, "Updating AppleDouble file for '%s/%s' with CNID: %u from database",
-                            cwdbuf, name, ntohl(db_cnid));
-            ad_init(&ad, myvol);
-            if (ad_open(&ad, name, adflags | ADFLAGS_HF | ADFLAGS_RDWR) != 0) {
-                dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
-                        cwdbuf, name, strerror(errno));
-                return CNID_INVALID;
-            }
-            ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
-            ad_flush(&ad);
-            ad_close(&ad, ADFLAGS_HF);
-        }
-        return db_cnid;
-    } else if (ad_cnid && (db_cnid == 0)) {
-        /* in ad-file but not in db */
-        if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
-            /* Ensure the cnid from the ad-file is not already occupied by another file */
-            dbd_log(LOGDEBUG, "Checking whether CNID %u from ad-file is occupied",
-                    ntohl(ad_cnid));
-
-            rqst.cnid = ad_cnid;
-            ret = dbd_resolve(dbd, &rqst, &rply);
-            if (rply.result == CNID_DBD_RES_OK) {
-                /* Occupied! Choose another, update ad-file */
-                ret = dbd_add(dbd, &rqst, &rply, 1);
-                if (dbif_txn_close(dbd, ret) != 0)
-                    return CNID_INVALID;
-                db_cnid = rply.cnid;
-                dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
-
-                if (ADFILE_OK && ( ! (dbd_flags & DBD_FLAGS_SCAN))) {
-                    dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file",
-                            cwdbuf, name, ntohl(db_cnid));
-                    ad_init(&ad, myvol);
-                    if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) {
-                        dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
-                                cwdbuf, name, strerror(errno));
-                        return CNID_INVALID;
-                    }
-                    ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
-                    ad_flush(&ad);
-                    ad_close(&ad, ADFLAGS_HF);
-                }
-                return db_cnid;
-            }
-
-            dbd_log(LOGDEBUG, "CNID rebuild add '%s/%s' with CNID from ad-file %u",
-                    cwdbuf, name, ntohl(ad_cnid));
-            rqst.cnid = ad_cnid;
-            ret = dbd_rebuild_add(dbd, &rqst, &rply);
-            if (dbif_txn_close(dbd, ret) != 0)
-                return CNID_INVALID;
-        }
-        return ad_cnid;
-    } else if ((db_cnid == 0) && (ad_cnid == 0)) {
-        /* No CNID at all, we clearly have to allocate a fresh one... */
-        /* Note: the next test will use this new CNID too! */
-        if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
-            /* add to db */
-            ret = dbd_add(dbd, &rqst, &rply, 1);
-            if (dbif_txn_close(dbd, ret) != 0)
-                return CNID_INVALID;
-            db_cnid = rply.cnid;
-            dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
-        }
-    }
-
-    if ((ad_cnid == 0) && db_cnid) {
-        /* in db but zeroID in ad-file, write it to ad-file */
-        if (ADFILE_OK && ! (dbd_flags & DBD_FLAGS_SCAN)) {            
-            dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file",
-                    cwdbuf, name, ntohl(db_cnid));
-            ad_init(&ad, myvol);
-            if (ad_open(&ad, name, adflags | ADFLAGS_RDWR) != 0) {
-                dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
-                        cwdbuf, name, strerror(errno));
-                return CNID_INVALID;
-            }
-            ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
-            ad_flush(&ad);
-            ad_close(&ad, ADFLAGS_HF);
+        dbd_log(LOGSTD, "CNID mismatch for '%s/%s', CNID db: %u, ad-file: %u",
+                cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid));
+        ad_init(&ad, myvol);
+        if (ad_open(&ad, name, adflags | ADFLAGS_HF | ADFLAGS_RDWR) != 0) {
+            dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
+                    cwdbuf, name, strerror(errno));
+            return CNID_INVALID;
         }
-        return db_cnid;
+        ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
+        ad_flush(&ad);
+        ad_close(&ad, ADFLAGS_HF);
     }
 
-    return CNID_INVALID;
+    return db_cnid;
 }
 
 /*
@@ -939,30 +788,28 @@ static int dbd_readdir(int volroot, cnid_t did)
             update_cnid(did, &st, ep->d_name, name);
         }
 
-        if ( ! nocniddb) {
-            /* Check CNIDs */
-            cnid = check_cnid(name, did, &st, adfile_ok);
+        /* Check CNIDs */
+        cnid = check_cnid(name, did, &st, adfile_ok);
 
-            /* Now add this object to our rebuild dbd */
-            if (cnid && dbd_rebuild) {
-                static uint count = 0;
-                rqst.cnid = rply.cnid;
-                ret = dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
-                if (dbif_txn_close(dbd_rebuild, ret) != 0)
-                    return -1;
-                if (rply.result != CNID_DBD_RES_OK) {
-                    dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
-                             cnid, cwdbuf, name);
+        /* Now add this object to our rebuild dbd */
+        if (cnid && dbd_rebuild) {
+            static uint count = 0;
+            rqst.cnid = rply.cnid;
+            ret = dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
+            if (dbif_txn_close(dbd_rebuild, ret) != 0)
+                return -1;
+            if (rply.result != CNID_DBD_RES_OK) {
+                dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
+                         cnid, cwdbuf, name);
+                return -1;
+            }
+            count++;
+            if (count == 10000) {
+                if (dbif_txn_checkpoint(dbd_rebuild, 0, 0, 0) < 0) {
+                    dbd_log(LOGSTD, "Error checkpointing!");
                     return -1;
                 }
-                count++;
-                if (count == 10000) {
-                    if (dbif_txn_checkpoint(dbd_rebuild, 0, 0, 0) < 0) {
-                        dbd_log(LOGSTD, "Error checkpointing!");
-                        return -1;
-                    }
-                    count = 0;
-                }
+                count = 0;
             }
         }
 
@@ -973,7 +820,7 @@ static int dbd_readdir(int volroot, cnid_t did)
         /**************************************************************************
           Recursion
         **************************************************************************/
-        if (S_ISDIR(st.st_mode) && (cnid || nocniddb)) { /* If we have no cnid for it we cant recur */
+        if (S_ISDIR(st.st_mode) && cnid) { /* If we have no cnid for it we cant enter recursion */
             strcat(cwdbuf, "/");
             strcat(cwdbuf, name);
             dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf);
@@ -1050,174 +897,39 @@ static int scanvol(struct vol *vol, dbd_flags_t flags)
     return 0;
 }
 
-/*
-  Remove all CNIDs from dbd that are not in dbd_rebuild
-*/
-static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
-{
-    int ret = 0, deleted = 0;
-    cnid_t dbd_cnid = 0, rebuild_cnid = 0;
-    struct cnid_dbd_rqst rqst;
-    struct cnid_dbd_rply rply;
-
-    /* jump over rootinfo key */
-    if ( dbif_idwalk(dbd, &dbd_cnid, 0) != 1)
-        return;
-    if ( dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0) != 1)
-        return;
-
-    /* Get first id from dbd_rebuild */
-    if ((dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1)
-        return;
-
-    /* Start main loop through dbd: get CNID from dbd */
-    while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
-        /* Check if we got a termination signal */
-        if (alarmed)
-            longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
-
-        if (deleted > 1000) {
-            deleted = 0;
-            if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
-                dbd_log(LOGSTD, "Error checkpointing!");
-                goto cleanup;
-            }
-        }
-
-        /* This should be the normal case: CNID is in both dbs */
-        if (dbd_cnid == rebuild_cnid) {
-            /* Get next CNID from rebuild db */
-            if ((ret = dbif_idwalk(dbd_rebuild, &rebuild_cnid, 0)) == -1) {
-                /* Some error */
-                goto cleanup;
-            } else if (ret == 0) {
-                /* end of rebuild_cnid, delete all remaining CNIDs from dbd */
-                while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) {
-                    dbd_log(LOGSTD, "Orphaned CNID in database: %u", dbd_cnid);
-                    if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
-                        rqst.cnid = htonl(dbd_cnid);
-                        if ((ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID)) == -1) {
-                            dbd_log(LOGSTD, "Error deleting CNID %u", dbd_cnid);
-                            (void)dbif_txn_abort(dbd);
-                            goto cleanup;
-                        }
-                        
-                        if (dbif_txn_close(dbd, ret) != 0)
-                            return;
-                        deleted++;
-                    }
-                    /* Check if we got a termination signal */
-                    if (alarmed)
-                        longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
-                }
-                return;
-            } else
-                /* Normal case (ret=1): continue while loop */
-                continue;
-        }
-
-        if (dbd_cnid < rebuild_cnid) {
-            /* CNID is orphaned -> delete */
-            dbd_log(LOGSTD, "One orphaned CNID in database: %u.", dbd_cnid);
-            if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
-                rqst.cnid = htonl(dbd_cnid);
-                if ((ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID)) == -1) {
-                    dbd_log(LOGSTD, "Error deleting CNID %u", dbd_cnid);
-                    (void)dbif_txn_abort(dbd);
-                    goto cleanup;
-                }
-                if (dbif_txn_close(dbd, ret) != 0)
-                    return;
-                deleted++;
-            }
-            continue;
-        }
-
-        if (dbd_cnid > rebuild_cnid) {
-            dbif_idwalk(dbd, NULL, 1); /* Close cursor */
-            dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
-            (void)dbif_txn_close(dbd, 2);
-            (void)dbif_txn_close(dbd_rebuild, 2);                
-            dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid);
-            dbif_dump(dbd_rebuild, 0);
-            dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!");
-            goto cleanup;
-        }
-    } /* while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) */
-
-cleanup:
-    dbif_idwalk(dbd, NULL, 1); /* Close cursor */
-    dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
-    return;
-}
-
-static const char *get_tmpdb_path(void)
-{
-    pid_t pid = getpid();
-    static char path[MAXPATHLEN];
-    snprintf(path, MAXPATHLEN, "/tmp/tmpdb-dbd.%u", pid);
-    if (mkdir(path, 0755) != 0)
-        return NULL;
-    return path;
-}
-
 /*
   Main func called from cmd_dbd.c
 */
-int cmd_dbd_scanvol(DBD *dbd_ref, struct vol *vol, dbd_flags_t flags)
+int cmd_dbd_scanvol(struct vol *vol_in, dbd_flags_t flags)
 {
     int ret = 0;
-    struct db_param db_param = { 0 };
-    const char *tmpdb_path = NULL;
-
-    /* Set cachesize for in-memory rebuild db */
-    db_param.cachesize = 64 * 1024;         /* 64 MB */
-    db_param.maxlocks = DEFAULT_MAXLOCKS;
-    db_param.maxlockobjs = DEFAULT_MAXLOCKOBJS;
-    db_param.logfile_autoremove = 1;
 
-    /* Make it accessible for all funcs */
-    dbd = dbd_ref;
+    /* Make vol accessible for all funcs */
+    vol = vol_in;
 
     /* We only support unicode volumes ! */
     if (vol->v_volcharset != CH_UTF8) {
-        dbd_log( LOGSTD, "Not a Unicode volume: %s, %u != %u", vol->v_volcodepage, vol->v_volcharset, CH_UTF8);
+        dbd_log(LOGSTD, "Not a Unicode volume: %s, %u != %u", vol->v_volcodepage, vol->v_volcharset, CH_UTF8);
         return -1;
     }
 
-    /* Get volume stamp */
-    dbd_getstamp(dbd, &rqst, &rply);
-    if (rply.result != CNID_DBD_RES_OK) {
-        ret = -1;
+    /*
+     * Get CNID database stamp, cnid_getstamp() passes the buffer,
+     * then cnid_resolve() actually gets the value from the db
+     */
+    cnid_getstamp(vol->v_cdb, stamp, sizeof(stamp));
+    cnid_t rootid = 0;
+    if (cnid_resolve(vol->v_cdb, &rootid, cnidResBuf, sizeof(cnidResBuf)) == NULL) {
+        dbd_log(LOGSTD, "error resolving rootinfo key");
         goto exit;
     }
-    memcpy(stamp, rply.name, CNID_DEV_LEN);
-
-    /* temporary rebuild db, used with -re rebuild to delete unused CNIDs, not used with -f */
-    if (! nocniddb && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE)) {
-        tmpdb_path = get_tmpdb_path();
-        if (NULL == (dbd_rebuild = dbif_init(tmpdb_path, "cnid2.db"))) {
-            ret = -1;
-            goto exit;
-        }
-
-        if (dbif_env_open(dbd_rebuild,
-                          &db_param,
-                          DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN) < 0) {
-            dbd_log(LOGSTD, "error opening tmp database!");
-            goto exit;
-        }
-
-        if (0 != (dbif_open(dbd_rebuild, NULL, 0))) {
-            ret = -1;
-            goto exit;
-        }
 
-        if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) {
-            ret = -1;
-            goto exit;
-        }
+#if 0
+    if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) {
+        ret = -1;
+        goto exit;
     }
+#endif
 
     if (setjmp(jmp) != 0) {
         ret = 0;                /* Got signal, jump from dbd_readdir */
@@ -1231,30 +943,5 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct vol *vol, dbd_flags_t flags)
     }
 
 exit:
-    if (! nocniddb) {
-        if (dbif_txn_close(dbd, ret == 0 ? 1 : 0) != 0)
-            ret = -1;
-        if (dbd_rebuild)
-            if (dbif_txn_close(dbd_rebuild, ret == 0 ? 1 : 0) != 0)
-                ret = -1;
-        if ((ret == 0) && dbd_rebuild && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE))
-            /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
-               other clients in between our pass 1 and 2 */
-            delete_orphaned_cnids(dbd, dbd_rebuild, flags);
-    }
-
-    if (dbd_rebuild) {
-        dbd_log(LOGDEBUG, "Closing tmp db");
-        dbif_close(dbd_rebuild);
-
-        if (tmpdb_path) {
-            char cmd[8 + MAXPATHLEN];
-            snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", tmpdb_path);
-            dbd_log( LOGDEBUG, "Removing temp database '%s'", tmpdb_path);
-            system(cmd);
-            snprintf(cmd, 8 + MAXPATHLEN, "rmdir %s", tmpdb_path);
-            system(cmd);
-        }        
-    }
     return ret;
 }
index 784ac422f63e9822ed1fde524e2b15d210f3d1e6..e2a24d488c7e6ffb6769850c6c60e3f7378456c9 100644 (file)
@@ -43,6 +43,8 @@
 static DBD *dbd;
 static int exit_sig = 0;
 static int db_locked;
+static bstring dbpath;
+static struct db_param *dbp;
 
 static void sig_exit(int signo)
 {
@@ -81,6 +83,74 @@ static void block_sigs_onoff(int block)
 #define min(a,b)        ((a)<(b)?(a):(b))
 #endif
 
+static int delete_db(void)
+{
+    EC_INIT;
+    int cwd = -1;
+
+    EC_NEG1( cwd = open(".", O_RDONLY) );
+
+    chdir(bdata(dbpath));
+    system("rm -f cnid2.db lock log.* __db.*");
+    if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
+        LOG(log_error, logtype_cnid, "main: fatal db lock error");
+        EC_FAIL;
+    }
+
+EC_CLEANUP:
+    if (cwd != -1)
+        fchdir(cwd);
+    EC_EXIT;
+}
+
+static int wipe_db(void)
+{
+    EC_INIT;
+    DBT key, data;
+
+    memset(&key, 0, sizeof(key));
+    memset(&data, 0, sizeof(data));
+
+    key.data = ROOTINFO_KEY;
+    key.size = ROOTINFO_KEYLEN;
+
+    if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) <= 0) {
+        LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error getting rootinfo record");
+        EC_FAIL;
+    }
+
+    EC_NEG1_LOG( dbif_close(dbd) );
+    EC_NEG1_LOG( dbif_env_remove(bdata(dbpath)) );
+    EC_ZERO_LOG( delete_db() );
+
+    /* Get db lock */
+    if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
+        LOG(log_error, logtype_cnid, "main: fatal db lock error");
+        EC_FAIL;
+    }
+
+    EC_NULL_LOG( dbd = dbif_init(bdata(dbpath), "cnid2.db") );
+
+    /* Only recover if we got the lock */
+    EC_NEG1_LOG( dbif_env_open(dbd, dbp, DBOPTIONS | DB_RECOVER) );
+
+    LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
+
+    EC_NEG1_LOG( dbif_open(dbd, dbp, 0) );
+
+    memset(&key, 0, sizeof(key));
+    key.data = ROOTINFO_KEY;
+    key.size = ROOTINFO_KEYLEN;
+
+    if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) != 0) {
+        LOG(log_error, logtype_cnid, "dbif_copy_rootinfokey: Error writing rootinfo key");
+        EC_FAIL;
+    }
+
+EC_CLEANUP:
+    EC_EXIT;
+}
+
 static int loop(struct db_param *dbp)
 {
     struct cnid_dbd_rqst rqst;
@@ -171,6 +241,9 @@ static int loop(struct db_param *dbp)
             case CNID_DBD_OP_SEARCH:
                 ret = dbd_search(dbd, &rqst, &rply);
                 break;
+            case CNID_DBD_OP_WIPE:
+                ret = wipe_db();
+                break;
             default:
                 LOG(log_error, logtype_cnid, "loop: unknown op %d", rqst.op);
                 ret = -1;
@@ -274,14 +347,12 @@ static void set_signal(void)
 int main(int argc, char *argv[])
 {
     EC_INIT;
-    struct db_param *dbp;
     int delete_bdb = 0;
     int ctrlfd = -1, clntfd = -1;
     char *logconfig;
     AFPObj obj = { 0 };
     struct vol *vol;
     char *volpath = NULL;
-    bstring dbpath;
 
     while (( ret = getopt( argc, argv, "dF:l:p:t:vV")) != -1 ) {
         switch (ret) {
@@ -327,26 +398,14 @@ int main(int argc, char *argv[])
     switch_to_user(bdata(dbpath));
 
     /* Get db lock */
-    if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) == -1) {
+    if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
         LOG(log_error, logtype_cnid, "main: fatal db lock error");
         EC_FAIL;
     }
-    if (db_locked != LOCK_EXCL) {
-        /* Couldn't get exclusive lock, try shared lock  */
-        if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD) {
-            LOG(log_error, logtype_cnid, "main: fatal db lock error");
-            EC_FAIL;
-        }
-    }
 
-    if (delete_bdb && (db_locked == LOCK_EXCL)) {
+    if (delete_bdb) {
         LOG(log_warning, logtype_cnid, "main: too many CNID db opening attempts, wiping the slate clean");
-        chdir(bdata(dbpath));
-        system("rm -f cnid2.db lock log.* __db.*");
-        if ((db_locked = get_lock(LOCK_EXCL, bdata(dbpath))) != LOCK_EXCL) {
-            LOG(log_error, logtype_cnid, "main: fatal db lock error");
-            EC_FAIL;
-        }
+        EC_ZERO( delete_db() );
     }
 
     set_signal();
index 2d3aa062b8b601c4ac016e4aa59d5d672e8e05c6..ba0b62fad3d0d1e4149d5aeae63565e1b748e3f8 100644 (file)
@@ -69,6 +69,7 @@ struct _cnid_db {
                                 const char *, size_t, cnid_t);
     int    (*cnid_find)        (struct _cnid_db *cdb, const char *name, size_t namelen,
                                 void *buffer, size_t buflen);
+    int    (*cnid_wipe)        (struct _cnid_db *cdb);
 };
 typedef struct _cnid_db cnid_db;
 
@@ -123,6 +124,7 @@ cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_
                         char *name, const size_t len, cnid_t hint);
 int    cnid_find       (struct _cnid_db *cdb, const char *name, size_t namelen,
                         void *buffer, size_t buflen);
+int    cnid_wipe       (struct _cnid_db *cdb);
 void   cnid_close      (struct _cnid_db *db);
 
 #endif
index d7484e42088d7c69ab71326f96d71c1d093bea86..b61f7a8ce6e3d1d65275c4c01537ac967c6a3894 100644 (file)
@@ -25,6 +25,7 @@
 #define CNID_DBD_OP_GETSTAMP    0x0b
 #define CNID_DBD_OP_REBUILD_ADD 0x0c
 #define CNID_DBD_OP_SEARCH      0x0d
+#define CNID_DBD_OP_WIPE        0x0e
 
 #define CNID_DBD_RES_OK            0x00
 #define CNID_DBD_RES_NOTFOUND      0x01
index 056420dad099f1123a6e514f98630055d285fa3a..757d1b0da1e2c3c351ef618679e5ab37b2c64b48 100644 (file)
@@ -144,7 +144,7 @@ static struct _cnid_db *cnid_cdb_new(const char *volpath)
     cdb->cnid_close = cnid_cdb_close;
     cdb->cnid_getstamp = cnid_cdb_getstamp;
     cdb->cnid_rebuild_add = cnid_cdb_rebuild_add;
-
+    cdb->cnid_wipe = NULL;
     return cdb;
 }
 
index 0a977e6ae8a5f4f469b48b7b037e1811d370ba76..7cf3af1618d19a6de2e0cecada09936aeab90508 100644 (file)
@@ -338,3 +338,15 @@ cnid_t ret;
     unblock_signal(cdb->flags);
     return ret;
 }
+
+/* --------------- */
+int cnid_wipe(struct _cnid_db *cdb)
+{
+    int ret = 0;
+
+    block_signal(cdb->flags);
+    if (cdb->cnid_wipe)
+        ret = cdb->cnid_wipe(cdb);
+    unblock_signal(cdb->flags);
+    return ret;
+}
index 32be8f475408fc644d21d010dc9e76091678d9e4..b654740a5df56d2fcd8082ba9ba361a5d98edd99 100644 (file)
@@ -456,7 +456,7 @@ static struct _cnid_db *cnid_dbd_new(const char *volpath)
     cdb->cnid_update = cnid_dbd_update;
     cdb->cnid_rebuild_add = cnid_dbd_rebuild_add;
     cdb->cnid_close = cnid_dbd_close;
-
+    cdb->cnid_wipe = cnid_dbd_wipe;
     return cdb;
 }
 
@@ -994,6 +994,57 @@ int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id)
     }
 }
 
+int cnid_dbd_wipe(struct _cnid_db *cdb)
+{
+    CNID_private *db;
+    struct cnid_dbd_rqst rqst;
+    struct cnid_dbd_rply rply;
+
+    if (!cdb || !(db = cdb->_private)) {
+        LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error");
+        errno = CNID_ERR_PARAM;
+        return -1;
+    }
+
+    LOG(log_debug, logtype_cnid, "cnid_dbd_wipe");
+
+    RQST_RESET(&rqst);
+    rqst.op = CNID_DBD_OP_WIPE;
+    rqst.cnid = 0;
+
+    rply.namelen = 0;
+    if (transmit(db, &rqst, &rply) < 0) {
+        errno = CNID_ERR_DB;
+        return -1;
+    }
+
+    if (rply.result != CNID_DBD_RES_OK) {
+        errno = CNID_ERR_DB;
+        return -1;
+    }
+    LOG(log_debug, logtype_cnid, "cnid_dbd_wipe: ok");
+
+    struct cnid_dbd_rqst rqst_stamp;
+    struct cnid_dbd_rply rply_stamp;
+    char  stamp[ADEDLEN_PRIVSYN];
+
+    dbd_initstamp(&rqst_stamp);
+    memset(stamp, 0, ADEDLEN_PRIVSYN);
+    rply_stamp.name = stamp;
+    rply_stamp.namelen = ADEDLEN_PRIVSYN;
+
+    if (dbd_rpc(db, &rqst_stamp, &rply_stamp) < 0)
+        return -1;
+    if (dbd_reply_stamp(&rply_stamp ) < 0)
+        return -1;
+
+    if (db->client_stamp)
+        memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
+    memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
+
+    return 0;
+}
+
 
 struct _cnid_module cnid_dbd_module = {
     "dbd",
index fdba4c042a62591e3e771ed449ad7de6588986ca..69ff5a64fb252a0e8424a76ebb9e688eded6174b 100644 (file)
@@ -32,7 +32,7 @@ extern int    cnid_dbd_update     (struct _cnid_db *, cnid_t, const struct stat
 extern int    cnid_dbd_delete     (struct _cnid_db *, const cnid_t);
 extern cnid_t cnid_dbd_rebuild_add(struct _cnid_db *, const struct stat *,
                                    cnid_t, const char *, size_t, cnid_t);
-
+extern int    cnid_dbd_wipe       (struct _cnid_db *cdb);
 /* FIXME: These functions could be static in cnid_dbd.c */
 
 #endif /* include/atalk/cnid_dbd.h */
index 5903d03fe449da281238818e9501c57e812cf9f1..fd92cc5a7b87090d032ab7cf97fdadd817c80937 100644 (file)
@@ -139,7 +139,8 @@ static struct _cnid_db *cnid_last_new(const char *volpath)
     cdb->cnid_resolve = cnid_last_resolve;
     cdb->cnid_update = cnid_last_update;
     cdb->cnid_close = cnid_last_close;
-    
+    cdb->cnid_wipe = NULL;
+
     return cdb;
 }
 
index d02ef0bcc054caa1da65ab3ccfa5f6c5885a8b5a..889cea1ee8c6539024952a00c70c1c4b7bfe35ab 100644 (file)
@@ -56,7 +56,8 @@ static struct _cnid_db *cnid_tdb_new(const char *volpath)
     cdb->cnid_resolve = cnid_tdb_resolve;
     cdb->cnid_update = cnid_tdb_update;
     cdb->cnid_close = cnid_tdb_close;
-    
+    cdb->cnid_wipe = NULL;
+
     return cdb;
 }