]> arthur.barton.de Git - netatalk.git/commitdiff
Merge sf/master
authorFrank Lahm <franklahm@googlemail.com>
Mon, 6 Jun 2011 07:40:59 +0000 (09:40 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Mon, 6 Jun 2011 07:40:59 +0000 (09:40 +0200)
81 files changed:
NEWS
VERSION
bin/ad/ad.h
bin/ad/ad_cp.c
bin/misc/uuidtest.c
configure.in
contrib/misc/make-casetable.pl
etc/afpd/Makefile.am
etc/afpd/acls.c
etc/afpd/afp_config.c
etc/afpd/afp_config.h
etc/afpd/afp_dsi.c
etc/afpd/afp_options.c
etc/afpd/afp_util.c
etc/afpd/appl.c
etc/afpd/auth.c
etc/afpd/auth.h
etc/afpd/catsearch.c
etc/afpd/desktop.c
etc/afpd/desktop.h
etc/afpd/dircache.c
etc/afpd/dircache.h
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/enumerate.c
etc/afpd/extattrs.c
etc/afpd/fce_api.c
etc/afpd/fce_util.c
etc/afpd/file.c
etc/afpd/file.h
etc/afpd/filedir.c
etc/afpd/filedir.h
etc/afpd/fork.c
etc/afpd/gettok.c
etc/afpd/globals.h [deleted file]
etc/afpd/icon.h
etc/afpd/main.c
etc/afpd/mangle.h
etc/afpd/messages.c
etc/afpd/misc.h
etc/afpd/ofork.c
etc/afpd/status.c
etc/afpd/status.h
etc/afpd/switch.c
etc/afpd/uam.c
etc/afpd/uam_auth.h
etc/afpd/volume.c
etc/afpd/volume.h
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.h
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c
etc/uams/uams_dhx2_pam.c
include/atalk/Makefile.am
include/atalk/directory.h
include/atalk/dsi.h
include/atalk/globals.h [new file with mode: 0644]
include/atalk/paths.h
include/atalk/server_child.h
include/atalk/server_ipc.h
include/atalk/uam.h
include/atalk/util.h
include/atalk/uuid.h
include/atalk/volume.h
libatalk/acl/cache.c
libatalk/acl/cache.h
libatalk/acl/uuid.c
libatalk/cnid/dbd/cnid_dbd.c
libatalk/dsi/dsi_getsess.c
libatalk/dsi/dsi_stream.c
libatalk/unicode/utf16_case.c
libatalk/util/logger.c
libatalk/util/server_child.c
libatalk/util/server_ipc.c
libatalk/util/socket.c
man/man5/AppleVolumes.default.5.tmpl
man/man8/afpd.8.tmpl

diff --git a/NEWS b/NEWS
index 20c32f55c08998c28517ec1ee9963e59d5db96be..d4df9e7a64f22c91b30243397ed4d3f099a98d86 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,24 @@
+Changes in 2.2
+==============
+
+* NEW: afpd: new volume option "nonetids"
+* NEW: afpd: ACL access check caching
 * NEW: afpd: FCE event notifications
 * NEW: afpd: new option "-mimicmodel" for specifying Bonjour model registration
+* 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
+* UPD: afpd: use internal function instead of popening du -sh in order to
+       calculate the used size of a volume for option "volsizelimit"
+* UPD: afpd: Add negative UUID caching, enhance local UUID handling
+* 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
 ===================
diff --git a/VERSION b/VERSION
index 4b92f18f6f96dfbc2b7957211686ba241ab46e87..e8159ab75245c6a59e23771c7b8f5142c57f2fcc 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2-beta4
\ No newline at end of file
+2.2-rc1
\ No newline at end of file
index 9f8fd4b5ae0dcb3692751d6d480cf71ca0fc17a0..ee22654c42fbe55351e48d235464e3a6fcdf1928 100644 (file)
@@ -15,7 +15,9 @@
 #ifndef AD_H
 #define AD_H
 
-#define _XOPEN_SOURCE 600
+#if !defined(__FreeBSD__)
+# define _XOPEN_SOURCE 600
+#endif
 
 #include <sys/types.h>
 #include <sys/stat.h>
index ac0a737a0b5a12cfcc3477ace70f282ba7f5a3e4..720ea6d3175027bc5d62480cbd31a58b61f2bcd3 100644 (file)
@@ -841,8 +841,14 @@ static int setfile(const struct stat *fs, int fd)
     islink = !fdval && S_ISLNK(fs->st_mode);
     mode = fs->st_mode & (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO);
 
+#if defined(__FreeBSD__)
+    TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atimespec);
+    TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtimespec);
+#else
     TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim);
     TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim);
+#endif
+
     if (utimes(to.p_path, tv)) {
         SLOG("utimes: %s", to.p_path);
         rval = 1;
index b12585ee9b7e57a2a7e57fdff81330d7e3de218f..0efc3318c6a45d0fe25c85b3cdf5016b9c548789 100644 (file)
@@ -123,15 +123,15 @@ int main( int argc, char **argv)
             ret = getnamefromuuid( uuid, &name, &type);
             if (ret == 0) {
                 switch (type) {
-                case UUID_LOCAL:
-                    printf("local UUID: %s\n", optarg);
-                    break;
                 case UUID_USER:
                     printf("UUID: %s ==> User: %s\n", optarg, name);
                     break;
                 case UUID_GROUP:
                     printf("UUID: %s ==> Group: %s\n", optarg, name);
                     break;
+                default:
+                    printf("???: %s\n", optarg);
+                    break;
                 }
                 free(name);
             } else {
index a0726f2f44e55b86737b56ab21dba35a3a7bb8aa..28df29fdc6db1ad0e1965d237250479dae19a6f9 100644 (file)
@@ -1075,13 +1075,27 @@ if test x"$with_acl_support" = x"yes" ; then
                                        acl_perm_t perm;
                                        return acl_get_perm_np(permset_d, perm);
                                ],
-                               [samba_cv_HAVE_ACL_GET_PERM_NP=yes],
-                               [samba_cv_HAVE_ACL_GET_PERM_NP=no])
+                               [netatalk_cv_HAVE_ACL_GET_PERM_NP=yes],
+                               [netatalk_cv_HAVE_ACL_GET_PERM_NP=no])
                                LIBS=$acl_LIBS
                        ])
                        if test x"netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
                                AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
                        fi
+
+                       AC_CACHE_CHECK([for acl_from_mode], netatalk_cv_HAVE_ACL_FROM_MODE,[
+                               acl_LIBS=$LIBS
+                               LIBS="$LIBS $ACL_LIBS"
+                AC_CHECK_FUNCS(acl_from_mode,
+                               [netatalk_cv_HAVE_ACL_FROM_MODE=yes],
+                               [netatalk_cv_HAVE_ACL_FROM_MODE=no])
+                               LIBS=$acl_LIBS
+                       ])
+                       if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then
+                               AC_DEFINE(HAVE_ACL_FROM_MODE,1,[Whether acl_from_mode() is available])
+                       fi
+
+
                else
                        AC_MSG_NOTICE(ACL support is not avaliable)
                        AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available])
@@ -1091,6 +1105,7 @@ if test x"$with_acl_support" = x"yes" ; then
 fi
 
 if test x"$with_acl_support" = x"yes" ; then
+   AC_CHECK_HEADERS([acl/libacl.h])
     AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available])
     AC_SUBST(ACL_LIBS)
 fi
index 68bcfc9baa8c983e176fda8d7702709e2f47a94a..9af15a9d5068ce89402533d64a2682e530f78e12 100755 (executable)
@@ -104,7 +104,7 @@ printf (CSOURCE "%s is got from\n", $ARGV[0]);
 printf (CSOURCE "http\:\/\/www.unicode.org\/Public\/UNIDATA\/UnicodeData.txt\n");
 printf (CSOURCE "\*\/\n");
 printf (CSOURCE "\n");
-printf (CSOURCE "\#include \<netatalk\/endian.h\>\n");
+printf (CSOURCE "\#include \<stdint.h\>\n");
 printf (CSOURCE "\#include \<atalk\/unicode.h\>\n");
 printf (CSOURCE "\#include \"%s\"\n", $ARGV[1]);
 printf (CSOURCE "\n");
