]> arthur.barton.de Git - netatalk.git/commitdiff
Merge master
authorFrank Lahm <franklahm@googlemail.com>
Sat, 23 Apr 2011 07:43:31 +0000 (09:43 +0200)
committerFrank Lahm <franklahm@googlemail.com>
Sat, 23 Apr 2011 07:43:31 +0000 (09:43 +0200)
45 files changed:
1  2 
bin/Makefile.am
bin/ad/ad_cp.c
bin/ad/ad_mv.c
bin/uniconv/uniconv.c
configure.in
etc/afpd/Makefile.am
etc/afpd/afp_config.c
etc/afpd/afp_dsi.c
etc/afpd/afp_options.c
etc/afpd/auth.c
etc/afpd/directory.c
etc/afpd/directory.h
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/fork.h
etc/afpd/globals.h
etc/afpd/ofork.c
etc/afpd/status.c
etc/afpd/unix.c
etc/afpd/volume.c
etc/afpd/volume.h
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/cnid_metad.c
etc/cnid_dbd/comm.c
etc/cnid_dbd/db_param.h
etc/cnid_dbd/dbif.c
etc/cnid_dbd/dbif.h
etc/cnid_dbd/main.c
include/atalk/dsi.h
include/atalk/unicode.h
include/atalk/util.h
libatalk/acl/unix.c
libatalk/cnid/dbd/cnid_dbd.c
libatalk/dsi/dsi_close.c
libatalk/dsi/dsi_getsess.c
libatalk/dsi/dsi_stream.c
libatalk/unicode/util_unistr.c
libatalk/util/Makefile.am
libatalk/util/server_child.c
libatalk/vfs/ea_sys.c
libatalk/vfs/extattr.c
libatalk/vfs/unix.c
macros/db3-check.m4
man/man1/Makefile.am
man/man5/Makefile.am

diff --combined bin/Makefile.am
index 1742ea6b54ead1da999d177b86cc338da4e5274e,7c633f748f409ed1fecf5ba637ebfa75d7ce572b..f5d1448ae3621d70a8241af4864a925335693e68
@@@ -1,3 -1,11 +1,7 @@@
  # Makefile.am for bin/
  
- SUBDIRS = ad afppasswd cnid megatron uniconv misc
 -SUBDIRS = adv1tov2 afppasswd cnid megatron uniconv misc
 -
 -if USE_APPLETALK
 -SUBDIRS += aecho getzones nbp pap psorder
 -endif
++SUBDIRS = afppasswd cnid megatron uniconv misc
+ if HAVE_ATFUNCS
+ SUBDIRS += ad
+ endif
diff --combined bin/ad/ad_cp.c
index 0ee0f405947717ff9e801c53d02310d5e72746d7,ac0a737a0b5a12cfcc3477ace70f282ba7f5a3e4..b0723b021976d69f4a778fdbeef3006d4c3489ea
@@@ -387,6 -387,10 +387,10 @@@ static int copy(const char *path
      if (alarmed)
          return -1;
  
+     /* This currently doesn't work with "." */
+     if (strcmp(path, ".") == 0) {
+         ERROR("\".\" not supported");
+     }
      const char *dir = strrchr(path, '/');
      if (dir == NULL)
          dir = path;
                  break;
              }
              ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options);
 -            if (ad_open_metadata(to.p_path, ADFLAGS_DIR, O_RDWR | O_CREAT, &ad) != 0) {
 +            if (ad_open(&ad, to.p_path, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0) {
                  ERROR("Error opening adouble for: %s", to.p_path);
              }
              ad_setid( &ad, st.st_dev, st.st_ino, did, pdid, dvolume.db_stamp);
                  break;
              }
              ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options);
 -            if (ad_open_metadata(to.p_path, 0, O_RDWR | O_CREAT, &ad) != 0) {
 +            if (ad_open(&ad, to.p_path, ADFLAGS_HF, O_RDWR | O_CREAT) != 0) {
                  ERROR("Error opening adouble for: %s", to.p_path);
              }
              ad_setid( &ad, st.st_dev, st.st_ino, cnid, did, dvolume.db_stamp);
diff --combined bin/ad/ad_mv.c
index 0355364398e81183e566f040ee1a53e0d16d7265,4d23183ae13865c3c59a8298cde36e5cedbfeb91..156d648b004a5d2fe0f26a6a30ef1b95b4378651
@@@ -186,7 -186,7 +186,7 @@@ int ad_mv(int argc, char *argv[]
      set_signal();
      cnid_init();
      if (openvol(argv[argc - 1], &dvolume) != 0) {
-         SLOG("Error opening CNID database for %s: ", argv[argc - 1]);
+         SLOG("Error opening CNID database for source \"%s\": ", argv[argc - 1]);
          return 1;
      }
  
          if (argc > 2)
              usage_mv();
          if (openvol(argv[0], &svolume) != 0) {
-             SLOG("Error opening CNID database for %s: ", argv[0]);
+             SLOG("Error opening CNID database for destination \"%s\": ", argv[0]);
              return 1;
          }
          rval = do_move(argv[0], argv[1]);
              rval = 1;
          } else {
              memmove(endp, p, (size_t)len + 1);
-             if (openvol(*argv, &svolume) != 0) {
-                 SLOG("Error opening CNID database for %s: ", argv[0]);
-                 rval = 1;
-                 goto exit;
-             }
+             openvol(*argv, &svolume);
              if (do_move(*argv, path))
                  rval = 1;
              closevol(&svolume);
@@@ -377,7 -374,7 +374,7 @@@ static int do_move(const char *from, co
  
          struct adouble ad;
          ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options);
 -        if (ad_open_metadata(to, S_ISDIR(sb.st_mode) ? ADFLAGS_DIR : 0, O_RDWR, &ad) != 0) {
 +        if (ad_open(&ad, to, S_ISDIR(sb.st_mode) ? (ADFLAGS_DIR | ADFLAGS_HF) : ADFLAGS_HF, O_RDWR) != 0) {
              SLOG("Error opening adouble for: %s", to);
              return 1;
          }
diff --combined bin/uniconv/uniconv.c
index 850c45d79747d13b77a15ed1bc3ca0d488efa3bf,e6d1daeb4d5fa470bb677687d3fcfc2ec7ad726d..5dfc823115bef5ea6f960d7429ce81012d0e559a
  #include <sys/param.h>
  #include <pwd.h>
  #include <dirent.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/afp.h>
  #include <atalk/unicode.h>
  #include <atalk/util.h>
  #include <atalk/logger.h>
 +#include <atalk/compat.h>
  
  #include "atalk/cnid.h"
  #ifndef MAXPATHLEN
@@@ -389,7 -386,7 +389,7 @@@ static int init(char* path
  {
        DIR* startdir;
  
-     if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, NULL, NULL)) ) {
+     if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, "localhost", "4700")) ) {
                  fprintf (stderr, "ERROR: cannot open CNID database in '%s'\n", path);
                  fprintf (stderr, "ERROR: check the logs for reasons, aborting\n");
                return -1;
diff --combined configure.in
index 9da854d290693bfc352305a3574a5827a04f1951,48449921b926c766497b252d458c08cb237e17e0..ea334e47e72210699089039979e18396ca1bb73b
@@@ -21,43 -21,35 +21,43 @@@ AC_PROG_LIBTOO
  AC_PROG_PERL
  AC_PROG_GREP
  AC_PROG_PS
 -
  AM_PROG_CC_C_O
  
 -dnl Checks for header files.
 -AC_HEADER_DIRENT
 -AC_HEADER_STDC
 -AC_HEADER_SYS_WAIT
 -AC_CHECK_HEADERS(fcntl.h limits.h stdint.h strings.h time.h sys/param.h sys/fcntl.h sys/file.h sys/ioctl.h sys/time.h sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h mntent.h syslog.h unistd.h termios.h sys/termios.h netdb.h sgtty.h ufs/quota.h mount.h statfs.h sys/types.h dlfcn.h errno.h sys/errno.h sys/uio.h langinfo.h locale.h sys/filio.h)
 -AC_CHECK_HEADER(sys/cdefs.h,,
 -      AC_MSG_RESULT([enabling generic cdefs.h from tree])
 -      CFLAGS="-I\$(top_srcdir)/sys/generic $CFLAGS"
 -)
 +dnl Checks for typedefs, structures, and compiler characteristics.
 +AC_C_INLINE
 +
 +dnl Request SUSv3 standard interfaces plus anything else the platform may have
 +CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D__EXTENSIONS__ -D_GNU_SOURCE"
 +
 +dnl Check if we can use attribute unused (gcc only) from ethereal
 +AC_MSG_CHECKING(to see if we can add '__attribute__((unused))' to CFLAGS)
 +if test x$GCC != x ; then
 +  CFLAGS="-D_U_=\"__attribute__((unused))\" $CFLAGS"
 +  AC_MSG_RESULT(yes)
 +else
 +  CFLAGS="-D_U_=\"\" $CFLAGS"
 +  AC_MSG_RESULT(no)
 +fi
 +
 +dnl Configure libevent
 +AC_CONFIG_SUBDIRS([libevent])
 +
 +dnl Checks for header files, some checks are obsolete, unfortunately the code
 +dnl uses the resulting macros, so the code has to cleaned up too before
 +dnl we can remove the checks here.
 +AC_CHECK_HEADERS(mntent.h unistd.h termios.h ufs/quota.h)
 +AC_CHECK_HEADERS(netdb.h sgtty.h statfs.h dlfcn.h langinfo.h locale.h)
 +AC_CHECK_HEADERS(sys/param.h sys/fcntl.h sys/termios.h)
 +AC_CHECK_HEADERS(sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h)
 +dnl Checks for header files, confirmed to be required as of 2011
 +AC_CHECK_HEADERS(sys/epoll.h)
  AC_CHECK_HEADERS([sys/mount.h], , , 
  [#ifdef HAVE_SYS_PARAM_H
  #include <sys/param.h>
  #endif
  ])
  
 -dnl Checks for typedefs, structures, and compiler characteristics.
 -AC_C_CONST
 -AC_TYPE_UID_T
 -AC_C_INLINE
 -AC_TYPE_MODE_T
 -AC_TYPE_OFF_T
 -AC_TYPE_PID_T
 -AC_TYPE_SIZE_T
 -AC_STRUCT_ST_RDEV
 -AC_HEADER_TIME
 -AC_STRUCT_TM
 +AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.]))
  
  dnl --------------------------------------------------------------------------
  dnl check if dlsym needs to add an underscore, uses libtool macros 
@@@ -69,55 -61,40 +69,60 @@@ if test x"$libltdl_cv_need_uscore" = xy
      AC_DEFINE(DLSYM_PREPEND_UNDERSCORE, 1, [BSD compatibility macro])
  fi
  
 -dnl Checks for library functions.
 -AC_TYPE_GETGROUPS
 -AC_PROG_GCC_TRADITIONAL
 -AC_FUNC_MEMCMP
 -AC_HEADER_MAJOR
 -AC_FUNC_MMAP
 -AC_TYPE_SIGNAL
 -AC_FUNC_UTIME_NULL
 -AC_FUNC_WAIT3
 -AC_CHECK_FUNCS(getcwd gethostname gettimeofday getusershell mkdir rmdir select socket strdup strcasestr strstr strtoul strchr memcpy)
 -AC_CHECK_FUNCS(backtrace_symbols setlocale nl_langinfo strlcpy strlcat setlinebuf dirfd pselect access pread pwrite)
 -AC_CHECK_FUNCS(waitpid getcwd strdup strndup strnlen strtoul strerror chown fchown chmod fchmod chroot link mknod mknod64)
 +dnl Special hecks
+ ac_neta_haveatfuncs=yes
+ AC_CHECK_FUNCS(openat renameat fstatat unlinkat, , ac_neta_haveatfuncs=no)
+ if test x"$ac_neta_haveatfuncs" = x"yes" ; then
+    AC_DEFINE([_ATFILE_SOURCE], 1, AT file source)
+    AC_DEFINE([HAVE_ATFUNCS], 1, whether at funcs are available)
+ fi
 -
  AC_CHECK_MEMBERS(struct tm.tm_gmtoff,,, [#include <time.h>])
  
 -AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)])
 -AC_CHECK_FUNC(connect,,[AC_CHECK_LIB(socket,connect)])
 -dnl search for necessary libs for libpthread stuff
 -AC_SEARCH_LIBS(pthread_sigmask, pthread,, 
 -               [AC_MSG_ERROR([cannot find pthread_sigmask in libc or libpthread])])
 +dnl these tests have been comfirmed to be needed in 2011
- AC_CHECK_FUNC(renameat, AC_DEFINE([_ATFILE_SOURCE], 1, AT file source)) 
 +AC_CHECK_FUNC(epoll_create, AC_DEFINE([HAVE_EPOLL], 1, Whether Linux epoll is available)) 
 +AC_CHECK_FUNCS(backtrace_symbols dirfd getusershell pread pwrite pselect)
 +AC_CHECK_FUNCS(setlinebuf strlcat strlcpy strnlen)
 +AC_CHECK_FUNCS(mmap utime getpagesize) dnl needed by tbd
 +
 +dnl search for necessary libraries
 +AC_SEARCH_LIBS(gethostbyname, nsl)
 +AC_SEARCH_LIBS(connect, socket)
 +AC_SEARCH_LIBS(pthread_sigmask, pthread,,[AC_MSG_ERROR([missing pthread_sigmask])])
  if test x"$ac_cv_search_pthread_sigmask" != x"none required" ; then
     PTHREAD_LIBS=$ac_cv_search_pthread_sigmask
  fi
  AC_SUBST(PTHREAD_LIBS)
 -AC_CACHE_SAVE
  
 -dnl Checks for (v)snprintf
 -NETATALK_SNPRINTF_CHECK
 +dnl --------------------- Check if realpath() takes NULL
 +AC_CACHE_CHECK([if the realpath function allows a NULL argument],
 +    neta_cv_REALPATH_TAKES_NULL, [
 +        AC_TRY_RUN([
 +            #include <stdio.h>
 +            #include <limits.h>
 +            #include <signal.h>
 +
 +            void exit_on_core(int ignored) {
 +                 exit(1);
 +            }
 +
 +            main() {
 +                char *newpath;
 +                signal(SIGSEGV, exit_on_core);
 +                newpath = realpath("/tmp", NULL);
 +                exit((newpath != NULL) ? 0 : 1);
 +            }],
 +            neta_cv_REALPATH_TAKES_NULL=yes,
 +            neta_cv_REALPATH_TAKES_NULL=no,
 +            neta_cv_REALPATH_TAKES_NULL=cross
 +        )
 +    ]
 +)
 +
 +if test x"$neta_cv_REALPATH_TAKES_NULL" = x"yes"; then
 +    AC_DEFINE(REALPATH_TAKES_NULL,1,[Whether the realpath function allows NULL])
 +fi
 +
 +AC_CACHE_SAVE
  
  dnl --------------------------------------------------------------------------
  dnl 64bit platform check
@@@ -158,92 -135,347 +163,92 @@@ dnl -----------------------------------
  dnl specific configuration comes in here:
  dnl --------------------------------------------------------------------------
  
 +dnl Check for optional admin group support
 +AC_NETATALK_ADMIN_GROUP
  
 -netatalk_cv_admin_group=yes
 -AC_MSG_CHECKING([for administrative group support])
 -AC_ARG_ENABLE(admin-group,
 -      [  --disable-admin-group   disable admin group],[
 -        if test x"$enableval" = x"no"; then
 -              AC_DEFINE(ADMIN_GRP, 0, [Define if the admin group should be enabled])
 -              netatalk_cv_admin_group=no
 -              AC_MSG_RESULT([no])
 -      else
 -              AC_DEFINE(ADMIN_GRP, 1, [Define if the admin group should be enabled])
 -              AC_MSG_RESULT([yes])
 -        fi],[
 -              AC_DEFINE(ADMIN_GRP, 1, [Define if the admin group should be enabled])
 -              AC_MSG_RESULT([yes])
 -      ]
 -)
 +dnl Check for optional AFS support
 +AC_NETATALK_AFS_CHECK
  
 -NETATALK_AFS_CHECK
 -
 -NETATALK_CONFIG_DIRS
 -
 -netatalk_cv_with_cracklib=no
 -AC_ARG_WITH(cracklib,
 -      [  --with-cracklib=DICT    enable/set location of cracklib dictionary],[
 -      if test "x$withval" != "xno" ; then
 -              cracklib="$withval"
 -              AC_CHECK_LIB(crack, main, [
 -                      AC_DEFINE(USE_CRACKLIB, 1, [Define if cracklib should be used])
 -                      LIBS="$LIBS -lcrack"
 -                      if test "$cracklib" = "yes"; then
 -                              cracklib="/usr/$atalk_libname/cracklib_dict"
 -                      fi
 -                      AC_DEFINE_UNQUOTED(_PATH_CRACKLIB, "$cracklib",
 -                              [path to cracklib dictionary])
 -                      AC_MSG_RESULT([setting cracklib dictionary to $cracklib])
 -                      netatalk_cv_with_cracklib=yes
 -                      ],[
 -                      AC_MSG_ERROR([cracklib not found!])
 -                      ]
 -              )
 -      fi
 -      ]
 -)
 -AC_MSG_CHECKING([for cracklib support])
 -AC_MSG_RESULT([$netatalk_cv_with_cracklib])
 -
 -netatalk_cv_ddp_enabled=no
 -AC_MSG_CHECKING([whether to enable DDP])
 -AC_ARG_ENABLE(ddp,
 -      [  --enable-ddp            enable DDP (AppleTalk)],[
 -      if test "$enableval" = "yes"; then 
 -              AC_MSG_RESULT([yes])
 -              netatalk_cv_ddp_enabled=yes
 -      else
 -              AC_MSG_RESULT([yes])
 -              AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -              AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
 -      ]
 -)
 +dnl --with-pkgconfdir check to change configuration directory location
 +AC_NETATALK_CONFIG_DIRS
  
 -AC_MSG_CHECKING([whether to enable debug code])
 -AC_ARG_ENABLE(debug1,
 -      [  --enable-debug1         enable debug code],[
 -      if test "$enableval" != "no"; then
 -              if test "$enableval" = "yes"; then
 -                      AC_DEFINE(DEBUG1, 1, [Define if debugging information should be included])
 -              else
 -                      AC_DEFINE_UNQUOTED(DEBUG1, $enableval, [Define if debugging information should be included])
 -              fi 
 -              AC_MSG_RESULT([yes])
 -      else
 -              AC_MSG_RESULT([no])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -      ]
 -)
 -
 -AC_MSG_CHECKING([whether to enable verbose debug code])
 -AC_ARG_ENABLE(debug,
 -      [  --enable-debug          enable verbose debug code],[
 -      if test "$enableval" != "no"; then
 -              if test "$enableval" = "yes"; then
 -                      AC_DEFINE(DEBUG, 1, [Define if verbose debugging information should be included])
 -              else
 -                      AC_DEFINE_UNQUOTED(DEBUG, $enableval, [Define if verbose debugging information should be included])
 -              fi 
 -              AC_MSG_RESULT([yes])
 -      else
 -              AC_MSG_RESULT([no])
 -        AC_DEFINE(NDEBUG, 1, [Disable assertions])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -        AC_DEFINE(NDEBUG, 1, [Disable assertions])
 -      ]
 -)
 +dnl Check for optional cracklib support
 +AC_NETATALK_CRACKLIB
  
 -AC_MSG_CHECKING([whether to enable debugging with debuggers])
 -AC_ARG_ENABLE(debugging,
 -      [  --enable-debugging      disable SIGALRM timers and DSI tickles (eg for debugging with gdb/dbx/...)],[
 -      if test "$enableval" != "no"; then
 -              if test "$enableval" = "yes"; then
 -                      AC_DEFINE(DEBUGGING, 1, [Define if you want to disable SIGALRM timers and DSI tickles])
 -              else
 -                      AC_DEFINE_UNQUOTED(DEBUGGING, $enableval, [Define if you want to disable SIGALRM timers and DSI tickles])
 -              fi 
 -              AC_MSG_RESULT([yes])
 -      else
 -              AC_MSG_RESULT([no])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -      ]
 -)
 +dnl Check whether to enable debug code
 +AC_NETATALK_DEBUG
  
 -AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.]))
 -AC_CHECK_ICONV
 -
 -dnl ----------- A NOTE ABOUT DROPKLUDGE
 -dnl The trouble with this fix is that if you know what the file is called, it
 -dnl can be read from the Unix side.  That's okay for most academic institutions
 -dnl since the students don't have telnet access to the Mac servers.  There is
 -dnl currently no one working on further development/fixes of DROPKLUDGE.
 -dnl -----------
 -
 -netatalk_cv_dropkludge=no
 -AC_MSG_CHECKING([whether to enable experimental dropbox support])
 -AC_ARG_ENABLE(dropkludge,
 -      [  --enable-dropkludge     enable the experimental dropbox fix (INSECURE!) ],[
 -      if test "$enableval" = "yes"; then 
 -              AC_DEFINE(DROPKLUDGE, 1, [Define if you want to use the experimental dropkludge support])
 -              AC_MSG_RESULT([yes])
 -              netatalk_cv_dropkludge=yes
 -      else
 -              AC_MSG_RESULT([no])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -      ]
 -)
 +dnl Check whethe to disable tickle SIGALARM stuff, which eases debugging
 +AC_NETATALK_DEBUGGING
  
 -netatalk_cv_force_uidgid=no
 -AC_MSG_CHECKING([whether to enable forcing of uid/gid per volume])
 -AC_ARG_ENABLE(force-uidgid,
 -      [  --enable-force-uidgid   allow forcing of uid/gid per volume (BROKEN) ],[
 -      if test "$enableval" = "yes"; then
 -              AC_DEFINE(FORCE_UIDGID, 1, [Define if you want forcing of uid/gid per volume])
 -              AC_MSG_RESULT([enabling forcing of uid/gid per volume])
 -              AC_MSG_RESULT([yes])
 -              netatalk_cv_force_uidgid=yes
 -      else
 -              AC_MSG_RESULT([no])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -      ]
 -)
 +dnl   Check for libiconv support
 +AC_NETATALK_CHECK_ICONV
  
  dnl Check for CNID database backends
 -bdb_required=no
  AC_NETATALK_CNID([bdb_required=yes],[bdb_required=no])
  
  dnl Check for quota support
 -AC_CHECK_QUOTA
 +AC_NETATALK_CHECK_QUOTA
  
  dnl Check for optional server location protocol support (used by MacOS X)
 -NETATALK_SRVLOC
 +AC_NETATALK_SRVLOC
  
  dnl Check for optional Zeroconf support
 -NETATALK_ZEROCONF
 +AC_NETATALK_ZEROCONF
  
 -dnl Check for PAM libs
 -netatalk_cv_use_pam=no
 -AC_PATH_PAM([
 -      use_pam_so=yes
 -      compile_pam=yes
 -      netatalk_cv_use_pam=yes
 -      AC_DEFINE(USE_PAM, 1, [Define to enable PAM support])
 -])
 +dnl Check for optional TCP-wrappers support
 +AC_NETATALK_TCP_WRAPPERS
  
 -netatalk_cv_use_shadowpw=no
 -AC_ARG_WITH(shadow,
 -      [  --with-shadow           enable shadow password support [[auto]]],
 -      [netatalk_cv_use_shadowpw="$withval"],
 -      [netatalk_cv_use_shadowpw=auto]
 -)
 -
 -if test "x$netatalk_cv_use_shadowpw" != "xno"; then
 -    AC_CHECK_HEADER([shadow.h])
 -    if test x"$ac_cv_header_shadow_h" = x"yes"; then
 -      netatalk_cv_use_shadowpw=yes
 -      AC_DEFINE(SHADOWPW, 1, [Define if shadow passwords should be used])
 -    else 
 -      if test "x$shadowpw" = "xyes"; then
 -        AC_MSG_ERROR([shadow support not available])
 -      else
 -              netatalk_cv_use_shadowpw=no
 -      fi
 -    fi 
 -fi
 +dnl Check for PAM libs
 +AC_NETATALK_PATH_PAM
  
 -AC_MSG_CHECKING([whether shadow support should be enabled])
 -if test "x$netatalk_cv_use_shadowpw" = "xyes"; then
 -      AC_MSG_RESULT([yes])
 -else
 -      AC_MSG_RESULT([no])
 -fi
 -      
 +dnl Check for optional shadow password support
 +AC_NETATALK_SHADOW
        
 -      
 -netatalk_cv_use_shellcheck=yes
 -AC_MSG_CHECKING([whether checking for a valid shell should be enabled])
 -AC_ARG_ENABLE(shell-check,
 -      [  --disable-shell-check   disable checking for a valid shell],[
 -      if test "$enableval" = "no"; then 
 -              AC_DEFINE(DISABLE_SHELLCHECK, 1, [Define if shell check should be disabled])
 -              AC_MSG_RESULT([no])
 -              netatalk_cv_use_shellcheck=no
 -      else
 -              AC_MSG_RESULT([yes])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([yes])
 -      ]
 -)
 +dnl Check for optional valid-shell-check support
 +AC_NETATALK_SHELL_CHECK
  
 -NETATALK_TCP_WRAPPERS
 -
 -AC_MSG_CHECKING([whether system (fcntl) locking should be disabled])
 -AC_ARG_ENABLE(locking,
 -        [  --disable-locking       disable system locking],[
 -              if test "$enableval" = "no"; then
 -                      AC_DEFINE(DISABLE_LOCKING, 1, [Define if system (fcntl) locking should be disabled])
 -                      AC_MSG_RESULT([yes])
 -              else
 -                      AC_MSG_RESULT([no])
 -              fi
 -              
 -      ],[
 -              AC_MSG_RESULT([no])
 -      ]
 +dnl Check for optional Webmin
 +AC_NETATALK_WEBMIN
  
 -)
 +dnl Check for optional sysv initscript install
 +AC_NETATALK_SYSV_STYLE
  
 +dnl Path where UAM modules shall be installed
 +AC_ARG_WITH(uams-path, [  --with-uams-path=PATH   path to UAMs [[PKGCONF/uams]]], [uams_path="$withval"], [uams_path="${PKGCONFDIR}/uams"])
  
 -AC_ARG_ENABLE(redhat,
 -      [  --enable-redhat         use redhat-style sysv configuration ],[
 -      if test "$enableval" = "yes"; then
 -              sysv_style=redhat
 -      fi
 -      AC_MSG_RESULT([enabling redhat-style sysv support])
 -      ]
 -)
 +dnl Check for libgcrypt, if found enables DHX2 UAM
 +AC_NETATALK_PATH_LIBGCRYPT([1:1.2.3])
  
 -AC_ARG_ENABLE(suse,
 -      [  --enable-suse           use suse-style sysv configuration ],[
 -      if test "$enableval" = "yes"; then
 -              sysv_style=suse
 -      fi
 -      AC_MSG_RESULT([enabling suse-style sysv support])
 -      ]
 -)
 +dnl Check for openssl, if found enables DHX UAM and Randnum UAM
 +AC_NETATALK_PATH_SSL
  
 -AC_ARG_ENABLE(gentoo,
 -      [  --enable-gentoo         use gentoo-style sysv configuration ],[
 -      if test "$enableval" = "yes"; then
 -              sysv_style=gentoo
 -      fi
 -      AC_MSG_RESULT([enabling gentoo-style sysv support])
 -      ]
 -)
 +dnl Check for Berkeley DB library
 +AC_NETATALK_PATH_BDB
  
 -AC_ARG_ENABLE(cobalt,
 -      [  --enable-cobalt         use cobalt-style sysv configuration ],
 -      if test "$enableval" = "yes"; then
 -              sysv_style=cobalt
 -      fi
 -      AC_MSG_RESULT([enabling cobalt-style sysv support])
 -)
 +dnl Check for crypt
 +AC_NETATALK_CRYPT
  
 -AC_ARG_ENABLE(netbsd,
 -      [  --enable-netbsd         use NetBSD-style rc.d configuration ],
 -      if test "x$enableval" = "xyes"; then
 -              sysv_style=netbsd
 -      fi
 -      AC_MSG_RESULT([enabling NetBSD-style rc.d support])
 -)
 +dnl Check for building PGP UAM module
 +AC_NETATALK_PGP_UAM
  
 -AC_ARG_ENABLE(debian,
 -      [  --enable-debian         use debian-style sysv configuration ],[
 -      if test "$enableval" = "yes"; then
 -              sysv_style=debian
 -      fi
 -      AC_MSG_RESULT([enabling debian-style sysv support])
 -      ]
 -)
 +dnl Check for building Kerberos V UAM module
 +AC_NETATALK_KRB5_UAM
  
 -dnl ----- timelord compilation (disabled by default)
 -AC_MSG_CHECKING([whether timelord should be compiled])
 -compile_timelord=no
 -AC_ARG_ENABLE(timelord,
 -      [  --enable-timelord       enable compilation of timelord server],
 -      [compile_timelord="$enableval"],
 -      [compile_timelord="no"]
 -)
 -AC_MSG_RESULT([$compile_timelord])
 -
 -dnl ----- a2boot compilation (disabled by default)
 -AC_MSG_CHECKING([whether a2boot should be compiled])
 -compile_a2boot=no
 -AC_ARG_ENABLE(a2boot,
 -      [  --enable-a2boot         enable compilation of Apple2 boot server],
 -      [compile_a2boot="$enableval"],
 -      [compile_a2boot="no"]
 -)
 -AC_MSG_RESULT([$compile_a2boot])
 +dnl Check for overwrite the config files or not
 +AC_NETATALK_OVERWRITE_CONFIG
  
 -AC_ARG_WITH(uams-path,
 -      [  --with-uams-path=PATH   path to UAMs [[PKGCONF/uams]]],[
 -              uams_path="$withval"
 -      ],[
 -              uams_path="${PKGCONFDIR}/uams"
 -      ]
 -)
 +dnl Check for LDAP support, for client-side ACL visibility
 +AC_NETATALK_LDAP
  
 -NETATALK_AC_CUPS
 +dnl Check for ACL support
 +AC_NETATALK_ACL
  
 -dnl check if we can use attribute unused (gcc only) from ethereal
 -AC_MSG_CHECKING(to see if we can add '__attribute__((unused))' to CFLAGS)
 -if test x$GCC != x ; then
 -  CFLAGS="-D_U_=\"__attribute__((unused))\" $CFLAGS"
 -  AC_MSG_RESULT(yes)
 -else
 -  CFLAGS="-D_U_=\"\" $CFLAGS"
 -  AC_MSG_RESULT(no)
 -fi
 +dnl Check for Extended Attributes support
 +AC_NETATALK_EXTENDED_ATTRIBUTES
 +
 +dnl Check for libsmbsharemodes from Samba for Samba/Netatalk access/deny/share modes interop
 +AC_NETATALK_SMB_SHAREMODES
  
  dnl --------------------------------------------------------------------------
  dnl FHS stuff has to be done last because it overrides other defaults
