]> arthur.barton.de Git - netatalk.git/commitdiff
Merge branch 'release-3-0-alpha2'
authorFrank Lahm <franklahm@googlemail.com>
Wed, 4 Apr 2012 10:13:17 +0000 (12:13 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Wed, 4 Apr 2012 10:13:17 +0000 (12:13 +0200)
37 files changed:
Makefile.am
NEWS
VERSION
bin/ad/ad.h
bin/ad/ad_cp.c
bin/ad/ad_util.c
configure.ac
distrib/initscripts/rc.redhat.tmpl
etc/afpd/Makefile.am
etc/afpd/afp_dsi.c
etc/afpd/afp_mdns.c
etc/afpd/enumerate.c
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/fork.c
etc/afpd/status.c
etc/afpd/volume.c
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/dbif.c
etc/netatalk/Makefile.am
etc/netatalk/netatalk.c
include/atalk/adouble.h
include/atalk/globals.h
include/atalk/volume.h
libatalk/acl/Makefile.am
libatalk/adouble/Makefile.am
libatalk/adouble/ad_conv.c [new file with mode: 0644]
libatalk/adouble/ad_open.c
libatalk/dsi/dsi_getsess.c
libatalk/unicode/charcnv.c
libatalk/util/netatalk_conf.c
libatalk/vfs/vfs.c
macros/gssapi-check.m4
macros/netatalk.m4
macros/summary.m4
man/man5/afp.conf.5.tmpl
test/afpd/Makefile.am

index ca880fffe619be3808c59005cc4780b9b1dd4d9c..5ee6b85319979f0c1e7f18a6af8fa32497a0e4a3 100644 (file)
@@ -7,3 +7,13 @@ EXTRA_DIST = CONTRIBUTORS COPYRIGHT COPYING NEWS VERSION services.atalk
 ACLOCAL_AMFLAGS = -I macros
 AUTOMAKE_OPTIONS = foreign
 
+if USE_BUILTIN_LIBEVENT
+       SUBDIRS += libevent
+endif
+
+if RUN_LDCONFIG
+install-exec-hook:
+       @printf "Running ldconfig to ensure libraries installed in system library directories are added to the dynamic linker cache ... "
+       @-@NETA_LDCONFIG@
+       @printf "done\n"
+endif
diff --git a/NEWS b/NEWS
index e79c93dec5f277a04e7315af8946753f24c2fbfc..c6f50991886bc6096be179465fcc6e83aa202edd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,26 @@
+Changes in 3.0 alpha2
+=====================
+
+* UPD: afpd: Store '.' as is and '/' as ':' on the server, don't
+       CAP hexencode as "2e" and "2f" respectively
+* UPD: afdp: Automatic name conversion, renaming files and directories
+       containing CAP sequences to their not enscaped forms
+* UPD: afpd: Correct handling of user homes and users without homes
+* UPD: afpd: Perform complete automatic adouble:v2 to adouble:ea conversion
+       as root. Previously only unlinking the adouble:v2 file was done as root
+* UPD: dbd: -C option removes CAP encoding
+* UPD: Add graceful option to RedHat init script
+* UPD: Add --disable-bundled-libevent configure options When set to yes,
+       we rely on a properly installed version on libevent CPPFLAGS and LDFLAGS
+       should be set properly to pick that up
+* UPD: Run ldconfig on Linux at the end of make install
+* FIX: afpd: ad cp on appledouble = ea volumes
+* FIX: dbd: ignore ._ appledouble files
+* REM: Volumes options "use dots" and "hex encoding"
+
 Changes in 3.0 alpha1
 =====================
+
 * NEW: Central configuration file afp.conf which replaces all previous files
 * NEW: netatalk: service controller starting and restarting afpd and cnid_metad
        as necessary
@@ -35,6 +56,8 @@ Changes in 2.2.3
 * FIX: afpd: Dont use searchdb when doing partial name search
 * FIX: afpd: Fix a possible bug handling disconnected sessions,
        NetAFP Bug ID #16
+* FIX: dbd: Don't remove BerkeleyDB if it's still in use by eg cnid_dbd, fixes
+       bug introduced in 2.2.2
 * FIX: debian initscript: start avahi-daemon (if available) before atalkd
 
 Changes in 2.2.2
diff --git a/VERSION b/VERSION
index 2f1303b0f3a0e3b9a0a5d24da2385c671cb021eb..9a9d379a3460d97af93913a3ef582d81a3e146f5 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0alpha1
\ No newline at end of file
+3.0alpha2
\ No newline at end of file
index fcfe1220115c48e43639a65ea3db3e98f681ed0b..c405ef680bb4cdbf17b86dc7fd26785e0401cc5c 100644 (file)
@@ -38,6 +38,8 @@
     }
 #endif
 
+#define ADVOL_V2_OR_EA(ad) ((ad) == AD_VERSION2 || (ad) == AD_VERSION_EA)
+
 enum logtype {STD, DBG};
 
 #define SLOG(...)                             \