@@ -231,7 +231,7 @@ sub make_array{
             $char_start = ($block_start -1)* 64;
             $char_end = ($block_end * 64) -1;
 
-            printf(CHEADER "static const u\_int16\_t %s\_table\_%d\[%d\] \= \{\n",
+            printf(CHEADER "static const uint16\_t %s\_table\_%d\[%d\] \= \{\n",
                    $_[0], $table_no, $char_end - $char_start +1);
 
             for ($char = $char_start ; $char <= $char_end ; $char++) {
@@ -270,7 +270,7 @@ sub make_array{
     printf(CSOURCE "\/*******************************************************************\n");
     printf(CSOURCE " Convert a surrogate pair to %s case.\n", $_[0]);
     printf(CSOURCE "*******************************************************************\/\n");
-    printf(CSOURCE "u\_int32\_t to%s\_sp\(u\_int32\_t val\)\n", $_[0]);
+    printf(CSOURCE "uint32\_t to%s\_sp\(uint32\_t val\)\n", $_[0]);
     printf(CSOURCE "{\n");
 
     $table_no = 1;
@@ -291,7 +291,7 @@ sub make_array{
             $char_start = ($block_start -1)* 64;
             $char_end = ($block_end * 64) -1;
 
-            printf(CHEADER "static const u\_int32\_t %s\_table\_sp\_%d\[%d\] \= \{\n",
+            printf(CHEADER "static const uint32\_t %s\_table\_sp\_%d\[%d\] \= \{\n",
                    $_[0], $table_no, $char_end - $char_start +1);
 
             for ($char = $char_start ; $char <= $char_end ; $char++) {
index 35580d93e599f84943f7fc8beda2baf7952de336..bcc8a17d460d32511dd029c742c472bcde882d8a 100644 (file)
@@ -70,8 +70,8 @@ afpd_SOURCES += acls.c
 endif
 
 
-noinst_HEADERS = auth.h afp_config.h desktop.h directory.h fce_api_internal.h file.h \
-        filedir.h fork.h globals.h icon.h mangle.h misc.h status.h switch.h \
+noinst_HEADERS = auth.h afp_config.h desktop.h directory.h file.h \
+        filedir.h fork.h icon.h mangle.h misc.h status.h switch.h \
         uam_auth.h uid.h unix.h volume.h hash.h acls.h acl_mappings.h extattrs.h \
         dircache.h afp_zeroconf.h afp_avahi.h
 
index 43e91042f10e0ee3850a2d3cc312b7b51ee7a038..c87ef9a0079cb95f44f1be366d9aad8340e1397e 100644 (file)
@@ -28,6 +28,8 @@
 #endif
 #ifdef HAVE_POSIX_ACLS
 #include <sys/acl.h>
+#endif
+#ifdef HAVE_ACL_LIBACL_H
 #include <acl/libacl.h>
 #endif
 
@@ -268,11 +270,6 @@ static int map_aces_darwin_to_solaris(darwin_ace_t *darwin_aces,
         /* uid/gid first */
         EC_ZERO(getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype));
         switch (uuidtype) {
-        case UUID_LOCAL:
-            free(name);
-            name = NULL;
-            darwin_aces++;
-            continue;
         case UUID_USER:
             EC_NULL_LOG(pwd = getpwnam(name));
             nfsv4_aces->a_who = pwd->pw_uid;
@@ -282,6 +279,9 @@ static int map_aces_darwin_to_solaris(darwin_ace_t *darwin_aces,
             nfsv4_aces->a_who = (uid_t)(grp->gr_gid);
             nfsv4_ace_flags |= ACE_IDENTIFIER_GROUP;
             break;
+        default:
+            LOG(log_error, logtype_afpd, "map_aces_darwin_to_solaris: unkown uuidtype");
+            EC_FAIL;
         }
         free(name);
         name = NULL;
@@ -309,8 +309,12 @@ static int map_aces_darwin_to_solaris(darwin_ace_t *darwin_aces,
                 nfsv4_ace_rights |= darwin_to_nfsv4_rights[i].to;
         }
 
-        LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE flags: Darwin:%08x -> NFSv4:%04x", darwin_ace_flags, nfsv4_ace_flags);
-        LOG(log_debug9, logtype_afpd, "map_aces_darwin_to_solaris: ACE rights: Darwin:%08x -> NFSv4:%08x", darwin_ace_rights, nfsv4_ace_rights);
+        LOG(log_debug9, logtype_afpd,
+            "map_aces_darwin_to_solaris: ACE flags: Darwin:%08x -> NFSv4:%04x",
+            darwin_ace_flags, nfsv4_ace_flags);
+        LOG(log_debug9, logtype_afpd,
+            "map_aces_darwin_to_solaris: ACE rights: Darwin:%08x -> NFSv4:%08x",
+            darwin_ace_rights, nfsv4_ace_rights);
 
         nfsv4_aces->a_flags = nfsv4_ace_flags;
         nfsv4_aces->a_access_mask = nfsv4_ace_rights;
@@ -342,12 +346,20 @@ static uint32_t posix_permset_to_darwin_rights(acl_entry_t e, int is_dir)
 
     EC_ZERO_LOG(acl_get_permset(e, &permset));
 
+#ifdef HAVE_ACL_GET_PERM_NP
+    if (acl_get_perm_np(permset, ACL_READ))
+#else
     if (acl_get_perm(permset, ACL_READ))
+#endif
         rights = DARWIN_ACE_READ_DATA
             | DARWIN_ACE_READ_EXTATTRIBUTES
             | DARWIN_ACE_READ_ATTRIBUTES
             | DARWIN_ACE_READ_SECURITY;
+#ifdef HAVE_ACL_GET_PERM_NP
+    if (acl_get_perm_np(permset, ACL_WRITE)) {
+#else
     if (acl_get_perm(permset, ACL_WRITE)) {
+#endif
         rights |= DARWIN_ACE_WRITE_DATA
             | DARWIN_ACE_APPEND_DATA
             | DARWIN_ACE_WRITE_EXTATTRIBUTES
@@ -355,7 +367,11 @@ static uint32_t posix_permset_to_darwin_rights(acl_entry_t e, int is_dir)
         if (is_dir)
             rights |= DARWIN_ACE_DELETE_CHILD;
     }
+#ifdef HAVE_ACL_GET_PERM_NP
+    if (acl_get_perm_np(permset, ACL_EXECUTE))
+#else
     if (acl_get_perm(permset, ACL_EXECUTE))
+#endif
         rights |= DARWIN_ACE_EXECUTE;
 
 EC_CLEANUP:
@@ -624,10 +640,6 @@ static int map_aces_darwin_to_posix(const darwin_ace_t *darwin_aces,
          /* uid/gid */
         EC_ZERO_LOG(getnamefromuuid(darwin_aces->darwin_ace_uuid, &name, &uuidtype));
         switch (uuidtype) {
-        case UUID_LOCAL:
-            free(name);
-            name = NULL;
-            continue;
         case UUID_USER:
             EC_NULL_LOG(pwd = getpwnam(name));
             tag = ACL_USER;
@@ -640,6 +652,8 @@ static int map_aces_darwin_to_posix(const darwin_ace_t *darwin_aces,
             id = (uid_t)(grp->gr_gid);
             LOG(log_debug, logtype_afpd, "map_ace: name: %s, gid: %u", name, id);
             break;
+        default:
+            continue;
         }
         free(name);
         name = NULL;
@@ -1043,8 +1057,11 @@ static int set_acl(const struct vol *vol,
     /* for files def_acl will be NULL */
 
     /* create access acl from mode */
+#ifdef HAVE_ACL_FROM_MODE
     EC_NULL_LOG_ERR(acc_acl = acl_from_mode(st.st_mode), AFPERR_MISC);
-
+#else
+#error "Missing acl_from_mode() replacement"
+#endif
     /* adds the clients aces */
     EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &def_acl, &acc_acl, ace_count), AFPERR_MISC);
 
@@ -1078,7 +1095,7 @@ EC_CLEANUP:
  * Note: this gets called frequently and is a good place for optimizations !
  *
  * @param vol              (r) volume
- * @param dir              (r) directory
+ * @param dir              (rw) directory
  * @param path             (r) path to filesystem object
  * @param uuid             (r) UUID of user
  * @param requested_rights (r) requested Darwin ACE
@@ -1086,7 +1103,7 @@ EC_CLEANUP:
  * @returns                    AFP result code
 */
 static int check_acl_access(const struct vol *vol,
-                            const struct dir *dir,
+                            struct dir *dir,
                             const char *path,
                             const uuidp_t uuid,
                             uint32_t requested_rights)
@@ -1111,57 +1128,60 @@ static int check_acl_access(const struct vol *vol,
         LOG(log_warning, logtype_afpd, "check_access: afp_access not supported for groups");
         EC_STATUS(AFPERR_MISC);
         goto EC_CLEANUP;
-
-    case UUID_LOCAL:
-        LOG(log_warning, logtype_afpd, "check_access: local UUID");
+    default:
         EC_STATUS(AFPERR_MISC);
         goto EC_CLEANUP;
     }
 
+    if ((strcmp(path, ".") == 0) && (dir->d_rights_cache != 0xffffffff)) {
+        /* its a dir and the cache value is valid */
+        allowed_rights = dir->d_rights_cache;
+        LOG(log_debug, logtype_afpd, "allowed rights from dircache: 0x%08x", allowed_rights);
+    } else {
 #ifdef HAVE_SOLARIS_ACLS
-    EC_ZERO_LOG(solaris_acl_rights(path, &st, &allowed_rights));
+        EC_ZERO_LOG(solaris_acl_rights(path, &st, &allowed_rights));
 #endif
 #ifdef HAVE_POSIX_ACLS
-    EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights));
+        EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights));
 #endif
+        /*
+         * The DARWIN_ACE_DELETE right might implicitly result from write acces to the parent
+         * directory. As it seems the 10.6 AFP client is puzzled when this right is not
+         * allowed where a delete would succeed because the parent dir gives write perms.
+         * So we check the parent dir for write access and set the right accordingly.
+         * Currentyl acl2ownermode calls us with dir = NULL, because it doesn't make sense
+         * there to do this extra check -- afaict.
+         */
+        if (vol && dir && (requested_rights & DARWIN_ACE_DELETE)) {
+            int i;
+            uint32_t parent_rights = 0;
+
+            if (dir->d_did == DIRDID_ROOT_PARENT) {
+                /* use volume path */
+                EC_NULL_LOG_ERR(parent = bfromcstr(vol->v_path), AFPERR_MISC);
+            } else {
+                /* build path for parent */
+                EC_NULL_LOG_ERR(parent = bstrcpy(dir->d_fullpath), AFPERR_MISC);
+                EC_ZERO_LOG_ERR(bconchar(parent, '/'), AFPERR_MISC);
+                EC_ZERO_LOG_ERR(bcatcstr(parent, path), AFPERR_MISC);
+                EC_NEG1_LOG_ERR(i = bstrrchr(parent, '/'), AFPERR_MISC);
+                EC_ZERO_LOG_ERR(binsertch(parent, i, 1, 0), AFPERR_MISC);
+            }
 
-    LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights);
-
-    /*
-     * The DARWIN_ACE_DELETE right might implicitly result from write acces to the parent
-     * directory. As it seems the 10.6 AFP client is puzzled when this right is not
-     * allowed where a delete would succeed because the parent dir gives write perms.
-     * So we check the parent dir for write access and set the right accordingly.
-     * Currentyl acl2ownermode calls us with dir = NULL, because it doesn't make sense
-     * there to do this extra check -- afaict.
-     */
-    if (vol && dir && (requested_rights & DARWIN_ACE_DELETE)) {
-        int i;
-        uint32_t parent_rights = 0;
-
-        if (dir->d_did == DIRDID_ROOT_PARENT) {
-            /* use volume path */
-            EC_NULL_LOG_ERR(parent = bfromcstr(vol->v_path), AFPERR_MISC);
-        } else {
-            /* build path for parent */
-            EC_NULL_LOG_ERR(parent = bstrcpy(dir->d_fullpath), AFPERR_MISC);
-            EC_ZERO_LOG_ERR(bconchar(parent, '/'), AFPERR_MISC);
-            EC_ZERO_LOG_ERR(bcatcstr(parent, path), AFPERR_MISC);
-            EC_NEG1_LOG_ERR(i = bstrrchr(parent, '/'), AFPERR_MISC);
-            EC_ZERO_LOG_ERR(binsertch(parent, i, 1, 0), AFPERR_MISC);
-        }
-
-        LOG(log_debug, logtype_afpd,"parent: %s", cfrombstr(parent));
-        EC_ZERO_LOG_ERR(lstat(cfrombstr(parent), &st), AFPERR_MISC);
+            LOG(log_debug, logtype_afpd,"parent: %s", cfrombstr(parent));
+            EC_ZERO_LOG_ERR(lstat(cfrombstr(parent), &st), AFPERR_MISC);
 
 #ifdef HAVE_SOLARIS_ACLS
-        EC_ZERO_LOG(solaris_acl_rights(cfrombstr(parent), &st, &parent_rights));
+            EC_ZERO_LOG(solaris_acl_rights(cfrombstr(parent), &st, &parent_rights));
 #endif
 #ifdef HAVE_POSIX_ACLS
-    EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights));
+            EC_ZERO_LOG(posix_acl_rights(path, &st, &allowed_rights));
 #endif
-        if (parent_rights & (DARWIN_ACE_WRITE_DATA | DARWIN_ACE_DELETE_CHILD))
-            allowed_rights |= DARWIN_ACE_DELETE; /* man, that was a lot of work! */
+            if (parent_rights & (DARWIN_ACE_WRITE_DATA | DARWIN_ACE_DELETE_CHILD))
+                allowed_rights |= DARWIN_ACE_DELETE; /* man, that was a lot of work! */
+        }
+        LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights);
+        dir->d_rights_cache = allowed_rights;
     }
 
     if ((requested_rights & allowed_rights) != requested_rights) {
index 7f5fd1f1fc9e32d10f3adc16c85da1cfdfdae4b6..291148c3458eeeca77432d751f5813128620d198 100644 (file)
@@ -36,7 +36,7 @@
 #include <atalk/ldapconfig.h>
 #endif
 
-#include "globals.h"
+#include <atalk/globals.h>
 #include "afp_config.h"
 #include "uam_auth.h"
 #include "status.h"
index ba800ce3aa45c5b547b296ea0e650ebf9a48d6f7..7d5c482a16951a17c4e87923a099b8d5069b0c14 100644 (file)
@@ -11,7 +11,7 @@
 
 #include <atalk/server_child.h>
 #include <atalk/atp.h>
-#include "globals.h"
+#include <atalk/globals.h>
 
 typedef struct AFPConfig {
     AFPObj obj;
index 0a735ea4d2ae1a0946b63d0ece3cdea8756547f8..0e9a21640ef303a656bdb0b0851eac686f44aa14 100644 (file)
 #endif /* HAVE_SYS_STAT_H */
 #include <netinet/in.h>
 #include <arpa/inet.h>
-#include <atalk/logger.h>
 #include <setjmp.h>
+#include <time.h>
 
+#include <atalk/logger.h>
 #include <atalk/dsi.h>
 #include <atalk/compat.h>
 #include <atalk/util.h>
+#include <atalk/uuid.h>
+#include <atalk/paths.h>
+#include <atalk/server_ipc.h>
+#include <atalk/fce_api.h>
 
-#include "globals.h"
+#include <atalk/globals.h>
 #include "switch.h"
 #include "auth.h"
 #include "fork.h"
@@ -129,6 +134,25 @@ static void afp_dsi_die(int sig)
     }
 }
 
+/* SIGQUIT handler */
+static void ipc_reconnect_handler(int sig _U_)
+{
+    DSI *dsi = (DSI *)AFPobj->handle;
+
+    if (reconnect_ipc(AFPobj) != 0) {
+        LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC reconnect");
+        afp_dsi_close(AFPobj);
+        exit(EXITERR_SYS);        
+    }
+
+    if (ipc_child_write(AFPobj->ipc_fd, IPC_GETSESSION, AFPobj->sinfo.clientid_len, AFPobj->sinfo.clientid) != 0) {
+        LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC ID resend");
+        afp_dsi_close(AFPobj);
+        exit(EXITERR_SYS);        
+    }
+    LOG(log_note, logtype_afpd, "ipc_reconnect_handler: IPC reconnect done");
+}
+
 /* SIGURG handler (primary reconnect) */
 static void afp_dsi_transfer_session(int sig _U_)
 {
@@ -291,6 +315,10 @@ static void alarm_handler(int sig _U_)
     } 
 
     if (dsi->flags & DSI_DISCONNECTED) {
+        if (geteuid() == 0) {
+            LOG(log_note, logtype_afpd, "afp_alarm: unauthenticated user, connection problem");
+            afp_dsi_die(EXITERR_CLNT);
+        }
         if (dsi->tickle > AFPobj->options.disconnected) {
             LOG(log_error, logtype_afpd, "afp_alarm: reconnect timer expired, goodbye");
             afp_dsi_die(EXITERR_CLNT);
@@ -301,8 +329,8 @@ static void alarm_handler(int sig _U_)
     /* if we're in the midst of processing something, don't die. */        
     if ( !(dsi->flags & DSI_RUNNING) && (dsi->tickle >= AFPobj->options.timeout)) {
         LOG(log_error, logtype_afpd, "afp_alarm: child timed out, entering disconnected state");
-        dsi->proto_close(dsi);
-        dsi->flags |= DSI_DISCONNECTED;
+        if (dsi_disconnect(dsi) != 0)
+            afp_dsi_die(EXITERR_CLNT);
         return;
     }
 
@@ -310,9 +338,13 @@ static void alarm_handler(int sig _U_)
         LOG(log_debug, logtype_afpd, "afp_alarm: sending DSI tickle");
         err = dsi_tickle(AFPobj->handle);
     if (err <= 0) {
+        if (geteuid() == 0) {
+            LOG(log_note, logtype_afpd, "afp_alarm: unauthenticated user, connection problem");
+            afp_dsi_die(EXITERR_CLNT);
+        }
         LOG(log_error, logtype_afpd, "afp_alarm: connection problem, entering disconnected state");
-        dsi->proto_close(dsi);
-        dsi->flags |= DSI_DISCONNECTED;
+        if (dsi_disconnect(dsi) != 0)
+            afp_dsi_die(EXITERR_CLNT);
     }
 }
 
@@ -352,22 +384,18 @@ void afp_over_dsi(AFPObj *obj)
     struct sigaction action;
 
     AFPobj = obj;
+    dsi->AFPobj = obj;
     obj->exit = afp_dsi_die;
     obj->reply = (int (*)()) dsi_cmdreply;
     obj->attention = (int (*)(void *, AFPUserBytes)) dsi_attention;
     dsi->tickle = 0;
 
     memset(&action, 0, sizeof(action));
+    sigfillset(&action.sa_mask);
+    action.sa_flags = SA_RESTART;
 
     /* install SIGHUP */
     action.sa_handler = afp_dsi_reload;
-    sigemptyset( &action.sa_mask );
-    sigaddset(&action.sa_mask, SIGALRM);
-    sigaddset(&action.sa_mask, SIGTERM);
-    sigaddset(&action.sa_mask, SIGUSR1);
-    sigaddset(&action.sa_mask, SIGINT);
-    sigaddset(&action.sa_mask, SIGUSR2);
-    action.sa_flags = SA_RESTART;
     if ( sigaction( SIGHUP, &action, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
         afp_dsi_die(EXITERR_SYS);
@@ -375,13 +403,6 @@ void afp_over_dsi(AFPObj *obj)
 
     /* install SIGURG */
     action.sa_handler = afp_dsi_transfer_session;
-    sigemptyset( &action.sa_mask );
-    sigaddset(&action.sa_mask, SIGALRM);
-    sigaddset(&action.sa_mask, SIGTERM);
-    sigaddset(&action.sa_mask, SIGUSR1);
-    sigaddset(&action.sa_mask, SIGINT);
-    sigaddset(&action.sa_mask, SIGUSR2);
-    action.sa_flags = SA_RESTART;
     if ( sigaction( SIGURG, &action, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
         afp_dsi_die(EXITERR_SYS);
@@ -389,27 +410,20 @@ void afp_over_dsi(AFPObj *obj)
 
     /* install SIGTERM */
     action.sa_handler = afp_dsi_die;
-    sigemptyset( &action.sa_mask );
-    sigaddset(&action.sa_mask, SIGALRM);
-    sigaddset(&action.sa_mask, SIGHUP);
-    sigaddset(&action.sa_mask, SIGUSR1);
-    sigaddset(&action.sa_mask, SIGINT);
-    sigaddset(&action.sa_mask, SIGUSR2);
-    action.sa_flags = SA_RESTART;
     if ( sigaction( SIGTERM, &action, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
         afp_dsi_die(EXITERR_SYS);
     }
 
-    /* Added for server message support */
+    /* install SIGQUIT */
+    action.sa_handler = ipc_reconnect_handler;
+    if ( sigaction(SIGQUIT, &action, NULL ) < 0 ) {
+        LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
+        afp_dsi_die(EXITERR_SYS);
+    }
+
+    /* SIGUSR2 - server message support */
     action.sa_handler = afp_dsi_getmesg;
-    sigemptyset( &action.sa_mask );
-    sigaddset(&action.sa_mask, SIGALRM);
-    sigaddset(&action.sa_mask, SIGTERM);
-    sigaddset(&action.sa_mask, SIGUSR1);
-    sigaddset(&action.sa_mask, SIGHUP);
-    sigaddset(&action.sa_mask, SIGINT);
-    action.sa_flags = SA_RESTART;
     if ( sigaction( SIGUSR2, &action, NULL) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
         afp_dsi_die(EXITERR_SYS);
@@ -417,12 +431,6 @@ void afp_over_dsi(AFPObj *obj)
 
     /*  SIGUSR1 - set down in 5 minutes  */
     action.sa_handler = afp_dsi_timedown;
-    sigemptyset( &action.sa_mask );
-    sigaddset(&action.sa_mask, SIGALRM);
-    sigaddset(&action.sa_mask, SIGHUP);
-    sigaddset(&action.sa_mask, SIGTERM);
-    sigaddset(&action.sa_mask, SIGINT);
-    sigaddset(&action.sa_mask, SIGUSR2);
     action.sa_flags = SA_RESTART;
     if ( sigaction( SIGUSR1, &action, NULL) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
@@ -431,23 +439,14 @@ void afp_over_dsi(AFPObj *obj)
 
     /*  SIGINT - enable max_debug LOGging to /tmp/afpd.PID.XXXXXX */
     action.sa_handler = afp_dsi_debug;
-    sigfillset( &action.sa_mask );
-    action.sa_flags = SA_RESTART;
     if ( sigaction( SIGINT, &action, NULL) < 0 ) {
         LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
         afp_dsi_die(EXITERR_SYS);
     }
 
 #ifndef DEBUGGING
-    /* tickle handler */
+    /* SIGALRM - tickle handler */
     action.sa_handler = alarm_handler;
-    sigemptyset(&action.sa_mask);
-    sigaddset(&action.sa_mask, SIGHUP);
-    sigaddset(&action.sa_mask, SIGTERM);
-    sigaddset(&action.sa_mask, SIGUSR1);
-    sigaddset(&action.sa_mask, SIGINT);
-    sigaddset(&action.sa_mask, SIGUSR2);
-    action.sa_flags = SA_RESTART;
     if ((sigaction(SIGALRM, &action, NULL) < 0) ||
             (setitimer(ITIMER_REAL, &dsi->timer, NULL) < 0)) {
         afp_dsi_die(EXITERR_SYS);
@@ -493,15 +492,25 @@ void afp_over_dsi(AFPObj *obj)
                 dsi->flags &= ~DSI_RECONSOCKET;
                 continue;
             }
-            /* Some error on the client connection, enter disconnected state */
-            dsi->flags |= DSI_DISCONNECTED;
 
             /* the client sometimes logs out (afp_logout) but doesn't close the DSI session */
             if (dsi->flags & DSI_AFP_LOGGED_OUT) {
+                LOG(log_note, logtype_afpd, "afp_over_dsi: client logged out, terminating DSI session");
                 afp_dsi_close(obj);
                 exit(0);
             }
 
+            /*  got ECONNRESET in read from client => exit*/
+            if (dsi->flags & DSI_GOT_ECONNRESET) {
+                LOG(log_note, logtype_afpd, "afp_over_dsi: client connection reset");
+                afp_dsi_close(obj);
+                exit(0);
+            }
+
+            /* Some error on the client connection, enter disconnected state */
+            if (dsi_disconnect(dsi) != 0)
+                afp_dsi_die(EXITERR_CLNT);
+
             pause(); /* gets interrupted by SIGALARM or SIGURG tickle */
             continue; /* continue receiving until disconnect timer expires
                        * or a primary reconnect succeeds  */
@@ -516,8 +525,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 */
@@ -525,6 +532,9 @@ void afp_over_dsi(AFPObj *obj)
             static int debugging = 0;
             debug_request = 0;
 
+            dircache_dump();
+            uuidcache_dump();
+
             if (debugging) {
                 if (obj->options.logconfig)
                     setuplog(obj->options.logconfig);
@@ -625,7 +635,8 @@ void afp_over_dsi(AFPObj *obj)
 
             if (!dsi_cmdreply(dsi, err)) {
                 LOG(log_error, logtype_afpd, "dsi_cmdreply(%d): %s", dsi->socket, strerror(errno) );
-                dsi->flags |= DSI_DISCONNECTED;
+                if (dsi_disconnect(dsi) != 0)
+                    afp_dsi_die(EXITERR_CLNT);
             }
             break;
 
@@ -658,7 +669,8 @@ void afp_over_dsi(AFPObj *obj)
 
             if (!dsi_wrtreply(dsi, err)) {
                 LOG(log_error, logtype_afpd, "dsi_wrtreply: %s", strerror(errno) );
-                dsi->flags |= DSI_DISCONNECTED;
+                if (dsi_disconnect(dsi) != 0)
+                    afp_dsi_die(EXITERR_CLNT);
             }
             break;
 
@@ -675,6 +687,8 @@ void afp_over_dsi(AFPObj *obj)
             break;
         }
         pending_request(dsi);
+
+        vol_fce_tm_event();
     }
 
     /* error */
index 3ad83fe26d19d1b872ef05b7bf78413ed82aa02b..b79bc8d1f443329bb220f5dbbf408e60e1e390b2 100644 (file)
@@ -34,9 +34,9 @@
 #include <atalk/paths.h>
 #include <atalk/util.h>
 #include <atalk/compat.h>
+#include <atalk/globals.h>
 #include <atalk/fce_api.h>
 
-#include "globals.h"
 #include "status.h"
 #include "auth.h"
 #include "dircache.h"
@@ -354,8 +354,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 7cf78ed211c3b7342e410f972507ab214d474a27..a8282c22b3fb38e57a4ddb94af1e529004a7022f 100644 (file)
@@ -15,7 +15,7 @@
 #endif /* HAVE_CONFIG_H */
 
 #include <atalk/afp.h>
-#include "globals.h"
+#include <atalk/globals.h>
 
 const char *AfpNum2name(int num)
 {
index fe9ff250336214d410a32bee946578865d490fd2..51b64ef283b97d48e3ef826fd25d20a6c3b7a7ed 100644 (file)
@@ -22,9 +22,9 @@
 #include <atalk/afp.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
+#include <atalk/globals.h>
 
 #include "volume.h"
-#include "globals.h"
 #include "directory.h"
 #include "file.h"
 #include "desktop.h"
index 566a8d0e05b1b838ddc5e2dceef29463e9c33d03..a41c624d8db739edfe5e46554aeb3fc8a7e7d1f8 100644 (file)
@@ -39,8 +39,8 @@ extern void afp_get_cmdline( int *ac, char ***av );
 #include <atalk/logger.h>
 #include <atalk/server_ipc.h>
 #include <atalk/uuid.h>
+#include <atalk/globals.h>
 
-#include "globals.h"
 #include "auth.h"
 #include "uam_auth.h"
 #include "switch.h"
@@ -594,7 +594,13 @@ int afp_getsession(
             if (ibuflen < idlen || idlen > (90-10)) {
                 return AFPERR_PARAM;
             }
-            ipc_child_write(obj->ipc_fd, IPC_GETSESSION, idlen+8, p);
+            if (!obj->sinfo.clientid) {
+                obj->sinfo.clientid = malloc(idlen + 8);
+                memcpy(obj->sinfo.clientid, p, idlen + 8);
+                obj->sinfo.clientid_len = idlen + 8;
+            }
+            if (ipc_child_write(obj->ipc_fd, IPC_GETSESSION, idlen+8, p) != 0)
+                return AFPERR_MISC;
             tklen = obj->sinfo.sessiontoken_len;
             token = obj->sinfo.sessiontoken;
         }
@@ -676,7 +682,7 @@ int afp_disconnect(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
     setitimer(ITIMER_REAL, &none, NULL);
 
     /* check for old session, possibly transfering session from here to there */
-    if (ipc_child_write(obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) == -1)
+    if (ipc_child_write(obj->ipc_fd, IPC_DISCOLDSESSION, tklen, &token) != 0)
         goto exit;
     /* write uint16_t DSI request ID */
     if (writet(obj->ipc_fd, &dsi->header.dsi_requestID, 2, 0, 2) != 2) {
index 21574c29e83f31c8a756a222df113f78dc9eb27d..d26354f38d972a58400d41bbcb2d78d47ab3e09d 100644 (file)
@@ -16,7 +16,7 @@
 #include <sys/cdefs.h>
 #endif /* HAVE_SYS_CDEFS_H */
 
-#include "globals.h"
+#include <atalk/globals.h>
 
 struct afp_versions {
     char       *av_name;
index 6a9161e2e8720743ca3cbbf4100b0980de9d34b0..a488501e6b67e3c101660b844aa218bb460a1da5 100644 (file)
 #include <atalk/util.h>
 #include <atalk/bstradd.h>
 #include <atalk/unicode.h>
+#include <atalk/globals.h>
 
 #include "desktop.h"
 #include "directory.h"
 #include "dircache.h"
 #include "file.h"
 #include "volume.h"
-#include "globals.h"
 #include "filedir.h"
 #include "fork.h"
 
@@ -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 9f105e13e13c612757386f70c342626e28fe5e77..8b6efd7e1bdac95dc73170d0ab6c0bdc4940b42c 100644 (file)
 #include <atalk/afp.h>
 #include <atalk/util.h>
 #include <atalk/logger.h>
+#include <atalk/globals.h>
 #include "volume.h"
 #include "directory.h"
 #include "fork.h"
-#include "globals.h"
 #include "desktop.h"
 #include "mangle.h"
 
index 039fa6aea77ea8ecc50f6f1cb0537bcd24ca9b57..a220a478ee7eebf19841f3c69fcb2f43217ab32f 100644 (file)
@@ -27,7 +27,7 @@
 #define AFPD_DESKTOP_H 1
 
 #include <sys/cdefs.h>
-#include "globals.h"
+#include <atalk/globals.h>
 #include "volume.h"
 
 struct savedt {
index 9907c5dd35bddabc02bbcef02d94dc07503d2975..5a702fa55bfd125f943c4ce37bf12ff4ba8524d5 100644 (file)
 #include <atalk/queue.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
+#include <atalk/globals.h>
 
 #include "dircache.h"
 #include "directory.h"
 #include "hash.h"
-#include "globals.h"
+
 
 /*
  * Directory Cache
@@ -52,8 +53,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 +289,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 +316,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 +331,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 +359,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 +394,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 +652,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 +668,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 +685,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 7b25849114d0d9c1e079ca3f77446d5ade6fce36..fe628e0c61b9fc692420bed1c87171b7d9b2f2cf 100644 (file)
@@ -29,6 +29,7 @@
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
 #include <atalk/errchk.h>
+#include <atalk/globals.h>
 #include <atalk/fce_api.h>
 
 #include "directory.h"
@@ -38,7 +39,6 @@
 #include "fork.h"
 #include "file.h"
 #include "filedir.h"
-#include "globals.h"
 #include "unix.h"
 #include "mangle.h"
 #include "hash.h"
@@ -266,7 +266,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;
 }
 
 /* --------------------- */
@@ -469,6 +469,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",
@@ -481,8 +482,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,
@@ -495,8 +495,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:
@@ -515,7 +513,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.
@@ -540,7 +538,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 */
@@ -558,18 +556,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;
@@ -591,6 +590,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;
@@ -608,7 +608,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;
@@ -623,9 +624,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;
@@ -656,7 +658,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;
@@ -681,7 +683,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;
@@ -779,8 +781,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
  *
@@ -792,7 +794,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;
 
@@ -826,7 +828,11 @@ 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;
+    dir->d_rights_cache = 0xffffffff;
     return dir;
 }
 
@@ -880,7 +886,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,
@@ -924,7 +930,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;
     }
@@ -1282,7 +1294,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 */
@@ -1432,8 +1444,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;
 }
 
@@ -1443,7 +1455,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);
 }
 
 /* ------------------------------
@@ -1479,6 +1491,17 @@ int getdirparams(const struct vol *vol,
             isad = 1;
             if (ad.ad_md->adf_flags & O_CREAT) {
                 /* We just created it */
+                if (s_path->m_name == NULL) {
+                    if ((s_path->m_name = utompath(vol,
+                                                   upath,
+                                                   dir->d_did,
+                                                   utf8_encoding())) == NULL) {
+                        LOG(log_error, logtype_afpd,
+                            "getdirparams(\"%s\"): can't assign macname",
+                            cfrombstr(dir->d_fullpath));
+                        return AFPERR_MISC;
+                    }
+                }
                 ad_setname(&ad, s_path->m_name);
                 ad_setid( &ad,
                           s_path->st.st_dev,
@@ -1582,11 +1605,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 ));
@@ -2234,7 +2257,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;
@@ -2492,9 +2515,6 @@ int afp_mapid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *r
             rbuf += sizeof( id );
             *rbuflen = 2 * sizeof( id );
             break;
-        case UUID_LOCAL:
-            free(name);
-            return (AFPERR_NOITEM);
         default:
             return AFPERR_MISC;
         }
index 79c4a0407fe3b6c1d61bb3d2208e1cc22f319d9f..e9c6a457f4344cb2865f0295d0d78885c4f096c7 100644 (file)
 #endif
 
 #include <atalk/directory.h>
+#include <atalk/globals.h>
 
-#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
@@ -109,7 +99,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..fe5a66d993746610ce45747d347abc1e409036e4 100644 (file)
 #include <atalk/util.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
+#include <atalk/globals.h>
 
 #include "desktop.h"
 #include "directory.h"
 #include "dircache.h"
 #include "volume.h"
-#include "globals.h"
 #include "file.h"
 #include "fork.h"
 #include "filedir.h"
@@ -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 649cc6a30f3044b96533412751f850acee8a10be..40298b50737ccfa62000ac1469c2e4749a4ef511 100644 (file)
@@ -28,8 +28,8 @@
 #include <atalk/afp.h>
 #include <atalk/logger.h>
 #include <atalk/ea.h>
+#include <atalk/globals.h>
 
-#include "globals.h"
 #include "volume.h"
 #include "desktop.h"
 #include "directory.h"
index 2b00142f85e09d12471e6c21c23bfeef4f72925b..b2dead294445229bb3984c6018fd22a62744879d 100755 (executable)
 #include <atalk/cnid.h>\r
 #include <atalk/unix.h>\r
 #include <atalk/fce_api.h>\r
+#include <atalk/globals.h>\r
 \r
 #include "fork.h"\r
 #include "file.h"\r
-#include "globals.h"\r
 #include "directory.h"\r
 #include "desktop.h"\r
 #include "volume.h"\r
index 6340110eeb3f3363c885703ee06b70d48e33e567..6959509df027e3de6825faedb838c74bd7f0ce1c 100755 (executable)
 #include <atalk/cnid.h>\r
 #include <atalk/unix.h>\r
 #include <atalk/fce_api.h>\r
+#include <atalk/globals.h>\r
 \r
 #include "fork.h"\r
 #include "file.h"\r
-#include "globals.h"\r
 #include "directory.h"\r
 #include "desktop.h"\r
 #include "volume.h"\r
index c165eb93f37680a0d6c10290d955e61c01d9c2b4..ec85f37a52e0dfdefb79335b05e447bb970138ea 100644 (file)
@@ -37,6 +37,7 @@ char *strchr (), *strrchr ();
 #include <atalk/util.h>
 #include <atalk/cnid.h>
 #include <atalk/unix.h>
+#include <atalk/globals.h>
 #include <atalk/fce_api.h>
 
 #include "directory.h"
@@ -46,7 +47,6 @@ char *strchr (), *strrchr ();
 #include "fork.h"
 #include "file.h"
 #include "filedir.h"
-#include "globals.h"
 #include "unix.h"
 
 /* the format for the finderinfo fields (from IM: Toolbox Essentials):
@@ -327,9 +327,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);
@@ -342,18 +343,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 {
@@ -769,7 +778,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
     ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
 
 createfile_done:
-    curdir->offcnt++;
+    curdir->d_offcnt++;
 
 #ifdef DROPKLUDGE
     if (vol->v_flags & AFPVOL_DROPBOX) {
@@ -1366,7 +1375,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++;
 
 #ifdef DROPKLUDGE
     if (vol->v_flags & AFPVOL_DROPBOX) {
@@ -1850,7 +1859,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 483f6be61a4d264fe74910a6f8c66a22a3b29f35..077cd1203b214f98eebccb634fc8b83c82593dcc 100644 (file)
@@ -31,8 +31,8 @@
 #include <sys/cdefs.h>
 #include <netatalk/endian.h>
 #include <atalk/adouble.h>
+#include <atalk/globals.h>
 
-#include "globals.h"
 #include "volume.h"
 #include "directory.h"
 
index 5f6e0f643e5987f101a2068123772eb8a50a21f8..16c329ab72d6b38c7580d416b8fe6c1e57ed88b5 100644 (file)
@@ -40,6 +40,7 @@ char *strchr (), *strrchr ();
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
 #include <atalk/acl.h>
+#include <atalk/globals.h>
 #include <atalk/fce_api.h>
 
 #include "directory.h"
@@ -48,7 +49,6 @@ char *strchr (), *strrchr ();
 #include "volume.h"
 #include "fork.h"
 #include "file.h"
-#include "globals.h"
 #include "filedir.h"
 #include "unix.h"
 
@@ -624,18 +624,22 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
         if (s_path->st_valid && s_path->st_errno == ENOENT) {
             rc = AFPERR_NOOBJ;
         } else {
-            if ((rc = deletefile(vol, -1, upath, 1)) == AFP_OK)
+            if ((rc = deletefile(vol, -1, upath, 1)) == AFP_OK) {
                                fce_register_delete_file( s_path );
-
+                if (vol->v_tm_used < s_path->st.st_size)
+                    vol->v_tm_used = 0;
+                else 
+                    vol->v_tm_used -= s_path->st.st_size;
+            }
             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 );
     }
 
@@ -776,8 +780,8 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
             rc = AFPERR_PARAM;
             goto exit;
         }
-        curdir->offcnt++;
-        sdir->offcnt--;
+        curdir->d_offcnt++;
+        sdir->d_offcnt--;
 #ifdef DROPKLUDGE
         if (vol->v_flags & AFPVOL_DROPBOX) {
             /* FIXME did is not always the source id */
index c5b857567db4fdf6e1318c8c60d897ae7afbaf82..5daf73f3c975bf0fb000f00a56d77c621b1a62a2 100644 (file)
@@ -7,7 +7,7 @@
 
 #include <sys/cdefs.h>
 #include <sys/stat.h>
-#include "globals.h"
+#include <atalk/globals.h>
 #include "volume.h"
 
 extern struct afp_options default_options;
index f7d9f82a839fb2412c3b514bf3df3e5fa06e0826..00436dbc01ab8dd4f29e654e9fd533eea7c99ab7 100644 (file)
 #include <atalk/atp.h>
 #include <atalk/asp.h>
 #include <atalk/afp.h>
-
 #include <atalk/util.h>
 #include <atalk/cnid.h>
+#include <atalk/globals.h>
 
 #include "fork.h"
 #include "file.h"
-#include "globals.h"
 #include "directory.h"
 #include "desktop.h"
 #include "volume.h"
@@ -1340,6 +1339,9 @@ static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, s
     /* we have modified any fork, remember until close_fork */
     ofork->of_flags |= AFPFORK_MODIFIED;
 
+    /* update write count */
+    ofork->of_vol->v_written += reqcount;
+
     *rbuflen = set_off_t (offset, rbuf, is64);
     return( AFP_OK );
 
index d4e4d8f58e30f6cac089ed11d07cdb6d03dd5296..6c9d473b34379f4741060826197e542dbf56b462 100644 (file)
@@ -29,7 +29,7 @@ char *strchr (), *strrchr ();
 #include <ctype.h>
 #include <pwd.h>
 
-#include "globals.h"
+#include <atalk/globals.h>
 
 static char    *l_curr;
 static char    *l_end;
diff --git a/etc/afpd/globals.h b/etc/afpd/globals.h
deleted file mode 100644 (file)
index cca15f5..0000000
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 1990,1993 Regents of The University of Michigan.
- * All Rights Reserved.  See COPYRIGHT.
- */
-
-#ifndef AFPD_GLOBALS_H
-#define AFPD_GLOBALS_H 1
-
-#include <sys/param.h>
-#include <sys/cdefs.h>
-
-#ifdef ADMIN_GRP
-#include <grp.h>
-#include <sys/types.h>
-#endif /* ADMIN_GRP */
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>  /* this isn't header-protected under ultrix */
-#endif /* HAVE_NETDB_H */
-
-#include <netatalk/at.h>
-#include <atalk/afp.h>
-#include <atalk/compat.h>
-#include <atalk/unicode.h>
-#include <atalk/uam.h>
-
-/* #define DOSFILELEN 12 */             /* Type1, DOS-compat*/
-#define MACFILELEN 31                   /* Type2, HFS-compat */
-#define UTF8FILELEN_EARLY 255           /* Type3, early Mac OS X 10.0-10.4.? */
-/* #define UTF8FILELEN_NAME_MAX 765 */  /* Type3, 10.4.?- , getconf NAME_MAX */
-/* #define UTF8FILELEN_SPEC 0xFFFF */   /* Type3, spec on document */
-/* #define HFSPLUSFILELEN 510 */        /* HFS+ spec, 510byte = 255codepoint */
-
-#define MAXUSERLEN 256
-
-#define OPTION_DEBUG         (1 << 0)
-#define OPTION_USERVOLFIRST  (1 << 1)
-#define OPTION_NOUSERVOL     (1 << 2)
-#define OPTION_PROXY         (1 << 3)
-#define OPTION_CUSTOMICON    (1 << 4)
-#define OPTION_NOSLP         (1 << 5)
-#define OPTION_ANNOUNCESSH   (1 << 6)
-#define OPTION_UUID          (1 << 7)
-#define OPTION_ACL2MACCESS   (1 << 8)
-#define OPTION_NOZEROCONF    (1 << 9)
-
-#ifdef FORCE_UIDGID
-/* set up a structure for this */
-typedef struct uidgidset_t {
-    uid_t uid;
-    gid_t gid;
-} uidgidset;
-#endif /* FORCE_UIDGID */
-
-/* a couple of these options could get stuck in unions to save
- * space. */
-struct afp_volume_name {
-    time_t     mtime;
-    char       *name;
-    char       *full_name;
-    int        loaded;
-};
-
-struct afp_options {
-    int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
-    int sleep;                  /* Maximum time allowed to sleep (in tickles) */
-    int disconnected;           /* Maximum time in disconnected state (in tickles) */
-    unsigned int tcp_sndbuf, tcp_rcvbuf;
-    unsigned char passwdbits, passwdminlen, loginmaxfail;
-    u_int32_t server_quantum;
-    int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */
-    char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
-    struct at_addr ddpaddr;
-    char *uampath, *fqdn;
-    char *pidfile;
-    char *sigconffile;
-    char *uuidconf;
-    struct afp_volume_name defaultvol, systemvol, uservol;
-    int  closevol;
-
-    char *guest, *loginmesg, *keyfile, *passwdfile;
-    char *uamlist;
-    char *authprintdir;
-    char *signatureopt;
-    unsigned char signature[16];
-    char *k5service, *k5realm, *k5keytab;
-    char *unixcodepage,*maccodepage;
-    charset_t maccharset, unixcharset; 
-    mode_t umask;
-    mode_t save_mask;
-#ifdef ADMIN_GRP
-    gid_t admingid;
-#endif /* ADMIN_GRP */
-    int    volnamelen;
-
-    /* default value for winbind authentication */
-    char *ntdomain, *ntseparator;
-    char *logconfig;
-
-    char *mimicmodel;
-};
-
-#define AFPOBJ_TMPSIZ (MAXPATHLEN)
-typedef struct _AFPObj {
-    int proto;
-    unsigned long servernum;
-    void *handle;               /* either (DSI *) or (ASP *) */
-    void *config; 
-    struct afp_options options;
-    char *Obj, *Type, *Zone;
-    char username[MAXUSERLEN];
-    void (*logout)(void), (*exit)(int);
-    int (*reply)(void *, int);
-    int (*attention)(void *, AFPUserBytes);
-    /* to prevent confusion, only use these in afp_* calls */
-    char oldtmp[AFPOBJ_TMPSIZ + 1], newtmp[AFPOBJ_TMPSIZ + 1];
-    void *uam_cookie; /* cookie for uams */
-    struct session_info  sinfo;
-    uid_t uid;         /* client running user id */
-    int ipc_fd; /* anonymous PF_UNIX socket for IPC with afpd parent */
-#ifdef FORCE_UIDGID
-    int                 force_uid;
-    uidgidset          uidgid;
-#endif
-} AFPObj;
-
-/* typedef for AFP functions handlers */
-typedef int (*AFPCmd)(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
-
-/* afp_dsi.c */
-extern AFPObj *AFPobj;
-
-extern int             afp_version;
-extern int             afp_errno;
-extern unsigned char   nologin;
-extern struct dir      *curdir;
-extern char            getwdbuf[];
-
-/* FIXME CNID */
-extern const char *Cnid_srv;
-extern const char *Cnid_port;
-
-extern int  get_afp_errno   (const int param);
-extern void afp_options_init (struct afp_options *);
-extern int afp_options_parse (int, char **, struct afp_options *);
-extern int afp_options_parseline (char *, struct afp_options *);
-extern void afp_options_free (struct afp_options *,
-                                      const struct afp_options *);
-extern void setmessage (const char *);
-extern void readmessage (AFPObj *);
-
-/* gettok.c */
-extern void initline   (int, char *);
-extern int  parseline  (int, char *);
-
-/* afp_util.c */
-extern const char *AfpNum2name (int );
-extern const char *AfpErr2name(int err);
-
-/* directory.c */
-extern struct dir rootParent;
-
-#ifndef NO_DDP
-extern void afp_over_asp (AFPObj *);
-#endif /* NO_DDP */
-extern void afp_over_dsi (AFPObj *);
-
-#endif /* globals.h */
index 47815e3d85de794eb5be2039e42457ec25496ee4..c3214a0a762b71cc84e4f469f0c14d99dc95451a 100644 (file)
@@ -9,7 +9,7 @@
 #define AFPD_ICON_H 1
 
 #include <sys/cdefs.h>
-#include "globals.h"
+#include <atalk/globals.h>
 
 static const unsigned char apple_atalk_icon[] = { /* default appletalk icon */
     0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,  0x00,
index 0d552d6f73c77faa3478f4a37702fb630aa6e7a3..63452d9e350fc8ceea033a82c889027c544c504e 100644 (file)
@@ -20,6 +20,7 @@
 #include <sys/poll.h>
 #include <errno.h>
 #include <sys/wait.h>
+#include <sys/resource.h>
 
 #include <atalk/adouble.h>
 
@@ -33,8 +34,8 @@
 #include <atalk/util.h>
 #include <atalk/server_child.h>
 #include <atalk/server_ipc.h>
+#include <atalk/globals.h>
 
-#include "globals.h"
 #include "afp_config.h"
 #include "status.h"
 #include "fork.h"
@@ -62,7 +63,7 @@ static struct pollfd *fdset;
 static struct polldata *polldata;
 static int fdset_size;          /* current allocated size */
 static int fdset_used;          /* number of used elements */
-
+static int disasociated_ipc_fd; /* disasociated sessions uses this fd for IPC */
 
 #ifdef TRU64
 void afp_get_cmdline( int *ac, char ***av)
@@ -93,6 +94,7 @@ static void fd_set_listening_sockets(void)
             continue;
         fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd, LISTEN_FD, config);
     }
+    fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd, DISASOCIATED_IPC_FD, NULL);
 }
  
 static void fd_reset_listening_sockets(void)
@@ -104,25 +106,33 @@ static void fd_reset_listening_sockets(void)
             continue;
         fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, config->fd);
     }
-    fd_set_listening_sockets();
+    fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd);
 }
 
 /* ------------------ */
 static void afp_goaway(int sig)
 {
+        AFPConfig *config;
 
 #ifndef NO_DDP
     asp_kill(sig);
 #endif /* ! NO_DDP */
 
-    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;
+    case SIGTERM:
+    case SIGQUIT:
+        switch (sig) {
+        case SIGTERM:
+            LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGTERM");
+            break;
+        case SIGQUIT:
+            LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT, NOT disconnecting clients");
+            break;
+        }
+        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);
@@ -134,6 +144,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 :
@@ -179,6 +192,26 @@ static void child_handler(int sig _U_)
     }
 }
 
