]> arthur.barton.de Git - netatalk.git/commitdiff
Merge branch 'v3-cleanup' into v3.1.3-alex v3.1.3-alex
authorAlexander Barton <alex@barton.de>
Thu, 10 Jul 2014 22:59:44 +0000 (00:59 +0200)
committerAlexander Barton <alex@barton.de>
Thu, 10 Jul 2014 23:00:00 +0000 (01:00 +0200)
* v3-cleanup:
  autoconf: Indentation fixes
  Spelling fixes
  Whitespace and exclamation mark fixes
  Reset version to 3.0.1 after merge
  sorry. revert...
  fix --enable-fhs

Conflicts:
VERSION
etc/afpd/main.c

Signed-off-by: Alexander Barton <alex@barton.de>
1  2 
NEWS
VERSION
bin/uniconv/uniconv.c
etc/afpd/auth.c
etc/afpd/status.c
etc/afpd/volume.c
libatalk/cnid/cdb/cnid_cdb_close.c
libatalk/cnid/cnid.c
libatalk/cnid/dbd/cnid_dbd.c
macros/netatalk.m4
macros/quota-check.m4

diff --combined NEWS
index 9587f4247c4b42ddef7c3df4c0e7eda77b7bb01e,866ac8871b478afb263850cbd13976e718f39c30..56a0968eae1f1bfc7a711647819695c22ffcd083
--- 1/NEWS
--- 2/NEWS
+++ b/NEWS
 +Changes in 3.1.3
 +================
 +* UPD: Spotlight: more SPARQL query optimisations
 +* UPD: Spotlight: new options "sparql results limit", "spotlight
 +       attributes" and "spotlight expr"
 +* FIX: afpd: Unarchiving certain ZIP archives fails, bug #569
 +* UPD: Update Unicode support to version 7.0.0
 +* FIX: Memory overflow caused by 'basedir regex', bug #567
 +* NEW: afpd: delete empty resource forks, from FR #92
 +* FIX: afpd: fix a crash when accessing ._ AppleDouble files created
 +       by OS X via SMB, bug #564
 +* FIX: afpd and dbd: Converting from AppleDouble v2 to ea may corrupt
 +       the resource fork. In some circumstances an offset calculation
 +       is wrong resulting in corrupt resource forks after the
 +       conversion. Bug #568.
 +* FIX: ad: fix for bug #563 broke ad file utilities, bug #570.
 +* NEW: afpd: new advanced option controlling permissions and ACLs,
 +       from FR #93
 +
 +Changes in 3.1.2
 +================
 +* FIX: Option "vol dbpath" was broken in 3.1.1
 +* FIX: Spotlight: file modification date, bug #545
 +* FIX: Improve reliability of afpd child handler
 +* FIX: debian initscript: add 0 and 6 to Default-Stop. debian-bug#745520
 +* FIX: put the Solaris share reservation after our locking stuff, bug #560.
 +* UPD: Improve Linux quota behaviour
 +* FIX: xattrs on *BSD, bug #562
 +* NEW: afpd: support for using $u username variable in AFP volume
 +       definitions. FR#90.
 +* FIX: getvolbypath returns incorrect volume, bug #563
 +* FIX: fd leak when using appledouble = v2, bug #554
 +* UPD: New options that control whether dbus and Tracker are started:
 +       'start dbus' and 'start tracker', both default to yes, FR#91
 +* UPD: Spotlight: SPARQL query optimisations
 +
 +Changes in 3.1.1
 +================
 +* FIX: Add asprint() compatibility function for systems lacking it
 +* FIX: Fix ressource fork name conversion. Bug #534.
 +* FIX: Fix a bug where only the first configured UAM was loaded.
 +       Bug #537.
 +* UPD: Add support for AFP 3.4. From FR #85.
 +* FIX: Registering with mDNS crashed. Bug #540
 +* FIX: Saving from applications like Photoshop may fail, because
 +       removing the ressource fork AppleDouble file failed. Bug #542.
 +* FIX: dbd: remove orphaned ._ AppleDouble files. Bug #549.
 +* NEW: afpd: Automatic conversion of ._ AppleDouble files
 +       created by OS X. Bug #550.
 +* FIX: afpd: Fix a crash in of_closefork(). Bug #551.
 +* FIX: dbd: Don't print message "Ignoring ._file" for every ._ file.
 +       Bug #552.
 +* FIX: afpd: Don't flood log with failed sys_set_ea() messages.
 +
 +Changes in 3.1.0
 +================
 +* NEW: AFP Spotlight support with Gnome Tracker
 +* NEW: New option "spotlight" (G/V)
 +* NEW: Configure option --with-tracker-pkgconfig-version
 +* NEW: Configure option --with-tracker-prefix
 +* NEW: If Spotlight is enabled, launch our own dbus instance
 +* NEW: New option "dbus daemon" (G)
 +* UPD: Add configure option --with-afpstats for overriding the
 +       result of autodetecting dbus-glib presence
 +* NEW: Add recvfile support with splice() on Linux. New global options
 +       "recvfile" (default: no) and "splice size" (default 64k).
 +* NEW: CNID backend "mysql" for use with a MySQL server
 +
 +Changes in 3.0.7
 +================
 +* FIX: Build fixes for the Kerberos UAM
 +* UPD: Use dedicated exit code for AFP connections that were dropped
 +       by the client right after the TCP handshake
 +* FIX: Workaround for a problem which cannot be advertized by Avahi. Bug #541.
 +* FIX: Registering with mDNS crashed. Bug #540
 +* FIX: Saving from applications like Photoshop may fail, because
 +       removing the ressource fork AppleDouble file failed. Bug #542.
 +* FIX: macusers showed root user. Bug #495.
 +* UPD: Add file pathname to logmessage parse_entries: bogus eid. FR#87.
 +
 +Changes in 3.0.6
 +================
 +* FIX: charset conversion failed when copying from Mac OS 9. Bug #523.
 +* UPD: Don't force S_ISGID for directories on FreeBSD. Bug #525.
 +* NEW: Add support for ZFS ACLs on FreeBSD with libsunacl. From FR#83.
 +* FIX: Active Directory LDAP queries for ACL support with new options
 +       "ldap user filter" and "ldap group filter". Bug #526.
 +* NEW: Option "vol dbnest", when set to true, the CNID database for
 +       a volume is stored in the volume root of a share in a directory
 +       .AppleDB like in Netatalk 2. Defaults to false. From FR#84.
 +* FIX: Small fix in the DSI tickle handling. Bug #528.
 +* UPD: Enhance handling of connection attempts when hitting the
 +       connection limit. Bug #529.
 +* FIX: Saving from Word to a folder that is a symlink to a folder on
 +       another filesystem results in a crash of the afpd process and
 +       the save to fail. This happens only if the option
 +       "follow symlinks" is enabled. Bug #532.
 +* FIX: Disable Kerberos UAM if AFP service principal name can't be
 +       evaluated. Fixes bug #531.
 +* FIX: Fix handling of large number of volumes. Bug #527.
 +* NEW: Configure option --with-tbd which can be used to disable the
 +       use of the bundled tdb and use a system installed version.
 +
 +Changes in 3.0.5
 +================
 +* FIX: Fix a crash when using pam_winbind. Fixes bug #516.
 +* NEW: New global/volume option "ignored attributes"
 +* FIX: "afp listen" option failed to take IPv6 addresses. Bug #515.
 +* FIX: Fix a possible crash in set_groups. Bug #518.
 +* NEW: Send optional AFP messages for vetoed files, new option
 +       "veto message" can be used to enable sending messages.
 +       Then whenever a client tries to access any file or directory
 +       with a vetoed name, it will be sent an AFP message indicating
 +       the name and the directory. From FR #81.
 +* NEW: New boolean volume option "delete veto files". If this option is
 +       set to yes, then Netatalk will attempt to recursively delete any
 +       vetoed files and directories. FR #82.
 +* UPD: systemd unit dir is /usr/lib/systemd/system .
 +* FIX: Saving files from application like MS Word may result in the file
 +       loosing metadata like the Finder label. Bug #521.
 +
 +Changes in 3.0.4
 +================
 +* FIX: Opening files without metadata EA may result in an invalid
 +       metadata EA. Check for malformed metadata EAs and delete them.
 +       Fixes bug #510.
 +* FIX: Fix an issue with filenames containing non-ASCII characters that
 +       lead to a failure setting the size of a files ressource fork.
 +       This affected application like Adobe Photoshop where saving
 +       files may fail. Fixes bug #511.
 +* UPD: Enhance ACL mapping, change global ACL option 'map acls' to take
 +       the following options: "none", "rights" (default), "mode".
 +       none   = no mapping, this resembles the previous false/no setting
 +       rights = map ACLs to Finder UARights, this resembles the previous
 +                true/yes setting. This is the default.
 +       mode   = map ACLs to Finder UARights and UNIX mode
 +       From FR #73.
 +* FIX: Fix a possible crash in cname() where cname_mtouname calls
 +       dirlookup() where the curdir is freed because the dircache
 +       detected a dev/inode cache difference and evicted the object
 +       from the cache. Fixes bug #498.
 +* FIX: Add missing include, fixes bug #512.
 +* FIX: Change default FinderInfo for directories to be all 0, fixes
 +       bug 514.
 +* NEW: New option "afp interfaces" which allows specifying where
 +       Netatalk listens for AFP connections by interface names.
 +       From FR #79.
 +
 +Changes in 3.0.3
 +================
 +* UPD: afpd: Increase default DSI server quantum to 1 MB
 +* UPD: bundled libevent2 is now static
 +* NEW: --with-lockfile=PATH configure option for specifying an
 +       alternative path for the netatalk lockfile.
 +* UPD: systemd service file use PIDFile and ExecReload.
 +       From FR #70.
 +* UPD: RedHat sysvinit: rm graceful, reimplement reload, add condrestart
 +* FIX: Couldn't create folders on FreeBSD 9.1 ZFS fileystems.
 +       Fixed bug #491.
 +* FIX: Fix an issue with user homes when user home directory has not the
 +       same name as the username.
 +       Fixes bug #497.
 +* UPD: Fix PAM config install, new default installation dir is
 +       $sysconfdir/pam.d/. Add configure option --with-pam-confdir
 +       to specify alternative path.
 +* NEW: AFP stats about active session via dbus IPC. Client side python
 +       program `afpstats`. Requires dbus, dbus-glib any python-dbus.
 +       configure option --dbus-sysconf-dir for specifying dbus
 +       system security configuration files.
 +       New option 'afpstats' (default: no) which determines whether
 +       to enable the feature or not.
 +* NEW: configure option --with-init-dir
 +* NEW: dtrace probes, cf include/atalk/afp_dtrace.d for available
 +       probes.
 +* UPD: Reload groups when reloading volumes. FR #71.
 +* FIX: Attempt to read read-only ._ rfork results in disconnect.
 +       Fixes bug #502.
 +* FIX: File's ressource fork can't be read if metadata EA is missing.
 +       Fixes bug #501.
 +* FIX: Conversion from adouble v2 to ea for directories.
 +       Fixes bug #500.
 +* FIX: Error messages when mounting read-only filesystems.
 +       Fixes bug #504.
 +* FIX: Permissions of ._ AppleDouble ressource fork after conversion
 +       from v2 to ea.
 +       Fixes bug #505.
 +* UPD: Use FreeBSD sendfile() capability to send protocol header.
 +       From FR #75.
 +* UPD: Increase IO size when sendfile() is not used.
 +       From FR #76.
 +* FIX: Can't set Finder label on symlinked folder with "follow symlinks = yes".
 +       Fixes bug #508.
 +* FIX: Setting POSIX ACLs on Linux
 +       Fixes bug #506.
 +* FIX: "ad ls" segfault if requested object is not in an AFP volume.
 +       Fixes bug #496.
 +
 +Changes in 3.0.2
 +================
 +* NEW: afpd: Put file extension type/creator mapping back in which had
 +       been removed in 3.0.
 +* NEW: afpd: new option 'ad domain'. From FR #66.
 +* FIX: volumes and home share with symlinks in the path
 +* FIX: Copying packages to a Netatalk share could fail, bug #469
 +* FIX: Reloading volumes from config file was broken.  Fixes bug #474.
 +* FIX: Fix _device-info service type registered with dns-sd API
 +* FIX: Fix pathname bug for FCE modified event.
 +* FIX: Remove length limitation of options like "valid users".
 +       Fixes bug #473.
 +* FIX: Dont copy our metadata EA in copyfile(). Fixes bug #452.
 +* FIX: Fix an error where catalog search gave incomplete results.
 +       Fixes bug #479.
 +* REM: Remove TimeMachine volume used size FCE event.
 +* UPD: Add quoting support to '[in]valid users' option. Fixes bug #472.
 +* FIX: Install working PAM config on Solaris 11. Fixes bug #481.
 +* FIX: Fix a race condition between dbd and the cnid_dbd daemon
 +       which could result in users being disconnected from volumes
 +       when dbd was scanning their volumes. Fixes bug #477.
 +* FIX: Netatalk didn't start when the last line of the config file
 +       afp.conf wasn't terminated by a newline. Fixes bug #476.
 +* NEW: Add a new volumes option 'follow symlinks'. The default setting is
 +       false, symlinks are not followed on the server. This is the same
 +       behaviour as OS X's AFP server.
 +       Setting the option to true causes afpd to follow symlinks on the
 +       server. symlinks may point outside of the AFP volume, currently
 +       afpd doesn't do any checks for "wide symlinks".
 +* FIX: Automatic AppleDouble conversion to EAs failing for directories.
 +       Fixes bug #486.
 +* FIX: dbd failed to convert appledouble files of symlinks.
 +       Fixes bug #490.
 +
  Changes in 3.0.1
  ================
  * NEW: afpd: Optional "ldap uuid encoding = string | ms-guid" parameter to