index 8f14e3f18a0b3d4d7f292d03d93201125559a6af..ef995ce8cf3f159c6346a5e32a4858e9cfad8948 100644 (file)
@@ -395,7 +395,7 @@ static int copy(const char *path,
         dir = path;
     else
         dir++;
-    if (check_netatalk_dirs(dir) != NULL)
+    if (!dvolume.vol->vfs->vfs_validupath(dvolume.vol, dir))
         return FTW_SKIP_SUBTREE;
 
     /*
@@ -510,17 +510,18 @@ static int copy(const char *path,
         }
 
         /* Create ad dir and copy ".Parent" */
-        if (dvolume.vol->v_path && dvolume.vol->v_adouble == AD_VERSION2) {
-
-            /* Create ".AppleDouble" dir */
+        if (dvolume.vol->v_path && ADVOL_V2_OR_EA(dvolume.vol->v_adouble)) {
             mode_t omask = umask(0);
-            bstring addir = bfromcstr(to.p_path);
-            bcatcstr(addir, "/.AppleDouble");
-            mkdir(cfrombstr(addir), 02777);
-            bdestroy(addir);
+            if (dvolume.vol->v_adouble == AD_VERSION2) {
+                /* Create ".AppleDouble" dir */
+                bstring addir = bfromcstr(to.p_path);
+                bcatcstr(addir, "/.AppleDouble");
+                mkdir(cfrombstr(addir), 02777);
+                bdestroy(addir);
+            }
 
-            if (svolume.vol->v_path && svolume.vol->v_adouble == AD_VERSION2) {
-                /* copy ".Parent" file */
+            if (svolume.vol->v_path && ADVOL_V2_OR_EA(svolume.vol->v_adouble)) {
+                /* copy metadata file */
                 if (dvolume.vol->vfs->vfs_copyfile(dvolume.vol, -1, path, to.p_path)) {
                     SLOG("Error copying adouble for %s -> %s", path, to.p_path);
                     badcp = rval = 1;
@@ -547,7 +548,8 @@ static int copy(const char *path,
                 ERROR("Error opening adouble for: %s", to.p_path);
             }
             ad_setid( &ad, st.st_dev, st.st_ino, did, pdid, dvolume.db_stamp);
-            ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
+            if (dvolume.vol->v_adouble == AD_VERSION2)
+                ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
             ad_setdate(&ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime);
             ad_setdate(&ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime);
             ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
@@ -582,10 +584,10 @@ static int copy(const char *path,
         if (ftw_copy_file(ftw, path, statp, dne))
             badcp = rval = 1;
 
-        if (dvolume.vol->v_path && dvolume.vol->v_adouble == AD_VERSION2) {
+        if (dvolume.vol->v_path && ADVOL_V2_OR_EA(dvolume.vol->v_adouble)) {
 
             mode_t omask = umask(0);
-            if (svolume.vol->v_path && svolume.vol->v_adouble == AD_VERSION2) {
+            if (svolume.vol->v_path && ADVOL_V2_OR_EA(svolume.vol->v_adouble)) {
                 /* copy ad-file */
                 if (dvolume.vol->vfs->vfs_copyfile(dvolume.vol, -1, path, to.p_path)) {
                     SLOG("Error copying adouble for %s -> %s", path, to.p_path);
@@ -614,7 +616,8 @@ static int copy(const char *path,
                 ERROR("Error opening adouble for: %s", to.p_path);
             }
             ad_setid( &ad, st.st_dev, st.st_ino, cnid, did, dvolume.db_stamp);
-            ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
+            if (dvolume.vol->v_adouble == AD_VERSION2)
+                ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
             ad_setdate(&ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime);
             ad_setdate(&ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime);
             ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
index d994f74f56afa666fe8376d142c882fcf6a83aaa..897bdf3b1415c609efdae24f2104d019ef3464fc 100644 (file)
@@ -211,20 +211,12 @@ int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path
     if ( ! svol->vol->v_path) {
         /* no source volume: escape special chars (eg ':') */
         from = dvol->vol->v_volcharset; /* src = dst charset */
-        flags |= CONV_ESCAPEHEX;
+        if (dvol->vol->v_adouble == AD_VERSION2)
+            flags |= CONV_ESCAPEHEX;
     } else {
         from = svol->vol->v_volcharset;
     }
 
-    if ( (svol->vol->v_path)
-         && ! (svol->vol->v_flags & AFPVOL_USEDOTS)
-         && (dvol->vol->v_flags & AFPVOL_USEDOTS)) {
-        /* source is without dots, destination is with */
-        flags |= CONV_UNESCAPEHEX;
-    } else if (! (dvol->vol->v_flags & AFPVOL_USEDOTS)) {
-        flags |= CONV_ESCAPEDOTS;
-    }
-
     int len = convert_charset(from,
                               dvol->vol->v_volcharset,
                               dvol->vol->v_maccharset,
index 54530e77921cbb34445b554ac77ea4c8ef763e62..484a0dedf8f72eec16f52a88100b55b3cc9c4fb4 100644 (file)
@@ -184,6 +184,9 @@ AC_NETATALK_REALPATH
 dnl Check for sendfile()
 AC_NETATALK_SENDFILE
 
+dnl Check whether bundled libevent shall not be used
+AC_NETATALK_LIBEVENT
+
 dnl FHS stuff has to be done last because it overrides other defaults
 AC_NETATALK_FHS
 
@@ -198,7 +201,7 @@ AM_CONDITIONAL(SOLARIS_MODULE, test x$solaris_module = xyes)
 AM_CONDITIONAL(HAVE_LIBGCRYPT, test x$neta_cv_have_libgcrypt = xyes)
 AM_CONDITIONAL(HAVE_OPENSSL, test x$neta_cv_have_openssl = xyes)
 AM_CONDITIONAL(HAVE_ACLS, test x"$with_acl_support" = x"yes")
-AM_CONDITIONAL(HAVE_LDAP, test x"$with_ldap" = x"yes")
+AM_CONDITIONAL(HAVE_LDAP, test x"$netatalk_cv_ldap" = x"yes")
 AM_CONDITIONAL(USE_DHX, test x$neta_cv_compile_dhx = xyes)
 AM_CONDITIONAL(USE_DHX2, test x$neta_cv_compile_dhx2 = xyes)
 AM_CONDITIONAL(USE_RANDNUM, test x$neta_cv_have_openssl = xyes)
@@ -210,9 +213,6 @@ AM_CONDITIONAL(DEFAULT_HOOK, test x$neta_cv_have_libgcrypt != xyes && test x$net
 AM_CONDITIONAL(USE_BDB, test x$bdb_required = xyes)
 AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes")
 
-dnl --------------------- configure subpackages
-AC_CONFIG_SUBDIRS([libevent])
-
 dnl --------------------- generate files
 AC_OUTPUT([Makefile
        bin/Makefile
index b2a8cd5a8efc382543c0630c17239a51cecfb9be..643448ae688869d8cb44b0b1f6fb59e708fc5881 100644 (file)
@@ -51,6 +51,15 @@ netatalk_stop() {
     fi
 }
 
+# code to cause apfd and cnid_metad to restart
+netatalk_graceful() {
+    if [ -x ${NETATALK_SBIN}/netatalk ]; then
+        echo -n $"Restarting cnid_metad and afpd: "
+        killproc  netatalk -QUIT
+        RETVAL=$?
+        echo
+    fi
+}
 
 case "$1" in
     'start')
@@ -68,8 +77,11 @@ case "$1" in
         status netatalk
         RETVAL=$?
         ;;
+    'graceful')
+        netatalk_graceful
+        ;;
     *)
-        echo "Usage: $0 {start|stop|restart|reload|status}"
+        echo "Usage: $0 {start|stop|restart|reload|status|graceful}"
         exit 2
 esac
 
index fdd2e58aaa4dc27562a1019b1b001e8b9450aa43..85b51dc86bdca8971ecb85ce94c66c1273c28e21 100644 (file)
@@ -45,12 +45,12 @@ afpd_SOURCES = \
 
 afpd_LDADD =  \
        $(top_builddir)/libatalk/libatalk.la \
-       @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@
+       @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@ @KRB5_LIBS@
 
 afpd_LDFLAGS = -export-dynamic
 
 afpd_CFLAGS = \
-       @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ \
+       @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ @KRB5_CFLAGS@\
        -DAPPLCNAME \
        -DSERVERTEXT=\"$(SERVERTEXT)/\" \
        -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
index e282002e4a37b02dd761a82f85446543be2887c3..fdd0418915f91a2b19abb80a441794f50bc567ed 100644 (file)
@@ -46,7 +46,7 @@
 #include "dircache.h"
 
 #ifndef SOL_TCP
-#define SOL_TCP IPPROTO_TCPSOL_TCP
+#define SOL_TCP IPPROTO_TCP
 #endif
 
 /* 
index 7c878d59bbc849b531e3e5dc983560567c446ec7..0e1635a63ce959e29aafdc2e25b0fd434491bbe1 100644 (file)
@@ -229,8 +229,10 @@ static void register_stuff(const AFPObj *obj) {
         }
 
         if (obj->options.mimicmodel) {
+            LOG(log_info, logtype_afpd, "Registering server '%s' with model '%s'",
+                dsi->bonjourname, obj->options.mimicmodel);
             TXTRecordCreate(&txt_devinfo, 0, NULL);
-            TXTRecordPrintf(&txt_devinfo, "model", obj->options.mimicmodel);
+            TXTRecordPrintf(&txt_devinfo, "model=%s", obj->options.mimicmodel);
             error = DNSServiceRegister(&svc_refs[svc_ref_count++],
                                        0,               // no flags
                                        0,               // all network interfaces
@@ -238,7 +240,7 @@ static void register_stuff(const AFPObj *obj) {
                                        DEV_INFO_SERVICE_TYPE,
                                        "",            // default domains
                                        NULL,            // default host name
-                                       htons(port),
+                                       0,
                                        TXTRecordGetLength(&txt_devinfo),
                                        TXTRecordGetBytesPtr(&txt_devinfo),
                                        RegisterReply,           // callback
index 80759a439cf61bfed6f088b0641bf5e4c48a907a..f77d34a522a91ce702ff80599540791684586548 100644 (file)
@@ -347,13 +347,15 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
             continue;
         }
         memset(&s_path, 0, sizeof(s_path));
+
+        /* conversions on the fly */
+        const char *convname;
         s_path.u_name = sd.sd_last;
-        if (of_stat( &s_path) < 0 ) {
-            /*
-             * Somebody else plays with the dir, well it can be us with 
-            * "Empty Trash..."
-            */
+        if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) {
+            s_path.u_name = (char *)convname;
+        }
 
+        if (of_stat( &s_path) < 0 ) {
             /* so the next time it won't try to stat it again
              * another solution would be to invalidate the cache with 
              * sd.sd_did = 0 but if it's not ENOENT error it will start again
@@ -364,12 +366,18 @@ static int enumerate(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,
             continue;
         }
 
+        /* Fixup CNID db if ad_convert resulted in a rename (then convname != NULL) */
+        if (convname) {
+            s_path.id = cnid_lookup(vol->v_cdb, &s_path.st, curdir->d_did, sd.sd_last, strlen(sd.sd_last));
+            if (s_path.id != CNID_INVALID) {
+                if (cnid_update(vol->v_cdb, s_path.id, &s_path.st, curdir->d_did, convname, strlen(convname)) != 0)
+                    LOG(log_error, logtype_afpd, "enumerate: error updating CNID of \"%s\"", fullpathname(convname));
+            }
+        }
+
         sd.sd_last += len + 1;
         s_path.m_name = NULL;
 
-        /* Convert adouble:v2 to adouble:ea on the fly */
-        (void)ad_convert(s_path.u_name, &s_path.st, vol);
-
         /*
          * If a fil/dir is not a dir, it's a file. This is slightly
          * inaccurate, since that means /dev/null is a file, /dev/printer
index c24d296b2f1049c76c6407267d6410847e7564cb..d06d4684e40ef2750b024c5449ad61cff32b71ab 100644 (file)
@@ -259,12 +259,13 @@ restart:
                 goto exit;
             }
         }
-        else if (adp && (adcnid != dbcnid)) { /* 4 */
+        else if (adp && adcnid && (adcnid != dbcnid)) { /* 4 */
             /* Update the ressource fork. For a folder adp is always null */
             LOG(log_debug, logtype_afpd, "get_id(%s/%s): calling ad_setid(old: %u, new: %u)",
                 getcwdpath(), upath, htonl(adcnid), htonl(dbcnid));
             if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) {
-                ad_flush(adp);
+                if (ad_flush(adp) != 0)
+                    LOG(log_error, logtype_afpd, "get_id(\"%s\"): can't flush", fullpathname(upath));
             }
         }
     }
index a04776fae35148b85735549221f22f0f2e479722..17473d19e7788adc542e8c95f8d66ed4b0e28e08 100644 (file)
@@ -203,9 +203,6 @@ int afp_setfildirparams(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf
 */
 int check_name(const struct vol *vol, char *name)
 {
-    if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/'))
-        return AFPERR_PARAM;
-
     if (!vol->vfs->vfs_validupath(vol, name)) {
         LOG(log_error, logtype_afpd, "check_name: illegal name: '%s'", name);
         return AFPERR_EXIST;
index 319f33f2b727cf0239fc0b1382ca964a71361153..2216a45c1b32a0d40be5b89698a9a95bc8553ffc 100644 (file)
@@ -880,11 +880,9 @@ static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, si
            an error. we can't do this with translation on. */
 #ifdef WITH_SENDFILE
         if (!(obj->options.flags & OPTION_NOSENDFILE)) {
-            if (dsi_stream_read_file(dsi,
-                                     ad_readfile_init(ofork->of_ad, eid, &offset, 0),
-                                     offset,
-                                     dsi->datasize) < 0) {
-                switch (errno) {
+            int fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0);
+            if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) { 
+               switch (errno) {
                 case EINVAL:
                 case ENOSYS:
                     goto afp_read_loop;
index 86ea243ae6ed675b0a559b7eaa3fc2c92da46004..4beb4285142b8c1fcaeb436a92e501c40166122e 100644 (file)
@@ -479,7 +479,8 @@ krb5_cleanup:
 
 offset_calc:
     /* Calculate and store offset for UTF8ServerName */
-    *diroffset += sizeof(uint16_t);
+    if (uam_gss_enabled())
+        *diroffset += sizeof(uint16_t);
     offset = htons(data - begin);
     memcpy(begin + *diroffset, &offset, sizeof(uint16_t));
 
@@ -491,7 +492,6 @@ static size_t status_utf8servername(char *data, int *nameoffset,
                                 const DSI *dsi _U_,
                                 const struct afp_options *options)
 {
-    char *Obj, *Type, *Zone;
     uint16_t namelen;
     size_t len;
     char *begin = data;
@@ -501,20 +501,15 @@ static size_t status_utf8servername(char *data, int *nameoffset,
     offset = ntohs(offset);
     data += offset;
 
-    /* FIXME:
-     * What is the valid character range for an nbpname?
-     *
-     * Apple's server likes to use the non-qualified hostname
-     * This obviously won't work very well if multiple servers are running
-     * on the box.
-     */
+    LOG(log_info, logtype_afpd, "servername: %s", options->hostname);
 
-    /* extract the obj part of the server */
-    Obj = options->hostname;
-    if ((size_t) -1 == (len = convert_string (
-                            options->unixcharset, CH_UTF8_MAC, 
-                            Obj, -1, data+sizeof(namelen), maxstatuslen-offset )) ) {
-        LOG ( log_error, logtype_afpd, "Could not set utf8 servername");
+    if ((len = convert_string(options->unixcharset,
+                              CH_UTF8_MAC, 
+                              options->hostname,
+                              -1,
+                              data + sizeof(namelen),
+                              maxstatuslen-offset)) == (size_t)-1) {
+        LOG(log_error, logtype_afpd, "Could not set utf8 servername");
 
         /* set offset to 0 */
         memset(begin + *nameoffset, 0, sizeof(offset));
index 1d4081e29212e9dcd851e8e39efbaccfc7fe3273..61d744ca70cdc980d21b98734a06b25682e3e1d9 100644 (file)
@@ -321,7 +321,7 @@ static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, str
      * .Parent file here if it doesn't exist. */
 
     /* Convert adouble:v2 to adouble:ea on the fly */
-    (void)ad_convert(vol->v_path, st, vol);
+    (void)ad_convert(vol->v_path, st, vol, NULL);
 
     ad_init(&ad, vol);
     if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0 ) {
index 9685c3d219c341a81aa48de436abd2e3f3bb4ca0..dcbd4c74779161acb4be4f3b3feda12bc6bec771 100644 (file)
@@ -124,11 +124,6 @@ static char *mtoupath(char *mpath)
     }
 
     /* set conversion flags */
-    if (!(myvol->v_flags & AFPVOL_NOHEX))
-        flags |= CONV_ESCAPEHEX;
-    if (!(myvol->v_flags & AFPVOL_USEDOTS))
-        flags |= CONV_ESCAPEDOTS;
-
     if ((myvol->v_casefold & AFPVOL_MTOUUPPER))
         flags |= CONV_TOUPPER;
     else if ((myvol->v_casefold & AFPVOL_MTOULOWER))
@@ -156,28 +151,6 @@ static char *mtoupath(char *mpath)
     return( upath );
 }
 
-/*
-  Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS.
-  We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result.
-*/
-static int check_name_encoding(char *uname)
-{
-    char *roundtripped;
-
-    roundtripped = mtoupath(utompath(uname));
-    if (!roundtripped) {
-        dbd_log( LOGSTD, "Error checking encoding for '%s/%s'", cwdbuf, uname);
-        return -1;
-    }
-
-    if ( STRCMP(uname, !=, roundtripped)) {
-        dbd_log( LOGSTD, "Bad encoding for '%s/%s'", cwdbuf, uname);
-        return -1;
-    }
-
-    return 0;
-}
-
 /*
   Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
   Returns pointer to name or NULL.
@@ -208,20 +181,72 @@ static const char *check_special_dirs(const char *name)
     return NULL;
 }
 
+/*
+ * We unCAPed a name, update CNID db
+ */
+static int update_cnid(cnid_t did, const struct stat *sp, const char *oldname, const char *newname)
+{
+    int ret;
+    cnid_t id;
+
+    /* Prepare request data */
+    memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
+    memset(&rply, 0, sizeof(struct cnid_dbd_rply));
+    rqst.did = did;
+    rqst.cnid = 0;
+    if ( ! (myvol->v_flags & AFPVOL_NODEV))
+        rqst.dev = sp->st_dev;
+    rqst.ino = sp->st_ino;
+    rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
+    rqst.name = (char *)oldname;
+    rqst.namelen = strlen(oldname);
+
+    /* Query the database */
+    ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
+    if (dbif_txn_close(dbd, ret) != 0)
+        return -1;
+    if (rply.result != CNID_DBD_RES_OK)
+        return 0;
+    id = rply.cnid;
+
+    /* Prepare request data */
+    memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
+    memset(&rply, 0, sizeof(struct cnid_dbd_rply));
+    rqst.did = did;
+    rqst.cnid = id;
+    if ( ! (myvol->v_flags & AFPVOL_NODEV))
+        rqst.dev = sp->st_dev;
+    rqst.ino = sp->st_ino;
+    rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
+    rqst.name = (char *)newname;
+    rqst.namelen = strlen(newname);
+
+    /* Update the database */
+    ret = dbd_update(dbd, &rqst, &rply);
+    if (dbif_txn_close(dbd, ret) != 0)
+        return -1;
+    if (rply.result != CNID_DBD_RES_OK)
+        return -1;
+
+    return 0;
+}
+
 /*
   Check for .AppleDouble file, create if missing
 */
-static int check_adfile(const char *fname, const struct stat *st)
+static int check_adfile(const char *fname, const struct stat *st, const char **newname)
 {
     int ret;
     int adflags = ADFLAGS_HF;
     struct adouble ad;
     const char *adname;
 
+    *newname = NULL;
+
     if (myvol->v_adouble == AD_VERSION_EA) {
         if (!(dbd_flags & DBD_FLAGS_V2TOEA))
             return 0;
-        if (ad_convert(fname, st, myvol) != 0) {
+        if (ad_convert(fname, st, myvol, newname) != 0) {
             switch (errno) {
             case ENOENT:
                 break;
@@ -854,6 +879,11 @@ static int dbd_readdir(int volroot, cnid_t did)
         if (STRCMP(ep->d_name, == , ADv2_DIRNAME))
             continue;
 
+        if (!myvol->vfs->vfs_validupath(myvol, ep->d_name)) {
+            dbd_log(LOGDEBUG, "Ignoring \"%s\"", ep->d_name);
+            continue;
+        }
+
         if ((ret = lstat(ep->d_name, &st)) < 0) {
             dbd_log( LOGSTD, "Lost file while reading dir '%s/%s', probably removed: %s",
                      cwdbuf, ep->d_name, strerror(errno));
@@ -897,21 +927,21 @@ static int dbd_readdir(int volroot, cnid_t did)
            Tests
         **************************************************************************/
 
-        /* Check encoding */
-        if ( -1 == (encoding_ok = check_name_encoding(ep->d_name)) ) {
-            /* If its a file: skipp all other tests now ! */
-            /* For dirs we could try to get a CNID for it and recurse, but currently I prefer not to */
-            continue;
-        }
-
         /* Check for appledouble file, create if missing, but only if we have addir */
+        const char *name = NULL;
         adfile_ok = -1;
         if (ADDIR_OK)
-            adfile_ok = check_adfile(ep->d_name, &st);
+            adfile_ok = check_adfile(ep->d_name, &st, &name);
+
+        if (name == NULL) {
+            name = ep->d_name;
+        } else {
+            update_cnid(did, &st, ep->d_name, name);
+        }
 
         if ( ! nocniddb) {
             /* Check CNIDs */
-            cnid = check_cnid(ep->d_name, did, &st, adfile_ok);
+            cnid = check_cnid(name, did, &st, adfile_ok);
 
             /* Now add this object to our rebuild dbd */
             if (cnid && dbd_rebuild) {
@@ -922,7 +952,7 @@ static int dbd_readdir(int volroot, cnid_t did)
                     return -1;
                 if (rply.result != CNID_DBD_RES_OK) {
                     dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
-                             cnid, cwdbuf, ep->d_name);
+                             cnid, cwdbuf, name);
                     return -1;
                 }
                 count++;
@@ -938,20 +968,20 @@ static int dbd_readdir(int volroot, cnid_t did)
 
         /* Check EA files */
         if (myvol->v_vfs_ea == AFPVOL_EA_AD)
-            check_eafiles(ep->d_name);
+            check_eafiles(name);
 
         /**************************************************************************
           Recursion
         **************************************************************************/
         if (S_ISDIR(st.st_mode) && (cnid || nocniddb)) { /* If we have no cnid for it we cant recur */
             strcat(cwdbuf, "/");
-            strcat(cwdbuf, ep->d_name);
+            strcat(cwdbuf, name);
             dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf);
             if (-1 == (cwd = open(".", O_RDONLY))) {
                 dbd_log( LOGSTD, "Cant open directory '%s': %s", cwdbuf, strerror(errno));
                 continue;
             }
-            if (0 != chdir(ep->d_name)) {
+            if (0 != chdir(name)) {
                 dbd_log( LOGSTD, "Cant chdir to directory '%s': %s", cwdbuf, strerror(errno));
                 close(cwd);
                 continue;
@@ -1002,7 +1032,7 @@ static int scanvol(struct vol *vol, dbd_flags_t flags)
     if ((myvol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) {
         if (lstat(".", &st) != 0)
             return -1;
-        if (ad_convert(".", &st, vol) != 0) {
+        if (ad_convert(".", &st, vol, NULL) != 0) {
             switch (errno) {
             case ENOENT:
                 break;
index 217fdd6d73d7255e6e1a16acc8c9acc3f7ada82b..e0860cbfdf322faf80badf659e9f4e3bf2a75242 100644 (file)
@@ -805,7 +805,12 @@ int dbif_env_remove(const char *path)
     int ret;
     DBD *dbd;
 
-    LOG(log_debug, logtype_cnid, "Reopening BerkeleyDB environment");
+    LOG(log_debug, logtype_cnid, "Trying to remove BerkeleyDB environment");
+
+    if (get_lock(LOCK_EXCL, path) != LOCK_EXCL) {
+        LOG(log_warning, logtype_cnid, "CNID db \"%s\" in use, can't remove BerkeleyDB environment", path);
+        return 0;
+    }
     
     if (NULL == (dbd = dbif_init(path, "cnid2.db")))
         return -1;
index 5897e40f0192e0484361b6bdf47c63bd6ec68d92..10f90cefedad7c9de980f5ada4a04cdbc800af73 100644 (file)
@@ -6,12 +6,18 @@ sbin_PROGRAMS = netatalk
 
 netatalk_SOURCES = netatalk.c
 netatalk_CFLAGS = \
-       -I$(top_srcdir)/libevent/include \
-       -I$(top_builddir)/libevent/include \
        -D_PATH_CONFDIR=\"$(pkgconfdir)/\" \
        -D_PATH_AFPD=\"$(sbindir)/afpd\" \
        -D_PATH_CNID_METAD=\"$(sbindir)/cnid_metad\"
 
 netatalk_LDADD = \
-       $(top_builddir)/libatalk/libatalk.la \
+       $(top_builddir)/libatalk/libatalk.la
+
+if USE_BUILTIN_LIBEVENT
+netatalk_CFLAGS += \
+       -I$(top_srcdir)/libevent/include \
+       -I$(top_builddir)/libevent/include
+
+netatalk_LDADD += \
        $(top_builddir)/libevent/libevent.la
+endif
\ No newline at end of file
index 7c7f1003fbfaa2a2f6a6527b2457774566ead0e2..3d052f46d3897100895ec85c301a47d339125790 100644 (file)
@@ -48,7 +48,7 @@ static sig_atomic_t got_chldsig;
 static pid_t afpd_pid = -1,  cnid_metad_pid = -1;
 static uint afpd_restarts, cnid_metad_restarts;
 static struct event_base *base;
-struct event *sigterm_ev, *sigquit_ev, *sigchld_ev;
+struct event *sigterm_ev, *sigquit_ev, *sigchld_ev, *timer_ev;
 static int in_shutdown;
 
 /******************************************************************
@@ -84,9 +84,29 @@ static void libevent_logmsg_cb(int severity, const char *msg)
 /* SIGTERM callback */
 static void sigterm_cb(evutil_socket_t fd, short what, void *arg)
 {
-    LOG(log_note, logtype_afpd, "Exiting on SIGTERM");
+    sigset_t sigs;
+    struct timeval tv;
+
+    LOG(log_info, logtype_afpd, "Exiting on SIGTERM");
+
+    if (in_shutdown)
+        return;
     in_shutdown = 1;
-    event_base_loopbreak(base);
+
+    /* block any signal but SIGCHLD */
+    sigfillset(&sigs);
+    sigdelset(&sigs, SIGCHLD);
+    sigprocmask(SIG_SETMASK, &sigs, NULL);
+
+    /* add 10 sec timeout timer, remove all events but SIGCHLD */
+    tv.tv_sec = KILL_GRACETIME;
+    tv.tv_usec = 0;
+    event_base_loopexit(base, &tv);
+    event_del(sigterm_ev);
+    event_del(sigquit_ev);
+    event_del(timer_ev);
+
+    kill_childs(SIGTERM, &afpd_pid, &cnid_metad_pid, NULL);
 }
 
 /* SIGQUIT callback */
@@ -117,37 +137,44 @@ static void sigchld_cb(evutil_socket_t fd, short what, void *arg)
                 LOG(log_info, logtype_afpd, "child[%d]: died", pid);
         }
 
-        if (pid == afpd_pid) {
-            if (in_shutdown) {
-                afpd_pid = -1;
-            } else {
-                sleep(1);
-                afpd_restarts++;
-                LOG(log_note, logtype_afpd, "Restarting 'afpd' (restarts: %u)", afpd_restarts);
-                if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
-                    LOG(log_error, logtype_afpd, "Error starting 'afpd'");
-                }
-            }
-        } else if (pid = cnid_metad_pid) {
-            if (in_shutdown) {
-                cnid_metad_pid = -1;
-            } else {
-                sleep(1);
-                cnid_metad_restarts++;
-                LOG(log_note, logtype_afpd, "Restarting 'cnid_metad' (restarts: %u)", cnid_metad_restarts);
-                if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
-                    LOG(log_error, logtype_afpd, "Error starting 'cnid_metad'");
-                }
-            }
-        } else {
+        if (pid == afpd_pid)
+            afpd_pid = -1;
+        else if (pid = cnid_metad_pid)
+            cnid_metad_pid = -1;
+        else
             LOG(log_error, logtype_afpd, "Bad pid: %d", pid);
-        }
     }
 
     if (in_shutdown && afpd_pid == -1 && cnid_metad_pid == -1)
         event_base_loopbreak(base);
 }
 
+/* timer callback */
+static void timer_cb(evutil_socket_t fd, short what, void *arg)
+{
+    static int i = 0;
+    LOG(log_debug, logtype_afpd, "looping: %i", i++);
+
+    if (in_shutdown)
+        return;
+
+    if (afpd_pid == -1) {
+        afpd_restarts++;
+        LOG(log_note, logtype_afpd, "Restarting 'afpd' (restarts: %u)", afpd_restarts);
+        if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
+            LOG(log_error, logtype_afpd, "Error starting 'afpd'");
+        }
+    }
+
+    if (cnid_metad_pid == -1) {
+        cnid_metad_restarts++;
+        LOG(log_note, logtype_afpd, "Restarting 'cnid_metad' (restarts: %u)", cnid_metad_restarts);
+        if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
+            LOG(log_error, logtype_afpd, "Error starting 'cnid_metad'");
+        }
+    }
+}
+
 /******************************************************************
  * helper functions
  ******************************************************************/
@@ -214,6 +241,7 @@ int main(int argc, char **argv)
     const char *configfile = NULL;
     int c, ret, debug = 0;
     sigset_t blocksigs;
+    struct timeval tv;
 
     /* Log SIGBUS/SIGSEGV SBT */
     fault_setup(NULL);
@@ -272,10 +300,15 @@ int main(int argc, char **argv)
     sigterm_ev = event_new(base, SIGTERM, EV_SIGNAL, sigterm_cb, NULL);
     sigquit_ev = event_new(base, SIGQUIT, EV_SIGNAL | EV_PERSIST, sigquit_cb, NULL);
     sigchld_ev = event_new(base, SIGCHLD, EV_SIGNAL | EV_PERSIST, sigchld_cb, NULL);
+    timer_ev = event_new(base, -1, EV_PERSIST, timer_cb, NULL);
+
+    tv.tv_sec = 1;
+    tv.tv_usec = 0;
 
     event_add(sigterm_ev, NULL);
     event_add(sigquit_ev, NULL);
     event_add(sigchld_ev, NULL);
+    event_add(timer_ev, &tv);
 
     sigfillset(&blocksigs);
     sigdelset(&blocksigs, SIGTERM);
@@ -286,25 +319,6 @@ int main(int argc, char **argv)
     /* run the event loop */
     ret = event_base_dispatch(base);
 
-    /* got SIGTERM so we're going to shutdown */
-
-    /* block any signal but SIGCHLD */
-    sigfillset(&blocksigs);
-    sigdelset(&blocksigs, SIGCHLD);
-    sigprocmask(SIG_SETMASK, &blocksigs, NULL);
-
-    /* setup new events: remove SIGTERM and SIGQUIT cbs, add timeout */
-    struct timeval tv;
-    tv.tv_sec = KILL_GRACETIME;
-    tv.tv_usec = 0;
-    event_base_loopexit(base, &tv);
-    event_del(sigterm_ev);
-    event_del(sigquit_ev);
-
-    /* run the event loop again, waiting for child to exit on SIGTERM for KILL_GRACETIME seconds */
-    kill_childs(SIGTERM, &afpd_pid, &cnid_metad_pid, NULL);
-    ret = event_base_dispatch(base);
-
     if (afpd_pid != -1 || cnid_metad_pid != -1) {
         if (afpd_pid != -1)
             LOG(log_error, logtype_afpd, "AFP service did not shutdown, killing it");
@@ -312,5 +326,8 @@ int main(int argc, char **argv)
             LOG(log_error, logtype_afpd, "CNID database service did not shutdown, killing it");
         kill_childs(SIGKILL, &afpd_pid, &cnid_metad_pid, NULL);
     }
+
+    LOG(log_note, logtype_afpd, "Netatalk AFP server exiting");
+
     netatalk_exit(ret);
 }
index 5b276a5a27a2e8255266eb5bbf810e3c0b19c2b8..f95279d7aa7779ada385ea7642799aad682b832e 100644 (file)
@@ -403,8 +403,11 @@ extern int ad_stat        (const char *, struct stat *);
 extern int ad_metadata    (const char *, int, struct adouble *);
 extern int ad_metadataat  (int, const char *, int, struct adouble *);
 extern mode_t ad_hf_mode(mode_t mode);
-extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol);
 extern int ad_valid_header_osx(const char *path);
+
+/* ad_conv.c */
+extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath);
+
 /* ad_read.c/ad_write.c */
 extern int     sys_ftruncate(int fd, off_t length);
 extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
index e1aca81491f28c871558862141267e37d03ec61e..e34f4ee829e33ccef3842880511c89abfb08a863 100644 (file)
@@ -50,6 +50,8 @@
 #define PASSWD_NOSAVE  (1 << 1)
 #define PASSWD_ALL     (PASSWD_SET | PASSWD_NOSAVE)
 
+#define IS_AFP_SESSION(obj) ((obj)->dsi && (obj)->dsi->serversock == -1)
+
 /**********************************************************************************************
  * Ini config sections
  **********************************************************************************************/
index d8948500e8eb86d57df8fc95236d7790016fd0f0..7a27c644daa864297d939dc6fa50f96549e69cc7 100644 (file)
@@ -112,10 +112,7 @@ struct vol {
   Keep in sync with libatalk/util/volinfo.c
 */
 #define AFPVOL_NOV2TOEACONV (1 << 5) /* no adouble:v2 to adouble:ea conversion */
-#define AFPVOL_UNIX_CTXT (1 << 6)   /* volume created by getvolbypath ie UNIX access, not afpd AFP user session */
 #define AFPVOL_RO        (1 << 8)   /* read-only volume */
-#define AFPVOL_NOHEX     (1 << 10)  /* don't do :hex translation */
-#define AFPVOL_USEDOTS   (1 << 11)  /* use real dots */
 #define AFPVOL_NOSTAT    (1 << 16)  /* advertise the volume even if we can't stat() it
                                      * maybe because it will be mounted later in preexec */
 #define AFPVOL_UNIX_PRIV (1 << 17)  /* support unix privileges */
index e7f9753aca68a1400cd41dd409dc5744e8478463..52a409eba311a8e9029f9e042c77f06af84d9cd4 100644 (file)
@@ -5,9 +5,11 @@ noinst_HEADERS = aclldap.h cache.h
 noinst_LTLIBRARIES = libacl.la
 libacl_la_SOURCES = cache.c unix.c uuid.c
 libacl_la_LDFLAGS =
+libacl_la_LIBADD  =
 
 if HAVE_LDAP
 libacl_la_SOURCES += ldap.c ldap_config.c
-libacl_la_LDFLAGS += -lldap
+libacl_la_LIBADD  += @LDAP_LIBS@
+libacl_la_LDFLAGS += @LDAP_LDLFLAGS@
 endif
 
index 6602926b6328986453cb395bbb9c476bdf582aca..49144a2aa62831042f33efff428316378d724b60 100644 (file)
@@ -2,7 +2,17 @@
 
 noinst_LTLIBRARIES = libadouble.la
 
-libadouble_la_SOURCES = ad_open.c ad_flush.c ad_read.c ad_write.c ad_size.c \
-       ad_mmap.c ad_lock.c ad_date.c ad_attr.c ad_sendfile.c
+libadouble_la_SOURCES = \
+       ad_attr.c \
+       ad_conv.c \
+       ad_date.c \
+       ad_flush.c \
+       ad_lock.c \
+       ad_mmap.c \
+       ad_open.c \
+       ad_read.c \
+       ad_sendfile.c \
+       ad_size.c \
+       ad_write.c
 
 noinst_HEADERS = ad_lock.h
diff --git a/libatalk/adouble/ad_conv.c b/libatalk/adouble/ad_conv.c
new file mode 100644 (file)
index 0000000..eaac8db
--- /dev/null
@@ -0,0 +1,252 @@
+/*
+ * Copyright (c) 2012 Frank Lahm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/*!
+ * @file
+ * Part of Netatalk's AppleDouble implementatation
+ * @sa include/atalk/adouble.h
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <errno.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <arpa/inet.h>
+
+#include <atalk/logger.h>
+#include <atalk/adouble.h>
+#include <atalk/util.h>
+#include <atalk/unix.h>
+#include <atalk/ea.h>
+#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
+#include <atalk/compat.h>
+#include <atalk/errchk.h>
+#include <atalk/volume.h>
+
+#include "ad_lock.h"
+
+static char emptyfilad[32] = {0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0};
+
+static char emptydirad[32] = {0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,1,0,
+                              0,0,0,0,0,0,0,0,
+                              0,0,0,0,0,0,0,0};
+
+static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol)
+{
+    EC_INIT;
+    struct adouble adv2;
+    struct adouble adea;
+    const char *adpath;
+    int adflags;
+    uint32_t ctime, mtime, afpinfo = 0;
+    char *emptyad;
+
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
+
+    ad_init(&adea, vol);
+    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
+    adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+
+    /* Open and lock adouble:v2 file */
+    EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) );
+
+    EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
+    EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) );
+
+    /* Check if it's a non-empty header */
+    if (S_ISREG(sp->st_mode))
+        emptyad = &emptyfilad[0];
+    else
+        emptyad = &emptydirad[0];
+
+    if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0)
+        goto copy;
+    if (ad_getentryoff(&adv2, ADEID_FINDERI)
+        && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI)
+        && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0))
+        goto copy;
+    if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) {
+        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) );
+        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) );
+        if ((ctime != mtime) || (mtime != sp->st_mtime))
+            goto copy;
+    }
+    if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) {
+        if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0)
+            goto copy;
+    }
+
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
+    goto EC_CLEANUP;
+
+copy:
+    /* Create a adouble:ea meta EA */
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
+    EC_ZERO_LOGSTR( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE),
+                    "ad_conv_v22ea_hf(\"%s\"): error creating metadata EA: %s",
+                    fullpathname(path), strerror(errno));
+    EC_ZERO_LOG( ad_copy_header(&adea, &adv2) );
+    ad_flush(&adea);
+
+EC_CLEANUP:
+    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
+    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret);
+    EC_EXIT;
+}
+
+static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol)
+{
+    EC_INIT;
+    struct adouble adv2;
+    struct adouble adea;
+
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
+
+    if (S_ISDIR(sp->st_mode))
+        return 0;
+
+    ad_init(&adea, vol);
+    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
+
+    /* Open and lock adouble:v2 file */
+    EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) );
+
+    if (adv2.ad_rlen > 0) {
+        EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
+
+        /* Create a adouble:ea resource fork */
+        EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) );
+
+        EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) );
+        adea.ad_rlen = adv2.ad_rlen;
+        ad_flush(&adea);
+    }
+
+EC_CLEANUP:
+    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) );
+    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) );
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret);
+    EC_EXIT;
+}
+
+static int ad_conv_v22ea(const char *path, const struct stat *sp, const struct vol *vol)
+{
+    EC_INIT;
+    const char *adpath;
+    int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+
+    become_root();
+
+    EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
+    EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
+
+    EC_NULL( adpath = ad_path(path, adflags) );
+    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
+        path, fullpathname(adpath));
+
+    unlink(adpath);
+
+EC_CLEANUP:
+    if (errno == ENOENT)
+        EC_STATUS(0);
+
+    unbecome_root();
+
+    EC_EXIT;
+}
+
+/*!
+ * Remove hexencoded dots and slashes (":2e" and ":2f")
+ */
+static int ad_conv_dehex(const char *path, const struct stat *sp, const struct vol *vol, const char **newpathp)
+{
+    EC_INIT;
+    static char buf[MAXPATHLEN];
+    const char *adpath, *p;
+    int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+    bstring newpath = NULL;
+
+    LOG(log_debug, logtype_default,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path));
+
+    *newpathp = NULL;
+
+    if ((p = strchr(path, ':')) == NULL)
+        goto EC_CLEANUP;
+
+    EC_NULL( newpath = bfromcstr(path) );
+
+    EC_ZERO( bfindreplace(newpath, bfromcstr(":2e"), bfromcstr("."), 0) );
+    EC_ZERO( bfindreplace(newpath, bfromcstr(":2f"), bfromcstr(":"), 0) );
+    
+    become_root();
+    if (adflags != ADFLAGS_DIR)
+        rename(vol->ad_path(path, 0), vol->ad_path(bdata(newpath), 0));
+    rename(path, bdata(newpath));
+    unbecome_root();
+
+    strlcpy(buf, bdata(newpath), sizeof(buf));
+    *newpathp = buf;
+
+EC_CLEANUP:
+    if (newpath)
+        bdestroy(newpath);
+    EC_EXIT;
+}
+
+/*!
+ * AppleDouble and encoding conversion on the fly
+ *
+ * @param path      (r) path to file or directory
+ * @param sp        (r) stat(path)
+ * @param vol       (r) volume handle
+ * @param newpath   (w) if encoding changed, new name. Can be NULL.
+ *
+ * @returns         -1 on internal error, otherwise 0. newpath is NULL if no character conversion was done,
+ *                  otherwise newpath points to a static string with the converted name
+ */
+int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath)
+{
+    EC_INIT;
+    const char *p;
+
+    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
+
+    if (newpath)
+        *newpath = NULL;
+
+    if ((vol->v_adouble == AD_VERSION_EA) && !(vol->v_flags & AFPVOL_NOV2TOEACONV))
+        EC_ZERO( ad_conv_v22ea(path, sp, vol) );
+
+    if (vol->v_adouble == AD_VERSION_EA) {
+        EC_ZERO( ad_conv_dehex(path, sp, vol, &p) );
+        if (p && newpath)
+            *newpath = p;
+    }
+
+EC_CLEANUP:
+    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
+    EC_EXIT;
+}
+
index 196053ee31ab288601b4c365f56da42600c00263..79016b5feac43e1d6fed2110e2d5e320610470e9 100644 (file)
@@ -809,111 +809,6 @@ static int ad2openflags(const struct adouble *ad, int adfile, int adflags)
     return oflags;
 }
 