+static int setlimits(void)
+{
+    struct rlimit rlim;
+
+    if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
+        LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
+        exit(1);
+    }
+    if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < 65535) {
+        rlim.rlim_cur = 65535;
+        if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < 65535)
+            rlim.rlim_max = 65535;
+        if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
+            LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
+            exit(1);
+        }
+    }
+    return 0;
+}
+
 int main(int ac, char **av)
 {
     AFPConfig           *config;
@@ -246,7 +279,7 @@ int main(int ac, char **av)
     sigaddset(&sv.sa_mask, SIGHUP);
     sigaddset(&sv.sa_mask, SIGTERM);
     sigaddset(&sv.sa_mask, SIGUSR1);
-    
+    sigaddset(&sv.sa_mask, SIGQUIT);    
     sv.sa_flags = SA_RESTART;
     if ( sigaction( SIGCHLD, &sv, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
@@ -259,6 +292,7 @@ int main(int ac, char **av)
     sigaddset(&sv.sa_mask, SIGTERM);
     sigaddset(&sv.sa_mask, SIGHUP);
     sigaddset(&sv.sa_mask, SIGCHLD);
+    sigaddset(&sv.sa_mask, SIGQUIT);
     sv.sa_flags = SA_RESTART;
     if ( sigaction( SIGUSR1, &sv, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
@@ -270,6 +304,7 @@ int main(int ac, char **av)
     sigaddset(&sv.sa_mask, SIGTERM);
     sigaddset(&sv.sa_mask, SIGUSR1);
     sigaddset(&sv.sa_mask, SIGCHLD);
+    sigaddset(&sv.sa_mask, SIGQUIT);
     sv.sa_flags = SA_RESTART;
     if ( sigaction( SIGHUP, &sv, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
@@ -282,12 +317,25 @@ int main(int ac, char **av)
     sigaddset(&sv.sa_mask, SIGHUP);
     sigaddset(&sv.sa_mask, SIGUSR1);
     sigaddset(&sv.sa_mask, SIGCHLD);
+    sigaddset(&sv.sa_mask, SIGQUIT);
     sv.sa_flags = SA_RESTART;
     if ( sigaction( SIGTERM, &sv, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
         exit(EXITERR_SYS);
     }
 
+    sigemptyset( &sv.sa_mask );
+    sigaddset(&sv.sa_mask, SIGALRM);
+    sigaddset(&sv.sa_mask, SIGHUP);
+    sigaddset(&sv.sa_mask, SIGUSR1);
+    sigaddset(&sv.sa_mask, SIGCHLD);
+    sigaddset(&sv.sa_mask, SIGTERM);
+    sv.sa_flags = SA_RESTART;
+    if (sigaction(SIGQUIT, &sv, NULL ) < 0 ) {
+        LOG(log_error, logtype_afpd, "main: sigaction: %s", strerror(errno) );
+        exit(EXITERR_SYS);
+    }
+
     /* afpd.conf: not in config file: lockfile, connections, configfile
      *            preference: command-line provides defaults.
      *                        config file over-writes defaults.
@@ -317,9 +365,15 @@ int main(int ac, char **av)
     cnid_init();
 
     /* watch atp, dsi sockets and ipc parent/child file descriptor. */
+    disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC);
     fd_set_listening_sockets();
 
+    /* set limits */
+    (void)setlimits();
+
     afp_child_t *child;
+    int fd[2];  /* we only use one, but server_child_add expects [2] */
+    pid_t pid;
 
     /* wait for an appleshare connection. parent remains in the loop
      * while the children get handled by afp_over_{asp,dsi}.  this is
@@ -337,6 +391,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)
@@ -350,10 +405,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)
@@ -367,8 +425,9 @@ int main(int ac, char **av)
         }
 
         for (int i = 0; i < fdset_used; i++) {
-            if (fdset[i].revents & POLLIN) {
+            if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP)) {
                 switch (polldata[i].fdtype) {
+
                 case LISTEN_FD:
                     config = (AFPConfig *)polldata[i].data;
                     /* config->server_start is afp_config.c:dsi_start() for DSI */
@@ -377,15 +436,42 @@ int main(int ac, char **av)
                         fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0], IPC_FD, child);
                     }
                     break;
+
                 case IPC_FD:
                     child = (afp_child_t *)polldata[i].data;
                     LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid);
+
                     if ((ret = ipc_server_read(server_children, child->ipc_fds[0])) == 0) {
                         fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fds[0]);
                         close(child->ipc_fds[0]);
                         child->ipc_fds[0] = -1;
+                        if (child->disasociated) {
+                            LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
+                            server_child_remove(server_children, CHILD_DSIFORK, child->pid);
+                        }
                     }
                     break;
+
+                case DISASOCIATED_IPC_FD:
+                    LOG(log_debug, logtype_afpd, "main: IPC reconnect request");
+                    if ((fd[0] = accept(disasociated_ipc_fd, NULL, NULL)) == -1) {
+                        LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno));
+                        break;
+                    }
+                    if (readt(fd[0], &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
+                        LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno));
+                        close(fd[0]);
+                    }
+                    LOG(log_note, logtype_afpd, "main: IPC reconnect from [%u]", pid);
+                    if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, fd)) == NULL) {
+                        LOG(log_error, logtype_afpd, "main: server_child_add");
+                        close(fd[0]);
+                        break;
+                    }
+                    child->disasociated = 1;
+                    fdset_add_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd[0], IPC_FD, child);
+                    break;
+
                 default:
                     LOG(log_debug, logtype_afpd, "main: IPC request for unknown type");
                     break;