@@@ -419,7 -188,7 +419,7 @@@ Changes in 2.2.
  Changes in 2.2.1
  ================
  
- * NEW: afpd: disable continous service feature by default, new option
+ * NEW: afpd: disable continuous service feature by default, new option
         -keepsessions to enable it
  * NEW: configure option "--enable-redhat-systemd" for Fedora15 and later.
         "--enable-redhat" is renamed "--enable-redhat-sysv".
diff --combined VERSION
index 711ee4f504af604a1be58325663a760990cf3783,13d683ccbfeed4ecf19a8f76e016a4e0296ea4cf..781a07bb18b75fa611244d98824dd88729ee1ad3
+++ b/VERSION
@@@ -1,1 -1,1 +1,1 @@@
- 3.1.3
 -3.0.1
++3.1.3-ab
diff --combined bin/uniconv/uniconv.c
index 93439cefa965efae35bab8255d0c97d7d1f04780,c8f80f52699e53ac56d39c8d20e548870f41a6d9..b9a2fc45c87b56e4fdccd2954cd34d32d36ed626
@@@ -184,8 -184,8 +184,8 @@@ static char *convert_name(char *name, s
                outlen = convert_charset(ch_to, ch_to, ch_mac, (char *)p, strlen((char *)p), (char *)q, sizeof(buffer) -2, &flags);
                if ((size_t)-1 == outlen) {
                        /* it's not UTF8... */
-                       fprintf(stderr, "ERROR: conversion from '%s' to '%s' for '%s' in DID %u failed!!!\n", 
-                               from_charset, to_charset, name, ntohl(cur_did));
+                               fprintf(stderr, "ERROR: conversion from '%s' to '%s' for '%s' in DID %u failed!\n",
+                                       from_charset, to_charset, name, ntohl(cur_did));
                        return name;
                }
  
@@@ -389,7 -389,7 +389,7 @@@ static int init(char* path
  {
        DIR* startdir;
  
 -    if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, "localhost", "4700")) ) {
 +    if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, "localhost", "4700", NULL, NULL)) ) {
                  fprintf (stderr, "ERROR: cannot open CNID database in '%s'\n", path);
                  fprintf (stderr, "ERROR: check the logs for reasons, aborting\n");
                return -1;
@@@ -441,11 -441,11 +441,11 @@@ static void help (void
      fprintf (stdout, "\t-V\tPrint version and exit\n");
      fprintf (stdout, "\t-h\tThis help screen\n\n");
      fprintf (stdout, "WARNING:\n");
-     fprintf (stdout, "     Setting the wrong options might render your data unusable!!!\n");
+     fprintf (stdout, "     Setting the wrong options might render your data unusable!\n");
      fprintf (stdout, "     Make sure you know what you are doing. Always backup your data first.\n\n");
      fprintf (stdout, "     It is *strongly* recommended to do a `dry run' first and to check the\n");
      fprintf (stdout, "     output for conversion errors.\n");
-     fprintf (stdout, "     USE AT YOUR OWN RISK!!!\n\n");
+     fprintf (stdout, "     USE AT YOUR OWN RISK!\n\n");
  
  }
  
diff --combined etc/afpd/auth.c
index 8011b56b6fbabe68c0d2f71e935e4f6921637cb1,ce1556b6930ee26b9569ad746dc726c3a722a821..8b38b37e5f19defcd3123c85d00aff4f5fa6063a
@@@ -39,8 -39,6 +39,8 @@@ extern void afp_get_cmdline( int *ac, c
  #include <atalk/server_ipc.h>
  #include <atalk/uuid.h>
  #include <atalk/globals.h>
 +#include <atalk/spotlight.h>
 +#include <atalk/unix.h>
  
  #include "auth.h"
  #include "uam_auth.h"
@@@ -170,7 -168,6 +170,7 @@@ static int set_auth_switch(const AFPOb
          afp_switch = postauth_switch;
          switch (obj->afp_version) {
  
 +        case 34:
          case 33:
          case 32:
  #ifdef HAVE_ACLS
          case 31:
              uam_afpserver_action(AFP_SYNCDIR, UAM_AFPSERVER_POSTAUTH, afp_syncdir, NULL);
              uam_afpserver_action(AFP_SYNCFORK, UAM_AFPSERVER_POSTAUTH, afp_syncfork, NULL);
 -            uam_afpserver_action(AFP_SPOTLIGHT_PRIVATE, UAM_AFPSERVER_POSTAUTH, afp_null_nolog, NULL);
 +            uam_afpserver_action(AFP_SPOTLIGHT_PRIVATE, UAM_AFPSERVER_POSTAUTH, afp_spotlight_rpc, NULL);
              uam_afpserver_action(AFP_ENUMERATE_EXT2, UAM_AFPSERVER_POSTAUTH, afp_enumerate_ext2, NULL);
  
          case 30:
      return AFP_OK;
  }
  
 -#define GROUPSTR_BUFSIZE 1024
 -static const char *print_groups(int ngroups, gid_t *groups)
 -{
 -    static char groupsstr[GROUPSTR_BUFSIZE];
 -    int i;
 -    char *s = groupsstr;
 -
 -    if (ngroups == 0)
 -        return "-";
 -
 -    for (i = 0; (i < ngroups) && (s < &groupsstr[GROUPSTR_BUFSIZE]); i++) {
 -        s += snprintf(s, &groupsstr[GROUPSTR_BUFSIZE] - s, " %u", groups[i]);
 -    }
 -
 -    return groupsstr;
 -}
 -
  static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expired)
  {
  #ifdef ADMIN_GRP
          return AFPERR_NOTAUTH;
      }
  
 -    LOG(log_note, logtype_afpd, "%s Login by %s",
 -        afp_versions[afp_version_index].av_name, pwd->pw_name);
 -
 -    if (initgroups( pwd->pw_name, pwd->pw_gid ) < 0) {
 -#ifdef RUN_AS_USER
 -        LOG(log_info, logtype_afpd, "running with uid %d", geteuid());
 -#else /* RUN_AS_USER */
 -        LOG(log_error, logtype_afpd, "login: %s", strerror(errno));
 -        return AFPERR_BADUAM;
 -#endif /* RUN_AS_USER */
 -
 +    if (obj->cnx_cnt > obj->cnx_max) {
 +        LOG(log_error, logtype_dsi, "login: too many connections, limit: %d", obj->cnx_max);
 +        return AFPERR_MAXSESS;
      }
  
 -    /* Basically if the user is in the admin group, we stay root */
 +    LOG(log_note, logtype_afpd, "Login by %s (%s)",
 +        pwd->pw_name, afp_versions[afp_version_index].av_name);
  
 -    if ((obj->ngroups = getgroups( 0, NULL )) < 0 ) {
 -        LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) );
 +    if (set_groups(obj, pwd) != 0)
          return AFPERR_BADUAM;
 -    }
 -
 -    if ( NULL == (obj->groups = calloc(obj->ngroups, sizeof(gid_t))) ) {
 -        LOG(log_error, logtype_afpd, "login: %s calloc: %d", obj->ngroups);
 -        return AFPERR_BADUAM;
 -    }
 -
 -    if (( obj->ngroups = getgroups(obj->ngroups, obj->groups )) < 0 ) {
 -        LOG(log_error, logtype_afpd, "login: %s getgroups: %s", pwd->pw_name, strerror(errno) );
 -        return AFPERR_BADUAM;
 -    }
  
  #ifdef ADMIN_GRP
      LOG(log_debug, logtype_afpd, "obj->options.admingid == %d", obj->options.admingid);
@@@ -342,7 -375,6 +342,7 @@@ int afp_zzz(AFPObj *obj, char *ibuf, si
          if (dsi->flags & DSI_EXTSLEEP) {
              LOG(log_note, logtype_afpd, "afp_zzz: waking up from extended sleep");
              dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP);
 +            ipc_child_state(obj, DSI_RUNNING);
          }
      } else {
          /* sleep request */
          if (data & AFPZZZ_EXT_SLEEP) {
              LOG(log_note, logtype_afpd, "afp_zzz: entering extended sleep");
              dsi->flags |= DSI_EXTSLEEP;
 +            ipc_child_state(obj, DSI_EXTSLEEP);
          } else {
              LOG(log_note, logtype_afpd, "afp_zzz: entering normal sleep");
 +            ipc_child_state(obj, DSI_SLEEPING);
          }
      }
  
@@@ -882,7 -912,7 +882,7 @@@ int afp_changepw(AFPObj *obj, char *ibu
          if ( ibuf[0] != '\0' || ibuf[1] != '\0')
              return AFPERR_PARAM;
          ibuf += 2;
 -        len = MIN(sizeof(username), strlen(obj->username));
 +        len = MIN(sizeof(username) - 1, strlen(obj->username));
          memcpy(username, obj->username, len);
          username[ len ] = '\0';
      }