@@@ -273,17 -505,12 +278,17 @@@ dnl -----------------------------------
  dnl post-FHS substitutions, etc
  dnl --------------------------------------------------------------------------
  
 -dnl ***** UAMS_PATH
 -dnl AC_DEFINE_UNQUOTED(UAMS_PATH, "${uams_path}",
 -dnl   [path to UAMs [default=PKGCONF/uams]])
  UAMS_PATH="${uams_path}"
  AC_SUBST(UAMS_PATH)
  
 +
 +dnl --------------------------------------------------------------------------
 +dnl OS specific configuration comes in here:
 +dnl --------------------------------------------------------------------------
 +
 +AC_NETATALK_OS_SPECIFIC
 +
 +
  dnl --------------------------------------------------------------------------
  dnl drop in includes for top level directory structures here...
  dnl --------------------------------------------------------------------------
  dnl Note: $(top_srcdir)/include should be added before all other includes
  dnl       so that includes from that directory a preferred to includes from
  dnl       /usr/include or similar places.
 -LIBS="$LIBS -L\$(top_srcdir)/libatalk"
 -CFLAGS="-I\$(top_srcdir)/include $CFLAGS -I\$(top_srcdir)/sys"
 +LIBS="$LIBS -L\$(top_srcdir)/libatalk -L\$(top_srcdir)/libevent"
 +CFLAGS="-I\$(top_srcdir)/include -I\$(top_srcdir)/sys -I\$(top_srcdir)/libevent/include $CFLAGS"
  
  AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW)
  
 +
  dnl --------------------------------------------------------------------------
 -dnl specific configuration comes in here:
 +dnl Last minute substitutions
  dnl --------------------------------------------------------------------------
 -
 -dnl ac_cv_target_os is now host_os, ac_cv_target_cpu is now host_cpu
 -
 -dnl --------------------- determine operating system from "target"
 -case "$host_os" in
 -      *aix*)                          this_os=aix ;;
 -      *freebsd*)                      this_os=freebsd ;;
 -      *hpux11*)                       this_os=hpux11 ;;
 -      *irix*)                         this_os=irix ;;
 -      *linux*)                        this_os=linux ;;
 -      *osx*)                          this_os=macosx ;;
 -      *darwin*)                       this_os=macosx ;;
 -      *netbsd*)                       this_os=netbsd ;;
 -      *openbsd*)                      this_os=openbsd ;;
 -      *osf*)                          this_os=tru64 ;;
 -      *solaris*)                      this_os=solaris ;;
 -esac
 -
 -case "$host_cpu" in
 -      i386|i486|i586|i686|k7)         this_cpu=x86 ;;
 -      alpha)                                          this_cpu=alpha ;;
 -      mips)                                           this_cpu=mips ;;
 -      powerpc|ppc)                            this_cpu=ppc ;;
 -esac
 -
 -dnl --------------------- GNU source
 -case "$this_os" in
 -      linux)  AC_DEFINE(_GNU_SOURCE, 1, [Whether to use GNU libc extensions])
 -        ;;
 -esac
 -
 -dnl --------------------- operating system specific flags (port from sys/*)
 -
 -dnl ----- AIX specific -----
 -if test x"$this_os" = "xaix"; then
 -      AC_MSG_RESULT([ * AIX specific configuration])
 -      AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available])
 -
 -      dnl This is probably a lie; AIX 4.3 supports a 64-bit long
 -      dnl compilation environment.  It's enough to get things defined
 -      dnl right in endian.h provided that long long is supported, though.
 -      AC_DEFINE(HAVE_32BIT_LONGS, 1, [Define if the data type long has 32 bit])
 -fi
 -
 -dnl ----- FreeBSD specific -----
 -if test x"$this_os" = "xfreebsd"; then 
 -      AC_MSG_RESULT([ * FreeBSD specific configuration])
 -      AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
 -      AC_DEFINE(FREEBSD, 1, [Define if OS is FreeBSD])
 -      AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics])
 -    AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW)
 -fi
 -
 -dnl ----- HP-UX 11 specific -----
 -if test x"$this_os" = "xhpux11"; then
 -      AC_MSG_RESULT([ * HP-UX 11 specific configuration])
 -
 -      AC_DEFINE(_ISOC9X_SOURCE, 1, [Compatibility macro])
 -      AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available])
 -fi
 -
 -dnl ----- IRIX specific -----
 -if test x"$this_os" = "xirix"; then
 -      AC_MSG_RESULT([ * IRIX specific configuration])
 -
 -      AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available])
 -fi
 -
 -dnl ----- Linux specific -----
 -if test x"$this_os" = "xlinux"; then 
 -      AC_MSG_RESULT([ * Linux specific configuration])
 -      
 -      dnl ----- kernel 2.6 changed struct at_addr to atalk_addr
 -      AC_MSG_CHECKING([for struct atalk_addr])
 -dnl   AC_COMPILE_IFELSE([
 -      AC_TRY_COMPILE([
 -#include <sys/socket.h>
 -#include <asm/types.h>
 -#include <linux/atalk.h>
 -
 -      struct atalk_addr foo;
 -],
 -[ ], [
 -              ac_have_atalk_addr=yes
 -              AC_MSG_RESULT([yes])
 -      ], [
 -              AC_MSG_RESULT([no])
 -      ])
 -
 -if test "x$ac_have_atalk_addr" = "xyes"; then
 -      AC_DEFINE(HAVE_ATALK_ADDR, 1, [set if struct at_addr is called atalk_addr])
 -fi
 -
 -      dnl ----- check if we need the quotactl wrapper
 -#     AC_CHECK_HEADERS(sys/quota.h linux/quota.h)
 -#     AC_CHECK_FUNC(quotactl,,
 -#             AC_DEFINE(NEED_QUOTACTL_WRAPPER, 1, [Define if the quotactl wrapper is needed])
 -#             AC_MSG_RESULT([enabling quotactl wrapper])
 -#     )
 -
 -        # For quotas on Linux XFS filesystems
 -        
 -        # For linux > 2.5.56
 -        AC_CHECK_HEADERS(linux/dqblk_xfs.h,,
 -              [AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h)
 -              AC_CHECK_HEADERS(xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h)]
 -      )
 -
 -
 -      dnl ----- as far as I can tell, dbtob always does the wrong thing
 -      dnl ----- on every single version of linux I've ever played with.
 -      dnl ----- see etc/afpd/quota.c
 -      AC_DEFINE(HAVE_BROKEN_DBTOB, 1, [Define if dbtob is broken])
 -
 -      netatalk_cv_linux_sendfile=yes
 -      AC_MSG_CHECKING([use sendfile syscall])
 -        AC_ARG_ENABLE(sendfile,
 -          [  --disable-sendfile       disable linux sendfile syscall],[
 -              if test x"$enableval" = x"no"; then
 -                      netatalk_cv_linux_sendfile=no
 -                      AC_MSG_RESULT([no])
 -              else
 -                      AC_MSG_RESULT([yes])
 -
 -              fi
 -          ],[
 -              AC_MSG_RESULT([yes])
 -      ]
 -
 -       )
 -
 -      if test x"$netatalk_cv_linux_sendfile" = "xyes"; then 
 -          AC_CACHE_CHECK([for linux sendfile support],netatalk_cv_HAVE_SENDFILE,[
 -          AC_TRY_LINK([#include <sys/sendfile.h>],
 -[\
 -int tofd, fromfd;
 -off_t offset;
 -size_t total;
 -ssize_t nwritten = sendfile(tofd, fromfd, &offset, total);
 -],
 -netatalk_cv_HAVE_SENDFILE=yes,netatalk_cv_HAVE_SENDFILE=no)])
 -
 -# Try and cope with broken Linux sendfile....
 -          AC_CACHE_CHECK([for broken linux sendfile support],netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE,[
 -          AC_TRY_LINK([\
 -#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
 -#undef _FILE_OFFSET_BITS
 -#endif
 -#include <sys/sendfile.h>],
 -[\
 -int tofd, fromfd;
 -off_t offset;
 -size_t total;
 -ssize_t nwritten = sendfile(tofd, fromfd, &offset, total);
 -],
 -netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE=yes,netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE=no,netatalk_cv_HAVE_BROKEN_SENDFILE=cross)])
 -
 -          if test x"$netatalk_cv_HAVE_SENDFILE" = x"yes"; then
 -              AC_DEFINE(HAVE_SENDFILE,1,[Whether sendfile() is available])
 -              AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available])
 -              AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile() should be used])
 -          elif test x"$netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE" = x"yes"; then
 -              AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available])
 -              AC_DEFINE(LINUX_BROKEN_SENDFILE_API,1,[Whether (linux) sendfile() is broken])
 -              AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile should be used])
 -          else
 -              netatalk_cv_linux_sendfile=no
 -              AC_MSG_RESULT(no);
 -          fi
 -      fi
 -
 -      dnl ----- Linux/alpha specific -----
 -      if test x"$this_cpu" = "xalpha"; then 
 -              AC_MSG_RESULT([enabling gcc memcpy bug workaround])
 -              AC_DEFINE(HAVE_GCC_MEMCPY_BUG, 1, [Define if memcpy is buggy])
 -      fi
 -      need_dash_r=no
 -
 -
 -fi
 -
 -dnl ----- Mac OSX specific -----
 -if test x"$this_os" = "xmacosx"; then 
 -      AC_MSG_RESULT([ * Mac OSX specific configuration])
 -      AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
 -      AC_DEFINE(HAVE_2ARG_DBTOB, 1, [Define if dbtob takes two arguments])
 -      dnl AC_DEFINE(NO_DLFCN_H)
 -      AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
 -      AC_DEFINE(NO_QUOTA_SUPPORT, 1, [Define if Quota support should be disabled])
 -      AC_DEFINE(MACOSX_SERVER, 1, [Define if compiling for MacOS X Server])
 -fi
 -
 -dnl ----- NetBSD specific -----
 -if test x"$this_os" = "xnetbsd"; then 
 -      AC_MSG_RESULT([ * NetBSD specific configuration])
 -      AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
 -      AC_DEFINE(NETBSD, 1, [Define if OS is NetBSD])
 -    AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EFTYPE, errno returned by open with O_NOFOLLOW)
 -
 -      CFLAGS="-I\$(top_srcdir)/sys/netbsd $CFLAGS"
 -      need_dash_r=yes 
 -
 -      dnl ----- NetBSD does not have crypt.h, uses unistd.h -----
 -      AC_DEFINE(UAM_DHX, 1, [Define if the DHX UAM modules should be compiled])
 -fi
 -
 -dnl ----- OpenBSD specific -----
 -if test x"$this_os" = "xopenbsd"; then 
 -      AC_MSG_RESULT([ * OpenBSD specific configuration])
 -      dnl ----- OpenBSD does not have crypt.h, uses unistd.h -----
 -      AC_DEFINE(UAM_DHX, 1, [Define if the DHX UAM modules should be compiled])
 -fi
 -
 -dnl ----- Solaris specific -----
 -if test x"$this_os" = "xsolaris"; then 
 -      AC_MSG_RESULT([ * Solaris specific configuration])
 -      AC_DEFINE(__svr4__, 1, [Solaris compatibility macro])
 -      AC_DEFINE(_ISOC9X_SOURCE, 1, [Compatibility macro])
 -      AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available])
 -      AC_DEFINE(SOLARIS, 1, [Solaris compatibility macro])
 -      CFLAGS="-I\$(top_srcdir)/sys/generic $CFLAGS"
 -      need_dash_r=yes
 -      sysv_style=solaris
 -
 -      solaris_module=no
 -      AC_MSG_CHECKING([if we can build Solaris kernel module])
 -      if test -x /usr/ccs/bin/ld && test x"$netatalk_cv_ddp_enabled" = x"yes" ; then
 -              solaris_module=yes
 -      fi
 -      AC_MSG_RESULT([$solaris_module])
 -
 -      COMPILE_64BIT_KMODULE=no
 -      KCFLAGS=""
 -      KLDFLAGS=""
 -      COMPILE_KERNEL_GCC=no
 -
 -      if test "$solaris_module" = "yes"; then
 -         dnl Solaris kernel module stuff
 -           AC_MSG_CHECKING([if we have to build a 64bit kernel module])
 -
 -         # check for isainfo, if not found it has to be a 32 bit kernel (<=2.6)       
 -         if test -x /usr/bin/isainfo; then
 -              # check for 64 bit platform
 -              if isainfo -kv | grep '^64-bit'; then
 -                      COMPILE_64BIT_KMODULE=yes
 -              fi
 -         fi
 -
 -         AC_MSG_RESULT([$COMPILE_64BIT_KMODULE])
 -
 -         if test "${GCC}" = yes; then
 -              COMPILE_KERNEL_GCC=yes
 -              if test "$COMPILE_64BIT_KMODULE" = yes; then
 -              
 -                        AC_MSG_CHECKING([if we can build a 64bit kernel module])
 -                      
 -                        case `$CC --version 2>/dev/null` in
 -                      [[12]].* | 3.0.*)
 -                              COMPILE_64BIT_KMODULE=no
 -                              COMPILE_KERNEL_GCC=no   
 -                              solaris_module=no;;
 -                      *)
 -                              # use for 64 bit
 -                              KCFLAGS="-m64"
 -                              #KLDFLAGS="-melf64_sparc"
 -                              KLDFLAGS="-64";;
 -                      esac    
 -                      
 -                      AC_MSG_RESULT([$COMPILE_64BIT_KMODULE])
 -                      
 -              else
 -                      KCFLAGS=""
 -                      KLDFLAGS=""
 -              fi
 -              KCFLAGS="$KCFLAGS -D_KERNEL -Wall -Wstrict-prototypes"
 -           else
 -              if test "$COMPILE_64BIT_KMODULE" = yes; then
 -                # use Sun CC (for a 64-bit kernel, uncomment " -xarch=v9 -xregs=no%appl ")
 -                      KCFLAGS="-xarch=v9 -xregs=no%appl"
 -                      KLDFLAGS="-64"
 -              else
 -                      KCFLAGS=""
 -                      KLDFLAGS=""
 -              fi
 -              KCFLAGS="-D_KERNEL $KCFLAGS -mno-app-regs -munaligned-doubles -fpcc-struct-return"
 -         fi
 -
 -           AC_CACHE_CHECK([for timeout_id_t],netatalk_cv_HAVE_TIMEOUT_ID_T,[
 -           AC_TRY_LINK([\
 -#include <sys/stream.h>
 -#include <sys/ddi.h>],
 -[\
 -timeout_id_t dummy;
 -],
 -netatalk_cv_HAVE_TIMEOUT_ID_T=yes,netatalk_cv_HAVE_TIMEOUT_ID_T=no,netatalk_cv_HAVE_TIMEOUT_ID_T=cross)])
 -
 -         AC_DEFINE(HAVE_TIMEOUT_ID_T, test x"$netatalk_cv_HAVE_TIMEOUT_ID" = x"yes", [define for timeout_id_t])
 -      fi
 -
 -      AC_SUBST(COMPILE_KERNEL_GCC)
 -      AC_SUBST(COMPILE_64BIT_KMODULE)
 -      AC_SUBST(KCFLAGS)
 -      AC_SUBST(KLDFLAGS)
 -fi
 -
 -dnl ----- Tru64 specific -----
 -if test x"$this_os" = "xtru64"; then 
 -      AC_MSG_RESULT([ * Tru64 specific configuration])
 -      AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
 -      AC_DEFINE(HAVE_64BIT_LONGS, 1, [Define if the data type long has 64 bit])
 -      dnl AC_DEFINE(USE_MOUNT_H)
 -      AC_DEFINE(USE_OLD_RQUOTA, 1, [Define to use old rquota])
 -      dnl AC_DEFINE(USE_UFS_QUOTA_H)
 -      AC_DEFINE(TRU64, 1, [Define on Tru64 platforms])
 -      AC_DEFINE(_OSF_SOURCE, 1, [Define if the *passwd UAMs should be used])
 -      AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Define for Berkeley DB 4])
 -      AC_CHECK_LIB(security,set_auth_parameters)
 -      CFLAGS="-I\$(top_srcdir)/sys/tru64 $CFLAGS"
 -      need_dash_r=no
 -      sysv_style=tru64
 -fi
 -
 -dnl -- check for libgcrypt, if found enables DHX UAM
 -AM_PATH_LIBGCRYPT([1:1.2.3],[neta_cv_compile_dhx2=yes
 -                      neta_cv_have_libgcrypt=yes
 -                      AC_MSG_NOTICE([Enabling DHX2 UAM])
 -                      AC_DEFINE(HAVE_LIBGCRYPT, 1, [Define if the DHX2 modules should be built with libgcrypt])
 -                      AC_DEFINE(UAM_DHX2, 1, [Define if the DHX2 UAM modules should be compiled])
 -                      ])
 -
 -dnl -- look for openssl, if found enables DHX UAM and Randnum UAM
 -AC_PATH_SSL
 -
 -dnl Check for Berkeley DB library
 -if test "x$bdb_required" = "xyes"; then
 -      AC_PATH_BDB(, [
 -              AC_MSG_RESULT([])
 -              AC_MSG_RESULT([Make sure you have the required Berkeley DB libraries AND headers installed.])
 -              AC_MSG_RESULT([You can download the latest version from http://www.sleepycat.com.])
 -              AC_MSG_RESULT([If you have installed BDB in a non standard location use the])
 -              AC_MSG_RESULT([--with-bdb=/path/to/bdb configure option and make sure])
 -              AC_MSG_RESULT([your linker is configured to check for libraries there.])
 -              AC_MSG_ERROR([Berkeley DB library required but not found!])
 -      ])
 -fi
 -
 -dnl -- check for crypt
 -AC_CRYPT
 -
 -dnl --------------------- check for building PGP UAM module
 -
 -AC_MSG_CHECKING([whether the PGP UAM should be build])
 -AC_ARG_ENABLE(pgp-uam,
 -      [  --enable-pgp-uam        enable build of PGP UAM module],[
 -      if test "$enableval" = "yes"; then 
 -              if test "x$neta_cv_have_openssl" = "xyes"; then 
 -                      AC_DEFINE(UAM_PGP, 1, [Define if the PGP UAM module should be compiled])
 -                      compile_pgp=yes
 -                      AC_MSG_RESULT([yes])
 -              else
 -                      AC_MSG_RESULT([no])
 -              fi
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -      ]
 -)
 -
 -dnl --------------------- check for building Kerberos v4 UAM module
 -
 -AC_MSG_CHECKING([whether the Kerberos IV UAM should be build])
 -AC_ARG_ENABLE(krb4-uam,
 -      [  --enable-krb4-uam       enable build of Kerberos v4 UAM module],[
 -      if test "$enableval" = "yes"; then
 -              AC_DEFINE(UAM_KRB4, 1, [Define if the Kerberos 4 UAM module should be compiled])
 -              compile_kerberos=yes
 -              AC_MSG_RESULT([yes])
 -      else
 -              AC_MSG_RESULT([no])
 -      fi
 -      ],[
 -              AC_MSG_RESULT([no])
 -      ]
 -)
 -
 -dnl --------------------- check for building Kerberos V UAM module
 -
 -netatalk_cv_build_krb5_uam=no
 -AC_ARG_ENABLE(krbV-uam,
 -      [  --enable-krbV-uam       enable build of Kerberos V UAM module],
 -      [
 -              if test x"$enableval" = x"yes"; then
 -                      NETATALK_GSSAPI_CHECK([
 -                              netatalk_cv_build_krb5_uam=yes
 -                      ],[
 -                              AC_MSG_ERROR([need GSSAPI to build Kerberos V UAM])
 -                      ])
 -              fi
 -      ]
 -      
 -)
 -
 -AC_MSG_CHECKING([whether Kerberos V UAM should be build])
 -if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then
 -      AC_MSG_RESULT([yes])
 -else
 -      AC_MSG_RESULT([no])
 -fi
 -AM_CONDITIONAL(USE_GSSAPI, test x"$netatalk_cv_build_krb5_uam" = x"yes")
 -
 -dnl --------------------- overwrite the config files . . . or not.
 -
 -AC_MSG_CHECKING([whether configuration files should be overwritten])
 -AC_ARG_ENABLE(overwrite,
 -      [  --enable-overwrite      overwrite configuration files during installation],
 -      [OVERWRITE_CONFIG="${enable_overwrite}"],
 -      [OVERWRITE_CONFIG="no"]
 -)
 -AC_MSG_RESULT([$OVERWRITE_CONFIG])
 -
 -dnl --------------------- check for LDAP support, for client-side ACL visibility
 -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)
 -
 -if test x"$with_ldap" != x"no" ; then
 -      AC_CHECK_HEADER([ldap.h], with_ldap=yes,
 -        [ if test x"$with_ldap" = x"yes" ; then
 -            AC_MSG_ERROR([Missing LDAP headers])
 -        fi
 -              with_ldap=no
 -        ])
 -      AC_CHECK_LIB(ldap, ldap_init, with_ldap=yes,
 -        [ if test x"$with_ldap" = x"yes" ; then
 -            AC_MSG_ERROR([Missing LDAP library])
 -        fi
 -              with_ldap=no
 -        ])
 -fi
 -
 -if test x"$with_ldap" = x"yes"; then
 -      AC_DEFINE(HAVE_LDAP,1,[Whether LDAP is available])
 -fi
 -
 -dnl --------------------- check for ACL support
 -AC_MSG_CHECKING(whether to support ACLs)
 -AC_ARG_WITH(acls,
 -    [AS_HELP_STRING([--with-acls],
 -        [Include ACL support (default=auto)])],
 -    [ case "$withval" in
 -      yes|no)
 -          with_acl_support="$withval"
 -                ;;
 -      *)
 -          with_acl_support=auto
 -          ;;
 -      esac ],
 -    [with_acl_support=auto])
 -AC_MSG_RESULT($with_acl_support)
 -
 -if test x"$with_acl_support" = x"no"; then
 -      AC_MSG_RESULT(Disabling ACL support)
 -      AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support should be built in])
 -else
 -    with_acl_support=yes
 -fi
 -
 -if test x"$with_acl_support" = x"yes" ; then
 -      AC_MSG_NOTICE(checking whether ACL support is available:)
 -      case "$host_os" in
 -      *sysv5*)
 -              AC_MSG_NOTICE(Using UnixWare ACLs)
 -              AC_DEFINE(HAVE_UNIXWARE_ACLS,1,[Whether UnixWare ACLs are available])
 -              ;;
 -      *solaris*)
 -              AC_MSG_NOTICE(Using solaris ACLs)
 -              AC_DEFINE(HAVE_SOLARIS_ACLS,1,[Whether solaris ACLs are available])
 -              ACL_LIBS="$ACL_LIBS -lsec"
 -              ;;
 -      *hpux*)
 -              AC_MSG_NOTICE(Using HPUX ACLs)
 -              AC_DEFINE(HAVE_HPUX_ACLS,1,[Whether HPUX ACLs are available])
 -              ;;
 -      *irix*)
 -              AC_MSG_NOTICE(Using IRIX ACLs)
 -              AC_DEFINE(HAVE_IRIX_ACLS,1,[Whether IRIX ACLs are available])
 -              ;;
 -      *aix*)
 -              AC_MSG_NOTICE(Using AIX ACLs)
 -              AC_DEFINE(HAVE_AIX_ACLS,1,[Whether AIX ACLs are available])
 -              ;;
 -      *osf*)
 -              AC_MSG_NOTICE(Using Tru64 ACLs)
 -              AC_DEFINE(HAVE_TRU64_ACLS,1,[Whether Tru64 ACLs are available])
 -              ACL_LIBS="$ACL_LIBS -lpacl"
 -              ;;
 -      *darwin*)
 -              AC_MSG_NOTICE(ACLs on Darwin currently not supported)
 -              AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available])
 -              ;;
 -      *)
 -              AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"])
 -              case "$host_os" in
 -              *linux*)
 -                      AC_CHECK_LIB(attr,getxattr,[ACL_LIBS="$ACL_LIBS -lattr"])
 -                      ;;
 -              esac
 -              AC_CACHE_CHECK([for POSIX ACL support],netatalk_cv_HAVE_POSIX_ACLS,[
 -                      acl_LIBS=$LIBS
 -                      LIBS="$LIBS $ACL_LIBS"
 -                      AC_TRY_LINK([
 -                              #include <sys/types.h>
 -                              #include <sys/acl.h>
 -                      ],[
 -                              acl_t acl;
 -                              int entry_id;
 -                              acl_entry_t *entry_p;
 -                              return acl_get_entry(acl, entry_id, entry_p);
 -                      ],
 -                      [netatalk_cv_HAVE_POSIX_ACLS=yes],
 -                      [netatalk_cv_HAVE_POSIX_ACLS=no
 -                with_acl_support=no])
 -                      LIBS=$acl_LIBS
 -              ])
 -              if test x"$netatalk_cv_HAVE_POSIX_ACLS" = x"yes"; then
 -                      AC_MSG_NOTICE(Using POSIX ACLs)
 -                      AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available])
 -                      AC_CACHE_CHECK([for acl_get_perm_np],netatalk_cv_HAVE_ACL_GET_PERM_NP,[
 -                              acl_LIBS=$LIBS
 -                              LIBS="$LIBS $ACL_LIBS"
 -                              AC_TRY_LINK([
 -                                      #include <sys/types.h>
 -                                      #include <sys/acl.h>
 -                              ],[
 -                                      acl_permset_t permset_d;
 -                                      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])
 -                              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
 -              else
 -                      AC_MSG_NOTICE(ACL support is not avaliable)
 -                      AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available])
 -              fi
 -              ;;
 -    esac
 -fi
 -
 -if test x"$with_acl_support" = x"yes" ; then
 -    AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available])
 -    AC_SUBST(ACL_LIBS)
 -fi
 -
 -dnl --------------------- check for Extended Attributes support
 -neta_cv_eas="ad"
 -neta_cv_eas_sys_found=no
 -neta_cv_eas_sys_not_found=no
 -
 -AC_CHECK_HEADERS(sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h sys/ea.h)
 -
 -case "$this_os" in
 -
 -  *osf*)
 -      AC_SEARCH_LIBS(getproplist, [proplist])
 -      AC_CHECK_FUNCS([getproplist fgetproplist setproplist fsetproplist],
 -                   [neta_cv_eas_sys_found=yes],
 -                   [neta_cv_eas_sys_not_found=yes])
 -      AC_CHECK_FUNCS([delproplist fdelproplist add_proplist_entry get_proplist_entry],,
 -                   [neta_cv_eas_sys_not_found=yes])
 -      AC_CHECK_FUNCS([sizeof_proplist_entry],,
 -                   [neta_cv_eas_sys_not_found=yes])
 -  ;;
 -
 -  *solaris*)
 -      AC_CHECK_FUNCS([attropen],
 -                   [neta_cv_eas_sys_found=yes],
 -                   [neta_cv_eas_sys_not_found=yes])
 -  ;;
 -
 -  'freebsd')
 -    AC_CHECK_FUNCS([extattr_delete_fd extattr_delete_file extattr_delete_link],
 -                   [neta_cv_eas_sys_found=yes],
 -                   [neta_cv_eas_sys_not_found=yes])
 -    AC_CHECK_FUNCS([extattr_get_fd extattr_get_file extattr_get_link],,
 -                   [neta_cv_eas_sys_not_found=yes])
 -    AC_CHECK_FUNCS([extattr_list_fd extattr_list_file extattr_list_link],,
 -                   [neta_cv_eas_sys_not_found=yes])
 -    AC_CHECK_FUNCS([extattr_set_fd extattr_set_file extattr_set_link],,
 -                   [neta_cv_eas_sys_not_found=yes])
 -  ;;
 -
 -  *freebsd4* | *dragonfly* )
 -    AC_DEFINE(BROKEN_EXTATTR, 1, [Does extattr API work])
 -  ;;
 -
 -  *)
 -      AC_SEARCH_LIBS(getxattr, [attr])
 -
 -    if test "x$neta_cv_eas_sys_found" != "xyes" ; then
 -       AC_CHECK_FUNCS([getxattr lgetxattr fgetxattr listxattr llistxattr],
 -                      [neta_cv_eas_sys_found=yes],
 -                      [neta_cv_eas_sys_not_found=yes])
 -         AC_CHECK_FUNCS([flistxattr removexattr lremovexattr fremovexattr],,
 -                      [neta_cv_eas_sys_not_found=yes])
 -         AC_CHECK_FUNCS([setxattr lsetxattr fsetxattr],,
 -                      [neta_cv_eas_sys_not_found=yes])
 -    fi
 -
 -    if test "x$neta_cv_eas_sys_found" != "xyes" ; then
 -         AC_CHECK_FUNCS([getea fgetea lgetea listea flistea llistea],
 -                      [neta_cv_eas_sys_found=yes],
 -                      [neta_cv_eas_sys_not_found=yes])
 -         AC_CHECK_FUNCS([removeea fremoveea lremoveea setea fsetea lsetea],,
 -                      [neta_cv_eas_sys_not_found=yes])
 -    fi
 -
 -    if test "x$neta_cv_eas_sys_found" != "xyes" ; then
 -         AC_CHECK_FUNCS([attr_get attr_list attr_set attr_remove],,
 -                      [neta_cv_eas_sys_not_found=yes])
 -       AC_CHECK_FUNCS([attr_getf attr_listf attr_setf attr_removef],,
 -                      [neta_cv_eas_sys_not_found=yes])
 -    fi
 -  ;;
 -esac
 -
 -# Do xattr functions take additional options like on Darwin?
 -if test x"$ac_cv_func_getxattr" = x"yes" ; then
 -      AC_CACHE_CHECK([whether xattr interface takes additional options], smb_attr_cv_xattr_add_opt, [
 -              old_LIBS=$LIBS
 -              LIBS="$LIBS $ACL_LIBS"
 -              AC_TRY_COMPILE([
 -                      #include <sys/types.h>
 -                      #if HAVE_ATTR_XATTR_H
 -                      #include <attr/xattr.h>
 -                      #elif HAVE_SYS_XATTR_H
 -                      #include <sys/xattr.h>
 -                      #endif
 -              ],[
 -                      getxattr(0, 0, 0, 0, 0, 0);
 -              ],
 -              [smb_attr_cv_xattr_add_opt=yes],
 -              [smb_attr_cv_xattr_add_opt=no;LIBS=$old_LIBS])
 -      ])
 -      if test x"$smb_attr_cv_xattr_add_opt" = x"yes"; then
 -              AC_DEFINE(XATTR_ADD_OPT, 1, [xattr functions have additional options])
 -      fi
 -fi
 -
 -if test "x$neta_cv_eas_sys_found" = "xyes" ; then
 -   if test "x$neta_cv_eas_sys_not_found" != "xyes" ; then
 -      neta_cv_eas="$neta_cv_eas | sys"
 -   fi
 -fi
 -AC_DEFINE_UNQUOTED(EA_MODULES,["$neta_cv_eas"],[Available Extended Attributes modules])
 -
 -dnl --------------------- Check if realpath() takes NULL
 -AC_CACHE_CHECK([if the realpath function allows a NULL argument],
 -    neta_cv_REALPATH_TAKES_NULL, [
 -        AC_TRY_RUN([
 -            #include <stdio.h>
 -            #include <limits.h>
 -            #include <signal.h>
 -
 -            void exit_on_core(int ignored) {
 -                 exit(1);
 -            }
 -
 -            main() {
 -                char *newpath;
 -                signal(SIGSEGV, exit_on_core);
 -                newpath = realpath("/tmp", NULL);
 -                exit((newpath != NULL) ? 0 : 1);
 -            }],
 -            neta_cv_REALPATH_TAKES_NULL=yes,
 -            neta_cv_REALPATH_TAKES_NULL=no,
 -            neta_cv_REALPATH_TAKES_NULL=cross
 -        )
 -    ]
 -)
 -
 -if test x"$neta_cv_REALPATH_TAKES_NULL" = x"yes"; then
 -    AC_DEFINE(REALPATH_TAKES_NULL,1,[Whether the realpath function allows NULL])
 -fi
 -
 -dnl --------------------- Netatalk Webmin
 -NETATALK_WEBMIN
 -
 -dnl --------------------- last minute substitutions
 -
  AC_SUBST(LIBS)
  AC_SUBST(CFLAGS)
 -AC_SUBST(OVERWRITE_CONFIG)
  
  AM_CONDITIONAL(SOLARIS_MODULE, test x$solaris_module = xyes)
 -AM_CONDITIONAL(COMPILE_TIMELORD, test x$compile_timelord = xyes)
 -AM_CONDITIONAL(COMPILE_A2BOOT, test x$compile_a2boot = 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")
@@@ -311,11 -1244,13 +316,11 @@@ AM_CONDITIONAL(HAVE_LDAP, test x"$with_
  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)
 -AM_CONDITIONAL(USE_KERBEROS, test x$compile_kerberos = xyes)
  AM_CONDITIONAL(USE_PAM_SO, test x$use_pam_so = xyes)
  AM_CONDITIONAL(USE_PAM, test x$netatalk_cv_install_pam = xyes)
  AM_CONDITIONAL(BUILD_PAM, test x$compile_pam = xyes)
  AM_CONDITIONAL(USE_PGP, test x$compile_pgp = xyes)
  AM_CONDITIONAL(DEFAULT_HOOK, test x$neta_cv_have_libgcrypt != xyes && test x$neta_cv_have_openssl != xyes)
 -AM_CONDITIONAL(USE_COBALT, test x$sysv_style = xcobalt)
  AM_CONDITIONAL(USE_NETBSD, test x$sysv_style = xnetbsd)
  AM_CONDITIONAL(USE_REDHAT, test x$sysv_style = xredhat)
  AM_CONDITIONAL(USE_SUSE, test x$sysv_style = xsuse)
@@@ -326,27 -1261,38 +331,28 @@@ AM_CONDITIONAL(USE_GENTOO, test x$sysv_
  AM_CONDITIONAL(USE_DEBIAN, test x$sysv_style = xdebian)
  AM_CONDITIONAL(USE_UNDEF, test x$sysv_style = x)
  AM_CONDITIONAL(USE_BDB, test x$bdb_required = xyes)
 -AM_CONDITIONAL(USE_APPLETALK, test x$netatalk_cv_ddp_enabled = xyes)
+ AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes")
  
  dnl --------------------- generate files
  
  AC_OUTPUT([Makefile
        bin/Makefile
        bin/ad/Makefile
 -      bin/adv1tov2/Makefile
 -      bin/aecho/Makefile
        bin/afppasswd/Makefile
        bin/cnid/Makefile
        bin/cnid/cnid2_create
 -      bin/getzones/Makefile
        bin/megatron/Makefile
      bin/misc/Makefile
 -      bin/nbp/Makefile
 -      bin/pap/Makefile
 -      bin/psorder/Makefile
        bin/uniconv/Makefile
        config/Makefile
      config/pam/Makefile
        contrib/Makefile
        contrib/macusers/Makefile
        contrib/macusers/macusers
 -      contrib/printing/Makefile
        contrib/shell_utils/Makefile
        contrib/shell_utils/afpd-mtab.pl
      contrib/shell_utils/apple_dump
        contrib/shell_utils/asip-status.pl
 -      contrib/timelord/Makefile
 -      contrib/a2boot/Makefile
        distrib/Makefile
        distrib/config/Makefile
        distrib/config/netatalk-config
        doc/Makefile
        etc/Makefile
        etc/afpd/Makefile
 -      etc/atalkd/Makefile
        etc/cnid_dbd/Makefile
 +      etc/netalockd/Makefile
        etc/uams/Makefile
 -      etc/uams/uams_krb4/Makefile
 -      etc/papd/Makefile
 -      etc/psf/Makefile
        include/Makefile
        include/atalk/Makefile
        libatalk/Makefile
        libatalk/acl/Makefile
        libatalk/adouble/Makefile
 -      libatalk/asp/Makefile
 -      libatalk/atp/Makefile
        libatalk/bstring/Makefile
        libatalk/cnid/Makefile
        libatalk/cnid/cdb/Makefile
        libatalk/cnid/tdb/Makefile
        libatalk/compat/Makefile
        libatalk/dsi/Makefile
 -      libatalk/nbp/Makefile
 -      libatalk/netddp/Makefile
 -      libatalk/util/Makefile
 +      libatalk/locking/Makefile
 +      libatalk/rpc/Makefile
 +      libatalk/talloc/Makefile
 +      libatalk/tevent/Makefile
 +      libatalk/tsocket/Makefile
        libatalk/tdb/Makefile
        libatalk/unicode/Makefile
        libatalk/unicode/charsets/Makefile
 +      libatalk/util/Makefile
        libatalk/vfs/Makefile
        macros/Makefile
        man/Makefile
        man/man1/Makefile
 -      man/man3/Makefile
 -      man/man4/Makefile
        man/man5/Makefile
        man/man8/Makefile
 -      sys/Makefile
 -      sys/generic/Makefile
 -      sys/generic/sys/Makefile
 -      sys/netatalk/Makefile
 -      sys/netbsd/Makefile
 -      sys/netbsd/netatalk/Makefile
 -      sys/solaris/Makefile
 -      sys/sunos/Makefile
 -      sys/ultrix/Makefile
        test/Makefile
        test/afpd/Makefile
 +      test/netalockd/Makefile
        ],
        [chmod a+x distrib/config/netatalk-config contrib/shell_utils/apple_*]
  )
diff --combined etc/afpd/Makefile.am
index a661a5e4c7b8facc7e8ba3f85c051c8db53d179c,dd81a3f7e854021e52bb0ea8cb0c32e22ff53e1d..9b3fcae6063c5ecd7379a5e90642d841dc860a21
@@@ -6,6 -6,7 +6,6 @@@ sbin_PROGRAMS = afp
  noinst_PROGRAMS = hash
  
  afpd_SOURCES = \
 -      afp_asp.c \
        afp_avahi.c \
        afp_config.c \
        afp_dsi.c \
  afpd_LDADD =  \
        $(top_builddir)/libatalk/cnid/libcnid.la \
        $(top_builddir)/libatalk/libatalk.la \
 -      @LIBGCRYPT_LIBS@ @ZEROCONF_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @PTHREAD_LIBS@
 +      $(top_builddir)/libevent/libevent.la \
-       @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@
++      @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@
  
 -afpd_LDFLAGS = -export-dynamic 
 +afpd_LDFLAGS = -export-dynamic -static
  
  afpd_CFLAGS = \
        -I$(top_srcdir)/include \
diff --combined etc/afpd/afp_config.c
index f3adf7bf05406687fc7dcf5ede83e8cc2bdee394,7f5fd1f1fc9e32d10f3adc16c85da1cfdfdae4b6..8c997ebe94f7999e0e51b248a304e95fd38997da
@@@ -25,6 -25,9 +25,6 @@@
  #include <atalk/logger.h>
  #include <atalk/util.h>
  #include <atalk/dsi.h>
 -#include <atalk/atp.h>
 -#include <atalk/asp.h>
 -#include <atalk/nbp.h>
  #include <atalk/afp.h>
  #include <atalk/compat.h>
  #include <atalk/server_child.h>
@@@ -61,6 -64,15 +61,6 @@@ void configfree(AFPConfig *configs, con
          }
  
          switch (p->obj.proto) {
 -#ifndef NO_DDP
 -        case AFPPROTO_ASP:
 -            free(p->obj.Obj);
 -            free(p->obj.Type);
 -            free(p->obj.Zone);
 -            atp_close(((ASP) p->obj.handle)->asp_atp);
 -            free(p->obj.handle);
 -            break;
 -#endif /* no afp/asp */
          case AFPPROTO_DSI:
              close(p->fd);
              free(p->obj.handle);
@@@ -86,6 -98,9 +86,6 @@@ static char * srvloc_encode(const struc
        char *conv_name;
        unsigned char *p;
        unsigned int i = 0;
 -#ifndef NO_DDP
 -      char *Obj, *Type = "", *Zone = "";
 -#endif
  
        /* Convert name to maccharset */
          if ((size_t)-1 ==(convert_string_allocate( options->unixcharset, options->maccharset,
        }
        buf[i] = '\0';
  
 -#ifndef NO_DDP
 -      /* Add ZONE,  */
 -        if (nbp_name(options->server, &Obj, &Type, &Zone )) {
 -              LOG(log_error, logtype_afpd, "srvloc_encode: can't parse %s", options->server );
 -      }
 -      else {
 -              snprintf( buf+i, sizeof(buf)-i-1 ,"&ZONE=%s", Zone);
 -      }
 -#endif
        free (conv_name);
  
        return buf;
@@@ -158,6 -182,38 +158,6 @@@ srvloc_dereg_err
  #endif /* USE_SRVLOC */
  }
  
 -#ifndef NO_DDP
 -static void asp_cleanup(const AFPConfig *config)
 -{
 -    /* we need to stop tickle handler */
 -    asp_stop_tickle();
 -    nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone,
 -                &config->obj.options.ddpaddr);
 -}
 -
 -/* these two are almost identical. it should be possible to collapse them
 - * into one with minimal junk. */
 -static int asp_start(AFPConfig *config, AFPConfig *configs,
 -                     server_child *server_children)
 -{
 -    ASP asp;
 -
 -    if (!(asp = asp_getsession(config->obj.handle, server_children,
 -                               config->obj.options.tickleval))) {
 -        LOG(log_error, logtype_afpd, "main: asp_getsession: %s", strerror(errno) );
 -        exit( EXITERR_CLNT );
 -    }
 -
 -    if (asp->child) {
 -        configfree(configs, config); /* free a bunch of stuff */
 -        afp_over_asp(&config->obj);
 -        exit (0);
 -    }
 -
 -    return 0;
 -}
 -#endif /* no afp/asp */
 -
  static afp_child_t *dsi_start(AFPConfig *config, AFPConfig *configs,
                                server_child *server_children)
  {
      return child;
  }
  
 -#ifndef NO_DDP
 -static AFPConfig *ASPConfigInit(const struct afp_options *options,
 -                                unsigned char *refcount)
 -{
 -    AFPConfig *config;
 -    ATP atp;
 -    ASP asp;
 -    char *Obj, *Type = "AFPServer", *Zone = "*";
 -    char *convname = NULL;
 -
 -    if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL)
 -        return NULL;
 -
 -    if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL)  {
 -        LOG(log_error, logtype_afpd, "main: atp_open: %s", strerror(errno) );
 -        free(config);
 -        return NULL;
 -    }
 -
 -    if ((asp = asp_init( atp )) == NULL) {
 -        LOG(log_error, logtype_afpd, "main: asp_init: %s", strerror(errno) );
 -        atp_close(atp);
 -        free(config);
 -        return NULL;
 -    }
 -
 -    /* register asp server */
 -    Obj = (char *) options->hostname;
 -    if (options->server && (size_t)-1 ==(convert_string_allocate( options->unixcharset, options->maccharset,
 -                         options->server, strlen(options->server), &convname)) ) {
 -        if ((convname = strdup(options->server)) == NULL ) {
 -            LOG(log_error, logtype_afpd, "malloc: %s", strerror(errno) );
 -            goto serv_free_return;
 -        }
 -    }
 -
 -    if (nbp_name(convname, &Obj, &Type, &Zone )) {
 -        LOG(log_error, logtype_afpd, "main: can't parse %s", options->server );
 -        goto serv_free_return;
 -    }
 -    if (convname)
 -        free (convname);
 -
 -    /* dup Obj, Type and Zone as they get assigned to a single internal
 -     * buffer by nbp_name */
 -    if ((config->obj.Obj  = strdup(Obj)) == NULL)
 -        goto serv_free_return;
 -
 -    if ((config->obj.Type = strdup(Type)) == NULL) {
 -        free(config->obj.Obj);
 -        goto serv_free_return;
 -    }
 -
 -    if ((config->obj.Zone = strdup(Zone)) == NULL) {
 -        free(config->obj.Obj);
 -        free(config->obj.Type);
 -        goto serv_free_return;
 -    }
 -
 -    /* make sure we're not registered */
 -    nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr);
 -    if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) {
 -        LOG(log_error, logtype_afpd, "Can't register %s:%s@%s", Obj, Type, Zone );
 -        free(config->obj.Obj);
 -        free(config->obj.Type);
 -        free(config->obj.Zone);
 -        goto serv_free_return;
 -    }
 -
 -    LOG(log_info, logtype_afpd, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone,
 -        ntohs( atp_sockaddr( atp )->sat_addr.s_net ),
 -        atp_sockaddr( atp )->sat_addr.s_node,
 -        atp_sockaddr( atp )->sat_port, VERSION );
 -
 -    config->fd = atp_fileno(atp);
 -    config->obj.handle = asp;
 -    config->obj.config = config;
 -    config->obj.proto = AFPPROTO_ASP;
 -
 -    memcpy(&config->obj.options, options, sizeof(struct afp_options));
 -    config->optcount = refcount;
 -    (*refcount)++;
 -
 -    config->server_start = asp_start;
 -    config->server_cleanup = asp_cleanup;
 -
 -    return config;
 -
 -serv_free_return:
 -                    asp_close(asp);
 -    free(config);
 -    return NULL;
 -}
 -#endif /* no afp/asp */
 -
 -
  static AFPConfig *DSIConfigInit(const struct afp_options *options,
                                  unsigned char *refcount,
                                  const dsi_proto protocol)
          free(config);
          return NULL;
      }