index 6c6ed75dceefdd55ecbb7195d09a83426e93330d..dce7e61681ac8e646ad4ed5ef810d39dacade824 100644 (file)
@@ -13,8 +13,8 @@
 #include <atalk/adouble.h>
 #include <atalk/cnid.h>
 #include <atalk/logger.h>
+#include <atalk/globals.h>
 
-#include "globals.h"
 #include "volume.h"
 #include "directory.h"
 
index 13e03f4066cb7fc6cca11fb0ae588846a6fde615..2784e8260280ee20e3af9298dd903decb2e3c75b 100644 (file)
@@ -20,7 +20,8 @@
 #include <atalk/dsi.h>
 #include <atalk/util.h>
 #include <atalk/logger.h>
-#include "globals.h"
+#include <atalk/globals.h>
+
 #include "misc.h"
 
 
index dded79b13bd2d1b762acd5d7b9374dc2dc7b18cc..9f3d70bfc71df244b58189f45ab5c5f5854cdb82 100644 (file)
@@ -6,7 +6,7 @@
 #define AFPD_MISC_H 1
 
 #include <sys/cdefs.h>
-#include "globals.h"
+#include <atalk/globals.h>
 
 /* FP functions */
 /* messages.c */
index c4901285c9e9d248692d7841cc546e986321fa55..2d2600895cb5cc37a730a84a5bb1bdb1b9c6380e 100644 (file)
 #include <atalk/util.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
+#include <atalk/globals.h>
 #include <atalk/fce_api.h>
 
-#include "globals.h"
 #include "volume.h"
 #include "directory.h"
 #include "fork.h"
 
-/* we need to have a hashed list of oforks (by dev inode). just hash
- * by first letter. */
+/* we need to have a hashed list of oforks (by dev inode) */
 #define OFORK_HASHSIZE  64
-static struct ofork     *ofork_table[OFORK_HASHSIZE];
-
-static struct ofork **oforks = NULL;
+static struct ofork *ofork_table[OFORK_HASHSIZE]; /* forks hashed by dev/inode */
+static struct ofork **oforks = NULL;              /* point to allocated table of open forks pointers */
 static int          nforks = 0;
 static u_short      lastrefnum = 0;
 
@@ -41,12 +39,6 @@ static u_short      lastrefnum = 0;
 /* OR some of each character for the hash*/
 static unsigned long hashfn(const struct file_key *key)
 {
-#if 0
-    unsigned long i = 0;
-    while (*name) {
-        i = ((i << 4) | (8*sizeof(i) - 4)) ^ *name++;
-    }
-#endif
     return key->inode & (OFORK_HASHSIZE - 1);
 }
 
index cbf59892c157143fb74d9fef60b0de4f12a04bb1..f89615b1091dc3c2d88feeff8b5c5858378fe94f 100644 (file)
@@ -36,8 +36,8 @@
 #include <atalk/nbp.h>
 #include <atalk/unicode.h>
 #include <atalk/util.h>
+#include <atalk/globals.h>
 
-#include "globals.h"  /* includes <netdb.h> */
 #include "status.h"
 #include "afp_config.h"
 #include "icon.h"
index 3a29a17418f092681bbf986e7de0a6b365158f91..ae16bb49c0cc2fb6d1cf50088e667e6351c60ff1 100644 (file)
@@ -4,7 +4,8 @@
 #include <sys/cdefs.h>
 #include <atalk/dsi.h>
 #include <atalk/asp.h>
-#include "globals.h"
+#include <atalk/globals.h>
+
 #include "afp_config.h"
 
 /* we use these to prevent whacky alignment problems */
index 7dbd9ab77315f57eba5a8c4aa0d1c8bc0d360472..5c98e8df57d511565c8d3366a5306925efb74ff6 100644 (file)
@@ -31,8 +31,7 @@
 
 #include <atalk/afp.h>
 #include <atalk/uam.h>
-
-#include "globals.h"
+#include <atalk/globals.h>
 
 /* grab the FP functions */
 #include "auth.h" 
index 92173915c5f5cc5e7dfa8934c00f1a1ba34a1d85..37ef9dd2d0a8a6b901e2cd8417e51f0140692cb0 100644 (file)
@@ -50,8 +50,8 @@ char *strchr (), *strrchr ();
 #include <atalk/dsi.h>
 #include <atalk/afp.h>
 #include <atalk/util.h>
+#include <atalk/globals.h>
 
-#include "globals.h"
 #include "afp_config.h"
 #include "auth.h"
 #include "uam_auth.h"
index 7c879b313797300d85b00d209dbc8224dca98e82..18f010bbb0b81ddebb5c2570a2753e96c3022002 100644 (file)
@@ -14,7 +14,7 @@
 #include <pwd.h>
 
 #include <atalk/uam.h>
-#include "globals.h"
+#include <atalk/globals.h>
 
 struct uam_mod {
     void *uam_module;
index a012dcd82eb38010d363ec5aee9a279ea8919c18..faf142c402bbe21c99029b135cfc3f23f8ed8a14 100644 (file)
@@ -35,6 +35,8 @@ char *strchr (), *strrchr ();
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <inttypes.h>
+#include <time.h>
 
 #include <atalk/asp.h>
 #include <atalk/dsi.h>
@@ -47,12 +49,14 @@ char *strchr (), *strrchr ();
 #include <atalk/uuid.h>
 #include <atalk/bstrlib.h>
 #include <atalk/bstradd.h>
+#include <atalk/ftw.h>
+#include <atalk/globals.h>
+#include <atalk/fce_api.h>
 
 #ifdef CNID_DB
 #include <atalk/cnid.h>
 #endif /* CNID_DB*/
 
-#include "globals.h"
 #include "directory.h"
 #include "file.h"
 #include "volume.h"
@@ -499,11 +503,8 @@ static void volset(struct vol_option *options, struct vol_option *save,
                 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)
-                options[VOLOPT_FLAGS].i_value |= AFPVOL_CDROM | AFPVOL_RO;
-#endif
+            else if (strcasecmp(p, "nonetids") == 0)
+                options[VOLOPT_FLAGS].i_value |= AFPVOL_NONETIDS;
             p = strtok(NULL, ",");
         }
 
@@ -662,7 +663,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);
@@ -670,15 +678,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;
             }
@@ -858,8 +875,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",
@@ -1188,12 +1205,22 @@ static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int us
         p1->mtime = st.st_mtime;
     }
 
-    if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) {
-        LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path);
-        if ( fclose( fp ) != 0 ) {
-            LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
+    /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */
+    int retries = 2;
+    while (1) {
+        if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) {
+            retries--;
+            if (!retries) {
+                LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path);
+                if ( fclose( fp ) != 0 ) {
+                    LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
+                }
+                return -1;
+            }
+            sleep(1);
+            continue;
         }
-        return -1;
+        break;
     }
 
     memset(save_options, 0, sizeof(save_options));
@@ -1403,12 +1430,72 @@ static void volume_unlink(struct vol *volume)
     }
 }
 
