]> arthur.barton.de Git - netatalk.git/commitdiff
Merge master
authorFrank Lahm <franklahm@googlemail.com>
Tue, 10 May 2011 06:01:02 +0000 (08:01 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Tue, 10 May 2011 06:01:02 +0000 (08:01 +0200)
17 files changed:
NEWS
etc/afpd/afp_dsi.c
etc/afpd/afp_options.c
etc/afpd/catsearch.c
etc/afpd/dircache.c
etc/afpd/dircache.h
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/enumerate.c
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/main.c
etc/afpd/volume.c
etc/cnid_dbd/cnid_metad.c
include/atalk/directory.h
libatalk/util/socket.c
man/man8/afpd.8.tmpl

diff --git a/NEWS b/NEWS
index 757b22a7d716020af4fa142e7d07d8bfe3c17317..f8d92829c0ce4883ec62ef59eda9e7211471fdfd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,18 @@
+Changes in 2.2
+==============
+
+* UPD: Support for Berkeley DB 5.1
+* UPD: case-conversion is based on Unicode 6.0.0
+* UPD: cnid_metad: allow up to 4096 volumes
+* UPD: afpd: only forward SIGTERM and SIGUSR1 from parent to childs
+* FIX: afpd: configuration reload with SIGHUP
+* FIX: afpd: crashes in the dircache
+* FIX: afpd: Correct afp logout vs dsi eof behaviour
+* FIX: afpd: new catsearch was broken
+* FIX: afpd: only use volume UUIDs in master afpd
+* FIX: dbd: Multiple fixes, reliable locking
+* FIX: ad file suite: fix an error that resulted in CNID database inconsistencies
+
 Changes in 2.2beta4
 ===================
 
index 96188688d88e899eb2adfd4bc774e1fb6772f4a7..dfebaca0fb8f20e1781d46388afc469635a9bd07 100644 (file)
@@ -512,8 +512,6 @@ void afp_over_dsi(AFPObj *obj)
         if (reload_request) {
             reload_request = 0;
             load_volumes(AFPobj);
-            dircache_dump();
-            log_dircache_stat();
         }
 
         /* The first SIGINT enables debugging, the next restores the config */
@@ -521,6 +519,8 @@ void afp_over_dsi(AFPObj *obj)
             static int debugging = 0;
             debug_request = 0;
 
+            dircache_dump();
+
             if (debugging) {
                 if (obj->options.logconfig)
                     setuplog(obj->options.logconfig);
index ec4b762dfb1a7b84a9da7e98ad21518a63e9f208..ffe28590289fd1f1c4ec01b67620b4087ebf536b 100644 (file)
@@ -350,8 +350,11 @@ int afp_options_parseline(char *buf, struct afp_options *options)
     while (NULL != (c = strstr(c, "-setuplog"))) {
         char *optstr;
         if ((optstr = getoption(c, "-setuplog"))) {
+            /* hokey2: options->logconfig must be converted to store an array of logstrings */
+            if (options->logconfig)
+                free(options->logconfig);
+            options->logconfig = strdup(optstr);
             setuplog(optstr);
-            options->logconfig = optstr; /* at least store the last (possibly only) one */
             c += sizeof("-setuplog");
         }
     }
index 6a9161e2e8720743ca3cbbf4100b0980de9d34b0..d0e89f39fdad3527dddd1a4862e8e5ca042610ad 100644 (file)
@@ -613,8 +613,7 @@ static int catsearch(struct vol *vol,
                 path.d_dir = dircache_search_by_name(vol,
                                                      curdir,
                                                      path.u_name,
-                                                     unlen,
-                                                     path.st.st_ctime);
+                                                     unlen);
                if (path.d_dir == NULL) {
                        /* path.m_name is set by adddir */
                    if ((path.d_dir = dir_add(vol,
index 9907c5dd35bddabc02bbcef02d94dc07503d2975..44b74ada4286696d3148525f285e5206ac83c5db 100644 (file)
@@ -52,8 +52,8 @@
  * a struct dir is initialized, the fullpath to the directory is stored there.
  *
  * In order to speed up the CNID query for files too, which eg happens when a directory is enumerated,
- * files are stored too in the dircache. In order to differentiate between files and dirs, we re-use
- * the element fullpath, which for files is always NULL.
+ * files are stored too in the dircache. In order to differentiate between files and dirs, we set
+ * the flag DIRF_ISFILE in struct dir.d_flags for files.
  *
  * The most frequent codepatch that leads to caching is directory enumeration (cf enumerate.c):
  * - if a element is a directory:
  * Debugging
  * =========
  *
- * Sending SIGHUP to a afpd child causes it to dump the dircache to a file "/tmp/dircache.PID".
+ * Sending SIGINT to a afpd child causes it to dump the dircache to a file "/tmp/dircache.PID".
  */
 
 /********************************************************
@@ -288,7 +288,7 @@ static void dircache_evict(void)
  * This func builds on the fact, that all our code only ever needs to and does search
  * the dircache by CNID expecting directories to be returned, but not files.
  * Thus
- * (1) if we find a file (d_fullpath == NULL) for a given CNID we
+ * (1) if we find a file for a given CNID we
  *     (1a) remove it from the cache
  *     (1b) return NULL indicating nothing found
  * (2) we can then use d_fullpath to stat the directory
@@ -315,7 +315,7 @@ struct dir *dircache_search_by_did(const struct vol *vol, cnid_t cnid)
         cdir = hnode_get(hn);
 
     if (cdir) {
-        if (cdir->d_fullpath == NULL) { /* (1) */
+        if (cdir->d_flags & DIRF_ISFILE) { /* (1) */
             LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {not a directory:\"%s\"}",
                 ntohl(cnid), cfrombstr(cdir->d_u_name));
             (void)dir_remove(vol, cdir); /* (1a) */
@@ -330,7 +330,7 @@ struct dir *dircache_search_by_did(const struct vol *vol, cnid_t cnid)
             dircache_stat.expunged++;
             return NULL;
         }
-        if (cdir->ctime_dircache != st.st_ctime) {
+        if ((cdir->dcache_ctime != st.st_ctime) || (cdir->dcache_ino != st.st_ino)) {
             LOG(log_debug, logtype_afpd, "dircache(cnid:%u): {modified:\"%s\"}",
                 ntohl(cnid), cfrombstr(cdir->d_u_name));
             (void)dir_remove(vol, cdir);
@@ -358,18 +358,17 @@ struct dir *dircache_search_by_did(const struct vol *vol, cnid_t cnid)
  * @param dir      (r) directory
  * @param name     (r) name (server side encoding)
  * @parma len      (r) strlen of name
- * @param ctime    (r) current st_ctime from stat
  *
  * @returns pointer to struct dir if found in cache, else NULL
  */
 struct dir *dircache_search_by_name(const struct vol *vol,
                                     const struct dir *dir,
                                     char *name,
-                                    int len,
-                                    time_t ctime)
+                                    int len)
 {
     struct dir *cdir = NULL;
     struct dir key;
+    struct stat st;
 
     hnode_t *hn;
     static_bstring uname = {-1, len, (unsigned char *)name};
@@ -394,7 +393,16 @@ struct dir *dircache_search_by_name(const struct vol *vol,
     }
 
     if (cdir) {
-        if (cdir->ctime_dircache != ctime) {
+        if (lstat(cfrombstr(cdir->d_fullpath), &st) != 0) {
+            LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {missing:\"%s\"}",
+                ntohl(dir->d_did), name, cfrombstr(cdir->d_fullpath));
+            (void)dir_remove(vol, cdir);
+            dircache_stat.expunged++;
+            return NULL;
+        }
+
+        /* Remove modified directories and files */
+        if ((cdir->dcache_ctime != st.st_ctime) || (cdir->dcache_ino != st.st_ino)) {
             LOG(log_debug, logtype_afpd, "dircache(did:%u,\"%s\"): {modified}",
                 ntohl(dir->d_did), name);
             (void)dir_remove(vol, cdir);
@@ -643,8 +651,8 @@ void dircache_dump(void)
                 ntohs(dir->d_vid),
                 ntohl(dir->d_pdid),
                 ntohl(dir->d_did),
-                dir->d_fullpath ? "d" : "f",
-                cfrombstr(dir->d_u_name));
+                dir->d_flags & DIRF_ISFILE ? "f" : "d",
+                cfrombstr(dir->d_fullpath));
     }
 
     fprintf(dump, "\nSecondary DID/name index:\n");
@@ -659,8 +667,8 @@ void dircache_dump(void)
                 ntohs(dir->d_vid),
                 ntohl(dir->d_pdid),
                 ntohl(dir->d_did),
-                dir->d_fullpath ? "d" : "f",
-                cfrombstr(dir->d_u_name));
+                dir->d_flags & DIRF_ISFILE ? "f" : "d",
+                cfrombstr(dir->d_fullpath));
     }
 
     fprintf(dump, "\nLRU Queue:\n");
@@ -676,8 +684,8 @@ void dircache_dump(void)
                 ntohs(dir->d_vid),
                 ntohl(dir->d_pdid),
                 ntohl(dir->d_did),
-                dir->d_fullpath ? "d" : "f",
-                cfrombstr(dir->d_u_name));
+                dir->d_flags & DIRF_ISFILE ? "f" : "d",
+                cfrombstr(dir->d_fullpath));
         n = n->next;
     }
 
index 16c2df1dbde26ab5d3d994d429172a98fa9bcc7a..42466d2dc67f004ba10c6b35779a6170f28699c2 100644 (file)
@@ -35,7 +35,7 @@ extern int        dircache_init(int reqsize);
 extern int        dircache_add(const struct vol *, struct dir *);
 extern void       dircache_remove(const struct vol *, struct dir *, int flag);
 extern struct dir *dircache_search_by_did(const struct vol *vol, cnid_t did);
-extern struct dir *dircache_search_by_name(const struct vol *, const struct dir *dir, char *name, int len, time_t ctime);
+extern struct dir *dircache_search_by_name(const struct vol *, const struct dir *dir, char *name, int len);
 extern void       dircache_dump(void);
 extern void       log_dircache_stat(void);
 #endif /* DIRCACHE_H */
index 488f900a0a553e7ee278962e8a2f786087557d72..df01ccc4b63e5a93fe345dfe3d0003ef9cab58b0 100644 (file)
@@ -265,7 +265,7 @@ copydir_done:
  */
 static int diroffcnt(struct dir *dir, struct stat *st)
 {
-    return st->st_ctime == dir->ctime;
+    return st->st_ctime == dir->d_ctime;
 }
 
 /* --------------------- */
@@ -468,6 +468,7 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path)
     l = bsplit(rpath, '/');
     for (int i = 0; i < l->qty ; i++) {                  /* 3. */
         did = cnid;
+        EC_ZERO(bcatcstr(statpath, "/"));
         EC_ZERO(bconcat(statpath, l->entry[i]));
         EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
                        "lstat(rpath: %s, elem: %s): %s: %s",
@@ -480,8 +481,7 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path)
         if ((dir = dircache_search_by_name(vol,          /* 5. */
                                            dir,
                                            cfrombstr(l->entry[i]),
-                                           blength(l->entry[i]),
-                                           st.st_ctime)) == NULL) {
+                                           blength(l->entry[i]))) == NULL) {
             if ((cnid = cnid_add(vol->v_cdb,             /* 6. */
                                  &st,
                                  did,
@@ -494,8 +494,6 @@ struct dir *dirlookup_bypath(const struct vol *vol, const char *path)
             if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */
                 EC_FAIL;
         }
-
-        EC_ZERO(bcatcstr(statpath, "/"));
     }
 
 EC_CLEANUP:
@@ -514,7 +512,7 @@ EC_CLEANUP:
  * Resolve a DID, allocate a struct dir for it
  * 1. Check for special CNIDs 0 (invalid), 1 and 2.
  * 2a. Check if the DID is in the cache.
- * 2b. Check if it's really a dir (d_fullpath != NULL) because we cache files too.
+ * 2b. Check if it's really a dir  because we cache files too.
  * 3. If it's not in the cache resolve it via the database.
  * 4. Build complete server-side path to the dir.
  * 5. Check if it exists and is a directory.
@@ -539,7 +537,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     int          utf8;
     int          err = 0;
 
-    LOG(log_debug, logtype_afpd, "dirlookup(did: %u)", ntohl(did));
+    LOG(log_debug, logtype_afpd, "dirlookup(did: %u): START", ntohl(did));
 
     /* check for did 0, 1 and 2 */
     if (did == 0 || vol == NULL) { /* 1 */
@@ -557,18 +555,19 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
 
     /* Search the cache */
     if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */
-        if (ret->d_fullpath == NULL) {                      /* 2b */
+        if (ret->d_flags & DIRF_ISFILE) {                   /* 2b */
             afp_errno = AFPERR_BADTYPE;
             ret = NULL;
             goto exit;
         }
         if (lstat(cfrombstr(ret->d_fullpath), &st) != 0) {
-            LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno));
+            LOG(log_debug, logtype_afpd, "dirlookup(did: %u, path: \"%s\"): lstat: %s",
+                ntohl(did), cfrombstr(ret->d_fullpath), strerror(errno));
             switch (errno) {
             case ENOENT:
             case ENOTDIR:
                 /* It's not there anymore, so remove it */
-                LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {calling dir_remove()}", ntohl(did));
+                LOG(log_debug, logtype_afpd, "dirlookup(did: %u): calling dir_remove", ntohl(did));
                 dir_remove(vol, ret);
                 afp_errno = AFPERR_NOOBJ;
                 ret = NULL;
@@ -590,6 +589,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
 
     /* Get it from the database */
     cnid = did;
+    LOG(log_debug, logtype_afpd, "dirlookup(did: %u): querying CNID database", ntohl(did));
     if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) {
         afp_errno = AFPERR_NOOBJ;
         err = 1;
@@ -607,7 +607,8 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
      * - DIRDID_ROOT is hit
      * - a cached entry is found
      */
-    LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {recursion for did: %u}", ntohl(pdid));
+    LOG(log_debug, logtype_afpd, "dirlookup(did: %u): recursion for did: %u",
+        ntohl(did), ntohl(pdid));
     if ((pdir = dirlookup(vol, pdid)) == NULL) {
         err = 1;
         goto exit;
@@ -622,9 +623,10 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     }
 
     /* stat it and check if it's a dir */
-    LOG(log_debug, logtype_afpd, "dirlookup: {stating %s}", cfrombstr(fullpath));
+    LOG(log_debug, logtype_afpd, "dirlookup(did: %u): stating \"%s\"",
+        ntohl(did), cfrombstr(fullpath));
 
-    if (stat(cfrombstr(fullpath), &st) != 0) { /* 5a */
+    if (lstat(cfrombstr(fullpath), &st) != 0) { /* 5a */
         switch (errno) {
         case ENOENT:
             afp_errno = AFPERR_NOOBJ;
@@ -655,7 +657,7 @@ struct dir *dirlookup(const struct vol *vol, cnid_t did)
     }
 
     /* Create struct dir */
-    if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, st.st_ctime)) == NULL) { /* 6 */
+    if ((ret = dir_new(mpath, upath, vol, pdid, did, fullpath, &st)) == NULL) { /* 6 */
         LOG(log_error, logtype_afpd, "dirlookup(did: %u) {%s, %s}: %s", ntohl(did), mpath, upath, strerror(errno));
         err = 1;
         goto exit;
@@ -680,7 +682,7 @@ exit:
         }
     }
     if (ret)
-        LOG(log_debug, logtype_afpd, "dirlookup(did: %u): pdid: %u, \"%s\"",
+        LOG(log_debug, logtype_afpd, "dirlookup(did: %u): RESULT: pdid: %u, path: \"%s\"",
             ntohl(ret->d_did), ntohl(ret->d_pdid), cfrombstr(ret->d_fullpath));
 
     return ret;
@@ -778,8 +780,8 @@ int caseenumerate(const struct vol *vol, struct path *path, struct dir *dir)
  * @param vol      (r) pointer to struct vol
  * @param pdid     (r) Parent CNID
  * @param did      (r) CNID
- * @param path     (r) Full unix path to dir or NULL for files
- * @param ctime    (r) st_ctime from stat
+ * @param path     (r) Full unix path to object
+ * @param st       (r) struct stat of object
  *
  * @returns pointer to new struct dir or NULL on error
  *
@@ -791,7 +793,7 @@ struct dir *dir_new(const char *m_name,
                     cnid_t pdid,
                     cnid_t did,
                     bstring path,
-                    time_t ctime)
+                    struct stat *st)
 {
     struct dir *dir;
 
@@ -825,7 +827,10 @@ struct dir *dir_new(const char *m_name,
     dir->d_pdid = pdid;
     dir->d_vid = vol->v_vid;
     dir->d_fullpath = path;
-    dir->ctime_dircache = ctime;
+    dir->dcache_ctime = st->st_ctime;
+    dir->dcache_ino = st->st_ino;
+    if (!S_ISDIR(st->st_mode))
+        dir->d_flags = DIRF_ISFILE;
     return dir;
 }
 
@@ -879,7 +884,7 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i
     AFP_ASSERT(path);
     AFP_ASSERT(len > 0);
 
-    if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name), path->st.st_ctime)) != NULL) {
+    if ((cdir = dircache_search_by_name(vol, dir, path->u_name, strlen(path->u_name))) != NULL) {
         /* there's a stray entry in the dircache */
         LOG(log_debug, logtype_afpd, "dir_add(did:%u,'%s/%s'): {stray cache entry: did:%u,'%s', removing}",
             ntohl(dir->d_did), cfrombstr(dir->d_fullpath), path->u_name,
@@ -923,7 +928,13 @@ struct dir *dir_add(struct vol *vol, const struct dir *dir, struct path *path, i
     }
 
     /* Allocate and initialize struct dir */
-    if ((cdir = dir_new( path->m_name, path->u_name, vol, dir->d_did, id, fullpath, path->st.st_ctime)) == NULL) { /* 3 */
+    if ((cdir = dir_new(path->m_name,
+                        path->u_name,
+                        vol,
+                        dir->d_did,
+                        id,
+                        fullpath,
+                        &path->st)) == NULL) { /* 3 */
         err = 4;
         goto exit;
     }
@@ -1281,7 +1292,7 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
 
             /* Search the cache */
             int unamelen = strlen(ret.u_name);
-            cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen, ret.st.st_ctime); /* 14 */
+            cdir = dircache_search_by_name(vol, dir, ret.u_name, unamelen); /* 14 */
             if (cdir == NULL) {
                 /* Not in cache, create one */
                 if ((cdir = dir_add(vol, dir, &ret, unamelen)) == NULL) { /* 15 */
@@ -1431,8 +1442,8 @@ int file_access(struct path *path, int mode)
 /* --------------------- */
 void setdiroffcnt(struct dir *dir, struct stat *st,  u_int32_t count)
 {
-    dir->offcnt = count;
-    dir->ctime = st->st_ctime;
+    dir->d_offcnt = count;
+    dir->d_ctime = st->st_ctime;
     dir->d_flags &= ~DIRF_CNID;
 }
 
@@ -1442,7 +1453,7 @@ void setdiroffcnt(struct dir *dir, struct stat *st,  u_int32_t count)
  */
 int dirreenumerate(struct dir *dir, struct stat *st)
 {
-    return st->st_ctime == dir->ctime && (dir->d_flags & DIRF_CNID);
+    return st->st_ctime == dir->d_ctime && (dir->d_flags & DIRF_CNID);
 }
 
 /* ------------------------------
@@ -1569,11 +1580,11 @@ int getdirparams(const struct vol *vol,
             ashort = 0;
             /* this needs to handle current directory access rights */
             if (diroffcnt(dir, st)) {
-                ashort = (dir->offcnt > 0xffff)?0xffff:dir->offcnt;
+                ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt;
             }
             else if ((ret = for_each_dirent(vol, upath, NULL,NULL)) >= 0) {
                 setdiroffcnt(dir, st,  ret);
-                ashort = (dir->offcnt > 0xffff)?0xffff:dir->offcnt;
+                ashort = (dir->d_offcnt > 0xffff)?0xffff:dir->d_offcnt;
             }
             ashort = htons( ashort );
             memcpy( data, &ashort, sizeof( ashort ));
@@ -2221,7 +2232,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_
         return AFPERR_MISC;
     }
 
-    curdir->offcnt++;
+    curdir->d_offcnt++;
 
     if ((dir = dir_add(vol, curdir, s_path, strlen(s_path->u_name))) == NULL) {
         return AFPERR_MISC;
index 1504c649dbb9ba55ea083f8bc95b6d701cf6b05c..b438b370251148fe22745d425b48ca2a1db0ad47 100644 (file)
 #include "globals.h"
 #include "volume.h"
 
-#define DIRF_FSMASK    (3<<0)
-#define DIRF_NOFS      (0<<0)
-#define DIRF_AFS       (1<<0)
-#define DIRF_UFS       (2<<0)
-
-#define DIRF_OFFCNT    (1<<4) /* offsprings count is valid */
-#define DIRF_CNID         (1<<5) /* renumerate id */
-
-#define AFPDIR_READ    (1<<0)
-
 /* directory bits */
 #define DIRPBIT_ATTR   0
 #define DIRPBIT_PDID   1
@@ -107,7 +97,7 @@ typedef int (*dir_loop)(struct dirent *, char *, void *);
 
 extern void        dir_free_invalid_q(void);
 extern struct dir  *dir_new(const char *mname, const char *uname, const struct vol *,
-                            cnid_t pdid, cnid_t did, bstring fullpath, time_t ctime);
+                            cnid_t pdid, cnid_t did, bstring fullpath, struct stat *);
 extern void        dir_free (struct dir *);
 extern struct dir  *dir_add(struct vol *, const struct dir *, struct path *, int);
 extern int         dir_modify(const struct vol *vol, struct dir *dir, cnid_t pdid, cnid_t did,
index 1659fb77ff89cc5fbff15513fe5915600b718ae4..0bc24cec4dbed2ff62836e1ff244d8cf4feebf77 100644 (file)
@@ -359,7 +359,7 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
              */
             *sd.sd_last = 0;
             sd.sd_last += len + 1;
-            curdir->offcnt--;          /* a little lie */
+            curdir->d_offcnt--;                /* a little lie */
             continue;
         }
 
@@ -375,7 +375,7 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
                 continue;
             }
             int len = strlen(s_path.u_name);
-            if ((dir = dircache_search_by_name(vol, curdir, s_path.u_name, len, s_path.st.st_ctime)) == NULL) {
+            if ((dir = dircache_search_by_name(vol, curdir, s_path.u_name, len)) == NULL) {
                 if ((dir = dir_add(vol, curdir, &s_path, len)) == NULL) {
                     LOG(log_error, logtype_afpd, "enumerate(vid:%u, did:%u, name:'%s'): error adding dir: '%s'",
                         ntohs(vid), ntohl(did), o_path->u_name, s_path.u_name);
index 009ec195f02d1150d3f0c5a7bd663d602380f1ae..b5a896373683c88e7380af2da72c36e6ca06f98c 100644 (file)
@@ -311,9 +311,10 @@ int getmetadata(struct vol *vol,
          || (bitmap & ( (1 << FILPBIT_LNAME) ) && utf8_encoding()) /* FIXME should be m_name utf8 filename */
          || (bitmap & (1 << FILPBIT_FNUM))) {
         if (!path->id) {
+            bstring fullpath;
             struct dir *cachedfile;
             int len = strlen(upath);
-            if ((cachedfile = dircache_search_by_name(vol, dir, upath, len, st->st_ctime)) != NULL)
+            if ((cachedfile = dircache_search_by_name(vol, dir, upath, len)) != NULL)
                 id = cachedfile->d_did;
             else {
                 id = get_id(vol, adp, st, dir->d_did, upath, len);
@@ -326,18 +327,26 @@ int getmetadata(struct vol *vol,
                 if (path->m_name == NULL) {
                     if ((path->m_name = utompath(vol, upath, id, utf8_encoding())) == NULL) {
                         LOG(log_error, logtype_afpd, "getmetadata: utompath error");
-                        exit(EXITERR_SYS);
+                        return AFPERR_MISC;
                     }
                 }
                 
-                if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, NULL, st->st_ctime)) == NULL) {
+                /* Build fullpath */
+                if (((fullpath = bstrcpy(dir->d_fullpath)) == NULL)
+                    || (bconchar(fullpath, '/') != BSTR_OK)
+                    || (bcatcstr(fullpath, upath)) != BSTR_OK) {
+                    LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno));
+                    return AFPERR_MISC;
+                }
+
+                if ((cachedfile = dir_new(path->m_name, upath, vol, dir->d_did, id, fullpath, st)) == NULL) {
                     LOG(log_error, logtype_afpd, "getmetadata: error from dir_new");
-                    exit(EXITERR_SYS);
+                    return AFPERR_MISC;
                 }
 
                 if ((dircache_add(vol, cachedfile)) != 0) {
                     LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error");
-                    exit(EXITERR_SYS);
+                    return AFPERR_MISC;
                 }
             }
         } else {
@@ -738,7 +747,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
     ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
 
 createfile_done:
-    curdir->offcnt++;
+    curdir->d_offcnt++;
 
     setvoltime(obj, vol );
 
@@ -1324,7 +1333,7 @@ int afp_copyfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si
         retvalue = err;
         goto copy_exit;
     }
-    curdir->offcnt++;
+    curdir->d_offcnt++;
 
     setvoltime(obj, d_vol );
 
@@ -1782,7 +1791,7 @@ reenumerate_id(struct vol *vol, char *name, struct dir *dir)
 
     if (dirreenumerate(dir, &st)) {
         /* we already did it once and the dir haven't been modified */
-       return dir->offcnt;
+       return dir->d_offcnt;
     }
     
     data.vol = vol;
index 1478299e262d297946cf9eed86434e6589c7d6b9..9453111b62349efb82113400fb9cb52b5ec94c39 100644 (file)
@@ -522,14 +522,14 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
             rc = deletefile(vol, -1, upath, 1);
 
             struct dir *cachedfile;
-            if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath), s_path->st.st_ctime))) {
+            if ((cachedfile = dircache_search_by_name(vol, dir, upath, strlen(upath)))) {
                 dircache_remove(vol, cachedfile, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX);
                 dir_free(cachedfile);
             }
         }
     }
     if ( rc == AFP_OK ) {
-        curdir->offcnt--;
+        curdir->d_offcnt--;
         setvoltime(obj, vol );
     }
 
