]> arthur.barton.de Git - netatalk.git/commitdiff
Merge master
authorFrank Lahm <franklahm@googlemail.com>
Fri, 10 Dec 2010 10:47:37 +0000 (11:47 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Fri, 10 Dec 2010 10:47:37 +0000 (11:47 +0100)
29 files changed:
NEWS
bin/ad/ad_find.c
bin/ad/ad_util.c
configure.in
etc/afpd/afp_config.c
etc/afpd/afp_options.c
etc/afpd/catsearch.c
etc/afpd/status.c
etc/afpd/volume.c
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/cmd_dbd.h
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/cnid_metad.c
etc/cnid_dbd/db_param.c
etc/cnid_dbd/db_param.h
etc/cnid_dbd/dbd.h
etc/cnid_dbd/dbd_add.c
etc/cnid_dbd/dbd_getstamp.c
etc/cnid_dbd/dbif.c
etc/cnid_dbd/main.c
etc/cnid_dbd/pack.c
include/atalk/cnid_private.h
include/atalk/util.h
include/atalk/volinfo.h
include/atalk/volume.h
libatalk/util/unix.c
libatalk/util/volinfo.c
man/man5/AppleVolumes.default.5.tmpl
man/man8/cnid_dbd.8.tmpl

diff --git a/NEWS b/NEWS
index 30f29b3cccafd90b8f9f59b26eb9a0752f2bd6f1..8dd452f2f1159a992a71b900d201b5ae64a71d52 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+Changes in 2.2alpha5
+====================
+
+* UPD: afpd: new option "searchdb" which enables fast catalog searches
+       using the CNID db.
+* UPD: Case-insensitive fast search with the CNID db
+* UPD: cnid_dbd: afpd now passes the volume path, not the db path when
+       connecting for a volume. cnid_dbd will read the
+       ".AppleDesktop/.volinfo" file of the volume in order to figure
+       out the CNID db path and the volume charset encoding.
+
 Changes in 2.2alpha4
 ====================
 
@@ -6,9 +17,8 @@ Changes in 2.2alpha4
 * NEW: afpd: support for fast catalog searches
 * NEW: ad utility: ad find
 * UPD: afpd: CNID database versioning check for "cdb" scheme
-* UPD: cnid_dbd: CNID database versioning
-* UPD: cnid_dbd: CNID database upgrading
-* UPD: cnid_dbd: additional CNID database index for fast name searches
+* UPD: cnid_dbd: CNID database versioning and upgrading. Additional
+       CNID database index for fast name searches.
 
 Changes in 2.2alpha3
 ====================
index 9891b14c742cf199adec486ebf53d271d74f5cee..8501500c7c7ff9acb229a3a005a0279db55442d3 100644 (file)
@@ -33,6 +33,7 @@
 #include <atalk/bstradd.h>
 #include <atalk/directory.h>
 #include <atalk/util.h>
+#include <atalk/unicode.h>
 #include "ad.h"
 
 static volatile sig_atomic_t alarmed;
@@ -114,9 +115,26 @@ int ad_find(int argc, char **argv)
     if (openvol(srchvol, &vol) != 0)
         ERROR("Cant open volume \"%s\"", srchvol);
 
+    uint16_t flags = CONV_TOLOWER;
+    char namebuf[MAXPATHLEN + 1];
+    if (convert_charset(vol.volinfo.v_volcharset,
+                        vol.volinfo.v_volcharset,
+                        vol.volinfo.v_maccharset,
+                        argv[optind],
+                        strlen(argv[optind]),
+                        namebuf,
+                        MAXPATHLEN,
+                        &flags) == (size_t)-1) {
+        ERROR("conversion error");
+    }
+
     int count;
     char resbuf[DBD_MAX_SRCH_RSLTS * sizeof(cnid_t)];
-    if ((count = cnid_find(vol.volume.v_cdb, argv[optind], strlen(argv[optind]), resbuf, sizeof(resbuf))) < 1) {
+    if ((count = cnid_find(vol.volume.v_cdb,
+                           namebuf,
+                           strlen(namebuf),
+                           resbuf,
+                           sizeof(resbuf))) < 1) {
         ret = 1;
     } else {
         ret = 0;
index 3032b93b13d2c04259bfdc3346d7a50563461de4..5a9b0973c7a2173f81a74850a594a07f7facb085 100644 (file)
@@ -127,7 +127,7 @@ int openvol(const char *path, afpvol_t *vol)
     if ((vol->volinfo.v_flags & AFPVOL_NODEV))
         flags |= CNID_FLAG_NODEV;
 
-    if ((vol->volume.v_cdb = cnid_open(vol->volinfo.v_dbpath,
+    if ((vol->volume.v_cdb = cnid_open(vol->volinfo.v_path,
                                        0000,
                                        "dbd",
                                        flags,
index 76b3065a75e7cb42a18c9dbfaadd0f065b948741..9a06906c0600f07313b1541757b8f2247048fe82 100644 (file)
@@ -1252,14 +1252,6 @@ fi
 dnl --------------------- Netatalk Webmin
 NETATALK_WEBMIN
 
-dnl --------------------- Check for libuuid which is required for TimeMachine
-AC_SEARCH_LIBS([uuid_generate],
-               [uuid], ,
-               AC_MSG_ERROR([missing library libuuid required for TimeMachine]))
-AC_CHECK_HEADER([uuid/uuid.h],
-                AC_DEFINE([HAVE_UUID], 1, [have libuuid]),
-                AC_MSG_ERROR([missing header <uuid/uuid.> from libuuid required for TimeMachine]))
-
 dnl --------------------- last minute substitutions
 dnl Request SUSv3 standard interfaces
 CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D__EXTENSIONS__"
index 5bd87f906aa4d349f3630f3cd38159a2c70d6192..648eed71589b27bf77f0eccf7d3057db42ed7e3d 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-
-/* STDC check */
-#if STDC_HEADERS
 #include <string.h>
-#else /* STDC_HEADERS */
-#ifndef HAVE_STRCHR
-#define strchr index
-#define strrchr index
-#endif /* HAVE_STRCHR */
-char *strchr (), *strrchr ();
-#ifndef HAVE_MEMCPY
-#define memcpy(d,s,n) bcopy ((s), (d), (n))
-#define memmove(d,s,n) bcopy ((s), (d), (n))
-#endif /* ! HAVE_MEMCPY */
-#endif /* STDC_HEADERS */
-
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif /* HAVE_UNISTD_H */
 #include <ctype.h>
-#include <atalk/logger.h>
-#include <atalk/util.h>
-
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#ifdef USE_SRVLOC
+#include <slp.h>
+#endif /* USE_SRVLOC */
+
+#include <atalk/logger.h>
+#include <atalk/util.h>
 #include <atalk/dsi.h>
 #include <atalk/atp.h>
 #include <atalk/asp.h>
@@ -45,9 +31,7 @@ char *strchr (), *strrchr ();
 #include <atalk/afp.h>
 #include <atalk/compat.h>
 #include <atalk/server_child.h>
-#ifdef USE_SRVLOC
-#include <slp.h>
-#endif /* USE_SRVLOC */
+
 #ifdef HAVE_LDAP
 #include <atalk/ldapconfig.h>
 #endif
index ca1a040d338a4f260c34728a00764e331874da93..95c31c851c16a11dbbcbbb2bdb9036358c5ee4c5 100644 (file)
 
 #include <stdio.h>
 #include <stdlib.h>
-
-/* STDC check */
-#if STDC_HEADERS
 #include <string.h>
-#else /* STDC_HEADERS */
-#ifndef HAVE_STRCHR
-#define strchr index
-#define strrchr index
-#endif /* HAVE_STRCHR */
-char *strchr (), *strrchr ();
-#ifndef HAVE_MEMCPY
-#define memcpy(d,s,n) bcopy ((s), (d), (n))
-#define memmove(d,s,n) bcopy ((s), (d), (n))
-#endif /* ! HAVE_MEMCPY */
-#endif /* STDC_HEADERS */
-
 #include <ctype.h>
-#ifdef HAVE_UNISTD_H
 #include <unistd.h>
-#endif /* HAVE_UNISTD_H */
 #include <sys/param.h>
 #include <sys/socket.h>
 #include <atalk/logger.h>
 
 #include <netinet/in.h>
 #include <arpa/inet.h>
+
 #ifdef HAVE_NETDB_H
 #include <netdb.h>
 #endif /* HAVE_NETDB_H */
 
+#ifdef ADMIN_GRP
+#include <grp.h>
+#include <sys/types.h>
+#endif /* ADMIN_GRP */
+
 #include <atalk/paths.h>
 #include <atalk/util.h>
+#include <atalk/compat.h>
+
 #include "globals.h"
 #include "status.h"
 #include "auth.h"
 #include "dircache.h"
 
-#include <atalk/compat.h>
-
-#ifdef ADMIN_GRP
-#include <grp.h>
-#include <sys/types.h>
-#endif /* ADMIN_GRP */
-
 #ifndef MIN
 #define MIN(a, b)  ((a) < (b) ? (a) : (b))
 #endif /* MIN */
index 819e04b8dba4523a0bf8657377e64e953fda00bc..0faeef9494b92619dd6cbcf2f905d6ce88a12dd8 100644 (file)
@@ -46,6 +46,7 @@
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/util.h>
 #include <atalk/bstradd.h>
+#include <atalk/unicode.h>
 
 #include "desktop.h"
 #include "directory.h"
@@ -707,6 +708,8 @@ static int catsearch_db(struct vol *vol,
        int result = AFP_OK;
     struct path path;
        char *rrbuf = rbuf;
+    char buffer[MAXPATHLEN +2];
+    uint16_t flags = CONV_TOLOWER;
 
     LOG(log_debug, logtype_afpd, "catsearch_db(req pos: %u): {pos: %u, name: %s}",
         *pos, cur_pos, uname);
@@ -717,8 +720,23 @@ static int catsearch_db(struct vol *vol,
        }
 
     if (cur_pos == 0 || *pos == 0) {
+        if (convert_charset(vol->v_volcharset,
+                            vol->v_volcharset,
+                            vol->v_maccharset,
+                            uname,
+                            strlen(uname),
+                            buffer,
+                            MAXPATHLEN,
+                            &flags) == (size_t)-1) {
+            LOG(log_error, logtype_cnid, "catsearch_db: conversion error");
+            result = AFPERR_MISC;
+            goto catsearch_end;
+        }
+
+        LOG(log_debug, logtype_afpd, "catsearch_db: %s", buffer);
+
         if ((num_matches = cnid_find(vol->v_cdb,
-                                     uname,
+                                     buffer,
                                      strlen(uname),
                                      resbuf,
                                      sizeof(resbuf))) == -1) {
@@ -754,8 +772,9 @@ static int catsearch_db(struct vol *vol,
             switch (errno) {
             case EACCES:
             case ELOOP:
-            case ENOENT:
                 goto next;
+            case ENOENT:
+                
             default:
                 result = AFPERR_MISC;
                 goto catsearch_end;
@@ -1012,7 +1031,9 @@ static int catsearch_afp(AFPObj *obj _U_, char *ibuf, size_t ibuflen,
     
     /* Call search */
     *rbuflen = 24;
-    if ((c1.rbitmap & (1 << FILPBIT_PDINFO)) && (strcmp(vol->v_cnidscheme, "dbd") == 0))
+    if ((c1.rbitmap & (1 << FILPBIT_PDINFO))
+        && (strcmp(vol->v_cnidscheme, "dbd") == 0)
+        && (vol->v_flags & AFPVOL_SEARCHDB))
         /* we've got a name and it's a dbd volume, so search CNID database */
         ret = catsearch_db(vol, vol->v_root, uname, rmatches, &catpos[0], rbuf+24, &nrecs, &rsize, ext);
     else
index 56d61903aec12f44d2b7a0a521abfa7d57aa3ec1..4131370460fa6d3839051825d0da2676a71d8c20 100644 (file)
@@ -661,14 +661,14 @@ server_signature_auto:
                 options->sigconffile, strerror(errno));
             goto server_signature_random;
         }
-    } else {                                                          /* conf file don't exist */
+    } else { /* conf file don't exist */
         if (( fd = creat(options->sigconffile, 0644 )) < 0 ) {
-            LOG(log_error, logtype_atalkd, "ERROR: Cannot create %s (%s). Using one-time signature.",
+            LOG(log_error, logtype_atalkd, "Cannot create %s (%s). Using one-time signature.",
                 options->sigconffile, strerror(errno));
             goto server_signature_random;
         }
         if (( fp = fdopen( fd, "w" )) == NULL ) {
-            LOG(log_error, logtype_atalkd, "ERROR: Cannot fdopen %s (%s). Using one-time signature.",
+            LOG(log_error, logtype_atalkd, "Cannot fdopen %s (%s). Using one-time signature.",
                 options->sigconffile, strerror(errno));
             close(fd);
             goto server_signature_random;
@@ -680,41 +680,9 @@ server_signature_auto:
 server_signature_random:
     
     /* generate signature from random number */
-    if ((randomp = fopen("/dev/urandom", "r")) != NULL) {   /* generate from /dev/urandom */
-        for (i=0 ; i<16 ; i++) {
-            (options->signature)[i] = fgetc(randomp);
-        }
-        LOG(log_note, logtype_afpd,
-            "generate %s's signature %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X from /dev/urandom",
-            server_tmp,
-            (options->signature)[ 0], (options->signature)[ 1],
-            (options->signature)[ 2], (options->signature)[ 3],
-            (options->signature)[ 4], (options->signature)[ 5],
-            (options->signature)[ 6], (options->signature)[ 7],
-            (options->signature)[ 8], (options->signature)[ 9],
-            (options->signature)[10], (options->signature)[11],
-            (options->signature)[12], (options->signature)[13],
-            (options->signature)[14], (options->signature)[15]);
-        
-    } else {                                   /* genarate from random() because cannot open /dev/urandom */
-        srandom((unsigned int)time(NULL) + (unsigned int)options + (unsigned int)server_tmp);
-        for (i=0 ; i<16 ; i++) {
-            (options->signature)[i] = random() & 0xFF;
-        }
-        LOG(log_note, logtype_afpd,
-            "generate %s's signature %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X from random()",
-            server_tmp,
-            (options->signature)[ 0], (options->signature)[ 1],
-            (options->signature)[ 2], (options->signature)[ 3],
-            (options->signature)[ 4], (options->signature)[ 5],
-            (options->signature)[ 6], (options->signature)[ 7],
-            (options->signature)[ 8], (options->signature)[ 9],
-            (options->signature)[10], (options->signature)[11],
-            (options->signature)[12], (options->signature)[13],
-            (options->signature)[14], (options->signature)[15]);
-    }
+    randombytes(options->signature, 16);
 
-    if (fp && header) {                                     /* conf file is created or size=0 */
+    if (fp && header) { /* conf file is created or size=0 */
         fprintf(fp, "# DON'T TOUCH NOR COPY THOUGHTLESSLY!\n");
         fprintf(fp, "# This file is auto-generated by afpd.\n");
         fprintf(fp, "# \n");
index 251e2031bfeee9931f0917eb1efc0f3369937a96..9e9b904b53abb47f673cb141a938611349b27019 100644 (file)
@@ -36,8 +36,6 @@ char *strchr (), *strrchr ();
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#include <uuid/uuid.h>
-
 #include <atalk/asp.h>
 #include <atalk/dsi.h>
 #include <atalk/adouble.h>
@@ -46,7 +44,8 @@ char *strchr (), *strrchr ();
 #include <atalk/volinfo.h>
 #include <atalk/logger.h>
 #include <atalk/vfs.h>
-#include <atalk/ea.h>
+#include <atalk/uuid.h>
+
 #ifdef CNID_DB
 #include <atalk/cnid.h>
 #endif /* CNID_DB*/
@@ -499,6 +498,8 @@ static void volset(struct vol_option *options, struct vol_option *save,
                 options[VOLOPT_FLAGS].i_value &= ~AFPVOL_CACHE;
             else if (strcasecmp(p, "tm") == 0)
                 options[VOLOPT_FLAGS].i_value |= AFPVOL_TM;
+            else if (strcasecmp(p, "searchdb") == 0)
+                options[VOLOPT_FLAGS].i_value |= AFPVOL_SEARCHDB;
 /* Found this in branch dir-rewrite, maybe we want to use it sometimes */
 #if 0
             else if (strcasecmp(p, "cdrom") == 0)
@@ -728,7 +729,8 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
     volume->v_vid = htons(volume->v_vid);
 #ifdef HAVE_ACLS
     if (check_vol_acl_support(volume))
-        volume->v_flags |= AFPVOL_ACLS;
+        volume->v_flags |= AFPVOL_ACLS
+;
 #endif
 
     /* handle options */
@@ -1931,7 +1933,7 @@ static int volume_openDB(struct vol *volume)
     }
 #endif
 
-    volume->v_cdb = cnid_open(volume->v_dbpath ? volume->v_dbpath : volume->v_path,
+    volume->v_cdb = cnid_open(volume->v_path,
                               volume->v_umask,
                               volume->v_cnidscheme,
                               flags,
@@ -2730,14 +2732,14 @@ char *get_uuid(const AFPObj *obj, const char *volname)
     }                    
     
     /* generate uuid and write to file */
-    uuid_t id;
-    uuid_generate(id);
-    uuid_unparse(id, uuid);
-    for (int i=0; uuid[i]; i++)
-        uuid[i] = toupper(uuid[i]);
-    LOG(log_debug, logtype_afpd, "get_uuid('%s'): generated UUID '%s'", volname, uuid);
-
-    fprintf(fp, "\"%s\"\t%36s\n", volname, uuid);
+    atalk_uuid_t id;
+    const char *cp;
+    randombytes((void *)id, 16);
+    cp = uuid_bin2string(id);
+
+    LOG(log_debug, logtype_afpd, "get_uuid('%s'): generated UUID '%s'", volname, cp);
+
+    fprintf(fp, "\"%s\"\t%36s\n", volname, cp);
     fclose(fp);
     
     return strdup(uuid);
index 6d847a788d24152c911804b38b8067a6f7eabbae..cb390f321bb886bcdb04ec81c901ad99bb8e719e 100644 (file)
@@ -1,6 +1,4 @@
 /* 
-   $Id: cmd_dbd.c,v 1.26 2010-04-20 16:46:20 hat001 Exp $
-
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
    
    This program is free software; you can redistribute it and/or modify
@@ -84,6 +82,7 @@
 
 int nocniddb = 0;               /* Dont open CNID database, only scan filesystem */
 volatile sig_atomic_t alarmed;
+struct volinfo volinfo;
 
 static DBD *dbd;
 static int verbose;             /* Logging flag */
@@ -101,7 +100,7 @@ static struct db_param db_param = {
     -1,
     -1
 };
-static char dbpath[PATH_MAX];   /* Path to the dbd database */
+static char dbpath[MAXPATHLEN+1];   /* Path to the dbd database */
 
 /* 
    Provide some logging
@@ -281,7 +280,6 @@ int main(int argc, char **argv)
     int dump=0, scan=0, rebuild=0, prep_upgrade=0, rebuildindexes=0, dumpindexes=0, force=0;
     dbd_flags_t flags = 0;
     char *volpath;
-    struct volinfo volinfo;
     int cdir;
 
     if (geteuid() != 0) {
@@ -382,12 +380,25 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);        
     }
 
+    /* Enuser dbpath is there, create if necessary */
+    struct stat st;
+    if (stat(volinfo.v_dbpath, &st) != 0) {
+        if (errno != ENOENT) {
+            dbd_log( LOGSTD, "Can't stat dbpath \"%s\": %s", volinfo.v_dbpath, strerror(errno));
+            exit(EXIT_FAILURE);        
+        }
+        if ((mkdir(volinfo.v_dbpath, 0755)) != 0) {
+            dbd_log( LOGSTD, "Can't create dbpath \"%s\": %s", dbpath, strerror(errno));
+            exit(EXIT_FAILURE);
+        }        
+    }
+
     /* Put "/.AppleDB" at end of volpath, get path from volinfo file */
-    if ( (strlen(volinfo.v_dbpath) + strlen("/.AppleDB")) > (PATH_MAX - 1) ) {
+    if ( (strlen(volinfo.v_dbpath) + strlen("/.AppleDB")) > MAXPATHLEN ) {
         dbd_log( LOGSTD, "Volume pathname too long");
         exit(EXIT_FAILURE);        
     }
-    strncpy(dbpath, volinfo.v_dbpath, PATH_MAX - 9 - 1);
+    strncpy(dbpath, volinfo.v_dbpath, MAXPATHLEN - strlen("/.AppleDB"));
     strcat(dbpath, "/.AppleDB");
 
     /* Check or create dbpath */
@@ -422,9 +433,13 @@ int main(int argc, char **argv)
     /* Check if -f is requested and wipe db if yes */
     if ((flags & DBD_FLAGS_FORCE) && rebuild && (volinfo.v_flags & AFPVOL_CACHE)) {
         char cmd[8 + MAXPATHLEN];
-        snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", dbpath);
+        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.");
     }
 
@@ -447,11 +462,6 @@ int main(int argc, char **argv)
             dbif_close(dbd);
             goto exit_failure;
         }
-
-        if (dbd_stamp(dbd) < 0) {
-            dbif_close(dbd);
-            goto exit_failure;
-        }
     }
 
     /* Now execute given command scan|rebuild|dump */
index a1d51b67dcdd77dddf648997f7cdefef2faebd19..c7449b5067f5d5f26834f2ef46aaaf5c2bd0ebf6 100644 (file)
@@ -25,7 +25,7 @@ typedef unsigned int dbd_flags_t;
 
 extern int nocniddb; /* Dont open CNID database, only scan filesystem */
 extern volatile sig_atomic_t alarmed;
-extern struct volinfo *volinfo;
+// extern struct volinfo *volinfo;
 extern char cwdbuf[MAXPATHLEN+1];
 
 extern void dbd_log(enum logtype lt, char *fmt, ...);
index 45d67ae1bd5b2c5dcfc09ce618fa3f95fb768372..fcc43e46dd8c3fe47ec43c62eb599d8dbc4663f8 100644 (file)
@@ -1073,7 +1073,12 @@ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
                     dbd_log(LOGSTD, "Orphaned CNID in database: %u", dbd_cnid);
                     if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
                         rqst.cnid = htonl(dbd_cnid);
-                        ret = dbd_delete(dbd, &rqst, &rply, DBIF_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;
+                        }
+                        
                         dbif_txn_close(dbd, ret);
                         deleted++;
                     }
@@ -1089,10 +1094,14 @@ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
 
         if (dbd_cnid < rebuild_cnid) {
             /* CNID is orphaned -> delete */
-            dbd_log(LOGSTD, "Orphaned CNID in database: %u.", dbd_cnid);
+            dbd_log(LOGSTD, "One orphaned CNID in database: %u.", dbd_cnid);
             if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
                 rqst.cnid = htonl(dbd_cnid);
-                ret = dbd_delete(dbd, &rqst, &rply, DBIF_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;
+                }
                 dbif_txn_close(dbd, ret);
                 deleted++;
             }
@@ -1108,7 +1117,7 @@ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
             dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
             goto cleanup;
         }
-    }
+    } /* while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) */
 
 cleanup:
     dbif_idwalk(dbd, NULL, 1); /* Close cursor */
index 043e6957d9eb07e8ba5bf173da0c8f2f1a3be6e9..85ea7a4fb21b88fd71b19a05a4376fe49c142b7f 100644 (file)
@@ -89,8 +89,8 @@
 #include <atalk/logger.h>
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/paths.h>
+#include <atalk/volinfo.h>
 
-#include "db_param.h"
 #include "usockfd.h"
 
 #define DBHOME        ".AppleDB"
@@ -108,7 +108,7 @@ static volatile sig_atomic_t sigchild = 0;
 #define DEFAULTPORT  "4700"
 
 struct server {
-    char  *name;
+    struct volinfo *volinfo;
     pid_t pid;
     time_t tm;                    /* When respawned last */
     int count;                    /* Times respawned in the last TESTTIME secondes */
@@ -139,11 +139,11 @@ static void sigterm_handler(int sig)
     daemon_exit(0);
 }
 
-static struct server *test_usockfn(char *dir)
+static struct server *test_usockfn(struct volinfo *volinfo)
 {
     int i;
     for (i = 0; i < MAXVOLS; i++) {
-        if (srv[i].name && !strcmp(srv[i].name, dir)) {
+        if ((srv[i].volinfo) && (strcmp(srv[i].volinfo->v_path, volinfo->v_path) == 0)) {
             return &srv[i];
         }
     }
@@ -204,7 +204,7 @@ static int send_cred(int socket, int fd)
 }
 
 /* -------------------- */
-static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
+static int maybe_start_dbd(char *dbdpn, struct volinfo *volinfo)
 {
     pid_t pid;
     struct server *up;
@@ -213,11 +213,11 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
     time_t t;
     char buf1[8];
     char buf2[8];
+    char *volpath = volinfo->v_path;
 
-    LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: dbdir: '%s', UNIX socket file: '%s'", 
-        dbdir, usockfn);
+    LOG(log_debug, logtype_cnid, "maybe_start_dbd: Volume: \"%s\"", volpath);
 
-    up = test_usockfn(dbdir);
+    up = test_usockfn(volinfo);
     if (up && up->pid) {
         /* we already have a process, send our fd */
         if (send_cred(up->control_fd, rqstfd) < 0) {
@@ -227,17 +227,18 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
         return 0;
     }
 
-    LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: no cnid_dbd for that volume yet. Starting one ...");
+    LOG(log_maxdebug, logtype_cnid, "maybe_start_dbd: no cnid_dbd for that volume yet");
 
     time(&t);
     if (!up) {
         /* find an empty slot */
         for (i = 0; i < MAXVOLS; i++) {
-            if ( !srv[i].name ) {
+            if (srv[i].volinfo == NULL) {
                 up = &srv[i];
+                up->volinfo = volinfo;
+                retainvolinfo(volinfo);
                 up->tm = t;
                 up->count = 0;
-                up->name = strdup(dbdir);
                 break;
             }
         }
@@ -245,8 +246,7 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
             LOG(log_error, logtype_cnid, "no free slot for cnid_dbd child. Configured maximum: %d. Do you have so many volumes?", MAXVOLS);
             return -1;
         }
-    }
-    else {
+    } else {
         /* we have a slot but no process, check for respawn too fast */
         if ( (t < (up->tm + TESTTIME)) /* We're in the respawn time window */
              &&
@@ -306,11 +306,11 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
             /* there's a pb with the db inform child
              * it will run recover, delete the db whatever
              */
-            LOG(log_error, logtype_cnid, "try with -d %s", up->name);
-            ret = execlp(dbdpn, dbdpn, "-d", dbdir, buf1, buf2, logconfig, NULL);
+            LOG(log_error, logtype_cnid, "try with -d %s", up->volinfo->v_path);
+            ret = execlp(dbdpn, dbdpn, "-d", volpath, buf1, buf2, logconfig, NULL);
         }
         else {
-            ret = execlp(dbdpn, dbdpn, dbdir, buf1, buf2, logconfig, NULL);
+            ret = execlp(dbdpn, dbdpn, volpath, buf1, buf2, logconfig, NULL);
         }
         /* Yikes! We're still here, so exec failed... */
         LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno));
@@ -326,12 +326,12 @@ static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
 }
 
 /* ------------------ */
-static int set_dbdir(char *dbdir, int len)
+static int set_dbdir(char *dbdir)
 {
+    int len;
     struct stat st;
 
-    if (!len)
-        return -1;
+    len = strlen(dbdir);
 
     if (stat(dbdir, &st) < 0 && mkdir(dbdir, 0755) < 0) {
         LOG(log_error, logtype_cnid, "set_dbdir: mkdir failed for %s", dbdir);
@@ -460,14 +460,13 @@ static void set_signal(void)
 /* ------------------ */
 int main(int argc, char *argv[])
 {
-    char  dbdir[MAXPATHLEN + 1];
+    char  volpath[MAXPATHLEN + 1];
     int   len, actual_len;
     pid_t pid;
     int   status;
     char  *dbdpn = _PATH_CNID_DBD;
     char  *host = DEFAULTHOST;
     char  *port = DEFAULTPORT;
-    struct db_param *dbp;
     int    i;
     int    cc;
     uid_t  uid = 0;
@@ -478,6 +477,7 @@ int main(int argc, char *argv[])
     char   *loglevel = NULL;
     char   *logfile  = NULL;
     sigset_t set;
+    struct volinfo *volinfo;
 
     set_processname("cnid_metad");
 
@@ -538,7 +538,7 @@ int main(int argc, char *argv[])
     }
 
     /* Check PID lockfile and become a daemon */
-    switch(server_lock("cnid_metad", _PATH_CNID_METAD_LOCK, 0)) {
+    switch(server_lock("cnid_metad", _PATH_CNID_METAD_LOCK, debug)) {
     case -1: /* error */
         daemon_exit(EXITERR_SYS);
     case 0: /* child */
@@ -620,7 +620,7 @@ int main(int argc, char *argv[])
             goto loop_end;
         }
 
-        actual_len = readt(rqstfd, dbdir, len, 1, 5);
+        actual_len = readt(rqstfd, volpath, len, 1, 5);
         if (actual_len < 0) {
             LOG(log_severe, logtype_cnid, "Read(2) error : %s", strerror(errno));
             goto loop_end;
@@ -629,17 +629,21 @@ int main(int argc, char *argv[])
             LOG(log_error, logtype_cnid, "error/short read (dir): %s", strerror(errno));
             goto loop_end;
         }
-        dbdir[len] = '\0';
+        volpath[len] = '\0';
 
-        if (set_dbdir(dbdir, len) < 0) {
+        /* Load .volinfo file */
+        if ((volinfo = allocvolinfo(volpath)) == NULL) {
+            LOG(log_severe, logtype_cnid, "allocvolinfo: %s", strerror(errno));
             goto loop_end;
         }
 
-        if ((dbp = db_param_read(dbdir, METAD)) == NULL) {
-            LOG(log_error, logtype_cnid, "Error reading config file");
+        if (set_dbdir(volinfo->v_dbpath) < 0) {
             goto loop_end;
         }
-        maybe_start_dbd(dbdpn, dbdir, dbp->usock_file);
+
+        maybe_start_dbd(dbdpn, volinfo);
+
+        (void)closevolinfo(volinfo);
 
     loop_end:
         close(rqstfd);
index eda624aec6edc645542704e0856772a579835d60..e31e782759830629536f25a8d95dcffc7517b57c 100644 (file)
@@ -102,7 +102,7 @@ static int parse_int(char *val)
    buffer overflow) nor elegant, we need to add support for whitespace in
    filenames as well. */
 
-struct db_param *db_param_read(char *dir, enum identity id)
+struct db_param *db_param_read(char *dir)
 {
     FILE *fp;
     static char key[MAXKEYLEN + 1];
@@ -149,39 +149,32 @@ struct db_param *db_param_read(char *dir, enum identity id)
                 LOG(log_info, logtype_cnid, "db_param: setting UNIX domain socket filename to %s", params.usock_file);
         }
 
-        /* Config for cnid_metad only */
-        if ( id == METAD ) {
-            /* Currently empty */
+        if (! strcmp(key, "fd_table_size")) {
+            params.fd_table_size = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting max number of concurrent afpd connections per volume (fd_table_size) to %d", params.fd_table_size);
+        } else if (! strcmp(key, "logfile_autoremove")) {
+            params.logfile_autoremove = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting logfile_autoremove to %d", params.logfile_autoremove);
+        } else if (! strcmp(key, "cachesize")) {
+            params.cachesize = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting cachesize to %d", params.cachesize);
+        } else if (! strcmp(key, "maxlocks")) {
+            params.maxlocks = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting maxlocks to %d", params.maxlocks);
+        } else if (! strcmp(key, "maxlockobjs")) {
+            params.maxlockobjs = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting maxlockobjs to %d", params.maxlockobjs);
+        } else if (! strcmp(key, "flush_frequency")) {
+            params.flush_frequency = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting flush_frequency to %d", params.flush_frequency);
+        } else if (! strcmp(key, "flush_interval")) {
+            params.flush_interval = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting flush_interval to %d", params.flush_interval);
+        } else if (! strcmp(key, "idle_timeout")) {
+            params.idle_timeout = parse_int(val);
+            LOG(log_info, logtype_cnid, "db_param: setting idle timeout to %d", params.idle_timeout);
         }
 
-        /* Config for dbd only */
-        else if (id == CNID_DBD ) {
-            if (! strcmp(key, "fd_table_size")) {
-                params.fd_table_size = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting max number of concurrent afpd connections per volume (fd_table_size) to %d", params.fd_table_size);
-            } else if (! strcmp(key, "logfile_autoremove")) {
-                params.logfile_autoremove = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting logfile_autoremove to %d", params.logfile_autoremove);
-            } else if (! strcmp(key, "cachesize")) {
-                params.cachesize = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting cachesize to %d", params.cachesize);
-            } else if (! strcmp(key, "maxlocks")) {
-                params.maxlocks = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting maxlocks to %d", params.maxlocks);
-            } else if (! strcmp(key, "maxlockobjs")) {
-                params.maxlockobjs = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting maxlockobjs to %d", params.maxlockobjs);
-            } else if (! strcmp(key, "flush_frequency")) {
-                params.flush_frequency = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting flush_frequency to %d", params.flush_frequency);
-            } else if (! strcmp(key, "flush_interval")) {
-                params.flush_interval = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting flush_interval to %d", params.flush_interval);
-            } else if (! strcmp(key, "idle_timeout")) {
-                params.idle_timeout = parse_int(val);
-                LOG(log_info, logtype_cnid, "db_param: setting idle timeout to %d", params.idle_timeout);
-            }
-        }
         if (parse_err)
             break;
     }
index 57ade7c5e425057f6f26c7e57269ed0010ba7814..67ec62e4e18c8fc6f40c5f02c8e9f5aa72948621 100644 (file)
 #include <sys/param.h>
 #include <sys/cdefs.h>
 
-enum identity {
-    METAD,
-    CNID_DBD
-};
-
 struct db_param {
     char *dir;
     int logfile_autoremove;
@@ -29,8 +24,7 @@ struct db_param {
     int max_vols;
 };
 
-extern struct db_param *      db_param_read  (char *, enum identity);
-
+extern struct db_param *db_param_read  (char *);
 
 #endif /* CNID_DBD_DB_PARAM_H */
 
index dea8327810c81c776601e9d4134eb97982a93dc1..b4f7e5d4a0013adfa8f50be1825d0e9ed7f664bc 100644 (file)
@@ -12,7 +12,6 @@
 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);
 
-extern int dbd_stamp(DBD *dbd);
 extern int dbd_add(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int nolookup);
 extern int dbd_lookup(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *, int roflag);
 extern int dbd_get(DBD *dbd, struct cnid_dbd_rqst *, struct cnid_dbd_rply *);
index ce7bcf1b0bd2de14fce5f9c3c1f6a053108b3ef3..6a818a3b325063f27fe37a0a412d6081bf6bb0b8 100644 (file)
@@ -131,44 +131,6 @@ int get_cnid(DBD *dbd, struct cnid_dbd_rply *rply)
     return 0;
 }
 
-/* --------------- 
-*/
-int dbd_stamp(DBD *dbd)
-{
-    DBT rootinfo_key, rootinfo_data;
-    cnid_t hint;
-    char buf[ROOTINFO_DATALEN];
-    char stamp[CNID_DEV_LEN];
-
-    memset(&rootinfo_key, 0, sizeof(rootinfo_key));
-    memset(&rootinfo_data, 0, sizeof(rootinfo_data));
-    rootinfo_key.data = ROOTINFO_KEY;
-    rootinfo_key.size = ROOTINFO_KEYLEN;
-
-    switch (dbif_get(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0)) {
-    case 0:
-        hint = htonl(CNID_START);
-        memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
-        rootinfo_data.data = buf;
-        rootinfo_data.size = ROOTINFO_DATALEN;
-        if (dbif_stamp(dbd, stamp, CNID_DEV_LEN) < 0) {
-            return -1;
-        }
-        memcpy((char *)rootinfo_data.data + CNID_TYPE_OFS, &hint, sizeof(hint));
-        memcpy((char *)rootinfo_data.data + CNID_DEV_OFS, stamp, sizeof(stamp));
-        if (dbif_put(dbd, DBIF_CNID, &rootinfo_key, &rootinfo_data, 0) < 0) {
-            return -1;
-        }
-        return 0;
-    
-    case 1: /* we already have one */
-        return 0;
-    default:
-        return -1;
-    }
-    return -1;
-}
-
 /* ------------------------ */
 /* We need a nolookup version for `dbd` */
 int dbd_add(DBD *dbd, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply, int nolookup)
index b7fc936aa893c2df3cfaa4b4cc5020882cf0f01a..ea75c4aba67799356636162a70c5c0a4194c63a4 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * $Id: dbd_getstamp.c,v 1.4 2009-05-06 11:54:24 franklahm Exp $
  *
index 4b52376a879f4548c7bcec2ba99051b8cd525d04..dd6439aae0f28d42dd7b08217a64beffe33df4b9 100644 (file)
@@ -199,6 +199,8 @@ exit:
     return ret;
 }
 
+#include <atalk/util.h>
+
 /* --------------- */
 int dbif_stamp(DBD *dbd, void *buffer, int size)
 {
@@ -224,6 +226,9 @@ int dbif_stamp(DBD *dbd, void *buffer, int size)
         LOG(log_error, logtype_cnid, "error stating database %s: %s", dbd->db_table[DBIF_CNID].name, db_strerror(errno));
         return -1;
     }
+
+    LOG(log_maxdebug, logtype_cnid,"stamp: %s", asctime(localtime(&st.st_ctime)));
+
     memset(buffer, 0, size);
     memcpy(buffer, &st.st_ctime, sizeof(st.st_ctime));
 
@@ -546,9 +551,13 @@ int dbif_open(DBD *dbd, struct db_param *dbp, int reindex)
 
     if (reindex)
         LOG(log_info, logtype_cnid, "Reindexing name index...");
-    int version = dbif_getversion(dbd);
-    if (version == -1)
-        return -1;
+
+    int version = CNID_VERSION;
+    if (dbd->db_envhome) {
+        if ((version = dbif_getversion(dbd)) == -1)
+            return -1;
+    }
+
     if ((ret = dbd->db_table[0].db->associate(dbd->db_table[0].db, 
                                               dbd->db_txn,
                                               dbd->db_table[DBIF_IDX_NAME].db, 
@@ -563,7 +572,7 @@ int dbif_open(DBD *dbd, struct db_param *dbp, int reindex)
     if (reindex)
         LOG(log_info, logtype_cnid, "... done.");
 
-    if ((ret = dbif_upgrade(dbd)) != 0) {
+    if ((dbd->db_envhome) && ((ret = dbif_upgrade(dbd)) != 0)) {
         LOG(log_error, logtype_cnid, "Error upgrading CNID database to version %d", CNID_VERSION);
         return -1;
     }
@@ -787,8 +796,10 @@ int dbif_del(DBD *dbd, const int dbi, DBT *key, u_int32_t flags)
                                      key,
                                      flags);
     
-    if (ret == DB_NOTFOUND || ret == DB_SECONDARY_BAD)
+    if (ret == DB_NOTFOUND) {
+        LOG(log_info, logtype_cnid, "key not found");
         return 0;
+    }
     if (ret) {
         LOG(log_error, logtype_cnid, "error deleting key/value from %s: %s",
             dbd->db_table[dbi].name, db_strerror(ret));
@@ -797,8 +808,51 @@ int dbif_del(DBD *dbd, const int dbi, DBT *key, u_int32_t flags)
         return 1;
 }
 
+/*!
+ * Inititialize rootinfo key (which has CNID 0 as key)
+ *
+ * This also "stamps" the database, which means storing st.st_ctime of the
+ * "cnid2.db" file in the rootinfo data at the DEV offset
+ *
+ * @param dbd      (rw) database handle
+ * @param version  (r)  database version number
+ *
+ * @returns -1 on error, 0 on success
+ */
+static int dbif_init_rootinfo(DBD *dbd, int version)
+{
+    DBT key, data;
+    uint32_t v;
+    char buf[ROOTINFO_DATALEN];
+
+    LOG(log_debug, logtype_cnid, "Setting CNID database version to %u", version);
+
+    v = version;
+    v = htonl(v);
+
+    memset(&key, 0, sizeof(key));
+    memset(&data, 0, sizeof(data));
+    key.data = ROOTINFO_KEY;
+    key.size = ROOTINFO_KEYLEN;
+    data.data = buf;
+    data.size = ROOTINFO_DATALEN;
+
+    memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
+    memcpy(buf + CNID_DID_OFS, &v, sizeof(v));
+    if (dbif_stamp(dbd, buf + CNID_DEV_OFS, CNID_DEV_LEN) < 0)
+        return -1;
+
+    if (dbif_put(dbd, DBIF_CNID, &key, &data, 0) < 0)
+        return -1;
+
+    return 0;
+}
+
 /*!
  * Initialize or return CNID database version number
+ *
+ * Calls dbif_init_rootinfo if the rootinfo key does not exist yet
+ *
  * @returns -1 on error, version number otherwise
  */
 int dbif_getversion(DBD *dbd)
@@ -820,7 +874,7 @@ int dbif_getversion(DBD *dbd)
         ret = version;
         break;
     case 0: /* not found */
-        if (dbif_setversion(dbd, CNID_VERSION) != 0)
+        if (dbif_init_rootinfo(dbd, CNID_VERSION) != 0)
             return -1;
         ret = CNID_VERSION;
         break;
@@ -831,7 +885,9 @@ int dbif_getversion(DBD *dbd)
 }
 
 /*!
- * Return CNID database version number
+ * Set CNID database version number
+ *
+ * Initializes rootinfo key as neccessary, as does dbif_getversion
  * @returns -1 on error, version number otherwise
  */
 int dbif_setversion(DBD *dbd, int version)
@@ -839,7 +895,6 @@ int dbif_setversion(DBD *dbd, int version)
     int ret;
     DBT key, data;
     uint32_t v;
-    char buf[ROOTINFO_DATALEN];
 
     LOG(log_debug, logtype_cnid, "Setting CNID database version to %u", version);
 
@@ -854,8 +909,12 @@ int dbif_setversion(DBD *dbd, int version)
     if ((ret = dbif_get(dbd, DBIF_CNID, &key, &data, 0)) == -1)
         return -1;
     if (ret == 0) {
-        memcpy(buf, ROOTINFO_DATA, ROOTINFO_DATALEN);
-        data.data = buf;
+        /* No rootinfo key yet, init it */
+        if (dbif_init_rootinfo(dbd, CNID_VERSION) != 0)
+            return -1;
+        /* Now try again */
+        if (dbif_get(dbd, DBIF_CNID, &key, &data, 0) == -1)
+            return -1;
     }
     memcpy((char *)data.data + CNID_DID_OFS, &v, sizeof(v));
     data.size = ROOTINFO_DATALEN;
@@ -1065,7 +1124,7 @@ int dbif_copy_rootinfokey(DBD *srcdbd, DBD *destdbd)
 int dbif_dump(DBD *dbd, int dumpindexes)
 {
     int rc;
-    uint32_t max = 0, count = 0, cnid, type, did, lastid;
+    uint32_t max = 0, count = 0, cnid, type, did, lastid, version;
     uint64_t dev, ino;
     time_t stamp;
     DBC *cur;
@@ -1092,11 +1151,15 @@ int dbif_dump(DBD *dbd, int dumpindexes)
 
         /* Rootinfo node ? */
         if (cnid == 0) {
-            memcpy(&stamp, (char *)data.data + 4, sizeof(time_t));
-            memcpy(&lastid, (char *)data.data + 20, sizeof(cnid_t));
+            memcpy(&stamp, (char *)data.data + CNID_DEV_OFS, sizeof(time_t));
+            memcpy(&lastid, (char *)data.data + CNID_TYPE_OFS, CNID_TYPE_LEN);
             lastid = ntohl(lastid);
+            memcpy(&version, (char *)data.data + CNID_DID_OFS, CNID_DID_LEN);
+            version = ntohl(version);
+
             strftime(timebuf, sizeof(timebuf), "%b %d %Y %H:%M:%S", localtime(&stamp));
-            printf("dbd stamp: 0x%08x (%s), next free CNID: %u\n", (unsigned int)stamp, timebuf, lastid + 1);
+            printf("CNID db version: %u, dbd stamp: 0x%08x (%s), next free CNID: %u\n",
+                   version, (unsigned int)stamp, timebuf, lastid + 1);
         } else {
             /* dev */
             memcpy(&dev, (char *)data.data + CNID_DEV_OFS, 8);
index 91027157292ea7dea5d85373b1c948cf95959d37..48b1d5075f34ccbea2a2153fd68770a0f59e92c9 100644 (file)
@@ -32,6 +32,7 @@
 #include <netatalk/endian.h>
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/logger.h>
+#include <atalk/volinfo.h>
 
 #include "db_param.h"
 #include "dbif.h"
  */
 #define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER)
 
-static DBD *dbd;
+/* Global */
+struct volinfo volinfo;
 
+static DBD *dbd;
 static int exit_sig = 0;
 
 static void sig_exit(int signo)
@@ -271,6 +274,7 @@ static int get_lock(void)
 
     if (fcntl(lockfd, F_SETLK, &lock) < 0) {
         if (errno == EACCES || errno == EAGAIN) {
+            LOG(log_error, logtype_cnid, "get_lock: locked");
             exit(0);
         } else {
             LOG(log_error, logtype_cnid, "main: fcntl F_WRLCK lockfile: %s", strerror(errno));
@@ -322,7 +326,7 @@ int main(int argc, char *argv[])
     struct db_param *dbp;
     int err = 0;
     int lockfd, ctrlfd, clntfd;
-    char *dir, *logconfig;
+    char *logconfig;
 
     set_processname("cnid_dbd");
 
@@ -332,26 +336,43 @@ int main(int argc, char *argv[])
         exit(1);
     }
 
-    dir = argv[1];
     ctrlfd = atoi(argv[2]);
     clntfd = atoi(argv[3]);
     logconfig = strdup(argv[4]);
     setuplog(logconfig);
 
-    switch_to_user(dir);
+    /* Load .volinfo file */
+    if (loadvolinfo(argv[1], &volinfo) == -1) {
+        LOG(log_error, logtype_cnid, "Cant load volinfo for \"%s\"", argv[1]);
+        exit(EXIT_FAILURE);
+    }
+    /* Put "/.AppleDB" at end of volpath, get path from volinfo file */
+    char dbpath[MAXPATHLEN+1];
+    if ((strlen(volinfo.v_dbpath) + strlen("/.AppleDB")) > MAXPATHLEN ) {
+        LOG(log_error, logtype_cnid, "CNID db pathname too long: \"%s\"", volinfo.v_dbpath);
+        exit(EXIT_FAILURE);
+    }
+    strncpy(dbpath, volinfo.v_dbpath, MAXPATHLEN - strlen("/.AppleDB"));
+    strcat(dbpath, "/.AppleDB");
+
+    if (vol_load_charsets(&volinfo) == -1) {
+        LOG(log_error, logtype_cnid, "Error loading charsets!");
+        exit(EXIT_FAILURE);
+    }
+    LOG(log_debug, logtype_cnid, "db dir: \"%s\"", dbpath);
+
+    switch_to_user(dbpath);
 
     /* Before we do anything else, check if there is an instance of cnid_dbd
        running already and silently exit if yes. */
     lockfd = get_lock();
 
-    LOG(log_info, logtype_cnid, "Startup, DB dir %s", dir);
-
     set_signal();
 
     /* SIGINT and SIGTERM are always off, unless we are in pselect */
     block_sigs_onoff(1);
 
-    if ((dbp = db_param_read(dir, CNID_DBD)) == NULL)
+    if ((dbp = db_param_read(dbpath)) == NULL)
         exit(1);
     LOG(log_maxdebug, logtype_cnid, "Finished parsing db_param config file");
 
@@ -368,12 +389,6 @@ int main(int argc, char *argv[])
     }
     LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
 
-    if (dbd_stamp(dbd) < 0) {
-        dbif_close(dbd);
-        exit(5);
-    }
-    LOG(log_maxdebug, logtype_cnid, "Finished checking database stamp");
-
     if (comm_init(dbp, ctrlfd, clntfd) < 0) {
         dbif_close(dbd);
         exit(3);
@@ -385,7 +400,7 @@ int main(int argc, char *argv[])
     if (dbif_close(dbd) < 0)
         err++;
 
-    if (dbif_env_remove(dir) < 0)
+    if (dbif_env_remove(dbpath) < 0)
         err++;
 
     free_lock(lockfd);
index eb90d85809b5f45af70e5736e7990e8d1beb26eb..159e62b8c6e14cb502bc0e59b0c78464b7439b33 100644 (file)
 #include <netatalk/endian.h>
 
 #include <string.h>
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif /* HAVE_SYS_TYPES_H */
+#include <inttypes.h>
 #include <sys/param.h>
 #include <sys/cdefs.h>
 #include <db.h>
 
+#include <atalk/unicode.h>
+#include <atalk/volinfo.h>
+#include <atalk/logger.h>
 #include <atalk/cnid_dbd_private.h>
 #include "pack.h"
 
+/* in main.c for `cnid_dbd` or cmd_dbd.c for `dbd` */
+extern struct volinfo volinfo;
+
 /* --------------- */
 /*
  *  This implementation is portable, but could probably be faster by using htonl
@@ -74,9 +78,24 @@ int devino(DB *dbp _U_, const DBT *pkey _U_,  const DBT *pdata, DBT *skey)
 /* --------------- */
 int idxname(DB *dbp _U_, const DBT *pkey _U_,  const DBT *pdata, DBT *skey)
 {
+    char buffer[MAXPATHLEN +2];
+    uint16_t flags = CONV_TOLOWER;
     memset(skey, 0, sizeof(DBT));
     skey->data = (char *)pdata->data + CNID_NAME_OFS;
-    skey->size = strlen((char *)skey->data) + 1;
+
+    if (convert_charset(volinfo.v_volcharset,
+                        volinfo.v_volcharset,
+                        volinfo.v_maccharset,
+                        (char *)pdata->data + CNID_NAME_OFS,
+                        strlen((char *)pdata->data + CNID_NAME_OFS),
+                        buffer,
+                        MAXPATHLEN,
+                        &flags) == (size_t)-1) {
+        LOG(log_error, logtype_cnid, "idxname: conversion error");
+    }
+
+    skey->data = buffer;
+    skey->size = strlen(skey->data);
     return (0);
 }
 
index 741077b1fcdbfeecf6c2d9dd0d571de5932b4c13..4e0e0b5570fe5503db28144505d2054757064474 100644 (file)
 #define CNID_INO_LEN             8
  
 #define CNID_DEVINO_OFS          CNID_LEN
-#define CNID_DEVINO_LEN          (CNID_DEV_LEN +CNID_INO_LEN)
+#define CNID_DEVINO_LEN          (CNID_DEV_LEN + CNID_INO_LEN)
  
-#define CNID_TYPE_OFS            (CNID_DEVINO_OFS +CNID_DEVINO_LEN)
+#define CNID_TYPE_OFS            (CNID_DEVINO_OFS + CNID_DEVINO_LEN)
 #define CNID_TYPE_LEN            4
  
-#define CNID_DID_OFS             (CNID_TYPE_OFS +CNID_TYPE_LEN)
+#define CNID_DID_OFS             (CNID_TYPE_OFS + CNID_TYPE_LEN)
 #define CNID_DID_LEN             CNID_LEN
  
 #define CNID_NAME_OFS            (CNID_DID_OFS + CNID_DID_LEN)
index 45c19c6cbf24295d0b00ccf472de3e9763a08711..9d61aaff71161c4c0b801f1226645d9e31a9bc61 100644 (file)
@@ -144,5 +144,5 @@ extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2);
 extern const char *getcwdpath(void);
 extern char *stripped_slashes_basename(char *p);
 extern int lchdir(const char *dir);
-
+extern void randombytes(void *buf, int n);
 #endif  /* _ATALK_UTIL_H */
index bd8c2a76e1bacadd7c3f75e736a9f299bdc7c94f..0f3a4024a6a36faedc4993783a731369e56237b3 100644 (file)
@@ -14,6 +14,9 @@ typedef struct {
 } vol_opt_name_t;
 
 struct volinfo {
+    int                 retaincount;
+    int                 malloced;
+
     char                *v_name;
     char                *v_path;
     int                 v_flags;
@@ -32,7 +35,10 @@ struct volinfo {
     char                *v_dbd_port;
 };
 
+struct volinfo *allocvolinfo(char *path);
 extern int loadvolinfo(char *path, struct volinfo *vol);
+extern void retainvolinfo(struct volinfo *vol);
+extern int closevolinfo(struct volinfo *vol);
 extern int savevolinfo(const struct vol *vol, const char *Cnid_srv, const char *Cnid_port);
 extern int vol_load_charsets(struct volinfo *vol);
 
index 993b1a746ecd9b3295d4f33074ef5a063119e1d5..77966459b2618f69d3cff16faeae7680a00bb9e0 100644 (file)
@@ -133,9 +133,13 @@ struct vol {
 
 #define AFPVOL_CACHE     (1 << 21)   /* Use adouble v2 CNID caching. Default: yes */
 #define AFPVOL_INV_DOTS  (1 << 22)   /* dots files are invisible */
-#define AFPVOL_TM        (1 << 24)   /* Supports TimeMachine */
-#define AFPVOL_ACLS      (1 << 25)   /* Volume supports ACLS */
-#define AFPVOL_CDROM     (1 << 25)   /* Ejectable media eg CD -> in memory CNID db */
+#define AFPVOL_TM        (1 << 23)   /* Supports TimeMachine */
+#define AFPVOL_ACLS      (1 << 24)   /* Volume supports ACLS */
+#define AFPVOL_SEARCHDB  (1 << 25)   /* Use fast CNID db search instead of filesystem */
+/* Found this in branch dir-rewrite, maybe we want to use it sometimes */
+#if 0
+#define AFPVOL_CDROM     (1 << XX)   /* Ejectable media eg CD -> in memory CNID db */
+#endif
 
 /* Extended Attributes vfs indirection  */
 #define AFPVOL_EA_NONE           0   /* No EAs */
index 1c131ad507c9712a4de3a18f8648795b89c950ef..9e71fcb4b71a3b7fd53479c4cebc2cef7cb3bb30 100644 (file)
@@ -30,6 +30,8 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <dirent.h>
+#include <sys/time.h>
+#include <time.h>
 
 #include <atalk/adouble.h>
 #include <atalk/ea.h>
@@ -148,3 +150,33 @@ int lchdir(const char *dir)
 
     return 0;
 }
+
+/*!
+ * Store n random bytes an buf
+ */
+void randombytes(void *buf, int n)
+{
+    char *p = (char *)buf;
+    int fd, i;
+    struct timeval tv;
+
+    if ((fd = open("/dev/urandom", O_RDONLY)) != -1) {
+        /* generate from /dev/urandom */
+        if (read(fd, buf, n) != n) {
+            close(fd);
+            fd = -1;
+        } else {
+            close(fd);
+            /* fd now != -1, so srandom wont be called below */
+        }
+    }
+
+    if (fd == -1) {
+        gettimeofday(&tv, NULL);
+        srandom((unsigned int)tv.tv_usec);
+        for (i=0 ; i < n ; i++)
+            p[i] = random() & 0xFF;
+    }
+
+    return;
+}
index 3e639f09ff28837bfcdc37d2d931315b27094658..6dec61a0ccf4f817d91d9128be7629ea2469a6bf 100644 (file)
@@ -294,10 +294,9 @@ static int parseline ( char *buf, struct volinfo *vol)
         }
         break;
       case CNID_DBPATH:
-        if ((vol->v_dbpath = strdup(value)) == NULL) {
-           fprintf (stderr, "strdup: %s", strerror(errno));
-            return -1;
-        }
+          if ((vol->v_dbpath = malloc(MAXPATHLEN+1)) == NULL)
+              return -1;
+          strcpy(vol->v_dbpath, value);
         break;
       case ADOUBLE_VER:
         if (strcasecmp(value, "v2") == 0) {
@@ -340,7 +339,7 @@ int loadvolinfo (char *path, struct volinfo *vol)
     char   volinfofile[MAXPATHLEN];
     char   buf[MAXPATHLEN];
     struct flock lock;
-    int    fd;
+    int    fd, len;
     FILE   *fp;
 
     if ( !path || !vol)
@@ -354,9 +353,16 @@ int loadvolinfo (char *path, struct volinfo *vol)
         return -1;
 
     if ((vol->v_path = strdup(volinfofile)) == NULL ) {
-       fprintf (stderr, "strdup: %s", strerror(errno));
+        fprintf (stderr, "strdup: %s", strerror(errno));
         return (-1);
     }
+    /* Remove trailing slashes */
+    len = strlen(vol->v_path);
+    while (len && (vol->v_path[len-1] == '/')) {
+        vol->v_path[len-1] = 0;
+        len--;
+    }
+
     strlcat(volinfofile, ".AppleDesktop/", sizeof(volinfofile));
     strlcat(volinfofile, VOLINFOFILE, sizeof(volinfofile));
 
@@ -399,10 +405,63 @@ int loadvolinfo (char *path, struct volinfo *vol)
     if ((vol->v_flags & AFPVOL_INV_DOTS))
         vol->v_ad_options |= ADVOL_INVDOTS;
 
+    vol->retaincount = 1;
+
     fclose(fp);
     return 0;
 }
 
+/*!
+ * Allocate a struct volinfo object for refcounting usage with retain and close, and
+ * call loadvolinfo with it
+ */
+struct volinfo *allocvolinfo(char *path)
+{
+    struct volinfo *p = malloc(sizeof(struct volinfo));
+    if (p == NULL)
+        return NULL;
+
+    if (loadvolinfo(path, p) == -1)
+        return NULL;
+
+    p->malloced = 1;
+
+    return p;
+}
+
+void retainvolinfo(struct volinfo *vol)
+{
+    vol->retaincount++;
+}
+
+/*!
+ * Decrement retain count, free resources when retaincount reaches 0
+ */
+int closevolinfo(struct volinfo *volinfo)
+{
+    if (volinfo->retaincount <= 0)
+        abort();
+
+    volinfo->retaincount--;
+
+    if (volinfo->retaincount == 0) {
+        free(volinfo->v_name); volinfo->v_name = NULL;
+        free(volinfo->v_path); volinfo->v_path = NULL;
+        free(volinfo->v_cnidscheme); volinfo->v_cnidscheme = NULL;
+        free(volinfo->v_dbpath); volinfo->v_dbpath = NULL;
+        free(volinfo->v_volcodepage); volinfo->v_volcodepage = NULL;
+        free(volinfo->v_maccodepage); volinfo->v_maccodepage = NULL;
+        free(volinfo->v_dbd_host); volinfo->v_dbd_host = NULL;
+        free(volinfo->v_dbd_port); volinfo->v_dbd_port = NULL;
+        if (volinfo->malloced) {
+            volinfo->malloced = 0;
+            free(volinfo);
+        }
+    }
+
+    return 0;
+}
+
 /*
  * Save the volume options to a file, used by shell utilities. Writing the file
  * everytime a volume is opened is unnecessary, but it shouldn't hurt much.
index afaec7866701b6049cdfe760d1c67c19d9d7fd27..c754aeea017bcca0ebdc4564e69f9d9b4b7cae8b 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: AppleVolumes.default
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 22 Apr 2010
+.\"      Date: 07 Dec 2010
 .\"    Manual: Netatalk 2.2
 .\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "APPLEVOLUMES\&.DEFAU" "5" "22 Apr 2010" "Netatalk 2.2" "Netatalk 2.2"
+.TH "APPLEVOLUMES\&.DEFAU" "5" "07 Dec 2010" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -234,6 +234,11 @@ options:\fI[option]\fR
 .RS 4
 This allows multiple options to be specified in a comma delimited format\&. The available options are:
 .PP
+searchdb
+.RS 4
+Use fast CNID database namesearch instead of slow recursive filesystem search\&. Relies on a consistent CNID database, ie Samba or local filesystem access lead to inaccurate or wrong results\&. Works only for "dbd" CNID db volumes\&.
+.RE
+.PP
 tm
 .RS 4
 Enable Time Machine suport for this volume\&.
index 5fc967a55bd7f8f21a37ef63b90ae696ad3223b7..090ab7724413234efa19c5d661236318e0438854 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: cnid_dbd
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\"      Date: 21 Mar 2009
-.\"    Manual: Netatalk 2.1
-.\"    Source: Netatalk 2.1
+.\"      Date: 10 Dec 2010
+.\"    Manual: Netatalk 2.2
+.\"    Source: Netatalk 2.2
 .\"  Language: English
 .\"
-.TH "CNID_DBD" "8" "21 Mar 2009" "Netatalk 2.1" "Netatalk 2.1"
+.TH "CNID_DBD" "8" "10 Dec 2010" "Netatalk 2.2" "Netatalk 2.2"
 .\" -----------------------------------------------------------------
 .\" * set default formatting
 .\" -----------------------------------------------------------------
@@ -22,7 +22,7 @@
 cnid_dbd \- implement access to CNID databases through a dedicated daemon process
 .SH "SYNOPSIS"
 .HP \w'\fBcnid_dbd\fR\fB\fR\fB\fR\fB\fR\ 'u
-\fBcnid_dbd\fR\fB\fR\fB\fR\fB\fR \fIdbdir\fR \fIctrlfd\fR \fIclntfd\fR \fIlogconfig_string\fR
+\fBcnid_dbd\fR\fB\fR\fB\fR\fB\fR \fIvolpath\fR \fIctrlfd\fR \fIclntfd\fR \fIlogconfig_string\fR
 .SH "DESCRIPTION"
 .PP
 \fBcnid_dbd\fR
@@ -41,7 +41,7 @@ backend\&.
 \fBcnid_dbd\fR
 is never started via the command line or system startup scripts but only by the
 \fBcnid_metad\fR
-daemon\&. There is at most one instance of
+daemon\&. There is one instance of
 \fBcnid_dbd\fR
 per netatalk volume\&.
 .PP
@@ -53,11 +53,6 @@ database library and uses transactionally protected updates\&. The
 backend with transactions will avoid corruption of the CNID database even if the system crashes unexpectedly\&.
 .PP
 \fBcnid_dbd\fR
-uses the same on\-disk database format as the
-\fBcdb\fR
-backend\&. It is therefore possible to switch between the two backends as necessary\&.
-.PP
-\fBcnid_dbd\fR
 inherits the effective userid and groupid from
 \fBcnid_metad\fR
 on startup, which is normally caused by
@@ -105,7 +100,7 @@ database subsystem will create files named log\&.xxxxxxxxxx in the database home
 \fBlogfile_autoremove\fR
 option is specified in the
 \fIdb_param\fR
-configuration file (see below)\&.
+configuration file (see below) with a value of 0 (default 1)\&.
 .PP
 Do not use
 \fBcnid_dbd\fR
@@ -180,7 +175,11 @@ exits\&. Default: 600\&. Set this to 0 to disable the timeout\&.
 .RE
 .SH "UPDATING"
 .PP
-In order to update between Netatalk releases using different BerkeleyDB library versions, follow this steps:
+Note that the first version to appear
+\fIafter\fR
+Netatalk 2\&.1 ie Netatalk 2\&.1\&.1, will support BerkeleyDB updates on the fly without manual intervention\&. In other words Netatalk 2\&.1 does contain code to prepare the BerkeleyDB database for upgrades and to upgrade it in case it has been prepared before\&. That means it can\'t upgrade a 2\&.0\&.x version because that one didn\'t prepare the database\&.
+.PP
+In order to update between older Netatalk releases using different BerkeleyDB library versions, follow this steps:
 .sp
 .RS 4
 .ie n \{\
@@ -239,10 +238,6 @@ Again using the new BerkeleyDB utilities run
 .\}
 Start the the new version of Netatalk
 .RE
-.PP
-Note that the first version to appear
-\fIafter\fR
-Netatalk 2\&.1 ie Netatalk 2\&.1\&.1, will support BerkeleyDB updates on the fly without manual intervention\&. In other words Netatalk 2\&.1 does contain code to prepare the BerkeleyDB database for upgrades and to upgrade it in case it has been prepared before\&. That means it can\'t upgrade a 2\&.0\&.x version because that one didn\'t prepare the database\&.
 .SH "SEE ALSO"
 .PP
 \fBcnid_metad\fR(8),