+static off_t getused_size; /* result of getused() */
+
+/*!
+  nftw callback for getused()
+ */
+static int getused_stat(const char *path,
+                        const struct stat *statp,
+                        int tflag,
+                        struct FTW *ftw)
+{
+    off_t low, high;
+
+    if (tflag == FTW_F || tflag == FTW_D) {
+        getused_size += statp->st_blocks * 512;
+    }
+
+    return 0;
+}
+
+#define GETUSED_CACHETIME 5
+/*!
+ * Calculate used size of a volume with nftw
+ *
+ * The result is cached, we're try to avoid frequently calling nftw()
+ *
+ * 1) Call nftw an refresh if:
+ * 1a) - we're called the first time 
+ * 1b) - volume modification date is not yet set and the last time we've been called is
+ *       longer then 30 sec ago
+ * 1c) - the last volume modification is less then 30 sec old
+ *
+ * @param vol     (rw) volume to calculate
+ */
+static int getused(struct vol *vol)
+{
+    static time_t vol_mtime = 0;
+    int ret = 0;
+    time_t now = time(NULL);
+
+    if (!vol_mtime
+        || (!vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < now))
+        || (vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < vol->v_mtime))
+        ) {
+        vol_mtime = now;
+        getused_size = 0;
+        vol->v_written = 0;
+        ret = nftw(vol->v_path, getused_stat, NULL, 20, FTW_PHYS); /* 2 */
+        LOG(log_debug, logtype_afpd, "volparams: from nftw: %" PRIu64 " bytes",
+            getused_size);
+    } else {
+        getused_size += vol->v_written;
+        vol->v_written = 0;
+        LOG(log_debug, logtype_afpd, "volparams: cached used: %" PRIu64 " bytes",
+            getused_size);
+    }
+
+    return ret;
+}
+
 static int getvolspace(struct vol *vol,
                        u_int32_t *bfree, u_int32_t *btotal,
                        VolSpace *xbfree, VolSpace *xbtotal, u_int32_t *bsize)
 {
     int         spaceflag, rc;
     u_int32_t   maxsize;
+    VolSpace    used;
 #ifndef NO_QUOTA_SUPPORT
     VolSpace    qfree, qtotal;
 #endif
@@ -1447,45 +1534,14 @@ static int getvolspace(struct vol *vol,
 
 getvolspace_done:
     if (vol->v_limitsize) {
-        bstring cmdstr;
-        if ((cmdstr = bformat("du -sh \"%s\" 2> /dev/null | cut -f1", vol->v_path)) == NULL)
-            return AFPERR_MISC;
-
-        FILE *cmd = popen(cfrombstr(cmdstr), "r");
-        bdestroy(cmdstr);
-        if (cmd == NULL)
+        if (getused(vol) != 0)
             return AFPERR_MISC;
-
-        char buf[100];
-        fgets(buf, 100, cmd);
-
-        if (pclose(cmd) == -1)
-            return AFPERR_MISC;
-
-        size_t multi = 0;
-        if (buf[strlen(buf) - 2] == 'G' || buf[strlen(buf) - 2] == 'g')
-            /* GB */
-            multi = 1024 * 1024 * 1024;
-        else if (buf[strlen(buf) - 2] == 'M' || buf[strlen(buf) - 2] == 'm')
-            /* MB */
-            multi = 1024 * 1024;
-        else if (buf[strlen(buf) - 2] == 'K' || buf[strlen(buf) - 2] == 'k')
-            /* MB */
-            multi = 1024;
-
-        char *p;
-        if (p = strchr(buf, ','))
-            /* ignore fraction */
-            *p = 0;
-        else
-            /* remove G|M|K char */
-            buf[strlen(buf) - 2] = 0;
-        /* now buf contains only digits */
-        long long used = atoll(buf) * multi;
-        LOG(log_debug, logtype_afpd, "volparams: used on volume: %llu bytes", used);
+        LOG(log_debug, logtype_afpd, "volparams: used on volume: %" PRIu64 " bytes",
+            getused_size);
+        vol->v_tm_used = getused_size;
 
         *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
-        *xbfree = min(*xbfree, *xbtotal < used ? 0 : *xbtotal - used);
+        *xbfree = min(*xbfree, *xbtotal < getused_size ? 0 : *xbtotal - getused_size);
     }
 
     *bfree = min( *xbfree, maxsize);
@@ -1493,6 +1549,22 @@ getvolspace_done:
     return( AFP_OK );
 }
 
+#define FCE_TM_DELTA 10  /* send notification every 10 seconds */
+void vol_fce_tm_event(void)
+{
+    static time_t last;
+    time_t now = time(NULL);
+    struct vol  *vol = Volumes;
+
+    if ((last + FCE_TM_DELTA) < now) {
+        last = now;
+        for ( ; vol; vol = vol->v_next ) {
+            if (vol->v_flags & AFPVOL_TM)
+                (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_written);
+        }
+    }
+}
+
 /* -----------------------
  * set volume creation date
  * avoid duplicate, well at least it tries
@@ -1603,7 +1675,8 @@ static int getvolparams( u_int16_t bitmap, struct vol *vol, struct stat *st, cha
                         ashort |= VOLPBIT_ATTR_UNIXPRIV;
                     if (vol->v_flags & AFPVOL_TM)
                         ashort |= VOLPBIT_ATTR_TM;
-
+                    if (vol->v_flags & AFPVOL_NONETIDS)
+                        ashort |= VOLPBIT_ATTR_NONETIDS;
                     if (afp_version >= 32) {
                         if (vol->v_vfs_ea)
                             ashort |= VOLPBIT_ATTR_EXT_ATTRS;
@@ -2219,7 +2292,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) );
@@ -2467,12 +2540,6 @@ void setvoltime(AFPObj *obj, struct vol *vol)
 {
     struct timeval  tv;
 
-    /* just looking at vol->v_mtime is broken seriously since updates
-     * from other users afpd processes never are seen.
-     * This is not the most elegant solution (a shared memory between
-     * the afpd processes would come closer)
-     * [RS] */
-
     if ( gettimeofday( &tv, NULL ) < 0 ) {
         LOG(log_error, logtype_afpd, "setvoltime(%s): gettimeofday: %s", vol->v_path, strerror(errno) );
         return;
index fd2d22514ff086d42daaf6eae389a0b3cf970e95..eedc622bd275107758b7522e570f6e37eb278b4c 100644 (file)
 #include <atalk/volume.h>
 #include <atalk/cnid.h>
 #include <atalk/unicode.h>
-
-#include "globals.h"
-#if 0
-#include "hash.h"
-#endif
+#include <atalk/globals.h>
 
 extern struct vol       *getvolbyvid (const u_int16_t);
 extern int              ustatfs_getvolspace (const struct vol *,
@@ -28,6 +24,7 @@ extern int              pollvoltime (AFPObj *);
 extern void             load_volumes (AFPObj *obj);
 extern const struct vol *getvolumes(void);
 extern void             unload_volumes_and_extmap(void);
+extern void             vol_fce_tm_event(void);
 
 /* FP functions */
 int afp_openvol      (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
index 2805b6fcf5c91423f36dd7e7c43784943c74300f..5493a28059461cb525f49f99ecaa0cbf16dbb15d 100644 (file)
 #include <atalk/logger.h>
 #include <atalk/cnid_dbd_private.h>
 #include <atalk/volinfo.h>
+#include <atalk/util.h>
+
 #include "cmd_dbd.h"
 #include "dbd.h"
 #include "dbif.h"
 #include "db_param.h"
 
-#define LOCKFILENAME  "lock"
 #define DBOPTIONS (DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN)
 
 int nocniddb = 0;               /* Dont open CNID database, only scan filesystem */
-volatile sig_atomic_t alarmed;
 struct volinfo volinfo; /* needed by pack.c:idxname() */
+volatile sig_atomic_t alarmed;  /* flags for signals */
+int db_locked;                  /* have we got the fcntl lock on lockfile ? */
 
 static DBD *dbd;
 static int verbose;             /* Logging flag */
@@ -95,7 +97,6 @@ static struct db_param db_param = {
     DEFAULT_MAXLOCKOBJS,        /* maxlockobjs */
     0,                          /* flush_interval */
     0,                          /* flush_frequency */
-    1000,                       /* txn_frequency */
     0,                          /* usock_file */
     -1,                         /* fd_table_size */
     -1,                         /* idle_timeout */
@@ -167,68 +168,6 @@ static void set_signal(void)
     }        
 }
 
-static int get_lock(const char *dbpath)
-{
-    int lockfd;
-    char lockpath[PATH_MAX];
-    struct flock lock;
-    struct stat st;
-
-    if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
-        dbd_log( LOGSTD, ".AppleDB pathname too long");
-        exit(EXIT_FAILURE);
-    }
-    strncpy(lockpath, dbpath, PATH_MAX - 1);
-    strcat(lockpath, "/");
-    strcat(lockpath, LOCKFILENAME);
-
-    if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
-        dbd_log( LOGSTD, "Error opening lockfile: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-
-    if ((stat(dbpath, &st)) != 0) {
-        dbd_log( LOGSTD, "Error statting lockfile: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-
-    if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
-        dbd_log( LOGSTD, "Error inheriting lockfile permissions: %s", strerror(errno));
-        exit(EXIT_FAILURE);
-    }
-    
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type   = F_WRLCK;
-
-    if (fcntl(lockfd, F_SETLK, &lock) < 0) {
-        if (errno == EACCES || errno == EAGAIN) {
-            if (exclusive) {
-                dbd_log( LOGSTD, "Database is in use and exlusive was requested", strerror(errno));        
-                exit(EXIT_FAILURE);
-            };
-        } else {
-            dbd_log( LOGSTD, "Error getting fcntl F_WRLCK on lockfile: %s", strerror(errno));
-            exit(EXIT_FAILURE);
-       }
-    }
-    
-    return lockfd;
-}
-
-static void free_lock(int lockfd)
-{
-    struct flock lock;
-
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type = F_UNLCK;
-    fcntl(lockfd, F_SETLK, &lock);
-    close(lockfd);
-}
-
 static void usage (void)
 {
     printf("Usage: dbd [-e|-t|-v|-x] -d [-i] | -s [-c|-n]| -r [-c|-f] | -u <path to netatalk volume>\n"
@@ -422,11 +361,18 @@ int main(int argc, char **argv)
         close(dbdirfd);
     }
 
-    /* 
-       Before we do anything else, check if there is an instance of cnid_dbd
-       running already and silently exit if yes.
-    */
-    lockfd = get_lock(dbpath);
+    /* Get db lock */
+    if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
+        goto exit_failure;
+    if (db_locked != LOCK_EXCL) {
+        /* Couldn't get exclusive lock, try shared lock if -e wasn't requested */
+        if (exclusive) {
+            dbd_log(LOGSTD, "Database is in use and exlusive was requested");
+            goto exit_failure;
+        }
+        if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD)
+            goto exit_failure;
+    }
 
     /* Prepare upgrade ? */
     if (prep_upgrade) {
@@ -438,7 +384,9 @@ 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];
-        close(lockfd);
+        if ((db_locked = get_lock(LOCK_FREE, NULL)) != 0)
+            goto exit_failure;
+
         snprintf(cmd, 8 + MAXPATHLEN, "rm -rf \"%s\"", dbpath);
         dbd_log( LOGDEBUG, "Removing old database of volume: '%s'", volpath);
         system(cmd);
@@ -447,7 +395,8 @@ int main(int argc, char **argv)
             exit(EXIT_FAILURE);
         }
         dbd_log( LOGDEBUG, "Removed old database.");
-        lockfd = get_lock(dbpath);
+        if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1)
+            goto exit_failure;
     }
 
     /* 
@@ -457,12 +406,14 @@ int main(int argc, char **argv)
         if ((dbd = dbif_init(dbpath, "cnid2.db")) == NULL)
             goto exit_failure;
         
-        if (dbif_env_open(dbd, &db_param, exclusive ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
+        if (dbif_env_open(dbd,
+                          &db_param,
+                          (db_locked == LOCK_EXCL) ? (DBOPTIONS | DB_RECOVER) : DBOPTIONS) < 0) {
             dbd_log( LOGSTD, "error opening database!");
             goto exit_failure;
         }
 
-        if (exclusive)
+        if (db_locked == LOCK_EXCL)
             dbd_log( LOGDEBUG, "Finished recovery.");
 
         if (dbif_open(dbd, NULL, rebuildindexes) < 0) {
@@ -471,6 +422,14 @@ int main(int argc, char **argv)
         }
     }
 
+    /* Downgrade db lock if not running exclusive */
+    if (!exclusive && (db_locked == LOCK_EXCL)) {
+        if (get_lock(LOCK_UNLOCK, NULL) != 0)
+            goto exit_failure;
+        if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD)
+            goto exit_failure;
+    }
+
     /* Now execute given command scan|rebuild|dump */
     if (dump && ! nocniddb) {
         if (dbif_dump(dbd, dumpindexes) < 0) {
@@ -495,7 +454,7 @@ exit_success:
     ret = 0;
 
 exit_failure:
-    free_lock(lockfd);
+    get_lock(0, NULL);
     
     if ((fchdir(cdir)) < 0)
         dbd_log(LOGSTD, "fchdir: %s", strerror(errno));
index 425fb400cd3f4d1e13a1b671b249278c1eba0c0a..ef7829881b28a851cc335998b6db8dfacdac7da6 100644 (file)
@@ -25,6 +25,7 @@ typedef unsigned int dbd_flags_t;
         (strcmp(a,c) b 0)
 
 extern int nocniddb; /* Dont open CNID database, only scan filesystem */
+extern int db_locked; /* have we got the fcntl lock on lockfd ? */
 extern volatile sig_atomic_t alarmed;
 
 extern void dbd_log(enum logtype lt, char *fmt, ...);
index 576df49fb570bd26009014e9ac8226d75eda5f6d..daa13e413e441622191606f31ae6085f8ce0ed19 100644 (file)
@@ -1082,8 +1082,6 @@ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
     struct cnid_dbd_rqst rqst;
     struct cnid_dbd_rply rply;
 
-    dbd->db_param.txn_frequency = 0;
-
     /* jump over rootinfo key */
     if ( dbif_idwalk(dbd, &dbd_cnid, 0) != 1)
         return;
@@ -1198,7 +1196,6 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *vi, dbd_flags_t flags)
     db_param.cachesize = 64 * 1024;         /* 64 MB */
     db_param.maxlocks = DEFAULT_MAXLOCKS;
     db_param.maxlockobjs = DEFAULT_MAXLOCKOBJS;
-    db_param.txn_frequency = 1000;          /* close txn every 1000 objects */
     db_param.logfile_autoremove = 1;
 
     /* Make it accessible for all funcs */
@@ -1210,15 +1207,16 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *vi, dbd_flags_t flags)
         return -1;
     }
 
-    /* temporary rebuild db, used with -re rebuild to delete unused CNIDs, not used with -f */
-    if (! nocniddb && !(flags & DBD_FLAGS_FORCE)) {
-        /* Get volume stamp */
-        dbd_getstamp(dbd, &rqst, &rply);
-        if (rply.result != CNID_DBD_RES_OK)
-            goto exit;
-        memcpy(stamp, rply.name, CNID_DEV_LEN);
+    /* Get volume stamp */
+    dbd_getstamp(dbd, &rqst, &rply);
+    if (rply.result != CNID_DBD_RES_OK) {
+        ret = -1;
+        goto exit;
+    }
+    memcpy(stamp, rply.name, CNID_DEV_LEN);
 
-        /* open/create rebuild dbd, copy rootinfo key */
+    /* temporary rebuild db, used with -re rebuild to delete unused CNIDs, not used with -f */
+    if (! nocniddb && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE)) {
         tmpdb_path = get_tmpdb_path();
         if (NULL == (dbd_rebuild = dbif_init(tmpdb_path, "cnid2.db"))) {
             ret = -1;
@@ -1256,10 +1254,10 @@ int cmd_dbd_scanvol(DBD *dbd_ref, struct volinfo *vi, dbd_flags_t flags)
 
 exit:
     if (! nocniddb) {
-        if (dbif_txn_close(dbd, 2) != 0)
+        if (dbif_txn_close(dbd, ret == 0 ? 1 : 0) != 0)
             ret = -1;
         if (dbd_rebuild)
-            if (dbif_txn_close(dbd_rebuild, 2) != 0)
+            if (dbif_txn_close(dbd_rebuild, ret == 0 ? 1 : 0) != 0)
                 ret = -1;
         if ((ret == 0) && dbd_rebuild && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE))
             /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
index a51d15c4196d911f2f132cc42207cc6f87fddcb2..19d0737351bf5e18b286bb84b592e08e7b50d41f 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"
 
@@ -141,7 +142,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];
         }
@@ -177,14 +178,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;
             }
         }
@@ -403,6 +406,26 @@ static void set_signal(void)
     sigprocmask(SIG_BLOCK, &set, NULL);
 }
 
+static int setlimits(void)
+{
+    struct rlimit rlim;
+
+    if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
+        LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
+        exit(1);
+    }
+    if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < 65535) {
+        rlim.rlim_cur = 65535;
+        if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < 65535)
+            rlim.rlim_max = 65535;
+        if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
+            LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
+            exit(1);
+        }
+    }
+    return 0;
+}
+
 /* ------------------ */
 int main(int argc, char *argv[])
 {
@@ -483,6 +506,8 @@ int main(int argc, char *argv[])
         daemon_exit(1);
     }
 
+    (void)setlimits();
+
     /* Check PID lockfile and become a daemon */
     switch(server_lock("cnid_metad", _PATH_CNID_METAD_LOCK, debug)) {
     case -1: /* error */
@@ -523,7 +548,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 302b16db93632b6f7617eeafbd635fb97926ea95..f3a4827a031a5f99e5fa055c2232d228539024f2 100644 (file)
@@ -28,7 +28,6 @@ struct db_param {
     int maxlockobjs;
     int flush_interval;
     int flush_frequency;
-    int txn_frequency;
     char usock_file[MAXPATHLEN + 1];    
     int fd_table_size;
     int idle_timeout;
index e8cfdd4cfc51dfa21db6c75161429938b5f134d8..792ebe915a4c8dcf7f5085dea7b8e4ce06dbac3f 100644 (file)
@@ -321,6 +321,91 @@ exit:
     return ret;
 }
 
+/*!
+ * Get lock on db lock file
+ *
+ * @args cmd       (r) lock command:
+ *                     LOCK_FREE:   close lockfd
+ *                     LOCK_UNLOCK: unlock lockm keep lockfd open
+ *                     LOCK_EXCL:   F_WRLCK on lockfd
+ *                     LOCK_SHRD:   F_RDLCK on lockfd
+ * @args dbpath    (r) path to lockfile, only used on first call,
+ *                     later the stored fd is used
+ * @returns            LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error
+ *                     LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on
+ *                     success, 0 if the lock couldn't be acquired, -1 on other errors
+ */
+int get_lock(int cmd, const char *dbpath)
+{
+    static int lockfd = -1;
+    int ret;
+    char lockpath[PATH_MAX];
+    struct stat st;
+
+    switch (cmd) {
+    case LOCK_FREE:
+        if (lockfd == -1)
+            return -1;
+        close(lockfd);
+        lockfd = -1;
+        return 0;
+
+    case LOCK_UNLOCK:
+        if (lockfd == -1)
+            return -1;
+        return unlock(lockfd, 0, SEEK_SET, 0);
+
+    case LOCK_EXCL:
+    case LOCK_SHRD:
+        if (lockfd == -1) {
+            if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) {
+                LOG(log_error, logtype_cnid, ".AppleDB pathname too long");
+                return -1;
+            }
+            strncpy(lockpath, dbpath, PATH_MAX - 1);
+            strcat(lockpath, "/");
+            strcat(lockpath, LOCKFILENAME);
+
+            if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) {
+                LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno));
+                return -1;
+            }
+
+            if ((stat(dbpath, &st)) != 0) {
+                LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno));
+                return -1;
+            }
+
+            if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) {
+                LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s",
+                         strerror(errno));
+                return -1;
+            }
+        }
+    
+        if (cmd == LOCK_EXCL)
+            ret = write_lock(lockfd, 0, SEEK_SET, 0);
+        else
+            ret = read_lock(lockfd, 0, SEEK_SET, 0);
+
+        if (ret != 0) {
+            if (cmd == LOCK_SHRD)
+                LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again...");
+            return 0; 
+        }
+
+        LOG(log_debug, logtype_cnid, "get_lock: got %s lock",
+            cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD");    
+        return cmd;
+
+    default:
+        return -1;
+    } /* switch(cmd) */
+
+    /* deadc0de, never get here */
+    return -1;
+}
+
 /* --------------- */
 DBD *dbif_init(const char *envhome, const char *filename)
 {
@@ -1007,16 +1092,10 @@ int dbif_txn_abort(DBD *dbd)
 }
 
 /* 
-   ret = 2 -> commit txn regardless of db_param.txn_frequency
    ret = 1 -> commit txn if db_param.txn_frequency
    ret = 0 -> abort txn db_param.txn_frequency -> exit!
    anything else -> exit!
 
-   db_param of the db environment might specify txn_frequency > 1 in which case
-   we only close a txn every txn_frequency time. the `dbd` command uses this for the
-   temp rebuild db, cnid_dbd keeps it at 0. For increasing cnid_dbd throughput this
-   should be tuned and testes as well.
-
    @returns 0 on success (abort or commit), -1 on error
 */
 int dbif_txn_close(DBD *dbd, int ret)
@@ -1026,13 +1105,7 @@ int dbif_txn_close(DBD *dbd, int ret)
             LOG( log_error, logtype_cnid, "Fatal error aborting transaction. Exiting!");
             return -1;
         }
-    } else if (ret == 1 || ret == 2) {
-        static uint count;
-        if (ret != 2 && dbd->db_param.txn_frequency > 1) {
-            count++;
-            if ((count % dbd->db_param.txn_frequency) != 0)
-                return 0;
-        }
+    } else if (ret == 1) {
         ret = dbif_txn_commit(dbd);
         if (  ret < 0) {
             LOG( log_error, logtype_cnid, "Fatal error committing transaction. Exiting!");
index f5d3759fca5affba4013d724e2b32813b70309dd..c936a2b93705daf7b5bf1a8061131f7a3174dd37 100644 (file)
 #define DBIF_IDX_DIDNAME   2
 #define DBIF_IDX_NAME      3
 
+/* get_lock cmd and return value */
+#define LOCKFILENAME  "lock"
+#define LOCK_FREE          0
+#define LOCK_UNLOCK        1
+#define LOCK_EXCL          2
+#define LOCK_SHRD          3
+
 /* Structures */
 typedef struct {
     char     *name;
@@ -86,6 +93,8 @@ typedef struct {
 } DBD;
 
 /* Functions */
+extern int get_lock(int cmd, const char *dbpath);
+
 extern DBD *dbif_init(const char *envhome, const char *dbname);
 extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags);
 extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex);
index da4cd9a4e7085d764590140786580a3e82a3bb9d..64734396d34f6d7d8cfd1758c68d1b663db8455e 100644 (file)
 #include "dbd.h"
 #include "comm.h"
 
-#define LOCKFILENAME  "lock"
-
 /* 
    Note: DB_INIT_LOCK is here so we can run the db_* utilities while netatalk is running.
    It's a likey performance hit, but it might we worth it.
  */
-#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER)
+#define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN)
 
 /* Global, needed by pack.c:idxname() */
 struct volinfo volinfo;
 
 static DBD *dbd;
 static int exit_sig = 0;
+static int db_locked;
 
 static void sig_exit(int signo)
 {
@@ -256,34 +255,6 @@ static void switch_to_user(char *dir)
     }
 }
 
-/* ------------------------ */
-static int get_lock(void)
-{
-    int lockfd;
-    struct flock lock;
-
-    if ((lockfd = open(LOCKFILENAME, O_RDWR | O_CREAT, 0644)) < 0) {
-        LOG(log_error, logtype_cnid, "main: error opening lockfile: %s", strerror(errno));
-        exit(1);
-    }
-
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type   = F_WRLCK;
-
-    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));
-            exit(1);
-        }
-    }
-
-    return lockfd;
-}
 
 /* ----------------------- */
 static void set_signal(void)
@@ -307,25 +278,12 @@ static void set_signal(void)
     }
 }
 
-/* ----------------------- */
-static void free_lock(int lockfd)
-{
-    struct flock lock;
-
-    lock.l_start  = 0;
-    lock.l_whence = SEEK_SET;
-    lock.l_len    = 0;
-    lock.l_type = F_UNLCK;
-    fcntl(lockfd, F_SETLK, &lock);
-    close(lockfd);
-}
-
 /* ------------------------ */
 int main(int argc, char *argv[])
 {
     struct db_param *dbp;
     int err = 0;
-    int lockfd, ctrlfd, clntfd;
+    int ctrlfd, clntfd;
     char *logconfig;
 
     set_processname("cnid_dbd");
@@ -363,9 +321,18 @@ int main(int argc, char *argv[])
 
     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();
+    /* Get db lock */
+    if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1) {
+        LOG(log_error, logtype_cnid, "main: fatal db lock error");
+        exit(1);
+    }
+    if (db_locked != LOCK_EXCL) {
+        /* Couldn't get exclusive lock, try shared lock  */
+        if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD) {
+            LOG(log_error, logtype_cnid, "main: fatal db lock error");
+            exit(1);
+        }
+    }
 
     set_signal();
 