+     dsi->dsireadbuf = options->dsireadbuf;
  
      if (options->flags & OPTION_PROXY) {
          LOG(log_note, logtype_afpd, "AFP/TCP proxy initialized for %s:%d (%s)",
@@@ -320,7 -473,7 +321,7 @@@ srvloc_reg_err
  static AFPConfig *AFPConfigInit(struct afp_options *options,
                                  const struct afp_options *defoptions)
  {
 -    AFPConfig *config = NULL, *next = NULL;
 +    AFPConfig *next = NULL;
      unsigned char *refcount;
  
      if ((refcount = (unsigned char *)
          return NULL;
      }
  
 -#ifndef NO_DDP
 -    /* handle asp transports */
 -    if ((options->transports & AFPTRANS_DDP) &&
 -            (config = ASPConfigInit(options, refcount)))
 -        config->defoptions = defoptions;
 -#endif /* NO_DDP */
 -
 -
      /* set signature */
      set_signature(options);
  
       *     (next = DSIConfigInit(options, refcount, i)))
       *     next->defoptions = defoptions;
       */
 -    if ((options->transports & AFPTRANS_TCP) &&
 -            (((options->flags & OPTION_PROXY) == 0) ||
 -             ((options->flags & OPTION_PROXY) && config))
 -            && (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
 +    if ( (options->transports & AFPTRANS_TCP)
 +         &&
 +         ((options->flags & OPTION_PROXY) == 0)
 +         &&
 +         (next = DSIConfigInit(options, refcount, DSI_TCPIP)))
          next->defoptions = defoptions;
  
      /* load in all the authentication modules. we can load the same
  
      /* this should be able to accept multiple dsi transports. i think
       * the only thing that gets affected is the net addresses. */
 -    status_init(config, next, options);
 -
 -    /* attach dsi config to tail of asp config */
 -    if (config) {
 -        config->next = next;
 -        return config;
 -    }
 +    status_init(next, options);
  
      return next;
  }
@@@ -425,8 -591,10 +426,10 @@@ AFPConfig *configinit(struct afp_option
          first = AFPConfigInit(cmdline, cmdline);
  
      /* Now register with zeroconf, we also need the volumes for that */
-     load_volumes(&first->obj);
-     zeroconf_register(first);
+     if (! (first->obj.options.flags & OPTION_NOZEROCONF)) {
+         load_volumes(&first->obj);
+         zeroconf_register(first);
+     }
  
      return first;
  }
diff --combined etc/afpd/afp_dsi.c
index 11af0d101e78866df00091d89444d7b3b36612e9,0a735ea4d2ae1a0946b63d0ece3cdea8756547f8..96188688d88e899eb2adfd4bc774e1fb6772f4a7
@@@ -31,7 -31,6 +31,7 @@@
  #include <atalk/dsi.h>
  #include <atalk/compat.h>
  #include <atalk/util.h>
 +#include <atalk/locking.h>
  
  #include "globals.h"
  #include "switch.h"
  #include "fork.h"
  #include "dircache.h"
  
 -#ifdef FORCE_UIDGID
 -#warning UIDGID
 -#include "uid.h"
 -#endif /* FORCE_UIDGID */
 -
  /* 
   * We generally pass this from afp_over_dsi to all afp_* funcs, so it should already be
   * available everywhere. Unfortunately some funcs (eg acltoownermode) need acces to it
@@@ -114,7 -118,7 +114,7 @@@ static void afp_dsi_die(int sig
  
      dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN);
      afp_dsi_close(AFPobj);
-     if (sig) /* if no signal, assume dieing because logins are disabled &
+    if (sig) /* if no signal, assume dieing because logins are disabled &
                  don't log it (maintenance mode)*/
          LOG(log_info, logtype_afpd, "Connection terminated");
      if (sig == SIGTERM || sig == SIGALRM) {
@@@ -280,7 -284,7 +280,7 @@@ static void alarm_handler(int sig _U_
  
      if (dsi->flags & DSI_SLEEPING) {
          if (dsi->tickle > AFPobj->options.sleep) {
-             LOG(log_error, logtype_afpd, "afp_alarm: sleep time ended");
+             LOG(log_note, logtype_afpd, "afp_alarm: sleep time ended");
              afp_dsi_die(EXITERR_CLNT);
          }
          return;
  
      if (dsi->flags & DSI_DISCONNECTED) {
          if (dsi->tickle > AFPobj->options.disconnected) {
-              LOG(log_error, logtype_afpd, "afp_alarm: no reconnect within 10 minutes, goodbye");
+             LOG(log_error, logtype_afpd, "afp_alarm: reconnect timer expired, goodbye");
              afp_dsi_die(EXITERR_CLNT);
          }
          return;
      }
  
      if ((err = pollvoltime(AFPobj)) == 0)
+         LOG(log_debug, logtype_afpd, "afp_alarm: sending DSI tickle");
          err = dsi_tickle(AFPobj->handle);
      if (err <= 0) {
          LOG(log_error, logtype_afpd, "afp_alarm: connection problem, entering disconnected state");
+         dsi->proto_close(dsi);
          dsi->flags |= DSI_DISCONNECTED;
      }
  }
@@@ -451,6 -457,26 +453,26 @@@ void afp_over_dsi(AFPObj *obj
      if (dircache_init(obj->options.dircachesize) != 0)
          afp_dsi_die(EXITERR_SYS);
  
+     /* set TCP snd/rcv buf */
+     if (obj->options.tcp_rcvbuf) {
+         if (setsockopt(dsi->socket,
+                        SOL_SOCKET,
+                        SO_RCVBUF,
+                        &obj->options.tcp_rcvbuf,
+                        sizeof(obj->options.tcp_rcvbuf)) != 0) {
+             LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_RCVBUF): %s", strerror(errno));
+         }
+     }
+     if (obj->options.tcp_sndbuf) {
+         if (setsockopt(dsi->socket,
+                        SOL_SOCKET,
+                        SO_SNDBUF,
+                        &obj->options.tcp_sndbuf,
+                        sizeof(obj->options.tcp_sndbuf)) != 0) {
+             LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_SNDBUF): %s", strerror(errno));
+         }
+     }
      /* get stuck here until the end */
      while (1) {
          if (sigsetjmp(recon_jmp, 1) != 0)
              }
              /* 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) {
+                 afp_dsi_close(obj);
+                 exit(0);
+             }
              pause(); /* gets interrupted by SIGALARM or SIGURG tickle */
              continue; /* continue receiving until disconnect timer expires
                         * or a primary reconnect succeeds  */
              }
          }
  
-         if (cmd == DSIFUNC_TICKLE) {
-             /* timer is not every 30 seconds anymore, so we don't get killed on the client side. */
-             if ((dsi->flags & DSI_DIE))
-                 dsi_tickle(dsi);
-             pending_request(dsi);
-             continue;
-         } 
  
          dsi->flags |= DSI_DATA;
+         dsi->tickle = 0;
          switch(cmd) {
          case DSIFUNC_CLOSE:
+             LOG(log_debug, logtype_afpd, "DSI: close session request");
              afp_dsi_close(obj);
              LOG(log_note, logtype_afpd, "done");
-             return;
+             exit(0);
+         case DSIFUNC_TICKLE:
+             dsi->flags &= ~DSI_DATA; /* thats no data in the sense we use it in alarm_handler */
+             LOG(log_debug, logtype_afpd, "DSI: client tickle");
+             /* timer is not every 30 seconds anymore, so we don't get killed on the client side. */
+             if ((dsi->flags & DSI_DIE))
+                 dsi_tickle(dsi);
              break;
  
          case DSIFUNC_CMD:
              function = (u_char) dsi->commands[0];
  
              /* AFP replay cache */
-             rc_idx = REPLAYCACHE_SIZE % dsi->clientID;
+             rc_idx = dsi->clientID % REPLAYCACHE_SIZE;
              LOG(log_debug, logtype_afpd, "DSI request ID: %u", dsi->clientID);
  
              if (replaycache[rc_idx].DSIreqID == dsi->clientID
                  && replaycache[rc_idx].AFPcommand == function) {
-                 LOG(log_debug, logtype_afpd, "AFP Replay Cache match: id: %u / cmd: %s",
+                 LOG(log_note, logtype_afpd, "AFP Replay Cache match: id: %u / cmd: %s",
                      dsi->clientID, AfpNum2name(function));
                  err = replaycache[rc_idx].result;
              /* AFP replay cache end */
  
                      dir_free_invalid_q();
  
 -#ifdef FORCE_UIDGID
 -                    /* bring everything back to old euid, egid */
 -                    if (obj->force_uid)
 -                        restore_uidgid ( &obj->uidgid );
 -#endif /* FORCE_UIDGID */
                      dsi->flags &= ~DSI_RUNNING;
  
                      /* Add result to the AFP replay cache */
                      AfpNum2name(function), AfpErr2name(err));
  
                  dsi->flags &= ~DSI_RUNNING;
 -#ifdef FORCE_UIDGID
 -              /* bring everything back to old euid, egid */
 -              if (obj->force_uid)
 -                  restore_uidgid ( &obj->uidgid );
 -#endif /* FORCE_UIDGID */
              } else {
                  LOG(log_error, logtype_afpd, "(write) bad function %x", function);
                  dsi->datalen = 0;
diff --combined etc/afpd/afp_options.c
index fac01fdef357c906408c1858012c0e7905a903f9,f3724c13cdbd6d05f8403b6a753839e9c1f207c0..ec4b762dfb1a7b84a9da7e98ad21518a63e9f208
@@@ -186,6 -186,9 +186,9 @@@ void afp_options_init(struct afp_option
      options->dircachesize = DEFAULT_MAX_DIRCACHE_SIZE;
      options->flags |= OPTION_ACL2MACCESS;
      options->flags |= OPTION_UUID;
+     options->tcp_sndbuf = 0;    /* 0 means don't change OS default */
+     options->tcp_rcvbuf = 0;    /* 0 means don't change OS default */
+     options->dsireadbuf = 12;
  }
  
  /* parse an afpd.conf line. i'm doing it this way because it's
@@@ -321,6 -324,12 +324,12 @@@ int afp_options_parseline(char *buf, st
          }
      }
  
+     if ((c = getoption(buf, "-dsireadbuf"))) {
+         options->dsireadbuf = atoi(c);
+         if (options->dsireadbuf < 6)
+             options->dsireadbuf = 6;
+     }
      if ((c = getoption(buf, "-server_quantum")))
          options->server_quantum = strtoul(c, NULL, 0);
  
  
      if ((c = getoption(buf, "-port")))
          options->port = strdup(c);
 -    if ((c = getoption(buf, "-ddpaddr")))
 -        atalk_aton(c, &options->ddpaddr);
      if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
          options->signatureopt = opt;
  
      if ((c = getoption(buf, "-dircachesize")))
          options->dircachesize = atoi(c);
       
+     if ((c = getoption(buf, "-tcpsndbuf")))
+         options->tcp_sndbuf = atoi(c);
+     if ((c = getoption(buf, "-tcprcvbuf")))
+         options->tcp_rcvbuf = atoi(c);
      return 1;
  }
  
@@@ -483,6 -500,13 +498,6 @@@ static void show_version( void 
          printf( "        TCP/IP Support:\t" );
          puts( "Yes" );
  
 -      printf( "DDP(AppleTalk) Support:\t" );
 -#ifdef NO_DDP
 -      puts( "No" );
 -#else
 -      puts( "Yes" );
 -#endif
 -
        printf( "         CNID backends:\t" );
  #ifdef CNID_BACKEND_CDB
        printf( "cdb ");
@@@ -569,6 -593,20 +584,6 @@@ static void show_version_extended(void 
        puts( "No" );
  #endif
  
 -      printf( "        Dropbox kludge:\t" );
 -#ifdef DROPKLUDGE
 -      puts( "Yes" );
 -#else
 -      puts( "No" );
 -#endif
 -
 -      printf( "  Force volume uid/gid:\t" );
 -#ifdef FORCE_UIDGID
 -      puts( "Yes" );
 -#else
 -      puts( "No" );
 -#endif
 -
        printf( "           ACL support:\t" );
  #ifdef HAVE_ACLS
        puts( "Yes" );
diff --combined etc/afpd/auth.c
index 9245293c80af9a1841a7556cb0026143d341dafb,566a8d0e05b1b838ddc5e2dceef29463e9c33d03..0768d22d1d6cacc122b8293798dabe5e79a48ebf
  #include <stdio.h>
  #include <stdlib.h>
  #include <errno.h>
 -#ifdef HAVE_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #include <sys/types.h>
  #include <sys/param.h>
  #include <sys/stat.h>
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/afp.h>
  #include <atalk/compat.h>
  #include <atalk/util.h>
@@@ -72,6 -73,11 +72,6 @@@ int ngroups
   * These numbers are scattered throughout the code.
   */
  static struct afp_versions  afp_versions[] = {
 -#ifndef NO_DDP
 -    { "AFPVersion 1.1", 11 },
 -    { "AFPVersion 2.0", 20 },
 -    { "AFPVersion 2.1", 21 },
 -#endif /* ! NO_DDP */
      { "AFP2.2", 22 },
      { "AFPX03", 30 },
      { "AFP3.1", 31 },
@@@ -88,7 -94,7 +88,7 @@@ static struct uam_obj uam_changepw = {"
  static struct uam_obj *afp_uam = NULL;
  
  
 -void status_versions( char *data, const ASP asp, const DSI *dsi)
 +void status_versions( char *data, const DSI *dsi)
  {
      char                *start = data;
      u_int16_t           status;
      num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] );
  
      for ( i = 0; i < num; i++ ) {
 -#ifndef NO_DDP
 -        if ( !asp && (afp_versions[ i ].av_number <= 21)) continue;
 -#endif /* ! NO_DDP */
          if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue;
          count++;
      }
      *data++ = count;
  
      for ( i = 0; i < num; i++ ) {
 -#ifndef NO_DDP
 -        if ( !asp && (afp_versions[ i ].av_number <= 21)) continue;
 -#endif /* ! NO_DDP */
          if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue;
          len = strlen( afp_versions[ i ].av_name );
          *data++ = len;
@@@ -256,6 -268,45 +256,6 @@@ static int login(AFPObj *obj, struct pa
      LOG(log_note, logtype_afpd, "%s Login by %s",
          afp_versions[afp_version_index].av_name, pwd->pw_name);
  
 -#ifndef NO_DDP
 -    if (obj->proto == AFPPROTO_ASP) {
 -        ASP asp = obj->handle;
 -        int addr_net = ntohs( asp->asp_sat.sat_addr.s_net );
 -        int addr_node  = asp->asp_sat.sat_addr.s_node;
 -
 -        if (obj->options.authprintdir) {
 -            if(addr_net && addr_node) { /* Do we have a valid Appletalk address? */
 -                char nodename[256];
 -                FILE *fp;
 -                int mypid = getpid();
 -                struct stat stat_buf;
 -
 -                sprintf(nodename, "%s/net%d.%dnode%d", obj->options.authprintdir,
 -                        addr_net / 256, addr_net % 256, addr_node);
 -                LOG(log_info, logtype_afpd, "registering %s (uid %d) on %u.%u as %s",
 -                    pwd->pw_name, pwd->pw_uid, addr_net, addr_node, nodename);
 -
 -                if (stat(nodename, &stat_buf) == 0) { /* file exists */
 -                    if (S_ISREG(stat_buf.st_mode)) { /* normal file */
 -                        unlink(nodename);
 -                        fp = fopen(nodename, "w");
 -                        fprintf(fp, "%s:%d\n", pwd->pw_name, mypid);
 -                        fclose(fp);
 -                        chown( nodename, pwd->pw_uid, -1 );
 -                    } else { /* somebody is messing with us */
 -                        LOG(log_error, logtype_afpd, "print authfile %s is not a normal file, it will not be modified", nodename );
 -                    }
 -                } else { /* file 'nodename' does not exist */
 -                    fp = fopen(nodename, "w");
 -                    fprintf(fp, "%s:%d\n", pwd->pw_name, mypid);
 -                    fclose(fp);
 -                    chown( nodename, pwd->pw_uid, -1 );
 -                }
 -            } /* if (addr_net && addr_node ) */
 -        } /* if (options->authprintdir) */
 -    } /* if (obj->proto == AFPPROTO_ASP) */
 -#endif
 -
      if (initgroups( pwd->pw_name, pwd->pw_gid ) < 0) {
  #ifdef RUN_AS_USER
          LOG(log_info, logtype_afpd, "running with uid %d", geteuid());
      obj->uid = geteuid();
      obj->logout = logout;
  
 -#ifdef FORCE_UIDGID
 -    obj->force_uid = 1;
 -    save_uidgid ( &obj->uidgid );
 -#endif
 -
      return( AFP_OK );
  }
  
  /* ---------------------- */
- int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
+ int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
  {
      uint32_t data;
      DSI *dsi = (DSI *)AFPobj->handle;
  
      *rbuflen = 0;
+     ibuf += 2;
+     ibuflen -= 2;
  
      if (ibuflen < 4)
          return AFPERR_MISC;
      if (data & AFPZZZ_EXT_WAKEUP) {
          /* wakeup request from exetended sleep */
          if (dsi->flags & DSI_EXTSLEEP) {
-             LOG(log_debug, logtype_afpd, "afp_zzz: waking up from extended sleep");
+             LOG(log_note, logtype_afpd, "afp_zzz: waking up from extended sleep");
              dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP);
          }
      } else {
          /* sleep request */
          dsi->flags |= DSI_SLEEPING;
          if (data & AFPZZZ_EXT_SLEEP) {
-             LOG(log_debug, logtype_afpd, "afp_zzz: entering extended sleep");
+             LOG(log_note, logtype_afpd, "afp_zzz: entering extended sleep");
              dsi->flags |= DSI_EXTSLEEP;
          } else {
-             LOG(log_debug, logtype_afpd, "afp_zzz: entering normal sleep");
+             LOG(log_note, logtype_afpd, "afp_zzz: entering normal sleep");
          }
      }
      /*
       * According to AFP 3.3 spec we should not return anything,
       * but eg 10.5.8 server still returns the numbers of hours
@@@ -876,11 -935,15 +879,15 @@@ int afp_logincont(AFPObj *obj, char *ib
  }
  
  
- int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_, size_t *rbuflen  _U_)
+ int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_, size_t *rbuflen)
  {
+     DSI *dsi = (DSI *)(obj->handle);
      LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username);
+     of_close_all_forks();
      close_all_vol();
-     obj->exit(0);
+     dsi->flags = DSI_AFP_LOGGED_OUT;
+     *rbuflen = 0;
      return AFP_OK;
  }
  
diff --combined etc/afpd/directory.c
index 3edbec25966df7627cd97c702da2adec011f1b55,b981af66c03fb6c4b94cff562402dcc78dbcd13d..488f900a0a553e7ee278962e8a2f786087557d72
@@@ -28,6 -28,7 +28,7 @@@
  #include <atalk/unix.h>
  #include <atalk/bstrlib.h>
  #include <atalk/bstradd.h>
+ #include <atalk/errchk.h>
  
  #include "directory.h"
  #include "dircache.h"
@@@ -301,7 -302,7 +302,7 @@@ static int cname_mtouname(const struct 
  {
      static char temp[ MAXPATHLEN + 1];
      char *t;
-     cnid_t fileid;
+     cnid_t fileid = 0;
  
      if (afp_version >= 30) {
          if (toUTF8) {
@@@ -429,6 -430,84 +430,84 @@@ int get_afp_errno(const int param
      return param;
  }
  
+ /*!
+  * Resolve struct dir for an absolute path
+  *
+  * Given a path like "/Volumes/volume/dir/subdir" in a volume "/Volumes/volume" return
+  * a pointer to struct dir of "subdir".
+  * 1. Remove volue path from absolute path
+  * 2. start path
+  * 3. loop through all elements of the remaining path from 1.
+  * 4. we only allow dirs
+  * 5. search dircache
+  * 6. if not found in the dircache query the CNID database for the DID
+  * 7. and use dirlookup to resolve the DID to a it's struct dir *
+  *
+  * @param vol   (r) volume the path is in, must be known
+  * @param path  (r) absoule path
+  *
+  * @returns pointer to struct dir or NULL on error
+  */
+ struct dir *dirlookup_bypath(const struct vol *vol, const char *path)
+ {
+     EC_INIT;
+     struct dir *dir = NULL;
+     cnid_t cnid, did;
+     bstring rpath = NULL;
+     bstring statpath = NULL;
+     struct bstrList *l = NULL;
+     struct stat st;
+     cnid = htonl(2);
+     dir = vol->v_root;
+     EC_NULL(rpath = rel_path_in_vol(path, vol->v_path)); /* 1. */
+     EC_NULL(statpath = bfromcstr(vol->v_path));          /* 2. */
+     l = bsplit(rpath, '/');
+     for (int i = 0; i < l->qty ; i++) {                  /* 3. */
+         did = cnid;
+         EC_ZERO(bconcat(statpath, l->entry[i]));
+         EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
+                        "lstat(rpath: %s, elem: %s): %s: %s",
+                        cfrombstr(rpath), cfrombstr(l->entry[i]),
+                        cfrombstr(statpath), strerror(errno));
+         if (!(S_ISDIR(st.st_mode)))                      /* 4. */
+             EC_FAIL;
+         if ((dir = dircache_search_by_name(vol,          /* 5. */
+                                            dir,
+                                            cfrombstr(l->entry[i]),
+                                            blength(l->entry[i]),
+                                            st.st_ctime)) == NULL) {
+             if ((cnid = cnid_add(vol->v_cdb,             /* 6. */
+                                  &st,
+                                  did,
+                                  cfrombstr(l->entry[i]),
+                                  blength(l->entry[i]),
+                                  0)) == CNID_INVALID) {
+                 EC_FAIL;
+             }
+             if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */
+                 EC_FAIL;
+         }
+         EC_ZERO(bcatcstr(statpath, "/"));
+     }
+ EC_CLEANUP:
+     bdestroy(rpath);
+     bstrListDestroy(l);
+     bdestroy(statpath);
+     if (ret != 0)
+         return NULL;
+     return dir;
+ }
  /*!
   * @brief Resolve a DID
   *
   * @param did   (r) DID to resolve
   *
   * @returns pointer to struct dir
-  *
-  * @note FIXME: OSX calls it with bogus id, ie file ID not folder ID,
-  *       and we are really bad in this case.
   */
  struct dir *dirlookup(const struct vol *vol, cnid_t did)
  {
      int          utf8;
      int          err = 0;
  
-     LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {start}", ntohl(did));
+     LOG(log_debug, logtype_afpd, "dirlookup(did: %u)", ntohl(did));
  
      /* check for did 0, 1 and 2 */
      if (did == 0 || vol == NULL) { /* 1 */
          afp_errno = AFPERR_PARAM;
-         return NULL;
+         ret = NULL;
+         goto exit;
      } else if (did == DIRDID_ROOT_PARENT) {
          rootParent.d_vid = vol->v_vid;
-         return (&rootParent);
+         ret = &rootParent;
+         goto exit;
      } else if (did == DIRDID_ROOT) {
-         return vol->v_root;
+         ret = vol->v_root;
+         goto exit;
      }
  
      /* Search the cache */
      if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */
          if (ret->d_fullpath == NULL) {                      /* 2b */
              afp_errno = AFPERR_BADTYPE;
-             return NULL;
+             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) {calling dir_remove()}", ntohl(did));
                  dir_remove(vol, ret);
                  afp_errno = AFPERR_NOOBJ;
-                 return NULL;
+                 ret = NULL;
+                 goto exit;
              default:
-                 return ret;
+                 ret = ret;
+                 goto exit;
              }
              /* DEADC0DE */
-             return NULL;
+             ret = NULL;
+             goto exit;            
          }
-         return ret;
+         ret = ret;
+         goto exit;
      }
  
      utf8 = utf8_encoding();
  
      /* Get it from the database */
      cnid = did;
-     if ( (upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL 
-          || (upath = strdup(upath)) == NULL) { /* 3 */
+     if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) {
+         afp_errno = AFPERR_NOOBJ;
+         err = 1;
+         goto exit;
+     }
+     if ((upath = strdup(upath)) == NULL) { /* 3 */
          afp_errno = AFPERR_NOOBJ;
          err = 1;
          goto exit;
       * - DIRDID_ROOT is hit
       * - a cached entry is found
       */
+     LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {recursion for did: %u}", ntohl(pdid));
      if ((pdir = dirlookup(vol, pdid)) == NULL) {
          err = 1;
          goto exit;
      }
      
      /* Add it to the cache only if it's a dir */
-     if (dircache_add(ret) != 0) { /* 7 */
+     if (dircache_add(vol, ret) != 0) { /* 7 */
          err = 1;
          goto exit;
      }
  
-     LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {end: did:%u, path:'%s'}",
-         ntohl(did), ntohl(pdid), cfrombstr(ret->d_fullpath));
  exit:
      if (upath) free(upath);
      if (err) {
              ret = NULL;
          }
      }
+     if (ret)
+         LOG(log_debug, logtype_afpd, "dirlookup(did: %u): pdid: %u, \"%s\"",
+             ntohl(ret->d_did), ntohl(ret->d_pdid), cfrombstr(ret->d_fullpath));
      return ret;
  }
  
@@@ -802,7 -892,7 +892,7 @@@ struct dir *dir_add(struct vol *vol, co
  
      /* get_id needs adp for reading CNID from adouble file */
      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 -    if ((ad_open_metadata(path->u_name, ADFLAGS_DIR, 0, &ad)) == 0) /* 1 */
 +    if ((ad_open(&ad, path->u_name, ADFLAGS_HF | ADFLAGS_DIR)) == 0) /* 1 */
          adp = &ad;
  
      /* Get CNID */
      /* Get macname from unixname */
      if (path->m_name == NULL) {
          if ((path->m_name = utompath(vol, path->u_name, id, utf8_encoding())) == NULL) {
+             LOG(log_error, logtype_afpd, "dir_add(\"%s\"): can't assign macname", path->u_name);
              err = 2;
              goto exit;
          }
          goto exit;
      }
  
-     if ((dircache_add(cdir)) != 0) { /* 4 */
+     if ((dircache_add(vol, cdir)) != 0) { /* 4 */
          LOG(log_error, logtype_afpd, "dir_add: fatal dircache error: %s", cfrombstr(fullpath));
          exit(EXITERR_SYS);
      }
@@@ -880,9 -971,9 +971,9 @@@ void dir_free_invalid_q(void
   * @brief Remove a dir from a cache and queue it for freeing
   *
   * 1. Check if the dir is locked or has opened forks
-  * 2. If it's a request to remove curdir, just chdir to volume root
-  * 3. Remove it from the cache
-  * 4. Queue it for removal
+  * 2. Remove it from the cache
+  * 3. Queue it for removal
+  * 4. If it's a request to remove curdir, mark curdir as invalid
   * 5. Mark it as invalid
   *
   * @param (r) pointer to struct vol
@@@ -896,27 -987,21 +987,21 @@@ int dir_remove(const struct vol *vol, s
      if (dir->d_did == DIRDID_ROOT_PARENT || dir->d_did == DIRDID_ROOT)
          return 0;
  
-     if (dir->d_flags & DIRF_CACHELOCK) { /* 1 */
-         LOG(log_warning, logtype_afpd, "dir_remove(did:%u,'%s'): dir is locked",
-             ntohl(dir->d_did), cfrombstr(dir->d_u_name));
-         return 0;
-     }
-     if (curdir == dir) {        /* 2 */
-         if (movecwd(vol, vol->v_root) < 0) {
-             LOG(log_error, logtype_afpd, "dir_remove: can't chdir to : %s", vol->v_root);
-         }
-     }
      LOG(log_debug, logtype_afpd, "dir_remove(did:%u,'%s'): {removing}",
          ntohl(dir->d_did), cfrombstr(dir->d_u_name));
  
-     dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 3 */
-     enqueue(invalid_dircache_entries, dir); /* 4 */
+     dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 2 */
+     enqueue(invalid_dircache_entries, dir); /* 3 */
+     if (curdir == dir)                      /* 4 */
+         curdir = NULL;
      dir->d_did = CNID_INVALID;              /* 5 */
      return 0;
  }
  
+ #if 0 /* unused */
  /*!
   * @brief Modify a struct dir, adjust cache
   *
@@@ -988,13 -1073,14 +1073,14 @@@ int dir_modify(const struct vol *vol
          dir->d_m_name_ucs2 = NULL;
  
      /* Re-add it to the cache */
-     if ((dircache_add(dir)) != 0) {
+     if ((dircache_add(vol, dir)) != 0) {
          dircache_dump();
          AFP_PANIC("dir_modify");
      }
  
      return ret;
  }
+ #endif
  
  /*!
   * @brief Resolve a catalog node name path
@@@ -1104,7 -1190,7 +1190,7 @@@ struct path *cname(struct vol *vol, str
          /* 6*/
          for ( p = path; *data != 0 && len > 0; len-- ) {
              *p++ = *data++;
-             if (p > &path[ MAXPATHLEN]) {
+             if (p > &path[UTF8FILELEN_EARLY]) {   /* FIXME safeguard, limit of early Mac OS X */
                  afp_errno = AFPERR_PARAM;
                  return NULL;
              }
@@@ -1253,21 -1339,19 +1339,19 @@@ int movecwd(const struct vol *vol, stru
      AFP_ASSERT(vol);
      AFP_ASSERT(dir);
  
-     LOG(log_maxdebug, logtype_afpd, "movecwd(curdir:'%s', cwd:'%s')",
-         cfrombstr(curdir->d_fullpath), getcwdpath());
+     LOG(log_maxdebug, logtype_afpd, "movecwd: from: curdir:\"%s\", cwd:\"%s\"",
+         curdir ? cfrombstr(curdir->d_fullpath) : "INVALID", getcwdpath());
  
-     if ( dir == curdir)
-         return( 0 );
      if (dir->d_did == DIRDID_ROOT_PARENT) {
          curdir = &rootParent;
          return 0;
      }
  
-     LOG(log_debug, logtype_afpd, "movecwd(did:%u, '%s')",
+     LOG(log_debug, logtype_afpd, "movecwd(to: did: %u, \"%s\")",
          ntohl(dir->d_did), cfrombstr(dir->d_fullpath));
  
      if ((ret = lchdir(cfrombstr(dir->d_fullpath))) != 0 ) {
-         LOG(log_debug, logtype_afpd, "movecwd('%s'): ret: %u, %s",
+         LOG(log_debug, logtype_afpd, "movecwd(\"%s\"): ret: %u, %s",
              cfrombstr(dir->d_fullpath), ret, strerror(errno));
          if (ret == 1) {
              /* p is a symlink or getcwd failed */
@@@ -1328,10 -1412,18 +1412,18 @@@ int file_access(struct path *path, int 
      struct maccess ma;
  
      accessmode(path->u_name, &ma, curdir, &path->st);
-     if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
+     LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x",
+         path->u_name, ma.ma_user);
+     if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) {
+         LOG(log_debug, logtype_afpd, "file_access(\"%s\"): write access denied", path->u_name);
          return -1;
-     if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
+     }
+     if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) {
+         LOG(log_debug, logtype_afpd, "file_access(\"%s\"): read access denied", path->u_name);
          return -1;
+     }
      return 0;
  
  }
@@@ -1382,8 -1474,20 +1474,8 @@@ int getdirparams(const struct vol *vol
                     (1 << DIRPBIT_FINFO)))) {
  
          ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 -        if ( !ad_metadata( upath, ADFLAGS_CREATE|ADFLAGS_DIR, &ad) ) {
 +        if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) )
              isad = 1;
 -            if (ad.ad_md->adf_flags & O_CREAT) {
 -                /* We just created it */
 -                ad_setname(&ad, s_path->m_name);
 -                ad_setid( &ad,
 -                          s_path->st.st_dev,
 -                          s_path->st.st_ino,
 -                          dir->d_did,
 -                          dir->d_pdid,
 -                          vol->v_stamp);
 -                ad_flush( &ad);
 -            }
 -        }
      }
  
      pdid = dir->d_pdid;
@@@ -1787,7 -1891,7 +1879,7 @@@ int setdirparams(struct vol *vol, struc
      }
      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
  
 -    if (ad_open_metadata( upath, ADFLAGS_DIR, O_CREAT, &ad) < 0) {
 +    if (ad_open(&ad, upath, ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) != 0) {
          /*
           * Check to see what we're trying to set.  If it's anything
           * but ACCESS, UID, or GID, give an error.  If it's any of those
           * Check to see if a create was necessary. If it was, we'll want
           * to set our name, etc.
           */
 -        if ( (ad_get_HF_flags( &ad ) & O_CREAT)) {
 +        if ( (ad_get_MD_flags( &ad ) & O_CREAT)) {
              ad_setname(&ad, cfrombstr(curdir->d_m_name));
          }
      }
@@@ -2140,7 -2244,7 +2232,7 @@@ int afp_createdir(AFPObj *obj, char *ib
      }
  
      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 -    if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad ) < 0)  {
 +    if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) < 0)  {
          if (vol_noadouble(vol))
              goto createdir_done;
          return( AFPERR_ACCESS );
@@@ -2206,7 -2310,7 +2298,7 @@@ int renamedir(const struct vol *vol
  
      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
  
 -    if (!ad_open_metadata( dst, ADFLAGS_DIR, 0, &ad)) {
 +    if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_DIR) == 0) {
          ad_setname(&ad, newname);
          ad_flush( &ad);
          ad_close_metadata( &ad);
@@@ -2220,13 -2324,13 +2312,13 @@@ int deletecurdir(struct vol *vol
  {
      struct dirent *de;
      struct stat st;
-     struct dir  *fdir;
+     struct dir  *fdir, *pdir;
      DIR *dp;
      struct adouble  ad;
      u_int16_t       ashort;
      int err;
  
-     if ( dirlookup(vol, curdir->d_pdid) == NULL ) {
+     if ((pdir = dirlookup(vol, curdir->d_pdid)) == NULL) {
          return( AFPERR_ACCESS );
      }
  
      }
      err = vol->vfs->vfs_deletecurdir(vol);
      if (err) {
+         LOG(log_error, logtype_afpd, "deletecurdir: error deleting .AppleDouble in \"%s\"",
+             curdir->d_fullpath);
          return err;
      }
  
  
              /* bail if it's not a symlink */
              if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) {
+                 LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): not empty",
+                     curdir->d_fullpath);
                  closedir(dp);
                  return AFPERR_DIRNEMPT;
              }
          }
      }
  
-     if ( movecwd(vol, dirlookup(vol, curdir->d_pdid)) < 0 ) {
+     if (movecwd(vol, pdir) < 0) {
          err = afp_errno;
          goto delete_done;
      }
  
+     LOG(log_debug, logtype_afpd, "deletecurdir: moved to \"%s\"",
+         cfrombstr(curdir->d_fullpath));
      err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name));
      if ( err ==  AFP_OK || err == AFPERR_NOOBJ) {
          cnid_delete(vol->v_cdb, fdir->d_did);
          dir_remove( vol, fdir );
+     } else {
+         LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error",
+             curdir->d_fullpath);
      }
  delete_done:
      if (dp) {
          /* inode is used as key for cnid.
diff --combined etc/afpd/directory.h
index 731140ababecd7140946c7572b8b392615a7525e,79c4a0407fe3b6c1d61bb3d2208e1cc22f319d9f..1504c649dbb9ba55ea083f8bc95b6d701cf6b05c
  #ifndef AFPD_DIRECTORY_H
  #define AFPD_DIRECTORY_H 1
  
 -#include <sys/cdefs.h>
  #include <sys/types.h>
 -/*#include <sys/stat.h>*/ /* including it here causes some confusion */
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
  #include <dirent.h>
  
  /* sys/types.h usually snarfs in major/minor macros. if they don't
@@@ -46,7 -48,6 +46,6 @@@
  
  #define DIRF_OFFCNT    (1<<4) /* offsprings count is valid */
  #define DIRF_CNID        (1<<5) /* renumerate id */
- #define DIRF_CACHELOCK (1<<6) /* lock in cache, don't remove in dircache_eviction, for catsearch */
  
  #define AFPDIR_READ   (1<<0)
  
@@@ -115,6 -116,8 +114,8 @@@ extern int         dir_modify(const str
                                const char *new_mname, const char *new_uname, bstring pdir_fullpath);
  extern int         dir_remove(const struct vol *vol, struct dir *dir);
  extern struct dir  *dirlookup (const struct vol *, cnid_t);
+ extern struct dir *dirlookup_bypath(const struct vol *vol, const char *path);
  extern int         movecwd (const struct vol *, struct dir *);
  extern struct path *cname (struct vol *, struct dir *, char **);
  
diff --combined etc/afpd/file.c
index bd0e935c0fe8d2e44049b7471578cdf69e969e9f,f7df604982f3b966f102d96125479c358f5952a4..0459656f1ed51572135398ef97adfd818470e5fa
  #include <stdio.h>
  #include <stdlib.h>
  
 -/* STDC check */
 -#if STDC_HEADERS
  #include <string.h>
 -#else /* STDC_HEADERS */
 -#ifndef HAVE_STRCHR
 -#define strchr index
 -#define strrchr index
 -#endif /* HAVE_STRCHR */
 -char *strchr (), *strrchr ();
 -
 -#ifndef HAVE_MEMCPY
 -#define memcpy(d,s,n) bcopy ((s), (d), (n))
 -#define memmove(d,s,n) bcopy ((s), (d), (n))
 -#endif /* ! HAVE_MEMCPY */
 -#endif /* STDC_HEADERS */
 -
  #include <utime.h>
  #include <errno.h>
  #include <sys/param.h>
@@@ -150,8 -165,8 +150,8 @@@ char *set_name(const struct vol *vol, c
      else {
          u_int16_t temp;
  
-         if (aint > 255)  /* FIXME safeguard, anyway if no ascii char it's game over*/
-            aint = 255;
+         if (aint > UTF8FILELEN_EARLY)  /* FIXME safeguard, anyway if no ascii char it's game over*/
+            aint = UTF8FILELEN_EARLY;
  
          utf8 = vol->v_kTextEncoding;
          memcpy(data, &utf8, sizeof(utf8));
@@@ -301,6 -316,8 +301,8 @@@ int getmetadata(struct vol *vol
      struct stat         *st;
      struct maccess    ma;
  
+     LOG(log_debug, logtype_afpd, "getmetadata(\"%s\")", path->u_name);
      upath = path->u_name;
      st = &path->st;
      data = buf;
                      exit(EXITERR_SYS);
                  }
  
-                 if ((dircache_add(cachedfile)) != 0) {
+                 if ((dircache_add(vol, cachedfile)) != 0) {
                      LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error");
                      exit(EXITERR_SYS);
                  }
@@@ -598,17 -615,19 +600,19 @@@ int getfilparams(struct vol *vol
      int                 opened = 0;
      int rc;    
  
+     LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name);
      opened = PARAM_NEED_ADP(bitmap);
      adp = NULL;
  
      if (opened) {
          char *upath;
 -        int  flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0;
 +        int  flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0;
  
          adp = of_ad(vol, path, &ad);
          upath = path->u_name;
  
 -        if ( ad_metadata( upath, flags|ADFLAGS_CREATE, adp) < 0 ) {
 +        if ( ad_metadata( upath, flags, adp) < 0 ) {
              switch (errno) {
              case EACCES:
                  LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?",
          }
      }
      rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
 -    if ( adp ) {
 -        ad_close_metadata( adp);
 -    }
 +    ad_close_metadata( adp);
  
      return( rc );
  }
  /* ----------------------------- */
  int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
  {
 -    struct adouble    ad, *adp;
 +    struct adouble    ad;
      struct vol                *vol;
      struct dir                *dir;
      struct ofork        *of = NULL;
      memcpy(&vid, ibuf, sizeof( vid ));
      ibuf += sizeof( vid );
  
 -    if (NULL == ( vol = getvolbyvid( vid )) ) {
 +    if (NULL == ( vol = getvolbyvid( vid )) )
          return( AFPERR_PARAM );
 -    }
  
      if (vol->v_flags & AFPVOL_RO)
          return AFPERR_VLOCK;
      memcpy(&did, ibuf, sizeof( did));
      ibuf += sizeof( did );
  
 -    if (NULL == ( dir = dirlookup( vol, did )) ) {
 +    if (NULL == ( dir = dirlookup( vol, did )) )
          return afp_errno;
 -    }
  
 -    if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
 +    if (NULL == ( s_path = cname( vol, dir, &ibuf )) )
          return get_afp_errno(AFPERR_PARAM);
 -    }
  
 -    if ( *s_path->m_name == '\0' ) {
 +    if ( *s_path->m_name == '\0' )
          return( AFPERR_BADTYPE );
 -    }
  
      upath = s_path->u_name;
 +    ad_init(&ad, vol->v_adouble, vol->v_ad_options);
      
      /* if upath is deleted we already in trouble anyway */
      if ((of = of_findname(s_path))) {
 -        adp = of->of_ad;
 -    } else {
 -        ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 -        adp = &ad;
 -    }
 -    if ( creatf) {
 -        /* on a hard create, fail if file exists and is open */
 -        if (of)
 +        if (creatf)
              return AFPERR_BUSY;
 +        else
 +            return AFPERR_EXIST;
 +    }
 +
 +    if ( creatf)
          openf = O_RDWR|O_CREAT|O_TRUNC;
 -    } else {
 +    else
        /* on a soft create, if the file is open then ad_open won't fail
 -         because open syscall is not called
 -      */
 -      if (of) {
 -              return AFPERR_EXIST;
 -      }
 +         because open syscall is not called */
          openf = O_RDWR|O_CREAT|O_EXCL;
 -    }
  
 -    if ( ad_open( upath, ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE,
 -                  openf, 0666, adp) < 0 ) {
 +    if ( ad_open(&ad, upath, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF,
 +                 openf, 0666, openf, 0666) < 0 ) {
          switch ( errno ) {
          case EROFS:
              return AFPERR_VLOCK;
              return( AFPERR_PARAM );
          }
      }
 -    if ( ad_reso_fileno( adp ) == -1 ) { /* Hard META / HF */
 +    if ( ad_meta_fileno( &ad ) == -1 ) { /* Hard META / HF */
           /* on noadouble volumes, just creating the data fork is ok */
           if (vol_noadouble(vol)) {
 -             ad_close( adp, ADFLAGS_DF );
 +             ad_close( &ad, ADFLAGS_DF );
               goto createfile_done;
           }
           /* FIXME with hard create on an existing file, we already
            * corrupted the data file.
            */
           netatalk_unlink( upath );
 -         ad_close( adp, ADFLAGS_DF );
 +         ad_close( &ad, ADFLAGS_DF );
           return AFPERR_ACCESS;
      }
  
      path = s_path->m_name;
 -    ad_setname(adp, path);
 +    ad_setname(&ad, path);
+     struct stat st;
+     if (lstat(upath, &st) != 0) {
+         LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): stat: %s",
+             upath, strerror(errno));
+         ad_close( adp, ADFLAGS_DF|ADFLAGS_HF);
+         return AFPERR_MISC;
+     }
+     (void)get_id(vol, adp, &st, dir->d_did, upath, strlen(upath));
 -    ad_flush( adp);
 -    ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
 +    ad_flush(&ad);
 +    ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
  
  createfile_done:
      curdir->offcnt++;
  
 -#ifdef DROPKLUDGE
 -    if (vol->v_flags & AFPVOL_DROPBOX) {
 -        retvalue = matchfile2dirperms(upath, vol, did);
 -    }
 -#endif /* DROPKLUDGE */
 -
      setvoltime(obj, vol );
  
      return (retvalue);
@@@ -939,7 -987,7 +954,7 @@@ int setfilparams(struct vol *vol
  
      /* second try with adouble open 
      */
 -    if ( ad_open_metadata( upath, 0, O_CREAT, adp) < 0) {
 +    if ( ad_open(adp, upath, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) < 0) {
          LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error");
          /*
           * For some things, we don't need an adouble header:
          }
          LOG(log_debug, logtype_afpd, "setfilparams: no adouble perms, but only FILPBIT_MDATE and/or FILPBIT_UNIXPR");
          isad = 0;
 -    } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) {
 +    } else if ((ad_get_MD_flags( adp ) & O_CREAT) ) {
          ad_setname(adp, path->m_name);
      }
      
@@@ -1033,6 -1081,7 +1048,6 @@@ setfilparam_done
      if (isad) {
          ad_flush( adp);
          ad_close_metadata( adp);
 -
      }
  
      if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
@@@ -1063,6 -1112,9 +1078,9 @@@ int renamefile(const struct vol *vol, i
  {
      int               rc;
  
+     LOG(log_debug, logtype_afpd,
+         "renamefile: src[%d, \"%s\"] -> dst[\"%s\"]", sdir_fd, src, dst);
      if ( unix_rename( sdir_fd, src, -1, dst ) < 0 ) {
          switch ( errno ) {
          case ENOENT :
          }
      }
  
 -    /* don't care if we can't open the newly renamed ressource fork
 -     */
 -    if (!ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) {
 +    /* don't care if we can't open the newly renamed ressource fork */
 +    if (ad_open(adp, dst, ADFLAGS_HF, O_RDWR) == 0) {
          ad_setname(adp, newname);
          ad_flush( adp );
          ad_close( adp, ADFLAGS_HF );
@@@ -1244,11 -1297,11 +1262,11 @@@ int afp_copyfile(AFPObj *obj, char *ibu
  
      adp = of_ad(s_vol, s_path, &ad);
  
 -    if (ad_open(s_path->u_name , ADFLAGS_DF |ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) {
 +    if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) {
          return AFPERR_DENYCONF;
      }
 -    denyreadset = (getforkmode(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || 
 -                  getforkmode(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
 +    denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || 
 +                  ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 );
  
      if (denyreadset) {
          retvalue = AFPERR_DENYCONF;
          goto copy_exit;
      }
  
 -#ifdef FORCE_UIDGID
 -    /* FIXME svid != dvid && dvid's user can't read svid */
 -#endif
      if (NULL == ( d_vol = getvolbyvid( dvid )) ) {
          retvalue = AFPERR_PARAM;
          goto copy_exit;
      }
      curdir->offcnt++;
  
 -#ifdef DROPKLUDGE
 -    if (vol->v_flags & AFPVOL_DROPBOX) {
 -        retvalue=matchfile2dirperms(upath, vol, ddid); /* FIXME sdir or ddid */
 -    }
 -#endif /* DROPKLUDGE */
 -
      setvoltime(obj, d_vol );
  
  copy_exit:
@@@ -1446,7 -1508,7 +1464,7 @@@ int copyfile(const struct vol *s_vol
          adflags |= ADFLAGS_HF;
      }
  
 -    if (ad_openat(sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) {
 +    if (ad_openat(adp, sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) {
          ret_err = errno;
          goto done;
      }
      }
  
      ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options);
 -    if (ad_open(dst , adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, &add) < 0) {
 +    if (ad_open(&add, dst, adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, O_RDWR|O_CREAT|O_EXCL, st.st_mode) < 0) {
          ret_err = errno;
          ad_close( adp, adflags );
          if (EEXIST != ret_err) {
@@@ -1579,7 -1641,7 +1597,7 @@@ int deletefile(const struct vol *vol, i
           * moreover sometimes deletefile is called with a no existent file and 
           * ad_open would create a 0 byte resource fork
          */
 -        if ( ad_metadataat(dirfd, file, ADFLAGS_OPENFORKS, &ad) == 0 ) {
 +        if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
              if ((err = check_attrib(&ad))) {
                 ad_close_metadata(&ad);
                 return err;
   
      /* try to open both forks at once */
      adflags = ADFLAGS_DF;
 -    if ( ad_openat(dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, 0, &ad ) < 0 ) {
 +    if ( ad_openat(&ad, dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0 ) {
          switch (errno) {
          case ENOENT:
              err = AFPERR_NOOBJ;
@@@ -1733,12 -1795,32 +1751,12 @@@ static int reenumerate_loop(struct dire
      cnid_t        did  = param->did;
      cnid_t      aint;
      
 -    if ( lstat(de->d_name, &path.st)<0 )
 +    if ( lstat(de->d_name, &path.st) < 0 )
          return 0;
      
      /* update or add to cnid */
      aint = cnid_add(vol->v_cdb, &path.st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */
  
 -#if AD_VERSION > AD_VERSION1
 -    if (aint != CNID_INVALID && !S_ISDIR(path.st.st_mode)) {
 -        struct adouble  ad, *adp;
 -
 -        path.st_errno = 0;
 -        path.st_valid = 1;
 -        path.u_name = de->d_name;
 -            
 -        adp = of_ad(vol, &path, &ad);
 -            
 -        if ( ad_open_metadata( de->d_name, 0, 0, adp ) < 0 ) {
 -            return 0;
 -        }
 -        if (ad_setid(adp, path.st.st_dev, path.st.st_ino, aint, did, vol->v_stamp)) {
 -            ad_flush(adp);
 -        }
 -        ad_close_metadata(adp);
 -    }
 -#endif /* AD_VERSION > AD_VERSION1 */
 -
      return 0;
  }
  
@@@ -2000,7 -2082,7 +2018,7 @@@ static struct adouble *find_adouble(str
          adp = (*of)->of_ad;
      }
      else {
 -        ret = ad_open( path->u_name, ADFLAGS_HF, O_RDONLY, 0, adp);
 +        ret = ad_open(adp, path->u_name, ADFLAGS_HF, O_RDONLY);
          /* META and HF */
          if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) {
              /* from AFP spec.
diff --combined etc/afpd/filedir.c
index bb2bdd1dd0011f21d0e9c001e981d9dd2f34cc76,8eb8bb4d8d12ede44f8550bf43207d4656b3416c..1478299e262d297946cf9eed86434e6589c7d6b9
@@@ -9,7 -9,24 +9,7 @@@
  
  #include <stdio.h>
  #include <stdlib.h>
 -/* STDC check */
 -#if STDC_HEADERS
  #include <string.h>
 -#else /* STDC_HEADERS */
 -#ifndef HAVE_STRCHR
 -#define strchr index
 -#define strrchr index
 -#endif /* HAVE_STRCHR */
 -char *strchr (), *strrchr ();
 -#ifndef HAVE_MEMCPY
 -#define memcpy(d,s,n) bcopy ((s), (d), (n))
 -#define memmove(d,s,n) bcopy ((s), (d), (n))
 -#endif /* ! HAVE_MEMCPY */
 -#endif /* STDC_HEADERS */
 -
 -#ifdef HAVE_STRINGS_H
 -#include <strings.h>
 -#endif
  #include <errno.h>
  #include <sys/param.h>
  
  #include "filedir.h"
  #include "unix.h"
  
 -#ifdef DROPKLUDGE
 -int matchfile2dirperms(
 -/* Since it's kinda' big; I decided against an
 -   inline function */
 -    char    *upath,
 -    struct vol  *vol,
 -    int     did)
 -/* The below code changes the way file ownership is determined in the name of
 -   fixing dropboxes.  It has known security problem.  See the netatalk FAQ for
 -   more information */
 -{
 -    struct stat st, sb;
 -    struct dir  *dir;
 -    char    *adpath;
 -    uid_t       uid;
 -    int         ret = AFP_OK;
 -#ifdef DEBUG
 -    LOG(log_debug9, logtype_afpd, "begin matchfile2dirperms:");
 -#endif
 -
 -    if (stat(upath, &st ) < 0) {
 -        LOG(log_error, logtype_afpd, "Could not stat %s: %s", upath, strerror(errno));
 -        return AFPERR_NOOBJ ;
 -    }
 -
 -    adpath = vol->vfs->ad_path( upath, ADFLAGS_HF );
 -    /* FIXME dirsearch doesn't move cwd to did ! */
 -    if (( dir = dirlookup( vol, did )) == NULL ) {
 -        LOG(log_error, logtype_afpd, "matchfile2dirperms: Unable to get directory info.");
 -        ret = AFPERR_NOOBJ;
 -    }
 -    else if (stat(".", &sb) < 0) {
 -        LOG(log_error, logtype_afpd,
 -            "matchfile2dirperms: Error checking directory \"%s\": %s",
 -            dir->d_m_name, strerror(errno));
 -        ret = AFPERR_NOOBJ;
 -    }
 -    else {
 -        uid=geteuid();
 -        if ( uid != sb.st_uid )
 -        {
 -            seteuid(0);
 -            if (lchown(upath, sb.st_uid, sb.st_gid) < 0)
 -            {
 -                LOG(log_error, logtype_afpd,
 -                    "matchfile2dirperms(%s): Error changing owner/gid: %s",
 -                    upath, strerror(errno));
 -                ret = AFPERR_ACCESS;
 -            }
 -            else if ((!S_ISLNK(st->st_mode)) && (chmod(upath,(st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0))
 -            {
 -                LOG(log_error, logtype_afpd,
 -                    "matchfile2dirperms(%s): Error adding file read permissions: %s",
 -                    upath, strerror(errno));
 -                ret = AFPERR_ACCESS;
 -            }
 -            else if (lchown(adpath, sb.st_uid, sb.st_gid) < 0)
 -            {
 -                LOG(log_error, logtype_afpd,
 -                    "matchfile2dirperms(%s): Error changing AppleDouble owner/gid: %s",
 -                    adpath, strerror(errno));
 -                ret = AFPERR_ACCESS;
 -            }
 -            else if (chmod(adpath, (st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0)
 -            {
 -                LOG(log_error, logtype_afpd,
 -                    "matchfile2dirperms(%s):  Error adding AD file read permissions: %s",
 -                    adpath, strerror(errno));
 -                ret = AFPERR_ACCESS;
 -            }
 -            seteuid(uid);
 -        }
 -    } /* end else if stat success */
 -
 -#ifdef DEBUG
 -    LOG(log_debug9, logtype_afpd, "end matchfile2dirperms:");
 -#endif
 -    return ret;
 -}
 -#endif
 -
  int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
  {
      struct stat     *st;
@@@ -230,7 -328,7 +230,7 @@@ static int moveandrename(const struct v
                           char *newname,
                           int isdir)
  {
-     char            *p;
+     char            *oldunixname = NULL;
      char            *upath;
      int             rc;
      struct stat     *st, nst;
      cnid_t          id;
      int             cwd_fd = -1;
  
+     LOG(log_debug, logtype_afpd,
+         "moveandrename: [\"%s\"/\"%s\"] -> \"%s\"",
+         cfrombstr(sdir->d_u_name), oldname, newname);
      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
      adp = &ad;
      adflags = 0;
  
      if (!isdir) {
-         if ((p = mtoupath(vol, oldname, sdir->d_did, utf8_encoding())) == NULL)
+         if ((oldunixname = strdup(mtoupath(vol, oldname, sdir->d_did, utf8_encoding()))) == NULL)
              return AFPERR_PARAM; /* can't convert */
+         id = cnid_get(vol->v_cdb, sdir->d_did, oldunixname, strlen(oldunixname));
  
- #ifndef HAVE_RENAMEAT
+ #ifndef HAVE_ATFUNCS
          /* Need full path */
-         id = cnid_get(vol->v_cdb, sdir->d_did, p, strlen(p));
-         p = ctoupath( vol, sdir, oldname );
-         if (!p)
+         free(oldunixname);
+         if ((oldunixname = strdup(ctoupath(vol, sdir, oldname))) == NULL)
              return AFPERR_PARAM; /* pathname too long */
- #endif /* HAVE_RENAMEAT */
+ #endif /* HAVE_ATFUNCS */
  
          path.st_valid = 0;
-         path.u_name = p;
- #ifdef HAVE_RENAMEAT
+         path.u_name = oldunixname;
+ #ifdef HAVE_ATFUNCS
          opened = of_findnameat(sdir_fd, &path);
  #else
          opened = of_findname(&path);
- #endif /* HAVE_RENAMEAT */
+ #endif /* HAVE_ATFUNCS */
          if (opened) {
              /* reuse struct adouble so it won't break locks */
              adp = opened->of_ad;
          }
      } else {
          id = sdir->d_did; /* we already have the CNID */
-         p = ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname );
-         if (!p) {
+         if ((oldunixname = strdup(ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname))) == NULL)
              return AFPERR_PARAM;
-         }
          adflags = ADFLAGS_DIR;
      }
  
      /*
-      * p now points to either
+      * oldunixname now points to either
       *   a) full pathname of the source fs object (if renameat is not available)
       *   b) the oldname (renameat is available)
       * we are in the dest folder so we need to use 
-      *   a) p for ad_open
+      *   a) oldunixname for ad_open
       *   b) fchdir sdir_fd before eg ad_open or use *at functions where appropiate
       */
  
              goto exit;
          }
      }
-     if (!ad_metadata(p, adflags, adp)) {
+     if (!ad_metadata(oldunixname, adflags, adp)) {
          u_int16_t bshort;
  
          ad_getattr(adp, &bshort);
 +        
          ad_close_metadata( adp);
          if ((bshort & htons(ATTRBIT_NORENAME))) {
              rc = AFPERR_OLOCK;
          }
  
          if (stat(upath, st) == 0 || caseenumerate(vol, &path, curdir) == 0) {
-             if (!stat(p, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) {
+             if (!stat(oldunixname, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) {
                  /* not the same file */
                  rc = AFPERR_EXIST;
                  goto exit;
          if (of_findname(&path)) {
              rc = AFPERR_EXIST; /* was AFPERR_BUSY; */
          } else {
-             rc = renamefile(vol, sdir_fd, p, upath, newname, adp );
+             rc = renamefile(vol, sdir_fd, oldunixname, upath, newname, adp );
              if (rc == AFP_OK)
                  of_rename(vol, opened, sdir, oldname, curdir, newname);
          }
      } else {
-         rc = renamedir(vol, sdir_fd, p, upath, sdir, curdir, newname);
+         rc = renamedir(vol, sdir_fd, oldunixname, upath, sdir, curdir, newname);
      }
      if ( rc == AFP_OK && id ) {
          /* renaming may have moved the file/dir across a filesystem */
              (void)dir_remove(vol, cacheddir);
          }
  
+         /* Fixup adouble info */
+         if (!ad_metadata(upath, adflags, adp)) {
+             ad_setid(adp, st->st_dev, st->st_ino, id, curdir->d_did, vol->v_stamp);
+             ad_flush(adp);
+             ad_close_metadata(adp);
+         }
          /* fix up the catalog entry */
          cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath));
      }
  exit:
      if (cwd_fd != -1)
          close(cwd_fd);
+     if (oldunixname)
+         free(oldunixname);
      return rc;
  }
  
@@@ -568,6 -678,9 +581,6 @@@ int afp_moveandrename(AFPObj *obj, cha
      int         plen;
      u_int16_t   vid;
      int         rc;
 -#ifdef DROPKLUDGE
 -    int     retvalue;
 -#endif /* DROPKLUDGE */
      int     sdir_fd = -1;
  
  
          memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) + 1);
      }
  
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if ((sdir_fd = open(".", O_RDONLY)) == -1)
          return AFPERR_MISC;
  #endif
          }
          curdir->offcnt++;
          sdir->offcnt--;
 -#ifdef DROPKLUDGE
 -        if (vol->v_flags & AFPVOL_DROPBOX) {
 -            /* FIXME did is not always the source id */
 -            if ((retvalue=matchfile2dirperms (upath, vol, did)) != AFP_OK) {
 -                rc = retvalue;
 -                goto exit;
 -            }
 -        }
 -        else
 -#endif /* DROPKLUDGE */
 -            /* if unix priv don't try to match perm with dest folder */
 -            if (!isdir && !vol_unix_priv(vol)) {
 -                int  admode = ad_mode("", 0777) | vol->v_fperm;
 +        /* if unix priv don't try to match perm with dest folder */
 +        if (!isdir && !vol_unix_priv(vol)) {
 +            int  admode = ad_mode("", 0777) | vol->v_fperm;
  
 -                setfilmode(upath, admode, NULL, vol->v_umask);
 -                vol->vfs->vfs_setfilmode(vol, upath, admode, NULL);
 -            }
 +            setfilmode(upath, admode, NULL, vol->v_umask);
 +            vol->vfs->vfs_setfilmode(vol, upath, admode, NULL);
 +        }
          setvoltime(obj, vol );
      }
  
  exit:
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if (sdir_fd != -1)
          close(sdir_fd);
  #endif
diff --combined etc/afpd/fork.h
index c1060dbe3492f569f57a28b0c296e436a85ceb84,7ea7a8a6edc56e52424897ce07616847224f4886..e950aa0ffdf6aa72cb47d8e167ab078ca32fcd41
@@@ -7,8 -7,9 +7,8 @@@
  #define AFPD_FORK_H 1
  
  #include <stdio.h>
 -#include <sys/cdefs.h>
 +#include <arpa/inet.h>
  
 -#include <netatalk/endian.h>
  #include <atalk/adouble.h>
  #include "volume.h"
  #include "directory.h"
@@@ -64,20 -65,23 +64,21 @@@ extern int          of_rename    (cons
                                            struct dir *, const char *,
                                            struct dir *, const char *);
  extern int          of_flush     (const struct vol *);
 -extern void         of_pforkdesc (FILE *);
  extern int          of_stat      (struct path *);
  extern int          of_statdir   (struct vol *vol, struct path *);
  extern int          of_closefork (struct ofork *ofork);
  extern void         of_closevol  (const struct vol *vol);
+ extern void         of_close_all_forks(void);
  extern struct adouble *of_ad     (const struct vol *, struct path *, struct adouble *);
  
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
  extern struct ofork *of_findnameat(int dirfd, struct path *path);
  extern int of_fstatat(int dirfd, struct path *path);
- #endif  /* HAVE_RENAMEAT */
+ #endif  /* HAVE_ATFUNCS */
  
  
  /* in fork.c */
  extern int          flushfork    (struct ofork *);
 -extern int          getforkmode  (struct adouble *, int , int );
  
  /* FP functions */
  int afp_openfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
diff --combined etc/afpd/globals.h
index 3a9c229c4ad077e7d1ee82cce6b8feffed294f99,02dcf8b56b58abd1dd00d02dbe44452a2c19a3e4..4d81463d44dfadc860fa71a4fca423e7daa32820
@@@ -7,6 -7,7 +7,6 @@@
  #define AFPD_GLOBALS_H 1
  
  #include <sys/param.h>
 -#include <sys/cdefs.h>
  
  #ifdef ADMIN_GRP
  #include <grp.h>
  #include <atalk/unicode.h>
  #include <atalk/uam.h>
  
- #define MACFILELEN 31
+ /* #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_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 {
@@@ -50,9 -65,12 +56,11 @@@ 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;
@@@ -98,6 -116,10 +106,6 @@@ typedef struct _AFPObj 
      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 */
@@@ -136,6 -158,9 +144,6 @@@ 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 */
diff --combined etc/afpd/ofork.c
index c3ca09c10cc5d4bc4df16c2e258e9524f0505ff4,e65c4024f530077f8db5cd3416735c81bcdc21fc..7e2d3d57630a3b28a76011d227db44abacc8a5e0
@@@ -69,6 -69,22 +69,6 @@@ static void of_unhash(struct ofork *of
      }
  }
  
 -#ifdef DEBUG1
 -void of_pforkdesc( FILE *f)
 -{
 -    int ofrefnum;
 -
 -    if (!oforks)
 -        return;
 -
 -    for ( ofrefnum = 0; ofrefnum < nforks; ofrefnum++ ) {
 -        if ( oforks[ ofrefnum ] != NULL ) {
 -            fprintf( f, "%hu <%s>\n", ofrefnum, of_name(oforks[ ofrefnum ]));
 -        }
 -    }
 -}
 -#endif
 -
  int of_flush(const struct vol *vol)
  {
      int refnum;
@@@ -195,7 -211,7 +195,7 @@@ of_alloc(struct vol *vol
             ad_open really does reinitialize the structure. */
          ad_init(ad, vol->v_adouble, vol->v_ad_options);
  
-         ad->ad_m_namelen = 255 +1;
+         ad->ad_m_namelen = UTF8FILELEN_EARLY +1;
          /* here's the deal: we allocate enough for the standard mac file length.
           * in the future, we'll reallocate in fairly large jumps in case
           * of long unicode names */
              return NULL;
          }
          strlcpy( ad->ad_m_name, path, ad->ad_m_namelen);
 -    } else {
 -        /* Increase the refcount on this struct adouble. This is
 -           decremented again in oforc_dealloc. */
 -        ad->ad_refcount++;
      }
  
 +    ad_ref(ad);
      of->of_ad = ad;
      of->of_vol = vol;
      of->of_did = dir->d_did;
@@@ -253,7 -272,7 +253,7 @@@ int of_stat(struct path *path
  }
  
  
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
  int of_fstatat(int dirfd, struct path *path)
  {
      int ret;
  
     return ret;
  }
- #endif /* HAVE_RENAMEAT */
+ #endif /* HAVE_ATFUNCS */
  
  /* -------------------------- 
     stat the current directory.
@@@ -346,7 -365,7 +346,7 @@@ struct ofork *of_findname(struct path *
   * @param dirfd     (r) directory fd
   * @param path      (rw) pointer to struct path
   */
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
  struct ofork *of_findnameat(int dirfd, struct path *path)
  {
      struct ofork *of;
@@@ -379,6 -398,17 +379,6 @@@ void of_dealloc( struct ofork *of
  
      of_unhash(of);
      oforks[ of->of_refnum % nforks ] = NULL;
 -
 -    /* decrease refcount */
 -    of->of_ad->ad_refcount--;
 -
 -    if ( of->of_ad->ad_refcount <= 0) {
 -        free( of->of_ad->ad_m_name );
 -        free( of->of_ad);
 -    } else {/* someone's still using it. just free this user's locks */
 -        ad_unlock(of->of_ad, of->of_refnum);
 -    }
 -
      free( of );
  }
  
  int of_closefork(struct ofork *ofork)
  {
      struct timeval      tv;
 -    int         adflags, doflush = 0;
 +    int         doflush = 0;
      int                 ret;
  
 -    adflags = 0;
 -    if ((ofork->of_flags & AFPFORK_DATA) && (ad_data_fileno( ofork->of_ad ) != -1)) {
 -        adflags |= ADFLAGS_DF;
 -    }
      if ( (ofork->of_flags & AFPFORK_OPEN) && ad_reso_fileno( ofork->of_ad ) != -1 ) {
 -        adflags |= ADFLAGS_HF;
          /*
           * Only set the rfork's length if we're closing the rfork.
           */
          }
      }
      ret = 0;
 -    if ( ad_close( ofork->of_ad, adflags ) < 0 ) {
 -        ret = -1;
 +
 +    ad_unlock(ofork->of_ad, ofork->of_refnum);
 +    
 +    if (ad_unref(ofork->of_ad) == 0) {
 +        if ( ad_close( ofork->of_ad, 0 ) < 0 ) {
 +            ret = -1;
 +        }
      }
  
      of_dealloc( ofork );
@@@ -455,3 -485,23 +455,23 @@@ void of_closevol(const struct vol *vol
      return;
  }
  
+ /* ----------------------
+    close all forks for a volume
+ */
+ void of_close_all_forks(void)
+ {
+     int refnum;
+     if (!oforks)
+         return;
+     for ( refnum = 0; refnum < nforks; refnum++ ) {
+         if (oforks[ refnum ] != NULL) {
+             if (of_closefork( oforks[ refnum ]) < 0 ) {
+                 LOG(log_error, logtype_afpd, "of_close_all_forks: %s", strerror(errno) );
+             }
+         }
+     }
+     return;
+ }
diff --combined etc/afpd/status.c
index 1037f15a0c591c1d09d33ae062278f46eac58e65,cbf59892c157143fb74d9fef60b0de4f12a04bb1..24b6b8077a9223203a4fe4e78e817ee29113aa61
  #endif /* BSD4_4 */
  #endif
  
 -#include <netatalk/at.h>
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/dsi.h>
 -#include <atalk/atp.h>
 -#include <atalk/asp.h>
 -#include <atalk/nbp.h>
  #include <atalk/unicode.h>
  #include <atalk/util.h>
  
@@@ -82,13 -85,14 +82,13 @@@ static int status_server(char *data, co
  
      /* extract the obj part of the server */
      Obj = (char *) server;
 -    nbp_name(server, &Obj, &Type, &Zone);
      if ((size_t)-1 == (len = convert_string( 
 -                      options->unixcharset, options->maccharset, 
 -                      Obj, -1, buf, sizeof(buf))) ) {
 -      len = MIN(strlen(Obj), 31);
 +                           options->unixcharset, options->maccharset, 
 +                           Obj, -1, buf, sizeof(buf))) ) {
 +        len = MIN(strlen(Obj), 31);
        *data++ = len;
        memcpy( data, Obj, len );
 -      LOG ( log_error, logtype_afpd, "Could not set servername, using fallback");
 +        LOG ( log_error, logtype_afpd, "Could not set servername, using fallback");
      } else {
        *data++ = len;
        memcpy( data, buf, len );
@@@ -169,7 -173,7 +169,7 @@@ static u_int16_t status_signature(char 
  }
  
  static size_t status_netaddress(char *data, int *servoffset,
 -                             const ASP asp, const DSI *dsi,
 +                             const DSI *dsi,
                               const struct afp_options *options)
  {
      char               *begin;
      /* number of addresses. this currently screws up if we have a dsi
         connection, but we don't have the ip address. to get around this,
         we turn off the status flag for tcp/ip. */
 -    *data++ = ((options->fqdn && dsi)? 1 : 0) + (dsi ? 1 : 0) + (asp ? 1 : 0) +
 +    *data++ = ((options->fqdn && dsi)? 1 : 0) + (dsi ? 1 : 0) +
                (((options->flags & OPTION_ANNOUNCESSH) && options->fqdn && dsi)? 1 : 0);
  
      /* ip address */
          }
      }
  
 -#ifndef NO_DDP
 -    if (asp) {
 -        const struct sockaddr_at *ddpaddr = atp_sockaddr(asp->asp_atp);
 -
 -        /* ddp address */
 -        *data++ = 6;
 -        *data++ = 0x03; /* ddp address */
 -        memcpy(data, &ddpaddr->sat_addr.s_net, sizeof(ddpaddr->sat_addr.s_net));
 -        data += sizeof(ddpaddr->sat_addr.s_net);
 -        memcpy(data, &ddpaddr->sat_addr.s_node,
 -               sizeof(ddpaddr->sat_addr.s_node));
 -        data += sizeof(ddpaddr->sat_addr.s_node);
 -        memcpy(data, &ddpaddr->sat_port, sizeof(ddpaddr->sat_port));
 -        data += sizeof(ddpaddr->sat_port);
 -    }
 -#endif /* ! NO_DDP */
 -
      /* calculate/store Directory Services Names offset */
      offset = htons(data - begin); 
      *servoffset += sizeof(offset);
@@@ -353,15 -374,18 +353,15 @@@ static size_t status_utf8servername(cha
  
      /* extract the obj part of the server */
      Obj = (char *) (options->server ? options->server : options->hostname);
 -    nbp_name(options->server ? options->server : options->hostname, &Obj, &Type, &Zone);
 -
      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");
 +                            options->unixcharset, CH_UTF8_MAC, 
 +                            Obj, -1, data+sizeof(namelen), maxstatuslen-offset )) ) {
 +        LOG ( log_error, logtype_afpd, "Could not set utf8 servername");
  
 -      /* set offset to 0 */
 -      memset(begin + *nameoffset, 0, sizeof(offset));
 +        /* set offset to 0 */
 +        memset(begin + *nameoffset, 0, sizeof(offset));
          data = begin + offset;
 -    }
 -    else {
 +    } else {
        namelen = htons(len);
        memcpy( data, &namelen, sizeof(namelen));
        data += sizeof(namelen);
@@@ -401,16 -425,24 +401,16 @@@ static void status_icon(char *data, con
  
  /* ---------------------
   */
 -void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig,
 +void status_init(AFPConfig *dsiconfig,
                   const struct afp_options *options)
  {
 -    ASP asp;
      DSI *dsi;
      char *status = NULL;
      size_t statuslen;
      int c, sigoff, ipok;
  
 -    if (!(aspconfig || dsiconfig) || !options)
 +    if (!dsiconfig || !options)
          return;
 -
 -    if (aspconfig) {
 -        status = aspconfig->status;
 -        maxstatuslen=sizeof(aspconfig->status);
 -        asp = aspconfig->obj.handle;
 -    } else
 -        asp = NULL;
        
      ipok = 0;
      if (dsiconfig) {
      c = status_server(status, options->server ? options->server :
                        options->hostname, options);
      status_machine(status);
 -    status_versions(status, asp, dsi);
 +    status_versions(status, dsi);
      status_uams(status, options->uamlist);
      if (options->flags & OPTION_CUSTOMICON)
          status_icon(status, icon, sizeof(icon), c);
      sigoff = status_signature(status, &c, options);
      /* c now contains the offset where the netaddress offset lives */
  
 -    status_netaddress(status, &c, asp, dsi, options);
 +    status_netaddress(status, &c, dsi, options);
      /* c now contains the offset where the Directory Names Count offset lives */
  
      statuslen = status_directorynames(status, &c, dsi, options);
      if ( statuslen < maxstatuslen) 
          statuslen = status_utf8servername(status, &c, dsi, options);
  
 -#ifndef NO_DDP
 -    if (aspconfig) {
 -        if (dsiconfig) /* status is dsiconfig->status */
 -            memcpy(aspconfig->status, status, statuslen);
 -        asp_setstatus(asp, status, statuslen);
 -        aspconfig->signature = status + sigoff;
 -        aspconfig->statuslen = statuslen;
 -    }
 -#endif /* ! NO_DDP */
 -
      if (dsiconfig) {
          if ((options->flags & OPTION_CUSTOMICON) == 0) {
              status_icon(status, apple_tcp_icon, sizeof(apple_tcp_icon), 0);
@@@ -609,14 -651,14 +609,14 @@@ server_signature_auto
                  options->sigconffile, strerror(errno));
              goto server_signature_random;
          }
-     } else { /* conf file don't exist */
+     } else {                                                          /* conf file don't exist */
          if (( fd = creat(options->sigconffile, 0644 )) < 0 ) {
-             LOG(log_error, logtype_atalkd, "Cannot create %s (%s). Using one-time signature.",
+             LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s). Using one-time signature.",
                  options->sigconffile, strerror(errno));
              goto server_signature_random;
          }
          if (( fp = fdopen( fd, "w" )) == NULL ) {
-             LOG(log_error, logtype_atalkd, "Cannot fdopen %s (%s). Using one-time signature.",
+             LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s). Using one-time signature.",
                  options->sigconffile, strerror(errno));
              close(fd);
              goto server_signature_random;
diff --combined etc/afpd/unix.c
index efc72923f6606a277674487317e702602f8b9d1d,f604d79b8258a44ccdb5b228d18c543f40bda77c..232fb30349e328b366bdfd1758c6b3c1a38645b5
@@@ -9,7 -9,24 +9,7 @@@
  
  #include <stdio.h>
  #include <stdlib.h>
 -
 -/* STDC check */
 -#ifdef STDC_HEADERS
  #include <string.h>
 -#else /* STDC_HEADERS */
 -
 -#ifndef HAVE_STRCHR
 -#define strchr index
 -#define strrchr index
 -#endif /* HAVE_STRCHR */
 -char *strchr (), *strrchr ();
 -
 -#ifndef HAVE_MEMCPY
 -#define memcpy(d,s,n) bcopy ((s), (d), (n))
 -#define memmove(d,s,n) bcopy ((s), (d), (n))
 -#endif /* ! HAVE_MEMCPY */
 -#endif /* STDC_HEADERS */
 -
  #include <errno.h>
  #include <limits.h>
  #include <sys/param.h>
@@@ -140,6 -157,7 +140,7 @@@ mode_t mode
  }
  
  #ifdef accessmode
  #undef accessmode
  #endif
  /*
@@@ -314,6 -332,9 +315,6 @@@ int setfilunixmode (const struct vol *v
  /* --------------------- */
  int setdirunixmode(const struct vol *vol, const char *name, mode_t mode)
  {
 -
 -    int dropbox = (vol->v_flags & AFPVOL_DROPBOX);
 -
      LOG(log_debug, logtype_afpd, "setdirunixmode('%s', mode:%04o) {v_dperm:%04o}",
          fullpathname(name), mode, vol->v_dperm);
  
  
      if (dir_rx_set(mode)) {
        /* extending right? dir first then .AppleDouble in rf_setdirmode */
 -      if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 )
 +      if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 )
                return -1;
      }
      if (vol->vfs->vfs_setdirunixmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) {
          return  -1 ;
      }
      if (!dir_rx_set(mode)) {
 -      if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 )
 +      if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 )
              return -1;
      }
      return 0;
@@@ -341,13 -362,15 +342,13 @@@ int setdirmode(const struct vol *vol, c
      struct dirent     *dirp;
      DIR                       *dir;
      mode_t              hf_mode;
 -    int                 osx = vol->v_adouble == AD_VERSION2_OSX;
 -    int                 dropbox = (vol->v_flags & AFPVOL_DROPBOX);
      
      mode |= vol->v_dperm;
      hf_mode = ad_hf_mode(mode);
  
      if (dir_rx_set(mode)) {
        /* extending right? dir first */
 -      if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 )
 +      if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 )
                return -1;
      }
      
  
      for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
          /* FIXME */
 -        if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) {
 +        if (*dirp->d_name == '.') {
              continue;
          }
          if ( lstat( dirp->d_name, &st ) < 0 ) {
          }
  
          if (!S_ISDIR(st.st_mode)) {
 -           int setmode = (osx && *dirp->d_name == '.')?hf_mode:mode;
 -
 -           if (setfilmode(dirp->d_name, setmode, &st, vol->v_umask) < 0) {
 +           if (setfilmode(dirp->d_name, mode, &st, vol->v_umask) < 0) {
                  LOG(log_error, logtype_afpd, "setdirmode: chmod %s: %s",dirp->d_name, strerror(errno) );
                  return -1;
             }
      }
  
      if (!dir_rx_set(mode)) {
 -      if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 )
 +      if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 )
                return -1;
      }
      return( 0 );
@@@ -485,12 -510,13 +486,12 @@@ int setdirowner(const struct vol *vol, 
      struct stat               st;
      struct dirent     *dirp;
      DIR                       *dir;
 -    int                 osx = vol->v_adouble == AD_VERSION2_OSX;
  
      if (( dir = opendir( name )) == NULL ) {
          return( -1 );
      }
      for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) {
 -        if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) {
 +        if ( *dirp->d_name == '.') {
              continue;
          }
          if ( lstat( dirp->d_name, &st ) < 0 ) {
diff --combined etc/afpd/volume.c
index 2970bcc3b25e4ae343491f83951d7b0d4c302ec3,b73d13c239ece87e8494c127dde753bc8ea7c235..60fc73e9073292a3452a03559022769b616a459e
  #include <grp.h>
  #include <utime.h>
  #include <errno.h>
 -#ifdef HAVE_STRINGS_H
 -#include <strings.h>
 -#endif
 -/* STDC check */
 -#if STDC_HEADERS
  #include <string.h>
 -#else /* STDC_HEADERS */
 -#ifndef HAVE_STRCHR
 -#define strchr index
 -#define strrchr index
 -#endif /* HAVE_STRCHR */
 -char *strchr (), *strrchr ();
 -#ifndef HAVE_MEMCPY
 -#define memcpy(d,s,n) bcopy ((s), (d), (n))
 -#define memmove(d,s,n) bcopy ((s), (d), (n))
 -#endif /* ! HAVE_MEMCPY */
 -#endif /* STDC_HEADERS */
  #include <sys/param.h>
  #include <sys/socket.h>
  #include <netinet/in.h>
  #include <arpa/inet.h>
  
 -#include <atalk/asp.h>
  #include <atalk/dsi.h>
  #include <atalk/adouble.h>
  #include <atalk/afp.h>
  #include <atalk/logger.h>
  #include <atalk/vfs.h>
  #include <atalk/uuid.h>
 +#include <atalk/ea.h>
+ #include <atalk/bstrlib.h>
+ #include <atalk/bstradd.h>
  
 -
  #ifdef CNID_DB
  #include <atalk/cnid.h>
  #endif /* CNID_DB*/
@@@ -95,7 -114,15 +97,7 @@@ static void             free_extmap(voi
  #define VOLOPT_MACCHARSET    16
  #define VOLOPT_CNIDSCHEME    17
  #define VOLOPT_ADOUBLE       18  /* adouble version */
 -
 -#ifdef FORCE_UIDGID
 -#warning UIDGID
 -#include "uid.h"
 -
 -#define VOLOPT_FORCEUID      19  /* force uid for username x */
 -#define VOLOPT_FORCEGID      20  /* force gid for group x */
 -#endif /* FORCE_UIDGID */
 -
 +/* Usable slot: 19/20 */
  #define VOLOPT_UMASK         21
  #define VOLOPT_ALLOWED_HOSTS 22
  #define VOLOPT_DENIED_HOSTS  23
@@@ -127,7 -154,12 +129,7 @@@ typedef struct _special_folder 
  
  static const _special_folder special_folders[] = {
      {"Network Trash Folder",     1,  0777,  1},
 -    {"Temporary Items",          1,  0777,  1},
      {".AppleDesktop",            1,  0777,  0},
 -#if 0
 -    {"TheFindByContentFolder",   0,     0,  1},
 -    {"TheVolumeSettingsFolder",  0,     0,  1},
 -#endif
      {NULL, 0, 0, 0}};
  
  /* Forward declarations */
@@@ -135,6 -167,8 +137,8 @@@ static void handle_special_folders (con
  static void deletevol(struct vol *vol);
  static void volume_free(struct vol *vol);
  static void check_ea_sys_support(struct vol *vol);
+ static char *get_vol_uuid(const AFPObj *obj, const char *volname);
+ static int readvolfile(AFPObj *obj, struct afp_volume_name *p1,char *p2, int user, struct passwd *pwent);
  
  static void volfree(struct vol_option *options, const struct vol_option *save)
  {
@@@ -239,12 -273,22 +243,12 @@@ static char *volxlate(AFPObj *obj
          } else if (is_var(p, "$c")) {
              if (afpmaster && xlatevolname)
                  return NULL;
 -            if (obj->proto == AFPPROTO_ASP) {
 -                ASP asp = obj->handle;
 -
 -                len = sprintf(dest, "%u.%u", ntohs(asp->asp_sat.sat_addr.s_net),
 -                              asp->asp_sat.sat_addr.s_node);
 -                dest += len;
 -                destlen -= len;
 -
 -            } else if (obj->proto == AFPPROTO_DSI) {
 -                DSI *dsi = obj->handle;
 -                len = sprintf(dest, "%s:%u",
 -                              getip_string((struct sockaddr *)&dsi->client),
 -                              getip_port((struct sockaddr *)&dsi->client));
 -                dest += len;
 -                destlen -= len;
 -            }
 +            DSI *dsi = obj->handle;
 +            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")) {
              if (afpmaster && xlatevolname)
                  return NULL;
          } else if (is_var(p, "$i")) {
              if (afpmaster && xlatevolname)
                  return NULL;
 -            if (obj->proto == AFPPROTO_ASP) {
 -                ASP asp = obj->handle;
 -
 -                len = sprintf(dest, "%u", ntohs(asp->asp_sat.sat_addr.s_net));
 -                dest += len;
 -                destlen -= len;
 -
 -            } else if (obj->proto == AFPPROTO_DSI) {
 -                DSI *dsi = obj->handle;
 -                q = getip_string((struct sockaddr *)&dsi->client);
 -            }
 +            DSI *dsi = obj->handle;
 +            q = getip_string((struct sockaddr *)&dsi->client);
          } else if (is_var(p, "$s")) {
              if (obj->Obj)
                  q = obj->Obj;
@@@ -396,10 -449,16 +400,10 @@@ static void volset(struct vol_option *o
          else if (strcasecmp(val + 1, "xlateupper") == 0)
              options[VOLOPT_CASEFOLD].i_value = AFPVOL_ULOWERMUPPER;
      } else if (optionok(tmp, "adouble:", val)) {
 -        if (strcasecmp(val + 1, "v1") == 0)
 -            options[VOLOPT_ADOUBLE].i_value = AD_VERSION1;
 -#if AD_VERSION == AD_VERSION2
 -        else if (strcasecmp(val + 1, "v2") == 0)
 +        if (strcasecmp(val + 1, "v2") == 0)
              options[VOLOPT_ADOUBLE].i_value = AD_VERSION2;
 -        else if (strcasecmp(val + 1, "osx") == 0)
 -            options[VOLOPT_ADOUBLE].i_value = AD_VERSION2_OSX;
 -        else if (strcasecmp(val + 1, "sfm") == 0)
 -            options[VOLOPT_ADOUBLE].i_value = AD_VERSION1_SFM;
 -#endif
 +        else if (strcasecmp(val + 1, "ea") == 0)
 +            options[VOLOPT_ADOUBLE].i_value = AD_VERSION_EA;
      } else if (optionok(tmp, "options:", val)) {
          char *p;
  
                  options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS | AFPVOL_INV_DOTS;
              else if (strcasecmp(p, "limitsize") == 0)
                  options[VOLOPT_FLAGS].i_value |= AFPVOL_LIMITSIZE;
 -            /* support for either "dropbox" or "dropkludge" */
 -            else if (strcasecmp(p, "dropbox") == 0)
 -                options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX;
 -            else if (strcasecmp(p, "dropkludge") == 0)
 -                options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX;
              else if (strcasecmp(p, "nofileid") == 0)
                  options[VOLOPT_FLAGS].i_value |= AFPVOL_NOFILEID;
              else if (strcasecmp(p, "nostat") == 0)
          options[VOLOPT_DFLTPERM].i_value = (int)strtol(val+1, NULL, 8);
      } else if (optionok(tmp, "password:", val)) {
          setoption(options, save, VOLOPT_PASSWORD, val);
 -
 -#ifdef FORCE_UIDGID
 -
 -        /* this code allows forced uid/gid per volume settings */
 -    } else if (optionok(tmp, "forceuid:", val)) {
 -        setoption(options, save, VOLOPT_FORCEUID, val);
 -    } else if (optionok(tmp, "forcegid:", val)) {
 -        setoption(options, save, VOLOPT_FORCEGID, val);
 -
 -#endif /* FORCE_UIDGID */
      } else if (optionok(tmp, "root_preexec:", val)) {
          setoption(options, save, VOLOPT_ROOTPREEXEC, val);
  
@@@ -616,6 -690,7 +620,7 @@@ static int creatvol(AFPObj *obj, struc
      /* 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 (volume->v_deleted) {
                  volume->v_new = hide = 1;
              }
          if ((volume->v_flags & AFPVOL_EILSEQ))
              volume->v_utom_flags |= CONV__EILSEQ;
  
 -#ifdef FORCE_UIDGID
 -        if (options[VOLOPT_FORCEUID].c_value) {
 -            volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value);
 -        } else {
 -            volume->v_forceuid = NULL; /* set as null so as to return 0 later on */
 -        }
 -
 -        if (options[VOLOPT_FORCEGID].c_value) {
 -            volume->v_forcegid = strdup(options[VOLOPT_FORCEGID].c_value);
 -        } else {
 -            volume->v_forcegid = NULL; /* set as null so as to return 0 later on */
 -        }
 -#endif
          if (!user) {
              if (options[VOLOPT_PREEXEC].c_value)
                  volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_PREEXEC].c_value, pwd, path, name);
  
      /* get/store uuid from file */
      if (volume->v_flags & AFPVOL_TM) {
-         char *uuid = get_uuid(obj, volume->v_localname);
+         char *uuid = get_vol_uuid(obj, volume->v_localname);
          if (!uuid) {
              LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID",
                  volume->v_localname);
@@@ -1075,7 -1163,7 +1080,7 @@@ static int volfile_changed(struct afp_v
   *      <extension> TYPE [CREATOR]
   *
   */
- int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent)
static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent)
  {
      FILE        *fp;
      char        path[MAXPATHLEN + 1];
          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) );
+         }
+         return -1;
+     }
      memset(save_options, 0, sizeof(save_options));
  
      /* Enable some default options for all volumes */
@@@ -1256,6 -1352,10 +1269,6 @@@ static void volume_free(struct vol *vol
      free(vol->v_cnidscheme);
      free(vol->v_dbpath);
      free(vol->v_gvs);
 -#ifdef FORCE_UIDGID
 -    free(vol->v_forceuid);
 -    free(vol->v_forcegid);
 -#endif /* FORCE_UIDGID */
      if (vol->v_uuid)
          free(vol->v_uuid);
  }
@@@ -1359,10 -1459,45 +1372,45 @@@ static int getvolspace(struct vol *vol
  
  getvolspace_done:
      if (vol->v_limitsize) {
-         /* FIXME: Free could be limit minus (total minus used), */
-         /* which will confuse the client less ? */
-         *xbfree = min(*xbfree, (vol->v_limitsize * 1024 * 1024));
+         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)
+             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);
          *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
+         *xbfree = min(*xbfree, *xbtotal < used ? 0 : *xbtotal - used);
      }
  
      *bfree = min( *xbfree, maxsize);
@@@ -1411,7 -1546,7 +1459,7 @@@ static int getvolparams( u_int16_t bitm
       * .Parent file here if it doesn't exist. */
  
      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 -    if ( ad_open_metadata( vol->v_path, ADFLAGS_DIR, O_CREAT, &ad) < 0 ) {
 +    if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0 ) {
          isad = 0;
          vol->v_ctime = AD_DATE_FROM_UNIX(st->st_mtime);
  
  #ifndef NO_LARGE_VOL_SUPPORT
          case VOLPBIT_XBFREE :
              xbfree = hton64( xbfree );
 -#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
 -            bcopy(&xbfree, data, sizeof(xbfree));
 -#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
              memcpy(data, &xbfree, sizeof( xbfree ));
 -#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
              data += sizeof( xbfree );
              break;
  
          case VOLPBIT_XBTOTAL :
              xbtotal = hton64( xbtotal );
 -#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
 -            bcopy(&xbtotal, data, sizeof(xbtotal));
 -#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
              memcpy(data, &xbtotal, sizeof( xbtotal ));
 -#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
              data += sizeof( xbfree );
              break;
  #endif /* ! NO_LARGE_VOL_SUPPORT */
@@@ -1890,7 -2033,7 +1938,7 @@@ static void check_ea_sys_support(struc
      if (vol->v_vfs_ea == AFPVOL_EA_AUTO) {
  
          if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) {
-             LOG(log_info, logtype_logger, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname);
+             LOG(log_info, logtype_afpd, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname);
              vol->v_vfs_ea = AFPVOL_EA_NONE;
              return;
          }
          process_uid = geteuid();
          if (process_uid)
              if (seteuid(0) == -1) {
-                 LOG(log_error, logtype_logger, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno));
+                 LOG(log_error, logtype_afpd, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno));
                  exit(EXITERR_SYS);
              }
  
  
          if (process_uid) {
              if (seteuid(process_uid) == -1) {
-                 LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno));
+                 LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
                  exit(EXITERR_SYS);
              }
          }
@@@ -1990,6 -2133,9 +2038,6 @@@ int afp_openvol(AFPObj *obj, char *ibuf
  
      if (( volume->v_flags & AFPVOL_OPEN  ) ) {
          /* the volume is already open */
 -#ifdef FORCE_UIDGID
 -        set_uidgid ( volume );
 -#endif
          return stat_vol(bitmap, volume, rbuf, rbuflen);
      }
  
          }
      }
  
 -#ifdef FORCE_UIDGID
 -    set_uidgid ( volume );
 -#endif
 -
      if (volume->v_preexec) {
          if ((ret = afprun(0, volume->v_preexec, NULL)) && volume->v_preexec_close) {
              LOG(log_error, logtype_afpd, "afp_openvol(%s): preexec : %d", volume->v_path, ret );
       * FIXME file size
       */
      if (utf8_encoding()) {
-         volume->max_filename = 255;
+         volume->max_filename = UTF8FILELEN_EARLY;
      }
      else {
          volume->max_filename = MACFILELEN;
@@@ -2244,6 -2394,10 +2292,6 @@@ struct vol *getvolbyvid(const u_int16_
          return( NULL );
      }
  
 -#ifdef FORCE_UIDGID
 -    set_uidgid ( vol );
 -#endif /* FORCE_UIDGID */
 -
      current_vol = vol;
  
      return( vol );
@@@ -2402,7 -2556,8 +2450,7 @@@ int afp_setvolparams(AFPObj *obj _U_, c
          return AFPERR_BITMAP;
  
      ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 -    if ( ad_open( vol->v_path, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR,
 -                  0666, &ad) < 0 ) {
 +    if ( ad_open(&ad,  vol->v_path, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR) < 0 ) {
          if (errno == EROFS)
              return AFPERR_VLOCK;
  
@@@ -2497,8 -2652,8 +2545,8 @@@ static int create_special_folder (cons
      if ( !ret && folder->hide) {
          /* Hide it */
          ad_init(&ad, vol->v_adouble, vol->v_ad_options);
 -        if (ad_open_metadata( p, ADFLAGS_DIR, O_CREAT, &ad) < 0) {
 -            free (p);
 +        if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0) {
 +            free(p);
              free(q);
              return (-1);
          }
@@@ -2554,7 -2709,7 +2602,7 @@@ void unload_volumes_and_extmap(void
   *
   * Returns pointer to allocated storage on success, NULL on error.
   */
char *get_uuid(const AFPObj *obj, const char *volname)
static char *get_vol_uuid(const AFPObj *obj, const char *volname)
  {
      char *volname_conf;
      char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p;
  
      if (stat(obj->options.uuidconf, &tmpstat)) {                /* no file */
          if (( fd = creat(obj->options.uuidconf, 0644 )) < 0 ) {
-             LOG(log_error, logtype_atalkd, "ERROR: Cannot create %s (%s).",
+             LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s).",
                  obj->options.uuidconf, strerror(errno));
              return NULL;
          }
          if (( fp = fdopen( fd, "w" )) == NULL ) {
-             LOG(log_error, logtype_atalkd, "ERROR: Cannot fdopen %s (%s).",
+             LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s).",
                  obj->options.uuidconf, strerror(errno));
              close(fd);
              return NULL;
      fprintf(fp, "\"%s\"\t%36s\n", volname, cp);
      fclose(fp);
      
-     return strdup(uuid);
+     return strdup(cp);
  }
diff --combined etc/afpd/volume.h
index 883b1d56729a526bfe84ed48395a7b843a44de01,fd2d22514ff086d42daaf6eae389a0b3cf970e95..a0b45940a1397036370df7029d3800c803100d08
@@@ -6,8 -6,9 +6,8 @@@
  #ifndef AFPD_VOLUME_H
  #define AFPD_VOLUME_H 1
  
 -#include <sys/cdefs.h>
  #include <sys/types.h>
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
  
  #include <atalk/volume.h>
  #include <atalk/cnid.h>
@@@ -25,14 -26,8 +25,8 @@@ extern int              ustatfs_getvols
  extern void             setvoltime (AFPObj *, struct vol *);
  extern int              pollvoltime (AFPObj *);
  extern void             load_volumes (AFPObj *obj);
- extern int              readvolfile(AFPObj *obj,
-                                     struct afp_volume_name *p1,
-                                     char *p2,
-                                     int user,
-                                     struct passwd *pwent);
  extern const struct vol *getvolumes(void);
  extern void             unload_volumes_and_extmap(void);
- extern char             *get_uuid(const AFPObj *obj, const char *volname);
  
  /* FP functions */
  int afp_openvol      (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
index f4122d84ccf71af47d23531bfc4204e69191ec97,daa13e413e441622191606f31ae6085f8ce0ed19..8fb09624bd1850564f6eb3384efbad6d79c6e65c
@@@ -34,7 -34,6 +34,7 @@@
  #include <atalk/ea.h>
  #include <atalk/util.h>
  #include <atalk/acl.h>
 +#include <atalk/compat.h>
  
  #include "cmd_dbd.h"
  #include "dbif.h"
@@@ -293,16 -292,17 +293,16 @@@ static const char *check_special_dirs(c
  */
  static int check_adfile(const char *fname, const struct stat *st)
  {
 -    int ret, adflags;
 +    int ret;
 +    int adflags = ADFLAGS_HF;
      struct adouble ad;
 -    char *adname;
 +    const char *adname;
  
      if (dbd_flags & DBD_FLAGS_CLEANUP)
          return 0;
  
      if (S_ISREG(st->st_mode))
 -        adflags = 0;
 -    else
 -        adflags = ADFLAGS_DIR;
 +        adflags |= ADFLAGS_DIR;
  
      adname = myvolinfo->ad_path(fname, adflags);
  
          /* Create ad file */
          ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
  
 -        if ((ret = ad_open_metadata( fname, adflags, O_CREAT, &ad)) != 0) {
 +        if ((ret = ad_open(&ad,  fname, adflags, O_CREAT | O_RDWR, 0666)) != 0) {
              dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s",
                       cwdbuf, adname, strerror(errno));
  
  #endif
      } else {
          ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
 -        if (ad_open_metadata( fname, adflags, O_RDONLY, &ad) != 0) {
 +        if (ad_open(&ad, fname, adflags, O_RDONLY) != 0) {
              dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s'", cwdbuf, fname);
              return -1;
          }
@@@ -494,7 -494,7 +494,7 @@@ static int check_addir(int volroot
          /* Create ad dir and set name */
          ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
  
 -        if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad) != 0) {
 +        if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR, O_CREAT | O_RDWR, 0777) != 0) {
              dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno));
              return -1;
          }
@@@ -666,6 -666,8 +666,8 @@@ static int read_addir(void
  /*
    Check CNID for a file/dir, both from db and from ad-file.
    For detailed specs see intro.
+   @return Correct CNID of object or CNID_INVALID (ie 0) on error
  */
  static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok, int adflags)
  {
      cnid_t db_cnid, ad_cnid;
      struct adouble ad;
  
+     /* Force checkout every X items */
+     static int cnidcount = 0;
+     cnidcount++;
+     if (cnidcount > 10000) {
+         cnidcount = 0;
+         if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
+             dbd_log(LOGSTD, "Error checkpointing!");
+             return CNID_INVALID;
+         }
+     }
      /* Get CNID from ad-file if volume is using AFPVOL_CACHE */
      ad_cnid = 0;
      if ( (myvolinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) {
          ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
 -        if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) {
 +        if (ad_open(&ad, name, adflags, O_RDWR) != 0) {
              
              if (dbd_flags & DBD_FLAGS_CLEANUP)
-                 return 0;
+                 return CNID_INVALID;
  
              dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno));
-             return 0;
+             return CNID_INVALID;
          }
  
          if (dbd_flags & DBD_FLAGS_FORCE) {
  
      /* Query the database */
      ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
-     dbif_txn_close(dbd, ret);
+     if (dbif_txn_close(dbd, ret) != 0)
+         return CNID_INVALID;
      if (rply.result == CNID_DBD_RES_OK) {
          db_cnid = rply.cnid;
      } else if (rply.result == CNID_DBD_RES_NOTFOUND) {
          if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
              rqst.cnid = db_cnid;
              ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
-             dbif_txn_close(dbd, ret);
+             if (dbif_txn_close(dbd, ret) != 0)
+                 return CNID_INVALID;
  
              rqst.cnid = ad_cnid;
              ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
-             dbif_txn_close(dbd, ret);
+             if (dbif_txn_close(dbd, ret) != 0)
+                 return CNID_INVALID;
  
              ret = dbd_rebuild_add(dbd, &rqst, &rply);
-             dbif_txn_close(dbd, ret);
+             if (dbif_txn_close(dbd, ret) != 0)
+                 return CNID_INVALID;
          }
          return ad_cnid;
      } else if (ad_cnid && (db_cnid == 0)) {
              if (ret == CNID_DBD_RES_OK) {
                  /* Occupied! Choose another, update ad-file */
                  ret = dbd_add(dbd, &rqst, &rply, 1);
-                 dbif_txn_close(dbd, ret);
+                 if (dbif_txn_close(dbd, ret) != 0)
+                     return CNID_INVALID;
                  db_cnid = rply.cnid;
                  dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
  
                      dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file",
                              cwdbuf, name, ntohl(db_cnid));
                      ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
 -                    if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) {
 +                    if (ad_open(&ad, name, adflags, O_RDWR) != 0) {
                          dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
                                  cwdbuf, name, strerror(errno));
-                         return 0;
+                         return CNID_INVALID;
                      }
                      ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
                      ad_flush(&ad);
                      cwdbuf, name, ntohl(ad_cnid));
              rqst.cnid = ad_cnid;
              ret = dbd_rebuild_add(dbd, &rqst, &rply);
-             dbif_txn_close(dbd, ret);
+             if (dbif_txn_close(dbd, ret) != 0)
+                 return CNID_INVALID;
          }
          return ad_cnid;
      } else if ((db_cnid == 0) && (ad_cnid == 0)) {
          if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
              /* add to db */
              ret = dbd_add(dbd, &rqst, &rply, 1);
-             dbif_txn_close(dbd, ret);
+             if (dbif_txn_close(dbd, ret) != 0)
+                 return CNID_INVALID;
              db_cnid = rply.cnid;
              dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid));
          }
                  dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file",
                          cwdbuf, name, ntohl(db_cnid));
                  ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options);
 -                if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) {
 +                if (ad_open(&ad, name, adflags, O_RDWR) != 0) {
                      dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
                              cwdbuf, name, strerror(errno));
-                     return 0;
+                     return CNID_INVALID;
                  }
                  ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
                  ad_flush(&ad);
          return db_cnid;
      }
  
-     return 0;
+     return CNID_INVALID;
  }
  
  /*
@@@ -921,6 -941,22 +941,22 @@@ static int dbd_readdir(int volroot, cni
              continue;
          }
  
+         /**************************************************************************
+            Statistics
+          **************************************************************************/
+         static unsigned long long statcount = 0;
+         static time_t t = 0;
+         if (t == 0)
+             t = time(NULL);
+         statcount++;
+         if ((statcount % 10000) == 0) {
+             if (dbd_flags & DBD_FLAGS_STATS)            
+                 dbd_log(LOGSTD, "Scanned: %10llu, time: %10llu s",
+                         statcount, (unsigned long long)(time(NULL) - t));
+         }
          /**************************************************************************
             Tests
          **************************************************************************/
              cnid = check_cnid(ep->d_name, did, &st, adfile_ok, adflags);
  
              /* Now add this object to our rebuild dbd */
-             if (cnid) {
+             if (cnid && dbd_rebuild) {
+                 static uint count = 0;
                  rqst.cnid = rply.cnid;
-                 dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
+                 ret = dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
+                 if (dbif_txn_close(dbd_rebuild, ret) != 0)
+                     return -1;
                  if (rply.result != CNID_DBD_RES_OK) {
-                     dbd_log( LOGDEBUG, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
+                     dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
                               cnid, cwdbuf, ep->d_name);
-                     longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
+                     return -1;
+                 }
+                 count++;
+                 if (count == 10000) {
+                     if (dbif_txn_checkpoint(dbd_rebuild, 0, 0, 0) < 0) {
+                         dbd_log(LOGSTD, "Error checkpointing!");
+                         return -1;
+                     }
+                     count = 0;
                  }
              }
          }
              close(cwd);
              *(strrchr(cwdbuf, '/')) = 0;
              if (ret < 0)
-                 continue;
+                 return -1;
          }
      }
  
@@@ -1030,7 -1077,7 +1077,7 @@@ static int scanvol(struct volinfo *vi, 
  */
  static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags)
  {
-     int ret, deleted = 0;
+     int ret = 0, deleted = 0;
      cnid_t dbd_cnid = 0, rebuild_cnid = 0;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
          if (alarmed)
              longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
  
-         if (deleted > 50) {
+         if (deleted > 1000) {
              deleted = 0;
              if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) {
                  dbd_log(LOGSTD, "Error checkpointing!");
                              goto cleanup;
                          }
                          
-                         dbif_txn_close(dbd, ret);
+                         if (dbif_txn_close(dbd, ret) != 0)
+                             return;
                          deleted++;
                      }
                      /* Check if we got a termination signal */
                      (void)dbif_txn_abort(dbd);
                      goto cleanup;
                  }
-                 dbif_txn_close(dbd, ret);
+                 if (dbif_txn_close(dbd, ret) != 0)
+                     return;
                  deleted++;
              }
              continue;
          }
  
          if (dbd_cnid > rebuild_cnid) {
+             dbif_idwalk(dbd, NULL, 1); /* Close cursor */
+             dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
+             (void)dbif_txn_close(dbd, 2);
+             (void)dbif_txn_close(dbd_rebuild, 2);                
              dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid);
              dbif_dump(dbd_rebuild, 0);
              dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!");
-             dbif_txn_close(dbd, ret);
-             dbif_idwalk(dbd, NULL, 1); /* Close cursor */
-             dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */
              goto cleanup;
          }
      } /* while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) */
@@@ -1123,6 -1173,16 +1173,16 @@@ cleanup
      return;
  }
  
+ static const char *get_tmpdb_path(void)
+ {
+     pid_t pid = getpid();
+     static char path[MAXPATHLEN];
+     snprintf(path, MAXPATHLEN, "/tmp/tmpdb-dbd.%u", pid);
+     if (mkdir(path, 0755) != 0)
+         return NULL;
+     return path;
+ }
  /*
    Main func called from cmd_dbd.c
  */
@@@ -1130,9 -1190,13 +1190,13 @@@ int cmd_dbd_scanvol(DBD *dbd_ref, struc
  {
      int ret = 0;
      struct db_param db_param = { 0 };
+     const char *tmpdb_path = NULL;
  
      /* Set cachesize for in-memory rebuild db */
-     db_param.cachesize = 128 * 1024 * 1024; /* 128 MB */
+     db_param.cachesize = 64 * 1024;         /* 64 MB */
+     db_param.maxlocks = DEFAULT_MAXLOCKS;
+     db_param.maxlockobjs = DEFAULT_MAXLOCKOBJS;
+     db_param.logfile_autoremove = 1;
  
      /* Make it accessible for all funcs */
      dbd = dbd_ref;
          return -1;
      }
  
-     if (! nocniddb) {
-         /* Get volume stamp */
-         dbd_getstamp(dbd, &rqst, &rply);
-         if (rply.result != CNID_DBD_RES_OK)
-             goto exit_cleanup;
-         memcpy(stamp, rply.name, CNID_DEV_LEN);
-         /* open/create rebuild dbd, copy rootinfo key */
-         if (NULL == (dbd_rebuild = dbif_init(NULL, NULL)))
-             return -1;
-         if (0 != (dbif_open(dbd_rebuild, &db_param, 0)))
-             return -1;
-         if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild)))
-             goto exit_cleanup;
+     /* 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);
+     /* temporary rebuild db, used with -re rebuild to delete unused CNIDs, not used with -f */
+     if (! nocniddb && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE)) {
+         tmpdb_path = get_tmpdb_path();
+         if (NULL == (dbd_rebuild = dbif_init(tmpdb_path, "cnid2.db"))) {
+             ret = -1;
+             goto exit;
+         }
  
-     if (setjmp(jmp) != 0)
-         goto exit_cleanup;      /* Got signal, jump from dbd_readdir */
+         if (dbif_env_open(dbd_rebuild,
+                           &db_param,
+                           DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN) < 0) {
+             dbd_log(LOGSTD, "error opening tmp database!");
+             goto exit;
+         }
+         if (0 != (dbif_open(dbd_rebuild, NULL, 0))) {
+             ret = -1;
+             goto exit;
+         }
+         if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) {
+             ret = -1;
+             goto exit;
+         }
+     }
+     if (setjmp(jmp) != 0) {
+         ret = 0;                /* Got signal, jump from dbd_readdir */
+         goto exit;
+     }
  
      /* scanvol */
-     if ( (scanvol(vi, flags)) != 0)
-         return -1;
+     if ( (scanvol(vi, flags)) != 0) {
+         ret = -1;
+         goto exit;
+     }
  
+ exit:
      if (! nocniddb) {
-         /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
-            other clients in between our pass 1 and 2 */
-         if (flags & DBD_FLAGS_EXCL)
+         if (dbif_txn_close(dbd, ret == 0 ? 1 : 0) != 0)
+             ret = -1;
+         if (dbd_rebuild)
+             if (dbif_txn_close(dbd_rebuild, ret == 0 ? 1 : 0) != 0)
+                 ret = -1;
+         if ((ret == 0) && dbd_rebuild && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE))
+             /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from
+                other clients in between our pass 1 and 2 */
              delete_orphaned_cnids(dbd, dbd_rebuild, flags);
      }
  
- exit_cleanup:
-     if (! nocniddb)
+     if (dbd_rebuild) {
+         dbd_log(LOGDEBUG, "Closing tmp db");
          dbif_close(dbd_rebuild);
+         if (tmpdb_path) {
+             char cmd[8 + MAXPATHLEN];
+             snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", tmpdb_path);
+             dbd_log( LOGDEBUG, "Removing temp database '%s'", tmpdb_path);
+             system(cmd);
+             snprintf(cmd, 8 + MAXPATHLEN, "rmdir %s", tmpdb_path);
+             system(cmd);
+         }        
+     }
      return ret;
  }
index 2f3b9150a1b7fd1278bc1746e7e1c4d9f86e5f7a,a51d15c4196d911f2f132cc42207cc6f87fddcb2..11987cc779b9225c01059cbbea1ad42fff44060e
@@@ -43,7 -43,7 +43,7 @@@
  #include <sys/wait.h>
  #include <sys/uio.h>
  #include <sys/un.h>
 -#define _XPG4_2 1
 +// #define _XPG4_2 1
  #include <sys/socket.h>
  #include <stdio.h>
  #include <time.h>
@@@ -89,7 -89,6 +89,7 @@@
  #include <atalk/cnid_dbd_private.h>
  #include <atalk/paths.h>
  #include <atalk/volinfo.h>
 +#include <atalk/compat.h>
  
  #include "usockfd.h"
  
@@@ -580,7 -579,8 +580,8 @@@ int main(int argc, char *argv[]
  
          /* Load .volinfo file */
          if ((volinfo = allocvolinfo(volpath)) == NULL) {
-             LOG(log_severe, logtype_cnid, "allocvolinfo: %s", strerror(errno));
+             LOG(log_severe, logtype_cnid, "allocvolinfo(\"%s\"): %s",
+                 volpath, strerror(errno));
              goto loop_end;
          }
  
diff --combined etc/cnid_dbd/comm.c
index 65ed8604ee827f73293f3815fa6ccf7314c8a7b9,083d27a7d8022129c9c8f8ffb4f22571e5ce8842..64038714961320c2adc775d46cdf016d20939e4a
@@@ -9,6 -9,16 +9,16 @@@
  #include "config.h"
  #endif
  
+ #ifndef _XOPEN_SOURCE
+ # define _XOPEN_SOURCE 600
+ #endif
+ #ifndef __EXTENSIONS__
+ # define __EXTENSIONS__
+ #endif
+ #ifndef _GNU_SOURCE
+ # define _GNU_SOURCE
+ #endif
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
@@@ -18,7 -28,6 +28,6 @@@
  #include <sys/types.h>
  #include <sys/time.h>
  #include <sys/uio.h>
- #define _XPG4_2 1
  #include <sys/socket.h>
  #include <sys/select.h>
  #include <assert.h>
@@@ -209,7 -218,7 +218,7 @@@ int comm_rcv(struct cnid_dbd_rqst *rqst
          return -1;
      }
  
 -    nametmp = rqst->name;
 +    nametmp = (char *)rqst->name;
      if ((b = readt(cur_fd, rqst, sizeof(struct cnid_dbd_rqst), 1, CNID_DBD_TIMEOUT))
          != sizeof(struct cnid_dbd_rqst)) {
          if (b)
          return 0;
      }
      rqst->name = nametmp;
 -    if (rqst->namelen && readt(cur_fd, rqst->name, rqst->namelen, 1, CNID_DBD_TIMEOUT)
 +    if (rqst->namelen && readt(cur_fd, (char *)rqst->name, rqst->namelen, 1, CNID_DBD_TIMEOUT)
          != rqst->namelen) {
          LOG(log_error, logtype_cnid, "error reading message name: %s", strerror(errno));
          invalidate_fd(cur_fd);
      }
      /* We set this to make life easier for logging. None of the other stuff
         needs zero terminated strings. */
 -    rqst->name[rqst->namelen] = '\0';
 +    ((char *)(rqst->name))[rqst->namelen] = '\0';
  
      LOG(log_maxdebug, logtype_cnid, "comm_rcv: got %u bytes", b + rqst->namelen);
  
diff --combined etc/cnid_dbd/db_param.h
index d8f3c9103d278c2bbf03f5626f7788138d393e3a,f3a4827a031a5f99e5fa055c2232d228539024f2..fce1cb5a9ddc89883745a30d1a386ed4be3cca81
@@@ -8,7 -8,18 +8,17 @@@
  #define CNID_DBD_DB_PARAM_H 1
  
  #include <sys/param.h>
 -#include <sys/cdefs.h>
  
+ #define DEFAULT_LOGFILE_AUTOREMOVE 1
+ #define DEFAULT_CACHESIZE          (8 * 1024) /* KB, so 8 MB */
+ #define DEFAULT_MAXLOCKS           5000
+ #define DEFAULT_MAXLOCKOBJS        5000
+ #define DEFAULT_FLUSH_FREQUENCY    1000
+ #define DEFAULT_FLUSH_INTERVAL     1800
+ #define DEFAULT_USOCK_FILE         "usock"
+ #define DEFAULT_FD_TABLE_SIZE      512
+ #define DEFAULT_IDLE_TIMEOUT       (10 * 60)
  struct db_param {
      char *dir;
      int logfile_autoremove;
diff --combined etc/cnid_dbd/dbif.c
index 87ff2e9a2f006b2a9344eadd24e37c4b3b7c7b30,792ebe915a4c8dcf7f5085dea7b8e4ce06dbac3f..91d9bec00ff18d0ba16a1c52dfe5c64ba3a7ab66
@@@ -14,8 -14,8 +14,8 @@@
  #include <string.h>
  #include <sys/types.h>
  #include <sys/stat.h>
 -#include <sys/cdefs.h>
  #include <unistd.h>
 +#include <arpa/inet.h>
  
  #include <db.h>
  
@@@ -321,6 -321,91 +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)
  {
@@@ -386,6 -471,8 +471,8 @@@ int dbif_env_open(DBD *dbd, struct db_p
          return -1;
      }
  
+     dbd->db_param = *dbp;
      if ((dbif_openlog(dbd)) != 0)
          return -1;
  
@@@ -1005,25 -1092,30 +1092,30 @@@ int dbif_txn_abort(DBD *dbd
  }
  
  /* 
-    ret = 1 -> commit txn
-    ret = 0 -> abort txn -> exit!
+    ret = 1 -> commit txn if db_param.txn_frequency
+    ret = 0 -> abort txn db_param.txn_frequency -> exit!
     anything else -> exit!
+    @returns 0 on success (abort or commit), -1 on error
  */
void dbif_txn_close(DBD *dbd, int ret)
int dbif_txn_close(DBD *dbd, int ret)
  {
      if (ret == 0) {
          if (dbif_txn_abort(dbd) < 0) {
              LOG( log_error, logtype_cnid, "Fatal error aborting transaction. Exiting!");
-             exit(EXIT_FAILURE);
+             return -1;
          }
      } else if (ret == 1) {
          ret = dbif_txn_commit(dbd);
          if (  ret < 0) {
              LOG( log_error, logtype_cnid, "Fatal error committing transaction. Exiting!");
-             exit(EXIT_FAILURE);
+             return -1;
          }
-     } else
-        exit(EXIT_FAILURE);
+     } else {
+         return -1;
+     }
+     return 0;
  }
  
  int dbif_txn_checkpoint(DBD *dbd, u_int32_t kbyte, u_int32_t min, u_int32_t flags)
diff --combined etc/cnid_dbd/dbif.h
index 2be8c0b1a5ac9469b2b8b3031c38eeaedb8c2d00,c936a2b93705daf7b5bf1a8061131f7a3174dd37..8c71de36b96221f598f64f4943b0878e7906f444
@@@ -53,6 -53,7 +53,6 @@@
  #ifndef CNID_DBD_DBIF_H
  #define CNID_DBD_DBIF_H 1
  
 -#include <sys/cdefs.h>
  #include <db.h>
  #include <atalk/adouble.h>
  #include "db_param.h"
  #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;
@@@ -75,6 -83,7 +82,7 @@@
  
  typedef struct {
      DB_ENV   *db_env;
+     struct db_param db_param;
      DB_TXN   *db_txn;
      DBC      *db_cur;              /* for dbif_walk */
      char     *db_envhome;
@@@ -84,6 -93,8 +92,8 @@@
  } 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);
@@@ -100,7 -111,7 +110,7 @@@ extern int dbif_copy_rootinfokey(DBD *s
  extern int dbif_txn_begin(DBD *);
  extern int dbif_txn_commit(DBD *);
  extern int dbif_txn_abort(DBD *);
- extern void dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */
+ extern int dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */
  extern int dbif_txn_checkpoint(DBD *, u_int32_t, u_int32_t, u_int32_t);
  
  extern int dbif_dump(DBD *dbd, int dumpindexes);
diff --combined etc/cnid_dbd/main.c
index 1c951cb9c6d182c5d238b5de7bf99eb99ae6dbd6,64734396d34f6d7d8cfd1758c68d1b663db8455e..4f5fd725b09fc4bbba95b5dca23d202a9af216d9
@@@ -8,20 -8,28 +8,20 @@@
  #include "config.h"
  #endif /* HAVE_CONFIG_H */
  
 -#ifdef HAVE_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
 -#ifdef HAVE_FCNTL_H
  #include <fcntl.h>
 -#endif /* HAVE_FCNTL_H */
  #include <stdio.h>
  #include <stdlib.h>
  #include <errno.h>
  #include <signal.h>
  #include <string.h>
 -#ifdef HAVE_SYS_TYPES_H
  #include <sys/types.h>
 -#endif /* HAVE_SYS_TYPES_H */
  #include <sys/param.h>
 -#ifdef HAVE_SYS_STAT_H
  #include <sys/stat.h>
 -#endif /* HAVE_SYS_STAT_H */
  #include <time.h>
  #include <sys/file.h>
 +#include <arpa/inet.h>
  
 -#include <netatalk/endian.h>
  #include <atalk/cnid_dbd_private.h>
  #include <atalk/logger.h>
  #include <atalk/volinfo.h>
  #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)
  {
@@@ -248,34 -255,6 +247,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)
      }
  }
  
- /* ----------------------- */
- 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");
  
      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();
  
      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");
  
      }
      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);
      if (dbif_env_remove(dbpath) < 0)
          err++;
  
-     free_lock(lockfd);
      if (err)
          exit(4);
      else if (exit_sig)
diff --combined include/atalk/dsi.h
index e16681a4eee95bbafc3d376065c2264dac631345,babd8288ce3fc55745b5acb7d2897479822ac4f5..7b90b38e561ab4c70eaee95c32718c889b5ddfb5
@@@ -6,15 -6,19 +6,15 @@@
  #ifndef _ATALK_DSI_H 
  #define _ATALK_DSI_H
  
 -#include <sys/cdefs.h>
  #include <sys/types.h>
  #include <sys/time.h>
 +#include <sys/socket.h>
  #include <signal.h>
 +#include <arpa/inet.h>
  
  #include <netinet/in.h>
  #include <atalk/afp.h>
  #include <atalk/server_child.h>
 -#include <netatalk/endian.h>
 -
 -#ifdef __OpenBSD__
 -#include <sys/socket.h>
 -#endif
  
  /* What a DSI packet looks like:
   0                               32
@@@ -51,6 -55,7 +51,7 @@@ struct dsi_block 
  
  #define DSI_CMDSIZ        8192 
  #define DSI_DATASIZ       8192
  /* child and parent processes might interpret a couple of these
   * differently. */
  typedef struct DSI {
  #endif 
  
  #ifdef USE_ZEROCONF
+   char *bonjourname;      /* server name as UTF8 maxlen MAXINSTANCENAMELEN */
    int zeroconf_registered;
  #endif
  
-   /* buffer for OSX deadlock */
+   /* DSI readahead buffer used for buffered reads in dsi_peek */
+   size_t dsireadbuf; /* size of the DSI readahead buffer used in dsi_peek() */
    char *buffer;
    char *start;
    char *eof;
    char *end;
-   int  maxsize;
  } DSI;
    
  /* DSI flags */
  #define DSI_NOREPLY          (1 << 6) /* in dsi_write we generate our own replies */
  #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 */
  
  /* basic initialization: dsi_init.c */
  extern DSI *dsi_init (const dsi_proto /*protocol*/,
diff --combined include/atalk/unicode.h
index 1bb2ee3efdaad8c7f0a0528c40d392b5ebd49d24,325b7ac2bf911275095a0939ce21109f33a953b1..27441549e2d803cd3e0f85b147673fb6aa3e51b0
@@@ -1,6 -1,8 +1,6 @@@
  #ifndef _ATALK_UNICODE_H
  #define _ATALK_UNICODE_H 1
  
 -#include <sys/cdefs.h>
 -#include <netatalk/endian.h>
  #include <errno.h>
  #include <sys/param.h>
  
@@@ -90,9 -92,13 +90,13 @@@ extern int atalk_iconv_close (atalk_ico
  extern struct charset_functions *find_charset_functions (const char *);
  extern int atalk_register_charset (struct charset_functions *);
  
+ /* from utf16_case.c */
+ extern ucs2_t    toupper_w  (ucs2_t);
+ extern u_int32_t toupper_sp (u_int32_t);
+ extern ucs2_t    tolower_w  (ucs2_t);
+ extern u_int32_t tolower_sp (u_int32_t);
  /* from util_unistr.c */
- extern ucs2_t   toupper_w  (ucs2_t);
- extern ucs2_t   tolower_w  (ucs2_t);
  extern int      strupper_w (ucs2_t *);
  extern int      strlower_w (ucs2_t *);
  extern int      islower_w  (ucs2_t);
diff --combined include/atalk/util.h
index 7b1b10fbe5f1ef56201089a88beee5818659eb3c,999f14daac86349e508be888df10e0a40a987123..1a428bda88de08f5166f3bfe9c8c1176e92aaf4c
  #ifndef _ATALK_UTIL_H
  #define _ATALK_UTIL_H 1
  
 -#include <sys/cdefs.h>
  #include <sys/types.h>
 -#ifdef HAVE_UNISTD_H
 +#include <sys/socket.h>
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #include <poll.h>
 -#include <netatalk/at.h>
  #include <atalk/unicode.h>
+ #include <atalk/bstrlib.h>
  
  /* exit error codes */
  #define EXITERR_CLNT 1  /* client related error */
  #define AFP_ASSERT(b)
  #endif /* NDEBUG */
  
 +#ifndef MIN
 +#define MIN(a, b)  ((a) < (b) ? (a) : (b))
 +#endif
 +
 +#ifndef MAX
 +#define MAX(a, b)  ((a) > (b) ? (a) : (b))
 +#endif
 +
  #define STRCMP(a,b,c) (strcmp(a,c) b 0)
 +#define ZERO_STRUCT(a) memset(&(a), 0, sizeof(a))
 +#define ZERO_STRUCTP(a) memset((a), 0, sizeof(a))
  
  #ifdef WITH_SENDFILE
  extern ssize_t sys_sendfile (int __out_fd, int __in_fd, off_t *__offset,size_t __count);
@@@ -64,6 -59,7 +66,6 @@@ extern void freeifacelist(char **)
  
  #define diatolower(x)     _dialowermap[(unsigned char) (x)]
  #define diatoupper(x)     _diacasemap[(unsigned char) (x)]
 -extern int atalk_aton     (char *, struct at_addr *);
  extern void bprint        (char *, int);
  extern int strdiacasecmp  (const char *, const char *);
  extern int strndiacasecmp (const char *, const char *, size_t);
@@@ -72,6 -68,19 +74,6 @@@ extern void fault_setup        (void (*fn)(v
  extern void netatalk_panic(const char *why);
  #define server_unlock(x)  (unlink(x))
  
 -/* strlcpy and strlcat are used by pam modules */
 -#ifndef UAM_MODULE_EXPORT
 -#define UAM_MODULE_EXPORT 
 -#endif
 -
 -#ifndef HAVE_STRLCPY
 -UAM_MODULE_EXPORT size_t strlcpy (char *, const char *, size_t);
 -#endif
 - 
 -#ifndef HAVE_STRLCAT
 -UAM_MODULE_EXPORT size_t strlcat (char *, const char *, size_t);
 -#endif
 -
  #ifndef HAVE_DLFCN_H
  extern void *mod_open    (const char *);
  extern void *mod_symbol  (void *, const char *);
@@@ -155,9 -164,14 +157,15 @@@ extern int recv_fd(int fd, int nonblock
   * unix.c
   *****************************************************************/
  
 +extern const char *abspath(const char *name);
  extern const char *getcwdpath(void);
  extern char *stripped_slashes_basename(char *p);
  extern int lchdir(const char *dir);
  extern void randombytes(void *buf, int n);
  #endif  /* _ATALK_UTIL_H */
+ /******************************************************************
+  * cnid.c
+  *****************************************************************/
+ extern bstring rel_path_in_vol(const char *path, const char *volpath);
diff --combined libatalk/acl/unix.c
index 57933f088e40d2e9d4210739af9050ca0683fe88,f72d9aaef7e3f01d96143de53cf20af517b259b4..0ff0ea5b6c169597ef5208767231329d0d320354
@@@ -52,7 -52,7 +52,7 @@@ int get_nfsv4_acl(const char *name, ace
          /* sorry, no ACLs for symlinks */
          return 0;
  
 -    if ( ! (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) {
 +    if ( ! ((S_ISREG(st.st_mode)) || (S_ISDIR(st.st_mode)))) {
          LOG(log_warning, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): special", getcwdpath(), name);
          return 0;
      }
@@@ -217,7 -217,7 +217,7 @@@ int nfsv4_chmod(char *name, mode_t mode
  {
      int ret = -1;
      int noaces, nnaces;
-     ace_t *oacl = NULL, *nacl = NULL, *cacl;
+     ace_t *oacl = NULL, *nacl = NULL, *cacl = NULL;
  
      LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o)",
          getcwdpath(), name, mode);
index 12287ff0c35d551adb36544443b1e0a25fc3f2be,4ad6883168a4d64098979e2be525588a266042fb..b7e1f4035f856b3480ef37bfd249139e77624a58
  #ifdef CNID_BACKEND_DBD
  
  #include <stdlib.h>
 -#ifdef HAVE_SYS_STAT_H
  #include <sys/stat.h>
 -#endif /* HAVE_SYS_STAT_H */
 -#ifdef HAVE_SYS_UIO_H
  #include <sys/uio.h>
 -#endif /* HAVE_SYS_UIO_H */
 -#ifdef HAVE_STRINGS_H
 -#include <strings.h>
 -#endif
  #include <sys/time.h>
  #include <sys/un.h>
  #include <sys/socket.h>
@@@ -26,8 -33,8 +26,8 @@@
  #include <errno.h>
  #include <netdb.h>
  #include <time.h>
 +#include <arpa/inet.h>
  
 -#include <netatalk/endian.h>
  #include <atalk/logger.h>
  #include <atalk/adouble.h>
  #include <atalk/cnid.h>
@@@ -97,7 -104,7 +97,7 @@@ static int tsock_getfd(const char *host
          }
  
          if (setnonblock(sock, 1) != 0) {
-             LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(err));
+             LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(errno));
              close(sock);
              sock = -1;
              return -1;
@@@ -266,7 -273,7 +266,7 @@@ static int send_packet(CNID_private *db
      vecs = 1;
  
      if (rqst->namelen) {
 -        iov[1].iov_base = rqst->name;
 +        iov[1].iov_base = (char *)rqst->name;
          iov[1].iov_len  = rqst->namelen;
          towrite += rqst->namelen;
          vecs++;
@@@ -531,7 -538,8 +531,7 @@@ void cnid_dbd_close(struct _cnid_db *cd
  
  /* ---------------------- */
  cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
 -                    const cnid_t did, char *name, const size_t len,
 -                    cnid_t hint)
 +                    cnid_t did, const char *name, size_t len, cnid_t hint)
  {
      CNID_private *db;
      struct cnid_dbd_rqst rqst;
  }
  
  /* ---------------------- */
 -cnid_t cnid_dbd_get(struct _cnid_db *cdb, const cnid_t did, char *name, const size_t len)
 +cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len)
  {
      CNID_private *db;
      struct cnid_dbd_rqst rqst;
@@@ -721,8 -729,8 +721,8 @@@ int cnid_dbd_getstamp(struct _cnid_db *
  }
  
  /* ---------------------- */
 -cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
 -                       char *name, const size_t len)
 +cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
 +                       const char *name, size_t len)
  {
      CNID_private *db;
      struct cnid_dbd_rqst rqst;
  }
  
  /* ---------------------- */
 -int cnid_dbd_find(struct _cnid_db *cdb, char *name, size_t namelen, void *buffer, size_t buflen)
 +int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen)
  {
      CNID_private *db;
      struct cnid_dbd_rqst rqst;
  }
  
  /* ---------------------- */
 -int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st,
 -                    const cnid_t did, char *name, const size_t len)
 +int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
 +                    cnid_t did, const char *name, size_t len)
  {
      CNID_private *db;
      struct cnid_dbd_rqst rqst;
  
  /* ---------------------- */
  cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
 -                            const cnid_t did, char *name, const size_t len,
 -                            cnid_t hint)
 +                            cnid_t did, const char *name, size_t len, cnid_t hint)
  {
      CNID_private *db;
      struct cnid_dbd_rqst rqst;
diff --combined libatalk/dsi/dsi_close.c
index 42a65ecdf35493e36e5124c862579936ec3a8a5e,6362182ba49fe6d259dd67277eb8cc0f7df6b7e3..80bee3fe702a79cfbd18bd7a7ac4bd8539295aaf
  
  #include <stdio.h>
  #include <stdlib.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/dsi.h>
 -#include <netatalk/endian.h>
  
  void dsi_close(DSI *dsi)
  {
    /* server generated. need to set all the fields. */
-   if (!(dsi->flags & DSI_SLEEPING)) {
+   if (!(dsi->flags & DSI_SLEEPING) && !(dsi->flags & DSI_DISCONNECTED)) {
        dsi->header.dsi_flags = DSIFL_REQUEST;
        dsi->header.dsi_command = DSIFUNC_CLOSE;
        dsi->header.dsi_requestID = htons(dsi_serverID(dsi));
index 180049f23fbf07c6fa980bef24e8afa9831e9d61,221ac47af76d50f4a01f777d8e17979207d1d578..5ea32b01a4afb8bccd46dce7ad76a2656a24880e
  #include <sys/types.h>
  #include <sys/socket.h>
  
 -/* POSIX.1 sys/wait.h check */
  #include <sys/types.h>
 -#ifdef HAVE_SYS_WAIT_H
  #include <sys/wait.h>
 -#endif /* HAVE_SYS_WAIT_H */
 -#ifndef WEXITSTATUS
 -#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
 -#endif /* ! WEXITSTATUS */
 -#ifndef WIFEXITED
 -#define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
 -#endif /* ! WIFEXITED */
 -
  #include <sys/time.h>
  #include <atalk/logger.h>
  #include <atalk/util.h>
@@@ -35,12 -45,12 +35,12 @@@ afp_child_t *dsi_getsession(DSI *dsi, s
    afp_child_t *child;
  
    if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) {
-       LOG(log_error, logtype_afpd, "dsi_getsess: %s", strerror(errno));
+       LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
        exit( EXITERR_CLNT );
    }
  
    if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) {
-       LOG(log_error, logtype_afpd, "dsi_getsess: setnonblock: %s", strerror(errno));
+       LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno));
        exit(EXITERR_CLNT);
    }
  
index 149bc208edbc40338a85d18cd7c180451741ddd7,680967e8be1f543b833d6ae9e6c6caf70d59f532..90df884efee6a1e054da359564a77f7e4122e4cd
@@@ -1,6 -1,4 +1,4 @@@
  /*
-  * $Id: dsi_stream.c,v 1.20 2009-10-26 12:35:56 franklahm Exp $
-  *
   * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu)
   * All rights reserved. See COPYRIGHT.
   *
@@@ -15,8 -13,6 +13,6 @@@
  #include "config.h"
  #endif /* HAVE_CONFIG_H */
  
- #define USE_WRITEV
  #include <stdio.h>
  #include <stdlib.h>
  
  #include <errno.h>
  #include <sys/types.h>
  #include <sys/socket.h>
- #ifdef USE_WRITEV
  #include <sys/uio.h>
- #endif
  
  #include <atalk/logger.h>
  #include <atalk/dsi.h>
 -#include <netatalk/endian.h>
  #include <atalk/util.h>
  
  #define min(a,b)  ((a) < (b) ? (a) : (b))
  #define MSG_DONTWAIT 0x40
  #endif
  
- /* ------------------------- 
-  * we don't use a circular buffer.
- */
- static void dsi_init_buffer(DSI *dsi)
- {
-     if (!dsi->buffer) {
-         /* XXX config options */
-         dsi->maxsize = 6 * dsi->server_quantum;
-         if (!dsi->maxsize)
-             dsi->maxsize = 6 * DSI_SERVQUANT_DEF;
-         dsi->buffer = malloc(dsi->maxsize);
-         if (!dsi->buffer) {
-             return;
-         }
-         dsi->start = dsi->buffer;
-         dsi->eof = dsi->buffer;
-         dsi->end = dsi->buffer + dsi->maxsize;
-     }
- }
- /* ---------------------- 
-    afpd is sleeping too much while trying to send something.
-    May be there's no reader or the reader is also sleeping in write,
-    look if there's some data for us to read, hopefully it will wake up
-    the reader so we can write again.
- */
+ /*
+  * afpd is sleeping too much while trying to send something.
+  * May be there's no reader or the reader is also sleeping in write,
+  * look if there's some data for us to read, hopefully it will wake up
+  * the reader so we can write again.
+  *
+  * @returns 0 when is possible to send again, -1 on error
+  */
  static int dsi_peek(DSI *dsi)
  {
+     static int warned = 0;
      fd_set readfds, writefds;
      int    len;
      int    maxfd;
      int    ret;
  
-     FD_ZERO(&readfds);
-     FD_ZERO(&writefds);
-     FD_SET( dsi->socket, &readfds);
-     FD_SET( dsi->socket, &writefds);
-     maxfd = dsi->socket +1;
+     LOG(log_debug, logtype_dsi, "dsi_peek");
+     maxfd = dsi->socket + 1;
  
      while (1) {
-         FD_SET( dsi->socket, &readfds);
+         FD_ZERO(&readfds);
+         FD_ZERO(&writefds);
+         if (dsi->eof < dsi->end) {
+             /* space in read buffer */
+             FD_SET( dsi->socket, &readfds);
+         } else {
+             if (!warned) {
+                 warned = 1;
+                 LOG(log_note, logtype_dsi, "dsi_peek: readahead buffer is full, possibly increase -dsireadbuf option");
+                 LOG(log_note, logtype_dsi, "dsi_peek: dsireadbuf: %d, DSI quantum: %d, effective buffer size: %d",
+                     dsi->dsireadbuf,
+                     dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF,
+                     dsi->end - dsi->buffer);
+             }
+         }
          FD_SET( dsi->socket, &writefds);
  
          /* No timeout: if there's nothing to read nor nothing to write,
                  /* we might have been interrupted by out timer, so restart select */
                  continue;
              /* give up */
+             LOG(log_error, logtype_dsi, "dsi_peek: unexpected select return: %d %s",
+                 ret, ret < 0 ? strerror(errno) : "");
+             return -1;
+         }
+         if (FD_ISSET(dsi->socket, &writefds)) {
+             /* we can write again */
+             LOG(log_debug, logtype_dsi, "dsi_peek: can write again");
              break;
          }
  
          /* Check if there's sth to read, hopefully reading that will unblock the client */
          if (FD_ISSET(dsi->socket, &readfds)) {
-             dsi_init_buffer(dsi);
-             len = dsi->end - dsi->eof;
-             if (len <= 0) {
-                 /* ouch, our buffer is full ! fall back to blocking IO 
-                  * could block and disconnect but it's better than a cpu hog */
-                 break;
+             len = dsi->end - dsi->eof; /* it's ensured above that there's space */
+             if ((len = read(dsi->socket, dsi->eof, len)) <= 0) {
+                 if (len == 0) {
+                     LOG(log_error, logtype_dsi, "dsi_peek: EOF");
+                     return -1;
+                 }
+                 LOG(log_error, logtype_dsi, "dsi_peek: read: %s", strerror(errno));
+                 if (errno == EAGAIN)
+                     continue;
+                 return -1;
              }
+             LOG(log_debug, logtype_dsi, "dsi_peek: read %d bytes", len);
  
-             len = read(dsi->socket, dsi->eof, len);
-             if (len <= 0)
-                 break;
              dsi->eof += len;
          }
-         if (FD_ISSET(dsi->socket, &writefds))
-             /* we can write again at last */
-             break;
      }
  
      return 0;
@@@ -140,12 -137,6 +136,6 @@@ ssize_t dsi_stream_write(DSI *dsi, voi
  
    LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
  
-   /* non blocking mode */
-   if (setnonblock(dsi->socket, 1) < 0) {
-       LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno));
-       return -1;
-   }
    while (written < length) {
        len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
        if (len >= 0) {
            continue;
  
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+           LOG(log_debug, logtype_dsi, "dsi_stream_write: send: %s", strerror(errno));
            if (mode == DSI_NOWAIT && written == 0) {
                /* DSI_NOWAIT is used by attention give up in this case. */
                written = -1;
    dsi->write_count += written;
  
  exit:
-   if (setnonblock(dsi->socket, 0) < 0) {
-       LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno));
-       written = -1;
-   }
    dsi->in_write--;
    return written;
  }
@@@ -198,15 -186,11 +185,11 @@@ ssize_t dsi_stream_read_file(DSI *dsi, 
    size_t written;
    ssize_t len;
  
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
    dsi->in_write++;
    written = 0;
  
-   /* non blocking mode */
-   if (setnonblock(dsi->socket, 1) < 0) {
-       LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno));
-       return -1;
-   }
    while (written < length) {
      len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
          
            }
            continue;
        }
-       LOG(log_error, logtype_dsi, "dsi_stream_write: %s", strerror(errno));
+       LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno));
        break;
      }
      else if (!len) {
          written += len;
    }
  
-   if (setnonblock(dsi->socket, 0) < 0) {
-       LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno));
-       return -1;
-   }
    dsi->write_count += written;
    dsi->in_write--;
    return written;
  static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
  {
      size_t nbe = 0;
-     
-     if (dsi->start) {        
-         nbe = dsi->eof - dsi->start;
  
-         if (nbe > 0) {
-            nbe = min((size_t)nbe, count);
-            memcpy(buf, dsi->start, nbe);
-            dsi->start += nbe;
+     if (dsi->buffer == NULL)
+         /* afpd master has no DSI buffering */
+         return 0;
  
-            if (dsi->eof == dsi->start) 
-                dsi->start = dsi->eof = dsi->buffer;
+     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;
  }
  
   */
  static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
  {
-     ssize_t nbe;
-     
+     ssize_t len;
+     LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes)", count);
      if (!count)
          return 0;
  
-     nbe = from_buf(dsi, buf, count); /* 1. */
-     if (nbe)
-         return nbe;             /* 2. */
+     len = from_buf(dsi, buf, count); /* 1. */
+     if (len)
+         return len;             /* 2. */
    
-     return read(dsi->socket, buf, count); /* 3. */
+     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
   * from dsi->buffer and/or the socket.
+  *
+  * @returns length on success, some value smaller then length indicates an error
   */
  size_t dsi_stream_read(DSI *dsi, void *data, const size_t length)
  {
    size_t stored;
    ssize_t len;
  
+   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) {
-       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 (len || stored || dsi->read_count) {
-           if (! (dsi->flags & DSI_DISCONNECTED))
-               LOG(log_error, logtype_dsi, "dsi_stream_read(fd: %i): len:%d, %s",
-                   dsi->socket, len, (len < 0) ? strerror(errno) : "unexpected EOF");
+       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");
+           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 (len || stored || dsi->read_count) {
+               if (! (dsi->flags & DSI_DISCONNECTED)) {
+                   LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s",
+                       len, (len < 0) ? strerror(errno) : "unexpected EOF");
+               }
+               return 0;
+           }
+           break;
        }
-       break;
-     }
    }
  
    dsi->read_count += stored;
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes): got: %u", length, stored);
    return stored;
  }
  
@@@ -332,8 -333,9 +332,9 @@@ static size_t dsi_buffered_stream_read(
  {
    size_t len;
    size_t buflen;
+   LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length);
    
-   dsi_init_buffer(dsi);
    len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */
    dsi->read_count += len;
    if (len == length) {          /* got enough bytes from there ? */
@@@ -375,11 -377,12 +376,12 @@@ static void unblock_sig(DSI *dsi
  int dsi_stream_send(DSI *dsi, void *buf, size_t length)
  {
    char block[DSI_BLOCKSIZ];
- #ifdef USE_WRITEV
    struct iovec iov[2];
    size_t towrite;
    ssize_t len;
- #endif /* USE_WRITEV */
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
+       length ? length : sizeof(block));
  
    block[0] = dsi->header.dsi_flags;
    block[1] = dsi->header.dsi_command;
    
    /* block signals */
    block_sig(dsi);
- #ifdef USE_WRITEV
    iov[0].iov_base = block;
    iov[0].iov_len = sizeof(block);
    iov[1].iov_base = buf;
    towrite = sizeof(block) + length;
    dsi->write_count += towrite;
    while (towrite > 0) {
-     if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || 
-       !len)
-       continue;
+       if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || (len == 0))
+           continue;
      
-     if ((size_t)len == towrite) /* wrote everything out */
-       break;
-     else if (len < 0) { /* error */
-       if (errno == EAGAIN || errno == EWOULDBLOCK) {
-           if (!dsi_peek(dsi)) {
-               continue;
+       if ((size_t)len == towrite) /* wrote everything out */
+           break;
+       else if (len < 0) { /* error */
+           if (errno == EAGAIN || errno == EWOULDBLOCK) {
+               if (!dsi_peek(dsi)) {
+                   continue;
+               }
            }
+           LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
+           unblock_sig(dsi);
+           return 0;
        }
-       LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno));
-       unblock_sig(dsi);
-       return 0;
-     }
      
-     towrite -= len;
-     if (towrite > length) { /* skip part of header */
-       iov[0].iov_base = (char *) iov[0].iov_base + len;
-       iov[0].iov_len -= len;
-     } else { /* skip to data */
-       if (iov[0].iov_len) {
-       len -= iov[0].iov_len;
-       iov[0].iov_len = 0;
+       towrite -= len;
+       if (towrite > length) { /* skip part of header */
+           iov[0].iov_base = (char *) iov[0].iov_base + len;
+           iov[0].iov_len -= len;
+       } else { /* skip to data */
+           if (iov[0].iov_len) {
+               len -= iov[0].iov_len;
+               iov[0].iov_len = 0;
+           }
+           iov[1].iov_base = (char *) iov[1].iov_base + len;
+           iov[1].iov_len -= len;
        }
-       iov[1].iov_base = (char *) iov[1].iov_base + len;
-       iov[1].iov_len -= len;
-     }
    }
    
- #else /* USE_WRITEV */
-   /* write the header then data */
-   if ((dsi_stream_write(dsi, block, sizeof(block), 1) != sizeof(block)) ||
-             (dsi_stream_write(dsi, buf, length, 0) != length)) {
-       unblock_sig(dsi);
-       return 0;
-   }
- #endif /* USE_WRITEV */
    unblock_sig(dsi);
    return 1;
  }
@@@ -460,6 -452,8 +451,8 @@@ int dsi_stream_receive(DSI *dsi, void *
  {
    char block[DSI_BLOCKSIZ];
  
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
    /* read in the header */
    if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) 
      return 0;
index da61a4371cc6968e84915e1bb2ba7eab0bc353ff,070ca93b1a99aedb24dc5fc510d302c26fc40fe3..5e4ae8597a42e1b2f73c1fccd0b3f8cd6b3fc249
@@@ -9,59 -9,13 +9,12 @@@
  #include <sys/stat.h>
  #include <atalk/logger.h>
  #include <errno.h>
 -
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
  
  #include <atalk/unicode.h>
- #include "ucs2_casetable.h"
  #include "precompose.h"
  #include "byteorder.h"
  
- /*******************************************************************
-  Convert a wide character to upper/lower case.
- ********************************************************************/
- ucs2_t toupper_w(ucs2_t val)
- {
-       if ( val >= 0x0040 && val <= 0x007F)
-               return upcase_table_1[val-0x0040];
-       if ( val >= 0x00C0 && val <= 0x02BF)
-               return upcase_table_2[val-0x00C0];
-       if ( val >= 0x0380 && val <= 0x04FF)
-               return upcase_table_3[val-0x0380];
-       if ( val >= 0x0540 && val <= 0x05BF)
-               return upcase_table_4[val-0x0540];
-       if ( val >= 0x1E00 && val <= 0x1FFF)
-               return upcase_table_5[val-0x1E00];
-       if ( val >= 0x2140 && val <= 0x217F)
-               return upcase_table_6[val-0x2140];
-       if ( val >= 0x24C0 && val <= 0x24FF)
-               return upcase_table_7[val-0x24C0];
-       if ( val >= 0xFF40 && val <= 0xFF7F)
-               return upcase_table_8[val-0xFF40];
-       return (val);
- }
- ucs2_t tolower_w(ucs2_t val)
- {
-       if ( val >= 0x0040 && val <= 0x007F)
-               return lowcase_table_1[val-0x0040];
-       if ( val >= 0x00C0 && val <= 0x023F)
-               return lowcase_table_2[val-0x00C0];
-       if ( val >= 0x0380 && val <= 0x057F)
-               return lowcase_table_3[val-0x0380];
-       if ( val >= 0x1E00 && val <= 0x1FFF)
-               return lowcase_table_4[val-0x1E00];
-       if ( val >= 0x2140 && val <= 0x217F)
-               return lowcase_table_5[val-0x2140];
-       if ( val >= 0x2480 && val <= 0x24FF)
-               return lowcase_table_6[val-0x2480];
-       if ( val >= 0xFF00 && val <= 0xFF3F)
-               return lowcase_table_7[val-0xFF00];
-       return (val);
- }
  /*******************************************************************
   Convert a string to lower case.
   return True if any char is converted
index 957bf527c14dc72e24ccb752667bbec558bb122f,af5d3c9ff6b10515d0aaebc26b6350ea3531c022..17ae747cb9ac45c278996965d57d697f8df91a65
@@@ -1,13 -1,14 +1,13 @@@
  # Makefile.am for libatalk/util/
  
 -noinst_LTLIBRARIES = libutil.la
 +pkgconfdir = @PKGCONFDIR@
  
 -AM_CFLAGS = -I$(top_srcdir)/sys
 +noinst_LTLIBRARIES = libutil.la
  
  libutil_la_SOURCES = \
 -      atalk_addr.c    \
        bprint.c        \
+       cnid.c          \
        fault.c         \
-       ftw.c           \
        getiface.c      \
        locking.c   \
        logger.c        \
        server_ipc.c    \
        server_lock.c   \
        socket.c        \
 -      strcasestr.c    \
        strdicasecmp.c  \
 -      strlcpy.c       \
 -      volinfo.c \
 +      volinfo.c       \
        unix.c
  
- libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\"
++libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\"
++
+ if HAVE_ATFUNCS
+ libutil_la_SOURCES += ftw.c
+ endif
index e8ed4d4d956382d06330ff02767f0efbf2afe18e,ecefbd2cb7502c65ff349e68b3b845f65e88d91b..47e9baa2549bee28b42cbf1695f855e534476d89
  
  #include <stdlib.h>
  #include <string.h>
 -#ifdef HAVE_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #include <signal.h>
  #include <errno.h>
 -
 -/* POSIX.1 sys/wait.h check */
  #include <sys/types.h>
 -#ifdef HAVE_SYS_WAIT_H
  #include <sys/wait.h>
 -#endif /* HAVE_SYS_WAIT_H */
  #include <sys/time.h>
  
  #include <atalk/logger.h>
@@@ -331,9 -337,9 +331,9 @@@ void server_child_kill_one_by_id(server
                                  "Session with different pid[%u]", child->pid);
                          }
                      } else {
-                         kill_child(child);
-                         LOG(log_note, logtype_default,
-                             "Terminated disconnected session[%u]", child->pid);
+                         /* One client with multiple sessions */
+                         LOG(log_debug, logtype_default,
+                             "Found another session[%u] for client[%u]", child->pid, pid);
                      }
                  }
              } else {
                  child->time = boottime;
                  if (child->clientid)
                      free(child->clientid);
-                 LOG(log_debug, logtype_default, "Setting client ID for %d", child->pid);
+                 LOG(log_debug, logtype_default, "Setting client ID for %u", child->pid);
                  child->uid = uid;
                  child->valid = 1;
                  child->idlen = idlen;
diff --combined libatalk/vfs/ea_sys.c
index a4fa75b5c97291f3a88d56665b27b68c4c8d1553,77ab783b04c8d3546f20ecb66e5d6335e387ae82..5b210d81de9042d9227bbd793d7dce0de9e07eb1
@@@ -1,4 -1,5 +1,4 @@@
  /*
 -  $Id: ea_sys.c,v 1.8 2010-04-13 08:05:06 franklahm Exp $
    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
  
    This program is free software; you can redistribute it and/or modify
  #include <sys/stat.h>
  #include <fcntl.h>
  #include <dirent.h>
 -
 -#if HAVE_ATTR_XATTR_H
 -#include <attr/xattr.h>
 -#elif HAVE_SYS_XATTR_H
 -#include <sys/xattr.h>
 -#endif
 -
 -#ifdef HAVE_SYS_EA_H
 -#include <sys/ea.h>
 -#endif
 -
 -#ifdef HAVE_SYS_EXTATTR_H
 -#include <sys/extattr.h>
 -#endif
 +#include <arpa/inet.h>
  
  #include <atalk/adouble.h>
  #include <atalk/ea.h>
  #include <atalk/unix.h>
  #include <atalk/compat.h>
  
 -#ifndef ENOATTR
 -#define ENOATTR ENODATA
 -#endif
 -
 -
  /**********************************************************************************
   * EA VFS funcs for storing EAs in nativa filesystem EAs
   **********************************************************************************/
@@@ -196,8 -215,6 +196,8 @@@ int sys_get_eacontent(VFS_FUNC_ARGS_EA_
   *
   * Copies names of all EAs of uname as consecutive C strings into rbuf.
   * Increments *rbuflen accordingly.
 + * We hide the adouble:ea extended attributes here, but we currently
 + * allow reading, writing and deleteting them.
   */
  int sys_list_eas(VFS_FUNC_ARGS_EA_LIST)
  {
      ptr = buf;
      while (ret > 0)  {
          len = strlen(ptr);
 -
 -        /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */
 -        if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) {
 -            ret = AFPERR_MISC;
 -            goto exit;
 -        }
 -
 -        LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr);
 -
 -        attrbuflen += nlen + 1;
 -        if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) {
 -            /* Next EA name could overflow, so bail out with error.
 -               FIXME: evantually malloc/memcpy/realloc whatever.
 -               Is it worth it ? */
 -            LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname);
 -            ret = AFPERR_MISC;
 -            goto exit;
 +        if (NOT_NETATALK_EA(ptr)) {
 +            /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */
 +            if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) {
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +
 +            LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr);
 +
 +            attrbuflen += nlen + 1;
 +            if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) {
 +                /* Next EA name could overflow, so bail out with error.
 +                   FIXME: evantually malloc/memcpy/realloc whatever.
 +                   Is it worth it ? */
 +                LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname);
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
          }
 -        ret -= len +1;
 -        ptr += len +1;
 +        ret -= len + 1;
 +        ptr += len + 1;
      }
  
      ret = AFP_OK;
@@@ -309,15 -325,20 +309,20 @@@ int sys_set_ea(VFS_FUNC_ARGS_EA_SET
          switch(errno) {
          case OPEN_NOFOLLOW_ERRNO:
              /* its a symlink and client requested O_NOFOLLOW  */
-             LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): encountered symlink with kXAttrNoFollow",
-                 uname, attruname);
+             LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): encountered symlink with kXAttrNoFollow",
+                 getcwdpath(), uname, attruname);
              return AFP_OK;
          case EEXIST:
-             LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): EA already exists",
-                 uname, attruname);
+             LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists",
+                 getcwdpath(), uname, attruname);
              return AFPERR_EXIST;
          default:
-             LOG(log_error, logtype_afpd, "sys_set_ea(%s/%s): error: %s", uname, attruname, strerror(errno));
+             LOG(log_error, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s', size: %u, flags: %s|%s|%s): %s",
+                 getcwdpath(), uname, attruname, attrsize, 
+                 oflag & O_CREAT ? "XATTR_CREATE" : "-",
+                 oflag & O_TRUNC ? "XATTR_REPLACE" : "-",
+                 oflag & O_NOFOLLOW ? "O_NOFOLLOW" : "-",
+                 strerror(errno));
              return AFPERR_MISC;
          }
      }
diff --combined libatalk/vfs/extattr.c
index 0115c1534bca209cb9b43e82ed2ba32a8a93695b,0000000000000000000000000000000000000000..bdae873e6c05ef3682a9db708167addd890ddf0c
mode 100644,000000..100644
--- /dev/null
@@@ -1,874 -1,0 +1,876 @@@
-               LOG(log_debug, logtype_default, "closedir dirp failed: %s\n",strerror(errno));
 +/* 
 +   Unix SMB/CIFS implementation.
 +   Samba system utilities
 +   Copyright (C) Andrew Tridgell 1992-1998
 +   Copyright (C) Jeremy Allison  1998-2005
 +   Copyright (C) Timur Bakeyev        2005
 +   Copyright (C) Bjoern Jacke    2006-2007
 +   
 +   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.
 +   
 +   You should have received a copy of the GNU General Public License
 +   along with this program; if not, write to the Free Software
 +   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 +   
 +   sys_copyxattr modified from LGPL2.1 libattr copyright
 +   Copyright (C) 2001-2002 Silicon Graphics, Inc.  All Rights Reserved.
 +   Copyright (C) 2001 Andreas Gruenbacher.
 +      
 +   Samba 3.0.28, modified for netatalk.
 +*/
 +
 +#ifdef HAVE_CONFIG_H
 +#include "config.h"
 +#endif
 +
 +#include <stdlib.h>
 +#include <string.h>
 +#include <sys/types.h>
 +#include <errno.h>
 +
 +#if HAVE_ATTR_XATTR_H
 +#include <attr/xattr.h>
 +#elif HAVE_SYS_XATTR_H
 +#include <sys/xattr.h>
 +#endif
 +
 +#ifdef HAVE_SYS_EA_H
 +#include <sys/ea.h>
 +#endif
 +
 +#ifdef HAVE_ATTROPEN
 +
 +#include <dirent.h>
 +#endif
 +
 +#ifdef HAVE_SYS_EXTATTR_H
 +#include <sys/extattr.h>
 +#endif
 +
 +#include <atalk/adouble.h>
 +#include <atalk/util.h>
 +#include <atalk/logger.h>
 +#include <atalk/ea.h>
 +#include <atalk/compat.h>
 +
 +/******** Solaris EA helper function prototypes ********/
 +#ifdef HAVE_ATTROPEN
 +#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP
 +static int solaris_write_xattr(int attrfd, const char *value, size_t size);
 +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size);
 +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size);
 +static int solaris_unlinkat(int attrdirfd, const char *name);
 +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode);
 +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode);
 +#endif
 +
 +/**************************************************************************
 + Wrappers for extented attribute calls. Based on the Linux package with
 + support for IRIX and (Net|Free)BSD also. Expand as other systems have them.
 +****************************************************************************/
 +static char attr_name[256 +5] = "user.";
 +
 +static const char *prefix(const char *uname)
 +{
 +#if defined(HAVE_ATTROPEN)
 +      return uname;
 +#else
 +      strlcpy(attr_name +5, uname, 256);
 +      return attr_name;
 +#endif
 +}
 +
 +ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size)
 +{
 +      const char *name = prefix(uname);
 +
 +#if defined(HAVE_GETXATTR)
 +#ifndef XATTR_ADD_OPT
 +      return getxattr(path, name, value, size);
 +#else
 +      int options = 0;
 +      return getxattr(path, name, value, size, 0, options);
 +#endif
 +#elif defined(HAVE_GETEA)
 +      return getea(path, name, value, size);
 +#elif defined(HAVE_EXTATTR_GET_FILE)
 +      ssize_t retval;
 +      /*
 +       * The BSD implementation has a nasty habit of silently truncating
 +       * the returned value to the size of the buffer, so we have to check
 +       * that the buffer is large enough to fit the returned value.
 +       */
 +      if((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
 +        if (size == 0)
 +            /* size == 0 means only return size */
 +            return retval;
 +              if (retval > size) {
 +                      errno = ERANGE;
 +                      return -1;
 +              }
 +              if ((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
 +                      return retval;
 +      }
 +
 +      LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno));
 +      return -1;
 +#elif defined(HAVE_ATTR_GET)
 +      int retval, flags = 0;
 +      int valuelength = (int)size;
 +      char *attrname = strchr(name,'.') + 1;
 +      
 +      if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
 +
 +      retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
 +
 +      return retval ? retval : valuelength;
 +#elif defined(HAVE_ATTROPEN)
 +      ssize_t ret = -1;
 +      int attrfd = solaris_attropen(path, name, O_RDONLY, 0);
 +      if (attrfd >= 0) {
 +              ret = solaris_read_xattr(attrfd, value, size);
 +              close(attrfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +ssize_t sys_fgetxattr (int filedes, const char *uname, void *value, size_t size)
 +{
 +    const char *name = prefix(uname);
 +
 +#if defined(HAVE_FGETXATTR)
 +#ifndef XATTR_ADD_OPT
 +    return fgetxattr(filedes, name, value, size);
 +#else
 +    int options = 0;
 +    return fgetxattr(filedes, name, value, size, 0, options);
 +#endif
 +#elif defined(HAVE_FGETEA)
 +    return fgetea(filedes, name, value, size);
 +#elif defined(HAVE_EXTATTR_GET_FD)
 +    char *s;
 +    ssize_t retval;
 +    int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
 +        EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
 +    const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
 +
 +    if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) {
 +        if(retval > size) {
 +            errno = ERANGE;
 +            return -1;
 +        }
 +        if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0)
 +            return retval;
 +    }
 +
 +    LOG(log_debug, logtype_default, "sys_fgetxattr: extattr_get_fd(): %s",
 +        strerror(errno)));
 +    return -1;
 +#elif defined(HAVE_ATTR_GETF)
 +    int retval, flags = 0;
 +    int valuelength = (int)size;
 +    char *attrname = strchr(name,'.') + 1;
 +
 +    if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
 +
 +    retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags);
 +
 +    return retval ? retval : valuelength;
 +#elif defined(HAVE_ATTROPEN)
 +    ssize_t ret = -1;
 +    int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0);
 +    if (attrfd >= 0) {
 +        ret = solaris_read_xattr(attrfd, value, size);
 +        close(attrfd);
 +    }
 +    return ret;
 +#else
 +    errno = ENOSYS;
 +    return -1;
 +#endif
 +}
 +
 +ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size)
 +{
 +      const char *name = prefix(uname);
 +
 +#if defined(HAVE_LGETXATTR)
 +      return lgetxattr(path, name, value, size);
 +#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT)
 +      int options = XATTR_NOFOLLOW;
 +      return getxattr(path, name, value, size, 0, options);
 +#elif defined(HAVE_LGETEA)
 +      return lgetea(path, name, value, size);
 +#elif defined(HAVE_EXTATTR_GET_LINK)
 +      ssize_t retval;
 +      if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
 +              if(retval > size) {
 +                      errno = ERANGE;
 +                      return -1;
 +              }
 +              if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
 +                      return retval;
 +      }
 +      
 +      LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno));
 +      return -1;
 +#elif defined(HAVE_ATTR_GET)
 +      int retval, flags = ATTR_DONTFOLLOW;
 +      int valuelength = (int)size;
 +      char *attrname = strchr(name,'.') + 1;
 +      
 +      if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
 +
 +      retval = attr_get(path, attrname, (char *)value, &valuelength, flags);
 +
 +      return retval ? retval : valuelength;
 +#elif defined(HAVE_ATTROPEN)
 +      ssize_t ret = -1;
 +      int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
 +      if (attrfd >= 0) {
 +              ret = solaris_read_xattr(attrfd, value, size);
 +              close(attrfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +#if defined(HAVE_EXTATTR_LIST_FILE)
 +
 +#define EXTATTR_PREFIX(s)     (s), (sizeof((s))-1)
 +
 +static struct {
 +        int space;
 +      const char *name;
 +      size_t len;
 +} 
 +extattr[] = {
 +      { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("") },
 +        { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("") },
 +};
 +
 +typedef union {
 +      const char *path;
 +      int filedes;
 +} extattr_arg;
 +
 +static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size)
 +{
 +      ssize_t list_size;
 +      int i, len;
 +
 +    switch(type) {
 +#if defined(HAVE_EXTATTR_LIST_FILE)
 +    case 0:
 +        list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size);
 +        break;
 +#endif
 +#if defined(HAVE_EXTATTR_LIST_LINK)
 +    case 1:
 +        list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size);
 +        break;
 +#endif
 +#if defined(HAVE_EXTATTR_LIST_FD)
 +    case 2:
 +        list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size);
 +        break;
 +#endif
 +    default:
 +        errno = ENOSYS;
 +        return -1;
 +    }
 +
 +    /* Some error happend. Errno should be set by the previous call */
 +    if(list_size < 0)
 +        return -1;
 +
 +    /* No attributes */
 +    if(list_size == 0)
 +        return 0;
 +
 +    /* XXX: Call with an empty buffer may be used to calculate
 +       necessary buffer size. Unfortunately, we can't say, how
 +       many attributes were returned, so here is the potential
 +       problem with the emulation.
 +    */
 +    if(list == NULL)
 +        return list_size;
 +
 +    /* Buffer is too small to fit the results */
 +    if(list_size > size) {
 +        errno = ERANGE;
 +        return -1;
 +    }
 +
 +    /* Convert from pascal strings to C strings */
 +    len = list[0];
 +    memmove(list, list + 1, list_size);
 +
 +    for(i = len; i < list_size; ) {
 +        LOG(log_maxdebug, logtype_afpd, "len: %d, i: %d", len, i);
 +
 +        len = list[i];
 +        list[i] = '\0';
 +        i += len + 1;
 +    }
 +
 +      return list_size;
 +}
 +
 +#endif
 +
 +#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
 +static char attr_buffer[ATTR_MAX_VALUELEN];
 +
 +static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags)
 +{
 +      int retval = 0, index;
 +      attrlist_cursor_t *cursor = 0;
 +      int total_size = 0;
 +      attrlist_t * al = (attrlist_t *)attr_buffer;
 +      attrlist_ent_t *ae;
 +      size_t ent_size, left = size;
 +      char *bp = list;
 +
 +      while (True) {
 +          if (filedes)
 +              retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
 +          else
 +              retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
 +          if (retval) break;
 +          for (index = 0; index < al->al_count; index++) {
 +              ae = ATTR_ENTRY(attr_buffer, index);
 +              ent_size = strlen(ae->a_name) + sizeof("user.");
 +              if (left >= ent_size) {
 +                  strncpy(bp, "user.", sizeof("user."));
 +                  strncat(bp, ae->a_name, ent_size - sizeof("user."));
 +                  bp += ent_size;
 +                  left -= ent_size;
 +              } else if (size) {
 +                  errno = ERANGE;
 +                  retval = -1;
 +                  break;
 +              }
 +              total_size += ent_size;
 +          }
 +          if (al->al_more == 0) break;
 +      }
 +      if (retval == 0) {
 +          flags |= ATTR_ROOT;
 +          cursor = 0;
 +          while (True) {
 +              if (filedes)
 +                  retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
 +              else
 +                  retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor);
 +              if (retval) break;
 +              for (index = 0; index < al->al_count; index++) {
 +                  ae = ATTR_ENTRY(attr_buffer, index);
 +                  ent_size = strlen(ae->a_name) + sizeof("system.");
 +                  if (left >= ent_size) {
 +                      strncpy(bp, "system.", sizeof("system."));
 +                      strncat(bp, ae->a_name, ent_size - sizeof("system."));
 +                      bp += ent_size;
 +                      left -= ent_size;
 +                  } else if (size) {
 +                      errno = ERANGE;
 +                      retval = -1;
 +                      break;
 +                  }
 +                  total_size += ent_size;
 +              }
 +              if (al->al_more == 0) break;
 +          }
 +      }
 +      return (ssize_t)(retval ? retval : total_size);
 +}
 +
 +#endif
 +
 +#if defined(HAVE_LISTXATTR)
 +static ssize_t remove_user(ssize_t ret, char *list, size_t size)
 +{
 +      size_t len;
 +      char *ptr;
 +      char *ptr1;
 +      ssize_t ptrsize;
 +      
 +      if (ret <= 0 || size == 0)
 +              return ret;
 +      ptrsize = ret;
 +      ptr = ptr1 = list;
 +      while (ptrsize > 0) {
 +              len = strlen(ptr1) +1;
 +              ptrsize -= len;
 +              if (strncmp(ptr1, "user.",5)) {
 +                      ptr1 += len;
 +                      continue;
 +              }
 +              memmove(ptr, ptr1 +5, len -5);
 +              ptr += len -5;
 +              ptr1 += len;
 +      }
 +      return ptr -list;
 +}
 +#endif
 +
 +ssize_t sys_listxattr (const char *path, char *list, size_t size)
 +{
 +#if defined(HAVE_LISTXATTR)
 +      ssize_t ret;
 +
 +#ifndef XATTR_ADD_OPT
 +      ret = listxattr(path, list, size);
 +#else
 +      int options = 0;
 +      ret = listxattr(path, list, size, options);
 +#endif
 +      return remove_user(ret, list, size);
 +
 +#elif defined(HAVE_LISTEA)
 +      return listea(path, list, size);
 +#elif defined(HAVE_EXTATTR_LIST_FILE)
 +      extattr_arg arg;
 +      arg.path = path;
 +      return bsd_attr_list(0, arg, list, size);
 +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
 +      return irix_attr_list(path, 0, list, size, 0);
 +#elif defined(HAVE_ATTROPEN)
 +      ssize_t ret = -1;
 +      int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
 +      if (attrdirfd >= 0) {
 +              ret = solaris_list_xattr(attrdirfd, list, size);
 +              close(attrdirfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +ssize_t sys_llistxattr (const char *path, char *list, size_t size)
 +{
 +#if defined(HAVE_LLISTXATTR)
 +      ssize_t ret;
 +
 +      ret = llistxattr(path, list, size);
 +      return remove_user(ret, list, size);
 +#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT)
 +      ssize_t ret;
 +      int options = XATTR_NOFOLLOW;
 +
 +      ret = listxattr(path, list, size, options);
 +      return remove_user(ret, list, size);
 +
 +#elif defined(HAVE_LLISTEA)
 +      return llistea(path, list, size);
 +#elif defined(HAVE_EXTATTR_LIST_LINK)
 +      extattr_arg arg;
 +      arg.path = path;
 +      return bsd_attr_list(1, arg, list, size);
 +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H)
 +      return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW);
 +#elif defined(HAVE_ATTROPEN)
 +      ssize_t ret = -1;
 +      int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
 +      if (attrdirfd >= 0) {
 +              ret = solaris_list_xattr(attrdirfd, list, size);
 +              close(attrdirfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +int sys_removexattr (const char *path, const char *uname)
 +{
 +      const char *name = prefix(uname);
 +#if defined(HAVE_REMOVEXATTR)
 +#ifndef XATTR_ADD_OPT
 +      return removexattr(path, name);
 +#else
 +      int options = 0;
 +      return removexattr(path, name, options);
 +#endif
 +#elif defined(HAVE_REMOVEEA)
 +      return removeea(path, name);
 +#elif defined(HAVE_EXTATTR_DELETE_FILE)
 +      return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname);
 +#elif defined(HAVE_ATTR_REMOVE)
 +      int flags = 0;
 +      char *attrname = strchr(name,'.') + 1;
 +      
 +      if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
 +
 +      return attr_remove(path, attrname, flags);
 +#elif defined(HAVE_ATTROPEN)
 +      int ret = -1;
 +      int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0);
 +      if (attrdirfd >= 0) {
 +              ret = solaris_unlinkat(attrdirfd, name);
 +              close(attrdirfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +int sys_lremovexattr (const char *path, const char *uname)
 +{
 +      const char *name = prefix(uname);
 +#if defined(HAVE_LREMOVEXATTR)
 +      return lremovexattr(path, name);
 +#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT)
 +      int options = XATTR_NOFOLLOW;
 +      return removexattr(path, name, options);
 +#elif defined(HAVE_LREMOVEEA)
 +      return lremoveea(path, name);
 +#elif defined(HAVE_EXTATTR_DELETE_LINK)
 +      return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, uname);
 +#elif defined(HAVE_ATTR_REMOVE)
 +      int flags = ATTR_DONTFOLLOW;
 +      char *attrname = strchr(name,'.') + 1;
 +      
 +      if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT;
 +
 +      return attr_remove(path, attrname, flags);
 +#elif defined(HAVE_ATTROPEN)
 +      int ret = -1;
 +      int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0);
 +      if (attrdirfd >= 0) {
 +              ret = solaris_unlinkat(attrdirfd, name);
 +              close(attrdirfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
 +{
 +      const char *name = prefix(uname);
 +#if defined(HAVE_SETXATTR)
 +#ifndef XATTR_ADD_OPT
 +      return setxattr(path, name, value, size, flags);
 +#else
 +      int options = 0;
 +      return setxattr(path, name, value, size, 0, options);
 +#endif
 +#elif defined(HAVE_SETEA)
 +      return setea(path, name, value, size, flags);
 +#elif defined(HAVE_EXTATTR_SET_FILE)
 +      int retval = 0;
 +      if (flags) {
 +              /* Check attribute existence */
 +              retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
 +              if (retval < 0) {
 +                      /* REPLACE attribute, that doesn't exist */
 +                      if (flags & XATTR_REPLACE && errno == ENOATTR) {
 +                              errno = ENOATTR;
 +                              return -1;
 +                      }
 +                      /* Ignore other errors */
 +              }
 +              else {
 +                      /* CREATE attribute, that already exists */
 +                      if (flags & XATTR_CREATE) {
 +                              errno = EEXIST;
 +                              return -1;
 +                      }
 +              }
 +      }
 +      retval = extattr_set_file(path, EXTATTR_NAMESPACE_USER, uname, value, size);
 +      return (retval < 0) ? -1 : 0;
 +#elif defined(HAVE_ATTR_SET)
 +      int myflags = 0;
 +      char *attrname = strchr(name,'.') + 1;
 +      
 +      if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
 +      if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
 +      if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
 +
 +      return attr_set(path, attrname, (const char *)value, size, myflags);
 +#elif defined(HAVE_ATTROPEN)
 +      int ret = -1;
 +      int myflags = O_RDWR;
 +      int attrfd;
 +      if (flags & XATTR_CREATE) myflags |= O_EXCL;
 +      if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
 +      attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
 +      if (attrfd >= 0) {
 +              ret = solaris_write_xattr(attrfd, value, size);
 +              close(attrfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +int sys_fsetxattr (int filedes, const char *uname, const void *value, size_t size, int flags)
 +{
 +    const char *name = prefix(uname);
 +
 +#if defined(HAVE_FSETXATTR)
 +#ifndef XATTR_ADD_OPT
 +    return fsetxattr(filedes, name, value, size, flags);
 +#else
 +    int options = 0;
 +    return fsetxattr(filedes, name, value, size, 0, options);
 +#endif
 +#elif defined(HAVE_FSETEA)
 +    return fsetea(filedes, name, value, size, flags);
 +#elif defined(HAVE_EXTATTR_SET_FD)
 +    char *s;
 +    int retval = 0;
 +    int attrnamespace = (strncmp(name, "system", 6) == 0) ? 
 +        EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER;
 +    const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1;
 +    if (flags) {
 +        /* Check attribute existence */
 +        retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0);
 +        if (retval < 0) {
 +            /* REPLACE attribute, that doesn't exist */
 +            if (flags & XATTR_REPLACE && errno == ENOATTR) {
 +                errno = ENOATTR;
 +                return -1;
 +            }
 +            /* Ignore other errors */
 +        }
 +        else {
 +            log_error, logtype_default            /* CREATE attribute, that already exists */
 +            if (flags & XATTR_CREATE) {
 +                errno = EEXIST;
 +                return -1;
 +            }
 +        }
 +    }
 +    retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size);
 +    return (retval < 0) ? -1 : 0;
 +#elif defined(HAVE_ATTR_SETF)
 +    int myflags = 0;
 +    char *attrname = strchr(name,'.') + 1;
 +
 +    if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
 +    if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
 +    if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
 +
 +    return attr_setf(filedes, attrname, (const char *)value, size, myflags);
 +#elif defined(HAVE_ATTROPEN)
 +    int ret = -1;
 +    int myflags = O_RDWR | O_XATTR;
 +    int attrfd;
 +    if (flags & XATTR_CREATE) myflags |= O_EXCL;
 +    if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
 +    attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE);
 +    if (attrfd >= 0) {
 +        ret = solaris_write_xattr(attrfd, value, size);
 +        close(attrfd);
 +    }
 +    return ret;
 +#else
 +    errno = ENOSYS;
 +    return -1;
 +#endif
 +}
 +
 +int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags)
 +{
 +      const char *name = prefix(uname);
 +#if defined(HAVE_LSETXATTR)
 +      return lsetxattr(path, name, value, size, flags);
 +#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT)
 +      int options = XATTR_NOFOLLOW;
 +      return setxattr(path, name, value, size, 0, options);
 +#elif defined(LSETEA)
 +      return lsetea(path, name, value, size, flags);
 +#elif defined(HAVE_EXTATTR_SET_LINK)
 +      int retval = 0;
 +      if (flags) {
 +              /* Check attribute existence */
 +              retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
 +              if (retval < 0) {
 +                      /* REPLACE attribute, that doesn't exist */
 +                      if (flags & XATTR_REPLACE && errno == ENOATTR) {
 +                              errno = ENOATTR;
 +                              return -1;
 +                      }
 +                      /* Ignore other errors */
 +              }
 +              else {
 +                      /* CREATE attribute, that already exists */
 +                      if (flags & XATTR_CREATE) {
 +                              errno = EEXIST;
 +                              return -1;
 +                      }
 +              }
 +      }
 +
 +      retval = extattr_set_link(path, EXTATTR_NAMESPACE_USER, uname, value, size);
 +      return (retval < 0) ? -1 : 0;
 +#elif defined(HAVE_ATTR_SET)
 +      int myflags = ATTR_DONTFOLLOW;
 +      char *attrname = strchr(name,'.') + 1;
 +      
 +      if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT;
 +      if (flags & XATTR_CREATE) myflags |= ATTR_CREATE;
 +      if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE;
 +
 +      return attr_set(path, attrname, (const char *)value, size, myflags);
 +#elif defined(HAVE_ATTROPEN)
 +      int ret = -1;
 +      int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW;
 +      int attrfd;
 +      if (flags & XATTR_CREATE) myflags |= O_EXCL;
 +      if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT;
 +      attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE);
 +      if (attrfd >= 0) {
 +              ret = solaris_write_xattr(attrfd, value, size);
 +              close(attrfd);
 +      }
 +      return ret;
 +#else
 +      errno = ENOSYS;
 +      return -1;
 +#endif
 +}
 +
 +/**************************************************************************
 + helper functions for Solaris' EA support
 +****************************************************************************/
 +#ifdef HAVE_ATTROPEN
 +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size)
 +{
 +      struct stat sbuf;
 +
 +      if (fstat(attrfd, &sbuf) == -1) {
 +              return -1;
 +      }
 +
 +      /* This is to return the current size of the named extended attribute */
 +      if (size == 0) {
 +              return sbuf.st_size;
 +      }
 +
 +      /* check size and read xattr */
 +      if (sbuf.st_size > size) {
 +              return -1;
 +      }
 +
 +      return read(attrfd, value, sbuf.st_size);
 +}
 +
 +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size)
 +{
 +      ssize_t len = 0;
 +      DIR *dirp;
 +      struct dirent *de;
 +      int newfd = dup(attrdirfd);
 +      /* CAUTION: The originating file descriptor should not be
 +                  used again following the call to fdopendir().
 +                  For that reason we dup() the file descriptor
 +                  here to make things more clear. */
 +      dirp = fdopendir(newfd);
 +
 +      while ((de = readdir(dirp))) {
 +              size_t listlen;
 +              if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") ||
 +                   !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw")) 
 +              {
 +                      /* we don't want "." and ".." here: */
 +                      LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name);
 +                      continue;
 +              }
 +
 +              listlen = strlen(de->d_name);
 +              if (size == 0) {
 +                      /* return the current size of the list of extended attribute names*/
 +                      len += listlen + 1;
 +              } else {
 +                      /* check size and copy entry + nul into list. */
 +                      if ((len + listlen + 1) > size) {
 +                              errno = ERANGE;
 +                              len = -1;
 +                              break;
 +                      } else {
 +                              strcpy(list + len, de->d_name);
 +                              len += listlen;
 +                              list[len] = '\0';
 +                              ++len;
 +                      }
 +              }
 +      }
 +
 +      if (closedir(dirp) == -1) {
-               LOG(log_maxdebug, logtype_default, "attropen FAILED: path: %s, name: %s, errno: %s",
-             path, attrpath, strerror(errno));
++              LOG(log_error, logtype_default, "closedir dirp: %s",strerror(errno));
 +              return -1;
 +      }
 +      return len;
 +}
 +
 +static int solaris_unlinkat(int attrdirfd, const char *name)
 +{
 +      if (unlinkat(attrdirfd, name, 0) == -1) {
 +              return -1;
 +      }
 +      return 0;
 +}
 +
 +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode)
 +{
 +      int filedes = attropen(path, attrpath, oflag, mode);
 +      if (filedes == -1) {
-               LOG(log_maxdebug, logtype_default, "openat FAILED: fd: %d, path: %s, errno: %s",
-             filedes, path, strerror(errno));
++        if (errno != ENOENT)
++            LOG(log_error, logtype_default, "attropen(\"%s\", ea:'%s'): %s",
++                path, attrpath, strerror(errno));
 +        errno = ENOATTR;
 +      }
 +      return filedes;
 +}
 +
 +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode)
 +{
 +      int filedes = openat(fildes, path, oflag, mode);
 +      if (filedes == -1) {
-               LOG(log_maxdebug, logtype_default, "solaris_write_xattr FAILED!");
++              LOG(log_error, logtype_default, "openat(\"%s\"): %s",
++            path, strerror(errno));
 +      }
 +      return filedes;
 +}
 +
 +static int solaris_write_xattr(int attrfd, const char *value, size_t size)
 +{
 +      if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) {
 +              return 0;
 +      } else {
++              LOG(log_error, logtype_default, "solaris_write_xattr: %s",
++            strerror(errno));
 +              return -1;
 +      }
 +}
 +
 +#endif /*HAVE_ATTROPEN*/
 +