-static char emptyfilad[32] = {0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0};
-
-static char emptydirad[32] = {0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,1,0,
-                              0,0,0,0,0,0,0,0,
-                              0,0,0,0,0,0,0,0};
-
-static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol)
-{
-    EC_INIT;
-    struct adouble adv2;
-    struct adouble adea;
-    const char *adpath;
-    int adflags;
-    uint32_t ctime, mtime, afpinfo = 0;
-    char *emptyad;
-
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
-
-    ad_init(&adea, vol);
-    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
-    adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
-
-    /* Open and lock adouble:v2 file */
-    EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) );
-    EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
-    EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) );
-
-    /* Check if it's a non-empty header */
-    if (S_ISREG(sp->st_mode))
-        emptyad = &emptyfilad[0];
-    else
-        emptyad = &emptydirad[0];
-
-    if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0)
-        goto copy;
-    if (ad_getentryoff(&adv2, ADEID_FINDERI)
-        && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI)
-        && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0))
-        goto copy;
-    if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) {
-        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) );
-        EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) );
-        if ((ctime != mtime) || (mtime != sp->st_mtime))
-            goto copy;
-    }
-    if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) {
-        if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0)
-            goto copy;
-    }
-
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
-    goto EC_CLEANUP;
-
-copy:
-    /* Create a adouble:ea meta EA */
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
-    EC_ZERO_LOG( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE) );
-    EC_ZERO_LOG( ad_copy_header(&adea, &adv2) );
-    ad_flush(&adea);
-
-EC_CLEANUP:
-    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
-    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret);
-    EC_EXIT;
-}
-
-static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol)
-{
-    EC_INIT;
-    struct adouble adv2;
-    struct adouble adea;
-
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
-
-    if (S_ISDIR(sp->st_mode))
-        return 0;
-
-    ad_init(&adea, vol);
-    ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
-
-    /* Open and lock adouble:v2 file */
-    EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) );
-    if (adv2.ad_rlen > 0) {
-        EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
-
-        /* Create a adouble:ea resource fork */
-        EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) );
-
-        EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) );
-        adea.ad_rlen = adv2.ad_rlen;
-        ad_flush(&adea);
-    }
-
-EC_CLEANUP:
-    EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) );
-    EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) );
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret);
-    EC_EXIT;
-}
-
 static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble *ad)
 {
     EC_INIT;
@@ -1929,33 +1824,6 @@ EC_CLEANUP:
     return ret;
 }
 