@@ -379,7 +346,10 @@ int main(int argc, char *argv[])
     if (NULL == (dbd = dbif_init(dbpath, "cnid2.db")))
         exit(2);
 
-    if (dbif_env_open(dbd, dbp, DBOPTIONS) < 0)
+    /* Only recover if we got the lock */
+    if (dbif_env_open(dbd,
+                      dbp,
+                      (db_locked == LOCK_EXCL) ? DBOPTIONS | DB_RECOVER : DBOPTIONS) < 0)
         exit(2); /* FIXME: same exit code as failure for dbif_open() */
     LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment");
 
@@ -389,6 +359,19 @@ int main(int argc, char *argv[])
     }
     LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases");
 
+    /* Downgrade db lock  */
+    if (db_locked == LOCK_EXCL) {
+        if (get_lock(LOCK_UNLOCK, NULL) != 0) {
+            dbif_close(dbd);
+            exit(2);
+        }
+        if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD) {
+            dbif_close(dbd);
+            exit(2);
+        }
+    }
+
+
     if (comm_init(dbp, ctrlfd, clntfd) < 0) {
         dbif_close(dbd);
         exit(3);
@@ -403,8 +386,6 @@ int main(int argc, char *argv[])
     if (dbif_env_remove(dbpath) < 0)
         err++;
 
-    free_lock(lockfd);
-
     if (err)
         exit(4);
     else if (exit_sig)
index 46c0d9700b7248fae5a424dd52d9109135dfdd29..b95e1587f7e81dc56fcaf1fd9039ac3bfb5a90f4 100644 (file)
@@ -32,7 +32,7 @@
 
 #include <atalk/afp.h>
 #include <atalk/uam.h>
-#include "../afpd/globals.h"
+#include <atalk/globals.h>
 
 /* Number of bits for p which we generate. Everybode out there uses 512, so we beet them */
 #define PRIMEBITS 1024
index 80bdc14b7a94fc42842723543b06d8d6ba760f4d..e4939e29082a5954c7f5cac4eeac6da43f658d24 100644 (file)
@@ -8,4 +8,4 @@ atalkinclude_HEADERS = \
        server_ipc.h tdb.h uam.h unicode.h util.h uuid.h volinfo.h \
        zip.h ea.h acl.h unix.h directory.h hash.h volume.h
 
-noinst_HEADERS = cnid_dbd_private.h cnid_private.h bstradd.h bstrlib.h errchk.h ftw.h fce_api.h
+noinst_HEADERS = cnid_dbd_private.h cnid_private.h bstradd.h bstrlib.h errchk.h ftw.h globals.h fce_api.h
index d15c048940e772229334e10f5f50aad76eefb9da..801db32643b714a7af010fcee807ff1265b503f7 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. */
+    uint32_t    d_rights_cache;       /* cached rights combinded from mode and possible ACL */
+
+    /* 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 babd8288ce3fc55745b5acb7d2897479822ac4f5..6c8236d750992e84c03db2e0f28fe0ee49d27f47 100644 (file)
@@ -14,6 +14,7 @@
 #include <netinet/in.h>
 #include <atalk/afp.h>
 #include <atalk/server_child.h>
+#include <atalk/globals.h>
 #include <netatalk/endian.h>
 
 #ifdef __OpenBSD__
@@ -59,6 +60,7 @@ struct dsi_block {
 /* child and parent processes might interpret a couple of these
  * differently. */
 typedef struct DSI {
+  AFPObj *AFPobj;
   dsi_proto protocol;
   struct dsi_block header;
   struct sockaddr_storage server, client;
@@ -157,6 +159,7 @@ typedef struct DSI {
 #define DSI_RECONSOCKET      (1 << 7) /* we have a new socket from primary reconnect */
 #define DSI_RECONINPROG      (1 << 8) /* used in the new session in reconnect */
 #define DSI_AFP_LOGGED_OUT   (1 << 9) /* client called afp_logout, quit on next EOF from socket */
+#define DSI_GOT_ECONNRESET   (1 << 10) /* got ECONNRESET from client => exit */
 
 /* basic initialization: dsi_init.c */
 extern DSI *dsi_init (const dsi_proto /*protocol*/,
@@ -185,6 +188,7 @@ extern ssize_t dsi_stream_write (DSI *, void *, const size_t, const int mode);
 extern size_t dsi_stream_read (DSI *, void *, const size_t);
 extern int dsi_stream_send (DSI *, void *, size_t);
 extern int dsi_stream_receive (DSI *, void *, const size_t, size_t *);
+extern int dsi_disconnect(DSI *dsi);
 
 #ifdef WITH_SENDFILE
 extern ssize_t dsi_stream_read_file(DSI *, int, off_t off, const size_t len);
diff --git a/include/atalk/globals.h b/include/atalk/globals.h
new file mode 100644 (file)
index 0000000..cca15f5
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1990,1993 Regents of The University of Michigan.
+ * All Rights Reserved.  See COPYRIGHT.
+ */
+
+#ifndef AFPD_GLOBALS_H
+#define AFPD_GLOBALS_H 1
+
+#include <sys/param.h>
+#include <sys/cdefs.h>
+
+#ifdef ADMIN_GRP
+#include <grp.h>
+#include <sys/types.h>
+#endif /* ADMIN_GRP */
+
+#ifdef HAVE_NETDB_H
+#include <netdb.h>  /* this isn't header-protected under ultrix */
+#endif /* HAVE_NETDB_H */
+
+#include <netatalk/at.h>
+#include <atalk/afp.h>
+#include <atalk/compat.h>
+#include <atalk/unicode.h>
+#include <atalk/uam.h>
+
+/* #define DOSFILELEN 12 */             /* Type1, DOS-compat*/
+#define MACFILELEN 31                   /* Type2, HFS-compat */
+#define UTF8FILELEN_EARLY 255           /* Type3, early Mac OS X 10.0-10.4.? */
+/* #define UTF8FILELEN_NAME_MAX 765 */  /* Type3, 10.4.?- , getconf NAME_MAX */
+/* #define UTF8FILELEN_SPEC 0xFFFF */   /* Type3, spec on document */
+/* #define HFSPLUSFILELEN 510 */        /* HFS+ spec, 510byte = 255codepoint */
+
+#define MAXUSERLEN 256
+
+#define OPTION_DEBUG         (1 << 0)
+#define OPTION_USERVOLFIRST  (1 << 1)
+#define OPTION_NOUSERVOL     (1 << 2)
+#define OPTION_PROXY         (1 << 3)
+#define OPTION_CUSTOMICON    (1 << 4)
+#define OPTION_NOSLP         (1 << 5)
+#define OPTION_ANNOUNCESSH   (1 << 6)
+#define OPTION_UUID          (1 << 7)
+#define OPTION_ACL2MACCESS   (1 << 8)
+#define OPTION_NOZEROCONF    (1 << 9)
+
+#ifdef FORCE_UIDGID
+/* set up a structure for this */
+typedef struct uidgidset_t {
+    uid_t uid;
+    gid_t gid;
+} uidgidset;
+#endif /* FORCE_UIDGID */
+
+/* a couple of these options could get stuck in unions to save
+ * space. */
+struct afp_volume_name {
+    time_t     mtime;
+    char       *name;
+    char       *full_name;
+    int        loaded;
+};
+
+struct afp_options {
+    int connections, transports, tickleval, timeout, server_notif, flags, dircachesize;
+    int sleep;                  /* Maximum time allowed to sleep (in tickles) */
+    int disconnected;           /* Maximum time in disconnected state (in tickles) */
+    unsigned int tcp_sndbuf, tcp_rcvbuf;
+    unsigned char passwdbits, passwdminlen, loginmaxfail;
+    u_int32_t server_quantum;
+    int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */
+    char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
+    struct at_addr ddpaddr;
+    char *uampath, *fqdn;
+    char *pidfile;
+    char *sigconffile;
+    char *uuidconf;
+    struct afp_volume_name defaultvol, systemvol, uservol;
+    int  closevol;
+
+    char *guest, *loginmesg, *keyfile, *passwdfile;
+    char *uamlist;
+    char *authprintdir;
+    char *signatureopt;
+    unsigned char signature[16];
+    char *k5service, *k5realm, *k5keytab;
+    char *unixcodepage,*maccodepage;
+    charset_t maccharset, unixcharset; 
+    mode_t umask;
+    mode_t save_mask;
+#ifdef ADMIN_GRP
+    gid_t admingid;
+#endif /* ADMIN_GRP */
+    int    volnamelen;
+
+    /* default value for winbind authentication */
+    char *ntdomain, *ntseparator;
+    char *logconfig;
+
+    char *mimicmodel;
+};
+
+#define AFPOBJ_TMPSIZ (MAXPATHLEN)
+typedef struct _AFPObj {
+    int proto;
+    unsigned long servernum;
+    void *handle;               /* either (DSI *) or (ASP *) */
+    void *config; 
+    struct afp_options options;
+    char *Obj, *Type, *Zone;
+    char username[MAXUSERLEN];
+    void (*logout)(void), (*exit)(int);
+    int (*reply)(void *, int);
+    int (*attention)(void *, AFPUserBytes);
+    /* to prevent confusion, only use these in afp_* calls */
+    char oldtmp[AFPOBJ_TMPSIZ + 1], newtmp[AFPOBJ_TMPSIZ + 1];
+    void *uam_cookie; /* cookie for uams */
+    struct session_info  sinfo;
+    uid_t uid;         /* client running user id */
+    int ipc_fd; /* anonymous PF_UNIX socket for IPC with afpd parent */
+#ifdef FORCE_UIDGID
+    int                 force_uid;
+    uidgidset          uidgid;
+#endif
+} AFPObj;
+
+/* typedef for AFP functions handlers */
+typedef int (*AFPCmd)(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
+
+/* afp_dsi.c */
+extern AFPObj *AFPobj;
+
+extern int             afp_version;
+extern int             afp_errno;
+extern unsigned char   nologin;
+extern struct dir      *curdir;
+extern char            getwdbuf[];
+
+/* FIXME CNID */
+extern const char *Cnid_srv;
+extern const char *Cnid_port;
+
+extern int  get_afp_errno   (const int param);
+extern void afp_options_init (struct afp_options *);
+extern int afp_options_parse (int, char **, struct afp_options *);
+extern int afp_options_parseline (char *, struct afp_options *);
+extern void afp_options_free (struct afp_options *,
+                                      const struct afp_options *);
+extern void setmessage (const char *);
+extern void readmessage (AFPObj *);
+
+/* gettok.c */
+extern void initline   (int, char *);
+extern int  parseline  (int, char *);
+
+/* afp_util.c */
+extern const char *AfpNum2name (int );
+extern const char *AfpErr2name(int err);
+
+/* directory.c */
+extern struct dir rootParent;
+
+#ifndef NO_DDP
+extern void afp_over_asp (AFPObj *);
+#endif /* NO_DDP */
+extern void afp_over_dsi (AFPObj *);
+
+#endif /* globals.h */
index 2e75b461b53c0ab198b2a8f44aecf08057c32ea3..ec67a4e3f27e1768af46f5dcce4916c89c7a3720 100644 (file)
@@ -75,6 +75,7 @@
 #  define _PATH_AFPDLOCK       ATALKPATHCAT(_PATH_LOCKDIR,"afpd.pid")
 #else
 #  define _PATH_AFPDLOCK       ATALKPATHCAT(_PATH_LOCKDIR,"afpd")
+#define _PATH_AFP_IPC       ATALKPATHCAT(_PATH_LOCKDIR,"afpd_ipc")
 #endif
 
 /*
index b45a3a42daf088c958618a69a6f350c4ff6653a4..f548ce4d5ab8a0db8a673403d93d268f6de91189 100644 (file)
@@ -27,8 +27,9 @@ typedef struct server_child_data {
   pid_t     pid;               /* afpd worker process pid (from the worker afpd process )*/
   uid_t     uid;               /* user id of connected client (from the worker afpd process) */
   int       valid;             /* 1 if we have a clientid */
-  uint32_t  time;              /* client boot time (from the mac client) */
   int       killed;            /* 1 if we already tried to kill the client */
+  int       disasociated; /* 1 if this is not a child, but a child from a previous afpd master */
+  uint32_t  time;              /* client boot time (from the mac client) */
   uint32_t  idlen;             /* clientid len (from the Mac client) */
   char      *clientid;  /* clientid (from the Mac client) */
   int       ipc_fds[2]; /* socketpair for IPC bw */
index 332897a0993bd2f34ca3be79f942bfd75fe27818..aca04f80f8f33ea6b180083c252452836c21caff 100644 (file)
@@ -2,11 +2,15 @@
 #define ATALK_SERVER_IPC_H
 
 #include <atalk/server_child.h>
+#include <atalk/globals.h>
 
 #define IPC_DISCOLDSESSION   0
 #define IPC_GETSESSION       1
 
-int ipc_server_read(server_child *children, int fd);
-int ipc_child_write(int fd, uint16_t command, int len, void *token);
+extern int ipc_server_uds(const char *name);
+extern int ipc_client_uds(const char *name);
+extern int reconnect_ipc(AFPObj *);
+extern int ipc_server_read(server_child *children, int fd);
+extern int ipc_child_write(int fd, uint16_t command, int len, void *token);
 
 #endif /* IPC_GETSESSION_LOGIN */
index 0fb199b3962f9103fb839521120883112eff9a88..ba62783aa657aad332875986cbb6854897993c9f 100644 (file)
@@ -77,6 +77,8 @@ struct session_info {
   size_t  cryptedkey_len;
   void    *sessiontoken;        /* session token sent to the client on FPGetSessionToken*/
   size_t  sessiontoken_len;
+  void    *clientid;          /* whole buffer cotaining eg idlen, id and boottime */
+  size_t  clientid_len;
 };
 
 /* register and unregister uams with these functions */
index 811c0ee661a6af7316b51a045034fd654b464447..277ac98975d7d430d50d999cfe6eb57ba7447bbb 100644 (file)
@@ -147,7 +147,7 @@ extern void apply_ip_mask(struct sockaddr *ai, int maskbits);
 extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2);
 
 /* Structures and functions dealing with dynamic pollfd arrays */
-enum fdtype {IPC_FD, LISTEN_FD};
+enum fdtype {IPC_FD, LISTEN_FD, DISASOCIATED_IPC_FD};
 struct polldata {
     enum fdtype fdtype; /* IPC fd or listening socket fd                 */
     void *data;         /* pointer to AFPconfig for listening socket and *
index a9432675af5dd2dac68dd0d5352676a6a0d9213e..ebaf2b851d392e9115356a8487eb878f6de60a11 100644 (file)
 typedef unsigned char *uuidp_t;
 typedef unsigned char atalk_uuid_t[UUID_BINSIZE];
 
-typedef enum {UUID_USER = 1, UUID_GROUP, UUID_LOCAL} uuidtype_t;
+typedef enum {UUID_USER   = 0,
+              UUID_GROUP  = 1,
+              UUID_ENOENT = 4} /* used as bit flag */
+    uuidtype_t;
+#define UUIDTYPESTR_MASK 3
 extern char *uuidtype[];
 
 /* afp_options.c needs these. defined in libatalk/ldap.c */
@@ -46,5 +50,5 @@ extern int getnamefromuuid( const uuidp_t uuidp, char **name, uuidtype_t *type);
 extern void localuuid_from_id(unsigned char *buf, uuidtype_t type, unsigned int id);
 extern const char *uuid_bin2string(unsigned char *uuid);
 extern void uuid_string2bin( const char *uuidstring, uuidp_t uuid);
-
+extern void uuidcache_dump(void);
 #endif /* AFP_UUID_H */
index c2db33db7ccc6d1a4a6268e7a64f5cfdab12e0ad..01de038d3c5ae19a09f2d42720e00597585156de 100644 (file)
@@ -65,7 +65,9 @@ struct vol {
     char            *v_gvs;
     void            *v_nfsclient;
     int             v_nfs;
-
+    uintmax_t       v_tm_used;  /* used bytes on a TM volume */
+    uintmax_t       v_written;  /* amount of data written in afp_write, reset every time a FCE_TM_SIZE event is sent */
+    
     /* only when opening/closing volumes or in error */
     int             v_casefold;
     char            *v_localname;   /* as defined in AppleVolumes.default */
@@ -136,10 +138,7 @@ struct vol {
 #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
+#define AFPVOL_NONETIDS  (1 << 26)   /* signal the client it shall do privelege mapping */
 
 /* Extended Attributes vfs indirection  */
 #define AFPVOL_EA_NONE           0   /* No EAs */
@@ -178,7 +177,7 @@ int wincheck(const struct vol *vol, const char *path);
 #define VOLPBIT_ATTR_BLANKACCESS  (1 << 4)
 #define VOLPBIT_ATTR_UNIXPRIV     (1 << 5)
 #define VOLPBIT_ATTR_UTF8         (1 << 6)
-#define VOLPBIT_ATTR_NONETUID     (1 << 7)
+#define VOLPBIT_ATTR_NONETIDS     (1 << 7)
 #define VOLPBIT_ATTR_EXT_ATTRS    (1 << 10)
 #define VOLPBIT_ATTR_ACLS         (1 << 11)
 #define VOLPBIT_ATTR_TM           (1 << 13)
index 585bb4801e8d4a727531f6ef3a4bff19f9d7c001..9fe8405ff72a3e9b9e749cbbeb8b97ce5e559d8f 100644 (file)
@@ -44,7 +44,7 @@ cacheduser_t *uuidcache[256];   /* indexed by hash of uuid */
  * helper function
  ********************************************************/
 
-static int dumpcache() {
+void uuidcache_dump(void) {
     int i;
     int ret = 0;
     cacheduser_t *entry;
@@ -59,8 +59,14 @@ static int dumpcache() {
                     continue;
                 if (strftime(timestr, 200, "%c", tmp) == 0)
                     continue;
-                LOG(log_debug9, logtype_default, "namecache{%d}: name:%s, uuid:%s, type: %s, cached: %s",
-                    i, entry->name, uuid_bin2string(entry->uuid), uuidtype[entry->type], timestr);
+                LOG(log_debug, logtype_default,
+                    "namecache{%d}: name:%s, uuid:%s, type%s: %s, cached: %s",
+                    i,
+                    entry->name,
+                    uuid_bin2string(entry->uuid),
+                    (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
+                    uuidtype[entry->type & UUIDTYPESTR_MASK],
+                    timestr);
             } while ((entry = entry->next) != NULL);
         }
     }
@@ -74,13 +80,17 @@ static int dumpcache() {
                     continue;
                 if (strftime(timestr, 200, "%c", tmp) == 0)
                     continue;
-                LOG(log_debug9, logtype_default, "uuidcache{%d}: uuid:%s, name:%s, type: %s, cached: %s",
-                    i, uuid_bin2string(entry->uuid), entry->name, uuidtype[entry->type], timestr);
+                LOG(log_debug, logtype_default,
+                    "uuidcache{%d}: uuid:%s, name:%s, type%s: %s, cached: %s",
+                    i,
+                    uuid_bin2string(entry->uuid),
+                    entry->name,
+                    (entry->type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
+                    uuidtype[entry->type & UUIDTYPESTR_MASK],
+                    timestr);
             } while ((entry = entry->next) != NULL);
         }
     }
-
-    return ret;
 }
 
 /* hash string it into unsigned char */
@@ -121,10 +131,6 @@ int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t
     cacheduser_t *cacheduser = NULL;
     unsigned char hash;
 
-#ifdef DEBUG
-    dumpcache();
-#endif
-
     /* allocate mem and copy values */
     name = malloc(strlen(inname)+1);
     if (!name) {
@@ -181,26 +187,25 @@ cleanup:
             free(cacheduser);
     }
 
-#ifdef DEBUG
-    dumpcache();
-#endif
-
     return ret;
 }
 
-/* 
- * Caller provides buffer uuid for result
+/*!
+ * Search cache by name and uuid type
+ *
+ * @args name     (r)  name to search
+ * @args type     (rw) type (user or group) of name, returns found type here which might
+ *                     mark it as a negative entry
+ * @args uuid     (w)  found uuid is returned here
+ * @returns       0 on sucess, entry found
+ *                -1 no entry found
  */
-int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
+int search_cachebyname(const char *name, uuidtype_t *type, uuidp_t uuid) {
     int ret;
     unsigned char hash;
     cacheduser_t *entry;
     time_t tim;
 
-#ifdef DEBUG
-    dumpcache();
-#endif
-
     hash = hashstring((unsigned char *)name);
 
     if (namecache[hash] == NULL)
@@ -209,11 +214,11 @@ int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
     entry = namecache[hash];
     while (entry) {
         ret = strcmp(entry->name, name);
-        if (ret == 0 && type == entry->type) {
+        if (ret == 0 && *type == (entry->type & UUIDTYPESTR_MASK)) {
             /* found, now check if expired */
             tim = time(NULL);
             if ((tim - entry->creationtime) > CACHESECONDS) {
-                LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\'%s\' in queue {%d}", entry->name, hash);
+                LOG(log_debug, logtype_default, "search_cachebyname: expired: name:\"%s\"", entry->name);
                 /* remove item */
                 if (entry->prev) {
                     /* 2nd to last in queue */
@@ -229,23 +234,16 @@ int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid) {
                 free(entry->name);
                 free(entry->uuid);
                 free(entry);
-#ifdef DEBUG
-                dumpcache();
-#endif
                 return -1;
             } else {
                 memcpy(uuid, entry->uuid, UUID_BINSIZE);
-#ifdef DEBUG
-                dumpcache();
-#endif
+                *type = entry->type;
                 return 0;
             }
         }
         entry = entry->next;
     }
-#ifdef DEBUG
-    dumpcache();
-#endif
+
     return -1;
 }
 
@@ -258,10 +256,6 @@ int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
     cacheduser_t *entry;
     time_t tim;
 
-#ifdef DEBUG
-    dumpcache();
-#endif
-
     hash = hashuuid(uuidp);
 
     if (! uuidcache[hash])
@@ -288,27 +282,17 @@ int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type) {
                 free(entry->name);
                 free(entry->uuid);
                 free(entry);
-#ifdef DEBUG
-                dumpcache();
-#endif
                 return -1;
             } else {
                 *name = malloc(strlen(entry->name)+1);
                 strcpy(*name, entry->name);
                 *type = entry->type;
-#ifdef DEBUG
-                dumpcache();
-#endif
                 return 0;
             }
         }
         entry = entry->next;
     }
 
-#ifdef DEBUG
-    dumpcache();
-#endif
-
     return -1;
 }
 
@@ -320,10 +304,6 @@ int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const
     cacheduser_t *entry;
     unsigned char hash;
 
-#ifdef DEBUG
-    dumpcache();
-#endif
-
     /* allocate mem and copy values */
     name = malloc(strlen(inname)+1);
     if (!name) {
@@ -380,9 +360,5 @@ cleanup:
             free(cacheduser);
     }
 
-#ifdef DEBUG
-    dumpcache();
-#endif
-
     return ret;
 }
index 7db8ecdc92453930e721232fba2d82db32652d78..252d7da2681742cda7772c43eb793f76204853ab 100644 (file)
  * Interface
  ********************************************************/
 
-/* 
- *   name: search for this name
- *   type: of type USER or GROUP
- *   uuid: if found copies uuid into this buffer
- * returns 0 on success, !=0 if not found or on errors
- */
-extern int search_cachebyname( const char *name, uuidtype_t type, uuidp_t uuid);
-
-/* 
- *   inname: name
- *   inuuid: uuid
- *   type: USER or GROUP
- *   (uid: unused)
- * returns 0 on success, !=0 on memory errors
- */
+extern int search_cachebyname( const char *name, uuidtype_t *type, uuidp_t uuid);
 extern int add_cachebyname( const char *inname, const uuidp_t inuuid, const uuidtype_t type, const unsigned long uid);
-
-/* same as above but for the uuid cache */
 extern int search_cachebyuuid( uuidp_t uuidp, char **name, uuidtype_t *type);
 extern int add_cachebyuuid( uuidp_t inuuid, const char *inname, uuidtype_t type, const unsigned long uid);
 
index 074d9deb8a76c1da0343292b6250d940ee09d5c2..fc64c0455f486f8004be22bea32ba12346c4a6b1 100644 (file)
@@ -33,7 +33,7 @@
 #include "aclldap.h"
 #include "cache.h"
 
-char *uuidtype[] = {"NULL","USER", "GROUP", "LOCAL"};
+char *uuidtype[] = {"USER", "GROUP", "LOCAL"};
 
 /********************************************************
  * Public helper function
@@ -41,7 +41,7 @@ char *uuidtype[] = {"NULL","USER", "GROUP", "LOCAL"};
 
 static unsigned char local_group_uuid[] = {0xab, 0xcd, 0xef,
                                            0xab, 0xcd, 0xef,
-                                           0xab, 0xcd, 0xef, 
+                                           0xab, 0xcd, 0xef,
                                            0xab, 0xcd, 0xef};
 
 static unsigned char local_user_uuid[] = {0xff, 0xff, 0xee, 0xee, 0xdd, 0xdd,
@@ -67,7 +67,7 @@ void localuuid_from_id(unsigned char *buf, uuidtype_t type, unsigned int id)
     return;
 }
 
-/* 
+/*
  * convert ascii string that can include dashes to binary uuid.
  * caller must provide a buffer.
  */
@@ -100,9 +100,9 @@ void uuid_string2bin( const char *uuidstring, uuidp_t uuid) {
 
 }
 
-/*! 
+/*!
  * Convert 16 byte binary uuid to neat ascii represantation including dashes.
- * 
+ *
  * Returns pointer to static buffer.
  */
 const char *uuid_bin2string(unsigned char *uuid) {
@@ -132,24 +132,34 @@ const char *uuid_bin2string(unsigned char *uuid) {
  *   type: and type (UUID_USER or UUID_GROUP)
  *   uuid: pointer to uuid_t storage that the caller must provide
  * returns 0 on success !=0 on errror
- */  
+ */
 int getuuidfromname( const char *name, uuidtype_t type, uuidp_t uuid) {
     int ret = 0;
+    uuidtype_t mytype = type;
+    char nulluuid[16] = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0};
 #ifdef HAVE_LDAP
     char *uuid_string = NULL;
 #endif
-    ret = search_cachebyname( name, type, uuid);
+
+    ret = search_cachebyname(name, &mytype, uuid);
+
     if (ret == 0) {
         /* found in cache */
-        LOG(log_debug, logtype_afpd, "getuuidfromname{cache}: name: %s, type: %s -> UUID: %s",
-            name, uuidtype[type], uuid_bin2string(uuid));
+        LOG(log_debug, logtype_afpd,
+            "getuuidfromname{cache}: name: %s, type%s: %s -> UUID: %s",
+            name,
+            (mytype & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
+            uuidtype[type & UUIDTYPESTR_MASK],
+            uuid_bin2string(uuid));
+        if ((mytype & UUID_ENOENT) == UUID_ENOENT)
+            return -1;
     } else  {
         /* if not found in cache */
 #ifdef HAVE_LDAP
         if ((ret = ldap_getuuidfromname( name, type, &uuid_string)) == 0) {
             uuid_string2bin( uuid_string, uuid);
-            LOG(log_debug, logtype_afpd, "getuuidfromname{local}: name: %s, type: %s -> UUID: %s",
-                name, uuidtype[type], uuid_bin2string(uuid));
+            LOG(log_debug, logtype_afpd, "getuuidfromname{LDAP}: name: %s, type: %s -> UUID: %s",
+                name, uuidtype[type & UUIDTYPESTR_MASK], uuid_bin2string(uuid));
         } else {
             LOG(log_debug, logtype_afpd, "getuuidfromname(\"%s\",t:%u): no result from ldap search",
                 name, type);
@@ -161,24 +171,31 @@ int getuuidfromname( const char *name, uuidtype_t type, uuidp_t uuid) {
                 struct passwd *pwd;
                 if ((pwd = getpwnam(name)) == NULL) {
                     LOG(log_error, logtype_afpd, "getuuidfromname(\"%s\",t:%u): unknown user",
-                        name, uuidtype[type]);
-                    goto cleanup;
+                        name, uuidtype[type & UUIDTYPESTR_MASK]);
+                    mytype |= UUID_ENOENT;
+                    memcpy(uuid, nulluuid, 16);
+                } else {
+                    localuuid_from_id(uuid, UUID_USER, pwd->pw_uid);
+                    ret = 0;
+                    LOG(log_debug, logtype_afpd, "getuuidfromname{local}: name: %s, type: %s -> UUID: %s",
+                        name, uuidtype[type & UUIDTYPESTR_MASK], uuid_bin2string(uuid));
                 }
-                localuuid_from_id(uuid, UUID_USER, pwd->pw_uid);
             } else {
                 struct group *grp;
                 if ((grp = getgrnam(name)) == NULL) {
                     LOG(log_error, logtype_afpd, "getuuidfromname(\"%s\",t:%u): unknown user",
-                        name, uuidtype[type]);
-                    goto cleanup;
+                        name, uuidtype[type & UUIDTYPESTR_MASK]);
+                    mytype |= UUID_ENOENT;
+                    memcpy(uuid, nulluuid, 16);
+                } else {
+                    localuuid_from_id(uuid, UUID_GROUP, grp->gr_gid);
+                    ret = 0;
+                    LOG(log_debug, logtype_afpd, "getuuidfromname{local}: name: %s, type: %s -> UUID: %s",
+                        name, uuidtype[type & UUIDTYPESTR_MASK], uuid_bin2string(uuid));
                 }
-                localuuid_from_id(uuid, UUID_GROUP, grp->gr_gid);
             }
-            LOG(log_debug, logtype_afpd, "getuuidfromname{local}: name: %s, type: %s -> UUID: %s",
-                name, uuidtype[type], uuid_bin2string(uuid));
         }
-        ret = 0;
-        add_cachebyname( name, uuid, type, 0);
+        add_cachebyname(name, uuid, mytype, 0);
     }
 
 cleanup:
@@ -198,39 +215,73 @@ cleanup:
  * Caller must free name appropiately.
  */
 int getnamefromuuid(const uuidp_t uuidp, char **name, uuidtype_t *type) {
-    int ret;
+    int ret = 0;
+    uid_t uid;
+    gid_t gid;
+    struct passwd *pwd;
+    struct group *grp;
 
-    ret = search_cachebyuuid( uuidp, name, type);
-    if (ret == 0) {
+    if (search_cachebyuuid(uuidp, name, type) == 0) {
         /* found in cache */
-        LOG(log_debug9, logtype_afpd, "getnamefromuuid{cache}: UUID: %s -> name: %s, type:%s",
-            uuid_bin2string(uuidp), *name, uuidtype[*type]);
-    } else {
-        /* not found in cache */
-
-        /* Check if UUID is a client local one */
-        if (memcmp(uuidp, local_user_uuid, 12) == 0
-            || memcmp(uuidp, local_group_uuid, 12) == 0) {
-            LOG(log_debug, logtype_afpd, "getnamefromuuid: local UUID: %" PRIu32 "",
-                ntohl(*(uint32_t *)(uuidp + 12)));
-            *type = UUID_LOCAL;
-            *name = strdup("UUID_LOCAL");
-            return 0;
+        LOG(log_debug, logtype_afpd,
+            "getnamefromuuid{cache}: UUID: %s -> name: %s, type%s: %s",
+            uuid_bin2string(uuidp),
+            *name,
+            (*type & UUID_ENOENT) == UUID_ENOENT ? "[negative]" : "",
+            uuidtype[(*type) & UUIDTYPESTR_MASK]);
+        if ((*type & UUID_ENOENT) == UUID_ENOENT)
+            return -1;
+        return 0;
+    }
+
+    /* not found in cache */
+
+    /* Check if UUID is a client local one */
+    if (memcmp(uuidp, local_user_uuid, 12) == 0) {
+        *type = UUID_USER;
+        uid = ntohl(*(uint32_t *)(uuidp + 12));
+        if ((pwd = getpwuid(uid)) == NULL) {
+            /* not found, add negative entry to cache */
+            add_cachebyuuid(uuidp, "UUID_ENOENT", UUID_ENOENT, 0);
+            ret = -1;
+        } else {
+            *name = strdup(pwd->pw_name);
+            add_cachebyuuid(uuidp, *name, *type, 0);
+            ret = 0;
         }
+        LOG(log_debug, logtype_afpd,
+            "getnamefromuuid{local}: UUID: %s -> name: %s, type:%s",
+            uuid_bin2string(uuidp), *name, uuidtype[(*type) & UUIDTYPESTR_MASK]);
+        return ret;
+    } else if (memcmp(uuidp, local_group_uuid, 12) == 0) {
+        *type = UUID_GROUP;
+        gid = ntohl(*(uint32_t *)(uuidp + 12));
+        if ((grp = getgrgid(gid)) == NULL) {
+            /* not found, add negative entry to cache */
+            add_cachebyuuid(uuidp, "UUID_ENOENT", UUID_ENOENT, 0);
+            ret = -1;
+        } else {
+            *name = strdup(grp->gr_name);
+            add_cachebyuuid(uuidp, *name, *type, 0);
+            ret = 0;
+        }
+        return ret;
+    }
 
 #ifdef HAVE_LDAP
-        ret = ldap_getnamefromuuid(uuid_bin2string(uuidp), name, type);
-        if (ret != 0) {
-            LOG(log_warning, logtype_afpd, "getnamefromuuid(%s): no result from ldap_getnamefromuuid",
-                uuid_bin2string(uuidp));
-            goto cleanup;
-        }
-        add_cachebyuuid( uuidp, *name, *type, 0);
-        LOG(log_debug, logtype_afpd, "getnamefromuuid{LDAP}: UUID: %s -> name: %s, type:%s",
-            uuid_bin2string(uuidp), *name, uuidtype[*type]);
-#endif
+    ret = ldap_getnamefromuuid(uuid_bin2string(uuidp), name, type);
+    if (ret != 0) {
+        LOG(log_warning, logtype_afpd, "getnamefromuuid(%s): no result from ldap_getnamefromuuid",
+            uuid_bin2string(uuidp));
+        add_cachebyuuid(uuidp, "UUID_ENOENT", UUID_ENOENT, 0);
+        return -1;
     }
+#endif
 
-cleanup:
-    return ret;
+    add_cachebyuuid(uuidp, *name, *type, 0);
+
+    LOG(log_debug, logtype_afpd, "getnamefromuuid{LDAP}: UUID: %s -> name: %s, type:%s",
+        uuid_bin2string(uuidp), *name, uuidtype[(*type) & UUIDTYPESTR_MASK]);
+
+    return 0;
 }
index 4ad6883168a4d64098979e2be525588a266042fb..4c45eb1dc9c6a7492a9d50b078dc514bf249b4fb 100644 (file)
@@ -332,7 +332,7 @@ static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd
     ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY);
 
     if (ret != sizeof(struct cnid_dbd_rply)) {
-        LOG(log_error, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s",
+        LOG(log_debug, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s",
             db->db_dir, ret == -1 ? strerror(errno) : "closed");
         rply->name = nametmp;
         return -1;
index 221ac47af76d50f4a01f777d8e17979207d1d578..ea22c2dca5cb096f5846c351913a82fd15ff0964 100644 (file)
@@ -66,7 +66,7 @@ afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval
   default: /* parent */
     /* using SIGQUIT is hokey, but the child might not have
      * re-established its signal handler for SIGTERM yet. */
-    if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds)) < 0) {
+    if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds)) ==  NULL) {
       LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
       dsi->header.dsi_flags = DSIFL_REPLY;
       dsi->header.dsi_code = DSIERR_SERVBUSY;
index 680967e8be1f543b833d6ae9e6c6caf70d59f532..0fec3260529b494bec92fbe2ebeac66be673f39f 100644 (file)
@@ -122,6 +122,135 @@ static int dsi_peek(DSI *dsi)
     return 0;
 }
 
+/* 
+ * Return all bytes up to count from dsi->buffer if there are any buffered there
+ */
+static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
+{
+    size_t nbe = 0;
+
+    if (dsi->buffer == NULL)
+        /* afpd master has no DSI buffering */
+        return 0;
+
+    LOG(log_maxdebug, logtype_dsi, "from_buf: %u bytes", count);
+    
+    nbe = dsi->eof - dsi->start;
+
+    if (nbe > 0) {
+        nbe = min((size_t)nbe, count);
+        memcpy(buf, dsi->start, nbe);
+        dsi->start += nbe;
+
+        if (dsi->eof == dsi->start)
+            dsi->start = dsi->eof = dsi->buffer;
+    }
+
+    LOG(log_debug, logtype_dsi, "from_buf(read: %u, unread:%u , space left: %u): returning %u",
+        dsi->start - dsi->buffer, dsi->eof - dsi->start, dsi->end - dsi->eof, nbe);
+
+    return nbe;
+}
+
+/*
+ * Get bytes from buffer dsi->buffer or read from socket
+ *
+ * 1. Check if there are bytes in the the dsi->buffer buffer.
+ * 2. Return bytes from (1) if yes.
+ *    Note: this may return fewer bytes then requested in count !!
+ * 3. If the buffer was empty, read from the socket.
+ */
+static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
+{
+    ssize_t len;
+
+    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes)", count);
+
+    if (!count)
+        return 0;
+
+    len = from_buf(dsi, buf, count); /* 1. */
+    if (len)
+        return len;             /* 2. */
+  
+    len = readt(dsi->socket, buf, count, 0, 1); /* 3. */
+
+    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes): got: %d", count, len);
+
+    return len;
+}
+
+/*
+ * Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads
+ * this tries to read larger chunks (8192 bytes) into a buffer.
+ */
+static size_t dsi_buffered_stream_read(DSI *dsi, u_int8_t *data, const size_t length)
+{
+  size_t len;
+  size_t buflen;
+
+  LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length);
+  
+  len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */
+  dsi->read_count += len;
+  if (len == length) {          /* got enough bytes from there ? */
+      return len;               /* yes */
+  }
+
+  /* fill the buffer with 8192 bytes or until buffer is full */
+  buflen = min(8192, dsi->end - dsi->eof);
+  if (buflen > 0) {
+      ssize_t ret;
+      ret = read(dsi->socket, dsi->eof, buflen);
+      if (ret > 0)
+          dsi->eof += ret;
+  }
+
+  /* now get the remaining data */
+  if ((buflen = dsi_stream_read(dsi, data + len, length - len)) != length - len)
+      return 0;
+  len += buflen;
+
+  return len;
+}
+
+/* ---------------------------------------
+*/
+static void block_sig(DSI *dsi)
+{
+  dsi->in_write++;
+}
+
+/* ---------------------------------------
+*/
+static void unblock_sig(DSI *dsi)
+{
+  dsi->in_write--;
+}
+
+/*********************************************************************************
+ * Public functions
+ *********************************************************************************/
+
+/*!
+ * Communication error with the client, enter disconnected state
+ *
+ * 1. close the socket
+ * 2. set the DSI_DISCONNECTED flag
+ *
+ * @returns  0 if successfully entered disconnected state
+ *          -1 if ppid is 1 which means afpd master died
+ *             or euid == 0 ie where still running as root (unauthenticated session)
+ */
+int dsi_disconnect(DSI *dsi)
+{
+    dsi->proto_close(dsi);          /* 1 */
+    dsi->flags |= DSI_DISCONNECTED; /* 2 */
+    if (geteuid() == 0)
+        return -1;
+    return 0;
+}
+
 /* ------------------------------
  * write raw data. return actual bytes read. checks against EINTR
  * aren't necessary if all of the signals have SA_RESTART
@@ -137,6 +266,9 @@ ssize_t dsi_stream_write(DSI *dsi, void *data, const size_t length, int mode)
 
   LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
 
+  if (dsi->flags & DSI_DISCONNECTED)
+      return -1;
+
   while (written < length) {
       len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
       if (len >= 0) {
@@ -188,6 +320,9 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
 
   LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
 
+  if (dsi->flags & DSI_DISCONNECTED)
+      return -1;
+
   dsi->in_write++;
   written = 0;
 
@@ -227,63 +362,6 @@ ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t le
 }
 #endif
 
-/* 
- * Return all bytes up to count from dsi->buffer if there are any buffered there
- */
-static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
-{
-    size_t nbe = 0;
-
-    if (dsi->buffer == NULL)
-        /* afpd master has no DSI buffering */
-        return 0;
-
-    LOG(log_maxdebug, logtype_dsi, "from_buf: %u bytes", count);
-    
-    nbe = dsi->eof - dsi->start;
-
-    if (nbe > 0) {
-        nbe = min((size_t)nbe, count);
-        memcpy(buf, dsi->start, nbe);
-        dsi->start += nbe;
-
-        if (dsi->eof == dsi->start)
-            dsi->start = dsi->eof = dsi->buffer;
-    }
-
-    LOG(log_debug, logtype_dsi, "from_buf(read: %u, unread:%u , space left: %u): returning %u",
-        dsi->start - dsi->buffer, dsi->eof - dsi->start, dsi->end - dsi->eof, nbe);
-
-    return nbe;
-}
-
-/*
- * Get bytes from buffer dsi->buffer or read from socket
- *
- * 1. Check if there are bytes in the the dsi->buffer buffer.
- * 2. Return bytes from (1) if yes.
- *    Note: this may return fewer bytes then requested in count !!
- * 3. If the buffer was empty, read from the socket.
- */
-static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
-{
-    ssize_t len;
-
-    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes)", count);
-
-    if (!count)
-        return 0;
-
-    len = from_buf(dsi, buf, count); /* 1. */
-    if (len)
-        return len;             /* 2. */
-  
-    len = readt(dsi->socket, buf, count, 0, 1); /* 3. */
-
-    LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes): got: %d", count, len);
-
-    return len;
-}
 
 /*
  * Essentially a loop around buf_read() to ensure "length" bytes are read
@@ -296,18 +374,23 @@ size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
   size_t stored;
   ssize_t len;
 
+  if (dsi->flags & DSI_DISCONNECTED)
+      return 0;
+
   LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes)", length);
 
   stored = 0;
   while (stored < length) {
       len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
       if (len == -1 && (errno == EINTR || errno == EAGAIN)) {
-          LOG(log_debug, logtype_dsi, "dsi_stream_read: select read loop");
+          LOG(log_maxdebug, logtype_dsi, "dsi_stream_read: select read loop");
           continue;
       } else if (len > 0) {
           stored += len;
       } else { /* eof or error */
           /* don't log EOF error if it's just after connect (OSX 10.3 probe) */