index c926c36899ebeaa529e0d8ec81bc752057c41b64..37bb4bd4a0916ba6c54ce5b074fa081edca47fe1 100644 (file)
@@ -107,20 +107,20 @@ static void fd_reset_listening_sockets(void)
             continue;
         fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd);
     }
-    fd_set_listening_sockets();
 }
 
 /* ------------------ */
 static void afp_goaway(int sig)
 {
-    if (server_children)
-        server_child_kill(server_children, CHILD_DSIFORK, sig);
-
     switch( sig ) {
 
     case SIGTERM :
         LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGTERM");
         AFPConfig *config;
+
+        if (server_children)
+            server_child_kill(server_children, CHILD_DSIFORK, sig);
+
         for (config = configs; config; config = config->next)
             if (config->server_cleanup)
                 config->server_cleanup(config);
@@ -132,6 +132,9 @@ static void afp_goaway(int sig)
         nologin++;
         auth_unload();
         LOG(log_info, logtype_afpd, "disallowing logins");        
+
+        if (server_children)
+            server_child_kill(server_children, CHILD_DSIFORK, sig);
         break;
 
     case SIGHUP :
@@ -341,6 +344,7 @@ int main(int ac, char **av)
         if (reloadconfig) {
             nologin++;
             auth_unload();
+            fd_reset_listening_sockets();
 
             LOG(log_info, logtype_afpd, "re-reading configuration file");
             for (config = configs; config; config = config->next)
@@ -354,10 +358,13 @@ int main(int ac, char **av)
                 LOG(log_error, logtype_afpd, "config re-read: no servers configured");
                 exit(EXITERR_CONF);
             }
-            fd_reset_listening_sockets();
+
+            fd_set_listening_sockets();
+
             nologin = 0;
             reloadconfig = 0;
             errno = saveerrno;
+            continue;
         }
 
         if (ret == 0)
index 60fc73e9073292a3452a03559022769b616a459e..23bd2c16444d62e68ed614fd60b1e1191f4e8ff7 100644 (file)
@@ -604,7 +604,14 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
     if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) {
         if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) {
             flags = CONV_FORCE;
-            tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_MACNAMELEN - suffixlen, &flags);
+            tmpvlen = convert_charset(obj->options.unixcharset,
+                                      obj->options.maccharset,
+                                      0,
+                                      name,
+                                      vlen,
+                                      tmpname,
+                                      AFPVOL_MACNAMELEN - suffixlen,
+                                      &flags);
             tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0;
         }
         strcat(tmpname, suffix);