diff --combined libatalk/vfs/unix.c
index 83c6016903e42e8615fe4232b2b4118b755ea4ce,229f1b7a216e25309c3c581c5c9fcc6e3a1ca6e5..5e0588dfd171bf54e9b6b7410c292639aaeabb1b
@@@ -22,7 -22,6 +22,7 @@@
  #include <atalk/logger.h>
  #include <atalk/unix.h>
  #include <atalk/acl.h>
 +#include <atalk/compat.h>
  
  /* -----------------------------
     a dropbox is a folder where w is set but not r eg:
@@@ -33,6 -32,29 +33,6 @@@ int stickydirmode(const char *name, con
  {
      int retval = 0;
  
 -#ifdef DROPKLUDGE
 -    /* Turn on the sticky bit if this is a drop box, also turn off the setgid bit */
 -    if ((dropbox & AFPVOL_DROPBOX)) {
 -        int uid;
 -
 -        if ( ( (mode & S_IWOTH) && !(mode & S_IROTH)) ||
 -             ( (mode & S_IWGRP) && !(mode & S_IRGRP)) )
 -        {
 -            uid=geteuid();
 -            if ( seteuid(0) < 0) {
 -                LOG(log_error, logtype_afpd, "stickydirmode: unable to seteuid root: %s", strerror(errno));
 -            }
 -            if ( (retval=chmod( name, ( (DIRBITS | mode | S_ISVTX) & ~v_umask) )) < 0) {
 -                LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) );
 -            } else {
 -                LOG(log_debug, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(retval) );
 -            }
 -            seteuid(uid);
 -            return retval;
 -        }
 -    }
 -#endif /* DROPKLUDGE */
 -
      /*
       *  Ignore EPERM errors:  We may be dealing with a directory that is
       *  group writable, in which case chmod will fail.
@@@ -79,15 -101,15 +79,15 @@@ int setfilmode(const char * name, mode_
  /*
   * @brief system rmdir with afp error code.
   *
-  * Supports *at semantics (cf openat) if HAVE_RENAMEAT. Pass dirfd=-1 to ignore this.
+  * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this.
   */
  int netatalk_rmdir_all_errors(int dirfd, const char *name)
  {
      int err;
  
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if (dirfd == -1)
-         dirfd = ATFD_CWD;
+         dirfd = AT_FDCWD;
      err = unlinkat(dirfd, name, AT_REMOVEDIR);
  #else
      err = rmdir(name);
  /*
   * @brief System rmdir with afp error code, but ENOENT is not an error.
   *
-  * Supports *at semantics (cf openat) if HAVE_RENAMEAT. Pass dirfd=-1 to ignore this.
+  * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this.
   */
  int netatalk_rmdir(int dirfd, const char *name)
  {
@@@ -166,7 -188,7 +166,7 @@@ char *fullpathname(const char *name
   **************************************************************************/
  
  /* 
-  * Supports *at semantics if HAVE_RENAMEAT, pass dirfd=-1 to ignore this
+  * Supports *at semantics if HAVE_ATFUNCS, pass dirfd=-1 to ignore this
   */
  int copy_file(int dirfd, const char *src, const char *dst, mode_t mode)
  {
      size_t  buflen;
      char   filebuf[8192];
  
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if (dirfd == -1)
-         dirfd = ATFD_CWD;
+         dirfd = AT_FDCWD;
      sfd = openat(dirfd, src, O_RDONLY);
  #else
      sfd = open(src, O_RDONLY);
@@@ -245,7 -267,7 +245,7 @@@ exit
   */
  int netatalk_unlinkat(int dirfd, const char *name)
  {
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if (dirfd == -1)
          dirfd = AT_FDCWD;
  
  /*
   * @brief This is equivalent of unix rename()
   *
-  * unix_rename mulitplexes rename and renameat. If we dont HAVE_RENAMEAT, sfd and dfd
+  * unix_rename mulitplexes rename and renameat. If we dont HAVE_ATFUNCS, sfd and dfd
   * are ignored.
   *
-  * @param sfd        (r) if we HAVE_RENAMEAT, -1 gives AT_FDCWD
+  * @param sfd        (r) if we HAVE_ATFUNCS, -1 gives AT_FDCWD
   * @param oldpath    (r) guess what
   * @param dfd        (r) same as sfd
   * @param newpath    (r) guess what
   */
  int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath)
  {
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if (sfd == -1)
          sfd = AT_FDCWD;
      if (dfd == -1)
  #else
      if (rename(oldpath, newpath) < 0)
          return -1;
- #endif  /* HAVE_RENAMEAT */
+ #endif  /* HAVE_ATFUNCS */
  
      return 0;
  }
  /* 
   * @brief stat/fsstatat multiplexer
   *
-  * statat mulitplexes stat and fstatat. If we dont HAVE_RENAMEAT, dirfd is ignored.
+  * statat mulitplexes stat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored.
   *
-  * @param dirfd   (r) Only used if HAVE_RENAMEAT, ignored else, -1 gives AT_FDCWD
+  * @param dirfd   (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD
   * @param path    (r) pathname
   * @param st      (rw) pointer to struct stat
   */
  int statat(int dirfd, const char *path, struct stat *st)
  {
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if (dirfd == -1)
          dirfd = AT_FDCWD;
      return (fstatat(dirfd, path, st, 0));
  /* 
   * @brief lstat/fsstatat multiplexer
   *
-  * lstatat mulitplexes lstat and fstatat. If we dont HAVE_RENAMEAT, dirfd is ignored.
+  * lstatat mulitplexes lstat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored.
   *
-  * @param dirfd   (r) Only used if HAVE_RENAMEAT, ignored else, -1 gives AT_FDCWD
+  * @param dirfd   (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD
   * @param path    (r) pathname
   * @param st      (rw) pointer to struct stat
   */
  int lstatat(int dirfd, const char *path, struct stat *st)
  {
- #ifdef HAVE_RENAMEAT
+ #ifdef HAVE_ATFUNCS
      if (dirfd == -1)
          dirfd = AT_FDCWD;
      return (fstatat(dirfd, path, st, AT_SYMLINK_NOFOLLOW));
diff --combined macros/db3-check.m4
index 6fae6187205b69d4542ace1016e7de16b6901e96,2cc59cbbb6200f40785c98d22d2c1df944dc1050..902220befa3581e0a1d6a9dea9bc4a850e4ea599
@@@ -1,3 -1,4 +1,3 @@@
 -dnl $Id: db3-check.m4,v 1.23 2010-04-12 14:28:48 franklahm Exp $
  dnl Autoconf macros to check for the Berkeley DB library
  
  dnl -- check header for minimum version and return version in
@@@ -82,12 -83,11 +82,12 @@@ AC_DEFUN([NETATALK_BDB_TRY_LINK],
  ])
  
  dnl -- This is called from configure
 -AC_DEFUN([AC_PATH_BDB],[
 +AC_DEFUN([AC_NETATALK_PATH_BDB],[
 +if test "x$bdb_required" = "xyes"; then
      trybdbdir=""
      dobdbsearch=yes
      bdb_search_dirs="/usr/local /usr"
-     search_subdirs="/ /db5 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4"
+     search_subdirs="/ /db5 /db5.1 /db51 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4"
  
      bdbfound=no
      savedcflags="$CFLAGS"
          ifelse([$1], , :, [$1])
      else
          ifelse([$2], , :, [$2])     
 +              AC_MSG_ERROR([Berkeley DB library required but not found!])
      fi
  
      CFLAGS_REMOVE_USR_INCLUDE(BDB_CFLAGS)
      AC_SUBST(BDB_LIBS)
      AC_SUBST(BDB_BIN)
      AC_SUBST(BDB_PATH)
 +fi
  ])
  
  
diff --combined man/man1/Makefile.am
index ef56aadbbee9384ffb11b4207797bd42cc782483,0154fc327a6a8686cc669b0e74d2c0f05649001c..52564afb6b3916de3408767103322e32e2a10ca5
@@@ -12,14 -12,33 +12,14 @@@ SUFFIXES= .tmpl 
            -e s@:DEFAULT_CNID_SCHEME:@${DEFAULT_CNID_SCHEME}@ \
            <$< >$@
  
- GENERATED_MANS        = uniconv.1 asip-status.pl.1
- TEMPLATE_FILES        = uniconv.1.tmpl asip-status.pl.1.tmpl
+ GENERATED_MANS        = uniconv.1 asip-status.pl.1 afpldaptest.1
+ TEMPLATE_FILES        = uniconv.1.tmpl asip-status.pl.1.tmpl afpldaptest.1.tmpl
 +
  NONGENERATED_MANS     =       ad.1 \
                                afppasswd.1 \
                                apple_dump.1 \
                                dbd.1 \
 -                              hqx2bin.1 \
 -                              macbinary.1 \
 -                              megatron.1 \
 -                              netatalk-config.1 \
 -                              single2bin.1 \
 -                              unbin.1 \
 -                              unhex.1 \
 -                              unsingle.1
 -ATALK_MANS = aecho.1 \
 -                              getzones.1 \
 -                              nbp.1 \
 -                              nbplkup.1 \
 -                              nbprgstr.1 \
 -                              nbpunrgstr.1 \
 -                              pap.1 \
 -                              papstatus.1 \
 -                              psorder.1
 -
 -if USE_APPLETALK
 -NONGENERATED_MANS += $(ATALK_MANS)
 -endif
 +                              netatalk-config.1
  
  man_MANS = $(GENERATED_MANS) $(NONGENERATED_MANS)
  CLEANFILES = $(GENERATED_MANS)
diff --combined man/man5/Makefile.am
index 84dd7b9cff6c90dfaa0cd54ea46447ea9cc6cf17,a382039eeae6ebfa7475aba6bb89d57ab5039139..2f7ec5b6cc091822761943fd771a8a71d2714f61
@@@ -17,18 -17,27 +17,20 @@@ GENERATED_MANS = AppleVolumes.default.
        afpd.conf.5 \
        netatalk.conf.5 \
        afp_ldap.conf.5 \
-       afp_signature.conf.5
+       afp_signature.conf.5 \
+       afp_voluuid.conf.5
  
  TEMPLATE_FILES = AppleVolumes.default.5.tmpl \
        afpd.conf.5.tmpl \
        netatalk.conf.5.tmpl \
        afp_ldap.conf.5.tmpl \
-       afp_signature.conf.5.tmpl
+       afp_signature.conf.5.tmpl \
+       afp_voluuid.conf.5.tmpl
  
 -ATALK_MANS = atalkd.conf.5.tmpl papd.conf.5.tmpl
 -
 -if USE_APPLETALK
 -GENERATED_MANS += atalkd.conf.5 papd.conf.5
 -TEMPLATE_FILES += $(ATALK_MANS)
 -endif
 -
  NONGENERATED_MANS = AppleVolumes.5 AppleVolumes.system.5
  
  man_MANS = $(GENERATED_MANS) $(NONGENERATED_MANS)
  
  CLEANFILES = $(GENERATED_MANS)
  
 -EXTRA_DIST = $(TEMPLATE_FILES) $(NONGENERATED_MANS) $(ATALK_MANS)
 +EXTRA_DIST = $(TEMPLATE_FILES) $(NONGENERATED_MANS)