+          if (errno == ECONNRESET)
+              dsi->flags |= DSI_GOT_ECONNRESET;
           if (len || stored || dsi->read_count) {
               if (! (dsi->flags & DSI_DISCONNECTED)) {
                   LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s",
@@ -325,51 +408,6 @@ size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
   return stored;
 }
 
-/*
- * Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads
- * this tries to read larger chunks (8192 bytes) into a buffer.
- */
-static size_t dsi_buffered_stream_read(DSI *dsi, u_int8_t *data, const size_t length)
-{
-  size_t len;
-  size_t buflen;
-
-  LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length);
-  
-  len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */
-  dsi->read_count += len;
-  if (len == length) {          /* got enough bytes from there ? */
-      return len;               /* yes */
-  }
-
-  /* fill the buffer with 8192 bytes or until buffer is full */
-  buflen = min(8192, dsi->end - dsi->eof);
-  if (buflen > 0) {
-      ssize_t ret;
-      ret = read(dsi->socket, dsi->eof, buflen);
-      if (ret > 0)
-          dsi->eof += ret;
-  }
-
-  /* now get the remaining data */
-  len += dsi_stream_read(dsi, data + len, length - len);
-  return len;
-}
-
-/* ---------------------------------------
-*/
-static void block_sig(DSI *dsi)
-{
-  dsi->in_write++;
-}
-
-/* ---------------------------------------
-*/
-static void unblock_sig(DSI *dsi)
-{
-  dsi->in_write--;
-}
-
 /* ---------------------------------------
  * write data. 0 on failure. this assumes that dsi_len will never
  * cause an overflow in the data buffer. 
@@ -384,6 +422,9 @@ int dsi_stream_send(DSI *dsi, void *buf, size_t length)
   LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
       length ? length : sizeof(block));
 
+  if (dsi->flags & DSI_DISCONNECTED)
+      return 0;
+
   block[0] = dsi->header.dsi_flags;
   block[1] = dsi->header.dsi_command;
   memcpy(block + 2, &dsi->header.dsi_requestID, 
@@ -454,6 +495,9 @@ int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
 
   LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
 
+  if (dsi->flags & DSI_DISCONNECTED)
+      return 0;
+
   /* read in the header */
   if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) 
     return 0;
