]> arthur.barton.de Git - netatalk.git/commitdiff
Merge master
authorFrank Lahm <franklahm@googlemail.com>
Mon, 28 Nov 2011 15:31:58 +0000 (16:31 +0100)
committerFrank Lahm <franklahm@googlemail.com>
Mon, 28 Nov 2011 15:31:58 +0000 (16:31 +0100)
47 files changed:
1  2 
bin/ad/ad.h
bin/afppasswd/afppasswd.c
bin/megatron/megatron.c
configure.ac
etc/afpd/acls.c
etc/afpd/afp_dsi.c
etc/afpd/afp_options.c
etc/afpd/afs.c
etc/afpd/catsearch.c
etc/afpd/directory.c
etc/afpd/file.c
etc/afpd/fork.c
etc/afpd/main.c
etc/afpd/unix.c
etc/afpd/unix.h
etc/afpd/volume.c
etc/cnid_dbd/cmd_dbd_scanvol.c
etc/cnid_dbd/comm.c
etc/cnid_dbd/dbd_rebuild_add.c
etc/cnid_dbd/dbd_resolve.c
etc/uams/uams_dhx2_pam.c
etc/uams/uams_dhx2_passwd.c
etc/uams/uams_dhx_passwd.c
etc/uams/uams_passwd.c
etc/uams/uams_pgp.c
include/atalk/Makefile.am
include/atalk/adouble.h
include/atalk/dsi.h
include/atalk/globals.h
include/atalk/paths.h
include/atalk/util.h
include/atalk/volume.h
libatalk/adouble/ad_sendfile.c
libatalk/cnid/cnid.c
libatalk/dsi/dsi_cmdreply.c
libatalk/dsi/dsi_read.c
libatalk/dsi/dsi_stream.c
libatalk/unicode/utf16_casetable.h
libatalk/util/unix.c
libatalk/util/volinfo.c
libatalk/vfs/ea_ad.c
libatalk/vfs/unix.c
libatalk/vfs/vfs.c
macros/gssapi-check.m4
macros/iconv.m4
macros/netatalk.m4
macros/summary.m4

diff --combined bin/ad/ad.h
index 360ac17369a0a4b8f7eadd79baa6850508038837,6e41a9c02ba932cd5e2829b11b5da05f9aacb668..b0e8efba4a0d3aca3907eb31e23e525a4f315469
@@@ -1,5 -1,5 +1,5 @@@
  /* 
-    Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+    Copyright (c) 2009,2011 Frank Lahm <franklahm@gmail.com>
     
     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
  #ifndef AD_H
  #define AD_H
  
- #if !defined(__FreeBSD__)
- # define _XOPEN_SOURCE 600
- #endif
+ #include <atalk/standards.h>
  
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <signal.h>
 +#include <arpa/inet.h>
  
  #include <atalk/ftw.h>
  #include <atalk/volinfo.h>
  #include <atalk/cnid.h>
 +#include <atalk/compat.h>
  
  #define DIR_DOT_OR_DOTDOT(a) \
          ((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
index c3e60fb5d8a5888c0a0a9c86d4d68cd78db88aff,7a003560b2c9a677128a369008a02ef582e8d53d..f5778a53d03ba6b398ece79cb0d163ba44a7eb8e
@@@ -1,6 -1,4 +1,4 @@@
  /* 
-  * $Id: afppasswd.c,v 1.19 2005-04-28 20:49:19 bfernhomberg Exp $
-  *
   * Copyright 1999 (c) Adrian Sun (asun@u.washington.edu)
   * All Rights Reserved. See COPYRIGHT.
   *
  #include <stdlib.h>
  #include <string.h>
  #include <errno.h>
 -#ifdef HAVE_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #include <ctype.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #include <sys/param.h>
 -#ifdef HAVE_FCNTL_H
  #include <fcntl.h>
 -#endif /* HAVE_FCNTL_H */
  #include <pwd.h>
 -
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
  
  #include <des.h>
  
@@@ -66,7 -69,7 +64,7 @@@ static char buf[MAXPATHLEN + 1]
  #define unhex(x)  (isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A')
  static void convert_passwd(char *buf, char *newpwd, const int keyfd)
  {
 -  u_int8_t key[HEXPASSWDLEN];
 +  uint8_t key[HEXPASSWDLEN];
    Key_schedule schedule;
    unsigned int i, j;
  
@@@ -265,6 -268,7 +263,7 @@@ int main(int argc, char **argv
    flags = ((uid = getuid()) == 0) ? OPT_ISROOT : 0;
  
    if (((flags & OPT_ISROOT) == 0) && (argc > 1)) {
+     fprintf(stderr, "afppasswd (Netatalk %s)\n", VERSION);
      fprintf(stderr, "Usage: afppasswd [-acfn] [-u minuid] [-p path] [username]\n");
      fprintf(stderr, "  -a        add a new user\n");
      fprintf(stderr, "  -c        create and initialize password file or specific user\n");
diff --combined bin/megatron/megatron.c
index f47a6dac7c8e9b681b57c01c22cf771e32ce5ebf,c86ba637a8980119600e025e1c46041526c59b73..573a3dc88696c408e92a2173687cec417c978107
@@@ -1,7 -1,3 +1,3 @@@
- /*
-  * $Id: megatron.c,v 1.14 2010-01-27 21:27:53 didg Exp $
-  */
  #ifdef HAVE_CONFIG_H
  #include "config.h"
  #endif /* HAVE_CONFIG_H */
@@@ -10,7 -6,9 +6,7 @@@
  #include <sys/param.h>
  #include <sys/stat.h>
  #include <sys/uio.h>
 -#ifdef HAVE_FCNTL_H
  #include <fcntl.h>
 -#endif /* HAVE_FCNTL_H */
  #include <time.h>
  #include <ctype.h>
  #include <stdio.h>
@@@ -307,6 -305,14 +303,14 @@@ int main(int argc, char **argv
  
      *newname = '\0';
      for ( c = 1 ; c < argc ; ++c ) {
+         if ( strcmp( argv [ c ], "--version" ) == 0 ) {
+           printf("%s (Netatalk %s megatron)\n", argv[0], VERSION);
+           return( -1 );
+       }
+         if ( strcmp( argv [ c ], "-v" ) == 0 ) {
+           printf("%s (Netatalk %s megatron)\n", argv[0], VERSION);
+           return( -1 );
+       }
          if ( strcmp( argv [ c ], "--header" ) == 0 ) {
            flags |= OPTION_HEADERONLY;
            continue;
      }
      return( rv );
  }
diff --combined configure.ac
index 0000000000000000000000000000000000000000,41d2cc834fc5f21c31492b22786e845f3a02a8ad..4a03c6de53b04ae8ffd8419ecd8c0a3d70af57ee
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,1378 +1,388 @@@
 -
+ dnl configure.in for netatalk
+ AC_INIT(etc/afpd/main.c)
+ NETATALK_VERSION=`cat $srcdir/VERSION`
+ AC_SUBST(NETATALK_VERSION)
+ AC_CANONICAL_SYSTEM
+ AM_INIT_AUTOMAKE(netatalk, ${NETATALK_VERSION})
+ AM_CONFIG_HEADER(config.h)
+ AM_MAINTAINER_MODE([enable])
+ dnl Checks for programs.
+ AC_PROG_AWK
+ AC_PROG_CC
+ AC_PROG_CC_C99
+ AC_PROG_INSTALL
+ AC_PROG_LN_S
+ AC_PROG_MAKE_SET
+ AC_LIBTOOL_DLOPEN
+ AC_PROG_LIBTOOL
+ AC_PROG_PERL
+ AC_PROG_GREP
+ AC_PROG_PS
 -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"
 -)
+ AM_PROG_CC_C_O
 -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
++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 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)
++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 
+ dnl --------------------------------------------------------------------------
+ AC_LTDL_DLLIB
+ AC_CHECK_FUNCS(dlopen dlsym dlclose)
+ AC_LTDL_DLSYM_USCORE
+ if test x"$libltdl_cv_need_uscore" = xyes; then
+     AC_DEFINE(DLSYM_PREPEND_UNDERSCORE, 1, [BSD compatibility macro])
+ fi
 -
++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_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])])
+ AC_CHECK_MEMBERS(struct tm.tm_gmtoff,,, [#include <time.h>])
 -AC_CACHE_SAVE
++dnl these tests have been comfirmed to be needed in 2011
++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)
 -dnl Checks for (v)snprintf
 -NETATALK_SNPRINTF_CHECK
 -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])
 -      ]
 -)
++AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW)
++
++AC_CACHE_SAVE
+ dnl --------------------------------------------------------------------------
+ dnl 64bit platform check
+ dnl --------------------------------------------------------------------------
+ AC_MSG_CHECKING([whether to check for 64bit libraries])
+ # Test if the compiler is in 64bit mode
+ echo 'int i;' > conftest.$ac_ext
+ atalk_cv_cc_64bit_output=no
+ if AC_TRY_EVAL(ac_compile); then
+     case `/usr/bin/file conftest.$ac_objext` in
+     *"ELF 64"*)
+       atalk_cv_cc_64bit_output=yes
+       ;;
+     esac
+ fi
+ rm -rf conftest*
+ case $host_cpu:$atalk_cv_cc_64bit_output in
+ powerpc64:yes | s390x:yes | sparc*:yes | x86_64:yes | i386:yes)
+     case $target_os in
+     solaris2*)
+         AC_MSG_RESULT([yes])
+         atalk_libname="lib/64"
+         ;;
+     *bsd* | dragonfly*)
+         AC_MSG_RESULT([no])
+         atalk_libname="lib"
+         ;;
+     *)
+         AC_MSG_RESULT([yes])
+         atalk_libname="lib64"
+         ;;
+     esac
+     ;;
+ *:*)
+     AC_MSG_RESULT([no])
+     atalk_libname="lib"
+     ;;
+ esac
+ dnl --------------------------------------------------------------------------
+ dnl specific configuration comes in here:
+ dnl --------------------------------------------------------------------------
++dnl Check for optional admin group support
++AC_NETATALK_ADMIN_GROUP
 -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 Check for optional AFS support
++AC_NETATALK_AFS_CHECK
 -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])
 -      ]
 -)
++dnl --with-pkgconfdir check to change configuration directory location
++AC_NETATALK_CONFIG_DIRS
 -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])
 -      ]
 -)
 -
 -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 whethe to disable tickle SIGALARM stuff, which eases debugging
++AC_NETATALK_DEBUGGING
 -bdb_required=no
++dnl   Check for libiconv support
++AC_NETATALK_CHECK_ICONV
+ dnl Check for CNID database backends
 -AC_CHECK_QUOTA
+ AC_NETATALK_CNID([bdb_required=yes],[bdb_required=no])
+ dnl Check for quota support
 -NETATALK_SRVLOC
++AC_NETATALK_CHECK_QUOTA
+ dnl Check for optional server location protocol support (used by MacOS X)
 -NETATALK_ZEROCONF
++AC_NETATALK_SRVLOC
+ dnl Check for optional Zeroconf support
 -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])
 -])
++AC_NETATALK_ZEROCONF
++
++dnl Check for optional TCP-wrappers support
++AC_NETATALK_TCP_WRAPPERS
+ dnl Check for PAM libs
 -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]
 -)
++AC_NETATALK_PATH_PAM
 -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 optional shadow password support
++AC_NETATALK_SHADOW
++      
++dnl Check for optional valid-shell-check support
++AC_NETATALK_SHELL_CHECK
 -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
 -      
 -      
 -      
 -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 Webmin
++AC_NETATALK_WEBMIN
 -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 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         obsoleted ],[
 -      echo "ERROR: --enable-redhat is obsoleted. Use --enable-redhat-sysv or --enable-redhat-systemd."
 -      echo "exit 1"
 -      exit 1
 -      ]
 -)
++dnl Check for libgcrypt, if found enables DHX2 UAM
++AC_NETATALK_PATH_LIBGCRYPT([1:1.2.3])
 -AC_ARG_ENABLE(redhat-sysv,
 -      [  --enable-redhat-sysv    use redhat-style sysv (upstart) configuration ],[
 -      if test "$enableval" = "yes"; then
 -              sysv_style=redhat-sysv
 -      fi
 -      AC_MSG_RESULT([enabling redhat-style sysv support])
 -      ]
 -)
++dnl Check for openssl, if found enables DHX UAM and Randnum UAM
++AC_NETATALK_PATH_SSL
 -AC_ARG_ENABLE(redhat-systemd,
 -      [  --enable-redhat-systemd use redhat-style systemd (>=Fedora15) configuration ],[
 -      if test "$enableval" = "yes"; then
 -              sysv_style=redhat-systemd
 -      fi
 -      AC_MSG_RESULT([enabling redhat-style systemd support])
 -      ]
 -)
++dnl Check for Berkeley DB library
++AC_NETATALK_PATH_BDB
 -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 crypt
++AC_NETATALK_CRYPT
 -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 building PGP UAM module
++AC_NETATALK_PGP_UAM
 -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 Kerberos V UAM module
++AC_NETATALK_KRB5_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 overwrite the config files or not
++AC_NETATALK_OVERWRITE_CONFIG
 -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 LDAP support, for client-side ACL visibility
++AC_NETATALK_LDAP
 -AC_ARG_WITH(uams-path,
 -      [  --with-uams-path=PATH   path to UAMs [[PKGCONF/uams]]],[
 -              uams_path="$withval"
 -      ],[
 -              uams_path="${PKGCONFDIR}/uams"
 -      ]
 -)
++dnl Check for ACL support
++AC_NETATALK_ACL
 -NETATALK_AC_CUPS
++dnl Check for Extended Attributes support
++AC_NETATALK_EXTENDED_ATTRIBUTES
 -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 libsmbsharemodes from Samba for Samba/Netatalk access/deny/share modes interop
++AC_NETATALK_SMB_SHAREMODES
 -dnl ***** UAMS_PATH
 -dnl AC_DEFINE_UNQUOTED(UAMS_PATH, "${uams_path}",
 -dnl   [path to UAMs [default=PKGCONF/uams]])
++dnl Check if realpath() takes NULL
++AC_NETATALK_REALPATH
++
++dnl Check for sendfile()
++AC_NETATALK_SENDFILE
+ dnl --------------------------------------------------------------------------
+ dnl FHS stuff has to be done last because it overrides other defaults
+ dnl --------------------------------------------------------------------------
+ AC_MSG_CHECKING([whether to use Filesystem Hierarchy Standard (FHS) compatibility])
+ AC_ARG_ENABLE(fhs,
+       [  --enable-fhs            use Filesystem Hierarchy Standard (FHS) compatibility],[
+       if test "$enableval" = "yes"; then
+               uams_path="${libdir}/netatalk"
+               sysconfdir="/etc"
+               PKGCONFDIR=${sysconfdir}/netatalk
+               SERVERTEXT="${PKGCONFDIR}/msg"
+               use_pam_so=yes
+               mandir="/usr/share/man"
+               AC_DEFINE(FHS_COMPATIBILITY, 1, [Define if you want compatibily with the FHS])
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+       fi
+       ],[
+               AC_MSG_RESULT([no])
+       ]
+ )
+ dnl --------------------------------------------------------------------------
+ dnl post-FHS substitutions, etc
+ dnl --------------------------------------------------------------------------
 -LIBS="$LIBS -L\$(top_srcdir)/libatalk"
 -CFLAGS="-I\$(top_srcdir)/include $CFLAGS -I\$(top_srcdir)/sys"
+ 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.
 -AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW)
++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"
 -dnl specific configuration comes in here:
+ 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 ;;
 -      *kfreebsd*-gnu)                 this_os=kfreebsd-gnu ;;
 -      *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])
 -        ;;
 -     kfreebsd-gnu) 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(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW)
 -fi
 -
 -dnl ----- GNU/kFreeBSD specific -----
 -if test x"$this_os" = "xkfreebsd-gnu"; then 
 -      AC_MSG_RESULT([ * GNU/kFreeBSD specific configuration])
 -      AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
 -      AC_DEFINE(FREEBSD, 1, [Define if OS is FreeBSD])
 -    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])
 -
 -
 -      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])
 -    AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
 -      dnl ----- OpenBSD does not have crypt.h, uses unistd.h -----
 -      AC_DEFINE(UAM_DHX, 1, [Define if the DHX UAM modules should be compiled])
 -    AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
 -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 sendfile() --------
 -netatalk_cv_search_sendfile=yes
 -AC_ARG_ENABLE(sendfile,
 -    [  --disable-sendfile       disable sendfile syscall],
 -    [if test x"$enableval" = x"no"; then
 -            netatalk_cv_search_sendfile=no
 -        fi]
 -)
 -
 -if test x"$netatalk_cv_search_sendfile" = x"yes"; then
 -   case "$host_os" in
 -   *linux*)
 -        AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available])
 -        AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
 -        ;;
 -
 -    *solaris*)
 -        AC_DEFINE(SENDFILE_FLAVOR_SOLARIS, 1, [Solaris sendfile()])
 -        AC_SEARCH_LIBS(sendfile, sendfile)
 -        AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
 -        ;;
 -
 -    *freebsd*)
 -        AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics])
 -        AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
 -        ;;
 -
 -    *)
 -        ;;
 -
 -    esac
 -
 -    if test x"$netatalk_cv_HAVE_SENDFILE" = x"yes"; then
 -        AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile() should be used])
 -    fi
 -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);
 -                              ],
 -                              [netatalk_cv_HAVE_ACL_GET_PERM_NP=yes],
 -                              [netatalk_cv_HAVE_ACL_GET_PERM_NP=no])
 -                              LIBS=$acl_LIBS
 -                      ])
 -                      if test x"$netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
 -                              AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
 -                      fi
 -
 -                      AC_CACHE_CHECK([for acl_from_mode], netatalk_cv_HAVE_ACL_FROM_MODE,[
 -                              acl_LIBS=$LIBS
 -                              LIBS="$LIBS $ACL_LIBS"
 -                AC_CHECK_FUNCS(acl_from_mode,
 -                              [netatalk_cv_HAVE_ACL_FROM_MODE=yes],
 -                              [netatalk_cv_HAVE_ACL_FROM_MODE=no])
 -                              LIBS=$acl_LIBS
 -                      ])
 -                      if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then
 -                              AC_DEFINE(HAVE_ACL_FROM_MODE,1,[Whether acl_from_mode() is available])
 -                      fi
 -
 -
 -              else
 -                      AC_MSG_NOTICE(ACL support is not avaliable)
 -                      AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available])
 -              fi
 -              ;;
 -    esac
 -fi
 -
 -if test x"$with_acl_support" = x"yes" ; then
 -   AC_CHECK_HEADERS([acl/libacl.h])
 -    AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available])
 -    AC_SUBST(ACL_LIBS)
 -fi
 -
 -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
 -
++dnl Last minute substitutions
+ dnl --------------------------------------------------------------------------
 -AC_SUBST(OVERWRITE_CONFIG)
+ AC_SUBST(LIBS)
+ AC_SUBST(CFLAGS)
 -AM_CONDITIONAL(COMPILE_TIMELORD, test x$compile_timelord = xyes)
 -AM_CONDITIONAL(COMPILE_A2BOOT, test x$compile_a2boot = xyes)
+ AM_CONDITIONAL(SOLARIS_MODULE, test x$solaris_module = xyes)
 -AM_CONDITIONAL(USE_KERBEROS, test x$compile_kerberos = xyes)
+ AM_CONDITIONAL(HAVE_LIBGCRYPT, test x$neta_cv_have_libgcrypt = xyes)
+ AM_CONDITIONAL(HAVE_OPENSSL, test x$neta_cv_have_openssl = xyes)
+ AM_CONDITIONAL(HAVE_ACLS, test x"$with_acl_support" = x"yes")
+ AM_CONDITIONAL(HAVE_LDAP, test x"$with_ldap" = x"yes")
+ AM_CONDITIONAL(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_APPLETALK, test x$netatalk_cv_ddp_enabled = 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_NETBSD, test x$sysv_style = xnetbsd)
+ AM_CONDITIONAL(USE_REDHAT_SYSV, test x$sysv_style = xredhat-sysv)
+ AM_CONDITIONAL(USE_REDHAT_SYSTEMD, test x$sysv_style = xredhat-systemd)
+ AM_CONDITIONAL(USE_SUSE, test x$sysv_style = xsuse)
+ AM_CONDITIONAL(USE_SHADOWPW, test x$shadowpw = xyes)
+ AM_CONDITIONAL(USE_TRU64, test x$sysv_style = xtru64)
+ AM_CONDITIONAL(USE_SOLARIS, test x$sysv_style = xsolaris)
+ AM_CONDITIONAL(USE_GENTOO, test x$sysv_style = xgentoo)
+ 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)
 -      bin/adv1tov2/Makefile
 -      bin/aecho/Makefile
+ AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes")
+ dnl --------------------- generate files
+ AC_OUTPUT([Makefile
+       bin/Makefile
+       bin/ad/Makefile
 -      bin/getzones/Makefile
+       bin/afppasswd/Makefile
+       bin/cnid/Makefile
+       bin/cnid/cnid2_create
 -      bin/misc/Makefile
 -      bin/nbp/Makefile
 -      bin/pap/Makefile
 -      bin/psorder/Makefile
+       bin/megatron/Makefile
 -      contrib/misc/Makefile
 -      contrib/printing/Makefile
++    bin/misc/Makefile
+       bin/uniconv/Makefile
+       config/Makefile
+       config/pam/Makefile
+       contrib/Makefile
+       contrib/macusers/Makefile
+       contrib/macusers/macusers
 -      contrib/timelord/Makefile
 -      contrib/a2boot/Makefile
+       contrib/shell_utils/Makefile
+       contrib/shell_utils/apple_dump
+       contrib/shell_utils/asip-status.pl
 -      etc/atalkd/Makefile
+       distrib/Makefile
+       distrib/config/Makefile
+       distrib/config/netatalk-config
+       distrib/initscripts/Makefile
+       distrib/m4/Makefile
+       distrib/systemd/Makefile
+       doc/Makefile
+       etc/Makefile
+       etc/afpd/Makefile
 -      etc/uams/uams_krb4/Makefile
 -      etc/papd/Makefile
 -      etc/psf/Makefile
+       etc/cnid_dbd/Makefile
++      etc/netalockd/Makefile
+       etc/uams/Makefile
 -      libatalk/asp/Makefile
 -      libatalk/atp/Makefile
+       include/Makefile
+       include/atalk/Makefile
+       libatalk/Makefile
+       libatalk/acl/Makefile
+       libatalk/adouble/Makefile
 -      libatalk/nbp/Makefile
 -      libatalk/netddp/Makefile
 -      libatalk/util/Makefile
+       libatalk/bstring/Makefile
+       libatalk/cnid/Makefile
+       libatalk/cnid/cdb/Makefile
+       libatalk/cnid/last/Makefile
+       libatalk/cnid/dbd/Makefile
+       libatalk/cnid/tdb/Makefile
+       libatalk/compat/Makefile
+       libatalk/dsi/Makefile
 -      man/man3/Makefile
 -      man/man4/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
 -      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
+       man/man5/Makefile
+       man/man8/Makefile
+       test/Makefile
+       test/afpd/Makefile
++      test/netalockd/Makefile
+       ],
+       [chmod a+x distrib/config/netatalk-config contrib/shell_utils/apple_*]
+ )
+ AC_NETATALK_LIBS_SUMMARY
+ AC_NETATALK_CONFIG_SUMMARY
diff --combined etc/afpd/acls.c
index fcc39995d952c9b684595ac6650c72a26a496442,82d61eb5444d88512ae58aa9ef6ed9c6496f4247..40281bcc9b079260922af9db90b38a0c879f5069
@@@ -1,5 -1,6 +1,6 @@@
  /*
    Copyright (c) 2008, 2009, 2010 Frank Lahm <franklahm@gmail.com>
+   Copyright (c) 2011 Laura Mueller <laura-mueller@uni-duesseldorf.de>
  
    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
  #define MAP_MASK               31
  #define IS_DIR                 32
  
+ /* bit flags for set_acl() and map_aces_darwin_to_posix() */
+ #define HAS_DEFAULT_ACL 0x01
+ #define HAS_EXT_DEFAULT_ACL 0x02
  /********************************************************
   * Solaris funcs
   ********************************************************/
@@@ -397,79 -402,81 +402,81 @@@ static int posix_acl_rights(const char 
                              uint32_t *result)
  {
      EC_INIT;
-     int havemask = 0;
      int entry_id = ACL_FIRST_ENTRY;
-     uint32_t rights = 0, maskrights = 0;
+     uint32_t rights = 0; /* rights which do not depend on ACL_MASK */
+     uint32_t acl_rights = 0; /* rights which are subject to limitations imposed by ACL_MASK */
+     uint32_t mask_rights = 0xffffffff;
      uid_t *uid = NULL;
      gid_t *gid = NULL;
      acl_t acl = NULL;
      acl_entry_t e;
      acl_tag_t tag;
  
-     EC_NULL_LOG(acl = acl_get_file(path, ACL_TYPE_ACCESS));
-     /* itereate through all ACEs to get the mask */
-     while (!havemask && acl_get_entry(acl, entry_id, &e) == 1) {
-         entry_id = ACL_NEXT_ENTRY;
-         EC_ZERO_LOG(acl_get_tag_type(e, &tag));
-         switch (tag) {
-         case ACL_MASK:
-             maskrights = posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
-             LOG(log_maxdebug, logtype_afpd, "maskrights: 0x%08x", maskrights);
-             havemask = 1;
-             break;
-         default:
-             continue;
-         }
-     }
+     EC_NULL_LOGSTR(acl = acl_get_file(path, ACL_TYPE_ACCESS),
+                    "acl_get_file(\"%s\"): %s", fullpathname(path), strerror(errno));
  
-     /* itereate through all ACEs */
-     entry_id = ACL_FIRST_ENTRY;
+     /* Iterate through all ACEs. If we apply mask_rights later there is no need to iterate twice. */
      while (acl_get_entry(acl, entry_id, &e) == 1) {
          entry_id = ACL_NEXT_ENTRY;
          EC_ZERO_LOG(acl_get_tag_type(e, &tag));
          switch (tag) {
-         case ACL_USER:
-             EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e));
-             if (*uid == uuid) {
-                 LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid);
-                 rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
-             }
-             acl_free(uid);
-             uid = NULL;
-             break;
-         case ACL_USER_OBJ:
-             if (sb->st_uid == uuid) {
-                 LOG(log_maxdebug, logtype_afpd, "ACL_USER_OBJ: %u", sb->st_uid);
-                 rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
-             }
-             break;
-         case ACL_GROUP:
-             EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e));
-             if (gmem(*gid)) {
-                 LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid);
-                 rights |= (posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)) & maskrights);
-             }
-             acl_free(gid);
-             gid = NULL;
-             break;
-         case ACL_GROUP_OBJ:
-             if (!(sb->st_uid == uuid) && gmem(sb->st_gid)) {
-                 LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
-                 rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));            
-             }
-             break;
-         case ACL_OTHER:
-             if (!(sb->st_uid == uuid) && !gmem(sb->st_gid)) {
-                 LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
-                 rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
-             }
-             break;
-         default:
-             continue;
+             case ACL_USER_OBJ:
+                 if (sb->st_uid == uuid) {
+                     LOG(log_maxdebug, logtype_afpd, "ACL_USER_OBJ: %u", sb->st_uid);
+                     rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+                 }
+                 break;
+             case ACL_USER:
+                 EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e));
+                 if (*uid == uuid) {
+                     LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid);
+                     acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+                 }
+                 acl_free(uid);
+                 uid = NULL;
+                 break;
+             case ACL_GROUP_OBJ:
+                 if (!(sb->st_uid == uuid) && gmem(sb->st_gid)) {
+                     LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
+                     acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+                 }
+                 break;
+             case ACL_GROUP:
+                 EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e));
+                 if (gmem(*gid)) {
+                     LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid);
+                     acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+                 }
+                 acl_free(gid);
+                 gid = NULL;
+                 break;
+             case ACL_MASK:
+                 mask_rights = posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+                 LOG(log_maxdebug, logtype_afpd, "maskrights: 0x%08x", mask_rights);
+                 break;
+             case ACL_OTHER:
+                 if (!(sb->st_uid == uuid) && !gmem(sb->st_gid)) {
+                     LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
+                     rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+                 }
+                 break;
+             default:
+                 continue;
          }
      } /* while */
  
+     /* apply the mask and collect the rights */
+     rights |= (acl_rights & mask_rights);
      *result |= rights;
  
  EC_CLEANUP:
      EC_EXIT;
  }
  
+ /*!
+  * Helper function for posix_acls_to_uaperms() to convert Posix ACL permissions
+  * into access rights needed to fill ua_permissions of a FPUnixPrivs structure.
+  *
+  * @param entry     (r) Posix ACL entry
+  *
+  * @returns         access rights
+  */
+ static u_char acl_permset_to_uarights(acl_entry_t entry) {
+     acl_permset_t permset;
+     u_char rights = 0;
+     if (acl_get_permset(entry, &permset) == -1)
+         return rights;
+ #ifdef HAVE_ACL_GET_PERM_NP
+     if (acl_get_perm_np(permset, ACL_READ))
+ #else
+     if (acl_get_perm(permset, ACL_READ))
+ #endif
+         rights |= AR_UREAD;
+ #ifdef HAVE_ACL_GET_PERM_NP
+     if (acl_get_perm_np(permset, ACL_WRITE))
+ #else
+     if (acl_get_perm(permset, ACL_WRITE))
+ #endif
+         rights |= AR_UWRITE;
+ #ifdef HAVE_ACL_GET_PERM_NP
+     if (acl_get_perm_np(permset, ACL_EXECUTE))
+ #else
+     if (acl_get_perm(permset, ACL_EXECUTE))
+ #endif
+         rights |= AR_USEARCH;
+     return rights;
+ }
+ /*!
+  * Update FPUnixPrivs for a file-system object on a volume supporting ACLs
+  *
+  * Checks permissions granted by ACLS for a user to one fs-object and
+  * updates user and group permissions in given struct maccess. As OS X
+  * doesn't conform to Posix 1003.1e Draft 17 it expects proper group
+  * permissions in st_mode of struct stat even if the fs-object has an
+  * ACL_MASK entry, st_mode gets modified to properly reflect group
+  * permissions.
+  *
+  * @param path           (r) path to filesystem object
+  * @param sb             (rw) struct stat of path
+  * @param maccess        (rw) struct maccess of path
+  *
+  * @returns                  0 or -1 on error
+  */
+ static int posix_acls_to_uaperms(const char *path, struct stat *sb, struct maccess *ma) {
+     EC_INIT;
+     int entry_id = ACL_FIRST_ENTRY;
+     acl_entry_t entry;
+     acl_tag_t tag;
+     acl_t acl = NULL;
+     uid_t *uid;
+     gid_t *gid;
+     uid_t whoami = geteuid();
+     u_char group_rights = 0x00;
+     u_char acl_rights = 0x00;
+     u_char mask = 0xff;
+     EC_NULL_LOG(acl = acl_get_file(path, ACL_TYPE_ACCESS));
+     /* iterate through all ACEs */
+     while (acl_get_entry(acl, entry_id, &entry) == 1) {
+         entry_id = ACL_NEXT_ENTRY;
+         EC_ZERO_LOG(acl_get_tag_type(entry, &tag));
+         switch (tag) {
+             case ACL_USER:
+                 EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(entry));
+                 if (*uid == uuid && !(whoami == sb->st_uid)) {
+                     LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid);
+                     acl_rights |= acl_permset_to_uarights(entry);
+                 }
+                 acl_free(uid);
+                 break;
+             case ACL_GROUP_OBJ:
+                 group_rights = acl_permset_to_uarights(entry);
+                 LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
+                 if (gmem(sb->st_gid) && !(whoami == sb->st_uid))
+                     acl_rights |= group_rights;
+                 break;
+             case ACL_GROUP:
+                 EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(entry));
+                 if (gmem(*gid) && !(whoami == sb->st_uid)) {
+                     LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid);
+                     acl_rights |= acl_permset_to_uarights(entry);
+                 }
+                 acl_free(gid);
+                 break;
+             case ACL_MASK:
+                 mask = acl_permset_to_uarights(entry);
+                 LOG(log_maxdebug, logtype_afpd, "ACL_MASK: 0x%02x", mask);
+                 break;
+             default:
+                 break;
+         }
+     }
+     /* apply the mask and adjust user and group permissions */
+     ma->ma_user |= (acl_rights & mask);
+     ma->ma_group = (group_rights & mask);
+     /* update st_mode to properly reflect group permissions */
+     sb->st_mode &= ~S_IRWXG;
+     if (ma->ma_group & AR_USEARCH)
+         sb->st_mode |= S_IXGRP;
+     if (ma->ma_group & AR_UWRITE)
+         sb->st_mode |= S_IWGRP;
+     if (ma->ma_group & AR_UREAD)
+         sb->st_mode |= S_IRGRP;
+ EC_CLEANUP:
+     if (acl) acl_free(acl);
+     EC_EXIT;
+ }
  /*!
   * Add entries of one acl to another acl
   *
@@@ -523,7 -667,7 +667,7 @@@ static acl_perm_t map_darwin_right_to_p
      if (darwin_ace_rights & DARWIN_ACE_READ_DATA)
          perm |= ACL_READ;
  
-     if (darwin_ace_rights & (DARWIN_ACE_WRITE_DATA | (DARWIN_ACE_DELETE_CHILD & is_dir)))
+     if (darwin_ace_rights & (DARWIN_ACE_WRITE_DATA | (is_dir ? DARWIN_ACE_DELETE_CHILD : 0)))
          perm |= ACL_WRITE;
  
      if (darwin_ace_rights & DARWIN_ACE_EXECUTE)
@@@ -583,7 -727,7 +727,7 @@@ static int posix_acl_add_perm(acl_t *ac
          EC_ZERO_LOG(acl_add_perm(permset, perm));
          EC_ZERO_LOG(acl_set_permset(e, permset));
      }
-     
  EC_CLEANUP:
      if (eid) acl_free(eid);
  
   * - we throw away DARWIN_ACE_FLAGS_LIMIT_INHERIT (can't be mapped), thus the ACL will
   *   not be limited
   *
-  * @param darwin_aces  (r)  pointer to darwin_aces buffer
-  * @param def_aclp     (rw) directories: pointer to an initialized acl_t with the default acl
-  *                          files: *def_aclp will be NULL
-  * @param acc_aclp     (rw) pointer to an initialized acl_t with the access acl
-  * @param ace_count    (r)  number of ACEs in darwin_aces buffer
+  * @param darwin_aces        (r)  pointer to darwin_aces buffer
+  * @param def_aclp           (rw) directories: pointer to an initialized acl_t with
+                                   the default acl files: *def_aclp will be NULL
+  * @param acc_aclp           (rw) pointer to an initialized acl_t with the access acl
+  * @param ace_count          (r)  number of ACEs in darwin_aces buffer
+  * @param default_acl_flags  (rw) flags to indicate if the object has a basic default
+  *                                acl or an extended default acl.
   *
-  * @returns 0 on success storing the result in aclp, -1 on error.
+  * @returns 0 on success storing the result in aclp, -1 on error. default_acl_flags
+  * is set to HAS_DEFAULT_ACL|HAS_EXT_DEFAULT_ACL in case there is at least one
+  * extended default ace. Otherwise default_acl_flags is left unchanged.
   */
  static int map_aces_darwin_to_posix(const darwin_ace_t *darwin_aces,
                                      acl_t *def_aclp,
                                      acl_t *acc_aclp,
-                                     int ace_count)
+                                     int ace_count,
+                                     uint32_t *default_acl_flags)
  {
      EC_INIT;
      char *name = NULL;
              }
              /* add it as default ace */
              EC_ZERO_LOG(posix_acl_add_perm(def_aclp, tag, id, perm));
+             *default_acl_flags = (HAS_DEFAULT_ACL|HAS_EXT_DEFAULT_ACL);
  
              if (! (darwin_ace_flags & DARWIN_ACE_FLAGS_ONLY_INHERIT))
                  /* if it not a "inherit only" ace, it must be added as access aces too */
@@@ -836,7 -985,7 +985,7 @@@ static int get_and_map_acl(char *name, 
      EC_INIT;
      int mapped_aces = 0;
      int dirflag;
 -    uint32_t *darwin_ace_count = (u_int32_t *)rbuf;
 +    uint32_t *darwin_ace_count = (uint32_t *)rbuf;
  #ifdef HAVE_SOLARIS_ACLS
      int ace_count = 0;
      ace_t *aces = NULL;
@@@ -1099,44 -1248,77 +1248,77 @@@ static int set_acl(const struct vol *vo
                     uint32_t ace_count)
  {
      EC_INIT;
-     acl_t def_acl = NULL;
-     acl_t acc_acl = NULL;
+     struct stat st;
+     acl_t default_acl = NULL;
+     acl_t access_acl = NULL;
+     acl_entry_t entry;
+     acl_tag_t tag;
+     int entry_id = ACL_FIRST_ENTRY;
+     int has_def_acl = 0;
+     /* flags to indicate if the object has a minimal default acl and/or an extended
+      * default acl.
+      */
+     uint32_t default_acl_flags = 0;
  
      LOG(log_maxdebug, logtype_afpd, "set_acl: BEGIN");
  
-     struct stat st;
-     EC_ZERO_LOG_ERR(lstat(name, &st), AFPERR_NOOBJ);
+     EC_NULL_LOG_ERR(access_acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC);
+     /* Iterate through acl and remove all extended acl entries. */
+     while (acl_get_entry(access_acl, entry_id, &entry) == 1) {
+         entry_id = ACL_NEXT_ENTRY;
+         EC_ZERO_LOG(acl_get_tag_type(entry, &tag));
+         if ((tag == ACL_USER) || (tag == ACL_GROUP) || (tag == ACL_MASK)) {
+             EC_ZERO_LOG_ERR(acl_delete_entry(access_acl, entry), AFPERR_MISC);
+         }
+     } /* while */
  
-     /* seed default ACL with access ACL */
-     if (S_ISDIR(st.st_mode))
-         EC_NULL_LOG_ERR(def_acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC);
+    /* In case we are acting on a directory prepare a default acl. For files default_acl will be NULL.
+     * If the directory already has a default acl it will be preserved.
+     */
+    EC_ZERO_LOG_ERR(lstat(name, &st), AFPERR_NOOBJ);
  
-     /* for files def_acl will be NULL */
+    if (S_ISDIR(st.st_mode)) {
+        default_acl = acl_get_file(name, ACL_TYPE_DEFAULT);
  
-     /* create access acl from mode */
-     EC_NULL_LOG_ERR(acc_acl = acl_from_mode(st.st_mode), AFPERR_MISC);
+        if (default_acl) {
+            /* If default_acl is not empty then the dir has a default acl. */
+            if (acl_get_entry(default_acl, ACL_FIRST_ENTRY, &entry) == 1)
+                default_acl_flags = HAS_DEFAULT_ACL;
  
+            acl_free(default_acl);
+        }
+        default_acl = acl_dup(access_acl);
+     }
      /* adds the clients aces */
-     EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &def_acl, &acc_acl, ace_count), AFPERR_MISC);
+     EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &default_acl, &access_acl, ace_count, &default_acl_flags), AFPERR_MISC);
  
      /* calcuate ACL mask */
-     EC_ZERO_LOG_ERR(acl_calc_mask(&acc_acl), AFPERR_MISC);
+     EC_ZERO_LOG_ERR(acl_calc_mask(&access_acl), AFPERR_MISC);
  
      /* is it ok? */
-     EC_ZERO_LOG_ERR(acl_valid(acc_acl), AFPERR_MISC);
+     EC_ZERO_LOG_ERR(acl_valid(access_acl), AFPERR_MISC);
  
      /* set it */
-     EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, acc_acl), AFPERR_MISC);
-     EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_ACCESS, 0, acc_acl), AFPERR_MISC);
-     if (def_acl) {
-         EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, def_acl), AFPERR_MISC);
-         EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_DEFAULT, 0, def_acl), AFPERR_MISC);
+     EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, access_acl), AFPERR_MISC);
+     EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_ACCESS, 0, access_acl), AFPERR_MISC);
+     if (default_acl) {
+         /* If the dir has an extended default acl it's ACL_MASK must be updated.*/
+         if (default_acl_flags & HAS_EXT_DEFAULT_ACL)
+             EC_ZERO_LOG_ERR(acl_calc_mask(&default_acl), AFPERR_MISC);
+         if (default_acl_flags) {
+             EC_ZERO_LOG_ERR(acl_valid(default_acl), AFPERR_MISC);
+             EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, default_acl), AFPERR_MISC);
+             EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_DEFAULT, 0, default_acl), AFPERR_MISC);
+         }
      }
  
  EC_CLEANUP:
-     acl_free(acc_acl);
-     acl_free(def_acl);
+     if (access_acl) acl_free(access_acl);
+     if (default_acl) acl_free(default_acl);
  
      LOG(log_maxdebug, logtype_afpd, "set_acl: END");
      EC_EXIT;
@@@ -1173,10 -1355,10 +1355,10 @@@ static int check_acl_access(const struc
      LOG(log_maxdebug, logtype_afpd, "check_acl_access(dir: \"%s\", path: \"%s\", curdir: \"%s\", 0x%08x)",
          cfrombstr(dir->d_fullpath), path, getcwdpath(), requested_rights);
  
+     /* This check is not used anymore, as OS X Server seems to be ignoring too */
+ #if 0
      /* Get uid or gid from UUID */
      EC_ZERO_ERR(getnamefromuuid(uuid, &username, &uuidtype), AFPERR_PARAM);
-     EC_ZERO_LOG_ERR(lstat(path, &st), AFPERR_PARAM);
      switch (uuidtype) {
      case UUID_USER:
          break;
          EC_STATUS(AFPERR_MISC);
          goto EC_CLEANUP;
      }
+ #endif
+     EC_ZERO_LOG_ERR(lstat(path, &st), AFPERR_PARAM);
  
      is_dir = !strcmp(path, ".");
  
              if (allowed_rights & DARWIN_ACE_ADD_SUBDIRECTORY)
                  allowed_rights |= DARWIN_ACE_DELETE;
  
-             dir->d_rights_cache = allowed_rights;
+             curdir->d_rights_cache = allowed_rights;
          }
          LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights);
      }
@@@ -1531,14 -1716,13 +1716,13 @@@ int afp_setacl(AFPObj *obj, char *ibuf
   * This is the magic function that makes ACLs usable by calculating
   * the access granted by ACEs to the logged in user.
   */
- int acltoownermode(char *path, struct stat *st, struct maccess *ma)
+ int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct maccess *ma)
  {
      EC_INIT;
      uint32_t rights = 0;
  
      if ( ! (AFPobj->options.flags & OPTION_ACL2MACCESS)
-          || (current_vol == NULL)
-          || ! (current_vol->v_flags & AFPVOL_ACLS))
+          || ! (vol->v_flags & AFPVOL_ACLS))
           return 0;
  
      LOG(log_maxdebug, logtype_afpd, "acltoownermode(\"%s/%s\", 0x%02x)",
  
  #ifdef HAVE_SOLARIS_ACLS
      EC_ZERO_LOG(solaris_acl_rights(path, st, &rights));
- #endif
- #ifdef HAVE_POSIX_ACLS
-     EC_ZERO_LOG(posix_acl_rights(path, st, &rights));
- #endif
  
      LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", rights);
  
          ma->ma_user |= AR_UWRITE;
      if (rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH))
          ma->ma_user |= AR_USEARCH;
+ #endif
+ #ifdef HAVE_POSIX_ACLS
+     EC_ZERO_LOG(posix_acls_to_uaperms(path, st, ma));
+ #endif
  
-     LOG(log_maxdebug, logtype_afpd, "resulting user maccess: 0x%02x", ma->ma_user);
+     LOG(log_maxdebug, logtype_afpd, "resulting user maccess: 0x%02x group maccess: 0x%02x", ma->ma_user, ma->ma_group);
  
  EC_CLEANUP:
      EC_EXIT;
diff --combined etc/afpd/afp_dsi.c
index 2fdeb9db32afc35fb68e73405bd4a1aa5542100c,3105db63efb4fde7831736e11204b83646b8fa48..51bd75b0b6055375c8b58266d2bed0205276ddc1
  #include <atalk/dsi.h>
  #include <atalk/compat.h>
  #include <atalk/util.h>
 +#include <atalk/locking.h>
  #include <atalk/uuid.h>
  #include <atalk/paths.h>
  #include <atalk/server_ipc.h>
  #include <atalk/fce_api.h>
 -
  #include <atalk/globals.h>
 +
  #include "switch.h"
  #include "auth.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
@@@ -375,8 -379,8 +375,8 @@@ void afp_over_dsi(AFPObj *obj
  {
      DSI *dsi = (DSI *) obj->handle;
      int rc_idx;
 -    u_int32_t err, cmd;
 -    u_int8_t function;
 +    uint32_t err, cmd;
 +    uint8_t function;
      struct sigaction action;
  
      AFPobj = obj;
              continue;
  
          /* Blocking read on the network socket */
-         cmd = dsi_receive(dsi);
+         cmd = dsi_stream_receive(dsi);
  
          if (cmd == 0) {
              /* cmd == 0 is the error condition */
  
              /* AFP replay cache */
              rc_idx = dsi->clientID % REPLAYCACHE_SIZE;
-             LOG(log_debug, logtype_afpd, "DSI request ID: %u", dsi->clientID);
+             LOG(log_debug, logtype_dsi, "DSI request ID: %u", dsi->clientID);
  
              if (replaycache[rc_idx].DSIreqID == dsi->clientID
                  && replaycache[rc_idx].AFPcommand == function) {
  
                      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 */
              if (dsi->flags & DSI_NOREPLY) {
                  dsi->flags &= ~DSI_NOREPLY;
                  break;
-             }
-             if (!dsi_cmdreply(dsi, err)) {
+             } else if (!dsi_cmdreply(dsi, err)) {
                  LOG(log_error, logtype_afpd, "dsi_cmdreply(%d): %s", dsi->socket, strerror(errno) );
                  if (dsi_disconnect(dsi) != 0)
                      afp_dsi_die(EXITERR_CLNT);
                      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 e79fc4f227928209ed140a4613f3825944551680,06cf20bc1b4bd6775336b2786361506f0da565bb..4464434116eb695eada997272d92d1cffb207a5e
@@@ -142,6 -142,8 +142,8 @@@ void afp_options_free(struct afp_option
        free(opt->logconfig);
        if (opt->mimicmodel && (opt->mimicmodel != save->mimicmodel))
        free(opt->mimicmodel);
+       if (opt->adminauthuser && (opt->adminauthuser != save->adminauthuser))
+       free(opt->adminauthuser);
  }
  
  /* initialize options */
@@@ -194,6 -196,7 +196,7 @@@ void afp_options_init(struct afp_option
      options->dsireadbuf = 12;
        options->mimicmodel = NULL;
      options->fce_fmodwait = 60; /* put fmod events 60 seconds on hold */
+     options->adminauthuser = NULL;
  }
  
  /* parse an afpd.conf line. i'm doing it this way because it's
@@@ -428,6 -431,10 +431,6 @@@ int afp_options_parseline(char *buf, st
  
      if ((c = getoption(buf, "-port")))
          options->port = strdup(c);
 -#ifndef NO_DDP
 -    if ((c = getoption(buf, "-ddpaddr")))
 -        atalk_aton(c, &options->ddpaddr);
 -#endif
      if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
          options->signatureopt = opt;
  
      if ((c = getoption(buf, "-mimicmodel")) && (opt = strdup(c)))
         options->mimicmodel = opt;
  
+     if ((c = getoption(buf, "-adminauthuser")) && (opt = strdup(c)))
+        options->adminauthuser = opt;
      return 1;
  }
  
@@@ -534,6 -544,13 +540,6 @@@ static void show_version( void 
        }
        puts( "" );
  
 -      printf( "DDP(AppleTalk) Support:\t" );
 -#ifdef NO_DDP
 -      puts( "No" );
 -#else
 -      puts( "Yes" );
 -#endif
 -
        printf( "         CNID backends:\t" );
  #ifdef CNID_BACKEND_CDB
        printf( "cdb ");
@@@ -620,6 -637,20 +626,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/afs.c
index 3b33c1ee3afabac3ca98d31131ed21282fa6acae,377d5fb5a6389c2d99a3faf0f0b220f8dc71a741..aebd1adbc52f00bacd1c022cdca3d8b23f5fa087
@@@ -32,7 -32,7 +32,7 @@@
  int afs_getvolspace( vol, bfree, btotal, bsize )
  struct vol    *vol;
  VolSpace      *bfree, *btotal;
 -u_int32_t   *bsize;
 +uint32_t   *bsize;
  {
      struct ViceIoctl  vi;
      struct VolumeStatus       *vs;
@@@ -81,8 -81,8 +81,8 @@@ int afp_getdiracl(AFPObj *obj, char *ib
      struct vol                *vol;
      struct dir                *dir;
      struct path               *path;
 -    u_int32_t         did;
 -    u_int16_t         vid;
 +    uint32_t          did;
 +    uint16_t          vid;
  
      ibuf += 2;
      memcpy( &vid, ibuf, sizeof( vid ));
      #undef accessmode
  #endif
  
- void afsmode( path, ma, dir, st )
+ void afsmode( vol, path, ma, dir, st )
+ const struct volume *vol;
  char          *path;
  struct maccess        *ma;
  struct dir      *dir;
@@@ -153,7 -154,7 +154,7 @@@ struct stat     *st
          return;
      }
  
-     accessmode( path, ma, dir, st );
+     accessmode(vol, path, ma, dir, st );
  
      return;
  }
@@@ -169,8 -170,8 +170,8 @@@ int afp_setdiracl(AFPObj *obj, char *ib
      struct dir                *dir;
      char              *iend;
      struct path               *path;
 -    u_int32_t         did;
 -    u_int16_t         vid;
 +    uint32_t          did;
 +    uint16_t          vid;
  
      *rbuflen = 0;
      iend = ibuf + ibuflen;
@@@ -235,7 -236,7 +236,7 @@@ int afp_afschangepw(AFPObj *obj, char *
      char      realm[ MAXKTCREALMLEN ];
      char      oldpw[ 9 ], newpw[ 9 ];
      int               len, rc;
 -    u_int16_t clen;
 +    uint16_t  clen;
      struct ktc_encryptionKey  oldkey, newkey;
      struct ktc_token          adtok;
      struct ubik_client                *conn;
diff --combined etc/afpd/catsearch.c
index 18fca228cf64e77e471ba212e8ce448faea533cf,71d1a44608af098cefa519234a15bdb216461e1d..1c913a0aab9de1fc008ea21b52cc789c724673e4
  
  
  struct finderinfo {
 -      u_int32_t f_type;
 -      u_int32_t creator;
 -      u_int16_t attrs;    /* File attributes (high 8 bits)*/
 -      u_int16_t label;    /* Label (low 8 bits )*/
 +      uint32_t f_type;
 +      uint32_t creator;
 +      uint16_t attrs;    /* File attributes (high 8 bits)*/
 +      uint16_t label;    /* Label (low 8 bits )*/
        char reserved[22]; /* Unknown (at least for now...) */
  };
  
@@@ -86,14 -86,14 +86,14 @@@ typedef char packed_finder[ADEDLEN_FIND
  
  /* This is our search-criteria structure. */
  struct scrit {
 -      u_int32_t rbitmap;          /* Request bitmap - which values should we check ? */
 -      u_int16_t fbitmap, dbitmap; /* file & directory bitmap - which values should we return ? */
 -      u_int16_t attr;             /* File attributes */
 +      uint32_t rbitmap;          /* Request bitmap - which values should we check ? */
 +      uint16_t fbitmap, dbitmap; /* file & directory bitmap - which values should we return ? */
 +      uint16_t attr;             /* File attributes */
        time_t cdate;               /* Creation date */
        time_t mdate;               /* Last modification date */
        time_t bdate;               /* Last backup date */
 -      u_int32_t pdid;             /* Parent DID */
 -    u_int16_t offcnt;           /* Offspring count */
 +      uint32_t pdid;             /* Parent DID */
 +    uint16_t offcnt;           /* Offspring count */
        struct finderinfo finfo;    /* Finder info */
        char lname[64];             /* Long name */ 
        char utf8name[514];         /* UTF8 or UCS2 name */ /* for convert_charset dest_len parameter +2 */
@@@ -257,11 -257,11 +257,11 @@@ unpack_finderinfo(struct vol *vol, stru
   */
  static int crit_check(struct vol *vol, struct path *path) {
        int result = 0;
 -      u_int16_t attr, flags = CONV_PRECOMPOSE;
 +      uint16_t attr, flags = CONV_PRECOMPOSE;
        struct finderinfo *finfo = NULL, finderinfo;
        struct adouble *adp = NULL;
        time_t c_date, b_date;
 -      u_int32_t ac_date, ab_date;
 +      uint32_t ac_date, ab_date;
        static char convbuf[514]; /* for convert_charset dest_len parameter +2 */
        size_t len;
      int islnk;
@@@ -429,7 -429,7 +429,7 @@@ static int rslt_add ( struct vol *vol, 
        char            *p = *buf;
        int             ret;
        size_t          tbuf =0;
 -      u_int16_t       resultsize;
 +      uint16_t        resultsize;
        int             isdir = S_ISDIR(path->st.st_mode); 
  
        /* Skip resultsize */
@@@ -502,9 -502,9 +502,9 @@@ static int catsearch(struct vol *vol
                       int *rsize,
                       int ext)
  {
 -    static u_int32_t cur_pos;    /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
 +    static uint32_t cur_pos;    /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
      static DIR *dirpos;                /* UNIX structure describing currently opened directory. */
-     struct dir *curdir;          /* struct dir of current directory */
+     struct dir *currentdir;      /* struct dir of current directory */
        int cidx, r;
        struct dirent *entry;
        int result = AFP_OK;
      start_time = time(NULL);
  
        while ((cidx = reducestack()) != -1) {
+         LOG(log_debug, logtype_afpd, "catsearch: dir: \"%s\"", dstack[cidx].path);
                error = lchdir(dstack[cidx].path);
  
                if (!error && dirpos == NULL)
                        goto catsearch_end;
                }
  
-         if ((curdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
+         if ((currentdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
              result = AFPERR_MISC;
              goto catsearch_end;
          }
+         LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath));
                
                while ((entry = readdir(dirpos)) != NULL) {
                        (*pos)++;
                        if (!check_dirent(vol, entry->d_name))
                           continue;
  
+             LOG(log_debug, logtype_afpd, "catsearch(\"%s\"): dirent: \"%s\"",
+                 cfrombstr(currentdir->d_fullpath), entry->d_name);
                        memset(&path, 0, sizeof(path));
                        path.u_name = entry->d_name;
                        if (of_stat(&path) != 0) {
                                */
                  int unlen = strlen(path.u_name);
                  path.d_dir = dircache_search_by_name(vol,
-                                                      curdir,
+                                                      currentdir,
                                                       path.u_name,
                                                       unlen);
                if (path.d_dir == NULL) {
                        /* path.m_name is set by adddir */
                    if ((path.d_dir = dir_add(vol,
-                                               curdir,
+                                               currentdir,
                                                &path,
                                                unlen)) == NULL) {
                                                result = AFPERR_MISC;
                                        goto catsearch_end;
                                } 
              } else {
-               path.d_dir = curdir;
+               path.d_dir = currentdir;
              }
  
                        ccr = crit_check(vol, &path);
@@@ -840,17 -846,17 +846,17 @@@ static int catsearch_afp(AFPObj *obj _U
                    char *rbuf, size_t *rbuflen, int ext)
  {
      struct vol *vol;
 -    u_int16_t   vid;
 -    u_int16_t   spec_len;
 -    u_int32_t   rmatches, reserved;
 -    u_int32_t catpos[4];
 -    u_int32_t   pdid = 0;
 +    uint16_t   vid;
 +    uint16_t   spec_len;
 +    uint32_t   rmatches, reserved;
 +    uint32_t  catpos[4];
 +    uint32_t   pdid = 0;
      int ret, rsize;
 -    u_int32_t nrecs = 0;
 +    uint32_t nrecs = 0;
      unsigned char *spec1, *spec2, *bspec1, *bspec2;
      size_t    len;
 -    u_int16_t namelen;
 -    u_int16_t flags;
 +    uint16_t  namelen;
 +    uint16_t  flags;
      char          tmppath[256];
      char        *uname;
  
diff --combined etc/afpd/directory.c
index a9e819e83a6b80065d317b81e6933c4b746f010a,78670ac1cfb1c6b339ae7d71f7f07c3d0ab87cda..dd9221034dbb5daf3e1cce0747ea2f92a4052516
@@@ -463,7 -463,15 +463,15 @@@ struct dir *dirlookup_bypath(const stru
      cnid = htonl(2);
      dir = vol->v_root;
  
+     LOG(log_debug, logtype_afpd, "dirlookup_bypath(\"%s\")", path);
+     if (strcmp(vol->v_path, path) == 0)
+         return dir;
      EC_NULL(rpath = rel_path_in_vol(path, vol->v_path)); /* 1. */
+     LOG(log_debug, logtype_afpd, "dirlookup_bypath: rpath: \"%s\"", cfrombstr(rpath));
      EC_NULL(statpath = bfromcstr(vol->v_path));          /* 2. */
  
      l = bsplit(rpath, '/');
          did = cnid;
          EC_ZERO(bcatcstr(statpath, "/"));
          EC_ZERO(bconcat(statpath, l->entry[i]));
+         LOG(log_debug, logtype_afpd, "dirlookup_bypath: statpath: \"%s\"", cfrombstr(statpath));
          EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
                         "lstat(rpath: %s, elem: %s): %s: %s",
                         cfrombstr(rpath), cfrombstr(l->entry[i]),
                                             dir,
                                             cfrombstr(l->entry[i]),
                                             blength(l->entry[i]))) == NULL) {
              if ((cnid = cnid_add(vol->v_cdb,             /* 6. */
                                   &st,
                                   did,
                                   cfrombstr(l->entry[i]),
                                   blength(l->entry[i]),
-                                  0)) == CNID_INVALID) {
+                                  0)) == CNID_INVALID)
                  EC_FAIL;
-             }
  
              if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */
                  EC_FAIL;
@@@ -504,6 -515,9 +515,9 @@@ EC_CLEANUP
      if (ret != 0)
          return NULL;
  
+     LOG(log_debug, logtype_afpd, "dirlookup_bypath: result: \"%s\"",
+         cfrombstr(dir->d_fullpath));
      return dir;
  }
  
@@@ -696,7 -710,7 +710,7 @@@ int caseenumerate(const struct vol *vol
      DIR               *dp;
      struct dirent     *de;
      int               ret;
 -    static u_int32_t  did = 0;
 +    static uint32_t  did = 0;
      static char       cname[MAXPATHLEN];
      static char       lname[MAXPATHLEN];
      ucs2_t        u2_path[MAXPATHLEN];
@@@ -899,7 -913,7 +913,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 */
@@@ -1129,8 -1143,8 +1143,8 @@@ struct path *cname(struct vol *vol, str
      struct dir  *cdir;
      char        *data, *p;
      int         len;
 -    u_int32_t   hint;
 -    u_int16_t   len16;
 +    uint32_t   hint;
 +    uint16_t   len16;
      int         size = 0;
      int         toUTF8 = 0;
  
@@@ -1410,7 -1424,7 +1424,7 @@@ int check_access(char *path, int mode
      if (!p)
          return -1;
  
-     accessmode(p, &ma, curdir, NULL);
+     accessmode(current_vol, p, &ma, curdir, NULL);
      if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
          return -1;
      if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
@@@ -1424,7 -1438,7 +1438,7 @@@ int file_access(struct path *path, int 
  {
      struct maccess ma;
  
-     accessmode(path->u_name, &ma, curdir, &path->st);
+     accessmode(current_vol, path->u_name, &ma, curdir, &path->st);
  
      LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x",
          path->u_name, ma.ma_user);
  }
  
  /* --------------------- */
 -void setdiroffcnt(struct dir *dir, struct stat *st,  u_int32_t count)
 +void setdiroffcnt(struct dir *dir, struct stat *st,  uint32_t count)
  {
      dir->d_offcnt = count;
      dir->d_ctime = st->st_ctime;
@@@ -1464,7 -1478,7 +1478,7 @@@ int dirreenumerate(struct dir *dir, str
  */
  
  int getdirparams(const struct vol *vol,
 -                 u_int16_t bitmap, struct path *s_path,
 +                 uint16_t bitmap, struct path *s_path,
                   struct dir *dir,
                   char *buf, size_t *buflen )
  {
      struct adouble  ad;
      char        *data, *l_nameoff = NULL, *utf_nameoff = NULL;
      int         bit = 0, isad = 0;
 -    u_int32_t           aint;
 -    u_int16_t       ashort;
 +    uint32_t           aint;
 +    uint16_t       ashort;
      int                 ret;
 -    u_int32_t           utf8 = 0;
 +    uint32_t           utf8 = 0;
      cnid_t              pdid;
      struct stat *st = &s_path->st;
      char *upath = s_path->u_name;
                     (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 */
                  ashort = htons(ATTRBIT_INVISIBLE);
              } else
                  ashort = 0;
-             ashort |= htons(ATTRBIT_SHARED);
              memcpy( data, &ashort, sizeof( ashort ));
              data += sizeof( ashort );
              break;
              if (dir->d_m_name) /* root of parent can have a null name */
                  l_nameoff = data;
              else
 -                memset(data, 0, sizeof(u_int16_t));
 -            data += sizeof( u_int16_t );
 +                memset(data, 0, sizeof(uint16_t));
 +            data += sizeof( uint16_t );
              break;
  
          case DIRPBIT_SNAME :
 -            memset(data, 0, sizeof(u_int16_t));
 -            data += sizeof( u_int16_t );
 +            memset(data, 0, sizeof(uint16_t));
 +            data += sizeof( uint16_t );
              break;
  
          case DIRPBIT_DID :
              break;
  
          case DIRPBIT_ACCESS :
-             accessmode( upath, &ma, dir , st);
+             accessmode(vol, upath, &ma, dir , st);
  
              *data++ = ma.ma_user;
              *data++ = ma.ma_world;
                  if (dir->d_m_name) /* root of parent can have a null name */
                      utf_nameoff = data;
                  else
 -                    memset(data, 0, sizeof(u_int16_t));
 -                data += sizeof( u_int16_t );
 +                    memset(data, 0, sizeof(uint16_t));
 +                data += sizeof( uint16_t );
                  aint = 0;
                  memcpy(data, &aint, sizeof( aint ));
                  data += sizeof( aint );
              break;
  
          case DIRPBIT_UNIXPR :
+             /* accessmode may change st_mode with ACLs */
+             accessmode(vol, upath, &ma, dir, st);
              aint = htonl(st->st_uid);
              memcpy( data, &aint, sizeof( aint ));
              data += sizeof( aint );
              memcpy( data, &aint, sizeof( aint ));
              data += sizeof( aint );
  
-             accessmode( upath, &ma, dir , st);
              *data++ = ma.ma_user;
              *data++ = ma.ma_world;
              *data++ = ma.ma_group;
@@@ -1730,8 -1744,8 +1744,8 @@@ int afp_setdirparams(AFPObj *obj, char 
      struct vol  *vol;
      struct dir  *dir;
      struct path *path;
 -    u_int16_t   vid, bitmap;
 -    u_int32_t   did;
 +    uint16_t   vid, bitmap;
 +    uint32_t   did;
      int     rc;
  
      *rbuflen = 0;
   *
   * assume path == '\0' eg. it's a directory in canonical form
   */
 -int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *buf )
 +int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *buf )
  {
      struct maccess  ma;
      struct adouble  ad;
      int         bit, isad = 1;
      int                 cdate, bdate;
      int                 owner, group;
 -    u_int16_t       ashort, bshort, oshort;
 +    uint16_t       ashort, bshort, oshort;
      int                 err = AFP_OK;
      int                 change_mdate = 0;
      int                 change_parent_mdate = 0;
      int                 newdate = 0;
 -    u_int16_t           bitmap = d_bitmap;
 +    uint16_t           bitmap = d_bitmap;
      u_char              finder_buf[32];
 -    u_int32_t       upriv;
 +    uint32_t       upriv;
      mode_t              mpriv = 0;
 -    u_int16_t           upriv_bit = 0;
 +    uint16_t           upriv_bit = 0;
  
      bit = 0;
      upath = path->u_name;
      }
      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));
          }
      }
          case DIRPBIT_FINFO :
              if (isad) {
                  /* Fixes #2802236 */
 -                u_int16_t *fflags = (u_int16_t *)(finder_buf + FINDERINFO_FRFLAGOFF);
 +                uint16_t *fflags = (uint16_t *)(finder_buf + FINDERINFO_FRFLAGOFF);
                  *fflags &= htons(~FINDERINFO_ISHARED);
                  /* #2802236 end */
                  if (  dir->d_did == DIRDID_ROOT ) {
@@@ -2125,8 -2139,8 +2139,8 @@@ int afp_syncdir(AFPObj *obj _U_, char *
      int                  dfd;
      struct vol           *vol;
      struct dir           *dir;
 -    u_int32_t            did;
 -    u_int16_t            vid;
 +    uint32_t            did;
 +    uint16_t            vid;
  
      *rbuflen = 0;
      ibuf += 2;
@@@ -2214,8 -2228,8 +2228,8 @@@ int afp_createdir(AFPObj *obj, char *ib
      struct dir      *dir;
      char        *upath;
      struct path         *s_path;
 -    u_int32_t       did;
 -    u_int16_t       vid;
 +    uint32_t       did;
 +    uint16_t       vid;
      int                 err;
  
      *rbuflen = 0;
      }
  
      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 );
      ad_close_metadata( &ad);
  
  createdir_done:
 -    memcpy( rbuf, &dir->d_did, sizeof( u_int32_t ));
 -    *rbuflen = sizeof( u_int32_t );
 +    memcpy( rbuf, &dir->d_did, sizeof( uint32_t ));
 +    *rbuflen = sizeof( uint32_t );
      setvoltime(obj, vol );
      return( AFP_OK );
  }
@@@ -2336,7 -2350,7 +2350,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);
@@@ -2353,7 -2367,7 +2367,7 @@@ int deletecurdir(struct vol *vol
      struct dir  *fdir, *pdir;
      DIR *dp;
      struct adouble  ad;
 -    u_int16_t       ashort;
 +    uint16_t       ashort;
      int err;
  
      if ((pdir = dirlookup(vol, curdir->d_pdid)) == NULL) {
          dir_remove( vol, fdir );
      } else {
          LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error",
-             curdir->d_fullpath);
+             cfrombstr(curdir->d_fullpath));
      }
  
  delete_done:
@@@ -2434,7 -2448,7 +2448,7 @@@ int afp_mapid(AFPObj *obj, char *ibuf, 
      struct passwd   *pw;
      struct group    *gr;
      char        *name;
 -    u_int32_t           id;
 +    uint32_t           id;
      int         len, sfunc;
      int         utf8 = 0;
  
          len = strlen( name );
  
      if (utf8) {
 -        u_int16_t tp = htons(len);
 +        uint16_t tp = htons(len);
          memcpy(rbuf, &tp, sizeof(tp));
          rbuf += sizeof(tp);
          *rbuflen += 2;
@@@ -2551,8 -2565,8 +2565,8 @@@ int afp_mapname(AFPObj *obj _U_, char *
      struct passwd   *pw;
      struct group    *gr;
      int             len, sfunc;
 -    u_int32_t       id;
 -    u_int16_t       ulen;
 +    uint32_t       id;
 +    uint16_t       ulen;
  
      ibuf++;
      sfunc = (unsigned char) *ibuf++;
@@@ -2639,8 -2653,8 +2653,8 @@@ int afp_closedir(AFPObj *obj _U_, char 
  #if 0
      struct vol   *vol;
      struct dir   *dir;
 -    u_int16_t    vid;
 -    u_int32_t    did;
 +    uint16_t    vid;
 +    uint32_t    did;
  #endif /* 0 */
  
      *rbuflen = 0;
@@@ -2675,8 -2689,8 +2689,8 @@@ int afp_opendir(AFPObj *obj _U_, char *
      struct vol      *vol;
      struct dir      *parentdir;
      struct path     *path;
 -    u_int32_t       did;
 -    u_int16_t       vid;
 +    uint32_t       did;
 +    uint16_t       vid;
  
      *rbuflen = 0;
      ibuf += 2;
diff --combined etc/afpd/file.c
index 779b93cabb6c91d854e81246f291b763405a47d1,36798904ad0802b9d5d89ca25d17432f456be6af..4c954e4e80f8daccb64bac9731b975749d035a5a
  #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>
@@@ -93,7 -108,7 +93,7 @@@ void *get_finderinfo(const struct vol *
          memcpy(data, ufinderi, ADEDLEN_FINDERI);
          chk_ext = 1;
          if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
 -            u_int16_t ashort;
 +            uint16_t ashort;
              
              ashort = htons(FINDERINFO_INVISIBLE);
              memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
      }
  
      if (islink){
 -        u_int16_t linkflag;
 +        uint16_t linkflag;
          memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2);
          linkflag |= htons(FINDERINFO_ISALIAS);
          memcpy((char *)data + FINDERINFO_FRFLAGOFF, &linkflag, 2);
  
  /* ---------------------
  */
 -char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, u_int32_t utf8) 
 +char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, uint32_t utf8) 
  {
 -    u_int32_t   aint;
 +    uint32_t   aint;
      char        *tp = NULL;
      char        *src = name;
      aint = strlen( name );
          *data++ = aint;
      }
      else {
 -        u_int16_t temp;
 +        uint16_t temp;
  
          if (aint > UTF8FILELEN_EARLY)  /* FIXME safeguard, anyway if no ascii char it's game over*/
             aint = UTF8FILELEN_EARLY;
@@@ -209,8 -224,8 +209,8 @@@ uint32_t get_id(struct vol *vol
                  const int len) 
  {
      static int first = 1;       /* mark if this func is called the first time */
 -    u_int32_t adcnid;
 -    u_int32_t dbcnid = CNID_INVALID;
 +    uint32_t adcnid;
 +    uint32_t dbcnid = CNID_INVALID;
  
  restart:
      if (vol->v_cdb != NULL) {
@@@ -287,18 -302,18 +287,18 @@@ exit
               
  /* -------------------------- */
  int getmetadata(struct vol *vol,
 -                 u_int16_t bitmap,
 +                 uint16_t bitmap,
                   struct path *path, struct dir *dir, 
                   char *buf, size_t *buflen, struct adouble *adp)
  {
      char              *data, *l_nameoff = NULL, *upath;
      char                *utf_nameoff = NULL;
      int                       bit = 0;
 -    u_int32_t         aint;
 +    uint32_t          aint;
      cnid_t              id = 0;
 -    u_int16_t         ashort;
 +    uint16_t          ashort;
      u_char              achar, fdType[4];
 -    u_int32_t           utf8 = 0;
 +    uint32_t           utf8 = 0;
      struct stat         *st;
      struct maccess    ma;
  
              /* FIXME do we want a visual clue if the file is read only
               */
              struct maccess    ma;
-             accessmode( ".", &ma, dir , NULL);
+             accessmode(vol, ".", &ma, dir , NULL);
              if ((ma.ma_user & AR_UWRITE)) {
-               accessmode( upath, &ma, dir , st);
+               accessmode(vol, upath, &ma, dir , st);
                if (!(ma.ma_user & AR_UWRITE)) {
                        ashort |= htons(ATTRBIT_NOWRITE);
                  }
              break;
  
          case FILPBIT_PDID :
 -            memcpy(data, &dir->d_did, sizeof( u_int32_t ));
 -            data += sizeof( u_int32_t );
 +            memcpy(data, &dir->d_did, sizeof( uint32_t ));
 +            data += sizeof( uint32_t );
              LOG(log_debug, logtype_afpd, "metadata('%s'):     Parent DID: %u",
                  path->u_name, ntohl(dir->d_did));
              break;
  
          case FILPBIT_LNAME :
              l_nameoff = data;
 -            data += sizeof( u_int16_t );
 +            data += sizeof( uint16_t );
              break;
  
          case FILPBIT_SNAME :
 -            memset(data, 0, sizeof(u_int16_t));
 -            data += sizeof( u_int16_t );
 +            memset(data, 0, sizeof(uint16_t));
 +            data += sizeof( uint16_t );
              break;
  
          case FILPBIT_FNUM :
              if (afp_version >= 30) { /* UTF8 name */
                  utf8 = kTextEncodingUTF8;
                  utf_nameoff = data;
 -                data += sizeof( u_int16_t );
 +                data += sizeof( uint16_t );
                  aint = 0;
                  memcpy(data, &aint, sizeof( aint ));
                  data += sizeof( aint );
              break;
          case FILPBIT_UNIXPR :
              /* accessmode may change st_mode with ACLs */
-             accessmode( upath, &ma, dir , st);
+             accessmode(vol, upath, &ma, dir , st);
  
              aint = htonl(st->st_uid);
              memcpy( data, &aint, sizeof( aint ));
                  
  /* ----------------------- */
  int getfilparams(struct vol *vol,
 -                 u_int16_t bitmap,
 +                 uint16_t bitmap,
                   struct path *path, struct dir *dir, 
                   char *buf, size_t *buflen )
  {
  
      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;
      char              *path, *upath;
      int                       creatf, did, openf, retvalue = AFP_OK;
 -    u_int16_t         vid;
 +    uint16_t          vid;
      struct path               *s_path;
      
      *rbuflen = 0;
      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);
 +        ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF);
          return AFPERR_MISC;
      }
  
 -    (void)get_id(vol, adp, &st, dir->d_did, upath, strlen(upath));
 -
 -    ad_flush( adp);
 +    (void)get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath));
  
 +    ad_flush(&ad);
 +    ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
      fce_register_new_file(s_path);
  
 -    ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
 -
  createfile_done:
      curdir->d_offcnt++;
  
 -#ifdef DROPKLUDGE
 -    if (vol->v_flags & AFPVOL_DROPBOX) {
 -        retvalue = matchfile2dirperms(upath, vol, did);
 -    }
 -#endif /* DROPKLUDGE */
 -
      setvoltime(obj, vol );
  
      return (retvalue);
@@@ -762,7 -797,7 +762,7 @@@ int afp_setfilparams(AFPObj *obj, char 
      struct dir        *dir;
      struct path *s_path;
      int               did, rc;
 -    u_int16_t vid, bitmap;
 +    uint16_t  vid, bitmap;
  
      *rbuflen = 0;
      ibuf += 2;
  extern struct path Cur_Path;
  
  int setfilparams(struct vol *vol,
 -                 struct path *path, u_int16_t f_bitmap, char *buf )
 +                 struct path *path, uint16_t f_bitmap, char *buf )
  {
      struct adouble    ad, *adp;
      struct extmap     *em;
      int                       bit, isad = 1, err = AFP_OK;
      char                *upath;
      u_char              achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
 -    u_int16_t         ashort, bshort, oshort;
 -    u_int32_t         aint;
 -    u_int32_t         upriv;
 -    u_int16_t           upriv_bit = 0;
 +    uint16_t          ashort, bshort, oshort;
 +    uint32_t          aint;
 +    uint32_t          upriv;
 +    uint16_t           upriv_bit = 0;
      
      struct utimbuf    ut;
  
      struct timeval      tv;
      uid_t             f_uid;
      gid_t             f_gid;
 -    u_int16_t           bitmap = f_bitmap;
 -    u_int32_t           cdate,bdate;
 +    uint16_t           bitmap = f_bitmap;
 +    uint32_t           cdate,bdate;
      u_char              finder_buf[32];
  
  #ifdef DEBUG
  
      /* 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);
      }
      
@@@ -1059,6 -1094,7 +1059,6 @@@ setfilparam_done
      if (isad) {
          ad_flush( adp);
          ad_close_metadata( adp);
 -
      }
  
      if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
@@@ -1144,8 -1180,9 +1144,8 @@@ int renamefile(const struct vol *vol, i
          }
      }
  
 -    /* 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 );
@@@ -1172,8 -1209,8 +1172,8 @@@ int copy_path_name(const struct vol *vo
  {
  char        type = *ibuf;
  size_t      plen = 0;
 -u_int16_t   len16;
 -u_int32_t   hint;
 +uint16_t   len16;
 +uint32_t   hint;
  
      if ( type != 2 && !(afp_version >= 30 && type == 3) ) {
          return -1;
@@@ -1231,9 -1268,9 +1231,9 @@@ int afp_copyfile(AFPObj *obj, char *ibu
      struct dir        *dir;
      char      *newname, *p, *upath;
      struct path *s_path;
 -    u_int32_t sdid, ddid;
 +    uint32_t  sdid, ddid;
      int         err, retvalue = AFP_OK;
 -    u_int16_t svid, dvid;
 +    uint16_t  svid, dvid;
  
      struct adouble ad, *adp;
      int denyreadset;
  
      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->d_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:
@@@ -1475,7 -1521,7 +1475,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) {
      if (ad_reso_fileno(adp) == -1 || 0 == (err = copy_fork(ADEID_RFORK, &add, adp))){
          /* copy the data fork */
          if ((err = copy_fork(ADEID_DFORK, &add, adp)) == 0) {
-             err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
+             if (ad_meta_fileno(adp) != -1)
+                 err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
          }
      }
  
@@@ -1575,7 -1622,7 +1576,7 @@@ done
  
  static int check_attrib(struct adouble *adp)
  {
 -u_int16_t   bshort = 0;
 +uint16_t   bshort = 0;
  
        ad_getattr(adp, &bshort);
      /*
@@@ -1608,7 -1655,7 +1609,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;
@@@ -1762,12 -1809,32 +1763,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;
  }
  
@@@ -1817,7 -1884,7 +1818,7 @@@ int afp_resolveid(AFPObj *obj _U_, cha
      int                 err, retry=0;
      size_t            buflen;
      cnid_t            id, cnid;
 -    u_int16_t         vid, bitmap;
 +    uint16_t          vid, bitmap;
  
      static char buffer[12 + MAXPATHLEN + 1];
      int len = 12 + MAXPATHLEN + 1;
@@@ -2029,7 -2096,7 +2030,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.
@@@ -2063,8 -2130,8 +2064,8 @@@ int afp_exchangefiles(AFPObj *obj, cha
      int                 crossdev;
      
      int                 slen, dlen;
 -    u_int32_t         sid, did;
 -    u_int16_t         vid;
 +    uint32_t          sid, did;
 +    uint16_t          vid;
  
      uid_t              uid;
      gid_t              gid;
diff --combined etc/afpd/fork.c
index f2c42b4f10e8cb9436808630c97f40fd5a56eb1a,41749b944308a6fdbeab9a4788d98e613ffd9c4b..2887f93e332767983bd43a5e2f92cb9e9c62d325
@@@ -1,7 -1,7 +1,7 @@@
  /*
 - * $Id: fork.c,v 1.73 2010-03-30 12:55:26 franklahm Exp $
 - *
   * Copyright (c) 1990,1993 Regents of The University of Michigan.
 + * Copyright (c) 2010      Frank Lahm
 + *
   * All Rights Reserved.  See COPYRIGHT.
   */
  
  #endif /* HAVE_CONFIG_H */
  
  #include <stdio.h>
 -
  #include <string.h>
  #include <errno.h>
 -
 -#include <atalk/adouble.h>
 -#include <atalk/logger.h>
 -
  #include <sys/param.h>
  #include <sys/socket.h>
 -
 -#include <netatalk/at.h>
 +#include <inttypes.h>
  
  #include <atalk/dsi.h>
 -#include <atalk/atp.h>
 -#include <atalk/asp.h>
  #include <atalk/afp.h>
 +#include <atalk/adouble.h>
 +#include <atalk/logger.h>
  #include <atalk/util.h>
  #include <atalk/cnid.h>
 +#include <atalk/bstradd.h>
  #include <atalk/globals.h>
  
  #include "fork.h"
  #include "desktop.h"
  #include "volume.h"
  
 -#ifdef DEBUG1
 -#define Debug(a) ((a)->options.flags & OPTION_DEBUG)
 -#else
 -#define Debug(a) (0)
 -#endif
 -
  #ifdef AFS
  struct ofork *writtenfork;
  #endif
  
 -static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen)
 +static int getforkparams(struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen)
  {
      struct path         path;
 -    struct stat               *st;
 +    struct stat     *st;
 +
 +    struct adouble  *adp;
 +    struct dir      *dir;
 +    struct vol      *vol;
  
 -    struct adouble    *adp;
 -    struct dir                *dir;
 -    struct vol                *vol;
 -    
  
      /* can only get the length of the opened fork */
 -    if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN))) 
 -                  && (ofork->of_flags & AFPFORK_RSRC)) 
 -        ||
 -          ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN))) 
 -                  && (ofork->of_flags & AFPFORK_DATA))) {
 +    if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
 +           && (ofork->of_flags & AFPFORK_RSRC))
 +         ||
 +         ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
 +           && (ofork->of_flags & AFPFORK_DATA))) {
          return( AFPERR_BITMAP );
      }
  
@@@ -69,8 -80,8 +69,8 @@@
      path.m_name = of_name(ofork);
      path.id = 0;
      st = &path.st;
 -    if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) | 
 -                    (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) | 
 +    if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
 +                    (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
                      (1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
          if ( ad_data_fileno( ofork->of_ad ) <= 0 ) {
              /* 0 is for symlink */
      return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp );
  }
  
 -/* ---------------------------- */
  static off_t get_off_t(char **ibuf, int is64)
  {
 -    u_int32_t             temp;
 +    uint32_t             temp;
      off_t                 ret;
  
      ret = 0;
          ret = ntohl(temp)| (ret << 32);
      }
      else {
 -      ret = (int)ret; /* sign extend */
 +        ret = (int)ret; /* sign extend */
      }
      return ret;
  }
  
 -/* ---------------------- */
  static int set_off_t(off_t offset, char *rbuf, int is64)
  {
 -    u_int32_t  temp;
 +    uint32_t  temp;
      int        ret;
  
      ret = 0;
      return ret;
  }
  
 -/* ------------------------ 
 -*/
  static int is_neg(int is64, off_t val)
  {
      if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
 -      return 1;
 +        return 1;
      return 0;
  }
  
 -static int sum_neg(int is64, off_t offset, off_t reqcount) 
 +static int sum_neg(int is64, off_t offset, off_t reqcount)
  {
 -    if (is_neg(is64, offset +reqcount) ) 
 -      return 1;
 +    if (is_neg(is64, offset +reqcount) )
 +        return 1;
      return 0;
  }
  
 -/* -------------------------
 -*/
 -static int setforkmode(struct adouble *adp, int eid, int ofrefnum, off_t what)
 -{
 -    return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
 -}
 -
 -/* -------------------------
 -*/
 -int getforkmode(struct adouble *adp, int eid, off_t what)
 -{
 -    return ad_testlock(adp, eid,  what);
 -}
 -
 -/* -------------------------
 -*/
  static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
  {
      int ret;
      int denywriteset;
  
      if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
 -        return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
 +        return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
      }
  
      if ((access & (OPENACC_RD | OPENACC_DRD))) {
 -        if ((readset = getforkmode(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
 +        if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
              return readset;
 -        if ((denyreadset = getforkmode(adp, eid, AD_FILELOCK_DENY_RD)) <0)
 +        if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
              return denyreadset;
  
          if ((access & OPENACC_RD) && denyreadset) {
          if ((access & OPENACC_DRD) && readset) {
              errno = EACCES;
              return -1;
 -        }   
 +        }
          /* boolean logic is not enough, because getforkmode is not always telling the
 -         * true 
 +         * true
           */
          if ((access & OPENACC_RD)) {
 -            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
 +            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
              if (ret)
                  return ret;
          }
          if ((access & OPENACC_DRD)) {
 -            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
 +            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
              if (ret)
                  return ret;
          }
      }
      /* ------------same for writing -------------- */
      if ((access & (OPENACC_WR | OPENACC_DWR))) {
 -        if ((writeset = getforkmode(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
 +        if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
              return writeset;
 -        if ((denywriteset = getforkmode(adp, eid, AD_FILELOCK_DENY_WR)) <0)
 +        if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
              return denywriteset;
  
          if ((access & OPENACC_WR) && denywriteset) {
          if ((access & OPENACC_DWR) && writeset) {
              errno = EACCES;
              return -1;
 -        }   
 +        }
          if ((access & OPENACC_WR)) {
 -            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
 +            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
              if (ret)
                  return ret;
          }
          if ((access & OPENACC_DWR)) {
 -            ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
 +            ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
              if (ret)
                  return ret;
          }
  /* ----------------------- */
  int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
  {
 -    struct vol                *vol;
 -    struct dir                *dir;
 -    struct ofork      *ofork, *opened;
 -    struct adouble      *adsame = NULL;
 -    size_t            buflen;
 -    int                       ret, adflags, eid;
 -    u_int32_t           did;
 -    u_int16_t         vid, bitmap, access, ofrefnum;
 -    char              fork, *path, *upath;
 -    struct stat         *st;
 -    u_int16_t           bshort;
 -    struct path         *s_path;
 -    
 +    struct vol      *vol;
 +    struct dir      *dir;
 +    struct ofork    *ofork, *opened;
 +    struct adouble  *adsame = NULL;
 +    size_t          buflen;
 +    int             ret, adflags, eid;
 +    uint32_t        did;
 +    uint16_t        vid, bitmap, access, ofrefnum;
 +    char            fork, *path, *upath;
 +    struct stat     *st;
 +    uint16_t        bshort;
 +    struct path     *s_path;
 +
      ibuf++;
      fork = *ibuf++;
      memcpy(&vid, ibuf, sizeof( vid ));
      ibuf += sizeof( int );
  
      if (NULL == ( dir = dirlookup( vol, did ))) {
 -      return afp_errno;    
 +        return afp_errno;
      }
  
      memcpy(&bitmap, ibuf, sizeof( bitmap ));
      }
  
      if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
 -      return get_afp_errno(AFPERR_PARAM);    
 +        return get_afp_errno(AFPERR_PARAM);
      }
  
      if (*s_path->m_name == '\0') {
 -       /* it's a dir ! */
 -       return  AFPERR_BADTYPE;
 +        /* it's a dir ! */
 +        return  AFPERR_BADTYPE;
      }
  
 +    LOG(log_debug, logtype_afpd,
 +        "afp_openfork(\"%s\", %s)",
 +        abspath(s_path->u_name),
 +        (fork & OPENFORK_RSCS) ? "OPENFORK_RSCS" : "OPENFORK_DATA");
 +
      /* stat() data fork st is set because it's not a dir */
      switch ( s_path->st_errno ) {
      case 0:
      case EACCES:
          return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
      default:
 -        LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
 +        LOG(log_error, logtype_afpd, "afp_openfork(%s): %s", s_path->m_name, strerror(errno));
          return AFPERR_PARAM;
      }
      /* FIXME should we check it first ? */
          if (check_access(upath, access ) < 0) {
              return AFPERR_ACCESS;
          }
 -    }
 -    else {
 +    } else {
          if (file_access(s_path, access ) < 0) {
              return AFPERR_ACCESS;
          }
      /* XXX: this probably isn't the best way to do this. the already
         open bits should really be set if the fork is opened by any
         program, not just this one. however, that's problematic to do
 -       if we can't write lock files somewhere. opened is also passed to 
 +       if we can't write lock files somewhere. opened is also passed to
         ad_open so that we can keep file locks together.
 -       FIXME: add the fork we are opening? 
 +       FIXME: add the fork we are opening?
      */
      if ((opened = of_findname(s_path))) {
          adsame = opened->of_ad;
  
      if ( fork == OPENFORK_DATA ) {
          eid = ADEID_DFORK;
 -        adflags = ADFLAGS_DF|ADFLAGS_HF;
 +        adflags = ADFLAGS_DF | ADFLAGS_HF ;
      } else {
          eid = ADEID_RFORK;
 -        adflags = ADFLAGS_HF;
 +        adflags = ADFLAGS_RF | ADFLAGS_HF;
      }
  
      path = s_path->m_name;
      ret = AFPERR_NOOBJ;
      if (access & OPENACC_WR) {
          /* try opening in read-write mode */
 -        if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
 +        if (ad_open(ofork->of_ad, upath, adflags, O_RDWR, O_RDWR) < 0) {
              switch ( errno ) {
              case EROFS:
                  ret = AFPERR_VLOCK;
              case ENOENT:
                  if (fork == OPENFORK_DATA) {
                      /* try to open only the data fork */
 -                    if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
 +                    if (ad_open(ofork->of_ad, upath, ADFLAGS_DF, O_RDWR) < 0) {
                          goto openfork_err;
                      }
                      adflags = ADFLAGS_DF;
 -                }
 -                else {
 +                } else {
                      /* here's the deal. we only try to create the resource
 -                    * fork if the user wants to open it for write acess. */
 -                    if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
 +                     * fork if the user wants to open it for write acess. */
 +                    if (ad_open(ofork->of_ad, upath, adflags, O_RDWR | O_CREAT, 0666, O_RDWR | O_CREAT, 0666) < 0)
                          goto openfork_err;
                      ofork->of_flags |= AFPFORK_OPEN;
                  }
      } else {
          /* try opening in read-only mode */
          ret = AFPERR_NOOBJ;
 -        if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
 +        if (ad_open(ofork->of_ad, upath, adflags, O_RDONLY, O_RDONLY) < 0) {
              switch ( errno ) {
              case EROFS:
                  ret = AFPERR_VLOCK;
              case ENOENT:
                  /* see if client asked for a read only data fork */
                  if (fork == OPENFORK_DATA) {
 -                    if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
 +                    if (ad_open(ofork->of_ad, upath, ADFLAGS_DF, O_RDONLY) < 0) {
                          goto openfork_err;
                      }
                      adflags = ADFLAGS_DF;
                  }
 -                /* else we don't set AFPFORK_OPEN because there's no ressource fork file 
 +                /* else we don't set AFPFORK_OPEN because there's no ressource fork file
                   * We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
                   * then create in open read-write.
                   * FIXME , it doesn't play well with byte locking example:
                   * ressource fork open read only
                   * locking set on it (no effect, there's no file!)
                   * ressource fork open read write now
 -                */
 +                 */
                  break;
              case EMFILE :
              case ENFILE :
                  goto openfork_err;
                  break;
              default:
 -                LOG(log_error, logtype_afpd, "afp_openfork('%s/%s'): ad_open: errno: %i (%s)",
 -                    getcwdpath, s_path->m_name, errno, strerror(errno) );
 +                LOG(log_error, logtype_afpd, "afp_openfork(\"%s\"): %s",
 +                    abspath(s_path->m_name), strerror(errno) );
                  goto openfork_err;
                  break;
              }
          }
      }
  
 -    if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
 +    if ((adflags & ADFLAGS_RF) && (ad_get_RF_flags( ofork->of_ad) & O_CREAT)) {
          if (ad_setname(ofork->of_ad, path)) {
              ad_flush( ofork->of_ad );
          }
      }
  
 -    if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
 -                              &buflen )) != AFP_OK ) {
 +    if ((ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
          ad_close( ofork->of_ad, adflags );
          goto openfork_err;
      }
  
 -    *rbuflen = buflen + 2 * sizeof( u_int16_t );
 +    *rbuflen = buflen + 2 * sizeof( uint16_t );
      bitmap = htons( bitmap );
 -    memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
 -    rbuf += sizeof( u_int16_t );
 +    memcpy(rbuf, &bitmap, sizeof( uint16_t ));
 +    rbuf += sizeof( uint16_t );
  
      /* check  WriteInhibit bit if we have a ressource fork
 -     * the test is done here, after some Mac trafic capture 
 +     * the test is done here, after some Mac trafic capture
       */
      if (ad_meta_fileno(ofork->of_ad) != -1) {   /* META */
          ad_getattr(ofork->of_ad, &bshort);
@@@ -492,14 -521,14 +492,14 @@@ openfork_err
  
  int afp_setforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen)
  {
 -    struct ofork      *ofork;
 -    off_t             size;
 -    u_int16_t         ofrefnum, bitmap;
 +    struct ofork    *ofork;
 +    off_t       size;
 +    uint16_t       ofrefnum, bitmap;
      int                 err;
      int                 is64;
      int                 eid;
 -    off_t             st_size;
 -    
 +    off_t       st_size;
 +
      ibuf += 2;
  
      memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
      } else
          return AFPERR_PARAM;
  
 -    if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) )) 
 -                  && eid == ADEID_RFORK 
 -         ) ||
 -         ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) )) 
 -                  && eid == ADEID_DFORK)) {
 +    if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
 +           && eid == ADEID_RFORK
 +             ) ||
 +         ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
 +           && eid == ADEID_DFORK)) {
          return AFPERR_BITMAP;
      }
 -    
 +
      is64 = 0;
      if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
          if (afp_version >= 30) {
              is64 = 4;
          }
 -        else 
 -           return AFPERR_BITMAP;
 +        else
 +            return AFPERR_BITMAP;
      }
  
      if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
          return AFPERR_PARAM ;
 -    
 +
      size = get_off_t(&ibuf, is64);
  
      if (size < 0)
  
  
      if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
 -      st_size = ad_size(ofork->of_ad, eid);
 -      err = -2;
 -      if (st_size > size && 
 -            ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) 
 +        st_size = ad_size(ofork->of_ad, eid);
 +        err = -2;
 +        if (st_size > size &&
 +            ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
              goto afp_setfork_err;
  
          err = ad_dtruncate( ofork->of_ad, size );
          if (st_size > size)
 -          ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);  
 +            ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
          if (err < 0)
              goto afp_setfork_err;
      } else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
          ad_refresh( ofork->of_ad );
  
 -      st_size = ad_size(ofork->of_ad, eid);
 -      err = -2;
 -      if (st_size > size && 
 -             ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
 +        st_size = ad_size(ofork->of_ad, eid);
 +        err = -2;
 +        if (st_size > size &&
 +            ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
              goto afp_setfork_err;
 -      }
 +        }
          err = ad_rtruncate(ofork->of_ad, size);
          if (st_size > size)
 -          ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);  
 +            ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
          if (err < 0)
              goto afp_setfork_err;
  
@@@ -620,7 -649,7 +620,7 @@@ afp_setfork_err
   * read and write. that's most easily handled by always doing an
   * appropriate check before each ad_read/ad_write. other things
   * that can change files like truncate are handled internally to those
 - * functions. 
 + * functions.
   */
  #define ENDBIT(a)  ((a) & 0x80)
  #define UNLOCKBIT(a) ((a) & 0x01)
  /* ---------------------- */
  static int byte_lock(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
  {
 -    struct ofork      *ofork;
 +    struct ofork    *ofork;
      off_t               offset, length;
      int                 eid;
 -    u_int16_t         ofrefnum;
 -    u_int8_t            flags;
 +    uint16_t       ofrefnum;
 +    uint8_t            flags;
      int                 lockop;
 -    
 +
      *rbuflen = 0;
  
      /* figure out parameters */
      /* FIXME AD_FILELOCK test is surely wrong */
      if (length == -1)
          length = BYTELOCK_MAX;
 -     else if (!length || is_neg(is64, length)) {
 -      return AFPERR_PARAM;
 -     } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
 +    else if (!length || is_neg(is64, length)) {
 +        return AFPERR_PARAM;
 +    } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
          return AFPERR_LOCK;
      }
  
      if (ENDBIT(flags)) {
          offset += ad_size(ofork->of_ad, eid);
 -        /* FIXME what do we do if file size > 2 GB and 
 +        /* FIXME what do we do if file size > 2 GB and
             it's not byte_lock_ext?
          */
      }
  /* --------------------------- */
  int afp_bytelock(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
  {
 -   return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
 +    return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
  }
  
  /* --------------------------- */
  int afp_bytelock_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
  {
 -   return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
 +    return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
  }
  
  #undef UNLOCKBIT
  /* --------------------------- */
  static int crlf(struct ofork *of)
  {
 -    struct extmap     *em;
 +    struct extmap   *em;
  
      if ( ad_meta_fileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) { /* META */
          /* no resource fork or no finderinfo, use our files extension mapping */
          if (!( em = getextmap( of_name(of) )) || memcmp( "TEXT", em->em_type, sizeof( em->em_type ))) {
              return 0;
 -        } 
 +        }
          /* file type is TEXT */
          return 1;
  
  
  
  static ssize_t read_file(struct ofork *ofork, int eid,
 -                                    off_t offset, u_char nlmask,
 -                                    u_char nlchar, char *rbuf,
 -                                    size_t *rbuflen, const int xlate)
 +                         off_t offset, u_char nlmask,
 +                         u_char nlchar, char *rbuf,
 +                         size_t *rbuflen, const int xlate)
  {
      ssize_t cc;
      int eof = 0;
  }
  
  /* -----------------------------
 - * with ddp, afp_read can return fewer bytes than in reqcount 
 + * with ddp, afp_read can return fewer bytes than in reqcount
   * so return EOF only if read actually past end of file not
   * if offset +reqcount > size of file
   * e.g.:
   * read fork offset 0 size 10752 ????  ==> 4264 bytes (without EOF)
   * read fork offset 4264 size 6128 ==> 4264 (without EOF)
   * read fork offset 9248 size 1508 ==> 1182 (EOF)
 - * 10752 is a bug in Mac 7.5.x finder 
 + * 10752 is a bug in Mac 7.5.x finder
   *
 - * with dsi, should we check that reqcount < server quantum? 
 -*/
 + * with dsi, should we check that reqcount < server quantum?
 + */
  static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
  {
 -    struct ofork      *ofork;
 -    off_t             offset, saveoff, reqcount, savereqcount;
 -    ssize_t           cc, err;
 -    int                       eid, xlate = 0;
 -    u_int16_t         ofrefnum;
 -    u_char            nlmask, nlchar;
 +    struct ofork    *ofork;
 +    off_t       offset, saveoff, reqcount, savereqcount;
 +    ssize_t     cc, err;
 +    int         eid, xlate = 0;
 +    uint16_t       ofrefnum;
 +    u_char      nlmask, nlchar;
  
      ibuf += 2;
      memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
      offset   = get_off_t(&ibuf, is64);
      reqcount = get_off_t(&ibuf, is64);
  
 +    LOG(log_debug, logtype_afpd,
 +         "afp_read(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
 +         cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount,
 +         (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
 +
      if (is64) {
          nlmask = nlchar = 0;
      }
          goto afp_read_err;
      }
  
+     LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd)",
+         of_name(ofork), (intmax_t)offset, (intmax_t)reqcount);
      savereqcount = reqcount;
      saveoff = offset;
      if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
          goto afp_read_err;
      }
  
++<<<<<<< HEAD
 +#define min(a,b)    ((a)<(b)?(a):(b))
 +    *rbuflen = min( reqcount, *rbuflen );
++=======
+     *rbuflen = MIN(reqcount, *rbuflen);
+     LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): reading %jd bytes from file",
+         of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
++>>>>>>> netafp/master
      err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate);
      if (err < 0)
          goto afp_read_done;
+     LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file",
+         of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
  
      /* dsi can stream requests. we can only do this if we're not checking
       * for an end-of-line character. oh well. */
          /* subtract off the offset */
          size -= offset;
          if (reqcount > size) {
 -         reqcount = size;
 -           err = AFPERR_EOF;
 +            reqcount = size;
 +            err = AFPERR_EOF;
          }
  
          offset += *rbuflen;
          *rbuflen = cc;
          /* due to the nature of afp packets, we have to exit if we get
             an error. we can't do this with translation on. */
 -#ifdef WITH_SENDFILE 
 -        if (!(xlate || Debug(obj) )) {
 +#ifdef WITH_SENDFILE
 +        if (!(xlate)) {
              int fd;
 -                        
 +
              fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0);
              if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) {
                  if (errno == EINVAL || errno == ENOSYS)
                      goto afp_read_loop;
              goto afp_read_done;
          }
  
 -afp_read_loop:
 -#endif 
 +    afp_read_loop:
 +#endif
  
          /* fill up our buffer. */
          while (*rbuflen > 0) {
          dsi_readdone(dsi);
          goto afp_read_done;
  
 -afp_read_exit:
 +    afp_read_exit:
          LOG(log_error, logtype_afpd, "afp_read(%s): %s", of_name(ofork), strerror(errno));
          dsi_readdone(dsi);
          ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
@@@ -977,7 -1008,7 +989,7 @@@ int afp_read_ext(AFPObj *obj, char *ibu
  int afp_flush(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
  {
      struct vol *vol;
 -    u_int16_t vid;
 +    uint16_t vid;
  
      *rbuflen = 0;
      ibuf += 2;
      return( AFP_OK );
  }
  
 -int afp_flushfork(AFPObj *obj _U_, char       *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 +int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
  {
 -    struct ofork      *ofork;
 -    u_int16_t         ofrefnum;
 +    struct ofork    *ofork;
 +    uint16_t       ofrefnum;
  
      *rbuflen = 0;
      ibuf += 2;
          return( AFPERR_PARAM );
      }
  
 +    LOG(log_debug, logtype_afpd,
 +        "afp_flushfork(\"%s\", fork: %s)",
 +        cfrombstr(ofork->of_ad->ad_fullpath),
 +        (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
 +
      if ( flushfork( ofork ) < 0 ) {
          LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) );
      }
    There is a lot to tell about fsync, fdatasync, F_FULLFSYNC.
    fsync(2) on OSX is implemented differently than on other platforms.
    see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf.
 - */
 +*/
  int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
  {
      struct ofork        *ofork;
 -    u_int16_t           ofrefnum;
 +    uint16_t           ofrefnum;
  
      *rbuflen = 0;
      ibuf += 2;
          return( AFPERR_PARAM );
      }
  
 +    LOG(log_debug, logtype_afpd,
 +        "afp_syncfork(\"%s\", fork: %s)",
 +        cfrombstr(ofork->of_ad->ad_fullpath),
 +        (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
 +
      if ( flushfork( ofork ) < 0 ) {
 -      LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
 -      return AFPERR_MISC;
 +        LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
 +        return AFPERR_MISC;
      }
  
      return( AFP_OK );
@@@ -1060,14 -1081,14 +1072,14 @@@ int flushfork(struct ofork *ofork
      int err = 0, doflush = 0;
  
      if ( ad_data_fileno( ofork->of_ad ) != -1 &&
 -            fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
 +         fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
          LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
              of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) );
          err = -1;
      }
  
      if ( ad_reso_fileno( ofork->of_ad ) != -1 &&  /* HF */
 -       (ofork->of_flags & AFPFORK_RSRC)) {
 +         (ofork->of_flags & AFPFORK_RSRC)) {
  
          /* read in the rfork length */
          ad_refresh(ofork->of_ad);
  
          /* flush the header */
          if (doflush && ad_flush(ofork->of_ad) < 0)
 -                err = -1;
 +            err = -1;
  
          if (fsync( ad_reso_fileno( ofork->of_ad )) < 0)
              err = -1;
  
  int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
  {
 -    struct ofork      *ofork;
 -    u_int16_t         ofrefnum;
 +    struct ofork    *ofork;
 +    uint16_t       ofrefnum;
  
      *rbuflen = 0;
      ibuf += 2;
          LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum );
          return( AFPERR_PARAM );
      }
 +
 +    LOG(log_debug, logtype_afpd,
 +        "afp_closefork(\"%s\", fork: %s)",
 +        cfrombstr(ofork->of_ad->ad_fullpath),
 +        (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
 +
      if ( of_closefork( ofork ) < 0 ) {
          LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) );
          return( AFPERR_PARAM );
  
  
  static ssize_t write_file(struct ofork *ofork, int eid,
 -                                     off_t offset, char *rbuf,
 -                                     size_t rbuflen, const int xlate)
 +                          off_t offset, char *rbuf,
 +                          size_t rbuflen, const int xlate)
  {
      char *p, *q;
      ssize_t cc;
  
  
  /* FPWrite. NOTE: on an error, we always use afp_write_err as
 - * the client may have sent us a bunch of data that's not reflected 
 + * the client may have sent us a bunch of data that's not reflected
   * in reqcount et al. */
  static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
  {
++<<<<<<< HEAD
 +    struct ofork    *ofork;
 +    off_t               offset, saveoff, reqcount;
 +    int             endflag, eid, xlate = 0, err = AFP_OK;
 +    uint16_t       ofrefnum;
++=======
+     struct ofork      *ofork;
+     off_t           offset, saveoff, reqcount, oldsize, newsize;
+     int                       endflag, eid, xlate = 0, err = AFP_OK;
+     u_int16_t         ofrefnum;
++>>>>>>> netafp/master
      ssize_t             cc;
  
      /* figure out parameters */
          goto afp_write_err;
      }
  
 +    LOG(log_debug, logtype_afpd,
 +        "afp_write(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
 +        cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount,
 +        (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
 +
      if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
          err = AFPERR_ACCESS;
          goto afp_write_err;
          goto afp_write_err;
      }
  
+     oldsize = ad_size(ofork->of_ad, eid);
      if (endflag)
-         offset += ad_size(ofork->of_ad, eid);
+         offset += oldsize;
  
      /* handle bogus parameters */
      if (reqcount < 0 || offset < 0) {
          goto afp_write_err;
      }
  
+     newsize = ((offset + reqcount) > oldsize) ? (offset + reqcount) : oldsize;
      /* offset can overflow on 64-bit capable filesystems.
       * report disk full if that's going to happen. */
 -     if (sum_neg(is64, offset, reqcount)) {
 +    if (sum_neg(is64, offset, reqcount)) {
          err = AFPERR_DFULL;
          goto afp_write_err;
      }
  
      /* this is yucky, but dsi can stream i/o and asp can't */
      switch (obj->proto) {
 -#ifndef NO_DDP
 -    case AFPPROTO_ASP:
 -        if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
 -            *rbuflen = 0;
 -            LOG(log_error, logtype_afpd, "afp_write: asp_wrtcont: %s", strerror(errno) );
 -            return( AFPERR_PARAM );
 -        }
 +    case AFPPROTO_DSI:
 +    {
 +        DSI *dsi = obj->handle;
  
 -#ifdef DEBUG1
 -        if (obj->options.flags & OPTION_DEBUG) {
 -            printf("(write) len: %d\n", *rbuflen);
 -            bprint(rbuf, *rbuflen);
 -        }
 -#endif
 -        if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
 -                             xlate)) < 0) {
 +        /* find out what we have already and write it out. */
 +        cc = dsi_writeinit(dsi, rbuf, *rbuflen);
 +        if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
 +            dsi_writeflush(dsi);
              *rbuflen = 0;
              ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
              return cc;
          }
          offset += cc;
 -        break;
 -#endif /* no afp/asp */
 -
 -    case AFPPROTO_DSI:
 -        {
 -            DSI *dsi = obj->handle;
  
 -            /* find out what we have already and write it out. */
 -            cc = dsi_writeinit(dsi, rbuf, *rbuflen);
 -            if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
 +#if 0 /*def HAVE_SENDFILE_WRITE*/
 +        if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
 +            if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
 +                                   offset, dsi->datasize)) < 0) {
 +                switch (errno) {
 +                case EDQUOT :
 +                case EFBIG :
 +                case ENOSPC :
 +                    cc = AFPERR_DFULL;
 +                    break;
 +                default :
 +                    LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
 +                    goto afp_write_loop;
 +                }
                  dsi_writeflush(dsi);
                  *rbuflen = 0;
 -                ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
 +                ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
 +                           reqcount,  ofork->of_refnum);
                  return cc;
              }
 -            offset += cc;
  
 -#if 0 /*def HAVE_SENDFILE_WRITE*/
 -            if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
 -                if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
 -                                       offset, dsi->datasize)) < 0) {
 -                    switch (errno) {
 -                    case EDQUOT :
 -                    case EFBIG :
 -                    case ENOSPC :
 -                        cc = AFPERR_DFULL;
 -                        break;
 -                    default :
 -                        LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
 -                        goto afp_write_loop;
 -                    }
 -                    dsi_writeflush(dsi);
 -                    *rbuflen = 0;
 -                    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
 -                               reqcount,  ofork->of_refnum);
 -                    return cc;
 -                }
 -
 -                offset += cc;
 -                goto afp_write_done;
 -            }
 +            offset += cc;
 +            goto afp_write_done;
 +        }
  #endif /* 0, was HAVE_SENDFILE_WRITE */
  
 -            /* loop until everything gets written. currently
 -                    * dsi_write handles the end case by itself. */
 -            while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
 -                if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
 -                    dsi_writeflush(dsi);
 -                    *rbuflen = 0;
 -                    ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
 -                               reqcount,  ofork->of_refnum);
 -                    return cc;
 -                }
 -                offset += cc;
 +        /* loop until everything gets written. currently
 +         * dsi_write handles the end case by itself. */
 +        while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
 +            if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
 +                dsi_writeflush(dsi);
 +                *rbuflen = 0;
 +                ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
 +                           reqcount,  ofork->of_refnum);
 +                return cc;
              }
 +            offset += cc;
          }
 -        break;
 +    }
 +    break;
      }
  
      ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount,  ofork->of_refnum);
      ofork->of_flags |= AFPFORK_MODIFIED;
  
      /* update write count */
-     ofork->of_vol->v_written += reqcount;
+     ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0;
  
      *rbuflen = set_off_t (offset, rbuf, is64);
      return( AFP_OK );
@@@ -1329,9 -1366,9 +1351,9 @@@ int afp_write(AFPObj *obj, char *ibuf, 
      return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
  }
  
 -/* ---------------------------- 
 +/* ----------------------------
   * FIXME need to deal with SIGXFSZ signal
 -*/
 + */
  int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
  {
      return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
  /* ---------------------------- */
  int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
  {
 -    struct ofork      *ofork;
 +    struct ofork    *ofork;
      int             ret;
 -    u_int16_t         ofrefnum, bitmap;
 +    uint16_t       ofrefnum, bitmap;
      size_t          buflen;
      ibuf += 2;
      memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
      }
  
      if (AFP_OK != ( ret = getforkparams( ofork, bitmap,
 -                               rbuf + sizeof( u_short ), &buflen ))) {
 +                                         rbuf + sizeof( u_short ), &buflen ))) {
          return( ret );
      }
  
diff --combined etc/afpd/main.c
index e858146752f25aa95d8c555f34b8cb5db199a528,edcfe6a7565d8339e5239b8ecead0a39fb66a821..c056a737c0a9e64f8c89c5b1e68718c6d63943b4
  #include <stdlib.h>
  #include <string.h>
  #include <signal.h>
 -
  #include <sys/param.h>
  #include <sys/uio.h>
 -#include <atalk/logger.h>
  #include <sys/time.h>
  #include <sys/socket.h>
  #include <sys/poll.h>
  #include <sys/wait.h>
  #include <sys/resource.h>
  
 +#include <atalk/logger.h>
  #include <atalk/adouble.h>
 -
 -#include <netatalk/at.h>
  #include <atalk/compat.h>
  #include <atalk/dsi.h>
 -#include <atalk/atp.h>
 -#include <atalk/asp.h>
  #include <atalk/afp.h>
  #include <atalk/paths.h>
  #include <atalk/util.h>
  #include <atalk/server_child.h>
  #include <atalk/server_ipc.h>
 +#include <atalk/errchk.h>
 +#include <atalk/locking.h>
  #include <atalk/globals.h>
  
 +#include "event2/event.h"
 +#include "event2/http.h"
 +#include "event2/rpc.h"
 +
  #include "afp_config.h"
  #include "status.h"
  #include "fork.h"
@@@ -57,7 -56,6 +57,7 @@@ static char **argv = NULL
  
  unsigned char nologin = 0;
  struct afp_options default_options;
 +
  static AFPConfig *configs;
  static server_child *server_children;
  static sig_atomic_t reloadconfig = 0;
@@@ -135,7 -133,11 +135,7 @@@ static void fd_reset_listening_sockets(
  /* ------------------ */
  static void afp_goaway(int sig)
  {
 -        AFPConfig *config;
 -
 -#ifndef NO_DDP
 -    asp_kill(sig);
 -#endif /* ! NO_DDP */
 +    AFPConfig *config;
  
      switch( sig ) {
  
@@@ -226,16 -228,16 +226,16 @@@ static int setlimits(void
      struct rlimit rlim;
  
      if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
-         LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
-         exit(1);
+         LOG(log_warning, logtype_afpd, "setlimits: reading current limits failed: %s", strerror(errno));
+         return -1;
      }
      if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < 65535) {
          rlim.rlim_cur = 65535;
          if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < 65535)
              rlim.rlim_max = 65535;
          if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
-             LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
-             exit(1);
+             LOG(log_warning, logtype_afpd, "setlimits: increasing limits failed: %s", strerror(errno));
+             return -1;
          }
      }
      return 0;
@@@ -391,15 -393,9 +391,15 @@@ int main(int ac, char **av
      }
      pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
  
 -    /* Register CNID  */
 +    /* Initialize */
      cnid_init();
 -
 +    if (locktable_init("XXX") != 0)
 +        exit(EXITERR_SYS);
 +#if 0
 +    if (rpc_init("127.0.0.1", 4701) != 0)
 +        exit(EXITERR_SYS);
 +#endif
 +    
      /* watch atp, dsi sockets and ipc parent/child file descriptor. */
  
      if (default_options.flags & OPTION_KEEPSESSIONS) {
diff --combined etc/afpd/unix.c
index e1358cc6100faa3f8ee8a2502b5bad2631194bd8,8d60a6ef61cca4a547e0ffe6bdfc1e9e6f534c7b..54914f1991779f3c392cd807457823ade7c09e4c
@@@ -9,7 -9,25 +9,8 @@@
  
  #include <stdio.h>
  #include <stdlib.h>
 -
 -/* STDC check */
 -#ifdef STDC_HEADERS
+ #include <inttypes.h>
  #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>
@@@ -33,9 -51,9 +34,9 @@@
  /*
   * Get the free space on a partition.
   */
 -int ustatfs_getvolspace(const struct vol *vol, VolSpace *bfree, VolSpace *btotal, u_int32_t *bsize)
 +int ustatfs_getvolspace(const struct vol *vol, VolSpace *bfree, VolSpace *btotal, uint32_t *bsize)
  {
-     VolSpace maxVolSpace = (~(VolSpace)0);
+     VolSpace maxVolSpace = UINT64_MAX;
  
  #ifdef ultrix
      struct fs_data    sfs;
@@@ -43,7 -61,6 +44,6 @@@
      struct statfs     sfs;
  #endif /*ultrix*/
  
      if ( statfs( vol->v_path, &sfs ) < 0 ) {
          LOG(log_error, logtype_afpd, "ustatfs_getvolspace unable to stat %s", vol->v_path);
          return( AFPERR_PARAM );
@@@ -152,7 -169,7 +152,7 @@@ mode_t mode
   *
   * dir parameter is used by AFS
   */
- void accessmode(char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st)
+ void accessmode(const struct vol *vol, char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st)
  {
      struct stat     sb;
  
      }
      utommode( st, ma );
  #ifdef HAVE_ACLS
-     acltoownermode(path, st, ma);
+     acltoownermode(vol, path, st, ma);
  #endif
  }
  
@@@ -266,17 -283,17 +266,17 @@@ int setdeskmode(const mode_t mode
              }
  
              if (S_ISDIR(st.st_mode)) {
-                 if ( chmod( modbuf,  (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
+                 if ( chmod_acl( modbuf,  (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
                       LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
                  }
-             } else if ( chmod( modbuf,  mode & ~(default_options.umask | EXEC_MODE) ) < 0 && errno != EPERM ) {
+             } else if ( chmod_acl( modbuf,  mode & ~(default_options.umask | EXEC_MODE) ) < 0 && errno != EPERM ) {
                  LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
              }
  
          }
          closedir( sub );
          /* XXX: need to preserve special modes */
-         if ( chmod( deskp->d_name,  (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
+         if ( chmod_acl( deskp->d_name,  (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
              LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) );
          }
      }
          return -1;
      }
      /* XXX: need to preserve special modes */
-     if ( chmod( ".AppleDesktop",  (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
+     if ( chmod_acl( ".AppleDesktop",  (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
          LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", fullpathname(".AppleDesktop"),strerror(errno) );
      }
      return( 0 );
@@@ -315,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;
@@@ -342,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 );
@@@ -486,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/unix.h
index dcf45c821537d79332523d2070a05c42f6b3dceb,54ebf3d69bfac079b576a6eae4f00edaf757181f..417acb172e1561eff6abf9159a311fd9db4475a9
@@@ -1,8 -1,14 +1,8 @@@
 -/*
 - * $Id: unix.h,v 1.23 2010-04-12 14:28:47 franklahm Exp $
 - */
 -
  #ifndef AFPD_UNIX_H
  #define AFPD_UNIX_H
  
 -#ifdef HAVE_SYS_CDEFS_H
 -#include <sys/cdefs.h>
 -#endif /* HAVE_SYS_CDEFS_H */
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
 +
  #include "config.h"
  #include "volume.h"
  
@@@ -203,12 -209,12 +203,12 @@@ extern long quotactl (unsigned int, con
  
  #endif /* linux */
  
 -extern int getnfsquota (struct vol *, const int, const u_int32_t,
 -                                struct dqblk *);
 +extern int getnfsquota (struct vol *, const int, const uint32_t,
 +                        struct dqblk *);
  
  #endif /* ! HAVE_LIBQUOTA */
  extern int uquota_getvolspace (struct vol *, VolSpace *, VolSpace *,
 -                                       const u_int32_t);
 +                               const uint32_t);
  #endif /* NO_QUOTA_SUPPORT */
  
  extern struct afp_options default_options;
@@@ -221,7 -227,7 +221,7 @@@ extern int setdeskowner     (const uid_
  extern int setdirowner      (const struct vol *, const char *, const uid_t, const gid_t);
  extern int setfilunixmode   (const struct vol *, struct path*, const mode_t);
  extern int setfilowner      (const struct vol *, const uid_t, const gid_t, struct path*);
- extern void accessmode      (char *, struct maccess *, struct dir *, struct stat *);
+ extern void accessmode      (const struct vol *, char *, struct maccess *, struct dir *, struct stat *);
  
  #ifdef AFS    
      #define accessmode afsmode
diff --combined etc/afpd/volume.c
index b6707b313699ea77646019f1ec44c068a8234ea2,50bafbe55b555e5aa0d12d89721a714b7d344879..7437f58b6a6fad9a86b7d13bf4dd1cac89cb7446
  #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>
@@@ -22,6 -38,7 +22,6 @@@
  #include <inttypes.h>
  #include <time.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>
  #include <atalk/ftw.h>
  #include <atalk/globals.h>
  #include <atalk/fce_api.h>
+ #include <atalk/errchk.h>
  
  #ifdef CNID_DB
  #include <atalk/cnid.h>
@@@ -64,7 -81,7 +65,7 @@@ extern int afprun(int root, char *cmd, 
  struct vol *current_vol;        /* last volume from getvolbyvid() */
  
  static struct vol *Volumes = NULL;
 -static u_int16_t    lastvid = 0;
 +static uint16_t    lastvid = 0;
  static char     *Trash = "\02\024Network Trash Folder";
  
  static struct extmap    *Extmap = NULL, *Defextmap = NULL;
@@@ -90,7 -107,15 +91,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
@@@ -122,7 -147,12 +123,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 */
@@@ -236,12 -266,25 +237,12 @@@ static char *volxlate(AFPObj *obj
          } else if (is_var(p, "$c")) {
              if (afpmaster && xlatevolname)
                  return NULL;
 -#ifndef NO_DDP
 -            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;
 -
 -            }
 -#endif
 -            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;
 -#ifndef NO_DDP
 -            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;
 -
 -            }
 -#endif
 -            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;
@@@ -393,10 -447,16 +394,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);
  
@@@ -537,7 -612,7 +538,7 @@@ static int creatvol(AFPObj *obj, struc
      char        tmpname[AFPVOL_U8MNAMELEN+1];
      ucs2_t      u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2];
      char        suffix[6]; /* max is #FFFF */
 -    u_int16_t   flags;
 +    uint16_t   flags;
  
      LOG(log_debug, logtype_afpd, "createvol: Volume '%s'", name);
  
          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);
@@@ -1102,6 -1190,7 +1103,7 @@@ static int readvolfile(AFPObj *obj, str
      int         i;
      struct passwd   *pw;
      struct vol_option   save_options[VOLOPT_NUM];
+     struct vol_option   default_options[VOLOPT_NUM];
      struct vol_option   options[VOLOPT_NUM];
      struct stat         st;
  
          break;
      }
  
-     memset(save_options, 0, sizeof(save_options));
+     memset(default_options, 0, sizeof(default_options));
  
      /* Enable some default options for all volumes */
-     save_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
+     default_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
  #ifdef HAVE_ACLS
-     save_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS;
+     default_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS;
  #endif
-     save_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO;
+     default_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO;
      LOG(log_maxdebug, logtype_afpd, "readvolfile: seeding default umask: %04o",
          obj->options.umask);
-     save_options[VOLOPT_UMASK].i_value = obj->options.umask;
+     default_options[VOLOPT_UMASK].i_value = obj->options.umask;
+     memcpy(save_options, default_options, sizeof(options));
  
      LOG(log_debug, logtype_afpd, "readvolfile: \"%s\"", path);
  
          case ':':
              /* change the default options for this file */
              if (strncmp(path, VOLOPT_DEFAULT, VOLOPT_DEFAULT_LEN) == 0) {
+                 volfree(default_options, save_options);
+                 memcpy(default_options, save_options, sizeof(options));
                  *tmp = '\0';
                  for (i = 0; i < VOLOPT_NUM; i++) {
                      if (parseline( sizeof( path ) - VOLOPT_DEFAULT_LEN - 1,
                                     path + VOLOPT_DEFAULT_LEN) < 0)
                          break;
-                     volset(save_options, NULL, tmp, sizeof(tmp) - 1,
+                     volset(default_options, NULL, tmp, sizeof(tmp) - 1,
                             path + VOLOPT_DEFAULT_LEN);
                  }
              }
               * able to specify things in any order, but i don't want to
               * re-write everything. */
  
-             memcpy(options, save_options, sizeof(options));
+             memcpy(options, default_options, sizeof(options));
              *volname = '\0';
  
              /* read in up to VOLOP_NUM possible options */
                  if (parseline( sizeof( tmp ) - 1, tmp ) < 0)
                      break;
  
-                 volset(options, save_options, volname, sizeof(volname) - 1, tmp);
+                 volset(options, default_options, volname, sizeof(volname) - 1, tmp);
              }
  
              /* check allow/deny lists (if not afpd master loading volumes for Zeroconf reg.):
  
                  creatvol(obj, pwent, path, tmp, options, p2 != NULL);
              }
-             volfree(options, save_options);
+             volfree(options, default_options);
              break;
  
          case '.' :
@@@ -1291,6 -1383,10 +1296,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);
  }
@@@ -1349,72 -1445,161 +1354,161 @@@ static void volume_unlink(struct vol *v
          }
      }
  }
- static off_t getused_size; /* result of getused() */
  /*!
-   nftw callback for getused()
+  * Read band-size info from Info.plist XML file of an TM sparsebundle
+  *
+  * @param path   (r) path to Info.plist file
+  * @return           band-size in bytes, -1 on error
   */
- static int getused_stat(const char *path,
-                         const struct stat *statp,
-                         int tflag,
-                         struct FTW *ftw)
+ static long long int get_tm_bandsize(const char *path)
  {
-     off_t low, high;
+     EC_INIT;
+     FILE *file = NULL;
+     char buf[512];
+     long long int bandsize = -1;
+     EC_NULL_LOGSTR( file = fopen(path, "r"),
+                     "get_tm_bandsize(\"%s\"): %s",
+                     path, strerror(errno) );
+     while (fgets(buf, sizeof(buf), file) != NULL) {
+         if (strstr(buf, "band-size") == NULL)
+             continue;
  
-     if (tflag == FTW_F || tflag == FTW_D) {
-         getused_size += statp->st_blocks * 512;
+         if (fscanf(file, " <integer>%lld</integer>", &bandsize) != 1) {
+             LOG(log_error, logtype_afpd, "get_tm_bandsize(\"%s\"): can't parse band-size", path);
+             EC_FAIL;
+         }
+         break;
      }
  
-     return 0;
+ EC_CLEANUP:
+     if (file)
+         fclose(file);
+     LOG(log_debug, logtype_afpd, "get_tm_bandsize(\"%s\"): bandsize: %lld", path, bandsize);
+     return bandsize;
  }
  
- #define GETUSED_CACHETIME 5
  /*!
-  * Calculate used size of a volume with nftw
+  * Return number on entries in a directory
   *
-  * The result is cached, we're try to avoid frequently calling nftw()
+  * @param path   (r) path to dir
+  * @return           number of entries, -1 on error
+  */
+ static long long int get_tm_bands(const char *path)
+ {
+     EC_INIT;
+     long long int count = 0;
+     DIR *dir = NULL;
+     const struct dirent *entry;
+     EC_NULL( dir = opendir(path) );
+     while ((entry = readdir(dir)) != NULL)
+         count++;
+     count -= 2; /* All OSens I'm aware of return "." and "..", so just substract them, avoiding string comparison in loop */
+         
+ EC_CLEANUP:
+     if (dir)
+         closedir(dir);
+     if (ret != 0)
+         return -1;
+     return count;
+ }
+ /*!
+  * Calculate used size of a TimeMachine volume
   *
-  * 1) Call nftw an refresh if:
-  * 1a) - we're called the first time 
-  * 1b) - volume modification date is not yet set and the last time we've been called is
-  *       longer then 30 sec ago
-  * 1c) - the last volume modification is less then 30 sec old
+  * This assumes that the volume is used only for TimeMachine.
+  *
+  * 1) readdir(path of volume)
+  * 2) for every element that matches regex "\(.*\)\.sparsebundle$" :
+  * 3) parse "\1.sparsebundle/Info.plist" and read the band-size XML key integer value
+  * 4) readdir "\1.sparsebundle/bands/" counting files
+  * 5) calculate used size as: (file_count - 1) * band-size
+  *
+  * The result of the calculation is returned in "volume->v_tm_used".
+  * "volume->v_appended" gets reset to 0.
+  * "volume->v_tm_cachetime" is updated with the current time from time(NULL).
+  *
+  * "volume->v_tm_used" is cached for TM_USED_CACHETIME seconds and updated by
+  * "volume->v_appended". The latter is increased by X every time the client
+  * appends X bytes to a file (in fork.c).
   *
   * @param vol     (rw) volume to calculate
+  * @return             0 on success, -1 on error
   */
- static int getused(struct vol *vol)
+ #define TM_USED_CACHETIME 60    /* cache for 60 seconds */
+ static int get_tm_used(struct vol * restrict vol)
  {
-     static time_t vol_mtime = 0;
-     int ret = 0;
+     EC_INIT;
+     long long int bandsize;
+     VolSpace used = 0;
+     bstring infoplist = NULL;
+     bstring bandsdir = NULL;
+     DIR *dir = NULL;
+     const struct dirent *entry;
+     const char *p;
+     struct stat st;
+     long int links;
      time_t now = time(NULL);
  
-     if (!vol_mtime
-         || (!vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < now))
-         || (vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < vol->v_mtime))
-         ) {
-         vol_mtime = now;
-         getused_size = 0;
-         vol->v_written = 0;
-         ret = nftw(vol->v_path, getused_stat, NULL, 20, FTW_PHYS); /* 2 */
-         LOG(log_debug, logtype_afpd, "volparams: from nftw: %" PRIu64 " bytes",
-             getused_size);
-     } else {
-         getused_size += vol->v_written;
-         vol->v_written = 0;
-         LOG(log_debug, logtype_afpd, "volparams: cached used: %" PRIu64 " bytes",
-             getused_size);
+     if (vol->v_tm_cachetime
+         && ((vol->v_tm_cachetime + TM_USED_CACHETIME) >= now)) {
+         if (vol->v_tm_used == -1)
+             EC_FAIL;
+         vol->v_tm_used += vol->v_appended;
+         vol->v_appended = 0;
+         LOG(log_debug, logtype_afpd, "getused(\"%s\"): cached: %" PRIu64 " bytes",
+             vol->v_path, vol->v_tm_used);
+         return 0;
      }
  
-     return ret;
+     vol->v_tm_cachetime = now;
+     EC_NULL( dir = opendir(vol->v_path) );
+     while ((entry = readdir(dir)) != NULL) {
+         if (((p = strstr(entry->d_name, "sparsebundle")) != NULL)
+             && (strlen(entry->d_name) == (p + strlen("sparsebundle") - entry->d_name))) {
+             EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") );
+             
+             if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1)
+                 continue;
+             EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") );
+             if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1)
+                 continue;
+             used += (links - 1) * bandsize;
+             LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes",
+                 cfrombstr(bandsdir), used);
+         }
+     }
+     vol->v_tm_used = used;
+ EC_CLEANUP:
+     if (infoplist)
+         bdestroy(infoplist);
+     if (bandsdir)
+         bdestroy(bandsdir);
+     if (dir)
+         closedir(dir);
+     LOG(log_debug, logtype_afpd, "getused(\"%s\"): %" PRIu64 " bytes", vol->v_path, vol->v_tm_used);
+     EC_EXIT;
  }
  
  static int getvolspace(struct vol *vol,
 -                       u_int32_t *bfree, u_int32_t *btotal,
 -                       VolSpace *xbfree, VolSpace *xbtotal, u_int32_t *bsize)
 +                       uint32_t *bfree, uint32_t *btotal,
 +                       VolSpace *xbfree, VolSpace *xbtotal, uint32_t *bsize)
  {
      int         spaceflag, rc;
 -    u_int32_t   maxsize;
 +    uint32_t   maxsize;
      VolSpace    used;
  #ifndef NO_QUOTA_SUPPORT
      VolSpace    qfree, qtotal;
          return( rc );
      }
  
- #define min(a,b)    ((a)<(b)?(a):(b))
  #ifndef NO_QUOTA_SUPPORT
      if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_UQUOTA ) {
          if ( uquota_getvolspace( vol, &qfree, &qtotal, *bsize ) == AFP_OK ) {
              vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_UQUOTA;
-             *xbfree = min(*xbfree, qfree);
-             *xbtotal = min( *xbtotal, qtotal);
+             *xbfree = MIN(*xbfree, qfree);
+             *xbtotal = MIN(*xbtotal, qtotal);
              goto getvolspace_done;
          }
      }
  
  getvolspace_done:
      if (vol->v_limitsize) {
-         if (getused(vol) != 0)
+         if (get_tm_used(vol) != 0)
              return AFPERR_MISC;
-         LOG(log_debug, logtype_afpd, "volparams: used on volume: %" PRIu64 " bytes",
-             getused_size);
-         vol->v_tm_used = getused_size;
  
-         *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
-         *xbfree = min(*xbfree, *xbtotal < getused_size ? 0 : *xbtotal - getused_size);
+         *xbtotal = MIN(*xbtotal, (vol->v_limitsize * 1024 * 1024));
+         *xbfree = MIN(*xbfree, *xbtotal < vol->v_tm_used ? 0 : *xbtotal - vol->v_tm_used);
+         LOG(log_debug, logtype_afpd,
+             "volparams: total: %" PRIu64 ", used: %" PRIu64 ", free: %" PRIu64 " bytes",
+             *xbtotal, vol->v_tm_used, *xbfree);
      }
  
-     *bfree = min( *xbfree, maxsize);
-     *btotal = min( *xbtotal, maxsize);
+     *bfree = MIN(*xbfree, maxsize);
+     *btotal = MIN(*xbtotal, maxsize);
      return( AFP_OK );
  }
  
@@@ -1480,7 -1665,7 +1574,7 @@@ void vol_fce_tm_event(void
          last = now;
          for ( ; vol; vol = vol->v_next ) {
              if (vol->v_flags & AFPVOL_TM)
-                 (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_written);
+                 (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_appended);
          }
      }
  }
   * set volume creation date
   * avoid duplicate, well at least it tries
   */
 -static void vol_setdate(u_int16_t id, struct adouble *adp, time_t date)
 +static void vol_setdate(uint16_t id, struct adouble *adp, time_t date)
  {
      struct vol  *volume;
      struct vol  *vol = Volumes;
  }
  
  /* ----------------------- */
 -static int getvolparams( u_int16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen)
 +static int getvolparams( uint16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen)
  {
      struct adouble  ad;
      int         bit = 0, isad = 1;
 -    u_int32_t       aint;
 +    uint32_t       aint;
      u_short     ashort;
 -    u_int32_t       bfree, btotal, bsize;
 +    uint32_t       bfree, btotal, bsize;
      VolSpace            xbfree, xbtotal; /* extended bytes */
      char        *data, *nameoff = NULL;
      char                *slash;
       * .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 */
  
          case VOLPBIT_NAME :
              nameoff = data;
 -            data += sizeof( u_int16_t );
 +            data += sizeof( uint16_t );
              break;
  
          case VOLPBIT_BSIZE:  /* block size */
  }
  
  /* ------------------------- */
 -static int stat_vol(u_int16_t bitmap, struct vol *vol, char *rbuf, size_t *rbuflen)
 +static int stat_vol(uint16_t bitmap, struct vol *vol, char *rbuf, size_t *rbuflen)
  {
      struct stat st;
      int     ret;
@@@ -1836,7 -2029,7 +1930,7 @@@ int afp_getsrvrparms(AFPObj *obj, char 
              if (!S_ISDIR(st.st_mode)) {
                  continue;       /* not a dir */
              }
-             accessmode(volume->v_path, &ma, NULL, &st);
+             accessmode(volume, volume->v_path, &ma, NULL, &st);
              if ((ma.ma_user & (AR_UREAD | AR_USEARCH)) != (AR_UREAD | AR_USEARCH)) {
                  continue;   /* no r-x access */
              }
          return AFPERR_PARAM;
      }
      tv.tv_sec = AD_DATE_FROM_UNIX(tv.tv_sec);
 -    memcpy(data, &tv.tv_sec, sizeof( u_int32_t));
 -    data += sizeof( u_int32_t);
 +    memcpy(data, &tv.tv_sec, sizeof( uint32_t));
 +    data += sizeof( uint32_t);
      *data = vcnt;
      return( AFP_OK );
  }
@@@ -2051,7 -2244,7 +2145,7 @@@ int afp_openvol(AFPObj *obj, char *ibuf
      struct dir  *dir;
      int     len, ret;
      size_t  namelen;
 -    u_int16_t   bitmap;
 +    uint16_t   bitmap;
      char        path[ MAXPATHLEN + 1];
      char        *vol_uname;
      char        *vol_mname;
  
      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 );
@@@ -2330,7 -2530,7 +2424,7 @@@ static void deletevol(struct vol *vol
  int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
  {
      struct vol  *vol;
 -    u_int16_t   vid;
 +    uint16_t   vid;
  
      *rbuflen = 0;
      ibuf += 2;
  }
  
  /* ------------------------- */
 -struct vol *getvolbyvid(const u_int16_t vid )
 +struct vol *getvolbyvid(const uint16_t vid )
  {
      struct vol  *vol;
  
          return( NULL );
      }
  
 -#ifdef FORCE_UIDGID
 -    set_uidgid ( vol );
 -#endif /* FORCE_UIDGID */
 -
      current_vol = vol;
  
      return( vol );
@@@ -2466,7 -2670,7 +2560,7 @@@ void setvoltime(AFPObj *obj, struct vo
  int afp_getvolparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,char *rbuf, size_t *rbuflen)
  {
      struct vol  *vol;
 -    u_int16_t   vid, bitmap;
 +    uint16_t   vid, bitmap;
  
      ibuf += 2;
      memcpy(&vid, ibuf, sizeof( vid ));
@@@ -2487,8 -2691,8 +2581,8 @@@ int afp_setvolparams(AFPObj *obj _U_, c
  {
      struct adouble ad;
      struct vol  *vol;
 -    u_int16_t   vid, bitmap;
 -    u_int32_t   aint;
 +    uint16_t   vid, bitmap;
 +    uint32_t   aint;
  
      ibuf += 2;
      *rbuflen = 0;
          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;
  
@@@ -2561,7 -2766,7 +2655,7 @@@ static int create_special_folder (cons
  {
      char        *p,*q,*r;
      struct adouble  ad;
 -    u_int16_t   attr;
 +    uint16_t   attr;
      struct stat st;
      int     ret;
  
      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);
          }
index 7cf72871de3990e87b4e3c5f8e1b98b9c183d3d6,50433c66de807a1dab6888ad7ca815a4cbd9729b..d661071d03b57c8e853e59cd431b2523f5474e69
@@@ -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;
          }
@@@ -374,7 -374,7 +374,7 @@@ static void remove_eafiles(const char *
      if ((dp = opendir(".")) == NULL) {
          dbd_log(LOGSTD, "Couldn't open the directory '%s/%s': %s",
                  cwdbuf, ADv2_DIRNAME, strerror(errno));
-         return;
+         goto exit;
      }
  
      while ((ep = readdir(dp))) {
          } /* if */
      } /* while */
  
+ exit:
      if (dp)
          closedir(dp);
+     if ((chdir("..")) != 0) {
+         dbd_log(LOGSTD, "Couldn't chdir to '%s': %s", cwdbuf, strerror(errno));
+         /* we can't proceed */
+         longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
+     }    
  }
  
  /*
@@@ -494,7 -499,7 +499,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;
          }
@@@ -690,7 -695,7 +695,7 @@@ static cnid_t check_cnid(const char *na
      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 CNID_INVALID;
          /* Everything is fine */
          return db_cnid;
      } else if (ad_cnid && db_cnid && (ad_cnid != db_cnid)) {
-         /* Mismatch ? Delete both from db and re-add data from file */
+         /* Mismatch, overwrite ad file with value from db */
          dbd_log( LOGSTD, "CNID mismatch for '%s/%s', db: %u, ad-file: %u", cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid));
          if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
-             rqst.cnid = db_cnid;
-             ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
-             if (dbif_txn_close(dbd, ret) != 0)
-                 return CNID_INVALID;
-             rqst.cnid = ad_cnid;
-             ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
-             if (dbif_txn_close(dbd, ret) != 0)
-                 return CNID_INVALID;
-             ret = dbd_rebuild_add(dbd, &rqst, &rply);
-             if (dbif_txn_close(dbd, ret) != 0)
+             dbd_log(LOGSTD, "Updating AppleDouble file for '%s/%s' with CNID: %u from database",
+                             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) {
+                 dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
+                         cwdbuf, name, strerror(errno));
                  return CNID_INVALID;
+             }
+             ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
+             ad_flush(&ad);
+             ad_close_metadata(&ad);
          }
-         return ad_cnid;
+         return db_cnid;
      } else if (ad_cnid && (db_cnid == 0)) {
          /* in ad-file but not in db */
          if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
  
              rqst.cnid = ad_cnid;
              ret = dbd_resolve(dbd, &rqst, &rply);
-             if (ret == CNID_DBD_RES_OK) {
+             if (rply.result == CNID_DBD_RES_OK) {
                  /* Occupied! Choose another, update ad-file */
                  ret = dbd_add(dbd, &rqst, &rply, 1);
                  if (dbif_txn_close(dbd, ret) != 0)
                      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 CNID_INVALID;
                  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 CNID_INVALID;
diff --combined etc/cnid_dbd/comm.c
index 4a109100a4264321ec4318dcd2e84141f96ceffe,dbe8da14c0707df7d03d4079f9fe52ee5417638a..23c6a58edaa18cfdeef1189759c047453ffd2416
@@@ -9,17 -9,7 +9,7 @@@
  #include "config.h"
  #endif
  
- #if !defined(__FreeBSD__) && !defined(__NetBSD__)
- #ifndef _XOPEN_SOURCE
- # define _XOPEN_SOURCE 600
- #endif
- #ifndef __EXTENSIONS__
- # define __EXTENSIONS__
- #endif
- #ifndef _GNU_SOURCE
- # define _GNU_SOURCE
- #endif
- #endif
+ #include <atalk/standards.h>
  
  #include <stdio.h>
  #include <stdlib.h>
@@@ -220,7 -210,7 +210,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);
  
index fc8e32afb4224231c971bd9a3673ec094aacda87,f3a93e4ca54d3d9ae03fb3bd0f60771f3551542e..562838b384a28dacc46873f8742a8296a6a2eba1
  
  #include <stdio.h>
  #include <string.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/logger.h>
 -#include <netatalk/endian.h>
  #include <atalk/cnid_dbd_private.h>
  
 -
  #include "pack.h"
  #include "dbif.h"
  #include "dbd.h"
@@@ -48,6 -48,11 +48,11 @@@ int dbd_rebuild_add(DBD *dbd, struct cn
          return -1;
      }
  
+     LOG(log_debug, logtype_cnid,
+         "dbd_rebuild_add(CNID: %u, did: %u, name: \"%s\", dev/ino:0x%llx/0x%llx): success",
+         ntohl(rqst->cnid), ntohl(rqst->did), rqst->name,
+         (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
      key.data = ROOTINFO_KEY;
      key.size = ROOTINFO_KEYLEN;
  
index 49c69e9afb3d4f3728d4a95d5bcab54ea68048d0,1c2e2da914bc0143df5d1c54f523be86c99e5281..bb3561caba7a1018605be36649d85b13abb8ab29
@@@ -12,8 -12,7 +12,8 @@@
  #include <string.h>
  #include <atalk/logger.h>
  #include <errno.h>
 -#include <netatalk/endian.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/cnid_dbd_private.h>
  
  #include "dbif.h"
@@@ -54,8 -53,8 +54,8 @@@ int dbd_resolve(DBD *dbd, struct cnid_d
      rply->namelen = data.size;
      rply->name = (char *)data.data;
  
-     LOG(log_debug, logtype_cnid, "dbd_resolve: Resolving CNID %u to did %u name %s",
-         ntohl(rqst->cnid), ntohl(rply->did), rply->name);
+     LOG(log_debug, logtype_cnid, "dbd_resolve(CNID: %u): did: %u, name: \"%s\"",
+         ntohl(rqst->cnid), ntohl(rply->did), rply->name + CNID_NAME_OFS);
  
      rply->result = CNID_DBD_RES_OK;
      return 1;
diff --combined etc/uams/uams_dhx2_pam.c
index f2976b45fb83d24af1edd6e32577a6bc876315dd,4c66a8732771f0a1803e285e0d726a8733ca9e64..0f0c8a535329b579bac63659a88b41194f481b59
@@@ -46,7 -46,7 +46,7 @@@ static gcry_mpi_t p, g, Ra
  static gcry_mpi_t serverNonce;
  static char *K_MD5hash = NULL;
  static int K_hash_len;
 -static u_int16_t ID;
 +static uint16_t ID;
  
  /* The initialization vectors for CAST128 are fixed by Apple. */
  static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' };
@@@ -267,7 -267,7 +267,7 @@@ static int dhx2_setup(void *obj, char *
  
      /* Session ID first */
      ID = dhxhash(obj);
 -    *(u_int16_t *)rbuf = htons(ID);
 +    *(uint16_t *)rbuf = htons(ID);
      rbuf += 2;
      *rbuflen += 2;
  
      *rbuflen += 4;
  
      /* len = length of p = PRIMEBITS/8 */
 -    *(u_int16_t *)rbuf = htons((u_int16_t) PRIMEBITS/8);
 +    *(uint16_t *)rbuf = htons((uint16_t) PRIMEBITS/8);
      rbuf += 2;
      *rbuflen += 2;
  
@@@ -365,7 -365,7 +365,7 @@@ static int pam_login_ext(void *obj, cha
  {
      char *username;
      size_t len, ulen;
 -    u_int16_t  temp16;
 +    uint16_t  temp16;
  
      *rbuflen = 0;
  
@@@ -488,7 -488,7 +488,7 @@@ static int logincont1(void *obj _U_, ch
      /* ---- Start building reply packet ---- */
  
      /* Session ID + 1 first */
 -    *(u_int16_t *)rbuf = htons(ID+1);
 +    *(uint16_t *)rbuf = htons(ID+1);
      rbuf += 2;
      *rbuflen += 2;
  
@@@ -529,16 -529,46 +529,46 @@@ exit
      return ret;
  }
  
- static int logincont2(void *obj, struct passwd **uam_pwd,
+ /**
+  * Try to authenticate via PAM as "adminauthuser"
+  **/
+ static int loginasroot(const char *adminauthuser, const char **hostname, int status)
+ {
+     int PAM_error;
+     if ((PAM_error = pam_end(pamh, status)) != PAM_SUCCESS)
+         goto exit;
+     pamh = NULL;
+     if ((PAM_error = pam_start("netatalk", adminauthuser, &PAM_conversation, &pamh)) != PAM_SUCCESS) {
+         LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error));
+         goto exit;
+     }
+     /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
+     pam_set_item(pamh, PAM_TTY, "afpd");
+     pam_set_item(pamh, PAM_RHOST, *hostname);
+     if ((PAM_error = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
+         goto exit;
+     LOG(log_warning, logtype_uams, "DHX2: Authenticated as \"%s\"", adminauthuser);
+ exit:
+     return PAM_error;
+ }
+ static int logincont2(void *obj_in, struct passwd **uam_pwd,
                        char *ibuf, size_t ibuflen,
                        char *rbuf _U_, size_t *rbuflen)
  {
-     int ret;
+     AFPObj *obj = obj_in;
+     int ret = AFPERR_MISC;
      int PAM_error;
      const char *hostname = NULL;
      gcry_mpi_t retServerNonce;
      gcry_cipher_hd_t ctx;
      gcry_error_t ctxerror;
+     char *utfpass = NULL;
  
      *rbuflen = 0;
  
  
      /* ---- Start authentication with PAM --- */
  
+     /* The password is in legacy Mac encoding, convert it to host encoding */
+     if (convert_string_allocate(CH_MAC, CH_UNIX, ibuf, -1, &utfpass) == (size_t)-1) {
+         LOG(log_error, logtype_uams, "DHX2: conversion error");
+         goto error_ctx;
+     }
+     PAM_password = utfpass;
+ #ifdef DEBUG
+     LOG(log_maxdebug, logtype_default, "DHX2: password: %s", PAM_password);
+ #endif
      /* Set these things up for the conv function */
-     PAM_password = ibuf;
  
      ret = AFPERR_NOTAUTH;
      PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, &pamh);
      if (PAM_error != PAM_SUCCESS) {
-         LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-             pam_strerror(pamh,PAM_error));
+         LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error));
          goto error_ctx;
      }
  
      /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
      pam_set_item(pamh, PAM_TTY, "afpd");
      pam_set_item(pamh, PAM_RHOST, hostname);
      PAM_error = pam_authenticate(pamh, 0);
      if (PAM_error != PAM_SUCCESS) {
          if (PAM_error == PAM_MAXTRIES)
              ret = AFPERR_PWDEXPR;
-         LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
-             pam_strerror(pamh, PAM_error));
-         goto error_ctx;
+         LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh, PAM_error));
+         if (!obj->options.adminauthuser)
+             goto error_ctx;
+         if (loginasroot(obj->options.adminauthuser, &hostname, PAM_error) != PAM_SUCCESS) {
+             goto error_ctx;
+         }
      }
  
      PAM_error = pam_acct_mgmt(pamh, 0);
          else if (PAM_error == PAM_AUTHTOKEN_REQD)
              ret = AFPERR_PWDCHNG;
  #endif
-         else
-             goto error_ctx;
+         goto error_ctx;
      }
  
  #ifndef PAM_CRED_ESTABLISH
      }
  
      memset(ibuf, 0, 256); /* zero out the password */
+     if (utfpass)
+         memset(utfpass, 0, strlen(utfpass));
      *uam_pwd = dhxpwd;
      LOG(log_info, logtype_uams, "DHX2: PAM Auth OK!");
-     if ( ret == AFPERR_PWDEXPR)
-         return ret;
      ret = AFP_OK;
  
  error_ctx:
      gcry_cipher_close(ctx);
  error_noctx:
+     if (utfpass) free(utfpass);
      free(K_MD5hash);
      K_MD5hash=NULL;
      gcry_mpi_release(serverNonce);
@@@ -669,11 -714,11 +714,11 @@@ static int pam_logincont(void *obj, str
                           char *ibuf, size_t ibuflen,
                           char *rbuf, size_t *rbuflen)
  {
 -    u_int16_t retID;
 +    uint16_t retID;
      int ret;
  
      /* check for session id */
 -    retID = ntohs(*(u_int16_t *)ibuf);
 +    retID = ntohs(*(uint16_t *)ibuf);
      if (retID == ID)
          ret = logincont1(obj, ibuf, ibuflen, rbuf, rbuflen);
      else if (retID == ID+1)
index c7ac24342aa80aaead5b50d8d80ae286cc5952d2,1392f0a75edfc2d513a3c65365795625cd0c0fb0..8d31b9f845b3502eb4935d38a0df5cf6635cfac2
  
  #ifdef UAM_DHX2
  
+ #include <atalk/standards.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
  #include <errno.h>
  #include <pwd.h>
 -
 -#ifdef HAVE_UNISTD_H
 +#include <arpa/inet.h>
  #include <unistd.h>
 -#endif
  
  #ifdef HAVE_CRYPT_H
  #include <crypt.h>
  #endif
  
 -#ifdef HAVE_SYS_TIME_H
  #include <sys/time.h>
 -#endif
 -
 -#ifdef HAVE_TIME_H
  #include <time.h>
 -#endif
  
  #ifdef SHADOWPW
  #include <shadow.h>
@@@ -51,7 -60,7 +53,7 @@@ static gcry_mpi_t p, Ra
  static gcry_mpi_t serverNonce;
  static char *K_MD5hash = NULL;
  static int K_hash_len;
 -static u_int16_t ID;
 +static uint16_t ID;
  
  /* The initialization vectors for CAST128 are fixed by Apple. */
  static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' };
@@@ -207,7 -216,7 +209,7 @@@ static int dhx2_setup(void *obj, char *
  
      /* Session ID first */
      ID = dhxhash(obj);
 -    *(u_int16_t *)rbuf = htons(ID);
 +    *(uint16_t *)rbuf = htons(ID);
      rbuf += 2;
      *rbuflen += 2;
  
      *rbuflen += 4;
  
      /* len = length of p = PRIMEBITS/8 */
 -    *(u_int16_t *)rbuf = htons((u_int16_t) PRIMEBITS/8);
 +    *(uint16_t *)rbuf = htons((uint16_t) PRIMEBITS/8);
      rbuf += 2;
      *rbuflen += 2;
  
@@@ -305,7 -314,7 +307,7 @@@ static int passwd_login_ext(void *obj, 
  {
      char *username;
      size_t len, ulen;
 -    u_int16_t  temp16;
 +    uint16_t  temp16;
  
      *rbuflen = 0;
  
@@@ -433,7 -442,7 +435,7 @@@ static int logincont1(void *obj _U_, st
      /* ---- Start building reply packet ---- */
  
      /* Session ID + 1 first */
 -    *(u_int16_t *)rbuf = htons(ID+1);
 +    *(uint16_t *)rbuf = htons(ID+1);
      rbuf += 2;
      *rbuflen += 2;
  
@@@ -580,11 -589,11 +582,11 @@@ static int passwd_logincont(void *obj, 
                              char *ibuf, size_t ibuflen,
                              char *rbuf, size_t *rbuflen)
  {
 -    u_int16_t retID;
 +    uint16_t retID;
      int ret;
  
      /* check for session id */
 -    retID = ntohs(*(u_int16_t *)ibuf);
 +    retID = ntohs(*(uint16_t *)ibuf);
      if (retID == ID)
          ret = logincont1(obj, uam_pwd, ibuf, ibuflen, rbuf, rbuflen);
      else if (retID == ID+1)
index 8b772b6c449ef465f950f6a82ef9b330090d65c3,465f28972e6b9eec0ceaf0468f41c9582b25bce6..d390f76b4da29d556fb07bdf559849e3610e9362
@@@ -1,4 -1,6 +1,4 @@@
  /*
 - * $Id: uams_dhx_passwd.c,v 1.29 2010-03-30 12:44:35 franklahm Exp $
 - *
   * Copyright (c) 1990,1993 Regents of The University of Michigan.
   * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
   * All Rights Reserved.  See COPYRIGHT.
  #include "config.h"
  #endif /* HAVE_CONFIG_H */
  
- #ifdef NETBSD
- #define _XOPEN_SOURCE 500 /* for crypt() */
- #endif
- #ifdef FREEBSD
- #define _XOPEN_SOURCE /* for crypt() */
- #endif
+ #include <atalk/standards.h>
  
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
 -#ifdef HAVE_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #ifdef HAVE_CRYPT_H
  #include <crypt.h>
  #endif /* ! HAVE_CRYPT_H */
 -#ifdef HAVE_SYS_TIME_H
  #include <sys/time.h>
 -#endif
 -#ifdef HAVE_TIME_H
  #include <time.h>
 -#endif
  #include <pwd.h>
 +#include <arpa/inet.h>
 +
  #ifdef SHADOWPW
  #include <shadow.h>
  #endif /* SHADOWPW */
 +
  #if defined(GNUTLS_DHX)
  #include <gnutls/openssl.h>
  #elif defined(OPENSSL_DHX)
@@@ -59,7 -59,7 +54,7 @@@
  /* the secret key */
  static CAST_KEY castkey;
  static struct passwd *dhxpwd;
 -static u_int8_t randbuf[16];
 +static uint8_t randbuf[16];
  
  #ifdef TRU64
  #include <sia.h>
@@@ -74,14 -74,14 +69,14 @@@ static int pwd_login(void *obj, char *u
                        char *rbuf, size_t *rbuflen)
  {
      unsigned char iv[] = "CJalbert";
 -    u_int8_t p[] = {0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4,
 +    uint8_t p[] = {0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4,
                    0x3F, 0x20, 0x24, 0x74, 0x4C, 0xEE, 0xE7, 0x5B };
 -    u_int8_t g = 0x07;
 +    uint8_t g = 0x07;
  #ifdef SHADOWPW
      struct spwd *sp;
  #endif /* SHADOWPW */
      BIGNUM *bn, *gbn, *pbn;
 -    u_int16_t sessid;
 +    uint16_t sessid;
      size_t i;
      DH *dh;
  
@@@ -250,7 -250,7 +245,7 @@@ static int passwd_login_ext(void *obj, 
  {
      char       *username;
      size_t     len, ulen;
 -    u_int16_t  temp16;
 +    uint16_t  temp16;
  
      *rbuflen = 0;
      
@@@ -280,7 -280,7 +275,7 @@@ static int passwd_logincont(void *obj, 
  #endif /* SHADOWPW */
      unsigned char iv[] = "LWallace";
      BIGNUM *bn1, *bn2, *bn3;
 -    u_int16_t sessid;
 +    uint16_t sessid;
      char *p;
      int err = AFPERR_NOTAUTH;
  
diff --combined etc/uams/uams_passwd.c
index 72d024d2b521dc70b257f2f1e71c3e20d4e1e02a,db9be446cf2723d3dbe0d62ad848948190464e4a..6db3ce62028f0e3567e3b1cd96876b1067667a8b
@@@ -1,4 -1,6 +1,4 @@@
  /*
 - * $Id: uams_passwd.c,v 1.31 2010-03-30 12:44:35 franklahm Exp $
 - *
   * Copyright (c) 1990,1993 Regents of The University of Michigan.
   * Copyright (c) 1999 Adrian Sun (asun@u.washington.edu) 
   * All Rights Reserved.  See COPYRIGHT.
  #include <config.h>
  #endif /* HAVE_CONFIG_H */
  
- #include <sys/types.h>
- /* crypt needs _XOPEN_SOURCE (500) at least on BSD, but that breaks Solaris compile */
- #ifdef NETBSD
- #define _XOPEN_SOURCE 500 /* for crypt() */
- #endif
- #ifdef FREEBSD
- #define _XOPEN_SOURCE /* for crypt() */
- #endif
+ #include <atalk/standards.h>
  
+ #include <sys/types.h>
  #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_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #ifdef HAVE_CRYPT_H
  #include <crypt.h>
  #endif /* ! HAVE_CRYPT_H */
  #include <pwd.h>
 -#ifdef HAVE_SYS_TIME_H
  #include <sys/time.h>
 -#endif
 -#ifdef HAVE_TIME_H
  #include <time.h>
 -#endif
  #ifdef SHADOWPW
  #include <shadow.h>
  #endif /* SHADOWPW */
 +#include <arpa/inet.h>
  
  #include <atalk/afp.h>
  #include <atalk/logger.h>
  #include <atalk/uam.h>
  #include <atalk/util.h>
 +#include <atalk/compat.h>
  
  #define PASSWDLEN 8
  
@@@ -185,7 -198,7 +179,7 @@@ static int passwd_login_ext(void *obj, 
  {
      char       *username;
      size_t     len, ulen;
 -    u_int16_t  temp16;
 +    uint16_t  temp16;
  
      *rbuflen = 0;
  
diff --combined etc/uams/uams_pgp.c
index 22aa8ae4d3edb60b64e63c20ad04c2aa0c5466d2,ec6d4095e17db4eea8caf3342e06d9a3cf0e0e4d..9b9c1d801dd57d53c543d8cdc1e11fb555f18f05
@@@ -12,8 -12,8 +12,8 @@@
  
  #ifdef UAM_PGP
  
- /* for crypt() */
- #define _XOPEN_SOURCE
+ #include <atalk/standards.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>
@@@ -53,7 -53,7 +53,7 @@@
  /* the secret key */
  static struct passwd *pgppwd;
  static CAST_KEY castkey;
 -static u_int8_t randbuf[16];
 +static uint8_t randbuf[16];
  
  /* pgp passwd */
  static int pgp_login(void *obj, struct passwd **uam_pwd,
@@@ -109,7 -109,7 +109,7 @@@ static int pgp_logincont(void *obj, str
  {
        unsigned char iv[] = "RJscorat";
      BIGNUM *bn1, *bn2, *bn3;
 -    u_int16_t sessid;
 +    uint16_t sessid;
      char *p;
  
      *rbuflen = 0;
index fb1d55dc16839a2025b6d8904cfa39e81dafb3ea,3c1feda3c8dd05e272f84ff377078460e48b8c8f..f4c2258df50027f6a51e35ba99af11a6b2e1e4fd
@@@ -1,53 -1,11 +1,54 @@@
  # Makefile.am for include/atalk/
  
  atalkincludedir = $(includedir)/atalk
 +
  atalkinclude_HEADERS = \
 -      adouble.h vfs.h aep.h afp.h asp.h atp.h \
 -      cnid.h compat.h ddp.h dsi.h ldapconfig.h list.h logger.h \
 -      nbp.h netddp.h pap.h paths.h queue.h rtmp.h server_child.h \
 -      server_ipc.h tdb.h uam.h unicode.h util.h uuid.h volinfo.h \
 -      zip.h ea.h acl.h unix.h directory.h hash.h volume.h
 +      adouble.h \
 +      afp.h \
 +      vfs.h \
 +      cnid.h \
 +      locking.h \
 +      logger.h \
 +      paths.h \
 +      unicode.h \
 +      util.h \
 +      volinfo.h \
 +      ea.h \
 +      acl.h \
 +      unix.h \
 +      volume.h
 +
 +noinst_HEADERS = \
 +      directory.h \
 +      hash.h \
 +      zip.h \
 +      uuid.h \
 +      queue.h \
 +      server_child.h \
 +      server_ipc.h \
 +      tdb.h \
 +      uam.h \
 +      cnid_dbd_private.h \
 +      cnid_private.h \
 +      bstradd.h \
 +      bstrlib.h \
 +      errchk.h \
 +      ftw.h \
 +      talloc.h \
 +      tevent.h \
 +      tsocket.h \
 +      boolean.h \
 +      compat.h \
 +      dsi.h \
 +      ldapconfig.h \
 +      list.h \
 +      globals.h \
-       fce_api.h
++      fce_api.h \
++      standards.h
  
 -noinst_HEADERS = cnid_dbd_private.h cnid_private.h bstradd.h bstrlib.h errchk.h ftw.h globals.h fce_api.h standards.h
 +BUILT_SOURCES = lockrpc.gen.h
 +EXTRADIST = lockrpc.gen.h
 +lockrpc.gen.h: $(top_srcdir)/libevent/event_rpcgen.py $(top_srcdir)/libatalk/rpc/lockrpc.rpc
 +      cd $(top_srcdir)/libatalk/rpc/ \
 +              && $(top_srcdir)/libevent/event_rpcgen.py lockrpc.rpc \
 +              && mv lockrpc.gen.h $(top_srcdir)/include/atalk
diff --combined include/atalk/adouble.h
index 963417bd32b16ff6e4569c3c4b034dc693e21ba0,78a35b02909ecd932bbf86d00cb5d908402e9426..6913ddcdcfc22ce788b8aeacb8ae0d47d0a043d4
@@@ -1,4 -1,5 +1,4 @@@
  /*
 - * $Id: adouble.h,v 1.55 2010-03-30 12:55:26 franklahm Exp $
   * Copyright (c) 1990,1991 Regents of The University of Michigan.
   * All Rights Reserved.
   *
  #include <config.h>
  #endif
  
+ #include <atalk/standards.h>
 +#include <inttypes.h>
  #include <sys/types.h>
  #include <sys/stat.h>
 -
 -#ifdef HAVE_UNISTD_H
 -#undef __USE_MISC
 -#define __USE_MISC
  #include <unistd.h>
 -#endif
 -
 -#include <sys/cdefs.h>
 -
 -#ifdef HAVE_FCNTL_H
  #include <fcntl.h>
 -#endif
  
  #include <sys/mman.h>
  
 -#ifdef HAVE_SYS_TIME_H
  #include <sys/time.h>
 -#endif
 -#include <netatalk/endian.h>
  
 -/* version info */
 -#define AD_VERSION1     0x00010000
 -#define SFM_VERSION     AD_VERSION1
 +#include <atalk/bstrlib.h>
 +#include <atalk/locking.h>
  
 +/* version info */
  #define AD_VERSION2     0x00020000
 -#define AD_VERSION2_OSX 0x00020001
 -/*
 -  #define AD_VERSION1_ADS 0x00010002
 -*/
 -#define AD_VERSION1_SFM 0x00010003
 +#define AD_VERSION_EA   0x00020002
 +
 +/* default */
  #define AD_VERSION      AD_VERSION2
  
  /*
@@@ -58,7 -75,7 +60,7 @@@
   */
  #define ADEID_DFORK         1
  #define ADEID_RFORK         2
 -#define ADEID_NAME          3 /* Note: starting with Netatalk 2.1 we do NOT alway set the name */
 +#define ADEID_NAME          3
  #define ADEID_COMMENT       4
  #define ADEID_ICONBW        5
  #define ADEID_ICONCOL       6
  #define ADEID_AFPFILEI      14 /* where the rest of the FILEI info goes */
  #define ADEID_DID           15
  
 -#if AD_VERSION == AD_VERSION1
 -#define ADEID_MAX           16
 -#else
  /* netatalk private note fileid reused DID */
  #define ADEID_PRIVDEV       16
  #define ADEID_PRIVINO       17
  #define ADEID_PRIVSYN       18 /* in synch with database */
  #define ADEID_PRIVID        19
 -#define ADEID_SFMRESERVE1   20
 -#define ADEID_SFMRESERVE2   21
 +#define ADEID_MAX           (ADEID_PRIVID + 1)
  
 +/* These are the real ids for these entries, as stored in the adouble file */
  #define AD_DEV              0x80444556
  #define AD_INO              0x80494E4F
  #define AD_SYN              0x8053594E
  #define AD_ID               0x8053567E
 -#define ADEID_MAX           22
 -#endif
  
  /* magic */
  #define AD_APPLESINGLE_MAGIC 0x00051600
  #define AD_APPLEDOUBLE_MAGIC 0x00051607
  #define AD_MAGIC             AD_APPLEDOUBLE_MAGIC
 -#define SFM_MAGIC            0x00504641
  
  /* sizes of relevant entry bits */
  #define ADEDLEN_MAGIC       4
  #define ADEDLEN_VERSION     4
  #define ADEDLEN_FILLER      16
  #define ADEDLEN_NENTRIES    2
 -
 -/* 26 */
 -#define AD_HEADER_LEN       (ADEDLEN_MAGIC + ADEDLEN_VERSION + \
 -                             ADEDLEN_FILLER + ADEDLEN_NENTRIES)
 +#define AD_HEADER_LEN       (ADEDLEN_MAGIC + ADEDLEN_VERSION + ADEDLEN_FILLER + ADEDLEN_NENTRIES)
  #define AD_ENTRY_LEN        12  /* size of a single entry header */
  
 -/* v1 field widths */
 -#define ADEDLEN_NAME        255
 -#define ADEDLEN_COMMENT     200
 -#define ADEDLEN_FILEI       16
 -#define ADEDLEN_FINDERI     32
 -
 -/* v2 field widths */
 +/* field widths */
 +#define ADEDLEN_NAME            255
 +#define ADEDLEN_COMMENT         200
 +#define ADEDLEN_FILEI           16
 +#define ADEDLEN_FINDERI         32
  #define ADEDLEN_FILEDATESI      16
  #define ADEDLEN_SHORTNAME       12 /* length up to 8.3 */
  #define ADEDLEN_AFPFILEI        4
  #define ADEDLEN_PRIVSYN         8
  #define ADEDLEN_PRIVID          4
  
 -#define ADEID_NUM_V1            5
  #define ADEID_NUM_V2            13
 +#define ADEID_NUM_EA            5
  
 -// #define ADEID_NUM_SFM        5
 -/* sizeof SFM meta data */
 -#define AD_SFM_LEN 60
 -
 -/* 589 */
 -#define AD_DATASZ1      (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT + ADEDLEN_FILEI + ADEDLEN_FINDERI + \
 -                         (ADEID_NUM_V1 * AD_ENTRY_LEN))
 -
 -#if AD_DATASZ1 != 589
 -#error bad size for AD_DATASZ1
 -#endif
 -
 -#define AD_NEWSZ2       (ADEDLEN_DID + ADEDLEN_AFPFILEI + ADEDLEN_SHORTNAME + ADEDLEN_PRODOSFILEI \
 -                         + ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + ADEDLEN_PRIVSYN + ADEDLEN_PRIVID)
 -
 -/* 725 */
 -#define AD_DATASZ2      (AD_DATASZ1 + AD_NEWSZ2 + ((ADEID_NUM_V2 - ADEID_NUM_V1) * AD_ENTRY_LEN))
 -
 +#define AD_DATASZ2 (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT + ADEDLEN_FILEI + \
 +                    ADEDLEN_FINDERI + ADEDLEN_DID + ADEDLEN_AFPFILEI + ADEDLEN_SHORTNAME + \
 +                    ADEDLEN_PRODOSFILEI + ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + \
 +                    ADEDLEN_PRIVSYN + ADEDLEN_PRIVID + (ADEID_NUM_V2 * AD_ENTRY_LEN))
  #if AD_DATASZ2 != 741
  #error bad size for AD_DATASZ2
  #endif
  
 -#define AD_DATASZ_MAX   1024
 -#if AD_VERSION == AD_VERSION1
 -#define AD_DATASZ   AD_DATASZ1 /* hold enough for the entries */
 -#elif AD_VERSION == AD_VERSION2
 -#define AD_DATASZ   AD_DATASZ2
 +#define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + ADEDLEN_FINDERI + \
 +                      ADEDLEN_COMMENT + ADEDLEN_FILEDATESI + ADEDLEN_AFPFILEI + ADEDLEN_PRIVID)
 +
 +#if AD_DATASZ_EA != 342
 +#error bad size for AD_DATASZ_EA
  #endif
  
 -/*
 - * some legacy defines from netatalk-990130
 - * (to keep from breaking certain packages)
 - *
 - */
 +#define AD_DATASZ_MAX   1024
  
 -#define ADEDOFF_RFORK   589
 -#define ADEDOFF_NAME    86
 -#define ADEDOFF_COMMENT 341
 -#define ADEDOFF_FINDERI 557
 -#ifndef ADEDOFF_FILEI
 -#define ADEDOFF_FILEI   541
 +#if AD_VERSION == AD_VERSION2
 +#define AD_DATASZ   AD_DATASZ2
 +#elif AD_VERSION == AD_VERSION_EA
 +#define AD_DATASZ   AD_DATASZ_EA
  #endif
  
 -typedef u_int32_t cnid_t;
 +#define RFORK_EA_ALLOCSIZE (128*1024) /* 128k */
  
 -/*
 - * The header of the AppleDouble Header File looks like this:
 - *
 - *  NAME            SIZE
 - *  ====            ====
 - *  Magic           4
 - *  Version         4
 - *  Home File System    16  (this becomes filler in ad v2)
 - *  Number of Entries   2
 - *  Entry Descriptors for each entry:
 - *      Entry ID    4
 - *      Offset      4
 - *      Length      4
 - */
 +typedef uint32_t cnid_t;
  
  struct ad_entry {
 -    off_t   ade_off;
 +    off_t     ade_off;
      ssize_t   ade_len;
  };
  
@@@ -158,67 -219,75 +160,67 @@@ typedef struct adf_lock_t 
  
  struct ad_fd {
      int          adf_fd;        /* -1: invalid, -2: symlink */
 -
  #ifndef HAVE_PREAD
      off_t        adf_off;
  #endif
 -
      char         *adf_syml;
      int          adf_flags;
      int          adf_excl;
 +#if 0
      adf_lock_t   *adf_lock;
      int          adf_refcount, adf_lockcount, adf_lockmax;
 +#endif
  };
  
  /* some header protection */
  #define AD_INITED  0xad494e54  /* ad"INT" */
 -struct adouble_fops;
 -
 -struct adouble {
 -    u_int32_t           ad_magic;
 -    u_int32_t           ad_version;
 -    char                ad_filler[ 16 ];
 -    struct ad_entry     ad_eid[ ADEID_MAX ];
 -    struct ad_fd        ad_data_fork, ad_resource_fork, ad_metadata_fork;
 -    struct ad_fd        *ad_md; /* either ad_resource or ad_metadata */
 -
 -    int                 ad_flags;    /* This really stores version info too (AD_VERSION*) */
 -    int                 ad_adflags;  /* ad_open flags adflags like ADFLAGS_DIR */
 -    unsigned int        ad_inited;
 -    int                 ad_options;
 -    int                 ad_fileordir;
 -    int                 ad_refcount; /* used in afpd/ofork.c */
 -    off_t               ad_rlen;     /* ressource fork len with AFP 3.0
 -                                        the header parameter size is too small.
 -                                     */
 -    char                *ad_m_name;   /* mac name for open fork */
 -    int                 ad_m_namelen;
 -    struct adouble_fops *ad_ops;
 -    u_int16_t       ad_open_forks;      /* open forks (by others) */
 +#define AD_CLOSED  0xadc10ced
  
 -#ifdef USE_MMAPPED_HEADERS
 -    char                *ad_data;
 -#else
 -    char        ad_data[AD_DATASZ_MAX];
 -#endif
 -};
 +struct adouble;
  
  struct adouble_fops {
 -    char *(*ad_path)(const char *, int);
 -    int  (*ad_mkrf)(char *);
 +    const char *(*ad_path)(const char *, int);
 +    int  (*ad_mkrf)(const char *);
      int  (*ad_rebuild_header)(struct adouble *);
 -    int  (*ad_check_header)(struct adouble *, struct stat *);
      int  (*ad_header_read)(struct adouble *, struct stat *);
 -    int  (*ad_header_upgrade)(struct adouble *, char *);
 +    int  (*ad_header_upgrade)(struct adouble *, const char *);
 +};
 +
 +struct adouble {
 +    uint32_t            ad_magic;         /* Official adouble magic                   */
 +    uint32_t            ad_version;       /* Official adouble version number          */
 +    char                ad_filler[16];
 +    struct ad_entry     ad_eid[ADEID_MAX];
 +    struct ad_fd        ad_data_fork;     /* the data fork                            */
 +    struct ad_fd        ad_resource_fork; /* adouble:v2 -> the adouble file           *
 +                                           * adouble:ea -> the rfork EA               */
 +    struct ad_fd        ad_metadata_fork; /* adouble:v2 -> unused                     *
 +                                           * adouble:ea -> the metadata EA            */
 +    struct ad_fd        *ad_md;           /* either ad_resource or ad_metadata        */
 +    int                 ad_flags;         /* Our adouble version info (AD_VERSION*)   */
 +    int                 ad_adflags;       /* ad_open flags adflags like ADFLAGS_DIR   */
 +    uint32_t            ad_inited;
 +    int                 ad_options;
 +    int                 ad_refcount;       /* multiple forks may open one adouble     */
 +    void                *ad_resforkbuf;    /* buffer for AD_VERSION_EA ressource fork */
 +    size_t              ad_resforkbufsize; /* size of ad_resforkbuf                   */
 +    off_t               ad_rlen;           /* ressource fork len with AFP 3.0         *
 +                                            * the header parameter size is too small. */
 +    char                *ad_m_name;        /* mac name for open fork                  */
 +    int                 ad_m_namelen;
 +    bstring             ad_fullpath;       /* fullpath of file, adouble:ea need this  */
 +    struct adouble_fops *ad_ops;
 +    uint16_t            ad_open_forks;     /* open forks (by others)                  */
 +    char                ad_data[AD_DATASZ_MAX];
  };
  
  #define ADFLAGS_DF        (1<<0)
 -#define ADFLAGS_HF        (1<<1)
 -#define ADFLAGS_DIR       (1<<2)
 -/*
 -#define ADFLAGS_NOADOUBLE (1<<3)
 -*/
 -#define ADFLAGS_V1COMPAT  (1<<4)
 -#define ADFLAGS_NOHF      (1<<5)  /* not an error if no ressource fork */
 -#define ADFLAGS_RDONLY    (1<<6)  /* don't try readwrite */
 -#define ADFLAGS_OPENFORKS (1<<7)  /* check for open fork in ad_metadata function */
 -#define ADFLAGS_RF        (1<<8)
 -#define ADFLAGS_MD        ADFLAGS_HF /* (1<<9) */
 -#define ADFLAGS_CREATE    (1<<9)
 -
 -/* adouble v2 cnid cache */
 +#define ADFLAGS_RF        (1<<1)
 +#define ADFLAGS_HF        (1<<2)
 +#define ADFLAGS_DIR       (1<<3)
 +#define ADFLAGS_NOHF      (1<<4)  /* not an error if no ressource fork */
 +#define ADFLAGS_CHECK_OF  (1<<6)  /* check for open forks from us and other afpd's */
 +
  #define ADVOL_NODEV      (1 << 0)
  #define ADVOL_CACHE      (1 << 1)
  #define ADVOL_UNIXPRIV   (1 << 2) /* adouble unix priv */
  #define ad_getentryoff(ad,eid)     ((ad)->ad_eid[(eid)].ade_off)
  #define ad_entry(ad,eid)           ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off)
  
 -#define ad_get_HF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
 +#define ad_get_RF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
  #define ad_get_MD_flags(ad) ((ad)->ad_md->adf_flags)
  
 +/* Refcounting open forks using one struct adouble */
 +#define ad_ref(ad)   (ad)->ad_refcount++
 +#define ad_unref(ad) --((ad)->ad_refcount)
 +
  /* ad_flush.c */
  extern int ad_rebuild_adouble_header (struct adouble *);
  extern int ad_rebuild_sfm_header (struct adouble *);
@@@ -360,38 -425,44 +362,38 @@@ extern int ad_flush (struct adouble *)
  extern int ad_close (struct adouble *, int);
  
  /* ad_lock.c */
 -extern int ad_fcntl_lock    (struct adouble *, const u_int32_t /*eid*/,
 -                                 const int /*type*/, const off_t /*offset*/,
 -                                 const off_t /*len*/, const int /*user*/);
 -extern void ad_fcntl_unlock (struct adouble *, const int /*user*/);
 -extern int ad_fcntl_tmplock (struct adouble *, const u_int32_t /*eid*/,
 -                                 const int /*type*/, const off_t /*offset*/,
 -                                 const off_t /*len*/, const int /*user*/);
 -extern int ad_testlock      (struct adouble * /*adp*/, int /*eid*/, off_t /*off*/);
 -
 -extern u_int16_t ad_openforks (struct adouble * /*adp*/, u_int16_t);
 -extern int ad_excl_lock     (struct adouble * /*adp*/, const u_int32_t /*eid*/);
 -
 -#define ad_lock ad_fcntl_lock
 -#define ad_tmplock ad_fcntl_tmplock
 -#define ad_unlock ad_fcntl_unlock
 +extern int ad_testlock      (struct adouble *adp, int eid, off_t off);
 +extern uint16_t ad_openforks(struct adouble *adp, uint16_t);
 +extern int ad_excl_lock     (struct adouble *adp, uint32_t eid);
 +
 +extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
 +extern void ad_unlock(struct adouble *, int user);
 +extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
  
  /* ad_open.c */
 +extern const char *oflags2logstr(int oflags);
 +extern const char *adflags2logstr(int adflags);
  extern int ad_setfuid     (const uid_t );
  extern uid_t ad_getfuid   (void );
  extern char *ad_dir       (const char *);
 -extern char *ad_path      (const char *, int);
 -extern char *ad_path_osx  (const char *, int);
 -extern char *ad_path_ads  (const char *, int);
 -extern char *ad_path_sfm  (const char *, int);
 +extern const char *ad_path      (const char *, int);
 +extern const char *ad_path_ea   (const char *, int);
  extern int ad_mode        (const char *, int);
  extern int ad_mkdir       (const char *, int);
  extern void ad_init       (struct adouble *, int, int );
 -extern int ad_open        (const char *, int, int, int, struct adouble *);
 -extern int ad_openat      (int dirfd, const char *, int, int, int, struct adouble *);
 +extern int ad_open        (struct adouble *ad, const char *path, int adflags, ...);
 +extern int ad_openat      (struct adouble *, int dirfd, const char *path, int adflags, ...);
  extern int ad_refresh     (struct adouble *);
  extern int ad_stat        (const char *, struct stat *);
  extern int ad_metadata    (const char *, int, struct adouble *);
  extern int ad_metadataat  (int, const char *, int, struct adouble *);
  
 +#if 0
  #define ad_open_metadata(name, flags, mode, adp)\
 -   ad_open(name, ADFLAGS_MD|(flags), O_RDWR |(mode), 0666, (adp))
 +   ad_open(name, ADFLAGS_HF | (flags), O_RDWR |(mode), 0666, (adp))
 +#endif
  
 -#define ad_close_metadata(adp) ad_close( (adp), ADFLAGS_MD)
 +#define ad_close_metadata(adp) ad_close( (adp), ADFLAGS_HF)
  
  /* build a resource fork mode from the data fork mode:
   * remove X mode and extend header to RW if R or W (W if R for locking),
@@@ -418,43 -489,73 +420,43 @@@ static inline mode_t ad_hf_mode (mode_
      return mode;
  }
  
 -/* ad_ea.c */
 -ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size);
 -ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size);
 -ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size);
 -ssize_t sys_listxattr (const char *path, char *list, size_t size);
 -ssize_t sys_llistxattr (const char *path, char *list, size_t size);
 -ssize_t sys_flistxattr (int filedes, char *list, size_t size);
 -int sys_removexattr (const char *path, const char *name);
 -int sys_lremovexattr (const char *path, const char *name);
 -int sys_fremovexattr (int filedes, const char *name);
 -int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags);
 -int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags);
 -int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags);
 -int sys_copyxattr (const char *src, const char *dst);
 -
  /* ad_read.c/ad_write.c */
  extern int     sys_ftruncate(int fd, off_t length);
 -
 -extern ssize_t ad_read (struct adouble *, const u_int32_t,
 -                            const off_t, char *, const size_t);
 -extern ssize_t ad_pread (struct ad_fd *, void *, size_t, off_t);
 -extern ssize_t ad_write (struct adouble *, const u_int32_t, off_t,
 -                             const int, const char *, const size_t);
 -extern ssize_t adf_pread  (struct ad_fd *, void *, size_t, off_t);
 -extern ssize_t adf_pwrite (struct ad_fd *, const void *, size_t, off_t);
 -extern int     ad_dtruncate (struct adouble *, const off_t);
 -extern int     ad_rtruncate (struct adouble *, const off_t);
 +extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
 +extern ssize_t ad_pread(struct ad_fd *, void *, size_t, off_t);
 +extern ssize_t ad_write(struct adouble *, uint32_t, off_t, int, const char *, size_t);
 +extern ssize_t adf_pread(struct ad_fd *, void *, size_t, off_t);
 +extern ssize_t adf_pwrite(struct ad_fd *, const void *, size_t, off_t);
 +extern int     ad_dtruncate(struct adouble *, off_t);
 +extern int     ad_rtruncate(struct adouble *, off_t);
  
  /* ad_size.c */
 -extern off_t ad_size (const struct adouble *, const u_int32_t );
 +extern off_t ad_size (const struct adouble *, uint32_t );
  
  /* ad_mmap.c */
 -extern void *ad_mmapread (struct adouble *, const u_int32_t,
 -                              const off_t, const size_t);
 -extern void *ad_mmapwrite (struct adouble *, const u_int32_t,
 -                               const off_t, const int, const size_t);
 +extern void *ad_mmapread(struct adouble *, uint32_t, off_t, size_t);
 +extern void *ad_mmapwrite(struct adouble *, uint32_t, off_t, int, size_t);
  #define ad_munmap(buf, len)  (munmap((buf), (len)))
  
  /* ad_date.c */
 -extern int ad_setdate (struct adouble *, unsigned int, u_int32_t);
 -extern int ad_getdate (const struct adouble *, unsigned int, u_int32_t *);
 +extern int ad_setdate(struct adouble *, unsigned int, uint32_t);
 +extern int ad_getdate(const struct adouble *, unsigned int, uint32_t *);
  
  /* ad_attr.c */
 -extern int       ad_setattr (const struct adouble *, const u_int16_t);
 -extern int       ad_getattr (const struct adouble *, u_int16_t *);
 -
 -/* Note: starting with Netatalk 2.1 we do NOT alway set the name */
 -extern int       ad_setname (struct adouble *, const char *);
 -
 -#if AD_VERSION == AD_VERSION2
 -extern int       ad_setid (struct adouble *, const dev_t dev,const ino_t ino, const u_int32_t, const u_int32_t, const void *);
 -extern u_int32_t ad_getid (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *);
 -extern u_int32_t ad_forcegetid (struct adouble *adp);
 -#else
 -#define ad_setid(a, b, c)
 -#endif
 +extern int       ad_setattr(const struct adouble *, uint16_t);
 +extern int       ad_getattr(const struct adouble *, uint16_t *);
 +extern int       ad_setname(struct adouble *, const char *);
 +extern int       ad_setid(struct adouble *, dev_t dev, ino_t ino, uint32_t, uint32_t, const void *);
 +extern uint32_t  ad_getid(struct adouble *, dev_t, ino_t, cnid_t, const void *);
 +extern uint32_t  ad_forcegetid(struct adouble *adp);
  
  #ifdef WITH_SENDFILE
 -extern int ad_readfile_init(const struct adouble *ad, 
 -                                     const int eid, off_t *off,
 -                                     const int end);
 +extern int ad_readfile_init(const struct adouble *ad, int eid, off_t *off, int end);
  #endif
  
  #if 0
  #ifdef HAVE_SENDFILE_WRITE
 -extern ssize_t ad_writefile (struct adouble *, const int,
 -                                 const int, off_t, const int, const size_t);
 +extern ssize_t ad_writefile(struct adouble *, int, int, off_t, int, size_t);
  #endif /* HAVE_SENDFILE_WRITE */
  #endif /* 0 */
  
diff --combined include/atalk/dsi.h
index 75e91b4f09e03c42d5dd0ee3ac16dd81e54d9ce4,eded2b8f5ad7d5e97980970694f1bf51381d6de8..de7464a593086d4670aff1965c6905ca3d2e5690
@@@ -6,16 -6,18 +6,16 @@@
  #ifndef _ATALK_DSI_H 
  #define _ATALK_DSI_H
  
 -#include <sys/cdefs.h>
  #include <sys/types.h>
  #include <sys/time.h>
 -#include <signal.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 <atalk/globals.h>
 -#include <netatalk/endian.h>
 -
  
  /* What a DSI packet looks like:
   0                               32
@@@ -42,12 -44,12 +42,12 @@@ typedef enum 
  
  #define DSI_BLOCKSIZ 16
  struct dsi_block {
 -  u_int8_t dsi_flags;       /* packet type: request or reply */
 -  u_int8_t dsi_command;     /* command */
 -  u_int16_t dsi_requestID;  /* request ID */
 -  u_int32_t dsi_code;       /* error code or data offset */
 -  u_int32_t dsi_len;        /* total data length */
 -  u_int32_t dsi_reserved;   /* reserved field */
 +  uint8_t dsi_flags;       /* packet type: request or reply */
 +  uint8_t dsi_command;     /* command */
 +  uint16_t dsi_requestID;  /* request ID */
 +  uint32_t dsi_code;       /* error code or data offset */
 +  uint32_t dsi_len;        /* total data length */
 +  uint32_t dsi_reserved;   /* reserved field */
  };
  
  #define DSI_CMDSIZ        8192 
@@@ -67,10 -69,10 +67,10 @@@ typedef struct DSI 
    int      msg_request;   /* pending message to the client */
    int      down_request;  /* pending SIGUSR1 down in 5 mn */
  
 -  u_int32_t attn_quantum, datasize, server_quantum;
 -  u_int16_t serverID, clientID;
 +  uint32_t attn_quantum, datasize, server_quantum;
 +  uint16_t serverID, clientID;
    char      *status;
 -  u_int8_t  commands[DSI_CMDSIZ], data[DSI_DATASIZ];
 +  uint8_t  commands[DSI_CMDSIZ], data[DSI_DATASIZ];
    size_t statuslen;
    size_t datalen, cmdlen;
    off_t  read_count, write_count;
@@@ -164,7 -166,7 +164,7 @@@ extern DSI *dsi_init (const dsi_proto /
                          const char * /*program*/, 
                          const char * /*host*/, const char * /*address*/,
                          const char * /*port*/, const int /*proxy*/,
 -                        const u_int32_t /* server quantum */);
 +                        const uint32_t /* server quantum */);
  extern void dsi_setstatus (DSI *, char *, const size_t);
  
  /* in dsi_getsess.c */
@@@ -185,7 -187,7 +185,7 @@@ extern void dsi_close (DSI *)
  extern ssize_t dsi_stream_write (DSI *, void *, const size_t, const int mode);
  extern size_t dsi_stream_read (DSI *, void *, const size_t);
  extern int dsi_stream_send (DSI *, void *, size_t);
- extern int dsi_stream_receive (DSI *, void *, const size_t, size_t *);
+ extern int dsi_stream_receive (DSI *);
  extern int dsi_disconnect(DSI *dsi);
  
  #ifdef WITH_SENDFILE
@@@ -210,6 -212,5 +210,5 @@@ extern void dsi_readdone (DSI *)
      (x)->header.dsi_len = htonl((x)->cmdlen); \
      dsi_stream_send((x), (x)->commands, (x)->cmdlen); \
  } while (0)
- #define dsi_receive(x)    (dsi_stream_receive((x), (x)->commands, \
-                                             DSI_CMDSIZ, &(x)->cmdlen))
  #endif /* atalk/dsi.h */
diff --combined include/atalk/globals.h
index aa20d25e91bf6da857e40d3d104769854d874156,68e68a32f3f403f6dea131dde173883a1dae9d90..b65eeba1e069cd2743c2969ceec5bd5876a8e453
@@@ -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>
  #define OPTION_NOZEROCONF    (1 << 9)
  #define OPTION_KEEPSESSIONS  (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
  
 -#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 {
@@@ -60,9 -69,12 +60,9 @@@ struct afp_options 
      int fce_fmodwait;           /* number of seconds FCE file mod events are put on hold */
      unsigned int tcp_sndbuf, tcp_rcvbuf;
      unsigned char passwdbits, passwdminlen, loginmaxfail;
 -    u_int32_t server_quantum;
 +    uint32_t server_quantum;
      int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */
      char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
 -#ifndef NO_DDP
 -    struct at_addr ddpaddr;
 -#endif
      char *uampath, *fqdn;
      char *pidfile;
      char *sigconffile;
      char *logconfig;
  
      char *mimicmodel;
+     char *adminauthuser;
  };
  
  #define AFPOBJ_TMPSIZ (MAXPATHLEN)
@@@ -110,6 -123,10 +111,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 */
@@@ -146,6 -163,9 +147,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 include/atalk/paths.h
index 297a2ca12242b353eac744bd498fb57104b195ff,98eb44b06864523836bfbef244da7687b2c8686e..ff97357b372f10de5bf5e9600ac12e8d51e4d08a
@@@ -16,7 -16,7 +16,7 @@@
  
  /* lock file path. this should be re-organized a bit. */
  #if ! defined (_PATH_LOCKDIR)
- #  if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #  if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
  #    define _PATH_LOCKDIR     "/var/run/"
  #  elif defined (BSD4_4)
  #    ifdef MACOSX_SERVER
@@@ -51,7 -51,7 +51,7 @@@
   */
  #define _PATH_ATALKDEBUG      "/tmp/atalkd.debug"
  #define _PATH_ATALKDTMP               "atalkd.tmp"
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
  #  define _PATH_ATALKDLOCK    ATALKPATHCAT(_PATH_LOCKDIR,"atalkd.pid")
  #else
  #  define _PATH_ATALKDLOCK    ATALKPATHCAT(_PATH_LOCKDIR,"atalkd")
@@@ -61,7 -61,7 +61,7 @@@
   * psorder paths
   */
  #define _PATH_TMPPAGEORDER    "/tmp/psorderXXXXXX"
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
  #  define _PATH_PAPDLOCK      ATALKPATHCAT(_PATH_LOCKDIR,"papd.pid")
  #else
  #  define _PATH_PAPDLOCK      ATALKPATHCAT(_PATH_LOCKDIR,"papd")
@@@ -72,7 -72,7 +72,7 @@@
   */
  #define _PATH_AFPTKT          "/tmp/AFPtktXXXXXX"
  #define _PATH_AFP_IPC       ATALKPATHCAT(_PATH_LOCKDIR,"afpd_ipc")
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
  #  define _PATH_AFPDLOCK      ATALKPATHCAT(_PATH_LOCKDIR,"afpd.pid")
  #else
  #  define _PATH_AFPDLOCK      ATALKPATHCAT(_PATH_LOCKDIR,"afpd")
  /*
   * cnid_metad paths
   */
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
  #  define _PATH_CNID_METAD_LOCK       ATALKPATHCAT(_PATH_LOCKDIR,"cnid_metad.pid")
  #else
  #  define _PATH_CNID_METAD_LOCK       ATALKPATHCAT(_PATH_LOCKDIR,"cnid_metad")
  #endif
  
 +/*
 + * netalockd paths
 + */
 +#if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
 +#  define _PATH_NETALOCKD_LOCK        ATALKPATHCAT(_PATH_LOCKDIR,"netalockd.pid")
 +#else
 +#  define _PATH_NETALOCKD_LOCK        ATALKPATHCAT(_PATH_LOCKDIR,"netalockd")
 +#endif
 +
  #endif /* atalk/paths.h */
diff --combined include/atalk/util.h
index 1664c8c992fccd11c45a139e267e3308827a39e7,3a6dd24498bb85e7e66c84800f4edb633ca26aeb..1febc062c0128fee626f5d64845b413effd0e2ab
  #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>
  #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))
+ #ifndef MAX
+ #define MAX(a,b) ((a) > (b) ? a : b)
+ #endif
+ #ifndef MIN
+ #define MIN(a,b) ((a) < (b) ? a : b)
+ #endif
  
  #if BYTE_ORDER == BIG_ENDIAN
  #define hton64(x)       (x)
@@@ -75,6 -74,9 +81,6 @@@ extern void freeifacelist(char **)
  
  #define diatolower(x)     _dialowermap[(unsigned char) (x)]
  #define diatoupper(x)     _diacasemap[(unsigned char) (x)]
 -#ifndef NO_DDP
 -extern int atalk_aton     (char *, struct at_addr *);
 -#endif
  extern void bprint        (char *, int);
  extern int strdiacasecmp  (const char *, const char *);
  extern int strndiacasecmp (const char *, const char *, size_t);
@@@ -85,6 -87,19 +91,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 *);
@@@ -169,8 -184,8 +175,9 @@@ extern int recv_fd(int fd, int nonblock
   * unix.c
   *****************************************************************/
  
 +extern const char *abspath(const char *name);
  extern const char *getcwdpath(void);
+ extern const char *fullpathname(const char *);
  extern char *stripped_slashes_basename(char *p);
  extern int lchdir(const char *dir);
  extern void randombytes(void *buf, int n);
diff --combined include/atalk/volume.h
index 615ecd631428a6c535f1c0e858291fc46841e6df,af2b411c625ca6b07f8203798d5ccbcd12d36c10..82de0420c95260b87757a79566daa84ee7e7437a
@@@ -6,7 -6,10 +6,9 @@@
  #ifndef ATALK_VOLUME_H
  #define ATALK_VOLUME_H 1
  
+ #include <stdint.h>
+ #include <sys/cdefs.h>
  #include <sys/types.h>
 -// #include <netatalk/endian.h>
  
  #include <atalk/unicode.h>
  #include <atalk/cnid.h>
@@@ -20,7 -23,7 +22,7 @@@ typedef uint64_t VolSpace
  
  struct vol {
      struct vol      *v_next;
 -    u_int16_t       v_vid;
 +    uint16_t        v_vid;
      int             v_flags;
      char            *v_path;
      struct dir      *v_root;
  
      charset_t       v_volcharset;
      charset_t       v_maccharset;
 -    u_int16_t       v_mtou_flags;    /* flags for convert_charset in mtoupath */
 -    u_int16_t       v_utom_flags;
 +    uint16_t        v_mtou_flags;    /* flags for convert_charset in mtoupath */
 +    uint16_t        v_utom_flags;
      long            v_kTextEncoding; /* mac charset encoding in network order
                                        * FIXME: should be a u_int32_t ? */
      size_t          max_filename;
      char            *v_veto;
      int             v_adouble;    /* adouble format: v1, v2, sfm ... */
      int             v_ad_options; /* adouble option NODEV, NOCACHE, etc.. */
 -    char            *(*ad_path)(const char *, int);
 +    const char      *(*ad_path)(const char *, int);
      struct _cnid_db *v_cdb;
      char            v_stamp[ADEDLEN_PRIVSYN];
      VolSpace        v_limitsize; /* Size limit, if any, in MiB */
@@@ -61,8 -64,9 +63,9 @@@
      char            *v_gvs;
      void            *v_nfsclient;
      int             v_nfs;
-     uintmax_t       v_tm_used;  /* used bytes on a TM volume */
-     uintmax_t       v_written;  /* amount of data written in afp_write, reset every time a FCE_TM_SIZE event is sent */
+     VolSpace        v_tm_used;  /* used bytes on a TM volume */
+     time_t          v_tm_cachetime; /* time at which v_tm_used was calculated last */
+     VolSpace        v_appended; /* amount of data appended to files */
      
      /* only when opening/closing volumes or in error */
      int             v_casefold;
      int             v_root_preexec_close;
      int             v_preexec_close;
      char            *v_uuid;    /* For TimeMachine zeroconf record */
 -#ifdef FORCE_UIDGID
 -    char            *v_forceuid;
 -    char            *v_forcegid;
 -#endif
  #ifdef __svr4__
      int         v_qfd;
  #endif /*__svr4__*/
  #define AFPVOL_USEDOTS   (1 << 11)  /* use real dots */
  #define AFPVOL_LIMITSIZE (1 << 12)  /* limit size for older macs */
  #define AFPVOL_MAPASCII  (1 << 13)  /* map the ascii range as well */
 -#define AFPVOL_DROPBOX   (1 << 14)  /* dropkludge dropbox support */
  #define AFPVOL_NOFILEID  (1 << 15)  /* don't advertise createid resolveid and deleteid calls */
  #define AFPVOL_NOSTAT    (1 << 16)  /* advertise the volume even if we can't stat() it
                                       * maybe because it will be mounted later in preexec */
index 2a1f1426aa45b6a5aeb1aa13614c46b3be17e078,20453bfd601404e94f344955aa17afb699aef3bb..5452b271860174ddfe1cd03736c7636f83ba652c
@@@ -1,4 -1,6 +1,4 @@@
  /*
 - * $Id: ad_sendfile.c,v 1.11 2010-01-21 14:14:49 didg Exp $
 - *
   * Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
   * All rights reserved. See COPYRIGHT.
   *
  #endif /* HAVE_CONFIG_H */
  
  #ifdef WITH_SENDFILE
 -
 -#include <atalk/adouble.h>
 -
  #include <stdio.h>
 -
  #include <sys/socket.h>
  #include <sys/uio.h>
 -
  #include <errno.h>  
  
 +#include <atalk/adouble.h>
  #include <atalk/logger.h>
 -#include "ad_private.h"
 +
 +#include "ad_lock.h"
  
- #if defined(LINUX_BROKEN_SENDFILE_API)
- extern int32_t sendfile (int fdout, int fdin, int32_t *offset, u_int32_t count);
+ #if defined(SENDFILE_FLAVOR_LINUX)
+ #include <sys/sendfile.h>
  
  ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
  {
- u_int32_t small_total;
- int32_t small_offset;
- int32_t nwritten;
-     /*
-      * Fix for broken Linux 2.4 systems with no working sendfile64().
-      * If the offset+count > 2 GB then pretend we don't have the
-      * system call sendfile at all. The upper layer catches this
-      * and uses a normal read. JRA.
-      */
-  
-      if ((sizeof(off_t) >= 8) && (*offset + count > (off_t)0x7FFFFFFF)) {
-          errno = ENOSYS;
-          return -1;
-      }
-      small_offset = (int32_t)*offset;
-      small_total = (u_int32_t)count;
-      nwritten = sendfile(tofd, fromfd, &small_offset, small_total);
-      if (nwritten > = 0)
-          *offset += nwritten;
-      
-     return nwritten;
+     return sendfile(tofd, fromfd, offset, count);
  }
  
- #elif defined(SENDFILE_FLAVOR_LINUX)
+ #elif defined(SENDFILE_FLAVOR_SOLARIS)
  #include <sys/sendfile.h>
  
  ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
@@@ -79,8 -62,6 +57,6 @@@
  }
  
  #elif defined(SENDFILE_FLAVOR_BSD )
- /* FIXME untested */
- #error sendfile semantic broken
  #include <sys/sendfile.h>
  ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
  {
diff --combined libatalk/cnid/cnid.c
index ab18f50c6baf4204aee05596a61916bf7f2428ea,8bb6373ee373e91acd57912a71414b3eebaafc30..0a977e6ae8a5f4f469b48b7b037e1811d370ba76
@@@ -29,7 -29,6 +29,7 @@@
  #include <atalk/list.h>
  #include <atalk/logger.h>
  #include <atalk/util.h>
 +#include <atalk/compat.h>
  
  /* List of all registered modules. */
  static struct list_head modules = ATALK_LIST_HEAD_INIT(modules);
@@@ -162,7 -161,7 +162,7 @@@ struct _cnid_db *cnid_open(const char *
  }
  
  /* ------------------- */
 -static void block_signal( u_int32_t flags)
 +static void block_signal(uint32_t flags)
  {
      if ((flags & CNID_FLAG_BLOCK)) {
          pthread_sigmask(SIG_BLOCK, &sigblockset, NULL);
  }
  
  /* ------------------- */
 -static void unblock_signal(u_int32_t flags)
 +static void unblock_signal(uint32_t flags)
  {
      if ((flags & CNID_FLAG_BLOCK)) {
          pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL);
@@@ -200,7 -199,7 +200,7 @@@ static cnid_t valide(cnid_t id
  /* Closes CNID database. Currently it's just a wrapper around db->cnid_close(). */
  void cnid_close(struct _cnid_db *db)
  {
 -u_int32_t flags;
 +    uint32_t flags;
  
      if (NULL == db) {
          LOG(log_error, logtype_afpd, "Error: cnid_close called with NULL argument !");
  cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, 
                  const char *name, const size_t len, cnid_t hint)
  {
- cnid_t ret;
+     cnid_t ret;
+     if (len == 0)
+         return CNID_INVALID;
  
      block_signal(cdb->flags);
      ret = valide(cdb->cnid_add(cdb, st, did, name, len, hint));
index 4d5a904d199003b8930f6b87e93641ee6907a13d,ae24535ddd11b85fb9e0a70eaf59f32520e81e72..45798b09e6f026715fb0fc4a1cd9956f56b40bd9
@@@ -1,6 -1,4 +1,4 @@@
  /*
-  * $Id: dsi_cmdreply.c,v 1.5 2009-10-25 06:13:11 didg Exp $
-  *
   * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
   * All rights reserved. See COPYRIGHT.
   */
  #endif /* HAVE_CONFIG_H */
  
  #include <stdio.h>
 +#include <arpa/inet.h>
 +
  #include <atalk/dsi.h>
+ #include <atalk/logger.h>
+ #include <netatalk/endian.h>
  
  /* this assumes that the reply follows right after the command, saving
   * on a couple assignments. specifically, command, requestID, and
   * reserved field are assumed to already be set. */ 
  int dsi_cmdreply(DSI *dsi, const int err)
  {
- int ret;
-   dsi->header.dsi_flags = DSIFL_REPLY;
-   /*dsi->header.dsi_command = DSIFUNC_CMD;*/
-   dsi->header.dsi_len = htonl(dsi->datalen);
-   dsi->header.dsi_code = htonl(err);
-   ret = dsi_stream_send(dsi, dsi->data, dsi->datalen);
-   return ret;
+     int ret;
+     LOG(log_debug, logtype_dsi, "dsi_cmdreply(DSI ID: %u, len: %jd): START",
+         dsi->clientID, (intmax_t)dsi->datalen);
+     dsi->header.dsi_flags = DSIFL_REPLY;
+     dsi->header.dsi_len = htonl(dsi->datalen);
+     dsi->header.dsi_code = htonl(err);
+     ret = dsi_stream_send(dsi, dsi->data, dsi->datalen);
+     LOG(log_debug, logtype_dsi, "dsi_cmdreply(DSI ID: %u, len: %jd): END",
+         dsi->clientID, (intmax_t)dsi->datalen);
+     return ret;
  }
diff --combined libatalk/dsi/dsi_read.c
index c723b3b43b878063c2ede7c1287cb8eea93589d9,12971511022f00835b61b922871b36bb75fa5789..75dfe9579d1c0923c3818a0b42255386f3e5fdd7
@@@ -1,4 -1,6 +1,4 @@@
  /*
 - * $Id: dsi_read.c,v 1.7 2009-10-25 06:13:11 didg Exp $
 - *
   * Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
   * All rights reserved. See COPYRIGHT.
   */
  
  #include <stdio.h>
  #include <string.h>
 -#ifdef HAVE_UNISTD_H
  #include <unistd.h>
 -#endif /* HAVE_UNISTD_H */
  #include <signal.h>
  #include <sys/types.h>
  #include <sys/time.h>
 -#ifdef HAVE_SYS_FILIO_H
 -#include <sys/filio.h>
 -#endif
  
  #include <atalk/dsi.h>
- #ifndef min
- #define min(a,b)   ((a) < (b) ? (a) : (b))
- #endif /* ! min */
+ #include <atalk/util.h>
+ #include <atalk/logger.h>
  
  /* streaming i/o for afp_read. this is all from the perspective of the
   * client. it basically does the reverse of dsi_write. on first entry,
   * buffer. it returns the amount of stuff still to be read
   * (constrained by the buffer size). */
  ssize_t dsi_readinit(DSI *dsi, void *buf, const size_t buflen,
-                   const size_t size, const int err)
+                      const size_t size, const int err)
  {
+     LOG(log_maxdebug, logtype_dsi, "dsi_readinit: sending %zd bytes from buffer, total size: %zd",
+         buflen, size);
  
-   dsi->flags |= DSI_NOREPLY; /* we will handle our own replies */
-   dsi->header.dsi_flags = DSIFL_REPLY;
-   /*dsi->header.dsi_command = DSIFUNC_CMD;*/
-   dsi->header.dsi_len = htonl(size);
-   dsi->header.dsi_code = htonl(err);
+     dsi->flags |= DSI_NOREPLY; /* we will handle our own replies */
+     dsi->header.dsi_flags = DSIFL_REPLY;
+     dsi->header.dsi_len = htonl(size);
+     dsi->header.dsi_code = htonl(err);
  
-   dsi->in_write++;
-   if (dsi_stream_send(dsi, buf, buflen)) {
-     dsi->datasize = size - buflen;
-     return min(dsi->datasize, buflen);
-   }
+     dsi->in_write++;
+     if (dsi_stream_send(dsi, buf, buflen)) {
+         dsi->datasize = size - buflen;
+         LOG(log_maxdebug, logtype_dsi, "dsi_readinit: remaining data for sendfile: %zd", dsi->datasize);
+         return MIN(dsi->datasize, buflen);
+     }
  
-   return -1; /* error */
+     return -1; /* error */
  }
  
  void dsi_readdone(DSI *dsi)
  {
-   dsi->in_write--;
+     dsi->in_write--;
  }
  
  /* send off the data */
  ssize_t dsi_read(DSI *dsi, void *buf, const size_t buflen)
  {
-   size_t len;
-   
-   len  = dsi_stream_write(dsi, buf, buflen, 0);
+     size_t len;
+     len  = dsi_stream_write(dsi, buf, buflen, 0);
  
-   if (len == buflen) {
-     dsi->datasize -= len;
-     return min(dsi->datasize, buflen);
-   }
+     if (len == buflen) {
+         dsi->datasize -= len;
+         return MIN(dsi->datasize, buflen);
+     }
  
-   return -1;
+     return -1;
  }
index 14a560815b6aa6050298e66af29db0076934613a,c709f2166fc8972e6a693fabc98fd535aab6663e..ef25275241e170c5563e730eba8260494cfa3d4e
@@@ -28,6 -28,7 +28,6 @@@
  
  #include <atalk/logger.h>
  #include <atalk/dsi.h>
 -#include <netatalk/endian.h>
  #include <atalk/util.h>
  
  #define min(a,b)  ((a) < (b) ? (a) : (b))
@@@ -124,7 -125,7 +124,7 @@@ static int dsi_peek(DSI *dsi
  /* 
   * Return all bytes up to count from dsi->buffer if there are any buffered there
   */
 -static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
 +static size_t from_buf(DSI *dsi, uint8_t *buf, size_t count)
  {
      size_t nbe = 0;
  
   *    Note: this may return fewer bytes then requested in count !!
   * 3. If the buffer was empty, read from the socket.
   */
 -static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
 +static ssize_t buf_read(DSI *dsi, uint8_t *buf, size_t count)
  {
      ssize_t len;
  
   * Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads
   * this tries to read larger chunks (8192 bytes) into a buffer.
   */
 -static size_t dsi_buffered_stream_read(DSI *dsi, u_int8_t *data, const size_t length)
 +static size_t dsi_buffered_stream_read(DSI *dsi, uint8_t *data, const size_t length)
  {
    size_t len;
    size_t buflen;
@@@ -265,13 -266,13 +265,13 @@@ ssize_t dsi_stream_write(DSI *dsi, voi
    dsi->in_write++;
    written = 0;
  
-   LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): START", length);
  
    if (dsi->flags & DSI_DISCONNECTED)
        return -1;
  
    while (written < length) {
 -      len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
 +      len = send(dsi->socket, (uint8_t *) data + written, length - written, flags);
        if (len >= 0) {
            written += len;
            continue;
    }
  
    dsi->write_count += written;
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): END", length);
  
  exit:
    dsi->in_write--;
  #ifdef WITH_SENDFILE
  ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t length)
  {
+   int ret = 0;
    size_t written;
    ssize_t len;
+   off_t pos = offset;
  
-   LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file(send %zd bytes): START", length);
  
    if (dsi->flags & DSI_DISCONNECTED)
        return -1;
    written = 0;
  
    while (written < length) {
-     len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
+     len = sys_sendfile(dsi->socket, fromfd, &pos, length - written);
          
      if (len < 0) {
        if (errno == EINTR)
            continue;
-       if (errno == EINVAL || errno == ENOSYS)
-           return -1;
-           
+       if (errno == EINVAL || errno == ENOSYS) {
+           ret = -1;
+           goto exit;
+       }          
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ #ifdef SOLARIS
+           if (pos > offset) {
+               /* we actually have sent sth., adjust counters and keep trying */
+               len = pos - offset;
+               written += len;
+               offset = pos;
+           }
+ #endif
            if (dsi_peek(dsi)) {
                /* can't go back to blocking mode, exit, the next read
                   will return with an error and afpd will die.
      }
      else if (!len) {
          /* afpd is going to exit */
-         errno = EIO;
-         return -1; /* I think we're at EOF here... */
+           ret = -1;
+           goto exit;
      }
      else 
          written += len;
    }
  
    dsi->write_count += written;
+ exit:
    dsi->in_write--;
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sent: %zd", written);
+   if (ret != 0)
+       return -1;
    return written;
  }
  #endif
@@@ -382,7 -400,7 +399,7 @@@ size_t dsi_stream_read(DSI *dsi, void *
  
    stored = 0;
    while (stored < length) {
 -      len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
 +      len = buf_read(dsi, (uint8_t *) data + stored, length - stored);
        if (len == -1 && (errno == EINTR || errno == EAGAIN)) {
            LOG(log_maxdebug, logtype_dsi, "dsi_stream_read: select read loop");
            continue;
@@@ -422,8 -440,7 +439,7 @@@ int dsi_stream_send(DSI *dsi, void *buf
    size_t towrite;
    ssize_t len;
  
-   LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
-       length ? length : sizeof(block));
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): START", length);
  
    if (dsi->flags & DSI_DISCONNECTED)
        return 0;
         sizeof(dsi->header.dsi_reserved));
  
    if (!length) { /* just write the header */
+       LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): DSI header, no data", sizeof(block));
      length = (dsi_stream_write(dsi, block, sizeof(block), 0) == sizeof(block));
      return length; /* really 0 on failure, 1 on success */
    }
            iov[1].iov_len -= len;
        }
    }
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): END", length);
    
    unblock_sig(dsi);
    return 1;
  }
  
  
- /* ---------------------------------------
-  * read data. function on success. 0 on failure. data length gets
-  * stored in length variable. this should really use size_t's, but
-  * that would require changes elsewhere. */
- int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
-                      size_t *rlength)
+ /*!
+  * Read DSI command and data
+  *
+  * @param  dsi   (rw) DSI handle
+  *
+  * @return    DSI function on success, 0 on failure
+  */
+ int dsi_stream_receive(DSI *dsi)
  {
    char block[DSI_BLOCKSIZ];
  
-   LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
+   LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: START");
  
    if (dsi->flags & DSI_DISCONNECTED)
        return 0;
  
    /* read in the header */
 -  if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) 
 +  if (dsi_buffered_stream_read(dsi, (uint8_t *)block, sizeof(block)) != sizeof(block)) 
      return 0;
  
    dsi->header.dsi_flags = block[0];
    dsi->header.dsi_command = block[1];
-   /* FIXME, not the right place, 
-      but we get a server disconnect without reason in the log
-   */
-   if (!block[1]) {
-       LOG(log_error, logtype_dsi, "dsi_stream_receive: invalid packet, fatal");
+   if (dsi->header.dsi_command == 0)
        return 0;
-   }
  
-   memcpy(&dsi->header.dsi_requestID, block + 2, 
-        sizeof(dsi->header.dsi_requestID));
+   memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID));
    memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
    memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
-   memcpy(&dsi->header.dsi_reserved, block + 12,
-        sizeof(dsi->header.dsi_reserved));
+   memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved));
    dsi->clientID = ntohs(dsi->header.dsi_requestID);
    
    /* make sure we don't over-write our buffers. */
-   *rlength = min(ntohl(dsi->header.dsi_len), ilength);
-   if (dsi_stream_read(dsi, buf, *rlength) != *rlength
+   dsi->cmdlen = min(ntohl(dsi->header.dsi_len), DSI_CMDSIZ);
+   if (dsi_stream_read(dsi, dsi->commands, dsi->cmdlen) != dsi->cmdlen
      return 0;
  
+   LOG(log_debug, logtype_dsi, "dsi_stream_receive: DSI cmdlen: %zd", dsi->cmdlen);
    return block[1];
  }
index dab605f746f3d872a4312aaa466a094139414651,cc00975ed333c4f6edaede90606ccd6e30f90927..c0a268802e635417397e27e3f3ee882600238d49
@@@ -2,13 -2,13 +2,13 @@@
  DO NOT EDIT BY HAND!!!
  
  This file is generated by
-  contrib/misc/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c
+  contrib/shell_utils/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c
  
  UnicodeData.txt is got from
  http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
  */
  
 -static const u_int16_t upper_table_1[704] = {
 +static const uint16_t upper_table_1[704] = {
    0x0000, /*U+0000*/ /**/
    0x0001, /*U+0001*/ /**/
    0x0002, /*U+0002*/ /**/
    0x02BF, /*U+02BF*/ /**/
  };
  
 -static const u_int16_t upper_table_2[640] = {
 +static const uint16_t upper_table_2[640] = {
    0x0340, /*U+0340*/ /**/
    0x0341, /*U+0341*/ /**/
    0x0342, /*U+0342*/ /**/
    0x05BF, /*U+05BF*/ /**/
  };
  
 -static const u_int16_t upper_table_3[64] = {
 +static const uint16_t upper_table_3[64] = {
    0x1D40, /*U+1D40*/ /**/
    0x1D41, /*U+1D41*/ /**/
    0x1D42, /*U+1D42*/ /**/
    0x1D7F, /*U+1D7F*/ /**/
  };
  
 -static const u_int16_t upper_table_4[512] = {
 +static const uint16_t upper_table_4[512] = {
    0x1E00, /*U+1E00*/ /**/
    0x1E00, /*U+1E01*/ /*LATIN SMALL LETTER A WITH RING BELOW*/
    0x1E02, /*U+1E02*/ /**/
    0x1FFF, /*U+1FFF*/ /**/
  };
  
 -static const u_int16_t upper_table_5[128] = {
 +static const uint16_t upper_table_5[128] = {
    0x2140, /*U+2140*/ /**/
    0x2141, /*U+2141*/ /**/
    0x2142, /*U+2142*/ /**/
    0x21BF, /*U+21BF*/ /**/
  };
  
 -static const u_int16_t upper_table_6[64] = {
 +static const uint16_t upper_table_6[64] = {
    0x24C0, /*U+24C0*/ /**/
    0x24C1, /*U+24C1*/ /**/
    0x24C2, /*U+24C2*/ /**/
    0x24FF, /*U+24FF*/ /**/
  };
  
 -static const u_int16_t upper_table_7[320] = {
 +static const uint16_t upper_table_7[320] = {
    0x2C00, /*U+2C00*/ /**/
    0x2C01, /*U+2C01*/ /**/
    0x2C02, /*U+2C02*/ /**/
    0x2D3F, /*U+2D3F*/ /**/
  };
  
 -static const u_int16_t upper_table_8[128] = {
 +static const uint16_t upper_table_8[128] = {
    0xA640, /*U+A640*/ /**/
    0xA640, /*U+A641*/ /*CYRILLIC SMALL LETTER ZEMLYA*/
    0xA642, /*U+A642*/ /**/
    0xA6BF, /*U+A6BF*/ /**/
  };
  
 -static const u_int16_t upper_table_9[192] = {
 +static const uint16_t upper_table_9[192] = {
    0xA700, /*U+A700*/ /**/
    0xA701, /*U+A701*/ /**/
    0xA702, /*U+A702*/ /**/
    0xA7BF, /*U+A7BF*/ /**/
  };
  
 -static const u_int16_t upper_table_10[64] = {
 +static const uint16_t upper_table_10[64] = {
    0xFF40, /*U+FF40*/ /**/
    0xFF21, /*U+FF41*/ /*FULLWIDTH LATIN SMALL LETTER A*/
    0xFF22, /*U+FF42*/ /*FULLWIDTH LATIN SMALL LETTER B*/
    0xFF7F, /*U+FF7F*/ /**/
  };
  
 -static const u_int32_t upper_table_sp_1[128] = {
 +static const uint32_t upper_table_sp_1[128] = {
    0xD801DC00, /*0xD801DC00*/ /*U+010400*/ /*U+010400*/ /**/
    0xD801DC01, /*0xD801DC01*/ /*U+010401*/ /*U+010401*/ /**/
    0xD801DC02, /*0xD801DC02*/ /*U+010402*/ /*U+010402*/ /**/
    0xD801DC7F, /*0xD801DC7F*/ /*U+01047F*/ /*U+01047F*/ /**/
  };
  
 -static const u_int16_t lower_table_1[128] = {
 +static const uint16_t lower_table_1[128] = {
    0x0000, /*U+0000*/ /**/
    0x0001, /*U+0001*/ /**/
    0x0002, /*U+0002*/ /**/
    0x007F, /*U+007F*/ /**/
  };
  
 -static const u_int16_t lower_table_2[448] = {
 +static const uint16_t lower_table_2[448] = {
    0x00E0, /*U+00C0*/ /*LATIN CAPITAL LETTER A WITH GRAVE*/
    0x00E1, /*U+00C1*/ /*LATIN CAPITAL LETTER A WITH ACUTE*/
    0x00E2, /*U+00C2*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX*/
    0x027F, /*U+027F*/ /**/
  };
  
 -static const u_int16_t lower_table_3[576] = {
 +static const uint16_t lower_table_3[576] = {
    0x0340, /*U+0340*/ /**/
    0x0341, /*U+0341*/ /**/
    0x0342, /*U+0342*/ /**/
    0x057F, /*U+057F*/ /**/
  };
  
 -static const u_int16_t lower_table_4[128] = {
 +static const uint16_t lower_table_4[128] = {
    0x1080, /*U+1080*/ /**/
    0x1081, /*U+1081*/ /**/
    0x1082, /*U+1082*/ /**/
    0x10FF, /*U+10FF*/ /**/
  };
  
 -static const u_int16_t lower_table_5[512] = {
 +static const uint16_t lower_table_5[512] = {
    0x1E01, /*U+1E00*/ /*LATIN CAPITAL LETTER A WITH RING BELOW*/
    0x1E01, /*U+1E01*/ /**/
    0x1E03, /*U+1E02*/ /*LATIN CAPITAL LETTER B WITH DOT ABOVE*/
    0x1FFF, /*U+1FFF*/ /**/
  };
  
 -static const u_int16_t lower_table_6[192] = {
 +static const uint16_t lower_table_6[192] = {
    0x2100, /*U+2100*/ /**/
    0x2101, /*U+2101*/ /**/
    0x2102, /*U+2102*/ /**/
    0x21BF, /*U+21BF*/ /**/
  };
  
 -static const u_int16_t lower_table_7[128] = {
 +static const uint16_t lower_table_7[128] = {
    0x2480, /*U+2480*/ /**/
    0x2481, /*U+2481*/ /**/
    0x2482, /*U+2482*/ /**/
    0x24FF, /*U+24FF*/ /**/
  };
  
 -static const u_int16_t lower_table_8[256] = {
 +static const uint16_t lower_table_8[256] = {
    0x2C30, /*U+2C00*/ /*GLAGOLITIC CAPITAL LETTER AZU*/
    0x2C31, /*U+2C01*/ /*GLAGOLITIC CAPITAL LETTER BUKY*/
    0x2C32, /*U+2C02*/ /*GLAGOLITIC CAPITAL LETTER VEDE*/
    0x2CFF, /*U+2CFF*/ /**/
  };
  
 -static const u_int16_t lower_table_9[128] = {
 +static const uint16_t lower_table_9[128] = {
    0xA641, /*U+A640*/ /*CYRILLIC CAPITAL LETTER ZEMLYA*/
    0xA641, /*U+A641*/ /**/
    0xA643, /*U+A642*/ /*CYRILLIC CAPITAL LETTER DZELO*/
    0xA6BF, /*U+A6BF*/ /**/
  };
  
 -static const u_int16_t lower_table_10[192] = {
 +static const uint16_t lower_table_10[192] = {
    0xA700, /*U+A700*/ /**/
    0xA701, /*U+A701*/ /**/
    0xA702, /*U+A702*/ /**/
    0xA7BF, /*U+A7BF*/ /**/
  };
  
 -static const u_int16_t lower_table_11[64] = {
 +static const uint16_t lower_table_11[64] = {
    0xFF00, /*U+FF00*/ /**/
    0xFF01, /*U+FF01*/ /**/
    0xFF02, /*U+FF02*/ /**/
    0xFF3F, /*U+FF3F*/ /**/
  };
  
 -static const u_int32_t lower_table_sp_1[64] = {
 +static const uint32_t lower_table_sp_1[64] = {
    0xD801DC28, /*0xD801DC00*/ /*U+010428*/ /*U+010400*/ /*DESERET CAPITAL LETTER LONG I*/
    0xD801DC29, /*0xD801DC01*/ /*U+010429*/ /*U+010401*/ /*DESERET CAPITAL LETTER LONG E*/
    0xD801DC2A, /*0xD801DC02*/ /*U+01042A*/ /*U+010402*/ /*DESERET CAPITAL LETTER LONG A*/
diff --combined libatalk/util/unix.c
index d202b99a31f9d1dc165c7836b8b43d3d0fcd6f4c,0e466307bcd30d6ad13ec3af0c8444be0b26bd45..0ac210ec2c8d4e3e1d99ab16a33f7067cfabd24f
@@@ -40,7 -40,6 +40,7 @@@
  #include <atalk/vfs.h>
  #include <atalk/util.h>
  #include <atalk/unix.h>
 +#include <atalk/compat.h>
  
  /* close all FDs >= a specified value */
  static void closeall(int fd)
@@@ -112,28 -111,25 +112,25 @@@ const char *getcwdpath(void
  }
  
  /*!
-  * Make argument path absoulte
+  * @brief Request absolute path
   *
-  * @returns pointer to path or pointer to error messages on error
+  * @returns Absolute filesystem path to object
   */
- const char *abspath(const char *name)
+ const char *fullpathname(const char *name)
  {
-     static char buf[MAXPATHLEN + 1];
-     char *p;
-     int n;
+     static char wd[MAXPATHLEN + 1];
  
      if (name[0] == '/')
          return name;
  
-     if ((p = getcwd(buf, MAXPATHLEN)) == NULL)
-         return strerror(errno);
+     if (getcwd(wd , MAXPATHLEN)) {
+         strlcat(wd, "/", MAXPATHLEN);
+         strlcat(wd, name, MAXPATHLEN);
+     } else {
+         strlcpy(wd, name, MAXPATHLEN);
+     }
  
-     n = strlen(buf);
-     if (buf[n-1] != '/')
-         buf[n++] = '/';
-         
-     strlcpy(buf + n, name, MAXPATHLEN - n);
-     return buf;
+     return wd;
  }
  
  /*!
diff --combined libatalk/util/volinfo.c
index 6e950924120995bd961a1e36002f0f8fbb368d40,c6cb1f21b454b1045e13ae5abe87608e337388ff..52360b1ece0330089386c5383f9cc619c74403e3
  #include <ctype.h>
  #include <errno.h>
  #include <fcntl.h>
 -#ifdef HAVE_STRINGS_H
 -#include <strings.h>
 -#endif
 -#ifdef STDC_HEADERS
  #include <string.h>
 -#endif
  #include <sys/param.h>
  
  #include <atalk/adouble.h>
@@@ -36,7 -41,6 +36,7 @@@
  #include <atalk/logger.h>
  #include <atalk/volinfo.h>
  #include <atalk/volume.h>
 +#include <atalk/compat.h>
  #ifdef CNID_DB
  #include <atalk/cnid.h>
  #endif /* CNID_DB*/
@@@ -51,6 -55,7 +51,6 @@@ static const vol_opt_name_t vol_opt_nam
      {AFPVOL_USEDOTS,    "USEDOTS"},     /* use real dots */
      {AFPVOL_LIMITSIZE,  "LIMITSIZE"},   /* limit size for older macs */
      {AFPVOL_MAPASCII,   "MAPASCII"},    /* map the ascii range as well */
 -    {AFPVOL_DROPBOX,    "DROPBOX"},     /* dropkludge dropbox support */
      {AFPVOL_NOFILEID,   "NOFILEID"},    /* don't advertise createid resolveid and deleteid calls */
      {AFPVOL_NOSTAT,     "NOSTAT"},      /* advertise the volume even if we can't stat() it
                                           * maybe because it will be mounted later in preexec */
@@@ -295,14 -300,21 +295,14 @@@ static int parseline ( char *buf, struc
            strcpy(vol->v_dbpath, value);
          break;
        case ADOUBLE_VER:
 -        if (strcasecmp(value, "v1") == 0) {
 -            vol->v_adouble = AD_VERSION1;
 -            vol->ad_path = ad_path;
 -        }
 -#if AD_VERSION == AD_VERSION2
 -        else if (strcasecmp(value, "v2") == 0) {
 +        if (strcasecmp(value, "v2") == 0) {
              vol->ad_path = ad_path;
              vol->v_adouble = AD_VERSION2;
 -        }
 -        else if (strcasecmp(value, "osx") == 0) {
 -            vol->v_adouble = AD_VERSION2_OSX;
 -            vol->ad_path = ad_path_osx;
 -        }
 -#endif
 -        else  {
 +        } else if (strcasecmp(value, "ea") == 0) {
 +            vol->ad_path = ad_path_ea;
 +            vol->v_adouble = AD_VERSION_EA;
 +        } else {
 +
            fprintf (stderr, "unknown adouble version: %s, %s", buf, value);
            return -1;
          }
@@@ -485,13 -497,19 +485,19 @@@ int savevolinfo(const struct vol *vol, 
      }
  
      if ((fd = open(item, O_RDWR | O_CREAT , 0666)) <0 ) {
-         LOG(log_error, logtype_afpd,"Error opening %s: %s", item, strerror(errno));
+         LOG(log_debug, logtype_default,"Error opening %s: %s", item, strerror(errno));
+         if (process_uid) {
+             if (seteuid(process_uid) == -1) {
+                 LOG(log_error, logtype_default, "can't seteuid back %s", strerror(errno));
+                 exit(EXITERR_SYS);
+             }
+         }
          return (-1);
      }
  
      if (process_uid) {
          if (seteuid(process_uid) == -1) {
-             LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno));
+             LOG(log_error, logtype_default, "can't seteuid back %s", strerror(errno));
              exit(EXITERR_SYS);
          }
      }
              /* ignore, other process already writing the file */
              return 0;
          } else {
-             LOG(log_error, logtype_cnid, "savevoloptions: cannot get lock: %s", strerror(errno));
+             LOG(log_error, logtype_default, "savevoloptions: cannot get lock: %s", strerror(errno));
              return (-1);
          }
      }
      strlcat(buf, item, sizeof(buf));
  
      switch (vol->v_adouble) {
 -        case AD_VERSION1:
 -            strlcat(buf, "ADOUBLE_VER:v1\n", sizeof(buf));
 -            break;
          case AD_VERSION2:
              strlcat(buf, "ADOUBLE_VER:v2\n", sizeof(buf));
              break;
 -        case AD_VERSION2_OSX:
 -            strlcat(buf, "ADOUBLE_VER:osx\n", sizeof(buf));
 -            break;
 -        case AD_VERSION1_SFM:
 -            strlcat(buf, "ADOUBLE_VER:sfm\n", sizeof(buf));
 +        case AD_VERSION_EA:
 +            strlcat(buf, "ADOUBLE_VER:ea\n", sizeof(buf));
              break;
      }
  
      strlcat(buf, item, sizeof(buf));
  
      if (strlen(buf) >= sizeof(buf)-1)
-         LOG(log_debug, logtype_afpd,"Error writing .volinfo file: buffer too small, %s", buf);
+         LOG(log_debug, logtype_default, "Error writing .volinfo file: buffer too small, %s", buf);
     if (write( fd, buf, strlen(buf)) < 0 || ftruncate(fd, strlen(buf)) < 0 ) {
-        LOG(log_debug, logtype_afpd,"Error writing .volinfo file: %s", strerror(errno));
+        LOG(log_debug, logtype_default, "Error writing .volinfo file: %s", strerror(errno));
     }
  
     lock.l_type = F_UNLCK;
diff --combined libatalk/vfs/ea_ad.c
index 7f9629b0053e19450c6d3e6a59edc10addc1373e,0000000000000000000000000000000000000000..9f369ea4fb3506036ba204d10080a5d26a016474
mode 100644,000000..100644
--- /dev/null
@@@ -1,1770 -1,0 +1,1772 @@@
-         LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion");
 +/*
 +  Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
 +
 +  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.
 +*/
 +
 +#ifdef HAVE_CONFIG_H
 +#include "config.h"
 +#endif /* HAVE_CONFIG_H */
 +
 +#include <unistd.h>
 +#include <stdint.h>
 +#include <errno.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <sys/types.h>
 +#include <sys/stat.h>
 +#include <fcntl.h>
 +#include <dirent.h>
 +#include <arpa/inet.h>
 +
 +#include <atalk/adouble.h>
 +#include <atalk/ea.h>
 +#include <atalk/afp.h>
 +#include <atalk/logger.h>
 +#include <atalk/volume.h>
 +#include <atalk/vfs.h>
 +#include <atalk/util.h>
 +#include <atalk/unix.h>
 +#include <atalk/compat.h>
 +
 +/*
 + * Store Extended Attributes inside .AppleDouble folders as follows:
 + *
 + * filename "fileWithEAs" with EAs "testEA1" and "testEA2"
 + *
 + * - create header with with the format struct adouble_ea_ondisk, the file is written to
 + *   ".AppleDouble/fileWithEAs::EA"
 + * - store EAs in files "fileWithEAs::EA::testEA1" and "fileWithEAs::EA::testEA2"
 + */
 +
 +/* 
 + * Build mode for EA header from file mode
 + */
 +static inline mode_t ea_header_mode(mode_t mode)
 +{
 +    /* Same as ad_hf_mode(mode) */
 +    mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
 +    /* Owner must be able to open, read and w-lock it, in order to chmod from eg 0000 -> 0xxxx*/
 +    mode |= S_IRUSR | S_IWUSR;
 +    return mode;
 +}
 +
 +/* 
 + * Build mode for EA file from file mode
 + */
 +static inline mode_t ea_mode(mode_t mode)
 +{
 +    /* Same as ad_hf_mode(mode) */
 +    mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
 +    return mode;
 +}
 +
 +/*
 +  Taken form afpd/desktop.c
 +*/
 +static char *mtoupath(const struct vol *vol, const char *mpath)
 +{
 +    static char  upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
 +    const char   *m;
 +    char         *u;
 +    size_t       inplen;
 +    size_t       outlen;
 +    uint16_t     flags = CONV_ESCAPEHEX | CONV_ALLOW_COLON;
 +
 +    if (!mpath)
 +        return NULL;
 +
 +    if ( *mpath == '\0' ) {
 +        return( "." );
 +    }
 +
 +    m = mpath;
 +    u = upath;
 +
 +    inplen = strlen(m);
 +    outlen = MAXPATHLEN;
 +
 +    if ((size_t)-1 == (outlen = convert_charset(CH_UTF8_MAC,
 +                                                vol->v_volcharset,
 +                                                vol->v_maccharset,
 +                                                m, inplen, u, outlen, &flags)) ) {
 +        return NULL;
 +    }
 +
 +    return( upath );
 +}
 +
 +
 +/*
 + * Function: unpack_header
 + *
 + * Purpose: unpack and verify header file data buffer at ea->ea_data into struct ea
 + *
 + * Arguments:
 + *
 + *    ea      (rw) handle to struct ea
 + *
 + * Returns: 0 on success, -1 on error
 + *
 + * Effects:
 + *
 + * Verifies magic and version.
 + */
 +static int unpack_header(struct ea * restrict ea)
 +{
 +    int ret = 0;
 +    unsigned int count = 0;
 +    uint32_t uint32;
 +    char *buf;
 +
 +    /* Check magic and version */
 +    buf = ea->ea_data;
 +    if (*(uint32_t *)buf != htonl(EA_MAGIC)) {
 +        LOG(log_error, logtype_afpd, "unpack_header: wrong magic 0x%08x", *(uint32_t *)buf);
 +        ret = -1;
 +        goto exit;
 +    }
 +    buf += 4;
 +    if (*(uint16_t *)buf != htons(EA_VERSION)) {
 +        LOG(log_error, logtype_afpd, "unpack_header: wrong version 0x%04x", *(uint16_t *)buf);
 +        ret = -1;
 +        goto exit;
 +    }
 +    buf += 2;
 +
 +    /* Get EA count */
 +    ea->ea_count = ntohs(*(uint16_t *)buf);
 +    LOG(log_debug, logtype_afpd, "unpack_header: number of EAs: %u", ea->ea_count);
 +    buf += 2;
 +
 +    if (ea->ea_count == 0)
 +        return 0;
 +
 +    /* Allocate storage for the ea_entries array */
 +    ea->ea_entries = malloc(sizeof(struct ea_entry) * ea->ea_count);
 +    if ( ! ea->ea_entries) {
 +        LOG(log_error, logtype_afpd, "unpack_header: OOM");
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +    buf = ea->ea_data + EA_HEADER_SIZE;
 +    while (count < ea->ea_count) {
 +        memcpy(&uint32, buf, 4); /* EA size */
 +        buf += 4;
 +        (*(ea->ea_entries))[count].ea_size = ntohl(uint32);
 +        (*(ea->ea_entries))[count].ea_name = strdup(buf);
 +        if (! (*(ea->ea_entries))[count].ea_name) {
 +            LOG(log_error, logtype_afpd, "unpack_header: OOM");
 +            ret = -1;
 +            goto exit;
 +        }
 +        (*(ea->ea_entries))[count].ea_namelen = strlen((*(ea->ea_entries))[count].ea_name);
 +        buf += (*(ea->ea_entries))[count].ea_namelen + 1;
 +
 +        LOG(log_maxdebug, logtype_afpd, "unpack_header: entry no:%u,\"%s\", size: %u, namelen: %u", count,
 +            (*(ea->ea_entries))[count].ea_name,
 +            (*(ea->ea_entries))[count].ea_size,
 +            (*(ea->ea_entries))[count].ea_namelen);
 +
 +        count++;
 +    }
 +
 +exit:
 +    return ret;
 +}
 +
 +/*
 + * Function: pack_header
 + *
 + * Purpose: pack everything from struct ea into buffer at ea->ea_data
 + *
 + * Arguments:
 + *
 + *    ea      (rw) handle to struct ea
 + *
 + * Returns: 0 on success, -1 on error
 + *
 + * Effects:
 + *
 + * adjust ea->ea_count in case an ea entry deletetion is detected
 + */
 +static int pack_header(struct ea * restrict ea)
 +{
 +    unsigned int count = 0, eacount = 0;
 +    uint16_t uint16;
 +    uint32_t uint32;
 +    size_t bufsize = EA_HEADER_SIZE;
 +
 +    char *buf = ea->ea_data + EA_HEADER_SIZE;
 +
 +    LOG(log_debug, logtype_afpd, "pack_header('%s'): ea_count: %u, ea_size: %u",
 +        ea->filename, ea->ea_count, ea->ea_size);
 +
 +    if (ea->ea_count == 0)
 +        /* nothing to do, magic, version and count are still valid in buffer */
 +        return 0;
 +
 +    while(count < ea->ea_count) { /* the names */
 +        /* Check if its a deleted entry */
 +        if ( ! ((*ea->ea_entries)[count].ea_name)) {
 +            count++;
 +            continue;
 +        }
 +
 +        bufsize += (*(ea->ea_entries))[count].ea_namelen + 1;
 +        count++;
 +        eacount++;
 +    }
 +
 +    bufsize += (eacount * 4); /* header + ea_size for each EA */
 +    if (bufsize > ea->ea_size) {
 +        /* we must realloc */
 +        if ( ! (buf = realloc(ea->ea_data, bufsize)) ) {
 +            LOG(log_error, logtype_afpd, "pack_header: OOM");
 +            return -1;
 +        }
 +        ea->ea_data = buf;
 +    }
 +    ea->ea_size = bufsize;
 +
 +    /* copy count */
 +    uint16 = htons(eacount);
 +    memcpy(ea->ea_data + EA_COUNT_OFF, &uint16, 2);
 +
 +    count = 0;
 +    buf = ea->ea_data + EA_HEADER_SIZE;
 +    while (count < ea->ea_count) {
 +        /* Check if its a deleted entry */
 +        if ( ! ((*ea->ea_entries)[count].ea_name)) {
 +            count++;
 +            continue;
 +        }
 +
 +        /* First: EA size */
 +        uint32 = htonl((*(ea->ea_entries))[count].ea_size);
 +        memcpy(buf, &uint32, 4);
 +        buf += 4;
 +
 +        /* Second: EA name as C-string */
 +        strcpy(buf, (*(ea->ea_entries))[count].ea_name);
 +        buf += (*(ea->ea_entries))[count].ea_namelen + 1;
 +
 +        LOG(log_maxdebug, logtype_afpd, "pack_header: entry no:%u,\"%s\", size: %u, namelen: %u", count,
 +            (*(ea->ea_entries))[count].ea_name,
 +            (*(ea->ea_entries))[count].ea_size,
 +            (*(ea->ea_entries))[count].ea_namelen);
 +
 +        count++;
 +    }
 +
 +    ea->ea_count = eacount;
 +
 +    LOG(log_debug, logtype_afpd, "pack_header('%s'): ea_count: %u, ea_size: %u",
 +        ea->filename, ea->ea_count, ea->ea_size);
 +    
 +    return 0;
 +}
 +
 +/*
 + * Function: ea_addentry
 + *
 + * Purpose: add one EA into ea->ea_entries[]
 + *
 + * Arguments:
 + *
 + *    ea            (rw) pointer to struct ea
 + *    attruname     (r) name of EA
 + *    attrsize      (r) size of ea
 + *    bitmap        (r) bitmap from FP func
 + *
 + * Returns: new number of EA entries, -1 on error
 + *
 + * Effects:
 + *
 + * Grow array ea->ea_entries[]. If ea->ea_entries is still NULL, start allocating.
 + * Otherwise realloc and put entry at the end. Increments ea->ea_count.
 + */
 +static int ea_addentry(struct ea * restrict ea,
 +                       const char * restrict attruname,
 +                       size_t attrsize,
 +                       int bitmap)
 +{
 +    int ea_existed = 0;
 +    unsigned int count = 0;
 +    void *tmprealloc;
 +
 +    /* First check if an EA of the requested name already exist */
 +    if (ea->ea_count > 0) {
 +        while (count < ea->ea_count) {
 +            if (strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
 +                ea_existed = 1;
 +                LOG(log_debug, logtype_afpd, "ea_addentry('%s', bitmap:0x%x): exists", attruname, bitmap);
 +                if (bitmap & kXAttrCreate)
 +                    /* its like O_CREAT|O_EXCL -> fail */
 +                    return -1;
 +                (*(ea->ea_entries))[count].ea_size = attrsize;
 +                return 0;
 +            }
 +            count++;
 +        }
 +    }
 +
 +    if ((bitmap & kXAttrReplace) && ! ea_existed)
 +        /* replace was requested, but EA didn't exist */
 +        return -1;
 +
 +    if (ea->ea_count == 0) {
 +        ea->ea_entries = malloc(sizeof(struct ea_entry));
 +        if ( ! ea->ea_entries) {
 +            LOG(log_error, logtype_afpd, "ea_addentry: OOM");
 +            return -1;
 +        }
 +    } else if (! ea_existed) {
 +        tmprealloc = realloc(ea->ea_entries, sizeof(struct ea_entry) * (ea->ea_count + 1));
 +        if ( ! tmprealloc) {
 +            LOG(log_error, logtype_afpd, "ea_addentry: OOM");
 +            return -1;
 +        }
 +        ea->ea_entries = tmprealloc;
 +    }
 +
 +    /* We've grown the array, now store the entry */
 +    (*(ea->ea_entries))[ea->ea_count].ea_size = attrsize;
 +    (*(ea->ea_entries))[ea->ea_count].ea_name = strdup(attruname);
 +    if ( ! (*(ea->ea_entries))[ea->ea_count].ea_name) {
 +        LOG(log_error, logtype_afpd, "ea_addentry: OOM");
 +        goto error;
 +    }
 +    (*(ea->ea_entries))[ea->ea_count].ea_namelen = strlen(attruname);
 +
 +    ea->ea_count++;
 +    return ea->ea_count;
 +
 +error:
 +    if (ea->ea_count == 0 && ea->ea_entries) {
 +        /* We just allocated storage but had an error somewhere -> free storage*/
 +        free(ea->ea_entries);
 +        ea->ea_entries = NULL;
 +    }
 +    ea->ea_count = 0;
 +    return -1;
 +}
 +
 +/*
 + * Function: create_ea_header
 + *
 + * Purpose: create EA header file, only called from ea_open
 + *
 + * Arguments:
 + *
 + *    uname       (r)  filename for which we have to create a header
 + *    ea          (rw) ea handle with already allocated storage pointed to
 + *                     by ea->ea_data
 + *
 + * Returns: fd of open header file on success, -1 on error, errno semantics:
 + *          EEXIST: open with O_CREAT | O_EXCL failed
 + *
 + * Effects:
 + *
 + * Creates EA header file and initialize ea->ea_data buffer.
 + * Possibe race condition with other afpd processes:
 + * we were called because header file didn't exist in eg. ea_open. We then
 + * try to create a file with O_CREAT | O_EXCL, but the whole process in not atomic.
 + * What do we do then? Someone else is in the process of creating the header too, but
 + * it might not have finished it. That means we cant just open, read and use it!
 + * We therefor currently just break with an error.
 + * On return the header file is still r/w locked.
 + */
 +static int create_ea_header(const char * restrict uname,
 +                            struct ea * restrict ea)
 +{
 +    int fd = -1, err = 0;
 +    char *ptr;
 +
 +    if ((fd = open(uname, O_RDWR | O_CREAT | O_EXCL, 0666 & ~ea->vol->v_umask)) == -1) {
 +        LOG(log_error, logtype_afpd, "ea_create: open race condition with ea header for file: %s", uname);
 +        return -1;
 +    }
 +
 +    /* lock it */
 +    if ((write_lock(fd, 0, SEEK_SET, 0)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_create: lock race condition with ea header for file: %s", uname);
 +        err = -1;
 +        goto exit;
 +    }
 +
 +    /* Now init it */
 +    ptr = ea->ea_data;
 +    *(uint32_t *)ptr = htonl(EA_MAGIC);
 +    ptr += EA_MAGIC_LEN;
 +    *(uint16_t *)ptr = htons(EA_VERSION);
 +    ptr += EA_VERSION_LEN;
 +    *(uint16_t *)ptr = 0;       /* count */
 +
 +    ea->ea_size = EA_HEADER_SIZE;
 +    ea->ea_inited = EA_INITED;
 +
 +exit:
 +    if (err != 0) {
 +        close(fd);
 +        fd = -1;
 +    }
 +    return fd;
 +}
 +
 +/*
 + * Function: write_ea
 + *
 + * Purpose: write an EA to disk
 + *
 + * Arguments:
 + *
 + *    ea         (r) struct ea handle
 + *    attruname  (r) EA name
 + *    ibuf       (r) buffer with EA content
 + *    attrsize   (r) size of EA
 + *
 + * Returns: 0 on success, -1 on error
 + *
 + * Effects:
 + *
 + * Creates/overwrites EA file.
 + *
 + */
 +static int write_ea(const struct ea * restrict ea,
 +                    const char * restrict attruname,
 +                    const char * restrict ibuf,
 +                    size_t attrsize)
 +{
 +    int fd = -1, ret = AFP_OK;
 +    struct stat st;
 +    char *eaname;
 +
 +    if ((eaname = ea_path(ea, attruname, 1)) == NULL) {
 +        LOG(log_error, logtype_afpd, "write_ea('%s'): ea_path error", attruname);
 +        return AFPERR_MISC;
 +    }
 +
 +    LOG(log_maxdebug, logtype_afpd, "write_ea('%s')", eaname);
 +
 +    /* Check if it exists, remove if yes*/
 +    if ((stat(eaname, &st)) == 0) {
 +        if ((unlink(eaname)) != 0) {
 +            if (errno == EACCES)
 +                return AFPERR_ACCESS;
 +            else
 +                return AFPERR_MISC;
 +        }
 +    }
 +
 +    if ((fd = open(eaname, O_RDWR | O_CREAT | O_EXCL, 0666 & ~ea->vol->v_umask)) == -1) {
 +        LOG(log_error, logtype_afpd, "write_ea: open race condition: %s", eaname);
 +        return -1;
 +    }
 +
 +    /* lock it */
 +    if ((write_lock(fd, 0, SEEK_SET, 0)) != 0) {
 +        LOG(log_error, logtype_afpd, "write_ea: open race condition: %s", eaname);
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +    if (write(fd, ibuf, attrsize) != (ssize_t)attrsize) {
 +        LOG(log_error, logtype_afpd, "write_ea('%s'): write: %s", eaname, strerror(errno));
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +exit:
 +    if (fd != -1)
 +        close(fd); /* and unlock */
 +    return ret;
 +}
 +
 +/*
 + * Function: ea_delentry
 + *
 + * Purpose: delete one EA from ea->ea_entries[]
 + *
 + * Arguments:
 + *
 + *    ea            (rw) pointer to struct ea
 + *    attruname     (r) EA name
 + *
 + * Returns: new number of EA entries, -1 on error
 + *
 + * Effects:
 + *
 + * Remove entry from  ea->ea_entries[]. Decrement ea->ea_count.
 + * Marks it as unused just by freeing name and setting it to NULL.
 + * ea_close and pack_buffer must honor this.
 + */
 +static int ea_delentry(struct ea * restrict ea, const char * restrict attruname)
 +{
 +    int ret = 0;
 +    unsigned int count = 0;
 +
 +    if (ea->ea_count == 0) {
-         if (strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
++        LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion",
++            attruname);
 +        return -1;
 +    }
 +
 +    while (count < ea->ea_count) {
 +        /* search matching EA */
++        if ((*ea->ea_entries)[count].ea_name &&
++            strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
 +            free((*ea->ea_entries)[count].ea_name);
 +            (*ea->ea_entries)[count].ea_name = NULL;
 +
 +            LOG(log_debug, logtype_afpd, "ea_delentry('%s'): deleted no %u/%u",
 +                attruname, count + 1, ea->ea_count);
 +
 +            break;
 +        }
 +        count++;
 +    }
 +
 +    return ret;
 +}
 +
 +/*
 + * Function: delete_ea_file
 + *
 + * Purpose: delete EA file from disk
 + *
 + * Arguments:
 + *
 + *    ea         (r) struct ea handle
 + *    attruname  (r) EA name
 + *
 + * Returns: 0 on success, -1 on error
 + */
 +static int delete_ea_file(const struct ea * restrict ea, const char *eaname)
 +{
 +    int ret = 0;
 +    char *eafile;
 +    struct stat st;
 +
 +    if ((eafile = ea_path(ea, eaname, 1)) == NULL) {
 +        LOG(log_error, logtype_afpd, "delete_ea_file('%s'): ea_path error", eaname);
 +        return -1;
 +    }
 +
 +    /* Check if it exists, remove if yes*/
 +    if ((stat(eafile, &st)) == 0) {
 +        if ((unlink(eafile)) != 0) {
 +            LOG(log_error, logtype_afpd, "delete_ea_file('%s'): unlink: %s",
 +                eafile, strerror(errno));
 +            ret = -1;
 +        } else
 +            LOG(log_debug, logtype_afpd, "delete_ea_file('%s'): success", eafile);
 +    }
 +
 +    return ret;
 +}
 +
 +/*************************************************************************************
 + * ea_path, ea_open and ea_close are only global so that dbd can call them
 + *************************************************************************************/
 +
 +/*
 + * Function: ea_path
 + *
 + * Purpose: return name of ea header filename
 + *
 + * Arguments:
 + *
 + *    ea           (r) ea handle
 + *    eaname       (r) name of EA or NULL
 + *    macname      (r) if != 0 call mtoupath on eaname
 + *
 + * Returns: pointer to name in static buffer, NULL on error
 + *
 + * Effects:
 + *
 + * Calls ad_open, copies buffer, appends "::EA" and if supplied append eanme
 + * Files: "file" -> "file/.AppleDouble/file::EA"
 + * Dirs: "dir" -> "dir/.AppleDouble/.Parent::EA"
 + * "file" with EA "myEA" -> "file/.AppleDouble/file::EA:myEA"
 + */
 +char *ea_path(const struct ea * restrict ea, const char * restrict eaname, int macname)
 +{
 +    const char *adname;
 +    static char pathbuf[MAXPATHLEN + 1];
 +
 +    /* get name of a adouble file from uname */
 +    adname = ea->vol->ad_path(ea->filename, (ea->ea_flags & EA_DIR) ? ADFLAGS_DIR : 0);
 +    /* copy it so we can work with it */
 +    strlcpy(pathbuf, adname, MAXPATHLEN + 1);
 +    /* append "::EA" */
 +    strlcat(pathbuf, "::EA", MAXPATHLEN + 1);
 +
 +    if (eaname) {
 +        strlcat(pathbuf, "::", MAXPATHLEN + 1);
 +        if (macname)
 +            if ((eaname = mtoupath(ea->vol, eaname)) == NULL)
 +                return NULL;
 +        strlcat(pathbuf, eaname, MAXPATHLEN + 1);
 +    }
 +
 +    return pathbuf;
 +}
 +
 +/*
 + * Function: ea_open
 + *
 + * Purpose: open EA header file, create if it doesnt exits and called with O_CREATE
 + *
 + * Arguments:
 + *
 + *    vol         (r) current volume
 + *    uname       (r) filename for which we have to open a header
 + *    flags       (r) EA_CREATE: create if it doesn't exist (without it won't be created)
 + *                    EA_RDONLY: open read only
 + *                    EA_RDWR: open read/write
 + *                    Eiterh EA_RDONLY or EA_RDWR MUST be requested
 + *    ea          (w) pointer to a struct ea that we fill
 + *
 + * Returns: 0 on success
 + *         -1 on misc error with errno = EFAULT
 + *         -2 if no EA header exists with errno = ENOENT
 + *
 + * Effects:
 + *
 + * opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size.
 + * number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags.
 + * file is either read or write locked depending on the open flags.
 + * When you're done with struct ea you must call ea_close on it.
 + */
 +int ea_open(const struct vol * restrict vol,
 +            const char * restrict uname,
 +            eaflags_t eaflags,
 +            struct ea * restrict ea)
 +{
 +    int ret = 0;
 +    char *eaname;
 +    struct stat st;
 +
 +    /* Enforce usage rules! */
 +    if ( ! (eaflags & (EA_RDONLY | EA_RDWR))) {
 +        LOG(log_error, logtype_afpd, "ea_open: called without EA_RDONLY | EA_RDWR", uname);
 +        return -1;
 +    }
 +
 +    /* Set it all to 0 */
 +    memset(ea, 0, sizeof(struct ea));
 +
 +    ea->vol = vol;              /* ea_close needs it */
 +    ea->ea_flags = eaflags;
 +    ea->dirfd = -1;             /* no *at (cf openat) semantics by default */
 +
 +    /* Dont care for errors, eg when removing the file is already gone */
 +    if (!stat(uname, &st) && S_ISDIR(st.st_mode))
 +        ea->ea_flags |=  EA_DIR;
 +
 +    if ( ! (ea->filename = strdup(uname))) {
 +        LOG(log_error, logtype_afpd, "ea_open: OOM");
 +        return -1;
 +    }
 +
 +    eaname = ea_path(ea, NULL, 0);
 +    LOG(log_maxdebug, logtype_afpd, "ea_open: ea_path: %s", eaname);
 +
 +    /* Check if it exists, if not create it if EA_CREATE is in eaflags */
 +    if ((stat(eaname, &st)) != 0) {
 +        if (errno == ENOENT) {
 +
 +            /* It doesnt exist */
 +
 +            if ( ! (eaflags & EA_CREATE)) {
 +                /* creation was not requested, so return with error */
 +                ret = -2;
 +                goto exit;
 +            }
 +
 +            /* Now create a header file */
 +
 +            /* malloc buffer for minimal on disk data */
 +            ea->ea_data = malloc(EA_HEADER_SIZE);
 +            if (! ea->ea_data) {
 +                LOG(log_error, logtype_afpd, "ea_open: OOM");
 +                ret = -1;
 +                goto exit;
 +            }
 +
 +            /* create it */
 +            ea->ea_fd = create_ea_header(eaname, ea);
 +            if (ea->ea_fd == -1) {
 +                ret = -1;
 +                goto exit;
 +            }
 +
 +            return 0;
 +
 +        } else {/* errno != ENOENT */
 +            ret = -1;
 +            goto exit;
 +        }
 +    }
 +
 +    /* header file exists, so read and parse it */
 +
 +    /* malloc buffer where we read disk file into */
 +    if (st.st_size < EA_HEADER_SIZE) {
 +        LOG(log_error, logtype_afpd, "ea_open('%s'): bogus EA header file", eaname);
 +        ret = -1;
 +        goto exit;
 +    }
 +    ea->ea_size = st.st_size;
 +    ea->ea_data = malloc(st.st_size);
 +    if (! ea->ea_data) {
 +        LOG(log_error, logtype_afpd, "ea_open: OOM");
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +    /* Now lock, open and read header file from disk */
 +    if ((ea->ea_fd = open(eaname, (ea->ea_flags & EA_RDWR) ? O_RDWR : O_RDONLY)) == -1) {
 +        LOG(log_error, logtype_afpd, "ea_open('%s'): error: %s", eaname, strerror(errno));
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +    /* lock it */
 +    if (ea->ea_flags & EA_RDONLY) {
 +        /* read lock */
 +        if ((read_lock(ea->ea_fd, 0, SEEK_SET, 0)) != 0) {
 +            LOG(log_error, logtype_afpd, "ea_open: lock error on  header: %s", eaname);
 +            ret = -1;
 +            goto exit;
 +        }
 +    } else {  /* EA_RDWR */
 +        /* write lock */
 +        if ((write_lock(ea->ea_fd, 0, SEEK_SET, 0)) != 0) {
 +            LOG(log_error, logtype_afpd, "ea_open: lock error on  header: %s", eaname);
 +            ret = -1;
 +            goto exit;
 +        }
 +    }
 +
 +    /* read it */
 +    if (read(ea->ea_fd, ea->ea_data, ea->ea_size) != (ssize_t)ea->ea_size) {
 +        LOG(log_error, logtype_afpd, "ea_open: short read on header: %s", eaname);
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +    if ((unpack_header(ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_open: error unpacking header for: %s", eaname);
 +        ret = -1;
 +        goto exit;
 +    }
 +
 +exit:
 +    switch (ret) {
 +    case 0:
 +        ea->ea_inited = EA_INITED;
 +        break;
 +    case -1:
 +        errno = EFAULT; /* force some errno distinguishable from ENOENT */
 +        /* fall through */
 +    case -2:
 +        if (ea->ea_data) {
 +            free(ea->ea_data);
 +            ea->ea_data = NULL;
 +        }
 +        if (ea->ea_fd) {
 +            close(ea->ea_fd);
 +            ea->ea_fd = -1;
 +        }
 +        break;
 +    }
 +
 +    return ret;
 +}
 +
 +/*
 + * Function: ea_openat
 + *
 + * Purpose: openat like wrapper for ea_open, takes a additional file descriptor
 + *
 + * Arguments:
 + *
 + *    vol         (r) current volume
 + *    sfd         (r) openat like file descriptor
 + *    uname       (r) filename for which we have to open a header
 + *    flags       (r) EA_CREATE: create if it doesn't exist (without it won't be created)
 + *                    EA_RDONLY: open read only
 + *                    EA_RDWR: open read/write
 + *                    Eiterh EA_RDONLY or EA_RDWR MUST be requested
 + *    ea          (w) pointer to a struct ea that we fill
 + *
 + * Returns: 0 on success
 + *         -1 on misc error with errno = EFAULT
 + *         -2 if no EA header exists with errno = ENOENT
 + *
 + * Effects:
 + *
 + * opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size.
 + * number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags.
 + * file is either read or write locked depending on the open flags.
 + * When you're done with struct ea you must call ea_close on it.
 + */
 +int ea_openat(const struct vol * restrict vol,
 +              int dirfd,
 +              const char * restrict uname,
 +              eaflags_t eaflags,
 +              struct ea * restrict ea)
 +{
 +    int ret = 0;
 +    int cwdfd = -1;
 +
 +    if (dirfd != -1) {
 +        if (((cwdfd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
 +            ret = -1;
 +            goto exit;
 +        }
 +    }
 +
 +    ret = ea_open(vol, uname, eaflags, ea);
 +    ea->dirfd = dirfd;
 +
 +    if (dirfd != -1) {
 +        if (fchdir(cwdfd) != 0) {
 +            LOG(log_error, logtype_afpd, "ea_openat: cant chdir back, exiting");
 +            exit(EXITERR_SYS);
 +        }
 +    }
 +
 +
 +exit:
 +    if (cwdfd != -1)
 +        close(cwdfd);
 +
 +    return ret;
 +
 +}
 +
 +/*
 + * Function: ea_close
 + *
 + * Purpose: flushes and closes an ea handle
 + *
 + * Arguments:
 + *
 + *    ea          (rw) pointer to ea handle
 + *
 + * Returns: 0 on success, -1 on error
 + *
 + * Effects:
 + *
 + * Flushes and then closes and frees all resouces held by ea handle.
 + * Pack data in ea into ea_data, then write ea_data to disk
 + */
 +int ea_close(struct ea * restrict ea)
 +{
 +    int ret = 0; 
 +    unsigned int count = 0;
 +    char *eaname;
 +    struct stat st;
 +
 +    LOG(log_debug, logtype_afpd, "ea_close('%s')", ea->filename);
 +
 +    if (ea->ea_inited != EA_INITED) {
 +        LOG(log_warning, logtype_afpd, "ea_close('%s'): non initialized ea", ea->filename);
 +        return 0;
 +    }
 +
 +    /* pack header and write it to disk if it was opened EA_RDWR*/
 +    if (ea->ea_flags & EA_RDWR) {
 +        if ((pack_header(ea)) != 0) {
 +            LOG(log_error, logtype_afpd, "ea_close: pack header");
 +            ret = -1;
 +        } else {
 +            if (ea->ea_count == 0) {
 +                /* Check if EA header exists and remove it */
 +                eaname = ea_path(ea, NULL, 0);
 +                if ((lstatat(ea->dirfd, eaname, &st)) == 0) {
 +                    if ((netatalk_unlinkat(ea->dirfd, eaname)) != 0) {
 +                        LOG(log_error, logtype_afpd, "ea_close('%s'): unlink: %s",
 +                            eaname, strerror(errno));
 +                        ret = -1;
 +                    }
 +                    else
 +                        LOG(log_debug, logtype_afpd, "ea_close(unlink '%s'): success", eaname);
 +                } else {
 +                    /* stat error */
 +                    if (errno != ENOENT) {
 +                        LOG(log_error, logtype_afpd, "ea_close('%s'): stat: %s",
 +                            eaname, strerror(errno));
 +                        ret = -1;
 +                    }
 +                }
 +            } else { /* ea->ea_count > 0 */
 +                if ((lseek(ea->ea_fd, 0, SEEK_SET)) == -1) {
 +                    LOG(log_error, logtype_afpd, "ea_close: lseek: %s", strerror(errno));
 +                    ret = -1;
 +                    goto exit;
 +                }
 +
 +                if ((ftruncate(ea->ea_fd, 0)) == -1) {
 +                    LOG(log_error, logtype_afpd, "ea_close: ftruncate: %s", strerror(errno));
 +                    ret = -1;
 +                    goto exit;
 +                }
 +
 +                if (write(ea->ea_fd, ea->ea_data, ea->ea_size) != (ssize_t)ea->ea_size) {
 +                    LOG(log_error, logtype_afpd, "ea_close: write: %s", strerror(errno));
 +                    ret = -1;
 +                }
 +            }
 +        }
 +    }
 +
 +exit:
 +    /* free names */
 +    while(count < ea->ea_count) {
 +        if ( (*ea->ea_entries)[count].ea_name ) {
 +            free((*ea->ea_entries)[count].ea_name);
 +            (*ea->ea_entries)[count].ea_name = NULL;
 +        }
 +        count++;
 +    }
 +    ea->ea_count = 0;
 +
 +    if (ea->filename) {
 +        free(ea->filename);
 +        ea->filename = NULL;
 +    }
 +
 +    if (ea->ea_entries) {
 +        free(ea->ea_entries);
 +        ea->ea_entries = NULL;
 +    }
 +
 +    if (ea->ea_data) {
 +        free(ea->ea_data);
 +        ea->ea_data = NULL;
 +    }
 +    if (ea->ea_fd != -1) {
 +        close(ea->ea_fd);       /* also releases the fcntl lock */
 +        ea->ea_fd = -1;
 +    }
 +
 +    return 0;
 +}
 +
 +
 +
 +/************************************************************************************
 + * VFS funcs called from afp_ea* funcs
 + ************************************************************************************/
 +
 +/*
 + * Function: get_easize
 + *
 + * Purpose: get size of an EA
 + *
 + * Arguments:
 + *
 + *    vol          (r) current volume
 + *    rbuf         (w) DSI reply buffer
 + *    rbuflen      (rw) current length of data in reply buffer
 + *    uname        (r) filename
 + *    oflag        (r) link and create flag
 + *    attruname    (r) name of attribute
 + *
 + * Returns: AFP code: AFP_OK on success or appropiate AFP error code
 + *
 + * Effects:
 + *
 + * Copies EA size into rbuf in network order. Increments *rbuflen +4.
 + */
 +int get_easize(VFS_FUNC_ARGS_EA_GETSIZE)
 +{
 +    int ret = AFPERR_MISC;
 +    unsigned int count = 0;
 +    uint32_t uint32;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "get_easize: file: %s", uname);
 +
 +    if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) {
 +        if (errno != ENOENT)
 +            LOG(log_error, logtype_afpd, "get_easize: error calling ea_open for file: %s", uname);
 +
 +        memset(rbuf, 0, 4);
 +        *rbuflen += 4;
 +        return ret;
 +    }
 +
 +    while (count < ea.ea_count) {
 +        if (strcmp(attruname, (*ea.ea_entries)[count].ea_name) == 0) {
 +            uint32 = htonl((*ea.ea_entries)[count].ea_size);
 +            memcpy(rbuf, &uint32, 4);
 +            *rbuflen += 4;
 +            ret = AFP_OK;
 +
 +            LOG(log_debug, logtype_afpd, "get_easize(\"%s\"): size: %u",
 +                attruname, (*ea.ea_entries)[count].ea_size);
 +            break;
 +        }
 +        count++;
 +    }
 +
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "get_easize: error closing ea handle for file: %s", uname);
 +        return AFPERR_MISC;
 +    }
 +
 +    return ret;
 +}
 +
 +/*
 + * Function: get_eacontent
 + *
 + * Purpose: copy EA into rbuf
 + *
 + * Arguments:
 + *
 + *    vol          (r) current volume
 + *    rbuf         (w) DSI reply buffer
 + *    rbuflen      (rw) current length of data in reply buffer
 + *    uname        (r) filename
 + *    oflag        (r) link and create flag
 + *    attruname    (r) name of attribute
 + *    maxreply     (r) maximum EA size as of current specs/real-life
 + *
 + * Returns: AFP code: AFP_OK on success or appropiate AFP error code
 + *
 + * Effects:
 + *
 + * Copies EA into rbuf. Increments *rbuflen accordingly.
 + */
 +int get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT)
 +{
 +    int ret = AFPERR_MISC, fd = -1;
 +    unsigned int count = 0;
 +    uint32_t uint32;
 +    size_t toread;
 +    struct ea ea;
 +    char *eafile;
 +
 +    LOG(log_debug, logtype_afpd, "get_eacontent('%s/%s')", uname, attruname);
 +
 +    if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) {
 +        if (errno != ENOENT)
 +            LOG(log_error, logtype_afpd, "get_eacontent('%s'): ea_open error", uname);
 +        memset(rbuf, 0, 4);
 +        *rbuflen += 4;
 +        return ret;
 +    }
 +
 +    while (count < ea.ea_count) {
 +        if (strcmp(attruname, (*ea.ea_entries)[count].ea_name) == 0) {
 +            if ( (eafile = ea_path(&ea, attruname, 1)) == NULL) {
 +                ret = AFPERR_MISC;
 +                break;
 +            }
 +
 +            if ((fd = open(eafile, O_RDONLY)) == -1) {
 +                LOG(log_error, logtype_afpd, "get_eacontent('%s'): open error: %s", uname, strerror(errno));
 +                ret = AFPERR_MISC;
 +                break;
 +            }
 +
 +            /* Check how much the client wants, give him what we think is right */
 +            maxreply -= MAX_REPLY_EXTRA_BYTES;
 +            if (maxreply > MAX_EA_SIZE)
 +                maxreply = MAX_EA_SIZE;
 +            toread = (maxreply < (*ea.ea_entries)[count].ea_size) ? maxreply : (*ea.ea_entries)[count].ea_size;
 +            LOG(log_debug, logtype_afpd, "get_eacontent('%s'): sending %u bytes", attruname, toread);
 +
 +            /* Put length of EA data in reply buffer */
 +            uint32 = htonl(toread);
 +            memcpy(rbuf, &uint32, 4);
 +            rbuf += 4;
 +            *rbuflen += 4;
 +
 +            if (read(fd, rbuf, toread) != (ssize_t)toread) {
 +                LOG(log_error, logtype_afpd, "get_eacontent('%s/%s'): short read", uname, attruname);
 +                close(fd);
 +                ret = AFPERR_MISC;
 +                break;
 +            }
 +            *rbuflen += toread;
 +            close(fd);
 +
 +            ret = AFP_OK;
 +            break;
 +        }
 +        count++;
 +    }
 +
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "get_eacontent('%s'): error closing ea handle", uname);
 +        return AFPERR_MISC;
 +    }
 +
 +    return ret;
 +
 +}
 +
 +/*
 + * Function: list_eas
 + *
 + * Purpose: copy names of EAs into attrnamebuf
 + *
 + * Arguments:
 + *
 + *    vol          (r) current volume
 + *    attrnamebuf  (w) store names a consecutive C strings here
 + *    buflen       (rw) length of names in attrnamebuf
 + *    uname        (r) filename
 + *    oflag        (r) link and create flag
 + *
 + * Returns: AFP code: AFP_OK on success or appropiate AFP error code
 + *
 + * Effects:
 + *
 + * Copies names of all EAs of uname as consecutive C strings into rbuf.
 + * Increments *buflen accordingly.
 + */
 +int list_eas(VFS_FUNC_ARGS_EA_LIST)
 +{
 +    unsigned int count = 0;
 +    int attrbuflen = *buflen, ret = AFP_OK, len;
 +    char *buf = attrnamebuf;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "list_eas: file: %s", uname);
 +
 +    if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) {
 +        if (errno != ENOENT) {
 +            LOG(log_error, logtype_afpd, "list_eas: error calling ea_open for file: %s", uname);
 +            return AFPERR_MISC;
 +        }
 +        else
 +            return AFP_OK;
 +    }
 +
 +    while (count < ea.ea_count) {
 +        /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */
 +        if ( ( len = convert_string(vol->v_volcharset,
 +                                    CH_UTF8_MAC, 
 +                                    (*ea.ea_entries)[count].ea_name,
 +                                    (*ea.ea_entries)[count].ea_namelen,
 +                                    buf + attrbuflen,
 +                                    255))
 +             <= 0 ) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +        if (len == 255)
 +            /* convert_string didn't 0-terminate */
 +            attrnamebuf[attrbuflen + 255] = 0;
 +
 +        LOG(log_debug7, logtype_afpd, "list_eas(%s): EA: %s",
 +            uname, (*ea.ea_entries)[count].ea_name);
 +
 +        attrbuflen += len + 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, "list_eas(%s): running out of buffer for EA names", uname);
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +        count++;
 +    }
 +
 +exit:
 +    *buflen = attrbuflen;
 +
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "list_eas: error closing ea handle for file: %s", uname);
 +        return AFPERR_MISC;
 +    }
 +
 +    return ret;
 +}
 +
 +/*
 + * Function: set_ea
 + *
 + * Purpose: set a Solaris native EA
 + *
 + * Arguments:
 + *
 + *    vol          (r) current volume
 + *    uname        (r) filename
 + *    attruname    (r) EA name
 + *    ibuf         (r) buffer with EA content
 + *    attrsize     (r) length EA in ibuf
 + *    oflag        (r) link and create flag
 + *
 + * Returns: AFP code: AFP_OK on success or appropiate AFP error code
 + *
 + * Effects:
 + *
 + * Copies names of all EAs of uname as consecutive C strings into rbuf.
 + * Increments *rbuflen accordingly.
 + */
 +int set_ea(VFS_FUNC_ARGS_EA_SET)
 +{
 +    int ret = AFP_OK;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "set_ea: file: %s", uname);
 +
 +    if ((ea_open(vol, uname, EA_CREATE | EA_RDWR, &ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "set_ea('%s'): ea_open error", uname);
 +        return AFPERR_MISC;
 +    }
 +
 +    if ((ea_addentry(&ea, attruname, attrsize, oflag)) == -1) {
 +        LOG(log_error, logtype_afpd, "set_ea('%s'): ea_addentry error", uname);
 +        ret = AFPERR_MISC;
 +        goto exit;
 +    }
 +
 +    if ((write_ea(&ea, attruname, ibuf, attrsize)) != 0) {
 +        LOG(log_error, logtype_afpd, "set_ea('%s'): write_ea error", uname);
 +        ret = AFPERR_MISC;
 +        goto exit;
 +    }
 +
 +exit:
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "set_ea('%s'): ea_close error", uname);
 +        ret = AFPERR_MISC;
 +        goto exit;
 +    }
 +
 +    return ret;
 +}
 +
 +/*
 + * Function: remove_ea
 + *
 + * Purpose: remove a EA from a file
 + *
 + * Arguments:
 + *
 + *    vol          (r) current volume
 + *    uname        (r) filename
 + *    attruname    (r) EA name
 + *    oflag        (r) link and create flag
 + *
 + * Returns: AFP code: AFP_OK on success or appropiate AFP error code
 + *
 + * Effects:
 + *
 + * Removes EA attruname from file uname.
 + */
 +int remove_ea(VFS_FUNC_ARGS_EA_REMOVE)
 +{
 +    int ret = AFP_OK;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "remove_ea('%s/%s')", uname, attruname);
 +
 +    if ((ea_open(vol, uname, EA_RDWR, &ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_open error", uname);
 +        return AFPERR_MISC;
 +    }
 +
 +    if ((ea_delentry(&ea, attruname)) == -1) {
 +        LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_delentry error", uname);
 +        ret = AFPERR_MISC;
 +        goto exit;
 +    }
 +
 +    if ((delete_ea_file(&ea, attruname)) != 0) {
 +        LOG(log_error, logtype_afpd, "remove_ea('%s'): delete_ea error", uname);
 +        ret = AFPERR_MISC;
 +        goto exit;
 +    }
 +
 +exit:
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_close error", uname);
 +        ret = AFPERR_MISC;
 +        goto exit;
 +    }
 +
 +    return ret;
 +}
 +
 +/******************************************************************************************
 + * EA VFS funcs that deal with file/dir cp/mv/rm
 + ******************************************************************************************/
 +
 +int ea_deletefile(VFS_FUNC_ARGS_DELETEFILE)
 +{
 +    unsigned int count = 0;
 +    int ret = AFP_OK;
 +    int cwd = -1;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "ea_deletefile('%s')", file);
 +
 +    /* Open EA stuff */
 +    if ((ea_openat(vol, dirfd, file, EA_RDWR, &ea)) != 0) {
 +        if (errno == ENOENT)
 +            /* no EA files, nothing to do */
 +            return AFP_OK;
 +        else {
 +            LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error calling ea_open", file);
 +            return AFPERR_MISC;
 +        }
 +    }
 +
 +    if (dirfd != -1) {
 +        if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +    }
 +
 +    while (count < ea.ea_count) {
 +        if ((delete_ea_file(&ea, (*ea.ea_entries)[count].ea_name)) != 0) {
 +            ret = AFPERR_MISC;
 +            continue;
 +        }
 +        free((*ea.ea_entries)[count].ea_name);
 +        (*ea.ea_entries)[count].ea_name = NULL;
 +        count++;
 +    }
 +
 +    /* ea_close removes the EA header file for us because all names are NULL */
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error closing ea handle", file);
 +        ret = AFPERR_MISC;
 +    }
 +
 +    if (dirfd != -1 && fchdir(cwd) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_deletefile: cant chdir back. exit!");
 +        exit(EXITERR_SYS);
 +    }
 +
 +exit:
 +    if (cwd != -1)
 +        close(cwd);
 +
 +    return ret;
 +}
 +
 +int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE)
 +{
 +    unsigned int count = 0;
 +    int    ret = AFP_OK;
 +    size_t easize;
 +    char   srceapath[ MAXPATHLEN + 1];
 +    char   *eapath;
 +    char   *eaname;
 +    struct ea srcea;
 +    struct ea dstea;
 +    struct adouble ad;
 +
 +    LOG(log_debug, logtype_afpd, "ea_renamefile('%s'/'%s')", src, dst);
 +            
 +
 +    /* Open EA stuff */
 +    if ((ea_openat(vol, dirfd, src, EA_RDWR, &srcea)) != 0) {
 +        if (errno == ENOENT)
 +            /* no EA files, nothing to do */
 +            return AFP_OK;
 +        else {
 +            LOG(log_error, logtype_afpd, "ea_renamefile('%s'/'%s'): ea_open error: '%s'", src, dst, src);
 +            return AFPERR_MISC;
 +        }
 +    }
 +
 +    if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
 +        if (errno == ENOENT) {
 +            /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
 +            ad_init(&ad, vol->v_adouble, vol->v_ad_options); 
 +            if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) {
 +                LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): ad_open error: '%s'", src, dst, dst);
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +            ad_close(&ad, ADFLAGS_HF);
 +            if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +        }
 +    }
 +
 +    /* Loop through all EAs: */
 +    while (count < srcea.ea_count) {
 +        /* Move EA */
 +        eaname = (*srcea.ea_entries)[count].ea_name;
 +        easize = (*srcea.ea_entries)[count].ea_size;
 +
 +        /* Build src and dst paths for rename() */
 +        if ((eapath = ea_path(&srcea, eaname, 1)) == NULL) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +        strcpy(srceapath, eapath);
 +        if ((eapath = ea_path(&dstea, eaname, 1)) == NULL) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +
 +        LOG(log_maxdebug, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
 +            src, dst, srceapath, eapath);
 +
 +        /* Add EA to dstea */
 +        if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) {
 +            LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
 +                src, dst, srceapath, eapath);
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +
 +        /* Remove EA entry from srcea */
 +        if ((ea_delentry(&srcea, eaname)) == -1) {
 +            LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
 +                src, dst, srceapath, eapath);
 +            ea_delentry(&dstea, eaname);
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +
 +        /* Now rename the EA */
 +        if ((unix_rename(dirfd, srceapath, -1, eapath)) < 0) {
 +            LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
 +                src, dst, srceapath, eapath);
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +
 +        count++;
 +    }
 +
 +
 +exit:
 +    ea_close(&srcea);
 +    ea_close(&dstea);
 +      return ret;
 +}
 +
 +int ea_copyfile(VFS_FUNC_ARGS_COPYFILE)
 +{
 +    unsigned int count = 0;
 +    int    ret = AFP_OK;
 +    size_t easize;
 +    char   srceapath[ MAXPATHLEN + 1];
 +    char   *eapath;
 +    char   *eaname;
 +    struct ea srcea;
 +    struct ea dstea;
 +    struct adouble ad;
 +
 +    LOG(log_debug, logtype_afpd, "ea_copyfile('%s'/'%s')", src, dst);
 +
 +    /* Open EA stuff */
 +    if ((ea_openat(vol, sfd, src, EA_RDWR, &srcea)) != 0) {
 +        if (errno == ENOENT)
 +            /* no EA files, nothing to do */
 +            return AFP_OK;
 +        else {
 +            LOG(log_error, logtype_afpd, "ea_copyfile('%s'/'%s'): ea_open error: '%s'", src, dst, src);
 +            return AFPERR_MISC;
 +        }
 +    }
 +
 +    if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
 +        if (errno == ENOENT) {
 +            /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
 +            ad_init(&ad, vol->v_adouble, vol->v_ad_options); 
 +            if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) {
 +                LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ad_open error: '%s'", src, dst, dst);
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +            ad_close(&ad, ADFLAGS_HF);
 +            if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +        }
 +    }
 +
 +    /* Loop through all EAs: */
 +    while (count < srcea.ea_count) {
 +        /* Copy EA */
 +        eaname = (*srcea.ea_entries)[count].ea_name;
 +        easize = (*srcea.ea_entries)[count].ea_size;
 +
 +        /* Build src and dst paths for copy_file() */
 +        if ((eapath = ea_path(&srcea, eaname, 1)) == NULL) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +        strcpy(srceapath, eapath);
 +        if ((eapath = ea_path(&dstea, eaname, 1)) == NULL) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +
 +        LOG(log_maxdebug, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'",
 +            src, dst, srceapath, eapath);
 +
 +        /* Add EA to dstea */
 +        if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) {
 +            LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ea_addentry('%s') error",
 +                src, dst, eaname);
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +
 +        /* Now copy the EA */
 +        if ((copy_file(sfd, srceapath, eapath, (0666 & ~vol->v_umask))) < 0) {
 +            LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'",
 +                src, dst, srceapath, eapath);
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +
 +        count++;
 +    }
 +
 +exit:
 +    ea_close(&srcea);
 +    ea_close(&dstea);
 +      return ret;
 +}
 +
 +int ea_chown(VFS_FUNC_ARGS_CHOWN)
 +{
 +
 +    unsigned int count = 0;
 +    int ret = AFP_OK;
 +    char *eaname;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "ea_chown('%s')", path);
 +    /* Open EA stuff */
 +    if ((ea_open(vol, path, EA_RDWR, &ea)) != 0) {
 +        if (errno == ENOENT)
 +            /* no EA files, nothing to do */
 +            return AFP_OK;
 +        else {
 +            LOG(log_error, logtype_afpd, "ea_chown('%s'): error calling ea_open", path);
 +            return AFPERR_MISC;
 +        }
 +    }
 +
 +    if ((lchown(ea_path(&ea, NULL, 0), uid, gid)) != 0) {
 +        switch (errno) {
 +        case EPERM:
 +        case EACCES:
 +            ret = AFPERR_ACCESS;
 +            goto exit;
 +        default:
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +    }
 +
 +    while (count < ea.ea_count) {
 +        if ((eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 1)) == NULL) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +        if ((lchown(eaname, uid, gid)) != 0) {
 +            switch (errno) {
 +            case EPERM:
 +            case EACCES:
 +                ret = AFPERR_ACCESS;
 +                goto exit;
 +            default:
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +            continue;
 +        }
 +
 +        count++;
 +    }
 +
 +exit:
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_chown('%s'): error closing ea handle", path);
 +        return AFPERR_MISC;
 +    }
 +
 +    return ret;
 +}
 +
 +int ea_chmod_file(VFS_FUNC_ARGS_SETFILEMODE)
 +{
 +
 +    unsigned int count = 0;
 +    int ret = AFP_OK;
 +    const char *eaname;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "ea_chmod_file('%s')", name);
 +    /* Open EA stuff */
 +    if ((ea_open(vol, name, EA_RDWR, &ea)) != 0) {
 +        if (errno == ENOENT)
 +            /* no EA files, nothing to do */
 +            return AFP_OK;
 +        else
 +            return AFPERR_MISC;
 +    }
 +
 +    /* Set mode on EA header file */
 +    if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
 +        switch (errno) {
 +        case EPERM:
 +        case EACCES:
 +            ret = AFPERR_ACCESS;
 +            goto exit;
 +        default:
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +    }
 +
 +    /* Set mode on EA files */
 +    while (count < ea.ea_count) {
 +        if ((eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 1)) == NULL) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +        if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
 +            LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", eaname, strerror(errno));
 +            switch (errno) {
 +            case EPERM:
 +            case EACCES:
 +                ret = AFPERR_ACCESS;
 +                goto exit;
 +            default:
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +            continue;
 +        }
 +
 +        count++;
 +    }
 +
 +exit:
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): error closing ea handle", name);
 +        return AFPERR_MISC;
 +    }
 +
 +    return ret;
 +}
 +
 +int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE)
 +{
 +
 +    int ret = AFP_OK;
 +    unsigned int count = 0;
 +    uid_t uid;
 +    const char *eaname;
 +    const char *eaname_safe = NULL;
 +    struct ea ea;
 +
 +    LOG(log_debug, logtype_afpd, "ea_chmod_dir('%s')", name);
 +    /* .AppleDouble already might be inaccesible, so we must run as id 0 */
 +    uid = geteuid();
 +    if (seteuid(0)) {
 +        LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): seteuid: %s", name, strerror(errno));
 +        return AFPERR_MISC;
 +    }
 +
 +    /* Open EA stuff */
 +    if ((ea_open(vol, name, EA_RDWR, &ea)) != 0) {
 +        /* ENOENT --> no EA files, nothing to do */
 +        if (errno != ENOENT)
 +            ret = AFPERR_MISC;
 +        if (seteuid(uid) < 0) {
 +            LOG(log_error, logtype_afpd, "can't seteuid back: %s", strerror(errno));
 +            exit(EXITERR_SYS);
 +        }
 +        return ret;
 +    }
 +
 +    /* Set mode on EA header */
 +    if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
 +        switch (errno) {
 +        case EPERM:
 +        case EACCES:
 +            ret = AFPERR_ACCESS;
 +            goto exit;
 +        default:
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +    }
 +
 +    /* Set mode on EA files */
 +    while (count < ea.ea_count) {
 +        eaname = (*ea.ea_entries)[count].ea_name;
 +        /*
 +         * Be careful with EA names from the EA header!
 +         * Eg NFS users might have access to them, can inject paths using ../ or /.....
 +         * FIXME:
 +         * Until the EA code escapes / in EA name requests from the client, these therefor wont work.
 +         */
 +        if ((eaname_safe = strrchr(eaname, '/'))) {
 +            LOG(log_warning, logtype_afpd, "ea_chmod_dir('%s'): contains a slash", eaname);
 +            eaname = eaname_safe;
 +        }
 +        if ((eaname = ea_path(&ea, eaname, 1)) == NULL) {
 +            ret = AFPERR_MISC;
 +            goto exit;
 +        }
 +        if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
 +            LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", eaname, strerror(errno));
 +            switch (errno) {
 +            case EPERM:
 +            case EACCES:
 +                ret = AFPERR_ACCESS;
 +                goto exit;
 +            default:
 +                ret = AFPERR_MISC;
 +                goto exit;
 +            }
 +            continue;
 +        }
 +
 +        count++;
 +    }
 +
 +exit:
 +    if (seteuid(uid) < 0) {
 +        LOG(log_error, logtype_afpd, "can't seteuid back: %s", strerror(errno));
 +        exit(EXITERR_SYS);
 +    }
 +
 +    if ((ea_close(&ea)) != 0) {
 +        LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): error closing ea handle", name);
 +        return AFPERR_MISC;
 +    }
 +
 +    return ret;
 +}
diff --combined libatalk/vfs/unix.c
index 5e0588dfd171bf54e9b6b7410c292639aaeabb1b,ffb524b825d88e7b2444a8e5cf742eaf4d5834d6..14a0f1647dec29ad31974533de1561c8bc9242c7
@@@ -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,11 -32,34 +33,11 @@@ 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_acl( 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.
       */
-     if ( (chmod( name, (DIRBITS | mode) & ~v_umask ) < 0) && errno != EPERM &&
+     if ( (chmod_acl( name, (DIRBITS | mode) & ~v_umask ) < 0) && errno != EPERM &&
           !(errno == ENOENT && (dropbox & AFPVOL_NOADOUBLE)) )
      {
          LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) );
@@@ -70,7 -92,7 +70,7 @@@ int setfilmode(const char * name, mode_
      
      mode |= st->st_mode & ~mask; /* keep other bits from previous mode */
  
-     if ( chmod( name,  mode & ~v_umask ) < 0 && errno != EPERM ) {
+     if ( chmod_acl( name,  mode & ~v_umask ) < 0 && errno != EPERM ) {
          return -1;
      }
      return 0;
@@@ -146,21 -168,6 +146,6 @@@ int netatalk_unlink(const char *name
      return AFP_OK;
  }
  
- char *fullpathname(const char *name)
- {
-     static char wd[ MAXPATHLEN + 1];
-     if ( getcwd( wd , MAXPATHLEN) ) {
-         strlcat(wd, "/", MAXPATHLEN);
-         strlcat(wd, name, MAXPATHLEN);
-     }
-     else {
-         strlcpy(wd, name, MAXPATHLEN);
-     }
-     return wd;
- }
  /**************************************************************************
   * *at semnatics support functions (like openat, renameat standard funcs)
   **************************************************************************/
@@@ -185,13 -192,13 +170,13 @@@ int copy_file(int dirfd, const char *sr
      sfd = open(src, O_RDONLY);
  #endif
      if (sfd < 0) {
-         LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
+         LOG(log_info, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
              src, dst, src, strerror(errno));
          return -1;
      }
  
      if ((dfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0) {
-         LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
+         LOG(log_info, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
              src, dst, dst, strerror(errno));
          ret = -1;
          goto exit;
diff --combined libatalk/vfs/vfs.c
index 0eaacfaee8af8fc5f6babb34709d2e7f7c8022f9,0999b878a8c37c800660e3ffb6945893e78623fe..b33138bc26ab22efe1fbd4d795b9a1b467f18c3c
@@@ -42,7 -42,6 +42,7 @@@
  #include <atalk/errchk.h>
  #include <atalk/bstrlib.h>
  #include <atalk/bstradd.h>
 +#include <atalk/compat.h>
  
  struct perm {
      uid_t uid;
@@@ -115,7 -114,7 +115,7 @@@ static int validupath_adouble(VFS_FUNC_
  static int RF_chown_adouble(VFS_FUNC_ARGS_CHOWN)
  {
      struct stat st;
 -    char        *ad_p;
 +    const char *ad_p;
  
      ad_p = vol->ad_path(path, ADFLAGS_HF );
  
@@@ -174,7 -173,7 +174,7 @@@ static int RF_setfilmode_adouble(VFS_FU
  /* ----------------- */
  static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE)
  {
 -    char *adouble = vol->ad_path(name, ADFLAGS_DIR );
 +    const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
      int  dropbox = vol->v_flags;
  
      if (dir_rx_set(mode)) {
@@@ -215,8 -214,8 +215,8 @@@ static int RF_setdirmode_adouble(VFS_FU
  {
      int   dropbox = vol->v_flags;
      mode_t hf_mode = ad_hf_mode(mode);
 -    char  *adouble = vol->ad_path(name, ADFLAGS_DIR );
 -    char  *adouble_p = ad_dir(adouble);
 +    const char  *adouble = vol->ad_path(name, ADFLAGS_DIR );
 +    const char  *adouble_p = ad_dir(adouble);
  
      if (dir_rx_set(mode)) {
          if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox, vol->v_umask) < 0) 
@@@ -309,7 -308,7 +309,7 @@@ static int RF_renamefile_adouble(VFS_FU
               * use a diff one, it's not a pb,ie it's not the same file, yet.
               */
              ad_init(&ad, vol->v_adouble, vol->v_ad_options); 
 -            if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
 +            if (ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) == 0) {
                ad_close(&ad, ADFLAGS_HF);
                if (!unix_rename(dirfd, adsrc, -1, vol->ad_path(dst, 0 )) ) 
                     err = 0;
@@@ -494,71 -493,368 +494,98 @@@ EC_CLEANUP
  }
  #endif
  
 -/*********************************************************************************
 - * sfm adouble format
 - *********************************************************************************/
 -static int ads_chown_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
 -{
 -    struct perm   *owner  = data;
 -    
 -    if (chown( name , owner->uid, owner->gid ) < 0) {
 -        return -1;
 -    }
 -    return 0;
 -}
 -
 -static int RF_chown_ads(VFS_FUNC_ARGS_CHOWN)
 -{
 -    struct        stat st;
 -    char          *ad_p;
 -    struct perm   owner;
 -    
 -    owner.uid = uid;
 -    owner.gid = gid;
 -
 -
 -    ad_p = ad_dir(vol->ad_path(path, ADFLAGS_HF ));
 -
 -    if ( stat( ad_p, &st ) < 0 ) {
 -      /* ignore */
 -        return 0;
 -    }
 -    
 -    if (chown( ad_p, uid, gid ) < 0) {
 -      return -1;
 -    }
 -    return for_each_adouble("chown_ads", ad_p, ads_chown_loop, &owner, 1, vol->v_umask);
 -}
 -
 -/* --------------------------------- */
 -static int deletecurdir_ads1_loop(struct dirent *de _U_, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
 -{
 -    return netatalk_unlink(name);
 -}
 -
 -static int ads_delete_rf(char *name)
 -{
 -    int err;
 -
 -    if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0))) 
 -        return err;
 -    /* FIXME 
 -     * it's a problem for a nfs mounted folder, there's .nfsxxx around
 -     * for linux the following line solve it.
 -     * but it could fail if rm .nfsxxx  create a new .nfsyyy :(
 -    */
 -    if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0))) 
 -        return err;
 -    return netatalk_rmdir(-1, name);
 -}
 -
 -static int deletecurdir_ads_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
 -{
 -    struct stat st;
 -    
 -    /* bail if the file exists in the current directory.
 -     * note: this will not fail with dangling symlinks */
 -    
 -    if (stat(de->d_name, &st) == 0) {
 -        return AFPERR_DIRNEMPT;
 -    }
 -    return ads_delete_rf(name);
 -}
 -
 -static int RF_deletecurdir_ads(VFS_FUNC_ARGS_DELETECURDIR)
 -{
 -    int err;
 -
 -    /* delete stray .AppleDouble files. this happens to get .Parent files as well. */
 -    if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_ads_loop, NULL, 1, 0))) 
 -        return err;
 -
 -    return netatalk_rmdir(-1, ".AppleDouble" );
 -}
 -
 -/* ------------------- */
 -struct set_mode {
 -    mode_t mode;
 -    struct stat *st;
 -};
 -
 -static int ads_setfilmode_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask)
 +/*************************************************************************
 + * EA adouble format 
 + ************************************************************************/
 +static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH)
  {
 -    struct set_mode *param = data;
 -
 -    return setfilmode(name, param->mode, param->st, v_umask);
 -}
 +    return 1;
 +}             
  
 -static int ads_setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
 +/* ----------------- */
 +static int RF_chown_ea(VFS_FUNC_ARGS_CHOWN)
  {
+     mode_t file_mode = ad_hf_mode(mode);
+     mode_t dir_mode = file_mode;
+     struct set_mode param;
+     if ((dir_mode & (S_IRUSR | S_IWUSR )))
+         dir_mode |= S_IXUSR;
+     if ((dir_mode & (S_IRGRP | S_IWGRP )))
+         dir_mode |= S_IXGRP;
+     if ((dir_mode & (S_IROTH | S_IWOTH )))
+         dir_mode |= S_IXOTH;
+       /* change folder */
+       dir_mode |= DIRBITS;
+     if (dir_rx_set(dir_mode)) {
+         if (chmod_acl( name,  dir_mode ) < 0)
+             return -1;
+     }
+     param.st = st;
+     param.mode = file_mode;
+     if (for_each_adouble("setfilmode_ads", name, ads_setfilmode_loop, &param, 0, v_umask) < 0)
+         return -1;
+     if (!dir_rx_set(dir_mode)) {
+         if (chmod_acl( name,  dir_mode ) < 0)
+             return -1;
+     }
      return 0;
  }
  
 -static int RF_setfilmode_ads(VFS_FUNC_ARGS_SETFILEMODE)
 +/* ---------------- */
 +static int RF_renamedir_ea(VFS_FUNC_ARGS_RENAMEDIR)
  {
 -    return ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_HF )), mode, st, vol->v_umask);
 +    return 0;
  }
  
 -/* ------------------- */
 -static int RF_setdirunixmode_ads(VFS_FUNC_ARGS_SETDIRUNIXMODE)
 +/* ---------------- */
 +static int RF_deletecurdir_ea(VFS_FUNC_ARGS_DELETECURDIR)
  {
 -    char *adouble = vol->ad_path(name, ADFLAGS_DIR );
 -    char   ad_p[ MAXPATHLEN + 1];
 -    int dropbox = vol->v_flags;
 -
 -    strlcpy(ad_p,ad_dir(adouble), MAXPATHLEN + 1);
 -
 -    if (dir_rx_set(mode)) {
 -
 -        /* .AppleDouble */
 -        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0) 
 -            return -1;
 -
 -        /* .AppleDouble/.Parent */
 -        if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0) 
 -            return -1;
 -    }
 -
 -    if (ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_DIR)), mode, st, vol->v_umask) < 0)
 -        return -1;
 -
 -    if (!dir_rx_set(mode)) {
 -        if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0) 
 -            return  -1 ;
 -        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0) 
 -            return -1;
 -    }
      return 0;
  }
  
 -/* ------------------- */
 -struct dir_mode {
 -    mode_t mode;
 -    int    dropbox;
 -};
 -
 -static int setdirmode_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask)
 +/* ---------------- */
 +static int RF_setdirunixmode_ea(VFS_FUNC_ARGS_SETDIRUNIXMODE)
  {
 -
 -    struct dir_mode *param = data;
 -    int    ret = 0; /* 0 ignore error, -1 */
 -
 -    if (dir_rx_set(param->mode)) {
 -        if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
 -            if (flag) {
 -                return 0;
 -            }
 -            return ret;
 -        }
 -    }
 -    if (ads_setfilmode(name, param->mode, NULL, v_umask) < 0)
 -        return ret;
 -
 -    if (!dir_rx_set(param->mode)) {
 -        if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
 -            if (flag) {
 -                return 0;
 -            }
 -            return ret;
 -        }
 -    }
      return 0;
  }
  
 -static int RF_setdirmode_ads(VFS_FUNC_ARGS_SETDIRMODE)
 +static int RF_setfilmode_ea(VFS_FUNC_ARGS_SETFILEMODE)
  {
 -    char *adouble = vol->ad_path(name, ADFLAGS_DIR );
 -    char   ad_p[ MAXPATHLEN + 1];
 -    struct dir_mode param;
 -
 -    param.mode = mode;
 -    param.dropbox = vol->v_flags;
 -
 -    strlcpy(ad_p,ad_dir(adouble), sizeof(ad_p));
 -
 -    if (dir_rx_set(mode)) {
 -        /* .AppleDouble */
 -        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0) 
 -            return -1;
 -    }
 -
 -    if (for_each_adouble("setdirmode_ads", ad_dir(ad_p), setdirmode_ads_loop, &param, vol_noadouble(vol), vol->v_umask))
 -        return -1;
 -
 -    if (!dir_rx_set(mode)) {
 -        if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0 ) 
 -            return -1;
 -    }
      return 0;
  }
  
 -/* ------------------- */
 -static int setdirowner_ads1_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
 +/* ---------------- */
 +static int RF_setdirmode_ea(VFS_FUNC_ARGS_SETDIRMODE)
  {
 -    struct perm   *owner  = data;
 -
 -    if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
 -         LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
 -                owner->uid, owner->gid, fullpathname(name), strerror(errno) );
 -         /* return ( -1 ); Sometimes this is okay */
 -    }
      return 0;
  }
  
 -static int setdirowner_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask _U_)
 +/* ---------------- */
 +static int RF_setdirowner_ea(VFS_FUNC_ARGS_SETDIROWNER)
  {
 -    struct perm   *owner  = data;
 -
 -    if (for_each_adouble("setdirowner", name, setdirowner_ads1_loop, data, flag, 0) < 0)
 -        return -1;
 -
 -    if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
 -         LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
 -                owner->uid, owner->gid, fullpathname(name), strerror(errno) );
 -         /* return ( -1 ); Sometimes this is okay */
 -    }
 -    return 0;
 +      return 0;
  }
  
 -static int RF_setdirowner_ads(VFS_FUNC_ARGS_SETDIROWNER)
 +static int RF_deletefile_ea(VFS_FUNC_ARGS_DELETEFILE)
  {
 -    int           noadouble = vol_noadouble(vol);
 -    char          adouble_p[ MAXPATHLEN + 1];
 -    struct stat   st;
 -    struct perm   owner;
 -    
 -    owner.uid = uid;
 -    owner.gid = gid;
 -
 -    strlcpy(adouble_p, ad_dir(vol->ad_path(name, ADFLAGS_DIR )), sizeof(adouble_p));
 -
 -    if (for_each_adouble("setdirowner", ad_dir(adouble_p), setdirowner_ads_loop, &owner, noadouble, 0)) 
 -        return -1;
 -
 -    /*
 -     * We cheat: we know that chown doesn't do anything.
 -     */
 -    if ( stat( ".AppleDouble", &st ) < 0) {
 -        if (errno == ENOENT && noadouble)
 -            return 0;
 -        LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
 -        return -1;
 -    }
 -    if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 && errno != EPERM ) {
 -        LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
 -            uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
 -        /* return ( -1 ); Sometimes this is okay */
 -    }
      return 0;
  }
 -
 -/* ------------------- */
 -static int RF_deletefile_ads(VFS_FUNC_ARGS_DELETEFILE)
 +static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE)
  {
 -    int ret = 0;
 -    int cwd = -1;
 -    char *ad_p;
 -
 -    ad_p = ad_dir(vol->ad_path(file, ADFLAGS_HF ));
 -
 -    if (dirfd != -1) {
 -        if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
 -            ret = AFPERR_MISC;
 -            goto exit;
 -        }
 -    }
 -
 -    ret = ads_delete_rf(ad_p);
 -
 -    if (dirfd != -1 && fchdir(cwd) != 0) {
 -        LOG(log_error, logtype_afpd, "RF_deletefile_ads: cant chdir back. exit!");
 -        exit(EXITERR_SYS);
 -    }
 -
 -exit:
 -    if (cwd != -1)
 -        close(cwd);
 -
 -    return ret;
 +    return 0;
  }
  
 -/* --------------------------- */
 -static int RF_renamefile_ads(VFS_FUNC_ARGS_RENAMEFILE)
 +/* ---------------- */
 +static int RF_renamefile_ea(VFS_FUNC_ARGS_RENAMEFILE)
  {
 -    char  adsrc[ MAXPATHLEN + 1];
 -    int   err = 0;
 -
 -    strcpy( adsrc, ad_dir(vol->ad_path(src, 0 )));
 -    if (unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) < 0) {
 -        struct stat st;
 -
 -        err = errno;
 -        if (errno == ENOENT) {
 -              struct adouble    ad;
 -
 -            if (lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
 -                return 0;
 -            
 -            /* We are here  because :
 -             * -there's no dest folder. 
 -             * -there's no .AppleDouble in the dest folder.
 -             * if we use the struct adouble passed in parameter it will not
 -             * create .AppleDouble if the file is already opened, so we
 -             * use a diff one, it's not a pb,ie it's not the same file, yet.
 -             */
 -            ad_init(&ad, vol->v_adouble, vol->v_ad_options); 
 -            if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
 -              ad_close(&ad, ADFLAGS_HF);
 -
 -              /* We must delete it */
 -              RF_deletefile_ads(vol, -1, dst );
 -              if (!unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) ) 
 -                   err = 0;
 -                else 
 -                   err = errno;
 -            }
 -            else { /* it's something else, bail out */
 -                  err = errno;
 -              }
 -          }
 -      }
 -      if (err) {
 -              errno = err;
 -              return -1;
 -      }
 -      return 0;
 +    return 0;
  }
  
 +#if 0
  /*************************************************************************
   * osx adouble format 
   ************************************************************************/
@@@ -619,7 -915,6 +646,7 @@@ static int RF_renamefile_osx(VFS_FUNC_A
      }
      return 0;
  }
 +#endif
  
  /********************************************************************************************
   * VFS chaining
@@@ -708,10 -1003,10 +735,10 @@@ static struct vfs_ops vfs_master_funcs 
  };
  
  /* 
 - * Primary adouble modules: default, osx, sfm
 + * Primary adouble modules: v2, ea
   */
  
 -static struct vfs_ops netatalk_adouble = {
 +static struct vfs_ops netatalk_adouble_v2 = {
      /* vfs_validupath:    */ validupath_adouble,
      /* vfs_chown:         */ RF_chown_adouble,
      /* vfs_renamedir:     */ RF_renamedir_adouble,
      NULL
  };
  
 -static struct vfs_ops netatalk_adouble_osx = {
 -    /* vfs_validupath:    */ validupath_osx,
 -    /* vfs_chown:         */ RF_chown_adouble,
 -    /* vfs_renamedir:     */ RF_renamedir_osx,
 -    /* vfs_deletecurdir:  */ RF_deletecurdir_osx,
 -    /* vfs_setfilmode:    */ RF_setfilmode_adouble,
 -    /* vfs_setdirmode:    */ RF_setdirmode_osx,
 -    /* vfs_setdirunixmode:*/ RF_setdirunixmode_osx,
 -    /* vfs_setdirowner:   */ RF_setdirowner_osx,
 -    /* vfs_deletefile:    */ RF_deletefile_adouble,
 -    /* vfs_renamefile:    */ RF_renamefile_osx,
 -    /* vfs_copyfile:      */ NULL,
 -    NULL
 -};
 -
 -/* samba sfm format. ad_path shouldn't be set her */
 -static struct vfs_ops netatalk_adouble_sfm = {
 -    /* vfs_validupath:    */ validupath_adouble,
 -    /* vfs_chown:         */ RF_chown_ads,
 -    /* vfs_renamedir:     */ RF_renamedir_adouble,
 -    /* vfs_deletecurdir:  */ RF_deletecurdir_ads,
 -    /* vfs_setfilmode:    */ RF_setfilmode_ads,
 -    /* vfs_setdirmode:    */ RF_setdirmode_ads,
 -    /* vfs_setdirunixmode:*/ RF_setdirunixmode_ads,
 -    /* vfs_setdirowner:   */ RF_setdirowner_ads,
 -    /* vfs_deletefile:    */ RF_deletefile_ads,
 -    /* vfs_renamefile:    */ RF_renamefile_ads,
 -    /* vfs_copyfile:      */ NULL,
 +static struct vfs_ops netatalk_adouble_ea = {
 +    /* vfs_validupath:    */ validupath_ea,
 +    /* vfs_chown:         */ RF_chown_ea,
 +    /* vfs_renamedir:     */ RF_renamedir_ea,
 +    /* vfs_deletecurdir:  */ RF_deletecurdir_ea,
 +    /* vfs_setfilmode:    */ RF_setfilmode_ea,
 +    /* vfs_setdirmode:    */ RF_setdirmode_ea,
 +    /* vfs_setdirunixmode:*/ RF_setdirunixmode_ea,
 +    /* vfs_setdirowner:   */ RF_setdirowner_ea,
 +    /* vfs_deletefile:    */ RF_deletefile_ea,
 +    /* vfs_renamefile:    */ RF_renamefile_ea,
 +    /* vfs_copyfile:      */ RF_copyfile_ea,
      NULL
  };
  
@@@ -839,12 -1150,17 +866,12 @@@ void initvol_vfs(struct vol *vol
      vol->vfs = &vfs_master_funcs;
  
      /* Default adouble stuff */
 -    if (vol->v_adouble == AD_VERSION2_OSX) {
 -        vol->vfs_modules[0] = &netatalk_adouble_osx;
 -        vol->ad_path = ad_path_osx;
 -    }
 -    else if (vol->v_adouble == AD_VERSION1_SFM) {
 -        vol->vfs_modules[0] = &netatalk_adouble_sfm;
 -        vol->ad_path = ad_path_sfm;
 -    }
 -    else {
 -        vol->vfs_modules[0] = &netatalk_adouble;
 +    if (vol->v_adouble == AD_VERSION2) {
 +        vol->vfs_modules[0] = &netatalk_adouble_v2;
          vol->ad_path = ad_path;
 +    } else {
 +        vol->vfs_modules[0] = &netatalk_adouble_ea;
 +        vol->ad_path = ad_path_ea;
      }
  
      /* Extended Attributes */
diff --combined macros/gssapi-check.m4
index 547907c30a8bfe0a94181bd4f97d93918762a19a,38d90d12c761a79ae7bb10f67020edb29034af4e..f604c9d6e690f4b99866bffd204bd2209da7550b
@@@ -28,10 -28,10 +28,10 @@@ AC_DEFUN([NETATALK_GSSAPI_CHECK]
          # Do no harm to the values of CFLAGS and LIBS while testing for
          # Kerberos support.
  
 -              ac_save_CFLAGS=$CFLAGS
 -              ac_save_CPPFLAGS=$CPPFLAGS
 -              ac_save_LDFLAGS=$LDFLAGS
 -              ac_save_LIBS=$LIBS
 +              save_CFLAGS=$CFLAGS
 +              save_CPPFLAGS=$CPPFLAGS
 +              save_LDFLAGS=$LDFLAGS
 +              save_LIBS=$LIBS
  
        if test x$FOUND_GSSAPI = x"no"; then
          #################################################
          AC_PATH_PROG(KRB5_CONFIG, krb5-config)
          AC_MSG_CHECKING(for working krb5-config)
          if test -x "$KRB5_CONFIG"; then
 -          ac_save_CFLAGS=$CFLAGS
 +          save_CFLAGS=$CFLAGS
            CFLAGS="";export CFLAGS
 -          ac_save_LDFLAGS=$LDFLAGS
 +          save_LDFLAGS=$LDFLAGS
            LDFLAGS="";export LDFLAGS
            GSSAPI_LIBS="`$KRB5_CONFIG --libs gssapi`"
            GSSAPI_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
            GSSAPI_CPPFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
 -          CFLAGS=$ac_save_CFLAGS;export CFLAGS
 -          LDFLAGS=$ac_save_LDFLAGS;export LDFLAGS
 +          CFLAGS=$save_CFLAGS;export CFLAGS
 +          LDFLAGS=$save_LDFLAGS;export LDFLAGS
            FOUND_GSSAPI=yes
            AC_MSG_RESULT(yes)
          else
@@@ -94,7 -94,7 +94,7 @@@
        CFLAGS="$CFLAGS $GSSAPI_CFLAGS"
        CPPFLAGS="$CPPFLAGS $GSSAPI_CPPFLAGS"
        LDFLAGS="$LDFLAGS $GSSAPI_LDFLAGS"
-       LIBS="$GSSAPI_LIBS"
+       LIBS="$LIBS $GSSAPI_LIBS"
  
  
        # check for gssapi headers
                GSSAPI_LIBS=""
        fi
  
 -        LIBS="$ac_save_LIBS"
 -        CFLAGS="$ac_save_CFLAGS"
 -        LDFLAGS="$ac_save_LDFLAGS"
 -        CPPFLAGS="$ac_save_CPPFLAGS"
 +        LIBS="$save_LIBS"
 +        CFLAGS="$save_CFLAGS"
 +        LDFLAGS="$save_LDFLAGS"
 +        CPPFLAGS="$save_CPPFLAGS"
        fi
  
          if test x"$ac_cv_func_gss_acquire_cred" = x"yes"; then
  
        AC_SUBST(GSSAPI_LIBS)
        AC_SUBST(GSSAPI_CFLAGS)
 +      AC_SUBST(GSSAPI_LDFLAGS)
  
  ])
diff --combined macros/iconv.m4
index 3ddd7a9dd5fd0f5069adcee03de762c35c57e95f,77e0e6bbfe9906f8eab1640a00ac2ad7af5dc56c..4805662d7e3933d04aa648c41cc0d322691e7a23
@@@ -1,8 -1,9 +1,9 @@@
 -AC_DEFUN([AC_CHECK_ICONV],
 +AC_DEFUN([AC_NETATALK_CHECK_ICONV],
  [
  
  dnl   #################################################
  dnl   # check for libiconv support
+       saved_CPPFLAGS="$CPPFLAGS"
          savedcflags="$CFLAGS"
          savedldflags="$LDFLAGS"
        ICONV_CFLAGS=""
diff --combined macros/netatalk.m4
index 94e65dd98eb8b7bb00dc0ae3367b576c5d137c43,0000000000000000000000000000000000000000..512e479a7aae8cd5fd3a4b7f21774a4056f4e8fe
mode 100644,000000..100644
--- /dev/null
@@@ -1,795 -1,0 +1,813 @@@
-       AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics])
 +dnl Kitchen sink for configuration macros
 +
 +dnl Check for optional admin group support
 +AC_DEFUN([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 cracklib support
 +AC_DEFUN([AC_NETATALK_CRACKLIB], [
 +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])
 +])
 +
 +dnl Check whether to enable debug code
 +AC_DEFUN([AC_NETATALK_DEBUG], [
 +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 whethe to disable tickle SIGALARM stuff, which eases debugging
 +AC_DEFUN([AC_NETATALK_DEBUGGING], [
 +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 for optional shadow password support
 +AC_DEFUN([AC_NETATALK_SHADOW], [
 +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
 +
 +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 valid-shell-check support
 +AC_DEFUN([AC_NETATALK_SHELL_CHECK], [
 +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 sysv initscript install
 +AC_DEFUN([AC_NETATALK_SYSV_STYLE], [
 +    AC_ARG_WITH(sysv-style,
 +                [  --with-sysv-style       use OS specific sysv config [[redhat-sysv|redhat-systemd|suse|gentoo|netbsd|debian]]],
 +                sysv_style="$withval", sysv_style=none
 +    )
 +    case "$sysv_style" in 
 +    "redhat")
 +          AC_MSG_ERROR([--enable-redhat is obsoleted. Use --enable-redhat-sysv or --enable-redhat-systemd.])
 +        ;;
 +    "redhat-sysv")
 +          AC_MSG_RESULT([enabling redhat-style sysv (upstart) configuration])
 +          ;;
 +    "redhat-systemd")
 +          AC_MSG_RESULT([enabling redhat-style systemd support])
 +          ;;
 +    "suse")
 +          AC_MSG_RESULT([enabling suse-style sysv support])
 +        ;;
 +    "gentoo")
 +          AC_MSG_RESULT([enabling gentoo-style sysv support])
 +        ;;
 +    "netbsd")
 +          AC_MSG_RESULT([enabling netbsd-style sysv support])
 +        ;;
 +    "debian")
 +          AC_MSG_RESULT([enabling debian-style sysv support])
 +        ;;
 +    *)
 +          AC_MSG_RESULT([disabling sysv support])
 +        ;;
 +    esac
 +])
 +
 +dnl OS specific configuration
 +AC_DEFUN([AC_NETATALK_OS_SPECIFIC], [
 +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])
++        ;;
++     kfreebsd-gnu) AC_DEFINE(_GNU_SOURCE, 1, [Whether to use GNU libc extensions])
++        ;;
++esac
++
 +dnl --------------------- operating system specific flags (port from sys/*)
 +
 +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])
-       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
++    AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW)
++fi
++
++dnl ----- GNU/kFreeBSD specific -----
++if test x"$this_os" = "xkfreebsd-gnu"; then 
++      AC_MSG_RESULT([ * GNU/kFreeBSD specific configuration])
++      AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
++      AC_DEFINE(FREEBSD, 1, [Define if OS is FreeBSD])
 +    AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW)
 +fi
 +
 +dnl ----- Linux specific -----
 +if test x"$this_os" = "xlinux"; then 
 +      AC_MSG_RESULT([ * Linux specific configuration])
 +      
 +      dnl ----- check if we need the quotactl wrapper
 +    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])
 +
- 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_QUOTA_SUPPORT, 1, [Define if Quota support should be disabled])
-       AC_DEFINE(MACOSX_SERVER, 1, [Define if compiling for MacOS X Server])
-     AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
- fi
 +      need_dash_r=no
 +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])
++    AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
 +      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 Check for building PGP UAM module
 +AC_DEFUN([AC_NETATALK_PGP_UAM], [
 +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 V UAM module
 +AC_DEFUN([AC_NETATALK_KRB5_UAM], [
 +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 Check for overwrite the config files or not
 +AC_DEFUN([AC_NETATALK_OVERWRITE_CONFIG], [
 +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])
 +AC_SUBST(OVERWRITE_CONFIG)
 +])
 +
 +dnl Check for LDAP support, for client-side ACL visibility
 +AC_DEFUN([AC_NETATALK_LDAP], [
 +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_DEFUN([AC_NETATALK_ACL], [
 +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);
 +                              ],
 +                              [netatalk_cv_HAVE_ACL_GET_PERM_NP=yes],
 +                              [netatalk_cv_HAVE_ACL_GET_PERM_NP=no])
 +                              LIBS=$acl_LIBS
 +                      ])
 +                      if test x"$netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
 +                              AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
 +                      fi
 +
 +
 +                       AC_CACHE_CHECK([for acl_from_mode], netatalk_cv_HAVE_ACL_FROM_MODE,[
 +                               acl_LIBS=$LIBS
 +                               LIBS="$LIBS $ACL_LIBS"
 +                AC_CHECK_FUNCS(acl_from_mode,
 +                               [netatalk_cv_HAVE_ACL_FROM_MODE=yes],
 +                               [netatalk_cv_HAVE_ACL_FROM_MODE=no])
 +                               LIBS=$acl_LIBS
 +                       ])
 +                       if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then
 +                               AC_DEFINE(HAVE_ACL_FROM_MODE,1,[Whether acl_from_mode() is available])
 +                       fi
 +
 +              else
 +                      AC_MSG_NOTICE(ACL support is not avaliable)
 +                      AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available])
 +              fi
 +              ;;
 +    esac
 +fi
 +
 +if test x"$with_acl_support" = x"yes" ; then
 +   AC_CHECK_HEADERS([acl/libacl.h])
 +    AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available])
 +    AC_SUBST(ACL_LIBS)
 +fi
 +])
 +
 +dnl Check for Extended Attributes support
 +AC_DEFUN([AC_NETATALK_EXTENDED_ATTRIBUTES], [
 +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 for libsmbsharemodes from Samba for Samba/Netatalk access/deny/share modes interop
 +dnl Defines "neta_cv_have_smbshmd" to "yes" or "no"
 +dnl AC_SUBST's "SMB_SHAREMODES_CFLAGS" and "SMB_SHAREMODES_LDFLAGS"
 +dnl AM_CONDITIONAL's "USE_SMB_SHAREMODES"
 +AC_DEFUN([AC_NETATALK_SMB_SHAREMODES], [
 +    neta_cv_have_smbshmd=no
 +    AC_ARG_WITH(smbsharemodes-lib,
 +                [  --with-smbsharemodes-lib=PATH        PATH to libsmbsharemodes lib from Samba],
 +                [SMB_SHAREMODES_LDFLAGS="-L$withval -lsmbsharemodes"]
 +    )
 +    AC_ARG_WITH(smbsharemodes-include,
 +                [  --with-smbsharemodes-include=PATH    PATH to libsmbsharemodes header from Samba],
 +                [SMB_SHAREMODES_CFLAGS="-I$withval"]
 +    )
 +    AC_ARG_WITH(smbsharemodes,
 +                [AS_HELP_STRING([--with-smbsharemodes],[Samba interop (default is yes)])],
 +                [use_smbsharemodes=$withval],
 +                [use_smbsharemodes=yes]
 +    )
 +
 +    if test x"$use_smbsharemodes" = x"yes" ; then
 +        AC_MSG_CHECKING([whether to enable Samba/Netatalk access/deny/share-modes interop])
 +
 +        saved_CFLAGS="$CFLAGS"
 +        saved_LDFLAGS="$LDFLAGS"
 +        CFLAGS="$SMB_SHAREMODES_CFLAGS $CFLAGS"
 +        LDFLAGS="$SMB_SHAREMODES_LDFLAGS $LDFLAGS"
 +
 +        AC_LINK_IFELSE(
 +            [#include <unistd.h>
 +             #include <stdio.h>
 +             #include <sys/time.h>
 +             #include <time.h>
 +             #include <stdint.h>
 +             /* From messages.h */
 +             struct server_id {
 +                 pid_t pid;
 +             };
 +             #include "smb_share_modes.h"
 +             int main(void) { (void)smb_share_mode_db_open(""); return 0;}],
 +            [neta_cv_have_smbshmd=yes]
 +        )
 +
 +        AC_MSG_RESULT($neta_cv_have_smbshmd)
 +        AC_SUBST(SMB_SHAREMODES_CFLAGS, [$SMB_SHAREMODES_CFLAGS])
 +        AC_SUBST(SMB_SHAREMODES_LDFLAGS, [$SMB_SHAREMODES_LDFLAGS])
 +        CFLAGS="$saved_CFLAGS"
 +        LDFLAGS="$saved_LDFLAGS"
 +    fi
 +
 +    AM_CONDITIONAL(USE_SMB_SHAREMODES, test x"$neta_cv_have_smbshmd" = x"yes")
 +])
++
++dnl ------ Check for sendfile() --------
++AC_DEFUN([AC_NETATALK_SENDFILE], [
++netatalk_cv_search_sendfile=yes
++AC_ARG_ENABLE(sendfile,
++    [  --disable-sendfile       disable sendfile syscall],
++    [if test x"$enableval" = x"no"; then
++            netatalk_cv_search_sendfile=no
++        fi]
++)
++
++if test x"$netatalk_cv_search_sendfile" = x"yes"; then
++   case "$host_os" in
++   *linux*)
++        AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available])
++        AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
++        ;;
++
++    *solaris*)
++        AC_DEFINE(SENDFILE_FLAVOR_SOLARIS, 1, [Solaris sendfile()])
++        AC_SEARCH_LIBS(sendfile, sendfile)
++        AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
++        ;;
++
++    *freebsd*)
++        AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics])
++        AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
++        ;;
++
++    *)
++        ;;
++
++    esac
++
++    if test x"$netatalk_cv_HAVE_SENDFILE" = x"yes"; then
++        AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile() should be used])
++    fi
++fi
++])
++
++dnl --------------------- Check if realpath() takes NULL
++AC_DEFUN([AC_NETATALK_REALPATH], [
++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
++])
diff --combined macros/summary.m4
index 744c4f2b7f8e05aade37cece7e06728fbbd0a49d,4514d94ab983f7866c217a1d5e6e0101ee6ad725..8498c4246e171f9a71cd32dc1fc4eec37a06c451
@@@ -11,8 -11,8 +11,8 @@@ AC_DEFUN([AC_NETATALK_CONFIG_SUMMARY], 
                AC_MSG_RESULT([         none])
        fi
        AC_MSG_RESULT([    AFP:])
 -      AC_MSG_RESULT([         Large file support (>2GB) for AFP3: $wx_largefile])
        AC_MSG_RESULT([         Extended Attributes: $neta_cv_eas])
 +      AC_MSG_RESULT([         ACL support: $with_acl_support])
        AC_MSG_RESULT([    CNID:])
        AC_MSG_RESULT([         backends: $compiled_backends])
        AC_MSG_RESULT([    UAMS:])
                  AC_MSG_RESULT([         DHX2    ($uams_using_options)])
          fi
        if test "x$neta_cv_have_openssl" = "xyes"; then
-               AC_MSG_RESULT([         RANDNUM ($uams_using_options)])
+               AC_MSG_RESULT([         RANDNUM])
        fi
        if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then
                AC_MSG_RESULT([         Kerberos V])
        fi
 -      if test x"$compile_kerberos" = x"yes"; then
 -              AC_MSG_RESULT([         Kerberos IV])
 -      fi
        if test x"$compile_pgp" = x"yes"; then
                AC_MSG_RESULT([         PGP])
        fi
-       AC_MSG_RESULT([         passwd  ($uams_using_options)])
+       AC_MSG_RESULT([         clrtxt  ($uams_using_options)])
        AC_MSG_RESULT([         guest])
        AC_MSG_RESULT([    Options:])
 -      AC_MSG_RESULT([         DDP (AppleTalk) support: $netatalk_cv_ddp_enabled])
 -      if test "x$netatalk_cv_ddp_enabled" = "xyes"; then
 -              AC_MSG_RESULT([         CUPS support:            $netatalk_cv_use_cups])
 -              AC_MSG_RESULT([         Apple 2 boot support:    $compile_a2boot])
 -      fi
        AC_MSG_RESULT([         SLP support:             $netatalk_cv_srvloc])
        AC_MSG_RESULT([         Zeroconf support:        $netatalk_cv_zeroconf])
        AC_MSG_RESULT([         tcp wrapper support:     $netatalk_cv_tcpwrap])
@@@ -51,7 -59,8 +51,7 @@@ dnl   f
        AC_MSG_RESULT([         admin group support:     $netatalk_cv_admin_group])
        AC_MSG_RESULT([         valid shell check:       $netatalk_cv_use_shellcheck])
        AC_MSG_RESULT([         cracklib support:        $netatalk_cv_with_cracklib])
 -      AC_MSG_RESULT([         dropbox kludge:          $netatalk_cv_dropkludge])
 -      AC_MSG_RESULT([         force volume uid/gid:    $netatalk_cv_force_uidgid])
 +      AC_MSG_RESULT([         Samba sharemode interop: $neta_cv_have_smbshmd])
        AC_MSG_RESULT([         ACL support:             $with_acl_support])
        AC_MSG_RESULT([         LDAP support:            $with_ldap])
        if test x"$use_pam_so" = x"yes" -a x"$netatalk_cv_install_pam" = x"no"; then