@@ -612,15 +619,24 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
     }
 
     /* Secondly convert name from maccharset to UCS2 */
-    if ( 0 >= ( macvlen = convert_string(obj->options.maccharset, CH_UCS2, tmpname, tmpvlen, mactmpname, AFPVOL_U8MNAMELEN*2)) )
+    if ( 0 >= ( macvlen = convert_string(obj->options.maccharset,
+                                         CH_UCS2,
+                                         tmpname,
+                                         tmpvlen,
+                                         mactmpname,
+                                         AFPVOL_U8MNAMELEN*2)) )
         return -1;
 
     LOG(log_maxdebug, logtype_afpd, "createvol: Volume '%s' ->  Longname: '%s'", name, tmpname);
 
     /* check duplicate */
     for ( volume = Volumes; volume; volume = volume->v_next ) {
-        if (( strcasecmp_w( volume->v_u8mname, u8mtmpname ) == 0 ) || ( strcasecmp_w( volume->v_macname, mactmpname ) == 0 )){
-            LOG (log_error, logtype_afpd, "ERROR: Volume name is duplicated. Check AppleVolumes files.");
+        if ((utf8_encoding() && (strcasecmp_w(volume->v_u8mname, u8mtmpname) == 0))
+             ||
+            (!utf8_encoding() && (strcasecmp_w(volume->v_macname, mactmpname) == 0))) {
+            LOG (log_error, logtype_afpd,
+                 "Duplicate volume name, check AppleVolumes files: previous: \"%s\", new: \"%s\"",
+                 volume->v_localname, name);
             if (volume->v_deleted) {
                 volume->v_new = hide = 1;
             }
@@ -787,8 +803,8 @@ static int creatvol(AFPObj *obj, struct passwd *pwd,
         check_ea_sys_support(volume);
     initvol_vfs(volume);
 
-    /* get/store uuid from file */
-    if (volume->v_flags & AFPVOL_TM) {
+    /* get/store uuid from file in afpd master*/
+    if ((parent_or_child == 0) && (volume->v_flags & AFPVOL_TM)) {
         char *uuid = get_vol_uuid(obj, volume->v_localname);
         if (!uuid) {
             LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID",
@@ -2129,7 +2145,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
                        DIRDID_ROOT_PARENT,
                        DIRDID_ROOT,
                        bfromcstr(volume->v_path),
-                       st.st_ctime)
+                       &st)
             ) == NULL) {
         free(vol_mname);
         LOG(log_error, logtype_afpd, "afp_openvol(%s): malloc: %s", volume->v_path, strerror(errno) );
index 11987cc779b9225c01059cbbea1ad42fff44060e..b23d57cf41d5f6208615d2ddcec968c98742d580 100644 (file)
 static int srvfd;
 static int rqstfd;
 static volatile sig_atomic_t sigchild = 0;
+static uint maxvol;
 
 #define MAXSPAWN   3                   /* Max times respawned in.. */
 #define TESTTIME   42                  /* this much seconds apfd client tries to  *
                                         * to reconnect every 5 secondes, catch it */
-#define MAXVOLS    512
+#define MAXVOLS    4096
 #define DEFAULTHOST  "localhost"
 #define DEFAULTPORT  "4700"
 
@@ -142,7 +143,7 @@ static void sigterm_handler(int sig)
 static struct server *test_usockfn(struct volinfo *volinfo)
 {
     int i;
-    for (i = 0; i < MAXVOLS; i++) {
+    for (i = 0; i < maxvol; i++) {
         if ((srv[i].volinfo) && (strcmp(srv[i].volinfo->v_path, volinfo->v_path) == 0)) {
             return &srv[i];
         }
@@ -178,14 +179,16 @@ static int maybe_start_dbd(char *dbdpn, struct volinfo *volinfo)
 
     time(&t);
     if (!up) {
-        /* find an empty slot */
-        for (i = 0; i < MAXVOLS; i++) {
-            if (srv[i].volinfo == NULL) {
+        /* find an empty slot (i < maxvol) or the first free slot (i == maxvol)*/
+        for (i = 0; i <= maxvol; i++) {
+            if (srv[i].volinfo == NULL && i < MAXVOLS) {
                 up = &srv[i];
                 up->volinfo = volinfo;
                 retainvolinfo(volinfo);
                 up->tm = t;
                 up->count = 0;
+                if (i == maxvol)
+                    maxvol++;
                 break;
             }
         }
@@ -524,7 +527,7 @@ int main(int argc, char *argv[])
         rqstfd = usockfd_check(srvfd, &set);
         /* Collect zombie processes and log what happened to them */
         if (sigchild) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
-            for (i = 0; i < MAXVOLS; i++) {
+            for (i = 0; i < maxvol; i++) {
                 if (srv[i].pid == pid) {
                     srv[i].pid = 0;
                     close(srv[i].control_fd);
index e8f333fbf9d0f0c38276e8ea9ad72338d6be2e54..47434759232d7dde8a511e2cf53da1b7eaf637df 100644 (file)
 #define DIRDID_ROOT_PARENT    htonl(1)  /* parent directory of root */
 #define DIRDID_ROOT           htonl(2)  /* root directory */
 
+/* struct dir.d_flags */
+#define DIRF_FSMASK       (3<<0)
+#define DIRF_NOFS         (0<<0)
+#define DIRF_AFS          (1<<0)
+#define DIRF_UFS          (1<<1)
+#define DIRF_ISFILE    (1<<3) /* it's cached file, not a directory */
+#define DIRF_OFFCNT    (1<<4) /* offsprings count is valid */
+#define DIRF_CNID         (1<<5) /* renumerate id */
+
 struct dir {
-    bstring     d_fullpath;          /* complete unix path to dir */
+    bstring     d_fullpath;          /* complete unix path to dir (or file) */
     bstring     d_m_name;            /* mac name */
     bstring     d_u_name;            /* unix name                                          */
                                      /* be careful here! if d_m_name == d_u_name, d_u_name */
                                      /* will just point to the same storage as d_m_name !! */
     ucs2_t      *d_m_name_ucs2;       /* mac name as UCS2 */
     qnode_t     *qidx_node;           /* pointer to position in queue index */
-    time_t      ctime;                /* inode ctime, used and modified by reenumeration */
-    time_t      ctime_dircache;       /* inode ctime, used and modified by dircache */
+    time_t      d_ctime;                /* inode ctime, used and modified by reenumeration */
+
     int         d_flags;              /* directory flags */
     cnid_t      d_pdid;               /* CNID of parent directory */
     cnid_t      d_did;                /* CNID of directory */
-    uint32_t    offcnt;               /* offspring count */
+    uint32_t    d_offcnt;             /* offspring count */
     uint16_t    d_vid;                /* only needed in the dircache, because
                                          we put all directories in one cache. */
+    /* Stuff used in the dircache */
+    time_t      dcache_ctime;         /* inode ctime, used and modified by dircache */
+    ino_t       dcache_ino;           /* inode number, used to detect changes in the dircache */
 };
 
 struct path {
index 528b2646bcfe2885bd2c0450b61b4429825f1082..5bdc03c3a3d671a0a6f116b77444aba2276320ae 100644 (file)
@@ -486,7 +486,8 @@ void fdset_add_fd(struct pollfd **fdsetp,
  * Remove a fd from our pollfd array
  *
  * 1. Search fd
- * 2. If we remove the last array elemnt, just decrease count
+ * 2a 
+ * 2b If we remove the last array elemnt, just decrease count
  * 3. If found move all following elements down by one
  * 4. Decrease count of used elements in array
  *
@@ -507,9 +508,15 @@ void fdset_del_fd(struct pollfd **fdsetp,
     struct pollfd *fdset = *fdsetp;
     struct polldata *polldata = *polldatap;
 
+    if (*fdset_usedp < 1)
+        return;
+
     for (int i = 0; i < *fdset_usedp; i++) {
         if (fdset[i].fd == fd) { /* 1 */
-            if (i < (*fdset_usedp - 1)) { /* 2 */
+            if (i == 0 && *fdset_usedp == 1) { /* 2a */
+                fdset[i].fd = -1;
+                memset(&polldata[i], 0, sizeof(struct polldata));
+            } else if (i < (*fdset_usedp - 1)) { /* 2b */
                 memmove(&fdset[i], &fdset[i+1], (*fdset_usedp - 1) * sizeof(struct pollfd)); /* 3 */
                 memmove(&polldata[i], &polldata[i+1], (*fdset_usedp - 1) * sizeof(struct polldata)); /* 3 */
             }
index 9fc6dd3739e148722266333b3145fe3c89bc6dc8..63b340e443aae2480964367e66a7e715b5338dac 100644 (file)
@@ -205,6 +205,17 @@ Signals that are sent to the main
 \fBafpd\fR
 process are propagated to the children, so all will be affected\&.
 .PP
+To shut down a user\'s
+\fBafpd\fR
+process it is recommended that
+\fBSIGKILL (\-9)\fR
+\fINOT\fR
+be used, except as a last resort, as this may leave the CNID database in an inconsistent state\&. The safe way to terminate an
+\fBafpd\fR
+is to send it a
+\fBSIGTERM (\-15)\fR
+signal and wait for it to die on its own\&.
+.PP
 SIGHUP
 .RS 4
 Sending a
@@ -223,7 +234,7 @@ enables
 logging for this process\&. The log is sent to fhe file
 /tmp/afpd\&.PID\&.XXXXXX\&. Sending another
 \fBSIGINT\fR
-will terminate the process\&.
+will revert to the original log settings\&.
 .RE
 .PP
 SIGUSR1
@@ -239,17 +250,6 @@ The
 \fBafpd\fR
 process will look in the message directory configured at build time for a file named message\&.pid\&. For each one found, a the contents will be sent as a message to the associated AFP client\&. The file is removed after the message is sent\&. This should only be sent to a child
 \fBafpd\fR\&.
-.sp
-To shut down a user\'s
-\fBafpd\fR
-process it is recommended that
-\fBSIGKILL (\-9)\fR
-\fINOT\fR
-be used, except as a last resort, as this may leave the CNID database in an inconsistent state\&. The safe way to terminate an
-\fBafpd\fR
-is to send it a
-\fBSIGTERM (\-15)\fR
-signal and wait for it to die on its own\&.
 .RE
 .SH "FILES"
 .PP