index 5b23ee32c970e9b7b9ec904ee917f0a727d702e0..dab888c280ca19fea8924700fab1b2cbddbd288b 100644 (file)
@@ -8,7 +8,7 @@ UnicodeData.txt is got from
 http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
 */
 
-#include <netatalk/endian.h>
+#include <stdint.h>
 #include <atalk/unicode.h>
 #include "utf16_casetable.h"
 
@@ -53,7 +53,7 @@ ucs2_t toupper_w(ucs2_t val)
 /*******************************************************************
  Convert a surrogate pair to upper case.
 *******************************************************************/
-u_int32_t toupper_sp(u_int32_t val)
+uint32_t toupper_sp(uint32_t val)
 {
     if ( val >= 0xD801DC00 && val <= 0xD801DC7F)
         return upper_table_sp_1[val-0xD801DC00];
@@ -105,7 +105,7 @@ ucs2_t tolower_w(ucs2_t val)
 /*******************************************************************
  Convert a surrogate pair to lower case.
 *******************************************************************/
-u_int32_t tolower_sp(u_int32_t val)
+uint32_t tolower_sp(uint32_t val)
 {
     if ( val >= 0xD801DC00 && val <= 0xD801DC3F)
         return lower_table_sp_1[val-0xD801DC00];
index eb98f45b290d5817461b90498a399bfb5034bbf0..e13ada1750a8019900f9856ea6f8c902a7746768 100644 (file)
@@ -542,6 +542,7 @@ void make_log_entry(enum loglevels loglevel, enum logtypes logtype,
     if (type_configs[logtype].level >= log_debug)
         goto log; /* bypass flooding checks */
 
+    goto log;
     /* Prevent flooding: hash the message and check if we got the same one recently */
     int hash = hash_message(temp_buffer) + log_src_linenumber;
 
index ecefbd2cb7502c65ff349e68b3b845f65e88d91b..7d04e0506ce1668d13097338c6625a8d0e9d2c04 100644 (file)
@@ -279,6 +279,16 @@ int server_child_transfer_session(server_child *children,
     fork = (server_child_fork *) children->fork + forkid;
     if ((child = resolve_child(fork->table, pid)) == NULL) {
         LOG(log_note, logtype_default, "Reconnect: no child[%u]", pid);
+        if (kill(pid, 0) == 0) {
+            LOG(log_note, logtype_default, "Reconnect: terminating old session[%u]", pid);
+            kill(pid, SIGTERM);
+            sleep(2);
+            if (kill(pid, 0) == 0) {
+                LOG(log_error, logtype_default, "Reconnect: killing old session[%u]", pid);
+                kill(pid, SIGKILL);
+                sleep(2);
+            }
+        }
         return 0;
     }
 
index 1115551ee4e10826f56aaa1d8fd2b807ecb25371..87ffa7763bf8848ed943147738ab690709ac8278 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <errno.h>
 #include <signal.h>
+#include <time.h>
 
 #include <atalk/server_child.h>
 #include <atalk/server_ipc.h>
 #include <atalk/logger.h>
 #include <atalk/util.h>
+#include <atalk/errchk.h>
+#include <atalk/paths.h>
+#include <atalk/globals.h>
+#include <atalk/dsi.h>
+
+#define IPC_HEADERLEN 14
+#define IPC_MAXMSGSIZE 90
 
 typedef struct ipc_header {
        uint16_t command;
@@ -99,8 +108,100 @@ static int ipc_get_session(struct ipc_header *ipc, server_child *children)
     return 0;
 }
 
-#define IPC_HEADERLEN 14
-#define IPC_MAXMSGSIZE 90
+/***********************************************************************************
+ * Public functions
+ ***********************************************************************************/
+
+/*!
+ * Listen on UNIX domain socket "name" for IPC from old sesssion
+ *
+ * @args name    (r) file name to use for UNIX domain socket
+ * @returns      socket fd, -1 on error
+ */
+int ipc_server_uds(const char *name)
+{
+    EC_INIT;
+    struct sockaddr_un address;
+    socklen_t address_length;
+    int fd = -1;
+
+    EC_NEG1_LOG( fd = socket(PF_UNIX, SOCK_STREAM, 0) );
+    EC_ZERO_LOG( setnonblock(fd, 1) );
+    unlink(name);
+    address.sun_family = AF_UNIX;
+    address_length = sizeof(address.sun_family) + sprintf(address.sun_path, name);
+    EC_ZERO_LOG( bind(fd, (struct sockaddr *)&address, address_length) );
+    EC_ZERO_LOG( listen(fd, 1024) );
+
+EC_CLEANUP:
+    if (ret != 0) {
+        return -1;
+    }
+
+    return fd;
+}
+
+/*!
+ * Connect to UNIX domain socket "name" for IPC with new afpd master
+ *
+ * 1. Connect
+ * 2. send pid, which establishes a child structure for us in the master
+ *
+ * @args name    (r) file name to use for UNIX domain socket
+ * @returns      socket fd, -1 on error
+ */
+int ipc_client_uds(const char *name)
+{
+    EC_INIT;
+    struct sockaddr_un address;
+    socklen_t address_length;
+    int fd = -1;
+    pid_t pid = getpid();
+
+    EC_NEG1_LOG( fd = socket(PF_UNIX, SOCK_STREAM, 0) );
+    EC_ZERO_LOG( setnonblock(fd, 1) );
+    address.sun_family = AF_UNIX;
+    address_length = sizeof(address.sun_family) + sprintf(address.sun_path, name);
+
+    EC_ZERO_LOG( connect(fd, (struct sockaddr *)&address, address_length) ); /* 1 */
+    LOG(log_debug, logtype_afpd, "ipc_client_uds: connected to master");
+
+    if (writet(fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
+        LOG(log_error, logtype_afpd, "ipc_client_uds: writet: %s", strerror(errno));
+        EC_FAIL;
+    }
+
+EC_CLEANUP:
+    if (ret != 0) {
+        return -1;
+    }
+    LOG(log_debug, logtype_afpd, "ipc_client_uds: fd: %d", fd);
+    return fd;
+}
+
+int reconnect_ipc(AFPObj *obj)
+{
+    int retrycount = 0;
+
+    LOG(log_debug, logtype_afpd, "reconnect_ipc: start");
+
+    close(obj->ipc_fd);
+    obj->ipc_fd = -1;
+
+    srandom(getpid());
+    sleep((random() % 5) + 5);  /* give it enough time to start */
+
+    while (retrycount++ < 10) {
+        if ((obj->ipc_fd = ipc_client_uds(_PATH_AFP_IPC)) == -1) {
+            LOG(log_error, logtype_afpd, "reconnect_ipc: cant reconnect to master");
+            sleep(1);
+            continue;
+        }
+        LOG(log_debug, logtype_afpd, "reconnect_ipc: succesfull IPC reconnect");
+        return 0;
+    }
+    return -1;
+}
 
 /* ----------------- 
  * Ipc format
@@ -108,7 +209,7 @@ static int ipc_get_session(struct ipc_header *ipc, server_child *children)
  * pid
  * uid
  * 
-*/
+ */
 
 /*!
  * Read a IPC message from a child
@@ -204,6 +305,8 @@ int ipc_child_write(int fd, uint16_t command, int len, void *msg)
    char block[IPC_MAXMSGSIZE], *p;
    pid_t pid;
    uid_t uid;
+   ssize_t ret;
+
    p = block;
 
    memset ( p, 0 , IPC_MAXMSGSIZE);
@@ -233,6 +336,10 @@ int ipc_child_write(int fd, uint16_t command, int len, void *msg)
 
    LOG(log_debug, logtype_afpd, "ipc_child_write(%s)", ipc_cmd_str[command]);
 
-   return write(fd, block, len+IPC_HEADERLEN );
+   if ((ret = writet(fd, block, len+IPC_HEADERLEN, 0, 1)) != len + IPC_HEADERLEN) {
+       return -1;
+   }
+
+   return 0;
 }
 
index 528b2646bcfe2885bd2c0450b61b4429825f1082..fe42cd76453c7ca9649817c344e2e9a5b0f82740 100644 (file)
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
-#ifndef _XOPEN_SOURCE
-# define _XOPEN_SOURCE 600
-#endif
-#ifndef __EXTENSIONS__
-# define __EXTENSIONS__
-#endif
-#ifndef _GNU_SOURCE
-# define _GNU_SOURCE
+#if !defined(__FreeBSD__)
+# ifndef _XOPEN_SOURCE
+#  define _XOPEN_SOURCE 600
+# endif
+# ifndef __EXTENSIONS__
+#  define __EXTENSIONS__
+# endif
+# ifndef _GNU_SOURCE
+#  define _GNU_SOURCE
+# endif
 #endif
 #include <unistd.h>
 #include <fcntl.h>
@@ -128,10 +130,11 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
                         goto exit;
 
                     default: /* -1 */
-                        if (errno == EINTR) {
+                        switch (errno) {
+                        case EINTR:
                             (void)gettimeofday(&now, NULL);
                             if (now.tv_sec >= end.tv_sec && now.tv_usec >= end.tv_usec) {
-                                LOG(log_warning, logtype_afpd, "select timeout %d s", timeout);
+                                LOG(log_debug, logtype_afpd, "select timeout %d s", timeout);
                                 goto exit;
                             }
                             if (now.tv_usec > end.tv_usec) {
@@ -143,10 +146,16 @@ ssize_t readt(int socket, void *data, const size_t length, int setnonblocking, i
                             }
                             FD_SET(socket, &rfds);
                             continue;
+                        case EBADF:
+                            /* possibly entered disconnected state, don't spam log here */
+                            LOG(log_debug, logtype_afpd, "select: %s", strerror(errno));
+                            stored = -1;
+                            goto exit;
+                        default:
+                            LOG(log_error, logtype_afpd, "select: %s", strerror(errno));
+                            stored = -1;
+                            goto exit;
                         }
-                        LOG(log_error, logtype_afpd, "select: %s", strerror(errno));
-                        stored = -1;
-                        goto exit;
                     }
                 } /* while (select) */
                 continue;
@@ -486,7 +495,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 +517,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 c6a1255bb7908c0ffd6885c5914dd2807ab4f7a8..716a7dc86e379df5154162b239e5e5adc338e9ce 100644 (file)
@@ -250,6 +250,11 @@ Use with
 \fBusedots\fR: make dot files invisible\&.
 .RE
 .PP
+nonetids
+.RS 4
+Try to force ACL unawareness on the client\&.
+.RE
+.PP
 limitsize
 .RS 4
 Limit disk size reporting to 2GB\&. This can be used for older Macintoshes using newer Appleshare clients\&.
@@ -277,7 +282,7 @@ a non\-zero return code from root_preexec closes the volume immediately, prevent
 .PP
 upriv
 .RS 4
-use AFP3 unix privileges\&. Become familiar with the new "unix privileges" AFP permissions concepts in MacOS X before using this option\&. See also:
+use AFP3 unix privileges\&. This should be set for OS X clients\&. Starting with Netatalk 2\&.1 it\'s part of the default config :DEFAULT: line\&. See also:
 \fBperm|fperm|dperm\fR\&.
 .RE
 .PP
index 9fc6dd3739e148722266333b3145fe3c89bc6dc8..6ce60fd41ef68274000299dbcef1746e5557e6dc 100644 (file)
@@ -201,10 +201,32 @@ for the creation of folders in Netatalk\&.
 .RE
 .SH "SIGNALS"
 .PP
-Signals that are sent to the main
+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
+SIGTERM and SIGUSR1 signals that are sent to the main
 \fBafpd\fR
 process are propagated to the children, so all will be affected\&.
 .PP
+SIGTERM
+.RS 4
+Clean exit\&. Propagates from master to childs\&.
+.RE
+.PP
+SIGQUIT
+.RS 4
+Send this to the master
+\fBafpd\fR, it will exit leaving all children running! Can be used to implement AFP service without downtime\&.
+.RE
+.PP
 SIGHUP
 .RS 4
 Sending a
@@ -223,7 +245,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 +261,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