-int ad_convert(const char *path, const struct stat *sp, const struct vol *vol)
-{
-    EC_INIT;
-    const char *adpath;
-    int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
-
-    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
-
-    if (!(vol->v_adouble == AD_VERSION_EA) || (vol->v_flags & AFPVOL_NOV2TOEACONV))
-        goto EC_CLEANUP;
-
-    EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
-    EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
-
-    EC_NULL( adpath = ad_path(path, adflags) );
-    LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
-        path, fullpathname(adpath));
-
-    become_root();
-    EC_ZERO_LOG( unlink(adpath) );
-    unbecome_root();
-
-EC_CLEANUP:
-    LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
-    EC_EXIT;
-}
-
 /* build a resource fork mode from the data fork mode:
  * remove X mode and extend header to RW if R or W (W if R for locking),
  */
index 5debd0377881372fdccad8402dfc208de0a60a82..7c668ec8a62cd3e7c921ad9666d07d0661a37901 100644 (file)
@@ -81,6 +81,7 @@ afp_child_t *dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval
 
   /* get rid of some stuff */
   close(dsi->serversock);
+  dsi->serversock = -1;
   server_child_free(serv_children); 
 
   switch (dsi->header.dsi_command) {
index fe33a21784f3eeb0125c33c99d0282c4f43f3665..455a72622ef9fb0f2aa7543aec6bfe6feb651c57 100644 (file)
@@ -772,13 +772,11 @@ static size_t pull_charset_flags (charset_t from_set, charset_t cap_set, const c
     o_len=destlen;
 
     while (i_len > 0) {
-        if ((option & CONV_UNESCAPEHEX)) {
-            for (j = 0; j < i_len; ++j) {
-                if (inbuf[j] == ':') break;
-            }
-            j = i_len - j;
-            i_len -= j;
-        }
+        for (j = 0; j < i_len; ++j)
+            if (inbuf[j] == ':')
+                break;
+        j = i_len - j;
+        i_len -= j;
 
         if (i_len > 0 &&
             atalk_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len) == (size_t)-1) {
@@ -806,36 +804,48 @@ static size_t pull_charset_flags (charset_t from_set, charset_t cap_set, const c
         }
 
         if (j) {
-            /* we're at the start on an hex encoded ucs2 char */
-            char h[MAXPATHLEN];
-            size_t hlen = 0;
-
+            /* we have a ':' */
             i_len = j, j = 0;
-            while (i_len >= 3 && inbuf[0] == ':' &&
-                   isxdigit(inbuf[1]) && isxdigit(inbuf[2])) {
-                h[hlen++] = (hextoint(inbuf[1]) << 4) | hextoint(inbuf[2]);
-                inbuf += 3;
-                i_len -= 3;
-            }
-            if (hlen) {
-                const char *h_buf = h;
-                if (atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len) == (size_t)-1) {
-                    i_len += hlen * 3;
-                    inbuf -= hlen * 3;
-                    if (errno == EILSEQ && (option & CONV_IGNORE)) {
+
+            if ((option & CONV_UNESCAPEHEX)) {
+                /* treat it as a CAP hex encoded char */
+                char h[MAXPATHLEN];
+                size_t hlen = 0;
+
+                while (i_len >= 3 && inbuf[0] == ':' &&
+                       isxdigit(inbuf[1]) && isxdigit(inbuf[2])) {
+                    h[hlen++] = (hextoint(inbuf[1]) << 4) | hextoint(inbuf[2]);
+                    inbuf += 3;
+                    i_len -= 3;
+                }
+                if (hlen) {
+                    const char *h_buf = h;
+                    if (atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len) == (size_t)-1) {
+                        i_len += hlen * 3;
+                        inbuf -= hlen * 3;
+                        if (errno == EILSEQ && (option & CONV_IGNORE)) {
+                            *flags |= CONV_REQMANGLE;
+                            return destlen - o_len;
+                        }
+                        goto end;
+                    }
+                } else {
+                    /* We have an invalid :xx sequence */
+                    errno = EILSEQ;
+                    if ((option & CONV_IGNORE)) {
                         *flags |= CONV_REQMANGLE;
                         return destlen - o_len;
                     }
                     goto end;
                 }
             } else {
-                /* We have an invalid :xx sequence */
-                errno = EILSEQ;
-                if ((option & CONV_IGNORE)) {
-                    *flags |= CONV_REQMANGLE;
-                    return destlen - o_len;
-                }
-                goto end;
+                /* a ':' that we just convert to a '/' */
+                ucs2_t slash = 0x002f;
+                memcpy(outbuf, &slash, sizeof(ucs2_t));
+                outbuf += 2;
+                o_len -= 2;
+                inbuf++;
+                i_len--;
             }
         }
     }
@@ -897,25 +907,23 @@ static size_t push_charset_flags (charset_t to_set, charset_t cap_set, char* src
     }
 
     while (i_len >= 2) {
-        if ((option & CONV_ESCAPEHEX)) {
-            for (i = 0; i < i_len; i += 2) {
-                ucs2_t c = SVAL(inbuf, i);
-                switch (c) {
-                case 0x003a: /* 0x003a = ':' */
-                    if ( ! (option & CONV_ALLOW_COLON)) {
-                        errno = EILSEQ;
-                        goto end;
-                    }
-                    escch = c;
-                    j = i_len - i;
-                    i_len = i;
-                    break;
-                case 0x002f: /* 0x002f = '/' */
-                    escch = c;
-                    j = i_len - i;
-                    i_len = i;
-                    break;
+        for (i = 0; i < i_len; i += 2) {
+            ucs2_t c = SVAL(inbuf, i);
+            switch (c) {
+            case 0x003a: /* 0x003a = ':' */
+                if ( ! (option & CONV_ALLOW_COLON)) {
+                    errno = EILSEQ;
+                    goto end;
                 }
+                escch = c;
+                j = i_len - i;
+                i_len = i;
+                break;
+            case 0x002f: /* 0x002f = '/' */
+                escch = c;
+                j = i_len - i;
+                i_len = i;
+                break;
             }
         }
         while (i_len > 0 &&
@@ -968,35 +976,53 @@ static size_t push_charset_flags (charset_t to_set, charset_t cap_set, char* src
         }
 
         if (j) {
+            /* we have a ':' or '/' */
             i_len = j, j = 0;
-            if (o_len < 3) {
-                errno = E2BIG;
-                goto end;
-            }
-            switch (escch) {
-            case '/':
-                *outbuf++ = ':';
-                *outbuf++ = '2';
-                *outbuf++ = 'f';
-                break;
-            case ':':
-                *outbuf++ = ':';
-                *outbuf++ = '3';
-                *outbuf++ = 'a';
-                break;
-            default:
-                /*
-                 *  THIS SHOULD NEVER BE REACHED !!!
-                 *  As a safety net I put in a ' ' here
-                 */
-                *outbuf++ = ':';
-                *outbuf++ = '2';
-                *outbuf++ = '0';
-                break;
+
+            if ((option & CONV_ESCAPEHEX)) {
+                /* CAP hex encode it */
+                if (o_len < 3) {
+                    errno = E2BIG;
+                    goto end;
+                }
+                switch (escch) {
+                case '/':
+                    *outbuf++ = ':';
+                    *outbuf++ = '2';
+                    *outbuf++ = 'f';
+                    break;
+                case ':':
+                    *outbuf++ = ':';
+                    *outbuf++ = '3';
+                    *outbuf++ = 'a';
+                    break;
+                default:
+                    /*
+                     *  THIS SHOULD NEVER BE REACHED !!!
+                     *  As a safety net I put in a ' ' here
+                     */
+                    *outbuf++ = ':';
+                    *outbuf++ = '2';
+                    *outbuf++ = '0';
+                    break;
+                }
+                o_len -= 3;
+                inbuf += 2;
+                i_len -= 2;
+            } else {
+                switch (escch) {
+                case '/':
+                case ':':
+                    *outbuf++ = ':';
+                    break;
+                default: /* should never be reached */
+                    *outbuf++ = ' ';
+                    break;
+                }
+                o_len--;
+                inbuf += 2;
+                i_len -= 2;
             }
-            o_len -= 3;
-            inbuf += 2;
-            i_len -= 2;
         }
     }
     if (i_len > 0) errno = EINVAL;
index c2388d5e78fa36f8642162debfbfd64ced2ce81c..a75ded21b552486f505da5e87bcc5fb5f624053a 100644 (file)
@@ -333,12 +333,14 @@ static char *volxlate(const AFPObj *obj,
                     q++;
             }
         } else if (IS_VAR(p, "$c")) {
-            DSI *dsi = obj->dsi;
-            len = sprintf(dest, "%s:%u",
-                          getip_string((struct sockaddr *)&dsi->client),
-                          getip_port((struct sockaddr *)&dsi->client));
-            dest += len;
-            destlen -= len;
+            if (IS_AFP_SESSION(obj)) {
+                DSI *dsi = obj->dsi;
+                len = sprintf(dest, "%s:%u",
+                              getip_string((struct sockaddr *)&dsi->client),
+                              getip_port((struct sockaddr *)&dsi->client));
+                dest += len;
+                destlen -= len;
+            }
         } else if (IS_VAR(p, "$d")) {
             q = path;
         } else if (pwd && IS_VAR(p, "$f")) {
@@ -356,7 +358,7 @@ static char *volxlate(const AFPObj *obj,
             q = getip_string((struct sockaddr *)&dsi->client);
         } else if (IS_VAR(p, "$s")) {
             q = obj->options.hostname;
-        } else if (obj->username && IS_VAR(p, "$u")) {
+        } else if (obj->username[0] && IS_VAR(p, "$u")) {
             char* sep = NULL;
             if ( obj->options.ntseparator && (sep = strchr(obj->username, obj->options.ntseparator[0])) != NULL)
                 q = sep+1;
@@ -716,10 +718,6 @@ static struct vol *creatvol(AFPObj *obj,
 
     if (getoption_bool(obj->iniconfig, section, "read only", preset, 0))
         volume->v_flags |= AFPVOL_RO;
-    if (!getoption_bool(obj->iniconfig, section, "hex encoding", preset, 1))
-        volume->v_flags |= AFPVOL_NOHEX;
-    if (getoption_bool(obj->iniconfig, section, "use dots", preset, 1))
-        volume->v_flags |= AFPVOL_USEDOTS;
     if (getoption_bool(obj->iniconfig, section, "invisible dots", preset, 0))
         volume->v_flags |= AFPVOL_INV_DOTS;
     if (!getoption_bool(obj->iniconfig, section, "stat vol", preset, 1))
@@ -768,10 +766,6 @@ static struct vol *creatvol(AFPObj *obj,
         volume->v_ad_options |= ADVOL_INVDOTS;
 
     /* Mac to Unix conversion flags*/
-    if (!(volume->v_flags & AFPVOL_NOHEX))
-        volume->v_mtou_flags |= CONV_ESCAPEHEX;
-    if (!(volume->v_flags & AFPVOL_USEDOTS))
-        volume->v_mtou_flags |= CONV_ESCAPEDOTS;
     if ((volume->v_flags & AFPVOL_EILSEQ))
         volume->v_mtou_flags |= CONV__EILSEQ;
 
@@ -781,7 +775,7 @@ static struct vol *creatvol(AFPObj *obj,
         volume->v_mtou_flags |= CONV_TOLOWER;
 
     /* Unix to Mac conversion flags*/
-    volume->v_utom_flags = CONV_IGNORE | CONV_UNESCAPEHEX;
+    volume->v_utom_flags = CONV_IGNORE;
     if ((volume->v_casefold & AFPVOL_UTOMUPPER))
         volume->v_utom_flags |= CONV_TOUPPER;
     else if ((volume->v_casefold & AFPVOL_UTOMLOWER))
@@ -947,13 +941,16 @@ static int vol_section(const char *sec)
 static int readvolfile(AFPObj *obj, const struct passwd *pwent)
 {
     EC_INIT;
+    static int regexerr = -1;
+    static regex_t reg;
     char        path[MAXPATHLEN + 1];
     char        volname[AFPVOL_U8MNAMELEN + 1];
     char        tmp[MAXPATHLEN + 1];
-    const char  *preset, *default_preset, *p;
+    const char  *preset, *default_preset, *p, *basedir;
     char        *q, *u;
     int         i;
     struct passwd   *pw;
+    regmatch_t match[1];
 
     LOG(log_debug, logtype_afpd, "readvolfile: BEGIN");
 
@@ -972,10 +969,31 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
             continue;
         if (STRCMP(secname, ==, INISEC_HOMES)) {
             have_uservol = 1;
-            if (obj->username[0] == 0
+            if (!IS_AFP_SESSION(obj)
                 || strcmp(obj->username, obj->options.guest) == 0)
                 /* not an AFP session, but cnid daemon, dbd or ad util, or guest login */
                 continue;
+            if (pwent->pw_dir == NULL || STRCMP("", ==, pwent->pw_dir))
+                /* no user home */
+                continue;
+
+            /* check if user home matches our "basedir regex" */
+            if ((basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL)
+                continue;
+            LOG(log_debug, logtype_afpd, "readvolfile: basedir regex: '%s'", basedir);
+
+            if (regexerr != 0 && (regexerr = regcomp(&reg, basedir, REG_EXTENDED)) != 0) {
+                char errbuf[1024];
+                regerror(regexerr, &reg, errbuf, sizeof(errbuf));
+                LOG(log_debug, logtype_default, "readvolfile: bad basedir regex: %s", errbuf);
+            }
+
+            if (regexec(&reg, pwent->pw_dir, 1, match, 0) == REG_NOMATCH) {
+                LOG(log_debug, logtype_default, "readvolfile: user home \"%s\" doesn't match basedir regex \"%s\"",
+                    pwent->pw_dir, basedir);
+                continue;
+            }
+
             strlcpy(tmp, pwent->pw_dir, MAXPATHLEN);
             strlcat(tmp, "/", MAXPATHLEN);
             if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))
@@ -1108,8 +1126,6 @@ int load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *))
             goto EC_CLEANUP;
         have_uservol = 0;
         for (vol = Volumes; vol; vol = vol->v_next) {
-            if (vol->v_flags & AFPVOL_UNIX_CTXT)
-                continue;
             vol->v_deleted = 1;
         }
     } else {
@@ -1222,6 +1238,8 @@ struct vol *getvolbyvid(const uint16_t vid )
 struct vol *getvolbypath(AFPObj *obj, const char *path)
 {
     EC_INIT;
+    static int regexerr = -1;
+    static regex_t reg;
     struct vol *vol;
     struct vol *tmp;
     const struct passwd *pw;
@@ -1231,8 +1249,6 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     char        tmpbuf[MAXPATHLEN + 1];
     const char *secname, *basedir, *p = NULL, *subpath = NULL, *subpathconfig;
     char *user = NULL, *prw;
-    int regexerr = -1;
-    static regex_t reg;
     regmatch_t match[1];
 
     LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\")", path);
@@ -1304,8 +1320,8 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     if (prw != 0)
         subpath = prw;
 
-    strlcpy(obj->username, user, MAXUSERLEN);
     strlcat(tmpbuf, user, MAXPATHLEN);
+    strlcat(obj->username, user, MAXUSERLEN);
     strlcat(tmpbuf, "/", MAXPATHLEN);
 
     /* (6) */
index 738e3b837851abc278296f05ebe6d038559dcbc6..8495d8c22fba19dd88789b82c6822bfb4a4fb3d6 100644 (file)
@@ -103,9 +103,6 @@ static int validupath_adouble(VFS_FUNC_ARGS_VALIDUPATH)
     if (name[0] != '.')
         return 1;
     
-    if (!(vol->v_flags & AFPVOL_USEDOTS))
-        return 0;
-        
     return netatalk_name(name) && strcmp(name,".AppleDouble") && strcasecmp(name,".Parent");
 }                                           
 
@@ -467,9 +464,6 @@ static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH)
     if (name[0] != '.')
         return 1;
     
-    if (!(vol->v_flags & AFPVOL_USEDOTS))
-        return 0;
-
 #ifndef HAVE_EAFD
     if (name[1] == '_')
         return ad_valid_header_osx(name);
index 9f738be994b844e7da3279bf1be45bea1ab2ab45..15c2f392f3200a7a6e5be64657fdff54b37503cf 100644 (file)
@@ -14,15 +14,14 @@ AC_DEFUN([NETATALK_GSSAPI_CHECK],
         )
 
        if test x"$compilegssapi" != x"no"; then
-
-                if test "x$compilegssapi" != "xyes" -a "x$compilegssapi" != "xauto"; then
-                       GSSAPI_CFLAGS="-I$withval/include"
-                       GSSAPI_CPPFLAGS="-I$withval/include"
-                       GSSAPI_LDFLAGS="-L$withval/${atalk_libname}"
-                       FOUND_GSSAPI=yes
+        if test "x$compilegssapi" != "xyes" -a "x$compilegssapi" != "xauto"; then
+            GSSAPI_CFLAGS="-I$withval/include"
+            GSSAPI_CPPFLAGS="-I$withval/include"
+            GSSAPI_LDFLAGS="-L$withval/${atalk_libname}"
+            FOUND_GSSAPI=yes
                        AC_MSG_CHECKING([checking for GSSAPI support in])
                        AC_MSG_RESULT([$compilegssapi])
-                fi
+        fi
 
 
          # Do no harm to the values of CFLAGS and LIBS while testing for
@@ -39,22 +38,20 @@ AC_DEFUN([NETATALK_GSSAPI_CHECK],
          AC_PATH_PROG(KRB5_CONFIG, krb5-config)
          AC_MSG_CHECKING(for working krb5-config)
          if test -x "$KRB5_CONFIG"; then
+        CFLAGS=""; export CFLAGS
+           LDFLAGS=""; export LDFLAGS
            TEMP="`$KRB5_CONFIG --libs gssapi`"
         if test $? -eq 0 ; then
-               save_CFLAGS=$CFLAGS
-               CFLAGS="";export CFLAGS
-               save_LDFLAGS=$LDFLAGS
-               LDFLAGS="";export LDFLAGS
                GSSAPI_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
                GSSAPI_CPPFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
             GSSAPI_LIBS="$TEMP"
-               CFLAGS=$save_CFLAGS;export CFLAGS
-               LDFLAGS=$save_LDFLAGS;export LDFLAGS
                FOUND_GSSAPI=yes
                AC_MSG_RESULT(yes)
         else
                AC_MSG_RESULT(no. Fallback to previous krb5 detection strategy)
         fi
+           CFLAGS=$save_CFLAGS; export CFLAGS
+           LDFLAGS=$save_LDFLAGS; export LDFLAGS
          else
            AC_MSG_RESULT(no. Fallback to previous krb5 detection strategy)
          fi
@@ -96,11 +93,10 @@ AC_DEFUN([NETATALK_GSSAPI_CHECK],
          fi
        fi
 
-       CFLAGS="$CFLAGS $GSSAPI_CFLAGS"
-       CPPFLAGS="$CPPFLAGS $GSSAPI_CPPFLAGS"
-       LDFLAGS="$LDFLAGS $GSSAPI_LDFLAGS"
-       LIBS="$LIBS $GSSAPI_LIBS"
-
+       CFLAGS="$GSSAPI_CFLAGS"
+       CPPFLAGS="$GSSAPI_CPPFLAGS"
+       LDFLAGS="$GSSAPI_LDFLAGS"
+       LIBS="$GSSAPI_LIBS"
 
        # check for gssapi headers
 
@@ -132,7 +128,7 @@ AC_DEFUN([NETATALK_GSSAPI_CHECK],
        if test x"$ac_cv_func_gss_acquire_cred" = x"yes"; then
                AC_DEFINE(HAVE_GSSAPI,1,[Whether to enable GSSAPI support])
                AC_MSG_RESULT([yes])
-               GSSAPI_LIBS="$LDFLAGS $LIBS"
+#              GSSAPI_LIBS="$LDFLAGS $LIBS"
        else
                AC_MSG_RESULT([no])
                if test x"$compilegssapi" = x"yes"; then
index 1fcdcb77168ec82e5545fd88633b3e3bc02dd29c..32ccd9e67c74fe1d6c8e0e1ea7dad6818d9d0867 100644 (file)
@@ -1,5 +1,24 @@
 dnl Kitchen sink for configuration macros
 
+dnl Whether to disable bundled libevent
+AC_DEFUN([AC_NETATALK_LIBEVENT], [
+    AC_MSG_CHECKING([whether to disable bundled libevent (define CPPFLAGS and LDFLAGS otherwise appropiately to pick up installed version)])
+    AC_ARG_ENABLE(
+        bundled-libevent,
+        [AC_HELP_STRING(
+            [--disable-bundled-libevent],
+            [whether the bundled version of libevent shall not be used (define CPPFLAGS and LDFLAGS otherwise appropiately to pick up installed version)]
+        )],
+        use_bundled_libevent=$enableval,
+        use_bundled_libevent=yes
+    )
+
+    if test x"$use_bundled_libevent" = x"yes" ; then
+        AC_CONFIG_SUBDIRS([libevent])
+    fi
+    AM_CONDITIONAL(USE_BUILTIN_LIBEVENT, test x"$use_bundled_libevent" = x"yes")
+])
+
 dnl Filesystem Hierarchy Standard (FHS) compatibility
 AC_DEFUN([AC_NETATALK_FHS], [
 AC_MSG_CHECKING([whether to use Filesystem Hierarchy Standard (FHS) compatibility])
@@ -441,6 +460,10 @@ netatalk_cv_HAVE_TIMEOUT_ID_T=yes,netatalk_cv_HAVE_TIMEOUT_ID_T=no,netatalk_cv_H
        AC_SUBST(KLDFLAGS)
 fi
 
+dnl Whether to run ldconfig after installing libraries
+AC_PATH_PROG(NETA_LDCONFIG, ldconfig, , [$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/usr/bin])
+echo NETA_LDCONFIG = $NETA_LDCONFIG
+AM_CONDITIONAL(RUN_LDCONFIG, test x"$this_os" = x"linux" -a x"$NETA_LDCONFIG" != x"")
 ])
 
 dnl Check for building PGP UAM module
@@ -489,6 +512,9 @@ fi
 AM_CONDITIONAL(USE_GSSAPI, test x"$netatalk_cv_build_krb5_uam" = x"yes")
 ])
 
+dnl Check if we can directly use Kerberos 5 API, used for reading keytabs
+dnl and automatically construction DirectoryService names from that, instead
+dnl of requiring special configuration in afp.conf
 AC_DEFUN([AC_NETATALK_KERBEROS], [
 AC_MSG_CHECKING([for Kerberos 5 (necessary for GetSrvrInfo:DirectoryNames support)])
 AC_ARG_WITH([kerberos],
@@ -508,8 +534,10 @@ if test x"$with_kerberos" != x"no"; then
    AC_MSG_CHECKING([for krb5-config])
    if test -x "$KRB5_CONFIG"; then
       AC_MSG_RESULT([$KRB5_CONFIG])
-      CFLAGS="$CFLAGS `$KRB5_CONFIG --cflags krb5`"
-      LIBS="`$KRB5_CONFIG --libs krb5` $LIBS"
+      KRB5_CFLAGS="`$KRB5_CONFIG --cflags krb5`"
+      KRB5_LIBS="`$KRB5_CONFIG --libs krb5`"
+      AC_SUBST(KRB5_CFLAGS)
+      AC_SUBST(KRB5_LIBS)
       with_kerberos="yes"
    else
       AC_MSG_RESULT([not found])
@@ -542,34 +570,47 @@ AC_MSG_CHECKING(for LDAP (necessary for client-side ACL visibility))
 AC_ARG_WITH(ldap,
     [AS_HELP_STRING([--with-ldap],
         [LDAP support (default=auto)])],
-    [ case "$withval" in
-      yes|no)
-          with_ldap="$withval"
-                 ;;
-      *)
-          with_ldap=auto
-          ;;
-      esac ])
-AC_MSG_RESULT($with_ldap)
+        netatalk_cv_ldap=$withval,
+        netatalk_cv_ldap=auto
+        )
+AC_MSG_RESULT($netatalk_cv_ldap)
 
-if test x"$with_ldap" != x"no" ; then
-       AC_CHECK_HEADER([ldap.h], with_ldap=yes,
-        [ if test x"$with_ldap" = x"yes" ; then
+save_CFLAGS=$CFLAGS
+save_LDLFLAGS=$LDLFLAGS
+CFLAGS=""
+LDLFLAGS=""
+
+if test x"$netatalk_cv_ldap" != x"no" ; then
+   if test x"$netatalk_cv_ldap" != x"yes" -a x"$netatalk_cv_ldap" != x"auto"; then
+       CFLAGS=-I$netatalk_cv_ldap/include
+       LDLFLAGS=-L$netatalk_cv_ldap/lib
+   fi
+       AC_CHECK_HEADER([ldap.h], netatalk_cv_ldap=yes,
+        [ if test x"$netatalk_cv_ldap" = x"yes" ; then
             AC_MSG_ERROR([Missing LDAP headers])
         fi
-               with_ldap=no
+               netatalk_cv_ldap=no
         ])
-       AC_CHECK_LIB(ldap, ldap_init, with_ldap=yes,
-        [ if test x"$with_ldap" = x"yes" ; then
+       AC_CHECK_LIB(ldap, ldap_init, netatalk_cv_ldap=yes,
+        [ if test x"$netatalk_cv_ldap" = x"yes" ; then
             AC_MSG_ERROR([Missing LDAP library])
         fi
-               with_ldap=no
+               netatalk_cv_ldap=no
         ])
 fi
 
-if test x"$with_ldap" = x"yes"; then
+if test x"$netatalk_cv_ldap" = x"yes"; then
+    LDAP_CFLAGS=$CFLAGS
+    LDAP_LDLFLAGS=$LDLFLAGS
+    LDAP_LIBS=-lldap
        AC_DEFINE(HAVE_LDAP,1,[Whether LDAP is available])
+    AC_SUBST(LDAP_CFLAGS)
+    AC_SUBST(LDAP_LDLFLAGS)
+    AC_SUBST(LDAP_LIBS)
 fi
+
+CFLAGS=$save_CFLAGS
+LDLFLAGS=$save_LDLFLAGS
 ])
 
 dnl Check for ACL support
index e6927be761a53d405a03667fe1c47044488e57c4..a618cf31ccacca089ec2e3a67b9b78038c0af9e9 100644 (file)
@@ -52,7 +52,7 @@ dnl   fi
        AC_MSG_RESULT([         Samba sharemode interop: $neta_cv_have_smbshmd])
        AC_MSG_RESULT([         ACL support:             $with_acl_support])
        AC_MSG_RESULT([         Kerberos support:        $with_kerberos])
-       AC_MSG_RESULT([         LDAP support:            $with_ldap])
+       AC_MSG_RESULT([         LDAP support:            $netatalk_cv_ldap])
        if test x"$use_pam_so" = x"yes" -a x"$netatalk_cv_install_pam" = x"no"; then
                AC_MSG_RESULT([])
                AC_MSG_WARN([ PAM support was configured for your system, but the netatalk PAM configuration file])
@@ -111,4 +111,9 @@ AC_DEFUN([AC_NETATALK_LIBS_SUMMARY], [
                AC_MSG_RESULT([        LIBS   = $ZEROCONF_LIBS])
                AC_MSG_RESULT([        CFLAGS = $ZEROCONF_CFLAGS])
        fi
+       if test x"$netatalk_cv_ldap" = x"yes"; then
+               AC_MSG_RESULT([    LDAP:])
+               AC_MSG_RESULT([        LIBS   = $LDAP_LDLFLAGS $LDAP_LIBS])
+               AC_MSG_RESULT([        CFLAGS = $LDAP_CFLAGS])
+       fi
 ])
index 0506a802aff7d6a015dbf6ff330aa36393ad804c..c96eddb828d95ab0c585d260245112ec3f1a9cc8 100644 (file)
@@ -942,17 +942,9 @@ is performed when accessing filesystems from clients\&. This is generally useful
 on volumes and do the conversion with that\&. Then this option can be set to no\&.
 .RE
 .PP
-hex encoding = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
-.RS 4
-Whether :hex encoding is done for file and directory names containing the character
-/\&. Setting this option to no makes the
-/
-character illegal\&.
-.RE
-.PP
 invisible dots = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
 .RS 4
-make dot files invisible\&. If "\fBuse dots = no\fR", this parameter is not unnecessary\&.
+make dot files invisible\&.
 .RE
 .PP
 network ids = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
@@ -1003,12 +995,6 @@ Whether to use AFP3 UNIX privileges\&. This should be set for OS X clients\&. Se
 and
 \fBumask\fR\&.
 .RE
-.PP
-use dots = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
-.RS 4
-Whether to do :hex translation for dot files\&. See also
-\fBinvisible dots\fR\&.
-.RE
 .SH "CNID BACKENDS"
 .PP
 The AFP protocol mostly refers to files and directories by ID and not by name\&. Netatalk needs a way to store these ID\'s in a persistent way, to achieve this several different CNID backends are available\&. The CNID Databases are by default located in the
index cb870d0c06813c0b561cc2b5307ae5fe9434ccb6..033c9e1d3784c3b4c0651100d0243c2aa02bf84f 100644 (file)
@@ -52,7 +52,7 @@ test_CFLAGS = \
        -I$(top_srcdir)/etc/afpd \
        -I$(top_srcdir)/include \
        -I$(top_srcdir)/sys \
-       @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ \
+       @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ @KRB5_CFLAGS@\
        -DAPPLCNAME \
        -DSERVERTEXT=\"$(SERVERTEXT)/\" \
        -D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
@@ -62,6 +62,6 @@ test_CFLAGS = \
 
 test_LDADD = \
        $(top_builddir)/libatalk/libatalk.la \
-       @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@
+       @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@ @KRB5_LIBS@
 
 test_LDFLAGS = -export-dynamic