@@@ -967,7 -997,7 +967,7 @@@ int afp_getuserinfo(AFPObj *obj _U_, ch
              atalk_uuid_t uuid;
              ret = getuuidfromname( obj->username, UUID_USER, uuid);
              if (ret != 0) {
-                 LOG(log_info, logtype_afpd, "afp_getuserinfo: error getting UUID !");
+                 LOG(log_info, logtype_afpd, "afp_getuserinfo: error getting UUID!");
                  return AFPERR_NOITEM;
              }
              LOG(log_debug, logtype_afpd, "afp_getuserinfo: got UUID: %s", uuid_bin2string(uuid));
@@@ -1019,9 -1049,9 +1019,9 @@@ int auth_register(const int type, struc
  }
  
  /* load all of the modules */
 -int auth_load(const char *path, const char *list)
 +int auth_load(AFPObj *obj, const char *path, const char *list)
  {
 -    char name[MAXPATHLEN + 1], buf[MAXPATHLEN + 1], *p;
 +    char name[MAXPATHLEN + 1], buf[MAXPATHLEN + 1], *p, *last;
      struct uam_mod *mod;
      struct stat st;
      size_t len;
      if (!path || !*path || !list || (len = strlen(path)) > sizeof(name) - 2)
          return -1;
  
 +    LOG(log_debug, logtype_afpd, "auth_load: %s, %s", path, list);
 +
      strlcpy(buf, list, sizeof(buf));
 -    if ((p = strtok(buf, ", ")) == NULL)
 +    if ((p = strtok_r(buf, ", ", &last)) == NULL)
          return -1;
  
      strcpy(name, path);
            if ((stat(name, &st) == 0) && (mod = uam_load(name, p))) {
          */
          if (stat(name, &st) == 0) {
 -            if ((mod = uam_load(name, p))) {
 +            if ((mod = uam_load(obj, name, p))) {
                  uam_attach(&uam_modules, mod);
                  LOG(log_debug, logtype_afpd, "uam: %s loaded", p);
              } else {
          } else {
              LOG(log_info, logtype_afpd, "uam: uam not found (status=%d)", stat(name, &st));
          }
 -        p = strtok(NULL, ", ");
 +        p = strtok_r(NULL, ", ", &last);
      }
  
      return 0;
diff --combined etc/afpd/status.c
index edf744664038965aeb0fffd3f673b587d198d64c,eb5b99b30b970a95f96547e6e87260be38282c9a..d95a7f3b8daf5fb24ecf8894bbb301da6da67154
@@@ -95,7 -95,7 +95,7 @@@ static void status_flags(char *data
  static int status_server(char *data, const char *server, const struct afp_options *options)
  {
      char                *start = data;
 -    char                *Obj, *Type, *Zone;
 +    char                *Obj;
      char              buf[32];
      uint16_t           status;
      size_t            len;
@@@ -311,6 -311,39 +311,6 @@@ static size_t status_netaddress(char *d
      return (data - begin);
  }
  
 -static bool append_directoryname(char **pdata,
 -                                 size_t offset,
 -                                 size_t *size,
 -                                 char* DirectoryNamesCount,
 -                                 size_t len,
 -                                 char *principal)
 -{
 -    if (sizeof(uint8_t) + len  > maxstatuslen - offset - *size) {
 -        LOG(log_error, logtype_afpd,
 -            "status:DirectoryNames: out of space for principal '%s' (len=%d)",
 -            principal, len);
 -        return false;
 -    } else if (len > 255) {
 -        LOG(log_error, logtype_afpd,
 -            "status:DirectoryNames: principal '%s' (len=%d) too long (max=255)",
 -            principal, len);
 -        return false;
 -    }
 -
 -    LOG(log_info, logtype_afpd,
 -        "DirectoryNames[%d]=%s",
 -        *DirectoryNamesCount, principal);
 -
 -    *DirectoryNamesCount += 1;
 -    char *data = *pdata;
 -    *data++ = len;
 -    strncpy(data, principal, len);
 -
 -    *pdata += len + 1;
 -    *size += sizeof(uint8_t) + len;
 -
 -    return true;
 -}
  
  /**
   * DirectoryNamesCount offset: uint16_t
  static size_t status_directorynames(char *data,
                                      int *diroffset,
                                      const DSI *dsi _U_,
 -                                    const struct afp_options *options _U_)
 +                                    const struct afp_options *options)
  {
      char *begin = data;
      uint16_t offset;
      offset = ntohs(offset);
      data += offset;
  
 -    char *DirectoryNamesCount = data++;
 -    char *DirectoryNames = data;
 -    size_t size = sizeof(uint8_t);
 -    *DirectoryNamesCount = 0;
 -
 -    if (!uam_gss_enabled())
 -        goto offset_calc;
 -
 -#ifdef HAVE_KERBEROS
 -    krb5_context context;
 -    krb5_error_code ret;
 -    const char *error_msg;
 -
 -    if (krb5_init_context(&context)) {
 -        LOG(log_error, logtype_afpd,
 -            "status:DirectoryNames failed to intialize a krb5_context");
 -        goto offset_calc;
 -    }
 -
 -    krb5_keytab keytab;
 -    if ((ret = krb5_kt_default(context, &keytab)))
 -        goto krb5_error;
 -
 -    // figure out which service principal to use
 -    krb5_keytab_entry entry;
 -    char *principal;
 -    if (options->k5service && options->fqdn && options->k5realm) {
 -        LOG(log_debug, logtype_afpd,
 -            "status:DirectoryNames: using service principal specified in options");
 -
 -        krb5_principal service_principal;
 -        if ((ret = krb5_build_principal(context,
 -                                        &service_principal,
 -                                        strlen(options->k5realm),
 -                                        options->k5realm,
 -                                        options->k5service,
 -                                        options->fqdn,
 -                                        NULL)))
 -            goto krb5_error;
 -
 -        // try to get the given service principal from keytab
 -        ret = krb5_kt_get_entry(context,
 -                                keytab,
 -                                service_principal,
 -                                0, // kvno - wildcard
 -                                0, // enctype - wildcard
 -                                &entry);
 -        if (ret == KRB5_KT_NOTFOUND) {
 -            krb5_unparse_name(context, service_principal, &principal);
 -            LOG(log_error, logtype_afpd,
 -                "status:DirectoryNames: specified service principal '%s' not found in keytab",
 -                principal);
 -            // XXX: should this be krb5_xfree?
 -#ifdef HAVE_KRB5_FREE_UNPARSED_NAME
 -            krb5_free_unparsed_name(context, principal);
 -#else
 -          krb5_xfree(principal);
 -#endif
 -            goto krb5_cleanup;
 -        }
 -        krb5_free_principal(context, service_principal);
 -        if (ret)
 -            goto krb5_error;
 +    if (!uam_gss_enabled() || !options->k5principal) {
 +        *data = 0;
 +        data++;
      } else {
 -        LOG(log_debug, logtype_afpd,
 -            "status:DirectoryNames: using first entry from keytab as service principal");
 -
 -        krb5_kt_cursor cursor;
 -        if ((ret = krb5_kt_start_seq_get(context, keytab, &cursor)))
 -            goto krb5_error;
 -
 -        ret = krb5_kt_next_entry(context, keytab, &entry, &cursor);
 -        krb5_kt_end_seq_get(context, keytab, &cursor);
 -        if (ret)
 -            goto krb5_error;
 +        memcpy(data, options->k5principal, options->k5principal_buflen);
 +        data += options->k5principal_buflen;
      }
  
 -    krb5_unparse_name(context, entry.principal, &principal);
 -    krb5_kt_free_entry(context, &entry);
 -
 -    append_directoryname(&data,
 -                         offset,
 -                         &size,
 -                         DirectoryNamesCount,
 -                         strlen(principal),
 -                         principal);
 -
 -    free(principal);
 -    goto krb5_cleanup;
 -
 -krb5_error:
 -    if (ret) {
 -        error_msg = krb5_get_error_message(context, ret);
 -        LOG(log_note, logtype_afpd, "Can't get principal from default keytab: %s",
 -            (char *)error_msg);
 -#ifdef HAVE_KRB5_FREE_ERROR_MESSAGE
 -        krb5_free_error_message(context, error_msg);
 -#else
 -      krb5_xfree(error_msg);
 -#endif
 -    }
 -
 -krb5_cleanup:
 -    krb5_kt_close(context, keytab);
 -    krb5_free_context(context);
 -#else
 -    if (!options->k5service || !options->fqdn || !options->k5realm)
 -        goto offset_calc;
 -
 -    char principal[255];
 -    size_t len = snprintf(principal, sizeof(principal), "%s/%s@%s",
 -                          options->k5service, options->fqdn, options->k5realm);
 -
 -    append_directoryname(&data,
 -                         offset,
 -                         &size,
 -                         DirectoryNamesCount,
 -                         strlen(principal),
 -                         principal);
 -#endif // HAVE_KERBEROS
 -
 -offset_calc:
      /* Calculate and store offset for UTF8ServerName */
      *diroffset += sizeof(uint16_t);
      offset = htons(data - begin);
@@@ -354,7 -501,7 +354,7 @@@ static size_t status_utf8servername(cha
      uint16_t namelen;
      size_t len;
      char *begin = data;
 -    uint16_t offset, status;
 +    uint16_t offset;
  
      memcpy(&offset, data + *nameoffset, sizeof(offset));
      offset = ntohs(offset);
@@@ -498,7 -645,7 +498,7 @@@ void set_signature(struct afp_options *
      char *servername_conf;
      int header = 0;
      char buf[1024], *p;
 -    FILE *fp = NULL, *randomp;
 +    FILE *fp = NULL;
      size_t len;
      char *server_tmp;
      
      if (len == 0) {
          goto server_signature_auto;   /* default */
      } else if (len < 3) {
-         LOG(log_warning, logtype_afpd, "WARNING: signature string %s is very short !", options->signatureopt);
+         LOG(log_warning, logtype_afpd, "WARNING: signature string %s is very short!", options->signatureopt);
          goto server_signature_user;
      } else if (len > 16) {
-         LOG(log_warning, logtype_afpd, "WARNING: signature string %s is very long !", options->signatureopt);
+         LOG(log_warning, logtype_afpd, "WARNING: signature string %s is very long!", options->signatureopt);
          len = 16;
          goto server_signature_user;
      } else {
diff --combined etc/afpd/volume.c
index 7bdff75dff53ecf87007a9b001a45c87bae944de,da57a30a822491746f603ba6112516b3ac325dac..ae6c35236d93a7b264ab3962c4f68cff3055d73c
@@@ -39,7 -39,6 +39,7 @@@
  #include <atalk/iniparser.h>
  #include <atalk/unix.h>
  #include <atalk/netatalk_conf.h>
 +#include <atalk/server_ipc.h>
  
  #ifdef CNID_DB
  #include <atalk/cnid.h>
@@@ -153,6 -152,7 +153,6 @@@ static int get_tm_used(struct vol * res
      DIR *dir = NULL;
      const struct dirent *entry;
      const char *p;
 -    struct stat st;
      long int links;
      time_t now = time(NULL);
  
  
              EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") );
              
 -            if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1)
 +            if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1) {
 +                bdestroy(infoplist);
                  continue;
 +            }
  
              EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") );
  
 -            if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1)
 +            if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1) {
 +                bdestroy(infoplist);
 +                bdestroy(bandsdir);
                  continue;
 +            }
  
              used += (links - 1) * bandsize;
              LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes",
@@@ -217,6 -212,7 +217,6 @@@ static int getvolspace(const AFPObj *ob
  {
      int         spaceflag, rc;
      uint32_t   maxsize;
 -    VolSpace    used;
  #ifndef NO_QUOTA_SUPPORT
      VolSpace    qfree, qtotal;
  #endif
@@@ -268,6 -264,22 +268,6 @@@ getvolspace_done
      return( AFP_OK );
  }
  
 -#define FCE_TM_DELTA 10  /* send notification every 10 seconds */
 -void vol_fce_tm_event(void)
 -{
 -    static time_t last;
 -    time_t now = time(NULL);
 -    struct vol  *vol = getvolumes();
 -
 -    if ((last + FCE_TM_DELTA) < now) {
 -        last = now;
 -        for ( ; vol; vol = vol->v_next ) {
 -            if (vol->v_flags & AFPVOL_TM)
 -                (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_appended);
 -        }
 -    }
 -}
 -
  /* -----------------------
   * set volume creation date
   * avoid duplicate, well at least it tries
@@@ -369,7 -381,7 +369,7 @@@ static int getvolparams(const AFPObj *o
              }
              /* prior 2.1 only VOLPBIT_ATTR_RO is defined */
              if (obj->afp_version > 20) {
 -                if (vol->v_cdb != NULL && (vol->v_cdb->flags & CNID_FLAG_PERSISTENT))
 +                if (vol->v_cdb != NULL && (vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT))
                      ashort |= VOLPBIT_ATTR_FILEID;
                  ashort |= VOLPBIT_ATTR_CATSEARCH;
  
@@@ -530,12 -542,11 +530,12 @@@ int afp_getsrvrparms(AFPObj *obj, char 
      char        *namebuf;
      int         vcnt;
      size_t      len;
 +    uint32_t    aint;
  
 -    load_volumes(obj, closevol);
 +    load_volumes(obj, lv_none);
  
      data = rbuf + 5;
 -    for ( vcnt = 0, volume = getvolumes(); volume; volume = volume->v_next ) {
 +    for ( vcnt = 0, volume = getvolumes(); volume && vcnt < 255; volume = volume->v_next ) {
          if (!(volume->v_flags & AFPVOL_NOSTAT)) {
              struct maccess ma;
  
          if (len == (size_t)-1)
              continue;
  
 +        /*
 +         * There seems to be an undocumented limit on how big our reply can get
 +         * before the client chokes and closes the connection.
 +         * Testing with 10.8.4 found the limit at ~4600 bytes. Go figure. 
 +         */
 +        if (((data + len + 3) - rbuf) > 4600)
 +            break;
 +
          /* set password bit if there's a volume password */
          *data = (volume->v_password) ? AFPSRVR_PASSWD : 0;
  
      *rbuflen = data - rbuf;
      data = rbuf;
      if ( gettimeofday( &tv, NULL ) < 0 ) {
 -        LOG(log_error, logtype_afpd, "afp_getsrvrparms(%s): gettimeofday: %s", volume->v_path, strerror(errno) );
 +        LOG(log_error, logtype_afpd, "afp_getsrvrparms: gettimeofday: %s", strerror(errno) );
          *rbuflen = 0;
          return AFPERR_PARAM;
      }
 -    tv.tv_sec = AD_DATE_FROM_UNIX(tv.tv_sec);
 -    memcpy(data, &tv.tv_sec, sizeof( uint32_t));
 +
 +    aint = AD_DATE_FROM_UNIX(tv.tv_sec);
 +    memcpy(data, &aint, sizeof( uint32_t));
      data += sizeof( uint32_t);
      *data = vcnt;
      return( AFP_OK );
@@@ -611,7 -613,7 +611,7 @@@ static int volume_codepage(AFPObj *obj
      }
  
      if ( NULL == (charset = find_charset_functions(volume->v_volcodepage)) || charset->flags & CHARSET_ICONV ) {
-         LOG (log_warning, logtype_afpd, "WARNING: volume encoding %s is *not* supported by netatalk, expect problems !!!!", volume->v_volcodepage);
+         LOG (log_warning, logtype_afpd, "WARNING: volume encoding %s is *not* supported by netatalk, expect problems!", volume->v_volcodepage);
      }
  
      if (!volume->v_maccodepage)
@@@ -639,7 -641,14 +639,7 @@@ static int volume_openDB(const AFPObj *
          flags |= CNID_FLAG_NODEV;
      }
  
 -    LOG(log_debug, logtype_afpd, "CNID server: %s:%s", volume->v_cnidserver, volume->v_cnidport);
 -
 -    volume->v_cdb = cnid_open(volume->v_path,
 -                              volume->v_umask,
 -                              volume->v_cnidscheme,
 -                              flags,
 -                              volume->v_cnidserver,
 -                              volume->v_cnidport);
 +    volume->v_cdb = cnid_open(volume, volume->v_cnidscheme, flags);
  
      if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) {
          /* The first attempt failed and it wasn't yet an attempt to open in-memory */
          LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.",
              volume->v_path);
          flags |= CNID_FLAG_MEMORY;
 -        volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags, NULL, NULL);
 +        volume->v_cdb = cnid_open(volume, "tdb", flags);
  #ifdef SERVERTEXT
          /* kill ourself with SIGUSR2 aka msg pending */
          if (volume->v_cdb) {
      return (!volume->v_cdb)?-1:0;
  }
  
 +/*
 + * Send list of open volumes to afpd master via IPC
 + */
 +static void server_ipc_volumes(AFPObj *obj)
 +{
 +    struct vol *volume, *vols;
 +    volume = vols = getvolumes();
 +    bstring openvolnames = bfromcstr("");
 +    bool firstvol = true;
 +
 +    while (volume) {
 +        if (volume->v_flags & AFPVOL_OPEN) {
 +            if (!firstvol)
 +                bcatcstr(openvolnames, ", ");
 +            else
 +                firstvol = false;
 +            bcatcstr(openvolnames, volume->v_localname);
 +        }
 +        volume = volume->v_next;
 +    }
 +
 +    ipc_child_write(obj->ipc_fd, IPC_VOLUMES, blength(openvolnames), bdata(openvolnames));
 +    bdestroy(openvolnames);
 +}
 +
  /* -------------------------
   * we are the user here
   */
@@@ -695,14 -679,16 +695,14 @@@ int afp_openvol(AFPObj *obj, char *ibuf
  {
      struct stat st;
      char    *volname;
 -    char        *p;
  
      struct vol  *volume;
      struct dir  *dir;
      int     len, ret;
      size_t  namelen;
      uint16_t   bitmap;
 -    char        path[ MAXPATHLEN + 1];
      char        *vol_uname;
 -    char        *vol_mname;
 +    char        *vol_mname = NULL;
      char        *volname_tmp;
  
      ibuf += 2;
      if ((len + 1) & 1) /* pad to an even boundary */
          ibuf++;
  
 -    load_volumes(obj, closevol);
 +    load_volumes(obj, lv_none);
  
      for ( volume = getvolumes(); volume; volume = volume->v_next ) {
          if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) {
          return AFPERR_PARAM;
      }
  
 -    if ( NULL == getcwd(path, MAXPATHLEN)) {
 -        /* shouldn't be fatal but it will fail later */
 -        LOG(log_error, logtype_afpd, "afp_openvol(%s): volume pathlen too long", volume->v_path);
 -        return AFPERR_MISC;
 -    }
 -
 -    /* Normalize volume path */
 -#ifdef REALPATH_TAKES_NULL
 -    if ((volume->v_path = realpath(path, NULL)) == NULL)
 -        return AFPERR_MISC;
 -#else
 -    if ((volume->v_path = malloc(MAXPATHLEN+1)) == NULL)
 -        return AFPERR_MISC;
 -    if (realpath(path, volume->v_path) == NULL) {
 -        free(volume->v_path);
 -        return AFPERR_MISC;
 -    }
 -    /* Safe some memory */
 -    char *tmp;
 -    if ((tmp = strdup(volume->v_path)) == NULL) {
 -        free(volume->v_path);
 -        return AFPERR_MISC;
 -    }
 -    free(volume->v_path);
 -    volume->v_path = tmp;
 -#endif
 -
      if (volume_codepage(obj, volume) < 0) {
          ret = AFPERR_MISC;
          goto openvol_err;
          goto openvol_err;
      }
  
 -    if ((vol_uname = strrchr(path, '/')) == NULL)
 -        vol_uname = path;
 -    else if (*(vol_uname + 1) != '\0')
 +    if ((vol_uname = strrchr(volume->v_path, '/')) == NULL)
 +        vol_uname = volume->v_path;
 +    else if (vol_uname[1] != '\0')
          vol_uname++;
  
      if ((dir = dir_new(vol_mname,
          ret = AFPERR_MISC;
          goto openvol_err;
      }
 -    free(vol_mname);
      volume->v_root = dir;
      curdir = dir;
  
           * fixing the trash at DID 17.
           * FIXME (RL): should it be done inside a CNID backend ? (always returning Trash DID when asked) ?
           */
 -        if ((volume->v_cdb->flags & CNID_FLAG_PERSISTENT)) {
 +        if ((volume->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) {
  
              /* FIXME find db time stamp */
              if (cnid_getstamp(volume->v_cdb, volume->v_stamp, sizeof(volume->v_stamp)) < 0) {
          }
  
          const char *msg;
 -        if ((msg = iniparser_getstring(obj->iniconfig, volume->v_configname, "login message",  NULL)) != NULL)
 +        if ((msg = atalk_iniparser_getstring(obj->iniconfig, volume->v_configname, "login message",  NULL)) != NULL)
              setmessage(msg);
  
 +        free(vol_mname);
 +        server_ipc_volumes(obj);
          return( AFP_OK );
      }
  
@@@ -878,7 -890,6 +878,7 @@@ openvol_err
          cnid_close(volume->v_cdb);
          volume->v_cdb = NULL;
      }
 +    free(vol_mname);
      *rbuflen = 0;
      return ret;
  }
@@@ -936,7 -947,6 +936,7 @@@ int afp_closevol(AFPObj *obj, char *ibu
      (void)chdir("/");
      curdir = NULL;
      closevol(obj, vol);
 +    server_ipc_volumes(obj);
  
      return( AFP_OK );
  }
index c5aeceec21b5ed4c1cde4f3a67fb7f34ffff2ed9,fcc01df2eb6ded40fc339f039389e548f6ab97e7..64ac20370f616b0ffce3831fa6f90e4086137106
@@@ -1,4 -1,5 +1,4 @@@
  /*
 - * $Id: cnid_cdb_close.c,v 1.2 2005-04-28 20:49:59 bfernhomberg Exp $
   */
  
  #ifdef HAVE_CONFIG_H
@@@ -12,11 -13,11 +12,11 @@@ void cnid_cdb_close(struct _cnid_db *cd
      CNID_private *db;
  
      if (!cdb) {
-           LOG(log_error, logtype_afpd, "cnid_close called with NULL argument !");
+           LOG(log_error, logtype_afpd, "cnid_close called with NULL argument!");
            return;
      }
  
 -    if (!(db = cdb->_private)) {
 +    if (!(db = cdb->cnid_db_private)) {
          return;
      }
      db->db_didname->sync(db->db_didname, 0); 
@@@ -30,6 -31,7 +30,6 @@@
      db->dbenv->close(db->dbenv, 0);
  
      free(db);
 -    free(cdb->volpath);
      free(cdb);
  }
  
diff --combined libatalk/cnid/cnid.c
index fde4d70f500298b3de09f6189de46e7f2eaffe22,f0b8903d6ccf95782bbb7dcd4809d01239733402..24de358895f931b97cb94cb9ff7320bc3dcb5178
@@@ -30,7 -30,6 +30,7 @@@
  #include <atalk/logger.h>
  #include <atalk/util.h>
  #include <atalk/compat.h>
 +#include <atalk/volume.h>
  
  /* List of all registered modules. */
  static struct list_head modules = ATALK_LIST_HEAD_INIT(modules);
@@@ -48,7 -47,7 +48,7 @@@ void cnid_register(struct _cnid_module 
      /* Check if our module is already registered. */
      list_for_each(ptr, &modules)
          if (0 == strcmp(list_entry(ptr, cnid_module, db_list)->name, module->name)) {
-         LOG(log_error, logtype_afpd, "Module with name [%s] is already registered !", module->name);
+         LOG(log_error, logtype_afpd, "Module with name [%s] is already registered!", module->name);
          return;
      }
  
@@@ -92,7 -91,8 +92,7 @@@ static int cnid_dir(const char *dir, mo
  }
  
  /* Opens CNID database using particular back-end */
 -struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int flags,
 -                           const char *cnidsrv, const char *cnidport)
 +struct _cnid_db *cnid_open(struct vol *vol, char *type, int flags)
  {
      struct _cnid_db *db;
      cnid_module *mod = NULL;
              LOG(log_error, logtype_afpd, "seteuid failed %s", strerror(errno));
              return NULL;
          }
 -        if (cnid_dir(volpath, mask) < 0) {
 +        if (cnid_dir(vol->v_path, vol->v_umask) < 0) {
              if ( setegid(gid) < 0 || seteuid(uid) < 0) {
                  LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno));
                  exit(EXITERR_SYS);
          }
      }
  
 -    struct cnid_open_args args = {volpath, mask, flags, cnidsrv, cnidport};
 +    struct cnid_open_args args =  {
 +        .cnid_args_flags = flags,
 +        .cnid_args_vol   = vol
 +    };
 +
      db = mod->cnid_open(&args);
  
      if ((mod->flags & CNID_FLAG_SETUID) && !(flags & CNID_FLAG_MEMORY)) {
      }
  
      if (NULL == db) {
 -        LOG(log_error, logtype_afpd, "Cannot open CNID db at [%s].", volpath);
 +        LOG(log_error, logtype_afpd, "Cannot open CNID db at [%s].", vol->v_path);
          return NULL;
      }
 -    /* FIXME should module know about it ? */
 -    if ((flags & CNID_FLAG_NODEV)) {
 -        db->flags |= CNID_FLAG_NODEV;
 -    }
 -    db->flags |= mod->flags;
  
 -    if ((db->flags & CNID_FLAG_BLOCK)) {
 +    db->cnid_db_flags |= mod->flags;
 +    if (flags & CNID_FLAG_NODEV)
 +        db->cnid_db_flags |= CNID_FLAG_NODEV;
 +
 +    if (db->cnid_db_flags & CNID_FLAG_BLOCK) {
          sigemptyset(&sigblockset);
          sigaddset(&sigblockset, SIGTERM);
          sigaddset(&sigblockset, SIGHUP);
@@@ -206,11 -203,11 +206,11 @@@ void cnid_close(struct _cnid_db *db
      uint32_t flags;
  
      if (NULL == db) {
-         LOG(log_error, logtype_afpd, "Error: cnid_close called with NULL argument !");
+         LOG(log_error, logtype_afpd, "Error: cnid_close called with NULL argument!");
          return;
      }
      /* cnid_close free db */
 -    flags = db->flags;
 +    flags = db->cnid_db_flags;
      block_signal(flags);
      db->cnid_close(db);
      unblock_signal(flags);
@@@ -225,9 -222,9 +225,9 @@@ cnid_t cnid_add(struct _cnid_db *cdb, c
      if (len == 0)
          return CNID_INVALID;
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = valide(cdb->cnid_add(cdb, st, did, name, len, hint));
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
  
@@@ -236,9 -233,9 +236,9 @@@ int cnid_delete(struct _cnid_db *cdb, c
  {
  int ret;
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = cdb->cnid_delete(cdb, id);
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
  
@@@ -248,9 -245,9 +248,9 @@@ cnid_t cnid_get(struct _cnid_db *cdb, c
  {
  cnid_t ret;
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = valide(cdb->cnid_get(cdb, did, name, len));
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
  
@@@ -269,9 -266,9 +269,9 @@@ time_t t
        memcpy(buffer, &t, sizeof(time_t));
          return 0;
      }
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = cdb->cnid_getstamp(cdb, buffer, len);
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
  
@@@ -281,9 -278,9 +281,9 @@@ cnid_t cnid_lookup(struct _cnid_db *cdb
  {
      cnid_t ret;
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = valide(cdb->cnid_lookup(cdb, st, did, name, len));
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
  
@@@ -297,9 -294,9 +297,9 @@@ int cnid_find(struct _cnid_db *cdb, con
          return -1;
      }
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = cdb->cnid_find(cdb, name, namelen, buffer, buflen);
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
  
@@@ -308,9 -305,9 +308,9 @@@ char *cnid_resolve(struct _cnid_db *cdb
  {
  char *ret;
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = cdb->cnid_resolve(cdb, id, buffer, len);
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      if (ret && !strcmp(ret, "..")) {
          LOG(log_error, logtype_afpd, "cnid_resolve: name is '..', corrupted db? ");
          ret = NULL;
@@@ -324,9 -321,9 +324,9 @@@ int cnid_update   (struct _cnid_db *cdb
  {
  int ret;
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = cdb->cnid_update(cdb, id, st, did, name, len);
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
                        
@@@ -336,20 -333,8 +336,20 @@@ cnid_t cnid_rebuild_add(struct _cnid_d
  {
  cnid_t ret;
  
 -    block_signal(cdb->flags);
 +    block_signal(cdb->cnid_db_flags);
      ret = cdb->cnid_rebuild_add(cdb, st, did, name, len, hint);
 -    unblock_signal(cdb->flags);
 +    unblock_signal(cdb->cnid_db_flags);
 +    return ret;
 +}
 +
 +/* --------------- */
 +int cnid_wipe(struct _cnid_db *cdb)
 +{
 +    int ret = 0;
 +
 +    block_signal(cdb->cnid_db_flags);
 +    if (cdb->cnid_wipe)
 +        ret = cdb->cnid_wipe(cdb);
 +    unblock_signal(cdb->cnid_db_flags);
      return ret;
  }
index d4606400aa1539e6bd64bf52b24c410bfa1a3b9e,c96a22596163659fc87be4a6b3a60f3eafc6e321..09cf9ead2ed4f4cc10cf6f4458b8e85545afb7b8
@@@ -31,9 -31,8 +31,9 @@@
  #include <atalk/logger.h>
  #include <atalk/adouble.h>
  #include <atalk/cnid.h>
 -#include <atalk/cnid_dbd_private.h>
 +#include <atalk/cnid_bdb_private.h>
  #include <atalk/util.h>
 +#include <atalk/volume.h>
  
  #include "cnid_dbd.h"
  
@@@ -225,49 -224,27 +225,49 @@@ static int write_vec(int fd, struct iov
  }
  
  /* --------------------- */
 -static int init_tsock(CNID_private *db)
 +static int init_tsock(CNID_bdb_private *db)
  {
      int fd;
 -    int len;
 -    struct iovec iov[2];
 +    int len[DBD_NUM_OPEN_ARGS];
 +    int iovecs;
 +    struct iovec iov[DBD_NUM_OPEN_ARGS + 1] = {{0}};
 +    struct vol *vol = db->vol;
 +    ssize_t iovlen;
  
 -    LOG(log_debug, logtype_cnid, "init_tsock: BEGIN. Opening volume '%s', CNID Server: %s/%s",
 -        db->db_dir, db->cnidserver, db->cnidport);
 +    LOG(log_debug, logtype_cnid, "connecting to CNID server: %s:%s",
 +        vol->v_cnidserver, vol->v_cnidport);
  
 -    if ((fd = tsock_getfd(db->cnidserver, db->cnidport)) < 0)
 +    if ((fd = tsock_getfd(vol->v_cnidserver, vol->v_cnidport)) < 0)
          return -1;
  
 -    len = strlen(db->db_dir);
 +    LOG(log_debug, logtype_cnid, "connecting volume '%s', path: %s, user: %s",
 +        vol->v_configname, vol->v_path, vol->v_obj->username[0] ? vol->v_obj->username : "-");
 +
 +    iovecs = 1 + DBD_NUM_OPEN_ARGS - 1;
 +
 +    len[0] = strlen(vol->v_configname) + 1;
 +    len[1] = strlen(vol->v_path) + 1;
 +    len[2] = strlen(vol->v_obj->username);
 +
 +    iov[0].iov_base = &len[0];
 +    iov[0].iov_len  = DBD_NUM_OPEN_ARGS * sizeof(int);
  
 -    iov[0].iov_base = &len;
 -    iov[0].iov_len  = sizeof(int);
 +    iov[1].iov_base = vol->v_configname;
 +    iov[1].iov_len  = len[0];
  
 -    iov[1].iov_base = db->db_dir;
 -    iov[1].iov_len  = len;
 +    iov[2].iov_base = vol->v_path;
 +    iov[2].iov_len  = len[1];
  
 -    if (write_vec(fd, iov, len + sizeof(int), 2) != len + sizeof(int)) {
 +    if (len[2] > 0) {
 +        len[2] += 1;
 +        iovecs++;
 +        iov[3].iov_base = vol->v_obj->username;
 +        iov[3].iov_len  = len[2];
 +    }
 +
 +    iovlen = iov[0].iov_len + iov[1].iov_len + iov[2].iov_len + iov[3].iov_len;
 +
 +    if (write_vec(fd, iov, iovlen, iovecs) != iovlen) {
          LOG(log_error, logtype_cnid, "init_tsock: Error/short write: %s", strerror(errno));
          close(fd);
          return -1;
  }
  
  /* --------------------- */
 -static int send_packet(CNID_private *db, struct cnid_dbd_rqst *rqst)
 +static int send_packet(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst)
  {
      struct iovec iov[2];
      size_t towrite;
      }
  
      if (write_vec(db->fd, iov, towrite, vecs) != towrite) {
 -        LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (db_dir %s): %s",
 -            db->db_dir, strerror(errno));
 +        LOG(log_warning, logtype_cnid, "send_packet: Error writev rqst (volume %s): %s",
 +            db->vol->v_localname, strerror(errno));
          return -1;
      }
  
@@@ -335,7 -312,7 +335,7 @@@ static int dbd_reply_stamp(struct cnid_
   * assume send is non blocking
   * if no answer after sometime (at least MAX_DELAY secondes) return an error
   */
 -static int dbd_rpc(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 +static int dbd_rpc(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
  {
      ssize_t ret;
      char *nametmp;
      ret = readt(db->fd, rply, sizeof(struct cnid_dbd_rply), 0, ONE_DELAY);
  
      if (ret != sizeof(struct cnid_dbd_rply)) {
 -        LOG(log_debug, logtype_cnid, "dbd_rpc: Error reading header from fd (db_dir %s): %s",
 -            db->db_dir, ret == -1 ? strerror(errno) : "closed");
 +        LOG(log_debug, logtype_cnid, "dbd_rpc: Error reading header from fd (volume %s): %s",
 +            db->vol->v_localname, ret == -1 ? strerror(errno) : "closed");
          rply->name = nametmp;
          return -1;
      }
      rply->name = nametmp;
      if (rply->namelen && rply->namelen > len) {
          LOG(log_error, logtype_cnid,
 -            "dbd_rpc: Error reading name (db_dir %s): %s name too long: %d. only wanted %d, garbage?",
 -            db->db_dir, rply->name, rply->namelen, len);
 +            "dbd_rpc: Error reading name (volume %s): %s name too long: %d. only wanted %d, garbage?",
 +            db->vol->v_localname, rply->name, rply->namelen, len);
          return -1;
      }
      if (rply->namelen && (ret = readt(db->fd, rply->name, rply->namelen, 0, ONE_DELAY)) != (ssize_t)rply->namelen) {
 -        LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (db_dir %s): %s",
 -            db->db_dir, ret == -1?strerror(errno):"closed");
 +        LOG(log_error, logtype_cnid, "dbd_rpc: Error reading name from fd (volume %s): %s",
 +            db->vol->v_localname, ret == -1?strerror(errno):"closed");
          return -1;
      }
  
  }
  
  /* -------------------- */
 -static int transmit(CNID_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
 +static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid_dbd_rply *rply)
  {
      time_t orig, t;
      int clean = 1; /* no errors so far - to prevent sleep on first try */
  
 -    if (db->changed) {
 -        /* volume and db don't have the same timestamp
 -         */
 -        return -1;
 -    }
      while (1) {
          if (db->fd == -1) {
 -            struct cnid_dbd_rqst rqst_stamp;
 -            struct cnid_dbd_rply rply_stamp;
 -            char  stamp[ADEDLEN_PRIVSYN];
 -
              LOG(log_maxdebug, logtype_cnid, "transmit: connecting to cnid_dbd ...");
              if ((db->fd = init_tsock(db)) < 0) {
                  goto transmit_fail;
              }
 -            dbd_initstamp(&rqst_stamp);
 -            memset(stamp, 0, ADEDLEN_PRIVSYN);
 -            rply_stamp.name = stamp;
 -            rply_stamp.namelen = ADEDLEN_PRIVSYN;
 -
 -            if (dbd_rpc(db, &rqst_stamp, &rply_stamp) < 0)
 -                goto transmit_fail;
 -            if (dbd_reply_stamp(&rply_stamp ) < 0)
 -                goto transmit_fail;
 -
              if (db->notfirst) {
 -                LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd, comparing database stamps...");
 -                if (memcmp(stamp, db->stamp, ADEDLEN_PRIVSYN)) {
 -                    LOG(log_error, logtype_cnid, "transmit: ... not the same db!");
 -                    db->changed = 1;
 -                    return -1;
 -                }
 -                LOG(log_debug7, logtype_cnid, "transmit: ... OK.");
 +                LOG(log_debug7, logtype_cnid, "transmit: reconnected to cnid_dbd");
              } else { /* db->notfirst == 0 */
                  db->notfirst = 1;
 -                if (db->client_stamp)
 -                    memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
 -                memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
              }
 -            LOG(log_debug, logtype_cnid, "transmit: attached to '%s', stamp: '%08lx'.",
 -                db->db_dir, *(uint64_t *)stamp);
 +            LOG(log_debug, logtype_cnid, "transmit: attached to '%s'", db->vol->v_localname);
          }
          if (!dbd_rpc(db, rqst, rply)) {
              LOG(log_maxdebug, logtype_cnid, "transmit: {done}");
  
          if (errno == ECONNREFUSED) { /* errno carefully injected in tsock_getfd */
              /* give up */
 -            LOG(log_error, logtype_cnid, "transmit: connection refused (db_dir %s)", db->db_dir);
 +            LOG(log_error, logtype_cnid, "transmit: connection refused (volume %s)", db->vol->v_localname);
              return -1;
          }
  
          if (!clean) { /* don't sleep if just got disconnected by cnid server */
              time(&t);
              if (t - orig > MAX_DELAY) {
 -                LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (db_dir %s) timed out.", db->db_dir);
 +                LOG(log_error, logtype_cnid, "transmit: Request to dbd daemon (volume %s) timed out.", db->vol->v_localname);
                  return -1;
              }
              /* sleep a little before retry */
  }
  
  /* ---------------------- */
 -static struct _cnid_db *cnid_dbd_new(const char *volpath)
 +static struct _cnid_db *cnid_dbd_new(struct vol *vol)
  {
      struct _cnid_db *cdb;
  
      if ((cdb = (struct _cnid_db *)calloc(1, sizeof(struct _cnid_db))) == NULL)
          return NULL;
  
 -    if ((cdb->volpath = strdup(volpath)) == NULL) {
 -        free(cdb);
 -        return NULL;
 -    }
 -
 -    cdb->flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT;
 -
 +    cdb->cnid_db_vol = vol;
 +    cdb->cnid_db_flags = CNID_FLAG_PERSISTENT | CNID_FLAG_LAZY_INIT;
      cdb->cnid_add = cnid_dbd_add;
      cdb->cnid_delete = cnid_dbd_delete;
      cdb->cnid_get = cnid_dbd_get;
      cdb->cnid_update = cnid_dbd_update;
      cdb->cnid_rebuild_add = cnid_dbd_rebuild_add;
      cdb->cnid_close = cnid_dbd_close;
 -
 +    cdb->cnid_wipe = cnid_dbd_wipe;
      return cdb;
  }
  
  /* ---------------------- */
  struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args)
  {
 -    CNID_private *db = NULL;
 +    CNID_bdb_private *db = NULL;
      struct _cnid_db *cdb = NULL;
  
 -    if (!args->dir) {
 -        return NULL;
 -    }
 -
 -    if ((cdb = cnid_dbd_new(args->dir)) == NULL) {
 +    if ((cdb = cnid_dbd_new(args->cnid_args_vol)) == NULL) {
          LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database");
          return NULL;
      }
  
 -    if ((db = (CNID_private *)calloc(1, sizeof(CNID_private))) == NULL) {
 +    if ((db = (CNID_bdb_private *)calloc(1, sizeof(CNID_bdb_private))) == NULL) {
          LOG(log_error, logtype_cnid, "cnid_open: Unable to allocate memory for database");
          goto cnid_dbd_open_fail;
      }
  
 -    cdb->_private = db;
 +    cdb->cnid_db_private = db;
  
 -    /* We keep a copy of the directory in the db structure so that we can
 -       transparently reconnect later. */
 -    strcpy(db->db_dir, args->dir);
 -    db->magic = CNID_DB_MAGIC;
      db->fd = -1;
 -    db->cnidserver = strdup(args->cnidserver);
 -    db->cnidport = strdup(args->cnidport);
 +    db->vol = args->cnid_args_vol;
  
 -    LOG(log_debug, logtype_cnid, "cnid_dbd_open: Finished initializing cnid dbd module for volume '%s'", db->db_dir);
 +    LOG(log_debug, logtype_cnid, "Finished initializing CNID dbd module for volume '%s'",
 +        args->cnid_args_vol->v_localname);
  
      return cdb;
  
  cnid_dbd_open_fail:
 -    if (cdb != NULL) {
 -        if (cdb->volpath != NULL) {
 -            free(cdb->volpath);
 -        }
 +    if (cdb != NULL)
          free(cdb);
 -    }
      if (db != NULL)
          free(db);
  
  /* ---------------------- */
  void cnid_dbd_close(struct _cnid_db *cdb)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
  
      if (!cdb) {
-         LOG(log_error, logtype_cnid, "cnid_close called with NULL argument !");
+         LOG(log_error, logtype_cnid, "cnid_close called with NULL argument!");
          return;
      }
  
 -    if ((db = cdb->_private) != NULL) {
 -        LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->db_dir);
 +    if ((db = cdb->cnid_db_private) != NULL) {
 +        LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->vol->v_localname);
  
          if (db->fd >= 0)
              close(db->fd);
          free(db);
      }
  
 -    free(cdb->volpath);
      free(cdb);
  
      return;
  }
  
 +/**
 + * Get the db stamp
 + **/
 +static int cnid_dbd_stamp(CNID_bdb_private *db)
 +{
 +    struct cnid_dbd_rqst rqst_stamp;
 +    struct cnid_dbd_rply rply_stamp;
 +    char  stamp[ADEDLEN_PRIVSYN];
 +
 +    dbd_initstamp(&rqst_stamp);
 +    memset(stamp, 0, ADEDLEN_PRIVSYN);
 +    rply_stamp.name = stamp;
 +    rply_stamp.namelen = ADEDLEN_PRIVSYN;
 +
 +    if (transmit(db, &rqst_stamp, &rply_stamp) < 0)
 +        return -1;
 +    if (dbd_reply_stamp(&rply_stamp ) < 0)
 +        return -1;
 +
 +    if (db->client_stamp)
 +        memcpy(db->client_stamp, stamp, ADEDLEN_PRIVSYN);
 +    memcpy(db->stamp, stamp, ADEDLEN_PRIVSYN);
 +
 +    return 0;
 +}
 +
  /* ---------------------- */
  cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
                      cnid_t did, const char *name, size_t len, cnid_t hint)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
      cnid_t id;
  
 -    if (!cdb || !(db = cdb->_private) || !st || !name) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) {
          LOG(log_error, logtype_cnid, "cnid_add: Parameter error");
          errno = CNID_ERR_PARAM;
          return CNID_INVALID;
      RQST_RESET(&rqst);
      rqst.op = CNID_DBD_OP_ADD;
  
 -    if (!(cdb->flags & CNID_FLAG_NODEV)) {
 +    if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) {
          rqst.dev = st->st_dev;
      }
  
      rqst.name = name;
      rqst.namelen = len;
  
 -    LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', inode: 0x%llx, type: %d (0=file, 1=dir)",
 -        ntohl(did), name, (long long)st->st_ino, rqst.type);
 +    LOG(log_debug, logtype_cnid, "cnid_dbd_add: CNID: %u, name: '%s', dev: 0x%llx, inode: 0x%llx, type: %s",
 +        ntohl(did), name, (long long)rqst.dev, (long long)st->st_ino, rqst.type ? "dir" : "file");
  
      rply.namelen = 0;
      if (transmit(db, &rqst, &rply) < 0) {
  /* ---------------------- */
  cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
      cnid_t id;
  
 -    if (!cdb || !(db = cdb->_private) || !name) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !name) {
          LOG(log_error, logtype_cnid, "cnid_dbd_get: Parameter error");
          errno = CNID_ERR_PARAM;
          return CNID_INVALID;
  /* ---------------------- */
  char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
      char *name;
  
 -    if (!cdb || !(db = cdb->_private) || !id || !(*id)) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) {
          LOG(log_error, logtype_cnid, "cnid_resolve: Parameter error");
          errno = CNID_ERR_PARAM;
          return NULL;
      return name;
  }
  
 -/* ---------------------- */
 +/**
 + * Caller passes buffer where we will store the db stamp
 + **/
  int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
  
 -    if (!cdb || !(db = cdb->_private) || len != ADEDLEN_PRIVSYN) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || len != ADEDLEN_PRIVSYN) {
          LOG(log_error, logtype_cnid, "cnid_getstamp: Parameter error");
          errno = CNID_ERR_PARAM;
          return -1;
      }
      db->client_stamp = buffer;
      db->stamp_size = len;
 -    memset(buffer,0, len);
 -    return 0;
 +
 +    return cnid_dbd_stamp(db);
  }
  
  /* ---------------------- */
  cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
                         const char *name, size_t len)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
      cnid_t id;
  
 -    if (!cdb || !(db = cdb->_private) || !st || !name) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) {
          LOG(log_error, logtype_cnid, "cnid_lookup: Parameter error");
          errno = CNID_ERR_PARAM;
          return CNID_INVALID;
      RQST_RESET(&rqst);
      rqst.op = CNID_DBD_OP_LOOKUP;
  
 -    if (!(cdb->flags & CNID_FLAG_NODEV)) {
 +    if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) {
          rqst.dev = st->st_dev;
      }
  
  /* ---------------------- */
  int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
      int count;
  
 -    if (!cdb || !(db = cdb->_private) || !name) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !name) {
          LOG(log_error, logtype_cnid, "cnid_find: Parameter error");
          errno = CNID_ERR_PARAM;
          return CNID_INVALID;
  int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
                      cnid_t did, const char *name, size_t len)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
  
 -    if (!cdb || !(db = cdb->_private) || !id || !st || !name) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name) {
          LOG(log_error, logtype_cnid, "cnid_update: Parameter error");
          errno = CNID_ERR_PARAM;
          return -1;
      RQST_RESET(&rqst);
      rqst.op = CNID_DBD_OP_UPDATE;
      rqst.cnid = id;
 -    if (!(cdb->flags & CNID_FLAG_NODEV)) {
 +    if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) {
          rqst.dev = st->st_dev;
      }
      rqst.ino = st->st_ino;
  cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
                              cnid_t did, const char *name, size_t len, cnid_t hint)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
      cnid_t id;
  
 -    if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name || hint == CNID_INVALID) {
          LOG(log_error, logtype_cnid, "cnid_rebuild_add: Parameter error");
          errno = CNID_ERR_PARAM;
          return CNID_INVALID;
      RQST_RESET(&rqst);
      rqst.op = CNID_DBD_OP_REBUILD_ADD;
  
 -    if (!(cdb->flags & CNID_FLAG_NODEV)) {
 +    if (!(cdb->cnid_db_flags & CNID_FLAG_NODEV)) {
          rqst.dev = st->st_dev;
      }
  
  /* ---------------------- */
  int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id)
  {
 -    CNID_private *db;
 +    CNID_bdb_private *db;
      struct cnid_dbd_rqst rqst;
      struct cnid_dbd_rply rply;
  
 -    if (!cdb || !(db = cdb->_private) || !id) {
 +    if (!cdb || !(db = cdb->cnid_db_private) || !id) {
          LOG(log_error, logtype_cnid, "cnid_delete: Parameter error");
          errno = CNID_ERR_PARAM;
          return -1;
      }
  }
  
 +int cnid_dbd_wipe(struct _cnid_db *cdb)
 +{
 +    CNID_bdb_private *db;
 +    struct cnid_dbd_rqst rqst;
 +    struct cnid_dbd_rply rply;
 +
 +    if (!cdb || !(db = cdb->cnid_db_private)) {
 +        LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error");
 +        errno = CNID_ERR_PARAM;
 +        return -1;
 +    }
 +
 +    LOG(log_debug, logtype_cnid, "cnid_dbd_wipe");
 +
 +    RQST_RESET(&rqst);
 +    rqst.op = CNID_DBD_OP_WIPE;
 +    rqst.cnid = 0;
 +
 +    rply.namelen = 0;
 +    if (transmit(db, &rqst, &rply) < 0) {
 +        errno = CNID_ERR_DB;
 +        return -1;
 +    }
 +
 +    if (rply.result != CNID_DBD_RES_OK) {
 +        errno = CNID_ERR_DB;
 +        return -1;
 +    }
 +    LOG(log_debug, logtype_cnid, "cnid_dbd_wipe: ok");
 +
 +    return cnid_dbd_stamp(db);
 +}
 +
  
  struct _cnid_module cnid_dbd_module = {
      "dbd",
diff --combined macros/netatalk.m4
index 060e467964a65f15d8ecb0402fd49f8917469eb7,34dfc08cc6c31128da4503e6e857a4ab6fc1038d..d8482f8d9384359a80d6a52537cf4cefed39916b
  dnl Kitchen sink for configuration macros
  
 +dnl Check for docbook
 +AC_DEFUN(AX_CHECK_DOCBOOK, [
 +  # It's just rude to go over the net to build
 +  XSLTPROC_FLAGS=--nonet
 +  DOCBOOK_ROOT=
 +  XSLTPROC_WORKS=no
 +
 +  AC_ARG_WITH(docbook,
 +    AS_HELP_STRING(
 +      [--with-docbook],
 +      [Path to Docbook XSL directory]
 +    ),
 +    [DOCBOOK_ROOT=$withval]
 +  )
 +
 +  if test -n "$DOCBOOK_ROOT" ; then
 +    AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,)
 +    if test -n "$XSLTPROC"; then
 +      AC_MSG_CHECKING([whether xsltproc works])
 +      DB_FILE="$DOCBOOK_ROOT/html/docbook.xsl"
 +      $XSLTPROC $XSLTPROC_FLAGS $DB_FILE >/dev/null 2>&1 << END
 +<?xml version="1.0" encoding='ISO-8859-1'?>
 +<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">
 +<book id="test">
 +</book>
 +END
 +      if test "$?" = 0; then
 +        XSLTPROC_WORKS=yes
 +      fi
 +      AC_MSG_RESULT($XSLTPROC_WORKS)
 +    fi
 +  fi
 +
 +  AC_MSG_CHECKING([whether to build Docbook documentation])
 +  AC_MSG_RESULT($XSLTPROC_WORKS)
 +
 +  AM_CONDITIONAL(HAVE_XSLTPROC, test x"$XSLTPROC_WORKS" = x"yes")
 +  AC_SUBST(XSLTPROC_FLAGS)
 +  AC_SUBST(DOCBOOK_ROOT)
 +  AC_SUBST(XSLTPROC)
 +])
 +
 +dnl Check for dtrace
 +AC_DEFUN([AC_NETATALK_DTRACE], [
 +  AC_ARG_WITH(dtrace,
 +    AS_HELP_STRING(
 +      [--with-dtrace],
 +      [Enable dtrace probes (default: enabled if dtrace found)]
 +    ),
 +    [WDTRACE=$withval],
 +    [WDTRACE=auto]
 +  )
 +  if test "x$WDTRACE" = "xyes" -o "x$WDTRACE" = "xauto" ; then
 +    AC_CHECK_PROG([atalk_cv_have_dtrace], [dtrace], [yes], [no])
 +    if test "x$atalk_cv_have_dtrace" = "xno" ; then
 +      if test "x$WDTRACE" = "xyes" ; then
 +        AC_MSG_FAILURE([dtrace requested but not found])
 +      fi
 +      WDTRACE="no"
 +    else
 +      WDTRACE="yes"
 +    fi
 +  fi
 +
 +  if test x"$WDTRACE" = x"yes" ; then
 +    AC_DEFINE([WITH_DTRACE], [1], [dtrace probes])
 +    DTRACE_LIBS=""
 +    if test x"$this_os" = x"freebsd" ; then
 +      DTRACE_LIBS="-lelf"
 +    fi
 +    AC_SUBST(DTRACE_LIBS)
 +  fi
 +  AM_CONDITIONAL(WITH_DTRACE, test "x$WDTRACE" = "xyes")
 +])
 +
 +dnl Check for dbus-glib, for AFP stats
 +AC_DEFUN([AC_NETATALK_DBUS_GLIB], [
 +  atalk_cv_with_dbus=no
 +
 +  AC_ARG_WITH(afpstats,
 +    AS_HELP_STRING(
 +      [--with-afpstats],
 +      [Enable AFP statistics via dbus (default: enabled if dbus found)]
 +    ),,[withval=auto]
 +  )
 +
 +  if test x"$withval" != x"no" ; then
 +    PKG_CHECK_MODULES(DBUS, dbus-1 >= 1.1, have_dbus=yes, have_dbus=no)
 +    PKG_CHECK_MODULES(DBUS_GLIB, dbus-glib-1, have_dbus_glib=yes, have_dbus_glib=no)
 +    PKG_CHECK_MODULES(DBUS_GTHREAD, gthread-2.0, have_dbus_gthread=yes, have_dbus_gthread=no)
 +    if test x$have_dbus_glib = xyes -a x$have_dbus = xyes -a x$have_dbus_gthread = xyes ; then
 +        saved_CFLAGS=$CFLAGS
 +        saved_LIBS=$LIBS
 +        CFLAGS="$CFLAGS $DBUS_GLIB_CFLAGS"
 +        LIBS="$LIBS $DBUS_GLIB_LIBS"
 +        AC_CHECK_FUNC([dbus_g_bus_get_private], [atalk_cv_with_dbus=yes], [atalk_cv_with_dbus=no])
 +        CFLAGS="$saved_CFLAGS"
 +        LIBS="$saved_LIBS"
 +    fi
 +  fi
 +
 +  if test x"$withval" = x"yes" -a x"$atalk_cv_with_dbus" = x"no"; then
 +    AC_MSG_ERROR([afpstats requested but dbus-glib not found])
 +  fi
 +
 +  AC_ARG_WITH(
 +      dbus-sysconf-dir,
 +      [AS_HELP_STRING([--with-dbus-sysconf-dir=PATH],[Path to dbus system bus security configuration directory (default: ${sysconfdir}/dbus-1/system.d/)])],
 +      ac_cv_dbus_sysdir=$withval,
 +      ac_cv_dbus_sysdir='${sysconfdir}/dbus-1/system.d'
 +  )
 +  DBUS_SYS_DIR=""
 +  if test x$atalk_cv_with_dbus = xyes ; then
 +      AC_DEFINE(HAVE_DBUS_GLIB, 1, [Define if support for dbus-glib was found])
 +      DBUS_SYS_DIR="$ac_cv_dbus_sysdir"
 +  fi
 +
 +  AC_SUBST(DBUS_SYS_DIR)
 +  AC_SUBST(DBUS_CFLAGS)
 +  AC_SUBST(DBUS_LIBS)
 +  AC_SUBST(DBUS_GLIB_CFLAGS)
 +  AC_SUBST(DBUS_GLIB_LIBS)
 +  AC_SUBST(DBUS_GTHREAD_CFLAGS)
 +  AC_SUBST(DBUS_GTHREAD_LIBS)
 +  AM_CONDITIONAL(HAVE_DBUS_GLIB, test x$atalk_cv_with_dbus = xyes)
 +])
 +
  dnl Whether to enable developer build
  AC_DEFUN([AC_DEVELOPER], [
      AC_MSG_CHECKING([whether to enable developer build])
      AM_CONDITIONAL(DEVELOPER, test x"$enable_dev" = x"yes")
  ])
  
 +dnl Tracker, for Spotlight
 +AC_DEFUN([AC_NETATALK_SPOTLIGHT], [
 +    ac_cv_have_tracker=no
 +    ac_cv_tracker_pkg_version_default=0.12
 +    ac_cv_tracker_pkg_version_min=0.12
 +
 +    dnl Tracker SPARQL
 +    AC_ARG_WITH([tracker-pkgconfig-version],
 +      [AS_HELP_STRING([--with-tracker-pkgconfig-version=VERSION],[Version suffix of the Tracker SPARQL and tracker-miner pkg in pkg-config (default: 0.12)])],
 +      [ac_cv_tracker_pkg_version=$withval],
 +      [ac_cv_tracker_pkg_version=$ac_cv_tracker_pkg_version_default]
 +    )
 +
 +    AC_ARG_WITH([tracker-prefix],
 +      [AS_HELP_STRING([--with-tracker-prefix=PATH],[Prefix of Tracker installation (default: none)])],
 +      [ac_cv_tracker_prefix=$withval],
 +      [ac_cv_tracker_prefix="`pkg-config --variable=prefix tracker-sparql-$ac_cv_tracker_pkg_version`"]
 +    )
 +
 +    AC_ARG_VAR([PKG_CONFIG_PATH], [Path to additional pkg-config packages])
 +    PKG_CHECK_MODULES([TRACKER], [tracker-sparql-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min], [ac_cv_have_tracker_sparql=yes], [ac_cv_have_tracker_sparql=no])
 +    PKG_CHECK_MODULES([TRACKER_MINER], [tracker-miner-$ac_cv_tracker_pkg_version >= $ac_cv_tracker_pkg_version_min], [ac_cv_have_tracker_miner=yes], [ac_cv_have_tracker_miner=no])
 +
 +    if test x"$ac_cv_have_tracker_sparql" = x"no" -o x"$ac_cv_have_tracker_miner" = x"no" ; then
 +        if test x"$need_tracker_sparql" = x"yes" ; then
 +            AC_MSG_ERROR([$ac_cv_tracker_pkg not found])
 +        fi
 +    else
 +        AC_DEFINE(HAVE_TRACKER, 1, [Define if Tracker is available])
 +        AC_DEFINE(HAVE_TRACKER_SPARQL, 1, [Define if Tracker SPARQL is available])
 +        AC_DEFINE(HAVE_TRACKER_MINER, 1, [Define if Tracker miner library is available])
 +        AC_DEFINE_UNQUOTED(TRACKER_PREFIX, ["$ac_cv_tracker_prefix"], [Path to Tracker])
 +        AC_DEFINE([DBUS_DAEMON_PATH], ["/bin/dbus-daemon"], [Path to dbus-daemon])
 +    fi
 +
 +    if test x"$ac_cv_have_tracker_sparql" = x"yes" ; then
 +       ac_cv_have_tracker=yes
 +    fi
 +
 +    AC_SUBST(TRACKER_CFLAGS)
 +    AC_SUBST(TRACKER_LIBS)
 +    AC_SUBST(TRACKER_MINER_CFLAGS)
 +    AC_SUBST(TRACKER_MINER_LIBS)
 +    AM_CONDITIONAL(HAVE_TRACKER_SPARQL, [test x"$ac_cv_have_tracker_sparql" = x"yes"])
 +])
 +
  dnl Whether to disable bundled libevent
  AC_DEFUN([AC_NETATALK_LIBEVENT], [
 -    use_bundled_libevent=no
 -    AC_MSG_CHECKING([whether to use bundled or installed libevent])
 +    AC_MSG_CHECKING([whether to use bundled libevent])
 +    AC_ARG_WITH(
 +        libevent,
 +        [AS_HELP_STRING([--with-libevent],[whether to use the bundled libevent (default: yes)])],
 +        use_bundled_libevent=$withval,
 +        use_bundled_libevent=yes
 +    )
      AC_ARG_WITH(
          libevent-header,
          [AS_HELP_STRING([--with-libevent-header],[path to libevent header files])],
 -        LIBEVENT_CFLAGS=-I$withval,
 -        use_bundled_libevent=yes
 +        [use_bundled_libevent=no; LIBEVENT_CFLAGS=-I$withval]
      )
      AC_ARG_WITH(
          libevent-lib,
 -        [AS_HELP_STRING([--with-libevent-lib],[path to libevent header library])],
 -        LIBEVENT_LDFLAGS=-L$withval,
 -        use_bundled_libevent=yes
 +        [AS_HELP_STRING([--with-libevent-lib],[path to libevent library])],
 +        [use_bundled_libevent=no; LIBEVENT_LDFLAGS=-L$withval]
      )
 +    if test x"$LIBEVENT_CFLAGS" = x"-Iyes" -o x"$LIBEVENT_LDFLAGS" = x"-Lyes" ; then
 +        AC_MSG_ERROR([--with-libevent requires a path])
 +    fi
      AC_MSG_RESULT([$use_bundled_libevent])
      if test x"$use_bundled_libevent" = x"yes" ; then
          AC_CONFIG_SUBDIRS([libevent])
      AM_CONDITIONAL(USE_BUILTIN_LIBEVENT, test x"$use_bundled_libevent" = x"yes")
  ])
  
 +dnl Whether to disable bundled tdb
 +AC_DEFUN([AC_NETATALK_TDB], [
 +    AC_ARG_WITH(
 +        tdb,
 +        [AS_HELP_STRING([--with-tdb],[whether to use the bundled tdb (default: yes)])],
 +        use_bundled_tdb=$withval,
 +        use_bundled_tdb=yes
 +    )
 +    AC_MSG_CHECKING([whether to use bundled tdb])
 +    AC_MSG_RESULT([$use_bundled_tdb])
 +
 +    if test x"$use_bundled_tdb" = x"yes" ; then
 +        AC_DEFINE(USE_BUILTIN_TDB, 1, [Use internal tbd])
 +    else
 +        if test -z "$TDB_LIBS" ; then
 +            PKG_CHECK_MODULES(TDB, tdb, , [AC_MSG_ERROR([couldn't find tdb with pkg-config])])
 +        fi
 +        use_bundled_tdb=no
 +    fi        
 +
 +    AC_SUBST(TDB_CFLAGS)
 +    AC_SUBST(TDB_LIBS)
 +    AM_CONDITIONAL(USE_BUILTIN_TDB, test x"$use_bundled_tdb" = x"yes")
 +])
 +
  dnl Filesystem Hierarchy Standard (FHS) compatibility
  AC_DEFUN([AC_NETATALK_FHS], [
  AC_MSG_CHECKING([whether to use Filesystem Hierarchy Standard (FHS) compatibility])
@@@ -260,47 -56,13 +260,47 @@@ AC_ARG_ENABLE(fhs
                use_pam_so=yes
                AC_DEFINE(FHS_COMPATIBILITY, 1, [Define if you want compatibily with the FHS])
                AC_MSG_RESULT([yes])
 +        atalk_cv_fhs_compat=yes
        else
                AC_MSG_RESULT([no])
 +        atalk_cv_fhs_compat=no
        fi
        ],[
                AC_MSG_RESULT([no])
 -      ]
 -)])
 +        atalk_cv_fhs_compat=no
 +])])
 +
 +dnl netatalk lockfile path
 +AC_DEFUN([AC_NETATALK_LOCKFILE], [
 +    AC_MSG_CHECKING([netatalk lockfile path])
 +    AC_ARG_WITH(
 +        lockfile,
 +        [AS_HELP_STRING([--with-lockfile=PATH],[Path of netatalk lockfile])],
 +        ac_cv_netatalk_lock=$withval,
 +        ac_cv_netatalk_lock=""
 +    )
 +    if test -z "$ac_cv_netatalk_lock" ; then
 +        ac_cv_netatalk_lock=/var/spool/locks/netatalk
 +        if test x"$atalk_cv_fhs_compat" = x"yes" ; then
 +            ac_cv_netatalk_lock=/var/run/netatalk.pid
 +        else
 +            case "$host_os" in
 +            *freebsd*)
 +                ac_cv_netatalk_lock=/var/spool/lock/netatalk
 +                ;;
 +            *netbsd*|*openbsd*)
 +                ac_cv_netatalk_lock=/var/run/netatalk.pid
 +                ;;
 +            *linux*)
 +                ac_cv_netatalk_lock=/var/lock/netatalk
 +                ;;
 +            esac
 +        fi
 +    fi
 +    AC_DEFINE_UNQUOTED(PATH_NETATALK_LOCK, ["$ac_cv_netatalk_lock"], [netatalk lockfile path])
 +    AC_SUBST(PATH_NETATALK_LOCK, ["$ac_cv_netatalk_lock"])
 +    AC_MSG_RESULT([$ac_cv_netatalk_lock])
 +])
  
  dnl 64bit platform check
  AC_DEFUN([AC_NETATALK_64BIT_LIBS], [
@@@ -483,7 -245,7 +483,7 @@@ AC_ARG_ENABLE(shell-check
  )
  ])
  
 -dnl Check for optional sysv initscript install
 +dnl Check for optional initscript install
  AC_DEFUN([AC_NETATALK_INIT_STYLE], [
      AC_ARG_WITH(init-style,
                  [  --with-init-style       use OS specific init config [[redhat-sysv|redhat-systemd|suse-sysv|suse-systemd|gentoo|netbsd|debian|solaris|systemd]]],
          ;;
      "redhat-sysv")
            AC_MSG_RESULT([enabling redhat-style sysv initscript support])
 +          ac_cv_init_dir="/etc/rc.d/init.d"
            ;;
      "redhat-systemd")
            AC_MSG_RESULT([enabling redhat-style systemd support])
 +          ac_cv_init_dir="/usr/lib/systemd/system"
            ;;
      "suse")
            AC_MSG_ERROR([--with-init-style=suse is obsoleted. Use suse-sysv or suse-systemd.])
          ;;
      "suse-sysv")
            AC_MSG_RESULT([enabling suse-style sysv initscript support])
 +          ac_cv_init_dir="/etc/init.d"
            ;;
      "suse-systemd")
            AC_MSG_RESULT([enabling suse-style systemd support (>=openSUSE12.1)])
 +          ac_cv_init_dir="/usr/lib/systemd/system"
            ;;
      "gentoo")
            AC_MSG_RESULT([enabling gentoo-style initscript support])
 +          ac_cv_init_dir="/etc/init.d"
          ;;
      "netbsd")
            AC_MSG_RESULT([enabling netbsd-style initscript support])
 +          ac_cv_init_dir="/etc/rc.d"
          ;;
      "debian")
            AC_MSG_RESULT([enabling debian-style initscript support])
 +          ac_cv_init_dir="/etc/init.d"
          ;;
      "solaris")
            AC_MSG_RESULT([enabling solaris-style SMF support])
 +          ac_cv_init_dir="/lib/svc/manifest/network/"
          ;;
      "systemd")
            AC_MSG_RESULT([enabling general systemd support])
 +          ac_cv_init_dir="/usr/lib/systemd/system"
          ;;
      "none")
            AC_MSG_RESULT([disabling init-style support])
 +          ac_cv_init_dir="none"
          ;;
      *)
            AC_MSG_ERROR([illegal init-style])
      AM_CONDITIONAL(USE_SYSTEMD, test x$init_style = xsystemd || test x$init_style = xredhat-systemd || test x$init_style = xsuse-systemd)
      AM_CONDITIONAL(USE_UNDEF, test x$init_style = xnone)
  
 +    AC_ARG_WITH(init-dir,
 +                [  --with-init-dir=PATH    path to OS specific init directory],
 +                ac_cv_init_dir="$withval", ac_cv_init_dir="$ac_cv_init_dir"
 +    )
 +    INIT_DIR="$ac_cv_init_dir"
 +    AC_SUBST(INIT_DIR, ["$ac_cv_init_dir"])
  ])
  
  dnl OS specific configuration
@@@ -609,7 -355,7 +609,7 @@@ f
  dnl ----- Linux specific -----
  if test x"$this_os" = "xlinux"; then 
        AC_MSG_RESULT([ * Linux specific configuration])
 -      
 +    AC_DEFINE(LINUX, 1, [OS is Linux])        
        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)
@@@ -656,8 -402,87 +656,8 @@@ if test x"$this_os" = "xsolaris"; the
        AC_DEFINE(SOLARIS, 1, [Solaris compatibility macro])
      AC_DEFINE(_XOPEN_SOURCE, 600, [Solaris compilation environment])
      AC_DEFINE(__EXTENSIONS__,  1, [Solaris compilation environment])
 -      CFLAGS="-I\$(top_srcdir)/sys/generic $CFLAGS"
        need_dash_r=yes
        init_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_LINK_IFELSE([AC_LANG_PROGRAM([[\
 -#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])])
 -
 -         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 Whether to run ldconfig after installing libraries
@@@ -756,7 -581,7 +756,7 @@@ save_CFLAGS="$CFLAGS
  save_LIBS="$LIBS"
  CFLAGS="$KRB5_CFLAGS"
  LIBS="$KRB5_LIBS"
 -AC_CHECK_FUNCS([krb5_free_unparsed_name krb5_free_error_message])
 +AC_CHECK_FUNCS([krb5_free_unparsed_name krb5_free_error_message krb5_free_keytab_entry_contents krb5_kt_free_entry])
  CFLAGS="$save_CFLAGS"
  LIBS="$save_LIBS"
  ])
@@@ -777,7 -602,7 +777,7 @@@ dnl Check for LDAP support, for client-
  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],
 +    [AS_HELP_STRING([--with-ldap[[=PATH]]],
          [LDAP support (default=auto)])],
          netatalk_cv_ldap=$withval,
          netatalk_cv_ldap=auto
@@@ -824,13 -649,12 +824,13 @@@ AC_SUBST(LDAP_CFLAGS
  AC_SUBST(LDAP_LDFLAGS)
  AC_SUBST(LDAP_LIBS)
  CFLAGS="$save_CFLAGS"
 -LDLFLAGS="$save_LDLFLAGS"
 +LDFLAGS="$save_LDFLAGS"
  LIBS="$save_LIBS"
  ])
  
  dnl Check for ACL support
  AC_DEFUN([AC_NETATALK_ACL], [
 +ac_cv_have_acls=no
  AC_MSG_CHECKING(whether to support ACLs)
  AC_ARG_WITH(acls,
      [AS_HELP_STRING([--with-acls],
@@@ -848,125 -672,112 +848,125 @@@ 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:)
 +# Platform specific checks
 +if test x"$with_acl_support" != x"no" ; then
        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])
 +              AC_DEFINE(HAVE_SOLARIS_ACLS,1,[Whether Solaris ACLs are available])
 +              AC_DEFINE(HAVE_NFSV4_ACLS,1,[Whether NFSv4 ACLs are available])
                ACL_LIBS="$ACL_LIBS -lsec"
 +              ac_cv_have_acls=yes
                ;;
 -      *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"
 +      *freebsd*)
 +              AC_MSG_NOTICE(checking whether libsunacl is available)
 +              sunacl_include_path="/usr/local/include"
 +              sunacl_lib_path="/usr/local/lib"
 +
 +              save_CPPFLAGS=$CPPFLAGS
 +              save_LDFLAGS=$LDFLAGS
 +              save_LIBS=$LIBS
 +
 +              CPPFLAGS="-I$sunacl_include_path $CPPFLAGS"
 +              AC_CHECK_HEADER([sunacl.h])
 +
 +              LDFLAGS="-L$sunacl_lib_path $LDFLAGS"
 +              AC_CHECK_LIB([sunacl], [acl])
 +
 +              if test x"$ac_cv_header_sunacl_h" = x"yes" -a x"$ac_cv_lib_sunacl_acl" = x"yes" ; then
 +                      AC_MSG_NOTICE([Enabling support for ZFS ACLs using libsunacl])
 +                      ac_cv_have_acls=yes
 +                      CFLAGS="-I$sunacl_include_path $CFLAGS"
 +                      ACL_LIBS="$ACL_LIBS -L$sunacl_lib_path -lsunacl"
 +                      AC_DEFINE(HAVE_FREEBSD_SUNACL, 1, [Whether FreeBSD ZFS ACLs with libsunacl are available])
 +                      AC_DEFINE(HAVE_NFSV4_ACLS,1,[Whether NFSv4 ACLs are available])
 +              else
 +                      AC_MSG_NOTICE([libsunacl not found, disabling ZFS ACL support])
 +              fi
 +
 +              CPPFLAGS=$save_CPPFLAGS
 +              LDFLAGS=$save_LDFLAGS
 +              LIBS=$save_LIBS
                ;;
 -      *darwin*)
 -              AC_MSG_NOTICE(ACLs on Darwin currently not supported)
 -              AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available])
 +      esac
 +fi
 +
 +if test x"$with_acl_support" != x"no" -a x"$ac_cv_have_acls" != x"yes" ; then
 +      # Runtime checks for POSIX ACLs
 +      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"])
                ;;
 -      *)
 -              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,[
 +      esac
 +
 +      AC_CACHE_CHECK([for POSIX ACL support],netatalk_cv_HAVE_POSIX_ACLS,[
 +              acl_LIBS=$LIBS
 +              LIBS="$LIBS $ACL_LIBS"
 +              AC_LINK_IFELSE([AC_LANG_PROGRAM([[
 +                      #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; ac_cv_have_acls=yes],
 +                      [netatalk_cv_HAVE_POSIX_ACLS=no; ac_cv_have_acls=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_LINK_IFELSE([AC_LANG_PROGRAM([[
                                #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])
 +                              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_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_LINK_IFELSE([AC_LANG_PROGRAM([[
 -                                      #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
 +              if test x"$netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then
 +                      AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available])
 +              fi
  
 -              else
 -                      AC_MSG_NOTICE(ACL support is not avaliable)
 -                      AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available])
 +              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
 -              ;;
 -    esac
 +      fi
  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)
 +if test x"$ac_cv_have_acls" = x"no" ; then
 +      if test x"$with_acl_support" = x"yes" ; then
 +              AC_MSG_ERROR(ACL support requested but not found)
 +      else
 +              AC_MSG_NOTICE(ACL support is not avaliable)
 +      fi
 +else
 +      AC_CHECK_HEADERS([acl/libacl.h])
 +      AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available])
  fi
 +AC_SUBST(ACL_LIBS)
  ])
  
  dnl Check for Extended Attributes support
@@@ -1128,7 -939,7 +1128,7 @@@ dnl ------ Check for sendfile() -------
  AC_DEFUN([AC_NETATALK_SENDFILE], [
  netatalk_cv_search_sendfile=yes
  AC_ARG_ENABLE(sendfile,
-     [  --disable-sendfile       disable sendfile syscall],
+     [  --disable-sendfile      disable sendfile syscall],
      [if test x"$enableval" = x"no"; then
              netatalk_cv_search_sendfile=no
          fi]
@@@ -1164,23 -975,6 +1164,23 @@@ if test x"$netatalk_cv_search_sendfile
  fi
  ])
  
 +dnl ------ Check for recvfile() --------
 +AC_DEFUN([AC_NETATALK_RECVFILE], [
 +case "$host_os" in
 +*linux*)
 +    AC_CHECK_FUNCS([splice], [atalk_cv_use_recvfile=yes])
 +    ;;
 +
 +*)
 +    ;;
 +
 +esac
 +
 +if test x"$atalk_cv_use_recvfile" = x"yes"; then
 +    AC_DEFINE(WITH_RECVFILE, 1, [Whether recvfile should be used])
 +fi
 +])
 +
  dnl --------------------- Check if realpath() takes NULL
  AC_DEFUN([AC_NETATALK_REALPATH], [
  AC_CACHE_CHECK([if the realpath function allows a NULL argument],
diff --combined macros/quota-check.m4
index 703c3568d34d38b36029a2c2e342abb8713af5a3,ad135080e91f0facd1610c26190561020741f54a..e2e145e616ed15da19fec87d1729c7ed211f9666
@@@ -1,9 -1,10 +1,9 @@@
 -dnl $Id: quota-check.m4,v 1.6 2005-07-20 23:58:21 didg Exp $
  dnl Autoconf macro to check for quota support
  dnl FIXME: This is in now way complete.
  
  AC_DEFUN([AC_NETATALK_CHECK_QUOTA], [
        AC_ARG_ENABLE(quota,
-       [  --enable-quota           Turn on quota support (default=auto)])
+       [  --enable-quota          Turn on quota support (default=auto)])
  
        if test x$enable_quota != xno; then
        QUOTA_LIBS=""