]> arthur.barton.de Git - netatalk.git/commitdiff
Merge remote-tracking branch 'origin/branch-netatalk-3-1'
authorRalph Boehme <rb@sernet.de>
Fri, 1 Aug 2014 14:19:01 +0000 (16:19 +0200)
committerRalph Boehme <rb@sernet.de>
Fri, 1 Aug 2014 14:19:01 +0000 (16:19 +0200)
95 files changed:
.gitignore
Makefile.am
NEWS
VERSION
abigen.sh
bin/Makefile.am
bin/ad/ad_util.c
bin/misc/fce.c
configure.ac
contrib/shell_utils/Makefile.am
contrib/shell_utils/fce_ev_script.sh [new file with mode: 0644]
distrib/initscripts/rc.debian.tmpl
doc/manpages/man1/dbd.1.xml
doc/manpages/man5/afp.conf.5.xml
doc/www/ReleaseNotes
etc/afpd/Makefile.am
etc/afpd/afp_config.c
etc/afpd/afp_dsi.c
etc/afpd/afprun.c
etc/afpd/auth.c
etc/afpd/desktop.c
etc/afpd/directory.c
etc/afpd/fce_api.c
etc/afpd/fce_api_internal.h
etc/afpd/fce_util.c
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/fork.c
etc/afpd/main.c
etc/afpd/ofork.c
etc/afpd/quota.c
etc/afpd/spotlight.c
etc/afpd/unix.c
etc/afpd/volume.c
etc/cnid_dbd/cmd_dbd.c
etc/cnid_dbd/cnid_metad.c
etc/cnid_dbd/main.c
etc/netatalk/netatalk.c
etc/spotlight/slmod_sparql.c
etc/spotlight/slmod_sparql_map.c
etc/spotlight/slmod_sparql_map.h
etc/spotlight/slmod_sparql_parser.c
etc/spotlight/slmod_sparql_parser.h
etc/spotlight/slmod_sparql_parser.y
include/atalk/acl.h
include/atalk/adouble.h
include/atalk/cnid.h
include/atalk/cnid_bdb_private.h
include/atalk/cnid_mysql_private.h
include/atalk/cnid_private.h
include/atalk/fce_api.h
include/atalk/globals.h
include/atalk/spotlight.h
include/atalk/util.h
include/atalk/volume.h
libatalk/Makefile.am
libatalk/adouble/ad_conv.c
libatalk/adouble/ad_flush.c
libatalk/adouble/ad_open.c
libatalk/adouble/ad_write.c
libatalk/cnid/cdb/cnid_cdb_add.c
libatalk/cnid/cdb/cnid_cdb_close.c
libatalk/cnid/cdb/cnid_cdb_delete.c
libatalk/cnid/cdb/cnid_cdb_get.c
libatalk/cnid/cdb/cnid_cdb_lookup.c
libatalk/cnid/cdb/cnid_cdb_open.c
libatalk/cnid/cdb/cnid_cdb_rebuild_add.c
libatalk/cnid/cdb/cnid_cdb_resolve.c
libatalk/cnid/cdb/cnid_cdb_update.c
libatalk/cnid/cnid.c
libatalk/cnid/dbd/cnid_dbd.c
libatalk/cnid/last/cnid_last.c
libatalk/cnid/mysql/cnid_mysql.c
libatalk/cnid/tdb/cnid_tdb_add.c
libatalk/cnid/tdb/cnid_tdb_close.c
libatalk/cnid/tdb/cnid_tdb_delete.c
libatalk/cnid/tdb/cnid_tdb_get.c
libatalk/cnid/tdb/cnid_tdb_lookup.c
libatalk/cnid/tdb/cnid_tdb_open.c
libatalk/cnid/tdb/cnid_tdb_resolve.c
libatalk/cnid/tdb/cnid_tdb_update.c
libatalk/libatalk-3.1.1.abi [new file with mode: 0644]
libatalk/libatalk-3.1.2.abi [new file with mode: 0644]
libatalk/libatalk-3.1.3.abi [new file with mode: 0644]
libatalk/unicode/precompose.h
libatalk/unicode/utf16_case.c
libatalk/unicode/utf16_casetable.h
libatalk/util/netatalk_conf.c
libatalk/util/socket.c
libatalk/util/unix.c
libatalk/vfs/extattr.c
libatalk/vfs/unix.c
libatalk/vfs/vfs.c
man/man1/dbd.1.in
man/man5/afp.conf.5.in

index cecdf4e2390733122fdb355cb0ce100182fd9fe0..c96ca95db3415b8263724df6e73d020fbdc22a47 100644 (file)
@@ -20,6 +20,7 @@ ltmain.sh
 autom4te.cache
 autoscan.log
 ylwrap
+test-driver
 *.rpm
 *.deb
 *.dsc
index 4d714f2de666a4451205a3f4bf7657e29334a0bb..d52633f7737b9e2b30994fdd9c1acee4df2aadff 100644 (file)
@@ -6,7 +6,7 @@ else
 SUBDIRS = include libatalk bin config etc contrib distrib doc man macros test
 endif
 
-EXTRA_DIST = CONTRIBUTORS COPYRIGHT COPYING NEWS VERSION
+EXTRA_DIST = CONTRIBUTORS COPYRIGHT COPYING NEWS VERSION abigen.sh
 
 ACLOCAL_AMFLAGS = -I macros
 AUTOMAKE_OPTIONS = foreign
diff --git a/NEWS b/NEWS
index cce1114b516863e261eba643a86e3ad2410e141e..0ff59489dfc6b02011ea38a2a8263fb4cea0b0de 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,48 @@
+Changes in 3.1.4
+================
+* FIX: afpd: Hangs in Netatalk which causes it to stop responding to
+       connections, bug #572.
+* NEW: afpd: new option "force xattr with sticky bit = yes|no"
+       (default: no), FR #94
+* UPD: afpd: FCE version 2 with new event types and new config options
+       "fce ignore names" and "fce notify script"
+
+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
@@ -14,6 +59,7 @@ Changes in 3.1.1
 * 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
 ================
diff --git a/VERSION b/VERSION
index ec747834113928cc9415cc86835b744e247e3b08..983072e58fdcfd374eceff9a19804cd4c3df05d3 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.1.1dev
\ No newline at end of file
+3.1.4dev
\ No newline at end of file
index 3d3c33dcb4ca8776bbf03b1af19afeaf3d536782..d5a3a2ea964d9e0fb93490091309cd11931ac84f 100755 (executable)
--- a/abigen.sh
+++ b/abigen.sh
@@ -10,7 +10,7 @@ cat <<EOF
 set height 0
 set width 0
 EOF
-nm "$SHAREDLIB" | cut -d' ' -f2- | egrep '^[BDGTRVWS]' | grep -v @ | cut -c3- | sort | while read s; do
+nm "$SHAREDLIB" | cut -d' ' -f2- | egrep '^[BDGTRVWS]' | grep -v @ | cut -c3- | egrep -v '^[_]' | sort | while read s; do
     echo "echo $s: "
     echo p $s
 done
index f5d1448ae3621d70a8241af4864a925335693e68..9aedd4b694a2989e3c8a792205e297bbb0176c28 100644 (file)
@@ -1,6 +1,6 @@
 # Makefile.am for bin/
 
-SUBDIRS = afppasswd cnid megatron uniconv misc
+SUBDIRS = afppasswd cnid megatron misc
 
 if HAVE_ATFUNCS
 SUBDIRS += ad
index 782bbffa6c7a0042f7f97c6c02e732e67ef32ea9..27f42b052cec9faff446681358ede8d251d8c557 100644 (file)
@@ -124,13 +124,9 @@ int openvol(AFPObj *obj, const char *path, afpvol_t *vol)
     if ((vol->vol->v_flags & AFPVOL_NODEV))
         flags |= CNID_FLAG_NODEV;
 
-    if ((vol->vol->v_cdb = cnid_open(vol->vol->v_path,
-                                     0000,
+    if ((vol->vol->v_cdb = cnid_open(vol->vol,
                                      "dbd",
-                                     flags,
-                                     vol->vol->v_cnidserver,
-                                     vol->vol->v_cnidport,
-                                     NULL, NULL)) == NULL)
+                                     flags)) == NULL)
         ERROR("Cant initialize CNID database connection for %s", vol->vol->v_path);
 
     cnid_getstamp(vol->vol->v_cdb,
index 23101bfbb34ed7a1622c488f82a1fa4e58278c88..cd767e9aa110647e2c5969589594e0acf86808a1 100644 (file)
@@ -27,52 +27,103 @@ static char *fce_ev_names[] = {
     "FCE_FILE_DELETE",
     "FCE_DIR_DELETE",
     "FCE_FILE_CREATE",
-    "FCE_DIR_CREATE"
+    "FCE_DIR_CREATE",
+    "FCE_FILE_MOVE",
+    "FCE_DIR_MOVE",
+    "FCE_LOGIN",
+    "FCE_LOGOUT"
 };
 
 static int unpack_fce_packet(unsigned char *buf, struct fce_packet *packet)
 {
     unsigned char *p = buf;
+    uint16_t uint16;
+    uint32_t uint32;
+    uint64_t uint64;
 
-    memcpy(&packet->magic[0], p, sizeof(packet->magic));
-    p += sizeof(packet->magic);
+    memcpy(&packet->fcep_magic[0], p, sizeof(packet->fcep_magic));
+    p += sizeof(packet->fcep_magic);
 
-    packet->version = *p;
-    p++;
+    packet->fcep_version = *p++;
 
-    packet->mode = *p;
-    p++;
+    if (packet->fcep_version > 1)
+        packet->fcep_options = *p++;
 
-    memcpy(&packet->event_id, p, sizeof(packet->event_id));
-    p += sizeof(packet->event_id);
-    packet->event_id = ntohl(packet->event_id);
+    packet->fcep_event = *p++;
 
-    memcpy(&packet->datalen, p, sizeof(packet->datalen));
-    p += sizeof(packet->datalen);
-    packet->datalen = ntohs(packet->datalen);
+    if (packet->fcep_version > 1)
+        /* padding */
+        p++;
 
-    memcpy(&packet->data[0], p, packet->datalen);
-    packet->data[packet->datalen] = 0; /* 0 terminate strings */
-    p += packet->datalen;
+    if (packet->fcep_version > 1)
+        /* reserved */
+        p += 8;
+
+    memcpy(&packet->fcep_event_id, p, sizeof(packet->fcep_event_id));
+    p += sizeof(packet->fcep_event_id);
+    packet->fcep_event_id = ntohl(packet->fcep_event_id);
+
+    if (packet->fcep_options & FCE_EV_INFO_PID) {
+        memcpy(&packet->fcep_pid, p, sizeof(packet->fcep_pid));
+        packet->fcep_pid = hton64(packet->fcep_pid);
+        p += sizeof(packet->fcep_pid);
+    }
+
+    if (packet->fcep_options & FCE_EV_INFO_USER) {
+        memcpy(&packet->fcep_userlen, p, sizeof(packet->fcep_userlen));
+        packet->fcep_userlen = ntohs(packet->fcep_userlen);
+        p += sizeof(packet->fcep_userlen);
+
+        memcpy(&packet->fcep_user[0], p, packet->fcep_userlen);
+        packet->fcep_user[packet->fcep_userlen] = 0; /* 0 terminate strings */
+        p += packet->fcep_userlen;
+    }
+
+    /* path */
+    memcpy(&packet->fcep_pathlen1, p, sizeof(packet->fcep_pathlen1));
+    p += sizeof(packet->fcep_pathlen1);
+    packet->fcep_pathlen1 = ntohs(packet->fcep_pathlen1);
+
+    memcpy(&packet->fcep_path1[0], p, packet->fcep_pathlen1);
+    packet->fcep_path1[packet->fcep_pathlen1] = 0; /* 0 terminate strings */
+    p += packet->fcep_pathlen1;
+
+    if (packet->fcep_options & FCE_EV_INFO_SRCPATH) {
+        memcpy(&packet->fcep_pathlen2, p, sizeof(packet->fcep_pathlen2));
+        p += sizeof(packet->fcep_pathlen2);
+        packet->fcep_pathlen2 = ntohs(packet->fcep_pathlen2);
+        memcpy(&packet->fcep_path2[0], p, packet->fcep_pathlen2);
+        packet->fcep_path2[packet->fcep_pathlen2] = 0; /* 0 terminate strings */
+        p += packet->fcep_pathlen2;
+    }
 
     return 0;
 }
 
-int main(void)
+int main(int argc, char **argv)
 {
-    int sockfd;
+    int sockfd, rv, c;
     struct addrinfo hints, *servinfo, *p;
-    int rv;
     int numbytes;
     struct sockaddr_storage their_addr;
     char buf[MAXBUFLEN];
     socklen_t addr_len;
+    char s[INET6_ADDRSTRLEN];
+    char *host = "localhost";
+
+    while ((c = getopt(argc, argv, "h:")) != -1) {
+        switch(c) {
+        case 'h':
+            host = strdup(optarg);
+            break;
+        }
+    }
 
     memset(&hints, 0, sizeof hints);
     hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
     hints.ai_socktype = SOCK_DGRAM;
 
-    if ((rv = getaddrinfo(NULL, FCE_DEFAULT_PORT_STRING, &hints, &servinfo)) != 0) {
+    if ((rv = getaddrinfo(host, FCE_DEFAULT_PORT_STRING, &hints, &servinfo)) != 0) {
         fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
         return 1;
     }
@@ -119,9 +170,9 @@ int main(void)
 
         unpack_fce_packet((unsigned char *)buf, &packet);
 
-        if (memcmp(packet.magic, FCE_PACKET_MAGIC, sizeof(packet.magic)) == 0) {
+        if (memcmp(packet.fcep_magic, FCE_PACKET_MAGIC, sizeof(packet.fcep_magic)) == 0) {
 
-            switch (packet.mode) {
+            switch (packet.fcep_event) {
             case FCE_CONN_START:
                 printf("FCE Start\n");
                 break;
@@ -131,8 +182,16 @@ int main(void)
                 break;
 
             default:
-                printf("ID: %" PRIu32 ", Event: %s, Path: %s\n",
-                       packet.event_id, fce_ev_names[packet.mode], packet.data);
+                printf("ID: %" PRIu32 ", Event: %s", packet.fcep_event_id, fce_ev_names[packet.fcep_event]);
+                if (packet.fcep_options & FCE_EV_INFO_PID)
+                    printf(", pid: %" PRId64, packet.fcep_pid);
+                if (packet.fcep_options & FCE_EV_INFO_USER)
+                    printf(", user: %s", packet.fcep_user);
+
+                if (packet.fcep_options & FCE_EV_INFO_SRCPATH)
+                    printf(", source: %s", packet.fcep_path2);
+
+                printf(", Path: %s\n", packet.fcep_path1);
                 break;
             }
         }
index 72c060358391743177634a309311575058bcd10c..6f54a896ce37402f8edd86146de575e7b1f25069 100644 (file)
@@ -245,7 +245,6 @@ AC_OUTPUT([Makefile
        bin/cnid/cnid2_create
        bin/megatron/Makefile
        bin/misc/Makefile
-       bin/uniconv/Makefile
        config/Makefile
        config/pam/Makefile
        contrib/Makefile
index dc4c7db7076b6f2b1de73ed7546a2acb1c3a182c..a85132276b074dec7dbcedc523f6e429e053a31e 100644 (file)
@@ -20,4 +20,4 @@ CLEANFILES = $(GENERATED_FILES)
 
 bin_SCRIPTS = $(PERLSCRIPTS) $(GENERATED_FILES) afpstats
 
-EXTRA_DIST = $(TEMPLATE_FILES) make-casetable.pl make-precompose.h.pl afpstats
+EXTRA_DIST = $(TEMPLATE_FILES) make-casetable.pl make-precompose.h.pl afpstats fce_ev_script.sh
diff --git a/contrib/shell_utils/fce_ev_script.sh b/contrib/shell_utils/fce_ev_script.sh
new file mode 100644 (file)
index 0000000..8e3410c
--- /dev/null
@@ -0,0 +1,62 @@
+#!/bin/sh
+
+usage="$(basename $0) [-h] [-v version] [-e event] [-P path] [-S source path] -- FCE sample script
+
+where:
+    -h  show this help text
+    -v  version
+    -e  event
+    -P  path
+    -S  source path for events like rename/move
+    -u  username
+    -p  pid
+    -i  event ID
+"
+
+while getopts ':hs:v:e:P:S:u:p:i:' option; do
+  case "$option" in
+    h) echo "$usage"
+       exit
+       ;;
+    v) version=$OPTARG
+       ;;
+    e) event=$OPTARG
+       ;;
+    P) path=$OPTARG
+       ;;
+    S) srcpath=$OPTARG
+       ;;
+    u) user=$OPTARG
+       ;;
+    p) pid=$OPTARG
+       ;;
+    i) evid=$OPTARG
+       ;;
+    ?) printf "illegal option: '%s'\n" "$OPTARG" >&2
+       echo "$usage" >&2
+       exit 1
+       ;;
+  esac
+done
+shift $((OPTIND - 1))
+
+printf "FCE Event: $event" >> /tmp/fce.log 
+if [ -n "$version" ] ; then
+    printf ", protocol: $version" >> /tmp/fce.log
+fi
+if [ -n "$evid" ] ; then
+    printf ", ID: $evid" >> /tmp/fce.log
+fi
+if [ -n "$pid" ] ; then
+    printf ", pid: $pid" >> /tmp/fce.log
+fi
+if [ -n "$user" ] ; then
+    echo -n ", user: $user" >> /tmp/fce.log
+fi
+if [ -n "$srcpath" ] ; then
+    echo -n ", source: $srcpath" >> /tmp/fce.log
+fi
+if [ -n "$path" ] ; then
+    echo -n ", path: $path" >> /tmp/fce.log
+fi
+printf "\n" >> /tmp/fce.log
index a0eb758f16374cc4db896637dd175d5fe7f5de96..9b26b61a5ec8c72c11e190fa2933324227adee74 100644 (file)
@@ -5,7 +5,7 @@
 # Should-Start:      avahi-daemon
 # Required-Stop:     $remote_fs $syslog
 # Default-Start:     2 3 4 5
-# Default-Stop:      1
+# Default-Stop:      0 1 6
 ### END INIT INFO
 #
 # netatalk      Netatalk :NETATALK_VERSION: initscript
index 36b7aba02b2c2e0edd7fa0b25aa8afe5997b335e..467537896e0447490a6335325b49ee99cc54bffb 100644 (file)
@@ -22,7 +22,7 @@
           <primary>dbd</primary>
         </indexterm></command>
 
-      <arg choice="opt">-fsv</arg>
+      <arg choice="opt">-cfFstuvV</arg>
 
       <arg choice="plain"><replaceable>volumepath</replaceable></arg>
     </cmdsynopsis>
         </listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term>-u</term>
+
+        <listitem>
+          <para>username for use with AFP volumes using user variable $u</para>
+        </listitem>
+      </varlistentry>
+
       <varlistentry>
         <term>-v</term>
 
index 8f398334ca45dbdcef3944e1674f4fd519f5eccc..2f5ef1a8e4abfc5d6360753aea81d5484601bd3e 100644 (file)
@@ -5,7 +5,7 @@
 
     <manvolnum>5</manvolnum>
 
-    <refmiscinfo class="date">09 Feb 2013</refmiscinfo>
+    <refmiscinfo class="date">05 Jun 2014</refmiscinfo>
 
     <refmiscinfo class="source">@NETATALK_VERSION@</refmiscinfo>
   </refmeta>
     <title>VARIABLE SUBSTITUTIONS</title>
 
     <para>You can use variables in volume names. The use of variables in paths
-    is not supported for now.</para>
+     is limited to $u.</para>
 
     <orderedlist>
       <listitem>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>chmod request = <replaceable>preserve (default) | ignore | simple</replaceable>
+          <type>(G/V)</type></term>
+
+          <listitem>
+            <para>Advanced permission control that deals with ACLs.</para>
+
+            <itemizedlist>
+              <listitem><para>
+                <option>ignore</option> - UNIX chmod() requests are completely ignored
+                     </para></listitem>
+              <listitem><para>
+                <option>preserve</option> - preserve ZFS ACEs for
+                named users and groups or POSIX ACL group mask
+                     </para></listitem>
+              <listitem><para>
+                <option>simple</option> - just to a chmod() as
+                requested without any extra steps
+                     </para></listitem>
+                   </itemizedlist>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>close vol = <replaceable>BOOLEAN</replaceable> (default:
           <emphasis>no</emphasis>) <type>(G)</type></term>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>force xattr with sticky bit =
+          <replaceable>BOOLEAN</replaceable> (default:
+          <emphasis>no</emphasis>) <type>(G/V)</type></term>
+
+          <listitem>
+            <para>Writing metadata xattr on directories with the
+            sticky bit set may fail even though we may have write
+            access to a directory, because if the sticky bit is set
+            only the owner is allowed to write xattrs.</para>
+
+            <para>By enabling this option Netatalk will write the
+            metadata xattr as root.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>guest account = <replaceable>name</replaceable>
           <type>(G)</type></term>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>sparql results limit =
+          <replaceable>NUMBER</replaceable> (default:
+          <emphasis>UNLIMITED</emphasis>) <type>(G)</type></term>
+
+          <listitem>
+            <para>Impose a limit on the number of results queried from Tracker
+           via SPARQL queries.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>spotlight =
           <replaceable>BOOLEAN</replaceable> (default:
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>spotlight attributes =
+          <replaceable>COMMA SEPERATED STRING</replaceable> (default:
+          <emphasis>EMPTY</emphasis>) <type>(G)</type></term>
+
+          <listitem>
+            <para>A list of attributes that are allowed to be used in
+            Spotlight searches. By default all attributes can be
+            searched, passing a string limits attributes to elements
+            of the string. Example: <programlisting>spotlight
+            attributes = *,kMDItemTextContent</programlisting>
+           </para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>spotlight expr =
+          <replaceable>BOOLEAN</replaceable> (default:
+          <emphasis>yes</emphasis>) <type>(G)</type></term>
+
+          <listitem>
+            <para>Whether to allow the use of logic expression in
+            searches.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>start dbus =
+          <replaceable>BOOLEAN</replaceable> (default:
+          <emphasis>yes</emphasis>) <type>(G)</type></term>
+
+          <listitem>
+            <para>Whether to start a dbus instance for use with Tracker.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>start tracker =
+          <replaceable>BOOLEAN</replaceable> (default:
+          <emphasis>yes</emphasis>) <type>(G)</type></term>
+
+          <listitem>
+            <para>Whether to start Tracker with 
+            <emphasis>tracker-control -s</emphasis>.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>veto message = <replaceable>BOOLEAN</replaceable> (default:
           <emphasis>no</emphasis>) <type>(G)</type></term>
 
         <varlistentry>
           <term>vol dbpath = <replaceable>path</replaceable>
-          <type>(G)</type></term>
+          <type>(G)/(V)</type></term>
 
           <listitem>
             <para>Sets the database information to be stored in path. You have
             to specify a writable location, even if the volume is read only.
             The default is
-            <filename>@localstatedir@/netatalk/CNID/</filename>.</para>
+            <filename>@localstatedir@/netatalk/CNID/$v/</filename>.</para>
           </listitem>
         </varlistentry>
 
       afpd processes notify interested listeners about certain filesystem
       event by UDP network datagrams.</para>
 
+      <para>The following FCE events are defined:</para>
+
+      <itemizedlist>
+        <listitem><para>file modification (<option>fmod</option>)</para></listitem>
+        <listitem><para>file deletion (<option>fdel</option>)</para></listitem>
+        <listitem><para>directory deletion (<option>ddel</option>)</para></listitem>
+        <listitem><para>file creation (<option>fcre</option>)</para></listitem>
+        <listitem><para>directory creation (<option>dcre</option>)</para></listitem>
+        <listitem><para>file move or rename (<option>fmov</option>)</para></listitem>
+        <listitem><para>directory move or rename (<option>dmov</option>)</para></listitem>
+        <listitem><para>login (<option>login</option>)</para></listitem>
+        <listitem><para>logout (<option>logout</option>)</para></listitem>
+      </itemizedlist>
+
       <variablelist>
         <varlistentry>
           <term>fce listener = <replaceable>host[:port]</replaceable>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>fce version = <replaceable>1|2</replaceable>
+          <type>(G)</type></term>
+
+          <listitem>
+            <para>FCE protocol version, default is 1. You need version
+            2 for the fmov, dmov, login or logout events.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>fce events =
-          <replaceable>fmod,fdel,ddel,fcre,dcre,tmsz</replaceable>
+          <replaceable>fmod,fdel,ddel,fcre,dcre,fmov,dmov,login,logout</replaceable>
           <type>(G)</type></term>
 
           <listitem>
             seconds.</para>
           </listitem>
         </varlistentry>
+
+        <varlistentry>
+          <term>fce ignore names = <replaceable>NAME[/NAME2/...]</replaceable>
+          <type>(G)</type></term>
+
+          <listitem>
+            <para>Slash delimited list of filenames for which FCE
+            events shall not be generated. Default: .DS_Store.</para>
+          </listitem>
+        </varlistentry>
+
+        <varlistentry>
+          <term>fce notify script = <replaceable>PATH</replaceable>
+          <type>(G)</type></term>
+
+          <listitem>
+            <para>Script which will be executed for every FCE event,
+            see contrib/shell_utils/fce_ev_script.shfrom the Netatalk
+            sources for an example script.</para>
+          </listitem>
+        </varlistentry>
+
       </variablelist>
     </refsect2>
 
index 6c96c692dd87aefc9fa18076b42250175c4f752e..df491b73f9fe50e70312354a96ab11c92db68fe1 100644 (file)
@@ -1,9 +1,10 @@
-Netatalk 3.1.0
+Netatalk 3.1.3
 ==============
 
-The Netatalk development team is proud to announce the first release of
-the Netatalk 3.1 release series. Early adopters are encouraged to update
-production systems.
+The Netatalk development team is proud to announce latest release of
+the Netatalk 3.1 release series. Users are encouraged to update their
+servers to the 3.1 release series which is the stable and supported
+version for production systems.
 
 Netatalk is a freely-available Open Source AFP fileserver.
 A *NIX/*BSD system running Netatalk is capable of serving many Macintosh
@@ -44,293 +45,24 @@ at:
 
 http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
 
-Changes in 3.1.0
+Changes in 3.1.3
 ~~~~~~~~~~~~~~~~
-* 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
-* 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
-
-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.
-
-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 messages" 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 acl' 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
-       afp.conf, allowing for usage of the binary objectGUID fields from
-       Active Directory.
-* FIX: afpd: Fix a Solaris 10 SPARC sendfilev bug
-* FIX: afpd: Fix a crash on FreeBSD
-* FIX: afpd: Fixes open file handle refcounting bug which was reported as
-       being unable to play movies off a Netatalk AFP share.
-       Bug ID 3559783.
-* FIX: afpd: Fix a possible data corruption when reading from and writing
-       to the server simultaniously under load
-* FIX: Fix possible alignment violations due to bad casts
-* FIX: dbd: Fix logging
-* FIX: apple_dump: Extended Attributes AppleDouble support for *BSD
-* FIX: handling of '/' and ':' in volume name
-* UPD: Install relevant includes necessary for building programs with
-       installed headers and shared lib libatalk
-* UPD: libevent configure args to pick up installed version. Removed
-       configure arg --disable-libevent, added configure args
-       --with-libevent-header|lib.
-* UPD: gentoo initscript: merge from portage netatalk.init,v 1.1
-* REM: Remove --with-smbsharemodes configure option, it was an
-       empty stub not yet implemented
-
-Changes in 3.0
-~~~~~~~~~~~~~~
-
-* UPD: afpd: force read only mode if cnid scheme is last
-* REM: afpd: removed global option "icon"
-* FIX: CNID path for user homes
-
-Changes in 3.0 beta2
-~~~~~~~~~~~~~~~~~~~~
-
-* UPD: Solaris and friends: Replace initscript with SMF manifest
-* FIX: Solaris and friends: resource fork handling
-
-Changes in 3.0 beta1
-~~~~~~~~~~~~~~~~~~~~
-
-* UPD: afpd: Performance tuning of read/write AFP operations. New option
-       "afp read locks" (default: no) which disables that the server
-       applies UNIX byte range locks to regions of files in AFP read and
-       write calls.
-* UPD: apple_dump: Extended Attributes AppleDouble support.
-       (*BSD is not supported yet)
-
-Changes in 3.0 alpha3
-~~~~~~~~~~~~~~~~~~~~~
-
-* NEW: afpd: Per volume "login message", NetAFP bug ID #18
-* NEW: afpd: Cross-platform locking (share modes) on Solaris and derivates
-       with Solaris CIFS/SMB server. Uses new Solaris fcntl F_SHARE share
-       reservation locking primitives. Enabled by default, set global
-       "solaris share reservations" option to false to disable it.
-* NEW: ad: ad set subcommand for changing Mac metadata on the server
-* UPD: unix charset is UTF8 by default
-       vol charset is same value as unix charset by default
-* UPD: .AppleDesktop/ are stored in $localstatedir/netatalk/CNID
-       (default: /var/netatalk/CNID), databases found in AFP volumes are
-       automatically moved
-* FIX: afpd: Server info packet was malformed resulting in broken
-       server names being displayed on clients
-* FIX: afpd: Byte order detection. Fixes an error where Netatalk on
-       OpenIndiana returned wrong volume size information.
-
-Changes in 3.0 alpha2
-~~~~~~~~~~~~~~~~~~~~~
-
-* UPD: afpd: Store '.' as is and '/' as ':' on the server, don't
-       CAP hexencode as "2e" and "2f" respectively
-* UPD: afdp: Automatic name conversion, renaming files and directories
-       containing CAP sequences to their not enscaped forms
-* UPD: afpd: Correct handling of user homes and users without homes
-* UPD: afpd: Perform complete automatic adouble:v2 to adouble:ea conversion
-       as root. Previously only unlinking the adouble:v2 file was done as root
-* UPD: dbd: -C option removes CAP encoding
-* UPD: Add graceful option to RedHat init script
-* UPD: Add --disable-bundled-libevent configure options When set to yes,
-       we rely on a properly installed version on libevent CPPFLAGS and LDFLAGS
-       should be set properly to pick that up
-* UPD: Run ldconfig on Linux at the end of make install
-* FIX: afpd: ad cp on appledouble = ea volumes
-* FIX: dbd: ignore ._ appledouble files
-* REM: Volumes options "use dots" and "hex encoding"
-
-Changes in 3.0 alpha1
-~~~~~~~~~~~~~~~~~~~~~
-
-* NEW: Central configuration file afp.conf which replaces all previous files
-* NEW: netatalk: service controller starting and restarting afpd and cnid_metad
-       as necessary
-* NEW: afpd: Extended Attributes AppleDouble backend (default)
-* UPD: CNID databases are stored in $localstatedir/netatalk/CNID
-       (default: /var/netatalk/CNID), databases found in AFP volumes are
-       automatically moved
-* UPD: Start scripts and service manifests have been changed to only start
-       the new netatalk service controller process
-* UPD: afpd: UNIX privileges and use dots enabled by default
-* UPD: afpd: Support for arbitrary AFP volumes using variable expansion has been
-       removed
-* UPD: afpd: afp_voluuid.conf and afp_signature.conf location has been
-       changed to $localstatedir/netatalk/ (default: /var/netatalk/)
-* UPD: afpd: default server messages dir changed to $localstatedir/netatalk/msg/
-* UPD: dbd: new option -C for conversion from AppleDouble v2 to ea
-* REM: AppleTalk support has been removed
-* REM: afpd: SLP and AFP proxy support have been removed
-* REM: afpd: legacy file extension to type/creator mapping has been removed
-* REM: afpd: AppleDouble backends v1, osx and sfm have been removed
-
+* 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
 
 Supported Platforms
 ~~~~~~~~~~~~~~~~~~~
@@ -385,4 +117,4 @@ We would like to thank all contributors to the Netatalk project for
 their commitment.  Without the many suggestions, bug and problem reports,
 patches, and reviews this project wouldn't be where it is.
 
- - The Netatalk Development Team, October 2013
+ - The Netatalk Development Team, July 2014
index a0b210e170e05a4e2029881c8a5a269760d573cd..77ed9d64d1886ea5cfd97f2d78d23c8611f57fe5 100644 (file)
@@ -7,7 +7,7 @@ CLEANFILES =
 DISTCLEANFILES =
 
 sbin_PROGRAMS = afpd
-noinst_PROGRAMS = hash fce spot
+noinst_PROGRAMS = hash spot
 
 afpd_SOURCES = \
        afp_avahi.c \
@@ -102,10 +102,6 @@ noinst_HEADERS = auth.h afp_config.h desktop.h directory.h fce_api_internal.h fi
 hash_SOURCES = hash.c
 hash_CFLAGS = -DKAZLIB_TEST_MAIN -I$(top_srcdir)/include
 
-fce_SOURCES = fce_api.c fce_util.c
-fce_CFLAGS = -DFCE_TEST_MAIN -I$(top_srcdir)/include
-fce_LDADD = $(top_builddir)/libatalk/libatalk.la
-
 spot_SOURCES = spotlight.c spotlight_marshalling.c
 spot_CFLAGS = -DSPOT_TEST_MAIN
 spot_LDADD = $(top_builddir)/libatalk/libatalk.la
index c7246f1f2d4c4206292fb69ac3c063d5dd39865b..ba5b232b43c0df41ccdd4d569438c8d18f073d83 100644 (file)
@@ -225,6 +225,19 @@ int configinit(AFPObj *obj)
                LOG(log_note, logtype_afpd, "Fce events: %s", r);
                fce_set_events(r);
     }
+    r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce version", "1");
+    LOG(log_debug, logtype_afpd, "Fce version: %s", r);
+    obj->fce_version = atoi(r);
+
+    if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce ignore names", ".DS_Store"))) {
+        obj->fce_ign_names = strdup(r);
+    }
+
+    if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce notify script", NULL))) {
+        obj->fce_notify_script = strdup(r);
+    }
+
+
 
 EC_CLEANUP:
     if (q)
index eb4b19f35d5153302e189b8911bb6d853149ed7d..124db47a251af34771a60271ad3b813d1044d569 100644 (file)
@@ -28,6 +28,8 @@
 #include <arpa/inet.h>
 #include <setjmp.h>
 #include <time.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 
 #include <atalk/logger.h>
 #include <atalk/dsi.h>
@@ -337,6 +339,11 @@ static void alarm_handler(int sig _U_)
     }
 }
 
+static void child_handler(int sig _U_)
+{
+    wait(NULL);
+}
+
 /* ----------------- 
    if dsi->in_write is set attention, tickle (and close?) msg
    aren't sent. We don't care about tickle 
@@ -428,6 +435,17 @@ void afp_over_dsi_sighandlers(AFPObj *obj)
         afp_dsi_die(EXITERR_SYS);
     }
 #endif /* DEBUGGING */
+
+    /*  SIGCLD */
+    action.sa_handler = child_handler;
+#ifdef SA_NOCLDWAIT
+/* this enhancement simplifies things for Solaris, it also improves performance */
+    action.sa_flags |= SA_NOCLDWAIT;
+#endif
+    if (sigaction(SIGCLD, &action, NULL) < 0 ) {
+        LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
+        afp_dsi_die(EXITERR_SYS);
+    }
 }
 
 /* -------------------------------------------
@@ -477,7 +495,7 @@ void afp_over_dsi(AFPObj *obj)
 
     /* Initialize Spotlight */
     if ((obj->options.flags & OPTION_SPOTLIGHT) && (obj->options.slmod_path))
-        sl_mod_load(obj->options.slmod_path);
+        sl_mod_load(obj);
 
     ipc_child_state(obj, DSI_RUNNING);
 
index 74a732e60bdd3a2359754aceb162d1bc58606342..ed412476df6f795ba7d33e7e26f512dc25a7615a 100644 (file)
@@ -259,3 +259,62 @@ int afprun(int root, char *cmd, int *outfd)
     exit(82);
     return 1;
 }
+
+/*
+ * Run a command in the background without waiting,
+ * being careful about uid/gid handling
+ */
+int afprun_bg(int root, char *cmd)
+{
+    pid_t pid;
+    uid_t uid = geteuid();
+    gid_t gid = getegid();
+    int fd, fdlimit = sysconf(_SC_OPEN_MAX);
+
+    LOG(log_debug, logtype_afpd, "running %s as user %d", cmd, root ? 0 : uid);
+
+    /* in this method we will exec /bin/sh with the correct
+       arguments, after first setting stdout to point at the file */
+
+    if ((pid = fork()) < 0) {
+        LOG(log_error, logtype_afpd, "afprun: fork failed with error %s", strerror(errno) );
+        return errno;
+    }
+
+    if (pid)
+        /* parent, just return */
+        return 0;
+
+    /* we are in the child. we exec /bin/sh to do the work for us. we
+       don't directly exec the command we want because it may be a
+       pipeline or anything else the config file specifies */
+
+    if (chdir("/") < 0) {
+        LOG(log_error, logtype_afpd, "afprun: can't change directory to \"/\" %s", strerror(errno) );
+        exit(83);
+    }
+
+    /* now completely lose our privileges. This is a fairly paranoid
+       way of doing it, but it does work on all systems that I know of */
+    if (root) {
+        become_user_permanently(0, 0);
+        uid = gid = 0;
+    } else {
+        become_user_permanently(uid, gid);
+    }
+
+    if (getuid() != uid || geteuid() != uid || getgid() != gid || getegid() != gid) {
+        /* we failed to lose our privileges - do not execute the command */
+        exit(81);
+    }
+
+    fd = 3;
+    while (fd < fdlimit)
+        close(fd++);
+
+    execl("/bin/sh","sh","-c", cmd, NULL);
+
+    /* not reached */
+    exit(82);
+    return 1;
+}
index 8011b56b6fbabe68c0d2f71e935e4f6921637cb1..7a7c41e5cd8a79104ba8a704350d342a167757bb 100644 (file)
@@ -39,6 +39,7 @@ extern void afp_get_cmdline( int *ac, char ***av );
 #include <atalk/server_ipc.h>
 #include <atalk/uuid.h>
 #include <atalk/globals.h>
+#include <atalk/fce_api.h>
 #include <atalk/spotlight.h>
 #include <atalk/unix.h>
 
@@ -313,6 +314,9 @@ static int login(AFPObj *obj, struct passwd *pwd, void (*logout)(void), int expi
     /* Some PAM module might have reset our signal handlers and timer, so we need to reestablish them */
     afp_over_dsi_sighandlers(obj);
 
+    /* Send FCE login event */
+    fce_register(obj, FCE_LOGIN, "", NULL);
+
     return( AFP_OK );
 }
 
@@ -831,6 +835,10 @@ int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen  _U_, char *rbuf  _U_
     close_all_vol(obj);
     dsi->flags = DSI_AFP_LOGGED_OUT;
     *rbuflen = 0;
+
+    /* Send FCE login event */
+    fce_register(obj, FCE_LOGOUT, "", NULL);
+
     return AFP_OK;
 }
 
index 9ba96bc595fd5562be47886acae0aba4238dccf2..5c56977acd3fd30e6dea0659b40b68b19ac68898 100644 (file)
@@ -95,17 +95,29 @@ int setdeskmode(const struct vol *vol, const mode_t mode)
             }
 
             if (S_ISDIR(st.st_mode)) {
-                if ( chmod_acl( modbuf,  (DIRBITS | mode)) < 0 && errno != EPERM ) {
+                if (ochmod(modbuf,
+                           DIRBITS | mode,
+                           &st,
+                           vol_syml_opt(vol) | vol_chmod_opt(vol)
+                        ) < 0 && errno != EPERM) {
                      LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
                 }
-            } else if ( chmod_acl( modbuf,  mode & ~EXEC_MODE ) < 0 && errno != EPERM ) {
+            } else if (ochmod(modbuf,
+                           mode & ~EXEC_MODE,
+                           &st,
+                           vol_syml_opt(vol) | vol_chmod_opt(vol)
+                        ) < 0 && errno != EPERM) {
                 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
             }
 
         }
         closedir( sub );
         /* XXX: need to preserve special modes */
-        if ( chmod_acl( deskp->d_name,  (DIRBITS | mode)) < 0 && errno != EPERM ) {
+        if (ochmod(deskp->d_name,
+                   DIRBITS | mode,
+                   NULL,
+                   vol_syml_opt(vol) | vol_chmod_opt(vol)
+                ) < 0 && errno != EPERM) {
             LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) );
         }
     }
@@ -115,7 +127,11 @@ int setdeskmode(const struct vol *vol, const mode_t mode)
         EC_FAIL;
     }
     /* XXX: need to preserve special modes */
-    if ( chmod_acl(bdata(dtpath),  (DIRBITS | mode)) < 0 && errno != EPERM ) {
+    if (ochmod(bdata(dtpath),
+               DIRBITS | mode,
+               NULL,
+               vol_syml_opt(vol) | vol_chmod_opt(vol)
+            ) < 0 && errno != EPERM) {
         LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno));
     }
 
index 07a2bb7d439cfa5721f148d59f6316a7a59d0369..e83e5e76ca45cd29e99faf27e3744914251c4412 100644 (file)
@@ -2214,7 +2214,7 @@ int afp_createdir(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_
     ad_setname(&ad, s_path->m_name);
     ad_setid( &ad, s_path->st.st_dev, s_path->st.st_ino, dir->d_did, did, vol->v_stamp);
 
-    fce_register(FCE_DIR_CREATE, bdata(curdir->d_fullpath), NULL, fce_dir);
+    fce_register(obj, FCE_DIR_CREATE, bdata(curdir->d_fullpath), NULL);
 
     ad_flush(&ad);
     ad_close(&ad, ADFLAGS_HF);
index 4620378922d763010ac006a700670f5fd194fdc1..158ad608c1e370b9192af9b9e6fdc7fbae254947 100644 (file)
@@ -56,6 +56,8 @@
 // ONLY USED IN THIS FILE
 #include "fce_api_internal.h"
 
+extern int afprun_bg(int root, char *cmd);
+
 /* We store our connection data here */
 static struct udp_entry udp_socket_list[FCE_MAX_UDP_SOCKS];
 static int udp_sockets = 0;
@@ -65,24 +67,34 @@ static unsigned long fce_ev_enabled =
     (1 << FCE_FILE_DELETE) |
     (1 << FCE_DIR_DELETE) |
     (1 << FCE_FILE_CREATE) |
-    (1 << FCE_DIR_CREATE);
+    (1 << FCE_DIR_CREATE) |
+    (1 << FCE_FILE_MOVE) |
+    (1 << FCE_DIR_MOVE) |
+    (1 << FCE_LOGIN) |
+    (1 << FCE_LOGOUT);
+
+static uint8_t fce_ev_info;    /* flags of additional info to send in events */
 
-#define MAXIOBUF 1024
+#define MAXIOBUF 4096
 static unsigned char iobuf[MAXIOBUF];
-static const char *skip_files[] = 
-{
-       ".DS_Store",
-       NULL
-};
+static const char **skip_files;
 static struct fce_close_event last_close_event;
 
-static char *fce_event_names[] = {
+/*
+ * This only initializes consecutive events beginning at 1, high
+ * numbered events must be initialized in the code
+ */
+static char *fce_event_names[FCE_LAST_EVENT + 1] = {
     "",
     "FCE_FILE_MODIFY",
     "FCE_FILE_DELETE",
     "FCE_DIR_DELETE",
     "FCE_FILE_CREATE",
-    "FCE_DIR_CREATE"
+    "FCE_DIR_CREATE",
+    "FCE_FILE_MOVE",
+    "FCE_DIR_MOVE",
+    "FCE_LOGIN",
+    "FCE_LOGOUT"
 };
 
 /*
@@ -161,98 +173,204 @@ void fce_cleanup()
 /*
  * Construct a UDP packet for our listeners and return packet size
  * */
-static ssize_t build_fce_packet( struct fce_packet *packet, const char *path, int event, uint32_t event_id )
+static ssize_t build_fce_packet(const AFPObj *obj,
+                                char *iobuf,
+                                fce_ev_t event,
+                                const char *path,
+                                const char *oldpath,
+                                pid_t pid,
+                                const char *user,
+                                uint32_t event_id)
 {
-    size_t pathlen = 0;
-    ssize_t data_len = 0;
-
-    /* Set content of packet */
-    memcpy(packet->magic, FCE_PACKET_MAGIC, sizeof(packet->magic) );
-    packet->version = FCE_PACKET_VERSION;
-    packet->mode = event;
-   
-    packet->event_id = event_id; 
-
-    pathlen = strlen(path); /* exclude string terminator */
-    
-    /* This should never happen, but before we bust this server, we send nonsense, fce listener has to cope */
-    if (pathlen >= MAXPATHLEN)
-        pathlen = MAXPATHLEN - 1;
-
-    packet->datalen = pathlen;
-
-    /* This is the payload len. Means: the packet has len bytes more until packet is finished */
-    data_len = FCE_PACKET_HEADER_SIZE + pathlen;
-
-    memcpy(packet->data, path, pathlen);
+    char *p = iobuf;
+    size_t pathlen;
+    ssize_t datalen = 0;
+    uint16_t uint16;
+    uint32_t uint32;
+    uint64_t uint64;
+    uint8_t packet_info = fce_ev_info;
+
+    /* FCE magic */
+    memcpy(p, FCE_PACKET_MAGIC, 8);
+    p += 8;
+    datalen += 8;
+
+    /* version */
+    *p = FCE_PACKET_VERSION;
+    p += 1;
+    datalen += 1;
+
+    /* optional: options */
+    if (FCE_PACKET_VERSION > 1) {
+        if (oldpath)
+            packet_info |= FCE_EV_INFO_SRCPATH;
+        *p = packet_info;
+        p += 1;
+        datalen += 1;
+    }
 
-    /* return the packet len */
-    return data_len;
-}
+    /* event */
+    *p = event;
+    p += 1;
+    datalen += 1;
 
-/*
- * Handle Endianess and write into buffer w/o padding
- **/ 
-static void pack_fce_packet(struct fce_packet *packet, unsigned char *buf, int maxlen)
-{
-    unsigned char *p = buf;
+    /* optional: padding */
+    if (FCE_PACKET_VERSION > 1) {
+        p += 1;
+        datalen += 1;
+    }
 
-    memcpy(p, &packet->magic[0], sizeof(packet->magic));
-    p += sizeof(packet->magic);
+    /* optional: reserved */
+    if (FCE_PACKET_VERSION > 1) {
+        p += 8;
+        datalen += 8;
+    }
 
-    *p = packet->version;
-    p++;
-    
-    *p = packet->mode;
-    p++;
-    
-    uint32_t *id = (uint32_t*)p;
-    *id = htonl(packet->event_id);
-    p += sizeof(packet->event_id);
+    /* event ID */
+    uint32 = htonl(event_id);
+    memcpy(p, &uint32, sizeof(uint32));
+    p += sizeof(uint32);
+    datalen += sizeof(uint32);
+
+    /* optional: pid */
+    if (packet_info & FCE_EV_INFO_PID) {
+        uint64 = pid;
+        uint64 = hton64(uint64);
+        memcpy(p, &uint64, sizeof(uint64));
+        p += sizeof(uint64);
+        datalen += sizeof(uint64);
+    }
 
-    uint16_t *l = ( uint16_t *)p;
-    *l = htons(packet->datalen);
-    p += sizeof(packet->datalen);
+    /* optional: username */
+    if (packet_info & FCE_EV_INFO_USER) {
+        uint16 = strlen(user);
+        uint16 = htons(uint16);
+        memcpy(p, &uint16, sizeof(uint16));
+        p += sizeof(uint16);
+        datalen += sizeof(uint16);
+        memcpy(p, user, strlen(user));
+        p += strlen(user);
+        datalen += strlen(user);
+    }
 
-    if (((p - buf) +  packet->datalen) < maxlen) {
-        memcpy(p, &packet->data[0], packet->datalen);
+    /* path */
+    if ((pathlen = strlen(path)) >= MAXPATHLEN)
+        pathlen = MAXPATHLEN - 1;
+    uint16 = pathlen;
+    uint16 = htons(uint16);
+    memcpy(p, &uint16, sizeof(uint16));
+    p += sizeof(uint16);
+    datalen += sizeof(uint16);
+    memcpy(p, path, pathlen);
+    p += pathlen;
+    datalen += pathlen;
+
+    /* optional: source path */
+    if (packet_info & FCE_EV_INFO_SRCPATH) {
+        if ((pathlen = strlen(oldpath)) >= MAXPATHLEN)
+            pathlen = MAXPATHLEN - 1;
+        uint16 = pathlen;
+        uint16 = htons(uint16);
+        memcpy(p, &uint16, sizeof(uint16));
+        p += sizeof(uint16);
+        datalen += sizeof(uint16);
+        memcpy(p, oldpath, pathlen);
+        p += pathlen;
+        datalen += pathlen;
     }
+
+    /* return the packet len */
+    return datalen;
 }
 
 /*
  * Send the fce information to all (connected) listeners
  * We dont give return code because all errors are handled internally (I hope..)
  * */
-static void send_fce_event(const char *path, int event)
+static void send_fce_event(const AFPObj *obj, int event, const char *path, const char *oldpath)
 {    
     static bool first_event = true;
-
-    struct fce_packet packet;
     static uint32_t event_id = 0; /* the unique packet couter to detect packet/data loss. Going from 0xFFFFFFFF to 0x0 is a valid increment */
+    static char *user;
     time_t now = time(NULL);
-
-    LOG(log_debug, logtype_fce, "send_fce_event: start");
+    ssize_t data_len;
 
     /* initialized ? */
     if (first_event == true) {
         first_event = false;
+
+        fce_event_names[FCE_CONN_START] = "FCE_CONN_START";
+        fce_event_names[FCE_CONN_BROKEN] = "FCE_CONN_BROKEN";
+
+        struct passwd *pwd = getpwuid(obj->uid);
+        user = strdup(pwd->pw_name);
+
+        switch (obj->fce_version) {
+        case 1:
+            /* fce_ev_info unused */
+            break;
+        case 2:
+            fce_ev_info = FCE_EV_INFO_PID | FCE_EV_INFO_USER;
+            break;
+        default:
+            fce_ev_info = 0;
+            LOG(log_error, logtype_fce, "Unsupported FCE protocol version %d", obj->fce_version);
+            break;
+        }
+
         fce_init_udp();
         /* Notify listeners the we start from the beginning */
-        send_fce_event( "", FCE_CONN_START );
+        send_fce_event(obj, FCE_CONN_START, "", NULL);
     }
 
-    /* build our data packet */
-    ssize_t data_len = build_fce_packet( &packet, path, event, ++event_id );
-    pack_fce_packet(&packet, iobuf, MAXIOBUF);
+    /* run script */
+    if (obj->fce_notify_script) {
+        static bstring quote = NULL;
+        static bstring quoterep = NULL;
+        static bstring slash = NULL;
+        static bstring slashrep = NULL;
+
+        if (!quote) {
+            quote = bfromcstr("'");
+            quoterep = bfromcstr("'\\''");
+            slash = bfromcstr("\\");
+            slashrep = bfromcstr("\\\\");
+        }
 
-    for (int i = 0; i < udp_sockets; i++)
-    {
+        bstring cmd = bformat("%s -v %d -e %s -i %" PRIu32 "",
+                              obj->fce_notify_script,
+                              FCE_PACKET_VERSION,
+                              fce_event_names[event],
+                              event_id);
+
+        if (path[0]) {
+            bstring bpath = bfromcstr(path);
+            bfindreplace(bpath, slash, slashrep, 0);
+            bfindreplace(bpath, quote, quoterep, 0);
+            bformata(cmd, " -P '%s'", bdata(bpath));
+            bdestroy(bpath);
+        }
+        if (fce_ev_info | FCE_EV_INFO_PID)
+            bformata(cmd, " -p %" PRIu64 "", (uint64_t)getpid());
+        if (fce_ev_info | FCE_EV_INFO_USER)
+            bformata(cmd, " -u %s", user);
+        if (oldpath) {
+            bstring boldpath = bfromcstr(oldpath);
+            bfindreplace(boldpath, slash, slashrep, 0);
+            bfindreplace(boldpath, quote, quoterep, 0);
+            bformata(cmd, " -S '%s'", bdata(boldpath));
+            bdestroy(boldpath);
+        }
+        (void)afprun_bg(1, bdata(cmd));
+        bdestroy(cmd);
+    }
+
+    for (int i = 0; i < udp_sockets; i++) {
         int sent_data = 0;
         struct udp_entry *udp_entry = udp_socket_list + i;
 
         /* we had a problem earlier ? */
-        if (udp_entry->sock == -1)
-        {
+        if (udp_entry->sock == -1) {
             /* We still have to wait ?*/
             if (now < udp_entry->next_try_on_error)
                 continue;
@@ -273,8 +391,7 @@ static void send_fce_event(const char *path, int event)
             udp_entry->next_try_on_error = 0;
 
             /* Okay, we have a running socket again, send server that we had a problem on our side*/
-            data_len = build_fce_packet( &packet, "", FCE_CONN_BROKEN, 0 );
-            pack_fce_packet(&packet, iobuf, MAXIOBUF);
+            data_len = build_fce_packet(obj, iobuf, FCE_CONN_BROKEN, "", NULL, getpid(), user, 0);
 
             sendto(udp_entry->sock,
                    iobuf,
@@ -282,12 +399,11 @@ static void send_fce_event(const char *path, int event)
                    0,
                    (struct sockaddr *)&udp_entry->sockaddr,
                    udp_entry->addrinfo.ai_addrlen);
-
-            /* Rebuild our original data packet */
-            data_len = build_fce_packet(&packet, path, event, event_id);
-            pack_fce_packet(&packet, iobuf, MAXIOBUF);
         }
 
+        /* build our data packet */
+        data_len = build_fce_packet(obj, iobuf, event, path, oldpath, getpid(), user, event_id);
+
         sent_data = sendto(udp_entry->sock,
                            iobuf,
                            data_len,
@@ -306,6 +422,8 @@ static void send_fce_event(const char *path, int event)
             udp_entry->next_try_on_error = now + FCE_SOCKET_RETRY_DELAY_S;
         }
     }
+
+    event_id++;
 }
 
 static int add_udp_socket(const char *target_ip, const char *target_port )
@@ -330,7 +448,7 @@ static int add_udp_socket(const char *target_ip, const char *target_port )
     return AFP_OK;
 }
 
-static void save_close_event(const char *path)
+static void save_close_event(const AFPObj *obj, const char *path)
 {
     time_t now = time(NULL);
 
@@ -338,7 +456,7 @@ static void save_close_event(const char *path)
     if (last_close_event.time   /* is there any saved event ? */
         && (strcmp(path, last_close_event.path) != 0)) {
         /* no, so send the saved event out now */
-        send_fce_event(last_close_event.path, FCE_FILE_MODIFY);
+        send_fce_event(obj, FCE_FILE_MODIFY,last_close_event.path, NULL);
     }
 
     LOG(log_debug, logtype_fce, "save_close_event: %s", path);
@@ -347,12 +465,36 @@ static void save_close_event(const char *path)
     strncpy(last_close_event.path, path, MAXPATHLEN);
 }
 
+static void fce_init_ign_names(const char *ignores)
+{
+    int count = 0;
+    char *names = strdup(ignores);
+    char *p;
+    int i = 0;
+
+    while (names[i]) {
+        count++;
+        for (; names[i] && names[i] != '/'; i++)
+            ;
+        if (!names[i])
+            break;
+        i++;
+    }
+
+    skip_files = calloc(count + 1, sizeof(char *));
+
+    for (i = 0, p = strtok(names, "/"); p ; p = strtok(NULL, "/"))
+        skip_files[i++] = strdup(p);
+
+    free(names);
+}
+
 /*
  *
  * Dispatcher for all incoming file change events
  *
  * */
-int fce_register(fce_ev_t event, const char *path, const char *oldpath, fce_obj_t type)
+int fce_register(const AFPObj *obj, fce_ev_t event, const char *path, const char *oldpath)
 {
     static bool first_event = true;
     const char *bname;
@@ -363,55 +505,56 @@ int fce_register(fce_ev_t event, const char *path, const char *oldpath, fce_obj_
     AFP_ASSERT(event >= FCE_FIRST_EVENT && event <= FCE_LAST_EVENT);
     AFP_ASSERT(path);
 
-    LOG(log_debug, logtype_fce, "register_fce(path: %s, type: %s, event: %s",
-        path, type == fce_dir ? "dir" : "file", fce_event_names[event]);
+    LOG(log_debug, logtype_fce, "register_fce(path: %s, event: %s)",
+        path, fce_event_names[event]);
 
     bname = basename_safe(path);
 
-    if (udp_sockets == 0)
+    if ((udp_sockets == 0) && (obj->fce_notify_script == NULL)) {
         /* No listeners configured */
         return AFP_OK;
-
+    }
 
        /* do some initialization on the fly the first time */
        if (first_event) {
                fce_initialize_history();
+        fce_init_ign_names(obj->fce_ign_names);
         first_event = false;
        }
 
        /* handle files which should not cause events (.DS_Store atc. ) */
-       for (int i = 0; skip_files[i] != NULL; i++) {
-               if (strcmp(bname, skip_files[i]) == 0)
+    for (int i = 0; skip_files[i] != NULL; i++) {
+        if (strcmp(bname, skip_files[i]) == 0)
                        return AFP_OK;
        }
 
        /* Can we ignore this event based on type or history? */
-       if (fce_handle_coalescation(event, path, type)) {
+       if (fce_handle_coalescation(event, path)) {
                LOG(log_debug9, logtype_fce, "Coalesced fc event <%d> for <%s>", event, path);
                return AFP_OK;
        }
 
     switch (event) {
     case FCE_FILE_MODIFY:
-        save_close_event(path);
+        save_close_event(obj, path);
         break;
     default:
-        send_fce_event(path, event);
+        send_fce_event(obj, event, path, oldpath);
         break;
     }
 
     return AFP_OK;
 }
 
-static void check_saved_close_events(int fmodwait)
+static void check_saved_close_events(const AFPObj *obj)
 {
     time_t now = time(NULL);
 
     /* check if configured holdclose time has passed */
-    if (last_close_event.time && ((last_close_event.time + fmodwait) < now)) {
+    if (last_close_event.time && ((last_close_event.time + obj->options.fce_fmodwait) < now)) {
         LOG(log_debug, logtype_fce, "check_saved_close_events: sending event: %s", last_close_event.path);
         /* yes, send event */
-        send_fce_event(&last_close_event.path[0], FCE_FILE_MODIFY);
+        send_fce_event(obj, FCE_FILE_MODIFY, &last_close_event.path[0], NULL);
         last_close_event.path[0] = 0;
         last_close_event.time = 0;
     }
@@ -422,11 +565,11 @@ static void check_saved_close_events(int fmodwait)
 /*
  * API-Calls for file change api, called form outside (file.c directory.c ofork.c filedir.c)
  * */
-void fce_pending_events(AFPObj *obj)
+void fce_pending_events(const AFPObj *obj)
 {
     if (!udp_sockets)
         return;
-    check_saved_close_events(obj->options.fce_fmodwait);
+    check_saved_close_events(obj);
 }
 
 /*
@@ -472,6 +615,14 @@ int fce_set_events(const char *events)
             fce_ev_enabled |= (1 << FCE_FILE_CREATE);
         } else if (strcmp(p, "dcre") == 0) {
             fce_ev_enabled |= (1 << FCE_DIR_CREATE);
+        } else if (strcmp(p, "fmov") == 0) {
+            fce_ev_enabled |= (1 << FCE_FILE_MOVE);
+        } else if (strcmp(p, "dmov") == 0) {
+            fce_ev_enabled |= (1 << FCE_DIR_MOVE);
+        } else if (strcmp(p, "login") == 0) {
+            fce_ev_enabled |= (1 << FCE_LOGIN);
+        } else if (strcmp(p, "logout") == 0) {
+            fce_ev_enabled |= (1 << FCE_LOGOUT);
         }
     }
 
@@ -479,84 +630,3 @@ int fce_set_events(const char *events)
 
     return AFP_OK;
 }
-
-#ifdef FCE_TEST_MAIN
-
-
-void shortsleep( unsigned int us )
-{    
-    usleep( us );
-}
-int main( int argc, char*argv[] )
-{
-    int c;
-
-    char *port = FCE_DEFAULT_PORT_STRING;
-    char *host = "localhost";
-    int delay_between_events = 1000;
-    int event_code = FCE_FILE_MODIFY;
-    char pathbuff[1024];
-    int duration_in_seconds = 0; // TILL ETERNITY
-    char target[256];
-    char *path = getcwd( pathbuff, sizeof(pathbuff) );
-
-    // FULLSPEED TEST IS "-s 1001" -> delay is 0 -> send packets without pause
-
-    while ((c = getopt(argc, argv, "d:e:h:p:P:s:")) != -1) {
-        switch(c) {
-        case '?':
-            fprintf(stdout, "%s: [ -p Port -h Listener1 [ -h Listener2 ...] -P path -s Delay_between_events_in_us -e event_code -d Duration ]\n", argv[0]);
-            exit(1);
-            break;
-        case 'd':
-            duration_in_seconds = atoi(optarg);
-            break;
-        case 'e':
-            event_code = atoi(optarg);
-            break;
-        case 'h':
-            host = strdup(optarg);
-            break;
-        case 'p':
-            port = strdup(optarg);
-            break;
-        case 'P':
-            path = strdup(optarg);
-            break;
-        case 's':
-            delay_between_events = atoi(optarg);
-            break;
-        }
-    }
-
-    sprintf(target, "%s:%s", host, port);
-    if (fce_add_udp_socket(target) != 0)
-        return 1;
-
-    int ev_cnt = 0;
-    time_t start_time = time(NULL);
-    time_t end_time = 0;
-
-    if (duration_in_seconds)
-        end_time = start_time + duration_in_seconds;
-
-    while (1)
-    {
-        time_t now = time(NULL);
-        if (now > start_time)
-        {
-            start_time = now;
-            fprintf( stdout, "%d events/s\n", ev_cnt );
-            ev_cnt = 0;
-        }
-        if (end_time && now >= end_time)
-            break;
-
-        fce_register(event_code, path, NULL, 0);
-        ev_cnt++;
-
-        
-        shortsleep( delay_between_events );
-    }
-}
-#endif /* TESTMAIN*/
index fb5e58e38971602b6de5317e41922e3db7d10461..1c22643682bd2398454d7e7bcb3ff184306640a3 100644 (file)
@@ -14,7 +14,6 @@
 
 #define FCE_MAX_UDP_SOCKS 5     /* Allow a maximum of udp listeners for file change events */
 #define FCE_SOCKET_RETRY_DELAY_S 600 /* Pause this time in s after socket was broken */
-#define FCE_PACKET_VERSION  1
 #define FCE_HISTORY_LEN 10  /* This is used to coalesce events */
 #define MAX_COALESCE_TIME_MS 1000  /* Events oldeer than this are not coalesced */
 
@@ -33,7 +32,6 @@ struct udp_entry {
 
 struct fce_history {
     fce_ev_t       fce_h_event;
-       fce_obj_t      fce_h_type;
        char           fce_h_path[MAXPATHLEN + 1];
        struct timeval fce_h_tv;
 };
@@ -45,7 +43,7 @@ struct fce_close_event {
 
 #define PACKET_HDR_LEN (sizeof(struct fce_packet) - FCE_MAX_PATH_LEN)
 
-bool fce_handle_coalescation(int event, const char *path, fce_obj_t type);
+bool fce_handle_coalescation(int event, const char *path);
 void fce_initialize_history();
 
 
index 69f6ea0dabfb9987c767eb6b8ff521bcdc3c1c9e..8586a40b9a3d49d575e0fd97450e8539ebcf5ada 100644 (file)
@@ -89,7 +89,7 @@ void fce_initialize_history()
        }
 }
 
-bool fce_handle_coalescation(int event, const char *path, fce_obj_t type)
+bool fce_handle_coalescation(int event, const char *path)
 {
        /* These two are used to eval our next index in history */
        /* the history is unsorted, speed should not be a problem, length is 10 */
@@ -138,7 +138,6 @@ bool fce_handle_coalescation(int event, const char *path, fce_obj_t type)
 
                /* If we find a parent dir we should be DELETED we are done */
                if ((coalesce & FCE_COALESCE_DELETE)
-            && fh->fce_h_type
             && (event == FCE_FILE_DELETE || event == FCE_DIR_DELETE)) {
                        /* Parent dir ? */
                        if (!strncmp(fh->fce_h_path, path, strlen(fh->fce_h_path)))
@@ -155,8 +154,7 @@ bool fce_handle_coalescation(int event, const char *path, fce_obj_t type)
        /* We have a new entry for the history, register it */
        fce_history_list[oldest_entry_idx].fce_h_tv = tv;
        fce_history_list[oldest_entry_idx].fce_h_event = event;
-       fce_history_list[oldest_entry_idx].fce_h_type = type;
-       strncpy(fce_history_list[oldest_entry_idx].fce_h_path, path, MAXPATHLEN);
+    strncpy(fce_history_list[oldest_entry_idx].fce_h_path, path, MAXPATHLEN);
 
        /* we have to handle this event */
        return false;
index cb8a968af09ddf491721b18b6b691f0fa97b62ce..881640da3871fa0824792fce47b578201b014da2 100644 (file)
@@ -252,7 +252,7 @@ restart:
                     }
                     LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.",
                         vol->v_path);
-                    vol->v_cdb = cnid_open(vol->v_path, vol->v_umask, "tdb", flags, NULL, NULL, NULL, NULL);
+                    vol->v_cdb = cnid_open(vol, "tdb", flags);
                     if (vol->v_cdb) {
                         if (!(vol->v_flags & AFPVOL_TM)) {
                             vol->v_flags |= AFPVOL_RO;
@@ -764,7 +764,7 @@ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_,
 createfile_iderr:
     ad_flush(&ad);
     ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
-    fce_register(FCE_FILE_CREATE, fullpathname(upath), NULL, fce_file);
+    fce_register(obj, FCE_FILE_CREATE, fullpathname(upath), NULL);
     sl_index_file(path);
 
     curdir->d_offcnt++;
@@ -1662,7 +1662,7 @@ int afp_createid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, si
         return( AFPERR_PARAM);
     }
 
-    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)) {
         return AFPERR_NOOP;
     }
 
@@ -1801,7 +1801,7 @@ int afp_resolveid(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_
         return( AFPERR_PARAM);
     }
 
-    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)) {
         return AFPERR_NOOP;
     }
 
@@ -1909,7 +1909,7 @@ int afp_deleteid(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_
         return( AFPERR_PARAM);
     }
 
-    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)) {
         return AFPERR_NOOP;
     }
 
index f35edfc9ad6496e4cf3e00d949015b97b7964374..7adbeed61c94e9fb02bfa80ed75f21b8e8e9912b 100644 (file)
@@ -219,7 +219,8 @@ int check_name(const struct vol *vol, char *name)
     move and rename sdir:oldname to curdir:newname in volume vol
     special care is needed for lock   
 */
-static int moveandrename(struct vol *vol,
+static int moveandrename(const AFPObj *obj,
+                         struct vol *vol,
                          struct dir *sdir,
                          int sdir_fd,
                          char *oldname,
@@ -238,10 +239,6 @@ static int moveandrename(struct vol *vol,
     cnid_t          id;
     int             cwd_fd = -1;
 
-    LOG(log_debug, logtype_afpd,
-        "moveandrename: [\"%s\"/\"%s\"] -> \"%s\"",
-        cfrombstr(sdir->d_u_name), oldname, newname);
-
     ad_init(&ad, vol);
     adp = &ad;
     adflags = 0;
@@ -326,6 +323,15 @@ static int moveandrename(struct vol *vol,
         goto exit;
     }
 
+    if (isdir)
+        LOG(log_debug, logtype_afpd,
+            "moveandrename(\"%s\" -> \"%s/%s\")",
+            oldunixname, bdata(curdir->d_fullpath), upath);
+    else
+        LOG(log_debug, logtype_afpd,
+            "moveandrename(\"%s/%s\" -> \"%s/%s\")",
+            bdata(sdir->d_fullpath), oldunixname, bdata(curdir->d_fullpath), upath);
+
     /* source == destination. we just silently accept this. */
     if ((!isdir && curdir == sdir) || (isdir && curdir->d_did == sdir->d_pdid)) {
         if (strcmp(oldname, newname) == 0) {
@@ -384,6 +390,15 @@ static int moveandrename(struct vol *vol,
         AFP_CNID_START("cnid_update");
         cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath));
         AFP_CNID_DONE();
+
+        /* Send FCE event */
+        if (isdir) {
+            fce_register(obj, FCE_DIR_MOVE, fullpathname(upath), oldunixname);
+        } else {
+            bstring srcpath = bformat("%s/%s", bdata(sdir->d_fullpath), oldunixname);
+            fce_register(obj, FCE_FILE_MOVE, fullpathname(upath), bdata(srcpath));
+            bdestroy(srcpath);
+        }
     }
 
 exit:
@@ -461,7 +476,7 @@ int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
         return AFP_OK; /* newname == oldname same dir */
     }
     
-    rc = moveandrename(vol, sdir, -1, oldname, newname, isdir);
+    rc = moveandrename(obj, vol, sdir, -1, oldname, newname, isdir);
     if ( rc == AFP_OK ) {
         setvoltime(obj, vol );
     }
@@ -615,7 +630,7 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
                 cnid_delete(vol->v_cdb, delcnid);
                 AFP_CNID_DONE();
             }
-            fce_register(FCE_DIR_DELETE, fullpathname(upath), NULL, fce_dir);
+            fce_register(obj, FCE_DIR_DELETE, fullpathname(upath), NULL);
         } else {
             /* we have to cache this, the structs are lost in deletcurdir*/
             /* but we need the positive returncode to send our event */
@@ -623,7 +638,7 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
             if ((dname = bstrcpy(curdir->d_u_name)) == NULL)
                 return AFPERR_MISC;
             if ((rc = deletecurdir(vol)) == AFP_OK)
-                fce_register(FCE_DIR_DELETE, fullpathname(cfrombstr(dname)), NULL, fce_dir);
+                fce_register(obj, FCE_DIR_DELETE, fullpathname(cfrombstr(dname)), NULL);
             bdestroy(dname);
         }
     } else if (of_findname(vol, s_path)) {
@@ -637,7 +652,7 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
             rc = AFPERR_NOOBJ;
         } else {
             if ((rc = deletefile(vol, -1, upath, 1)) == AFP_OK) {
-                               fce_register(FCE_FILE_DELETE, fullpathname(upath), NULL, fce_file);
+                               fce_register(obj, FCE_FILE_DELETE, fullpathname(upath), NULL);
                 if (vol->v_tm_used < s_path->st.st_size)
                     vol->v_tm_used = 0;
                 else 
@@ -782,7 +797,7 @@ int afp_moveandrename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
     /* This does the work */
     LOG(log_debug, logtype_afpd, "afp_move(oldname:'%s', newname:'%s', isdir:%u)",
         oldname, newname, isdir);
-    rc = moveandrename(vol, sdir, sdir_fd, oldname, newname, isdir);
+    rc = moveandrename(obj, vol, sdir, sdir_fd, oldname, newname, isdir);
 
     if ( rc == AFP_OK ) {
         char *upath = mtoupath(vol, newname, pdid, utf8_encoding(obj));
index 24284c1d745f0bc62fce6668637b7333943a8964..4311655ec6597a19a55d9bff6cffbb061fbfa204 100644 (file)
@@ -153,27 +153,6 @@ static int fork_setmode(const AFPObj *obj, struct adouble *adp, int eid, int acc
     int denyreadset;
     int denywriteset;
 
-#ifdef HAVE_FSHARE_T
-    fshare_t shmd;
-
-    if (obj->options.flags & OPTION_SHARE_RESERV) {
-        shmd.f_access = (access & OPENACC_RD ? F_RDACC : 0) | (access & OPENACC_WR ? F_WRACC : 0);
-        if (shmd.f_access == 0)
-            /* we must give an access mode, otherwise fcntl will complain */
-            shmd.f_access = F_RDACC;
-        shmd.f_deny = (access & OPENACC_DRD ? F_RDDNY : F_NODNY) | (access & OPENACC_DWR) ? F_WRDNY : 0;
-        shmd.f_id = ofrefnum;
-
-        int fd = (eid == ADEID_DFORK) ? ad_data_fileno(adp) : ad_reso_fileno(adp);
-
-        if (fd != -1 && fd != AD_SYMLINK && fcntl(fd, F_SHARE, &shmd) != 0) {
-            LOG(log_debug, logtype_afpd, "fork_setmode: fcntl: %s", strerror(errno));
-            errno = EACCES;
-            return -1;
-        }
-    }
-#endif
-
     if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
         return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
     }
@@ -233,6 +212,35 @@ static int fork_setmode(const AFPObj *obj, struct adouble *adp, int eid, int acc
         }
     }
 
+    /*
+     * Fix for Bug 560: put the Solaris share reservation after our locking stuff.
+     * Note that this still leaves room for a race condition where between placing our own
+     * locks above and putting the Solaris share move below another client puts a lock.
+     * We then end up with set locks from above and return with an error code, the proper
+     * fix requires a sane cleanup function for the error path in this function.
+     */
+
+#ifdef HAVE_FSHARE_T
+    fshare_t shmd;
+
+    if (obj->options.flags & OPTION_SHARE_RESERV) {
+        shmd.f_access = (access & OPENACC_RD ? F_RDACC : 0) | (access & OPENACC_WR ? F_WRACC : 0);
+        if (shmd.f_access == 0)
+            /* we must give an access mode, otherwise fcntl will complain */
+            shmd.f_access = F_RDACC;
+        shmd.f_deny = (access & OPENACC_DRD ? F_RDDNY : F_NODNY) | (access & OPENACC_DWR) ? F_WRDNY : 0;
+        shmd.f_id = ofrefnum;
+
+        int fd = (eid == ADEID_DFORK) ? ad_data_fileno(adp) : ad_reso_fileno(adp);
+
+        if (fd != -1 && fd != AD_SYMLINK && fcntl(fd, F_SHARE, &shmd) != 0) {
+            LOG(log_debug, logtype_afpd, "fork_setmode: fcntl: %s", strerror(errno));
+            errno = EACCES;
+            return -1;
+        }
+    }
+#endif
+
     return 0;
 }
 
index ac1ce217b31904593f30b0ce4aa5d57617df323a..e612a01cae9615f3264378d4df11ff37a4832fa6 100644 (file)
@@ -40,8 +40,7 @@
 #include "afp_zeroconf.h"
 #include "afpstats.h"
 
-#define AFP_LISTENERS 32
-#define FDSET_SAFETY  5
+#define ASEV_THRESHHOLD 10
 
 unsigned char nologin = 0;
 
@@ -49,12 +48,7 @@ static AFPObj obj;
 static server_child_t *server_children;
 static sig_atomic_t reloadconfig = 0;
 static sig_atomic_t gotsigchld = 0;
-
-/* Two pointers to dynamic allocated arrays which store pollfds and associated data */
-static struct pollfd *fdset;
-static struct polldata *polldata;
-static int fdset_size;          /* current allocated size */
-static int fdset_used;          /* number of used elements */
+static struct asev *asev;
 
 static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child_t *server_children);
 
@@ -67,29 +61,39 @@ static void afp_exit(int ret)
 /* ------------------
    initialize fd set we are waiting for.
 */
-static void fd_set_listening_sockets(const AFPObj *config)
+static bool init_listening_sockets(const AFPObj *config)
 {
     DSI *dsi;
+    int numlisteners;
+
+    for (numlisteners = 0, dsi = config->dsi; dsi; dsi = dsi->next) {
+        numlisteners++;
+    }
+
+    asev = asev_init(config->options.connections + numlisteners + ASEV_THRESHHOLD);
+    if (asev == NULL) {
+        return false;
+    }
 
     for (dsi = config->dsi; dsi; dsi = dsi->next) {
-        fdset_add_fd(config->options.connections + AFP_LISTENERS + FDSET_SAFETY,
-                     &fdset,
-                     &polldata,
-                     &fdset_used,
-                     &fdset_size,
-                     dsi->serversock,
-                     LISTEN_FD,
-                     dsi);
+        if (!(asev_add_fd(asev, dsi->serversock, LISTEN_FD, dsi))) {
+            return false;
+        }
     }
+
+    return true;
 }
  
-static void fd_reset_listening_sockets(const AFPObj *config)
+static bool reset_listening_sockets(const AFPObj *config)
 {
     const DSI *dsi;
 
     for (dsi = config->dsi; dsi; dsi = dsi->next) {
-        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, dsi->serversock);
+        if (!(asev_del_fd(asev, dsi->serversock))) {
+            return false;
+        }
     }
+    return true;
 }
 
 /* ------------------ */
@@ -133,7 +137,7 @@ static void afp_goaway(int sig)
 static void child_handler(void)
 {
     int fd;
-    int status, i;
+    int status;
     pid_t pid;
   
 #ifndef WAIT_ANY
@@ -141,11 +145,6 @@ static void child_handler(void)
 #endif /* ! WAIT_ANY */
 
     while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
-        if ((fd = server_child_remove(server_children, pid)) != -1) {
-            fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd);        
-            break;
-        }
-
         if (WIFEXITED(status)) {
             if (WEXITSTATUS(status))
                 LOG(log_info, logtype_afpd, "child[%d]: exited %d", pid, WEXITSTATUS(status));
@@ -157,6 +156,14 @@ static void child_handler(void)
             else
                 LOG(log_info, logtype_afpd, "child[%d]: died", pid);
         }
+
+        fd = server_child_remove(server_children, pid);
+        if (fd == -1) {
+            continue;
+        }
+        if (!(asev_del_fd(asev, fd))) {
+            LOG(log_error, logtype_afpd, "child[%d]: asev_del_fd: %d", pid, fd);
+        }
     }
 }
 
@@ -327,14 +334,15 @@ int main(int ac, char **av)
     cnid_init();
 
     /* watch atp, dsi sockets and ipc parent/child file descriptor. */
-    fd_set_listening_sockets(&obj);
+    if (!(init_listening_sockets(&obj))) {
+        LOG(log_error, logtype_afpd, "main: couldn't initialize socket handler");
+        afp_exit(EXITERR_CONF);
+    }
 
     /* set limits */
     (void)setlimits();
 
     afp_child_t *child;
-    int recon_ipc_fd;
-    pid_t pid;
     int saveerrno;
 
     /* wait for an appleshare connection. parent remains in the loop
@@ -344,9 +352,8 @@ int main(int ac, char **av)
      * afterwards. establishing timeouts for logins is a possible 
      * solution. */
     while (1) {
-        LOG(log_maxdebug, logtype_afpd, "main: polling %i fds", fdset_used);
         pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
-        ret = poll(fdset, fdset_used, -1);
+        ret = poll(asev->fdset, asev->used, -1);
         pthread_sigmask(SIG_BLOCK, &sigs, NULL);
         saveerrno = errno;
 
@@ -359,7 +366,10 @@ int main(int ac, char **av)
         if (reloadconfig) {
             nologin++;
 
-            fd_reset_listening_sockets(&obj);
+            if (!(reset_listening_sockets(&obj))) {
+                LOG(log_error, logtype_afpd, "main: reset socket handlers");
+                afp_exit(EXITERR_CONF);
+            }
 
             LOG(log_info, logtype_afpd, "re-reading configuration file");
 
@@ -374,7 +384,10 @@ int main(int ac, char **av)
                 afp_exit(EXITERR_CONF);
             }
 
-            fd_set_listening_sockets(&obj);
+            if (!(init_listening_sockets(&obj))) {
+                LOG(log_error, logtype_afpd, "main: couldn't initialize socket handler");
+                afp_exit(EXITERR_CONF);
+            }
 
             nologin = 0;
             reloadconfig = 0;
@@ -392,30 +405,40 @@ int main(int ac, char **av)
             break;
         }
 
-        for (int i = 0; i < fdset_used; i++) {
-            if (fdset[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) {
-                switch (polldata[i].fdtype) {
+        for (int i = 0; i < asev->used; i++) {
+            if (asev->fdset[i].revents & (POLLIN | POLLERR | POLLHUP | POLLNVAL)) {
+                switch (asev->data[i].fdtype) {
 
                 case LISTEN_FD:
-                    if ((child = dsi_start(&obj, (DSI *)polldata[i].data, server_children))) {
-                        /* Add IPC fd to select fd set */
-                        fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
-                                     &fdset,
-                                     &polldata,
-                                     &fdset_used,
-                                     &fdset_size,
-                                     child->afpch_ipc_fd,
-                                     IPC_FD,
-                                     child);
+                    if ((child = dsi_start(&obj, (DSI *)(asev->data[i].private), server_children))) {
+                        if (!(asev_add_fd(asev, child->afpch_ipc_fd, IPC_FD, child))) {
+                            LOG(log_error, logtype_afpd, "out of asev slots");
+
+                            /*
+                             * Close IPC fd here and mark it as unused
+                             */
+                            close(child->afpch_ipc_fd);
+                            child->afpch_ipc_fd = -1;
+
+                            /*
+                             * Being unfriendly here, but we really
+                             * want to get rid of it. The 'child'
+                             * handle gets cleaned up in the SIGCLD
+                             * handler.
+                             */
+                            kill(child->afpch_pid, SIGKILL);
+                        }
                     }
                     break;
 
                 case IPC_FD:
-                    child = (afp_child_t *)polldata[i].data;
+                    child = (afp_child_t *)(asev->data[i].private);
                     LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->afpch_pid);
 
                     if (ipc_server_read(server_children, child->afpch_ipc_fd) != 0) {
-                        fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->afpch_ipc_fd);
+                        if (!(asev_del_fd(asev, child->afpch_ipc_fd))) {
+                            LOG(log_error, logtype_afpd, "child[%u]: no IPC fd");
+                        }
                         close(child->afpch_ipc_fd);
                         child->afpch_ipc_fd = -1;
                     }
index 7c975c38f9ed581702e74827aaaf2c2d863e8ce7..59e9f153041d4da0768055a9f548ada9dd594171 100644 (file)
 #include <atalk/bstradd.h>
 #include <atalk/globals.h>
 #include <atalk/fce_api.h>
+#include <atalk/ea.h>
 
 #include "volume.h"
 #include "directory.h"
 #include "fork.h"
+#include "desktop.h"
 
 /* we need to have a hashed list of oforks (by dev inode) */
 #define OFORK_HASHSIZE  64
@@ -389,6 +391,8 @@ int of_closefork(const AFPObj *obj, struct ofork *ofork)
     struct timeval      tv;
     int         adflags = 0;
     int                 ret;
+    struct dir *dir;
+    bstring forkpath = NULL;
 
     adflags = 0;
     if (ofork->of_flags & AFPFORK_DATA)
@@ -405,14 +409,18 @@ int of_closefork(const AFPObj *obj, struct ofork *ofork)
         }
     }
 
+    dir = dirlookup(ofork->of_vol, ofork->of_did);
+    if (dir == NULL) {
+        LOG(log_debug, logtype_afpd, "dirlookup failed for %ju", (uintmax_t)ofork->of_did);
+    }
+
+    if (dir) {
+        forkpath = bformat("%s/%s", bdata(dir->d_fullpath), of_name(ofork));
+    }
+
     /* Somone has used write_fork, we assume file was changed, register it to file change event api */
-    if (ofork->of_flags & AFPFORK_MODIFIED) {
-        struct dir *dir =  dirlookup(ofork->of_vol, ofork->of_did);
-        if (dir) {
-            bstring forkpath = bformat("%s/%s", bdata(dir->d_fullpath), of_name(ofork));
-            fce_register(FCE_FILE_MODIFY, bdata(forkpath), NULL, fce_file);
-            bdestroy(forkpath);
-        }
+    if ((ofork->of_flags & AFPFORK_MODIFIED) && (forkpath)) {
+        fce_register(obj, FCE_FILE_MODIFY, bdata(forkpath), NULL);
     }
 
     ad_unlock(ofork->of_ad, ofork->of_refnum, ofork->of_flags & AFPFORK_ERROR ? 0 : 1);
@@ -429,12 +437,46 @@ int of_closefork(const AFPObj *obj, struct ofork *ofork)
 #endif
 
     ret = 0;
+
+    /*
+     * Check for 0 byte size resource forks, delete them.
+     * Here's the deal:
+     * (1) the size must be 0
+     * (2) the fork must refer to a resource fork
+     * (3) the refcount must be 1 which means this fork has the last
+     *     reference to the adouble struct and the subsequent
+     *     ad_close() will close the assoiciated fd.
+     * (4) nobody else has the resource fork open
+     *
+     * We only do this for ._ AppleDouble resource forks, not for
+     * xattr resource forks, because the test-suite then fails several
+     * tests on Solaris, the reason for that still needs to be
+     * determined.
+     */
+    if ((ofork->of_ad->ad_rlen == 0)
+        && (ofork->of_flags & AFPFORK_RSRC)
+        && (ofork->of_ad->ad_rfp->adf_refcount == 1)
+        && (ad_openforks(ofork->of_ad, ATTRBIT_DOPEN) == 0)) {
+
+#ifndef HAVE_EAFD
+        (void)unlink(ofork->of_ad->ad_ops->ad_path(
+                         mtoupath(ofork->of_vol,
+                                  of_name(ofork),
+                                  ofork->of_did,
+                                  utf8_encoding(obj)),
+                         0));
+#endif
+    }
+
     if ( ad_close( ofork->of_ad, adflags | ADFLAGS_SETSHRMD) < 0 ) {
         ret = -1;
     }
 
     of_dealloc(ofork);
 
+    if (forkpath)
+        bdestroy(forkpath);
+
     return ret;
 }
 
index 614a7f95e74956a6d5881b4b35b0915cf20c3fe4..bab14e1345baf9a9f8b9447518ab1233b7f7650b 100644 (file)
@@ -510,6 +510,7 @@ static int getfsquota(const AFPObj *obj, struct vol *vol, const int uid, struct
     struct quotctl      qc;
 #endif
 
+    memset(dq, 0, sizeof(struct dqblk));
     memset(&dqg, 0, sizeof(dqg));
        
 #ifdef __svr4__
@@ -558,7 +559,9 @@ static int getfsquota(const AFPObj *obj, struct vol *vol, const int uid, struct
 
 #else /* BSD4_4 */
     if (get_linux_quota (WANT_USER_QUOTA, vol->v_gvs, uid, dq) !=0) {
-        return( AFPERR_PARAM );
+#ifdef DEBUG_QUOTA
+        LOG(log_debug, logtype_afpd, "user quota did not work!" );
+#endif /* DEBUG_QUOTA */
     }
 
     if (get_linux_quota(WANT_GROUP_QUOTA, vol->v_gvs, getegid(),  &dqg) != 0) {
@@ -590,10 +593,15 @@ static int getfsquota(const AFPObj *obj, struct vol *vol, const int uid, struct
       ) /* if */
     {
         /* use group quota limits rather than user limits */
-        dq->dqb_curblocks = dqg.dqb_curblocks;
         dq->dqb_bhardlimit = dqg.dqb_bhardlimit;
         dq->dqb_bsoftlimit = dqg.dqb_bsoftlimit;
-        dq->dqb_btimelimit = dqg.dqb_btimelimit;
+        dq->dqb_curblocks = dqg.dqb_curblocks;
+        dq->dqb_ihardlimit = dqg.dqb_ihardlimit;
+        dq->dqb_isoftlimit = dqg.dqb_isoftlimit;
+        dq->dqb_curinodes = dqg.dqb_curinodes;
+        dq->dqb_btime = dqg.dqb_btime;
+        dq->dqb_itime = dqg.dqb_itime;
+        dq->bsize = dqg.bsize;
     } /* if */
 
 #endif /* TRU64 */
index fff5a36ba244def42fed80134ae2664b603cfbd9..565462444504ea6a042f9c2ce77350ee25768796 100644 (file)
@@ -283,6 +283,11 @@ static int sl_rpc_openQuery(AFPObj *obj, const DALLOC_CTX *query, DALLOC_CTX *re
     slq->slq_state = SLQ_STATE_NEW;
     slq->slq_obj = obj;
     slq->slq_vol = v;
+    slq->slq_allow_expr = obj->options.flags & OPTION_SPOTLIGHT_EXPR ? true : false;
+    slq->slq_result_limit = obj->options.sparql_limit;
+
+    LOG(log_info, logtype_sl, "sl_rpc_openQuery: expr: %s, limit: %" PRIu64,
+        slq->slq_allow_expr ? "yes" : "no", slq->slq_result_limit);
 
     /* convert spotlight query charset to host charset */
     EC_NULL_LOG( sl_query = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, "kMDQueryString") );
@@ -390,7 +395,14 @@ static int sl_rpc_storeAttributesForOIDArray(const AFPObj *obj, const DALLOC_CTX
         EC_NEG1_LOG( movecwd(vol, dir) );
     }
 
-    if ((sl_time = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, "DALLOC_CTX", 1, "kMDItemLastUsedDate"))) {
+    /*
+     * We're possibly supposed to update attributes in two places: the
+     * database and the filesystem.  Due to the lack of documentation
+     * and not yet implemented database updates, we cherry pick attributes
+     * that seems to be candidates for updating filesystem metadata.
+     */
+
+    if ((sl_time = dalloc_value_for_key(query, "DALLOC_CTX", 0, "DALLOC_CTX", 1, "DALLOC_CTX", 1, "kMDItemFSContentChangeDate"))) {
         struct utimbuf utimes;
         utimes.actime = utimes.modtime = sl_time->tv_sec;
         utime(path, &utimes);
@@ -573,23 +585,23 @@ EC_CLEANUP:
  * Spotlight module functions
  **************************************************************************************************/
 
-int sl_mod_load(const char *path)
+int sl_mod_load(AFPObj *obj)
 {
     EC_INIT;
 
     sl_ctx = talloc_new(NULL);
 
-    if ((sl_module = mod_open(path)) == NULL) {
-        LOG(log_error, logtype_sl, "Failed to load module \'%s\': %s", path, mod_error());
+    if ((sl_module = mod_open(obj->options.slmod_path)) == NULL) {
+        LOG(log_error, logtype_sl, "Failed to load module \'%s\': %s", obj->options.slmod_path, mod_error());
         EC_FAIL;
     }
 
     if ((sl_module_export = mod_symbol(sl_module, "sl_mod")) == NULL) {
-        LOG(log_error, logtype_sl, "sl_mod_load(%s): mod_symbol error for symbol %s", path, "sl_mod");
+        LOG(log_error, logtype_sl, "sl_mod_load(%s): mod_symbol error for symbol sl_mod", obj->options.slmod_path);
         EC_FAIL;
     }
 
-    sl_module_export->sl_mod_init("test");
+    sl_module_export->sl_mod_init(obj);
    
 EC_CLEANUP:
     EC_EXIT;
index 7c90462874cd0cceec47f3c9836f42319e6a1937..a42a6ab9093fde4f923e43510474d52ad58334b4 100644 (file)
@@ -229,18 +229,22 @@ int setdirunixmode(const struct vol *vol, char *name, mode_t mode)
     LOG(log_debug, logtype_afpd, "setdirunixmode('%s', mode:%04o) {v_dperm:%04o}",
         fullpathname(name), mode, vol->v_dperm);
 
-    mode |= vol->v_dperm;
+    mode |= (vol->v_dperm | DIRBITS) & ~vol->v_umask;
 
     if (dir_rx_set(mode)) {
        /* extending right? dir first then .AppleDouble in rf_setdirmode */
-       if (chmod_acl(name, (DIRBITS | mode) & ~vol->v_umask) < 0 )
+        if (ochmod(name, mode, NULL,
+                   vol_syml_opt(vol) | vol_chmod_opt(vol)
+                ) < 0)
                return -1;
     }
     if (vol->vfs->vfs_setdirunixmode(vol, name, mode, NULL) < 0) {
         return  -1 ;
     }
     if (!dir_rx_set(mode)) {
-       if (chmod_acl(name, (DIRBITS | mode) & ~vol->v_umask) < 0 )
+        if (ochmod(name, mode, NULL,
+                   vol_syml_opt(vol) | vol_chmod_opt(vol)
+                ) < 0)
             return -1;
     }
     return 0;
index a3ee79278763d198029af7c35a0be3260cae17a2..7bdff75dff53ecf87007a9b001a45c87bae944de 100644 (file)
@@ -369,7 +369,7 @@ static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, str
             }
             /* 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;
 
@@ -639,16 +639,7 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume)
         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,
-                              (const void *)obj,
-                              volume->v_uuid);
+    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 */
@@ -657,7 +648,7 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume)
         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, NULL, NULL);
+        volume->v_cdb = cnid_open(volume, "tdb", flags);
 #ifdef SERVERTEXT
         /* kill ourself with SIGUSR2 aka msg pending */
         if (volume->v_cdb) {
@@ -855,7 +846,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
          * 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) {
index 266b986ba00da9905c56777b4ac5dff6f50b4625..9e8e008ec0ce86da94d186f57309da9e002ae752 100644 (file)
@@ -25,6 +25,7 @@
 #include <signal.h>
 #include <string.h>
 #include <errno.h>
+#include <pwd.h>
 
 #include <atalk/logger.h>
 #include <atalk/globals.h>
@@ -92,7 +93,7 @@ static void set_signal(void)
 
 static void usage (void)
 {
-    printf("Usage: dbd [-cfFstvV] <path to netatalk volume>\n\n"
+    printf("Usage: dbd [-cfFstuvV] <path to netatalk volume>\n\n"
            "dbd scans all file and directories of AFP volumes, updating the\n"
            "CNID database of the volume. dbd must be run with appropiate\n"
            "permissions i.e. as root.\n\n"
@@ -103,6 +104,7 @@ static void usage (void)
            "   -F location of the afp.conf config file\n"
            "   -f delete and recreate CNID database\n"
            "   -t show statistics while running\n"
+           "   -u username for use with AFP volumes using user variable $u\n"
            "   -v verbose\n"
            "   -V show version info\n\n"
         );
@@ -136,9 +138,9 @@ int main(int argc, char **argv)
     AFPObj obj = { 0 };
     struct vol *vol = NULL;
     const char *volpath = NULL;
-
+    char *username = NULL;
     int c;
-    while ((c = getopt(argc, argv, ":cfF:rstvV")) != -1) {
+    while ((c = getopt(argc, argv, ":cfF:rstu:vV")) != -1) {
         switch(c) {
         case 'c':
             flags |= DBD_FLAGS_V2TOEA;
@@ -159,6 +161,9 @@ int main(int argc, char **argv)
         case 't':
             flags |= DBD_FLAGS_STATS;
             break;
+        case 'u':
+            username = strdup(optarg);
+            break;
         case 'v':
             flags |= DBD_FLAGS_VERBOSE;
             break;
@@ -203,6 +208,7 @@ int main(int argc, char **argv)
         exit(EXIT_FAILURE);
     }
 
+
     /* Initialize CNID subsystem */
     cnid_init();
 
@@ -212,6 +218,18 @@ int main(int argc, char **argv)
     else
         setuplog("default:note", "/dev/tty");
 
+    /* Set username */
+    if (username) {
+        strncpy(obj.username, username, MAXUSERLEN);
+        struct passwd *pwd;
+        pwd = getpwnam(obj.username);
+        if (!pwd) {
+            dbd_log( LOGSTD, "unknown user");
+            exit(EXIT_FAILURE);
+        }
+        obj.uid = pwd->pw_uid;
+    }
+
     if (load_volumes(&obj, lv_all) != 0) {
         dbd_log( LOGSTD, "Couldn't load volumes");
         exit(EXIT_FAILURE);
@@ -232,14 +250,9 @@ int main(int argc, char **argv)
         dbd_log(LOGSTD, "\"%s\" isn't a \"dbd\" CNID volume", vol->v_path);
         exit(EXIT_FAILURE);
     }
-    if ((vol->v_cdb = cnid_open(vol->v_path,
-                                0000,
-                                vol->v_cnidscheme,
-                                vol->v_flags & AFPVOL_NODEV ? CNID_FLAG_NODEV : 0,
-                                vol->v_cnidserver,
-                                vol->v_cnidport,
-                                &obj,
-                                vol->v_uuid)) == NULL) {
+    vol->v_cdb = cnid_open(vol, vol->v_cnidscheme,
+                           vol->v_flags & AFPVOL_NODEV ? CNID_FLAG_NODEV : 0);
+    if (vol->v_cdb == NULL) {
         dbd_log(LOGSTD, "Cant initialize CNID database connection for %s", vol->v_path);
         exit(EXIT_FAILURE);
     }
index 1b991cb8bf39d5f89a86d4f3c849e3d63b4379ce..b05d72db61cf4d1d3cd76711f129ba50079d9358 100644 (file)
@@ -155,8 +155,17 @@ static struct server *test_usockfn(const char *path)
     return NULL;
 }
 
-/* -------------------- */
-static int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath)
+/**
+ * Pass connection request to existing cnid_dbd process or start a new one
+ *
+ * @param[in] obj      handle
+ * @param[in] dbdpn    Path to cnid_dbd binary
+ * @param[in] volpath  Path of AFP volume
+ * @param[in] username  Optional username, may be NULL
+ *
+ * @return 0 on success, -1 on error
+ **/
+ int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath, const char *username)
 {
     pid_t pid;
     struct server *up;
@@ -266,9 +275,21 @@ static int maybe_start_dbd(const AFPObj *obj, char *dbdpn, const char *volpath)
             LOG(log_warning, logtype_cnid,
                 "Multiple attempts to start CNID db daemon for \"%s\" failed, wiping the slate clean...",
                 up->v_path);
-            ret = execlp(dbdpn, dbdpn, "-F", obj->options.configfile, "-p", volpath, "-t", buf1, "-l", buf2, "-d", NULL);
+            ret = execlp(dbdpn, dbdpn,
+                         "-F", obj->options.configfile,
+                         "-p", volpath,
+                         "-t", buf1,
+                         "-l", buf2,
+                         "-u", username,
+                         NULL);
         } else {
-            ret = execlp(dbdpn, dbdpn, "-F", obj->options.configfile, "-p", volpath, "-t", buf1, "-l", buf2, NULL);
+            ret = execlp(dbdpn, dbdpn,
+                         "-F", obj->options.configfile,
+                         "-p", volpath,
+                         "-t", buf1,
+                         "-l", buf2,
+                         "-u", username,
+                         NULL);
         }
         /* Yikes! We're still here, so exec failed... */
         LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno));
@@ -419,11 +440,23 @@ static int setlimits(void)
     return 0;
 }
 
+static uid_t uid_from_name(const char *name)
+{
+    struct passwd *pwd;
+
+    pwd = getpwnam(name);
+    if (pwd == NULL)
+        return 0;
+    return pwd->pw_uid;
+}
+
 /* ------------------ */
 int main(int argc, char *argv[])
 {
-    char  volpath[MAXPATHLEN + 1];
-    int   len, actual_len;
+    char  *volname = NULL;
+    char  *volpath = NULL;
+    char  *username = NULL;
+    int   len[DBD_NUM_OPEN_ARGS], actual_len;
     pid_t pid;
     int   status;
     char  *dbdpn = _PATH_CNID_DBD;
@@ -463,9 +496,6 @@ int main(int argc, char *argv[])
     if (afp_config_parse(&obj, "cnid_metad") != 0)
         daemon_exit(1);
 
-    if (load_volumes(&obj, lv_all) != 0)
-        daemon_exit(1);
-
     (void)setlimits();
 
     host = atalk_iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700");
@@ -529,7 +559,7 @@ int main(int argc, char *argv[])
         if (rqstfd <= 0)
             continue;
 
-        ret = readt(rqstfd, &len, sizeof(int), 1, 4);
+        ret = readt(rqstfd, &len[0], sizeof(int) * DBD_NUM_OPEN_ARGS, 1, 4);
 
         if (!ret) {
             /* already close */
@@ -539,31 +569,58 @@ int main(int argc, char *argv[])
             LOG(log_severe, logtype_cnid, "error read: %s", strerror(errno));
             goto loop_end;
         }
-        else if (ret != sizeof(int)) {
+        else if (ret != DBD_NUM_OPEN_ARGS * sizeof(int)) {
             LOG(log_error, logtype_cnid, "short read: got %d", ret);
             goto loop_end;
         }
+
         /*
          *  checks for buffer overruns. The client libatalk side does it too
          *  before handing the dir path over but who trusts clients?
          */
-        if (!len || len +DBHOMELEN +2 > MAXPATHLEN) {
-            LOG(log_error, logtype_cnid, "wrong len parameter: %d", len);
+        if (!len[0] || !len[1]) {
+            LOG(log_error, logtype_cnid, "wrong len parameter: len[0]: %d, len[1]: %d", len[0], len[1]);
             goto loop_end;
         }
 
-        actual_len = readt(rqstfd, volpath, len, 1, 5);
-        if (actual_len < 0) {
-            LOG(log_severe, logtype_cnid, "Read(2) error : %s", strerror(errno));
+        volname = malloc(len[0]);
+        volpath = malloc(len[1]);
+        if (len[2]) {
+            username = malloc(len[2]);
+        }
+        if (!volname || !volpath || (len[2] && !username)) {
+            LOG(log_severe, logtype_cnid, "malloc: %s", strerror(errno));
             goto loop_end;
         }
-        if (actual_len != len) {
-            LOG(log_error, logtype_cnid, "error/short read (dir): %s", strerror(errno));
+
+        actual_len = readt(rqstfd, volname, len[0], 1, 5);
+        if (actual_len != len[0]) {
+            LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno));
+            goto loop_end;
+        }
+
+        actual_len = readt(rqstfd, volpath, len[1], 1, 5);
+        if (actual_len != len[1]) {
+            LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno));
             goto loop_end;
         }
-        volpath[len] = '\0';
 
-        LOG(log_debug, logtype_cnid, "main: request for volume: %s", volpath);
+        if (len[2]) {
+            actual_len = readt(rqstfd, username, len[2], 1, 5);
+            if (actual_len != len[2]) {
+                LOG(log_severe, logtype_cnid, "readt: %s", strerror(errno));
+                goto loop_end;
+            }
+            strlcpy(obj.username, username, MAXUSERLEN);
+            obj.uid = uid_from_name(username);
+            if (!obj.uid)
+                goto loop_end;
+        } else {
+            obj.username[0] = 0;
+        }
+
+        LOG(log_debug, logtype_cnid, "user: %s, volume %s, path %s",
+            username ? username : "-", volname, volpath);
 
         if (load_volumes(&obj, lv_all) != 0) {
             LOG(log_severe, logtype_cnid, "main: error reloading config");
@@ -577,12 +634,17 @@ int main(int argc, char *argv[])
 
         LOG(log_maxdebug, logtype_cnid, "main: dbpath: %s", vol->v_dbpath);
 
-        if (set_dbdir(vol->v_dbpath, volpath) < 0) {
+        if (set_dbdir(vol->v_dbpath, vol->v_path) < 0) {
             goto loop_end;
         }
 
-        maybe_start_dbd(&obj, dbdpn, vol->v_path);
+        maybe_start_dbd(&obj, dbdpn, vol->v_path, username);
+
     loop_end:
         close(rqstfd);
+        unload_volumes(&obj);
+        SAFE_FREE(volname);
+        SAFE_FREE(volpath);
+        SAFE_FREE(username);
     }
 }
index 994c8ff698f44776c92b8413e4f344ff38892661..ddcf66743c8812273b16b3ad484466ecfbcfae2b 100644 (file)
@@ -474,6 +474,16 @@ static void set_signal(void)
     }
 }
 
+static uid_t uid_from_name(const char *name)
+{
+    struct passwd *pwd;
+
+    pwd = getpwnam(name);
+    if (pwd == NULL)
+        return 0;
+    return pwd->pw_uid;
+}
+
 /* ------------------------ */
 int main(int argc, char *argv[])
 {
@@ -482,8 +492,9 @@ int main(int argc, char *argv[])
     int ctrlfd = -1, clntfd = -1;
     AFPObj obj = { 0 };
     char *volpath = NULL;
+    char *username = NULL;
 
-    while (( ret = getopt( argc, argv, "dF:l:p:t:vV")) != -1 ) {
+    while (( ret = getopt( argc, argv, ":dF:l:p:t:u:vV")) != -1 ) {
         switch (ret) {
         case 'd':
             /* this is now just ignored, as we do it automatically anyway */
@@ -501,10 +512,15 @@ int main(int argc, char *argv[])
         case 't':
             ctrlfd = atoi(optarg);
             break;
+        case 'u':
+            username = strdup(optarg);
+            break;
         case 'v':
         case 'V':
             printf("cnid_dbd (Netatalk %s)\n", VERSION);
             return -1;
+        case ':':
+            break;
         }
     }
 
@@ -515,6 +531,17 @@ int main(int argc, char *argv[])
 
     EC_ZERO( afp_config_parse(&obj, "cnid_dbd") );
 
+    if (username) {
+        strlcpy(obj.username, username, MAXUSERLEN);
+        obj.uid = uid_from_name(username);
+        if (!obj.uid) {
+            EC_FAIL_LOG("unknown user: '%s'", username);
+        }
+    }
+
+    LOG(log_debug, logtype_cnid, "user: %s, path %s",
+        username ? username : "-", volpath);
+
     EC_ZERO( load_volumes(&obj, lv_all) );
     EC_NULL( vol = getvolbypath(&obj, volpath) );
     EC_ZERO( load_charset(vol) );
index 4a20d7b787af5547dddd5f24e6b7ee89d26edc41..1ce7befca67d66073dbac94b16fe7924fb4ef746 100644 (file)
 /* how many seconds we wait to shutdown from SIGTERM before we send SIGKILL */
 #define KILL_GRACETIME 5
 
+/* defines that control whether services should run by default */
+#define NETATALK_SRV_NEEDED  -1
+#define NETATALK_SRV_OPTIONAL 0
+#define NETATALK_SRV_ERROR    NETATALK_SRV_NEEDED
+
 /* forward declaration */
 static pid_t run_process(const char *path, ...);
 static void kill_childs(int sig, ...);
 
 /* static variables */
 static AFPObj obj;
-static pid_t afpd_pid = -1,  cnid_metad_pid = -1, dbus_pid = -1;
-static uint afpd_restarts, cnid_metad_restarts, dbus_restarts, trackerd_restarts;
+static pid_t afpd_pid = NETATALK_SRV_NEEDED;
+static pid_t cnid_metad_pid = NETATALK_SRV_NEEDED;
+static pid_t dbus_pid = NETATALK_SRV_OPTIONAL;
+static uint afpd_restarts, cnid_metad_restarts, dbus_restarts;
 static struct event_base *base;
 struct event *sigterm_ev, *sigquit_ev, *sigchld_ev, *timer_ev;
 static int in_shutdown;
 static const char *dbus_path;
-static char *trackerd_loglev;
 
 /******************************************************************
  * Misc stuff
  ******************************************************************/
 
+static bool service_running(pid_t pid)
+{
+    if ((pid != NETATALK_SRV_NEEDED) && (pid != NETATALK_SRV_OPTIONAL))
+        return true;
+    return false;
+}
+
 /* Set Tracker Miners to index all our volumes */
 static int set_sl_volumes(void)
 {
@@ -203,17 +216,21 @@ static void sigchld_cb(evutil_socket_t fd, short what, void *arg)
         }
 
         if (pid == afpd_pid)
-            afpd_pid = -1;
+            afpd_pid = NETATALK_SRV_ERROR;
         else if (pid == cnid_metad_pid)
-            cnid_metad_pid = -1;
+            cnid_metad_pid = NETATALK_SRV_ERROR;
         else if (pid == dbus_pid)
-            dbus_pid = -1;
+            dbus_pid = NETATALK_SRV_ERROR;
         else
             LOG(log_error, logtype_afpd, "Bad pid: %d", pid);
     }
 
-    if (in_shutdown && afpd_pid == -1 && cnid_metad_pid == -1 && dbus_pid == -1)
+    if (in_shutdown
+        && !service_running(afpd_pid)
+        && !service_running(cnid_metad_pid)
+        && !service_running(dbus_pid)) {
         event_base_loopbreak(base);
+    }
 }
 
 /* timer callback */
@@ -222,7 +239,7 @@ static void timer_cb(evutil_socket_t fd, short what, void *arg)
     if (in_shutdown)
         return;
 
-    if (afpd_pid == -1) {
+    if (afpd_pid == NETATALK_SRV_NEEDED) {
         afpd_restarts++;
         LOG(log_note, logtype_afpd, "Restarting 'afpd' (restarts: %u)", afpd_restarts);
         if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
@@ -230,7 +247,7 @@ static void timer_cb(evutil_socket_t fd, short what, void *arg)
         }
     }
 
-    if (cnid_metad_pid == -1) {
+    if (cnid_metad_pid == NETATALK_SRV_NEEDED) {
         cnid_metad_restarts++;
         LOG(log_note, logtype_afpd, "Restarting 'cnid_metad' (restarts: %u)", cnid_metad_restarts);
         if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
@@ -239,10 +256,10 @@ static void timer_cb(evutil_socket_t fd, short what, void *arg)
     }
 
 #ifdef HAVE_TRACKER
-    if (dbus_pid == -1) {
+    if (dbus_pid == NETATALK_SRV_NEEDED) {
         dbus_restarts++;
         LOG(log_note, logtype_afpd, "Restarting 'dbus' (restarts: %u)", dbus_restarts);
-        if ((dbus_pid = run_process(dbus_path, "--config-file=" _PATH_CONFDIR "dbus.session.conf", NULL)) == -1) {
+        if ((dbus_pid = run_process(dbus_path, "--config-file=" _PATH_CONFDIR "dbus-session.conf", NULL)) == -1) {
             LOG(log_error, logtype_default, "Error starting '%s'", dbus_path);
         }
     }
@@ -262,7 +279,7 @@ static void kill_childs(int sig, ...)
     va_start(args, sig);
 
     while ((pid = va_arg(args, pid_t *)) != NULL) {
-        if (*pid == -1)
+        if (*pid == NETATALK_SRV_ERROR || *pid == NETATALK_SRV_OPTIONAL)
             continue;
         kill(*pid, sig);
     }
@@ -279,7 +296,7 @@ static void netatalk_exit(int ret)
 /* this forks() and exec() "path" with varags as argc[] */
 static pid_t run_process(const char *path, ...)
 {
-    int ret, i = 0;
+    int i = 0;
 #define MYARVSIZE 64
     char *myargv[MYARVSIZE];
     va_list args;
@@ -299,7 +316,7 @@ static pid_t run_process(const char *path, ...)
         }
         va_end(args);
 
-        ret = execv(path, myargv);
+        (void)execv(path, myargv);
 
         /* Yikes! We're still here, so exec failed... */
         LOG(log_error, logtype_cnid, "Fatal error in exec: %s", strerror(errno));
@@ -358,12 +375,12 @@ int main(int argc, char **argv)
 
     LOG(log_note, logtype_default, "Netatalk AFP server starting");
 
-    if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
+    if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == NETATALK_SRV_ERROR) {
         LOG(log_error, logtype_afpd, "Error starting 'afpd'");
         netatalk_exit(EXITERR_CONF);
     }
 
-    if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
+    if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == NETATALK_SRV_ERROR) {
         LOG(log_error, logtype_afpd, "Error starting 'cnid_metad'");
         netatalk_exit(EXITERR_CONF);
     }
@@ -395,42 +412,42 @@ int main(int argc, char **argv)
     sigprocmask(SIG_SETMASK, &blocksigs, NULL);
 
 #ifdef HAVE_TRACKER
-    setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=" _PATH_STATEDIR "spotlight.ipc", 1);
-    setenv("XDG_DATA_HOME", _PATH_STATEDIR, 0);
-    setenv("XDG_CACHE_HOME", _PATH_STATEDIR, 0);
-    setenv("TRACKER_USE_LOG_FILES", "1", 0);
-
-    dbus_path = atalk_iniparser_getstring(obj.iniconfig, INISEC_GLOBAL, "dbus daemon", DBUS_DAEMON_PATH);
-    LOG(log_debug, logtype_default, "DBUS: '%s'", dbus_path);
-    if ((dbus_pid = run_process(dbus_path, "--config-file=" _PATH_CONFDIR "dbus-session.conf", NULL)) == -1) {
-        LOG(log_error, logtype_default, "Error starting '%s'", dbus_path);
-        netatalk_exit(EXITERR_CONF);
-    }
+    if (obj.options.flags & OPTION_SPOTLIGHT) {
+        setenv("DBUS_SESSION_BUS_ADDRESS", "unix:path=" _PATH_STATEDIR "spotlight.ipc", 1);
+        setenv("XDG_DATA_HOME", _PATH_STATEDIR, 0);
+        setenv("XDG_CACHE_HOME", _PATH_STATEDIR, 0);
+        setenv("TRACKER_USE_LOG_FILES", "1", 0);
+
+        if (atalk_iniparser_getboolean(obj.iniconfig, INISEC_GLOBAL, "start dbus", 1)) {
+            dbus_path = atalk_iniparser_getstring(obj.iniconfig, INISEC_GLOBAL, "dbus daemon", DBUS_DAEMON_PATH);
+            LOG(log_debug, logtype_default, "DBUS: '%s'", dbus_path);
+            if ((dbus_pid = run_process(dbus_path, "--config-file=" _PATH_CONFDIR "dbus-session.conf", NULL)) == NETATALK_SRV_ERROR) {
+                LOG(log_error, logtype_default, "Error starting '%s'", dbus_path);
+                netatalk_exit(EXITERR_CONF);
+            }
+
+            /* Allow dbus some time to start up */
+            sleep(1);
+        }
 
-    /* Allow dbus some time to start up */
-    sleep(1);
-#endif
+        set_sl_volumes();
 
-#ifdef HAVE_TRACKER_SPARQL
-#ifdef SOLARIS
-    setenv("XDG_DATA_DIRS", TRACKER_PREFIX "/share", 0);
-    setenv("TRACKER_DB_ONTOLOGIES_DIR", TRACKER_PREFIX "/share/tracker/ontologies", 0);
-    setenv("TRACKER_EXTRACTOR_RULES_DIR", TRACKER_PREFIX "/share/tracker/extract-rules", 0);
-    setenv("TRACKER_LANGUAGE_STOPWORDS_DIR", TRACKER_PREFIX "/share/tracker/languages", 0);
-#endif
-    set_sl_volumes();
-    system(TRACKER_PREFIX "/bin/tracker-control -s");
+        if (atalk_iniparser_getboolean(obj.iniconfig, INISEC_GLOBAL, "start tracker", 1)) {
+            system(TRACKER_PREFIX "/bin/tracker-control -s");
+        }
+    }
 #endif
 
+
     /* run the event loop */
     ret = event_base_dispatch(base);
 
-    if (afpd_pid != -1 || cnid_metad_pid != -1 || dbus_pid != -1) {
-        if (afpd_pid != -1)
+    if (service_running(afpd_pid) || service_running(cnid_metad_pid) || service_running(dbus_pid)) {
+        if (service_running(afpd_pid))
             LOG(log_error, logtype_afpd, "AFP service did not shutdown, killing it");
-        if (cnid_metad_pid != -1)
+        if (service_running(cnid_metad_pid))
             LOG(log_error, logtype_afpd, "CNID database service did not shutdown, killing it");
-        if (dbus_pid != -1)
+        if (service_running(dbus_pid))
             LOG(log_error, logtype_afpd, "DBUS session daemon still running, killing it");
         kill_childs(SIGKILL, &afpd_pid, &cnid_metad_pid, &dbus_pid, NULL);
     }
index 11b1dacf53449274b3eaea215f8105bc1745ff4c..21e8d382876dbfeb4082a886f7eb58e4a9ad6bbf 100644 (file)
@@ -34,7 +34,9 @@
 #define MAX_SL_RESULTS 20
 
 static TrackerSparqlConnection *connection;
+#if 0
 static TrackerMinerManager *manager;
+#endif
 
 static char *tracker_to_unix_path(const char *uri)
 {
@@ -57,7 +59,8 @@ static int sl_mod_init(void *p)
 {
     EC_INIT;
     GError *error = NULL;
-    const char *msg = p;
+    AFPObj *obj = (AFPObj *)p;
+    const char *attributes;
 
     LOG(log_info, logtype_sl, "Initializing Spotlight module");
 
@@ -73,7 +76,9 @@ static int sl_mod_init(void *p)
 
     become_root();
     connection = tracker_sparql_connection_get(NULL, &error);
+#if 0 /* this may hang, so disable it as we don't use the miner anyway  */
     manager = tracker_miner_manager_new_full(FALSE, &error);
+#endif
     unbecome_root();
 
     if (!connection) {
@@ -83,11 +88,18 @@ static int sl_mod_init(void *p)
         EC_FAIL;
     }
 
+#if 0
     if (!manager) {
         LOG(log_error, logtype_sl, "Couldn't connect to Tracker miner");
         g_clear_error(&error);
         EC_FAIL;
     }
+#endif
+
+    attributes = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "spotlight attributes", NULL);
+    if (attributes) {
+        configure_spotlight_attributes(attributes);
+    }
 
 EC_CLEANUP:
     EC_EXIT;
@@ -387,6 +399,7 @@ static int sl_mod_index_file(const void *p)
      */
     return 0;
 
+#if 0
 #ifdef HAVE_TRACKER_MINER
     EC_INIT;
     const char *f = p;
@@ -414,7 +427,8 @@ EC_CLEANUP:
     EC_EXIT;
 #else
     return 0;
-#endif
+#endif /* HAVE_TRACKER_MINER */
+#endif /* 0 */
 }
 
 struct sl_module_export sl_mod = {
index 49296d799bfd1cb17119fe46708df928ba4c3b4c..7ac4963cee46bf384fcc534f393ff2cfc04f4e1c 100644 (file)
 #endif /* HAVE_CONFIG_H */
 
 #include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <atalk/logger.h>
 
 #include "slmod_sparql_map.h"
 
 #define SPECIAL      NULL
 
 struct spotlight_sparql_map spotlight_sparql_map[] = {
-    /* ssm_spotlight_attr               ssm_type,   ssm_sparql_attr */
-    {"*",                               ssmt_fts,   "fts:match"},
+    /* ssm_spotlight_attr               ssm_enabled, ssm_type,   ssm_sparql_attr */
+    {"*",                               true, ssmt_fts,   "fts:match"},
 
     /* Filesystem metadata */
-    {"kMDItemFSLabel",                  ssmt_num,   NOTSUPPORTED},
-    {"kMDItemDisplayName",              ssmt_str,   "nfo:fileName"},
-    {"kMDItemFSName",                   ssmt_str,   "nfo:fileName"},
-    {"kMDItemFSContentChangeDate",      ssmt_date,  "nfo:fileLastModified"},
+    {"kMDItemFSLabel",                  true, ssmt_num,   NOTSUPPORTED},
+    {"kMDItemDisplayName",              true, ssmt_str,   "nfo:fileName"},
+    {"kMDItemFSName",                   true, ssmt_str,   "nfo:fileName"},
+    {"kMDItemFSContentChangeDate",      true, ssmt_date,  "nfo:fileLastModified"},
 
     /* Common metadata */
-    {"kMDItemTextContent",              ssmt_fts,   "fts:match"},
-    {"kMDItemContentCreationDate",      ssmt_date,  "nie:contentCreated"},
-    {"kMDItemContentModificationDate",  ssmt_date,  "nfo:fileLastModified"},
-    {"kMDItemAttributeChangeDate",      ssmt_date,  "nfo:fileLastModified"},
-    {"kMDItemAuthors",                  ssmt_str,   "dc:creator"},
-    {"kMDItemCopyright",                ssmt_str,   "nie:copyright"},
-    {"kMDItemCountry",                  ssmt_str,   "nco:country"},
-    {"kMDItemCreator",                  ssmt_str,   "dc:creator"},
-    {"kMDItemDurationSeconds",          ssmt_num,   "nfo:duration"},
-    {"kMDItemNumberOfPages",            ssmt_num,   "nfo:pageCount"},
-    {"kMDItemTitle",                    ssmt_str,   "nie:title"},
-    {"_kMDItemGroupId",                 ssmt_type,  SPECIAL},
-    {"kMDItemContentTypeTree",          ssmt_type,  SPECIAL},
+    {"kMDItemTextContent",              true, ssmt_fts,   "fts:match"},
+    {"kMDItemContentCreationDate",      true, ssmt_date,  "nie:contentCreated"},
+    {"kMDItemContentModificationDate",  true, ssmt_date,  "nfo:fileLastModified"},
+    {"kMDItemAttributeChangeDate",      true, ssmt_date,  "nfo:fileLastModified"},
+    {"kMDItemLastUsedDate",             true, ssmt_date,  "nfo:fileLastAccessed"},
+    {"kMDItemAuthors",                  true, ssmt_str,   "dc:creator"},
+    {"kMDItemCopyright",                true, ssmt_str,   "nie:copyright"},
+    {"kMDItemCountry",                  true, ssmt_str,   "nco:country"},
+    {"kMDItemCreator",                  true, ssmt_str,   "dc:creator"},
+    {"kMDItemDurationSeconds",          true, ssmt_num,   "nfo:duration"},
+    {"kMDItemNumberOfPages",            true, ssmt_num,   "nfo:pageCount"},
+    {"kMDItemTitle",                    true, ssmt_str,   "nie:title"},
+    {"_kMDItemGroupId",                 true, ssmt_type,  SPECIAL},
+    {"kMDItemContentTypeTree",          true, ssmt_type,  SPECIAL},
 
     /* Image metadata */
-    {"kMDItemPixelWidth",               ssmt_num,   "nfo:width"},
-    {"kMDItemPixelHeight",              ssmt_num,   "nfo:height"},
-    {"kMDItemColorSpace",               ssmt_str,   "nexif:colorSpace"},
-    {"kMDItemBitsPerSample",            ssmt_num,   "nfo:colorDepth"},
-    {"kMDItemFocalLength",              ssmt_num,   "nmm:focalLength"},
-    {"kMDItemISOSpeed",                 ssmt_num,   "nmm:isoSpeed"},
-    {"kMDItemOrientation",              ssmt_bool,  "nfo:orientation"},
-    {"kMDItemResolutionWidthDPI",       ssmt_num,   "nfo:horizontalResolution"},
-    {"kMDItemResolutionHeightDPI",      ssmt_num,   "nfo:verticalResolution"},
-    {"kMDItemExposureTimeSeconds",      ssmt_num,   "nmm:exposureTime"},
+    {"kMDItemPixelWidth",               true, ssmt_num,   "nfo:width"},
+    {"kMDItemPixelHeight",              true, ssmt_num,   "nfo:height"},
+    {"kMDItemColorSpace",               true, ssmt_str,   "nexif:colorSpace"},
+    {"kMDItemBitsPerSample",            true, ssmt_num,   "nfo:colorDepth"},
+    {"kMDItemFocalLength",              true, ssmt_num,   "nmm:focalLength"},
+    {"kMDItemISOSpeed",                 true, ssmt_num,   "nmm:isoSpeed"},
+    {"kMDItemOrientation",              true, ssmt_bool,  "nfo:orientation"},
+    {"kMDItemResolutionWidthDPI",       true, ssmt_num,   "nfo:horizontalResolution"},
+    {"kMDItemResolutionHeightDPI",      true, ssmt_num,   "nfo:verticalResolution"},
+    {"kMDItemExposureTimeSeconds",      true, ssmt_num,   "nmm:exposureTime"},
 
     /* Audio metadata */
-    {"kMDItemComposer",                 ssmt_str,   "nmm:composer"},
-    {"kMDItemMusicalGenre",             ssmt_str,   "nfo:genre"},
+    {"kMDItemComposer",                 true, ssmt_str,   "nmm:composer"},
+    {"kMDItemMusicalGenre",             true, ssmt_str,   "nfo:genre"},
 
-    {NULL, ssmt_str, NULL}
+    {NULL, false, ssmt_str, NULL}
 };
 
 struct MDTypeMap MDTypeMap[] = {
@@ -98,3 +103,34 @@ struct MDTypeMap MDTypeMap[] = {
     {"public.source-code",      kMDTypeMapRDF,      "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#SourceCode"},
     {NULL,                      kMDTypeMapNotSup,   NULL}
 };
+
+void configure_spotlight_attributes(const char *attributes_in)
+{
+    char *attr, *attributes;
+    int i;
+
+    for (i = 0; spotlight_sparql_map[i].ssm_spotlight_attr != NULL; i++)
+        spotlight_sparql_map[i].ssm_enabled = false;
+
+    /*
+     * Go through the attribute map and for every element scan
+     * attributes_in with strtok(). If it's contained, keep it
+     * enabled, otherwise disable it.
+     */
+
+    attributes = strdup(attributes_in);
+
+    for (attr = strtok(attributes, ","); attr; attr = strtok(NULL, ",")) {
+
+        for (i = 0; spotlight_sparql_map[i].ssm_spotlight_attr != NULL; i++)
+
+            if (strcmp(attr, spotlight_sparql_map[i].ssm_spotlight_attr) == 0) {
+                LOG(log_info, logtype_sl, "Enabling Spotlight attribute: %s",
+                    spotlight_sparql_map[i].ssm_spotlight_attr);
+                spotlight_sparql_map[i].ssm_enabled = true;
+                break;
+        }
+    }
+
+    free(attributes);
+}
index 250894b1094ad12e4c18ea028915f61199e5575b..3b9247408c9a41f0acedb8e79b35cb696700298f 100644 (file)
@@ -36,6 +36,7 @@ enum kMDTypeMap {
 
 struct spotlight_sparql_map {
     const char *ssm_spotlight_attr;
+    bool ssm_enabled;
     enum ssm_type ssm_type;
     const char *ssm_sparql_attr;
 };
index d4082fd248bbc8f72ef531f994ac747e5b350ca6..3d32af6219d386d9b093a8e6f07b3b3ea8b198dd 100644 (file)
   /* local vars */
   static gchar *ssp_result;
   static char sparqlvar;
+  static char *result_limit;
 
 /* Line 371 of yacc.c  */
-#line 106 "slmod_sparql_parser.c"
+#line 107 "slmod_sparql_parser.c"
 
 # ifndef YY_NULL
 #  if defined __cplusplus && 201103L <= __cplusplus
 
 /* In a future release of Bison, this section will be replaced
    by #include "y.tab.h".  */
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
+#ifndef YY_YY_SLMOD_SPARQL_PARSER_H_INCLUDED
+# define YY_YY_SLMOD_SPARQL_PARSER_H_INCLUDED
 /* Enabling traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 0
@@ -176,7 +177,7 @@ extern int yydebug;
 typedef union YYSTYPE
 {
 /* Line 387 of yacc.c  */
-#line 45 "slmod_sparql_parser.y"
+#line 46 "slmod_sparql_parser.y"
 
     int ival;
     const char *sval;
@@ -185,7 +186,7 @@ typedef union YYSTYPE
 
 
 /* Line 387 of yacc.c  */
-#line 189 "slmod_sparql_parser.c"
+#line 190 "slmod_sparql_parser.c"
 } YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
@@ -209,7 +210,7 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 /* "%code provides" blocks.  */
 /* Line 387 of yacc.c  */
-#line 39 "slmod_sparql_parser.y"
+#line 40 "slmod_sparql_parser.y"
 
   #define SPRAW_TIME_OFFSET 978307200
   extern int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result);
@@ -217,14 +218,14 @@ int yyparse ();
 
 
 /* Line 387 of yacc.c  */
-#line 221 "slmod_sparql_parser.c"
+#line 222 "slmod_sparql_parser.c"
 
-#endif /* !YY_YY_Y_TAB_H_INCLUDED  */
+#endif /* !YY_YY_SLMOD_SPARQL_PARSER_H_INCLUDED  */
 
 /* Copy the second part of user declarations.  */
 
 /* Line 390 of yacc.c  */
-#line 228 "slmod_sparql_parser.c"
+#line 229 "slmod_sparql_parser.c"
 
 #ifdef short
 # undef short
@@ -523,9 +524,9 @@ static const yytype_int8 yyrhs[] =
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint8 yyrline[] =
 {
-       0,    67,    67,    69,    73,    83,    89,    95,    96,    97,
-      98,    99,   108,   109,   110,   111,   112,   113,   114,   115,
-     119,   123,   124
+       0,    68,    68,    70,    74,    88,    94,   102,   103,   104,
+     105,   112,   125,   126,   127,   128,   129,   130,   131,   132,
+     136,   140,   141
 };
 #endif
 
@@ -1446,19 +1447,23 @@ yyreduce:
     {
         case 4:
 /* Line 1792 of yacc.c  */
-#line 73 "slmod_sparql_parser.y"
+#line 74 "slmod_sparql_parser.y"
     {
+    if (ssp_slq->slq_result_limit)
+        result_limit = talloc_asprintf(ssp_slq, "LIMIT %ld", ssp_slq->slq_result_limit);
+    else
+        result_limit = "";
     ssp_result = talloc_asprintf(ssp_slq,
-                                 "SELECT DISTINCT ?url WHERE "
-                                 "{ ?obj nie:url ?url FILTER(regex(?url, '^file://%s/')) . %s}",
-                                 ssp_slq->slq_vol->v_path, (yyvsp[(1) - (1)].sval));
+                                 "SELECT ?url WHERE "
+                                 "{ %s . ?obj nie:url ?url . FILTER(tracker:uri-is-descendant('file://%s/', ?url)) } %s",
+                                 (yyvsp[(1) - (1)].sval), ssp_slq->slq_vol->v_path, result_limit);
     (yyval.sval) = ssp_result;
 }
     break;
 
   case 5:
 /* Line 1792 of yacc.c  */
-#line 83 "slmod_sparql_parser.y"
+#line 88 "slmod_sparql_parser.y"
     {
     if ((yyvsp[(1) - (1)].bval) == false)
         YYACCEPT;
@@ -1469,8 +1474,10 @@ yyreduce:
 
   case 6:
 /* Line 1792 of yacc.c  */
-#line 89 "slmod_sparql_parser.y"
+#line 94 "slmod_sparql_parser.y"
     {
+    if ((yyvsp[(1) - (3)].sval) == NULL || (yyvsp[(3) - (3)].sval) == NULL)
+        YYABORT;
     if (strcmp((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)) != 0)
         (yyval.sval) = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", (yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval));
     else
@@ -1480,32 +1487,42 @@ yyreduce:
 
   case 7:
 /* Line 1792 of yacc.c  */
-#line 95 "slmod_sparql_parser.y"
+#line 102 "slmod_sparql_parser.y"
     {(yyval.sval) = (yyvsp[(1) - (1)].sval); if ((yyval.sval) == NULL) YYABORT;}
     break;
 
   case 8:
 /* Line 1792 of yacc.c  */
-#line 96 "slmod_sparql_parser.y"
+#line 103 "slmod_sparql_parser.y"
     {(yyval.sval) = (yyvsp[(1) - (1)].sval);}
     break;
 
   case 9:
 /* Line 1792 of yacc.c  */
-#line 97 "slmod_sparql_parser.y"
+#line 104 "slmod_sparql_parser.y"
     {(yyval.sval) = talloc_asprintf(ssp_slq, "%s", (yyvsp[(2) - (3)].sval));}
     break;
 
   case 10:
 /* Line 1792 of yacc.c  */
-#line 98 "slmod_sparql_parser.y"
-    {(yyval.sval) = talloc_asprintf(ssp_slq, "%s . %s", (yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval));}
+#line 105 "slmod_sparql_parser.y"
+    {
+    if (!ssp_slq->slq_allow_expr) {
+        yyerror("Spotlight queries with logic expressions are disabled");
+        YYABORT;
+    }
+    (yyval.sval) = talloc_asprintf(ssp_slq, "%s . %s", (yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval));
+}
     break;
 
   case 11:
 /* Line 1792 of yacc.c  */
-#line 99 "slmod_sparql_parser.y"
+#line 112 "slmod_sparql_parser.y"
     {
+    if (!ssp_slq->slq_allow_expr) {
+        yyerror("Spotlight queries with logic expressions are disabled");
+        YYABORT;
+    }
     if (strcmp((yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval)) != 0)
         (yyval.sval) = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", (yyvsp[(1) - (3)].sval), (yyvsp[(3) - (3)].sval));
     else
@@ -1515,73 +1532,73 @@ yyreduce:
 
   case 12:
 /* Line 1792 of yacc.c  */
-#line 108 "slmod_sparql_parser.y"
+#line 125 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '=', (yyvsp[(4) - (5)].sval));}
     break;
 
   case 13:
 /* Line 1792 of yacc.c  */
-#line 109 "slmod_sparql_parser.y"
+#line 126 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '!', (yyvsp[(4) - (5)].sval));}
     break;
 
   case 14:
 /* Line 1792 of yacc.c  */
-#line 110 "slmod_sparql_parser.y"
+#line 127 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '<', (yyvsp[(4) - (5)].sval));}
     break;
 
   case 15:
 /* Line 1792 of yacc.c  */
-#line 111 "slmod_sparql_parser.y"
+#line 128 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (5)].sval), '>', (yyvsp[(4) - (5)].sval));}
     break;
 
   case 16:
 /* Line 1792 of yacc.c  */
-#line 112 "slmod_sparql_parser.y"
+#line 129 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '=', (yyvsp[(4) - (6)].sval));}
     break;
 
   case 17:
 /* Line 1792 of yacc.c  */
-#line 113 "slmod_sparql_parser.y"
+#line 130 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '!', (yyvsp[(4) - (6)].sval));}
     break;
 
   case 18:
 /* Line 1792 of yacc.c  */
-#line 114 "slmod_sparql_parser.y"
+#line 131 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '<', (yyvsp[(4) - (6)].sval));}
     break;
 
   case 19:
 /* Line 1792 of yacc.c  */
-#line 115 "slmod_sparql_parser.y"
+#line 132 "slmod_sparql_parser.y"
     {(yyval.sval) = map_expr((yyvsp[(1) - (6)].sval), '>', (yyvsp[(4) - (6)].sval));}
     break;
 
   case 20:
 /* Line 1792 of yacc.c  */
-#line 119 "slmod_sparql_parser.y"
+#line 136 "slmod_sparql_parser.y"
     {(yyval.sval) = map_daterange((yyvsp[(3) - (8)].sval), (yyvsp[(5) - (8)].tval), (yyvsp[(7) - (8)].tval));}
     break;
 
   case 21:
 /* Line 1792 of yacc.c  */
-#line 123 "slmod_sparql_parser.y"
+#line 140 "slmod_sparql_parser.y"
     {(yyval.tval) = isodate2unix((yyvsp[(3) - (4)].sval));}
     break;
 
   case 22:
 /* Line 1792 of yacc.c  */
-#line 124 "slmod_sparql_parser.y"
+#line 141 "slmod_sparql_parser.y"
     {(yyval.tval) = atoi((yyvsp[(1) - (1)].sval)) + SPRAW_TIME_OFFSET;}
     break;
 
 
 /* Line 1792 of yacc.c  */
-#line 1585 "slmod_sparql_parser.c"
+#line 1602 "slmod_sparql_parser.c"
       default: break;
     }
   /* User semantic actions sometimes alter yychar, and that requires
@@ -1813,7 +1830,7 @@ yyreturn:
 
 
 /* Line 2055 of yacc.c  */
-#line 127 "slmod_sparql_parser.y"
+#line 144 "slmod_sparql_parser.y"
 
 
 static time_t isodate2unix(const char *s)
@@ -1896,7 +1913,7 @@ static const char *map_expr(const char *attr, char op, const char *val)
     bstring q = NULL, search = NULL, replace = NULL;
 
     for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) {
-        if (strcmp(p->ssm_spotlight_attr, attr) == 0) {
+        if (p->ssm_enabled && (strcmp(p->ssm_spotlight_attr, attr) == 0)) {
             if (p->ssm_type != ssmt_type && p->ssm_sparql_attr == NULL) {
                 yyerror("unsupported Spotlight attribute");
                 EC_FAIL;
@@ -2021,6 +2038,7 @@ int main(int argc, char **argv)
     struct vol *vol = talloc_zero(ssp_slq, struct vol);
     vol->v_path = "/Volumes/test";
     ssp_slq->slq_vol = vol;
+    ssp_slq->slq_allow_expr = true;
     sparqlvar = 'a';
 
     s = yy_scan_string(argv[1]);
index 985d4cbe26fcfbd870c8f128b97ef7de773fcf98..9eb22b37f672b254a60208ce3bbfccb8b26a3437 100644 (file)
@@ -30,8 +30,8 @@
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
-#ifndef YY_YY_Y_TAB_H_INCLUDED
-# define YY_YY_Y_TAB_H_INCLUDED
+#ifndef YY_YY_SLMOD_SPARQL_PARSER_H_INCLUDED
+# define YY_YY_SLMOD_SPARQL_PARSER_H_INCLUDED
 /* Enabling traces.  */
 #ifndef YYDEBUG
 # define YYDEBUG 0
@@ -84,7 +84,7 @@ extern int yydebug;
 typedef union YYSTYPE
 {
 /* Line 2058 of yacc.c  */
-#line 45 "slmod_sparql_parser.y"
+#line 46 "slmod_sparql_parser.y"
 
     int ival;
     const char *sval;
@@ -117,7 +117,7 @@ int yyparse ();
 #endif /* ! YYPARSE_PARAM */
 /* "%code provides" blocks.  */
 /* Line 2058 of yacc.c  */
-#line 39 "slmod_sparql_parser.y"
+#line 40 "slmod_sparql_parser.y"
 
   #define SPRAW_TIME_OFFSET 978307200
   extern int map_spotlight_to_sparql_query(slq_t *slq, gchar **sparql_result);
@@ -127,4 +127,4 @@ int yyparse ();
 /* Line 2058 of yacc.c  */
 #line 129 "slmod_sparql_parser.h"
 
-#endif /* !YY_YY_Y_TAB_H_INCLUDED  */
+#endif /* !YY_YY_SLMOD_SPARQL_PARSER_H_INCLUDED  */
index 68d3d1013afd36fe2ed625ba1d764b737a4e1ed7..76d8b5a768d5b668c72f093b1adf1ebfb3f8dda9 100644 (file)
@@ -34,6 +34,7 @@
   /* local vars */
   static gchar *ssp_result;
   static char sparqlvar;
+  static char *result_limit;
 %}
 
 %code provides {
@@ -71,10 +72,14 @@ input:
      
 line:
 expr                           {
+    if (ssp_slq->slq_result_limit)
+        result_limit = talloc_asprintf(ssp_slq, "LIMIT %ld", ssp_slq->slq_result_limit);
+    else
+        result_limit = "";
     ssp_result = talloc_asprintf(ssp_slq,
-                                 "SELECT DISTINCT ?url WHERE "
-                                 "{ ?obj nie:url ?url FILTER(regex(?url, '^file://%s/')) . %s}",
-                                 ssp_slq->slq_vol->v_path, $1);
+                                 "SELECT ?url WHERE "
+                                 "{ %s . ?obj nie:url ?url . FILTER(tracker:uri-is-descendant('file://%s/', ?url)) } %s",
+                                 $1, ssp_slq->slq_vol->v_path, result_limit);
     $$ = ssp_result;
 }
 ;
@@ -87,6 +92,8 @@ BOOL                             {
         YYABORT;
 }
 | match OR match                 {
+    if ($1 == NULL || $3 == NULL)
+        YYABORT;
     if (strcmp($1, $3) != 0)
         $$ = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", $1, $3);
     else
@@ -95,8 +102,18 @@ BOOL                             {
 | match                        {$$ = $1; if ($$ == NULL) YYABORT;}
 | function                     {$$ = $1;}
 | OBRACE expr CBRACE           {$$ = talloc_asprintf(ssp_slq, "%s", $2);}
-| expr AND expr                {$$ = talloc_asprintf(ssp_slq, "%s . %s", $1, $3);}
+| expr AND expr                {
+    if (!ssp_slq->slq_allow_expr) {
+        yyerror("Spotlight queries with logic expressions are disabled");
+        YYABORT;
+    }
+    $$ = talloc_asprintf(ssp_slq, "%s . %s", $1, $3);
+}
 | expr OR expr                 {
+    if (!ssp_slq->slq_allow_expr) {
+        yyerror("Spotlight queries with logic expressions are disabled");
+        YYABORT;
+    }
     if (strcmp($1, $3) != 0)
         $$ = talloc_asprintf(ssp_slq, "{ %s } UNION { %s }", $1, $3);
     else
@@ -206,7 +223,7 @@ static const char *map_expr(const char *attr, char op, const char *val)
     bstring q = NULL, search = NULL, replace = NULL;
 
     for (p = spotlight_sparql_map; p->ssm_spotlight_attr; p++) {
-        if (strcmp(p->ssm_spotlight_attr, attr) == 0) {
+        if (p->ssm_enabled && (strcmp(p->ssm_spotlight_attr, attr) == 0)) {
             if (p->ssm_type != ssmt_type && p->ssm_sparql_attr == NULL) {
                 yyerror("unsupported Spotlight attribute");
                 EC_FAIL;
@@ -331,6 +348,7 @@ int main(int argc, char **argv)
     struct vol *vol = talloc_zero(ssp_slq, struct vol);
     vol->v_path = "/Volumes/test";
     ssp_slq->slq_vol = vol;
+    ssp_slq->slq_allow_expr = true;
     sparqlvar = 'a';
 
     s = yy_scan_string(argv[1]);
index e639cfa6ac12b27053ba96901bcb3429b6d86e30..c7343a9e735f37878cc0b6e89dbc43fc258b4b4b 100644 (file)
@@ -22,6 +22,7 @@
 #ifdef HAVE_ACLS
 
 #define O_NETATALK_ACL (O_NOFOLLOW << 1)
+#define O_IGNORE (O_NOFOLLOW << 2)
 
 #ifdef HAVE_SOLARIS_ACLS
 #include <sys/acl.h>
index 1881ba028240c0ff5f74edbd162e3d3083e6e5ae..40c92a11af01e046ceba97e59e15c3f1f0f1da9e 100644 (file)
@@ -249,6 +249,7 @@ struct adouble {
 #define ADVOL_UNIXPRIV   (1 << 2) /* adouble unix priv */
 #define ADVOL_INVDOTS    (1 << 3) /* dot files (.DS_Store) are invisible) */
 #define ADVOL_FOLLO_SYML (1 << 4)
+#define ADVOL_FORCE_STICKY_XATTR (1 << 5)
 
 /* lock flags */
 #define ADLOCK_CLR      (0)
@@ -348,6 +349,12 @@ struct adouble {
 #define AD_AFPFILEI_GROUP       (1 << 1) /* ignore group */
 #define AD_AFPFILEI_BLANKACCESS (1 << 2) /* blank access permissions */
 
+/*
+ * String identifiers for the 16 AppleDouble filler bytes
+ */
+#define AD_FILLER_NETATALK "Netatalk        "
+#define AD_FILLER_OSX      "Mac OS X"
+
 #define ad_data_fileno(ad)  ((ad)->ad_data_fork.adf_fd)
 #define ad_reso_fileno(ad)  ((ad)->ad_rfp->adf_fd)
 #define ad_meta_fileno(ad)  ((ad)->ad_mdp->adf_fd)
index 9c8e0bacd065a69afb363b499ee78024c41f26f3..4fefcd0439a0b902ef6548fdc9f3143629e77429 100644 (file)
 /*
  * This is instance of CNID database object.
  */
-struct _cnid_db {
-    uint32_t flags;             /* Flags describing some CNID backend aspects. */
-    char *volpath;               /* Volume path this particular CNID db refers to. */
-    void *_private;              /* back-end speficic data */
+typedef struct _cnid_db {
+    uint32_t      cnid_db_flags;     /* Flags describing some CNID backend aspects. */
+    struct vol   *cnid_db_vol;
+    void         *cnid_db_private;   /* back-end speficic data */
 
     cnid_t (*cnid_add)         (struct _cnid_db *cdb, const struct stat *st, cnid_t did,
                                 const char *name, size_t, cnid_t hint);
@@ -71,25 +71,15 @@ struct _cnid_db {
     int    (*cnid_find)        (struct _cnid_db *cdb, const char *name, size_t namelen,
                                 void *buffer, size_t buflen);
     int    (*cnid_wipe)        (struct _cnid_db *cdb);
-};
-typedef struct _cnid_db cnid_db;
+} cnid_db;
 
 /*
  * Consolidation of args passedn from main cnid_open to modules cnid_XXX_open, so
  * that it's easier to add aditional args as required.
  */
 struct cnid_open_args {
-    const char *dir;
-    mode_t mask;
-    uint32_t flags;
-
-    /* for dbd */
-    const char *cnidserver;
-    const char *cnidport;
-
-    /* for MySQL */
-    const void *obj;
-    char *voluuid;
+    uint32_t cnid_args_flags;
+    struct vol *cnid_args_vol;
 };
 
 /*
@@ -111,14 +101,7 @@ void cnid_init();
 void cnid_register(struct _cnid_module *module);
 
 /* This function opens a CNID database for selected volume. */
-struct _cnid_db *cnid_open(const char *volpath,
-                           mode_t mask,
-                           char *type,
-                           int flags,
-                           const char *cnidsrv,
-                           const char *cnidport,
-                           const void *obj,
-                           char *uuid);
+struct _cnid_db *cnid_open(struct vol *vol, char *type, int flags);
 cnid_t cnid_add        (struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
                         const char *name, const size_t len, cnid_t hint);
 int    cnid_delete     (struct _cnid_db *cdb, cnid_t id);
index 8aab3e059e8545698dd0bd345fce59fdfa9f1aa3..f87eddd0f2a850d9b77f8783f109da06c528e40c 100644 (file)
@@ -36,6 +36,7 @@
 #define CNID_DBD_RES_SRCH_DONE     0x06
 
 #define DBD_MAX_SRCH_RSLTS 100
+#define DBD_NUM_OPEN_ARGS 3
 
 struct cnid_dbd_rqst {
     int     op;
@@ -57,10 +58,7 @@ struct cnid_dbd_rply {
 };
 
 typedef struct CNID_bdb_private {
-    uint32_t magic;
-    char      db_dir[MAXPATHLEN + 1]; /* Database directory without /.AppleDB appended */
-    char      *cnidserver;
-    char      *cnidport;
+    struct vol *vol;
     int       fd;              /* File descriptor to cnid_dbd */
     char      stamp[ADEDLEN_PRIVSYN]; /* db timestamp */
     char      *client_stamp;
index 6affaf7a15aae1ba9f87f79bee918dbe616fecce..79a54e8a0a3c92bbaf64b329f47a02398e819ea7 100644 (file)
@@ -7,12 +7,9 @@
 #define CNID_MYSQL_FLAG_DEPLETED (1 << 0) /* CNID set overflowed */
 
 typedef struct CNID_mysql_private {
+    struct vol *vol;
     uint32_t      cnid_mysql_flags;
-    uint32_t      cnid_mysql_magic;
-    char         *cnid_mysql_volname;
-    const void   *cnid_mysql_obj;
     MYSQL        *cnid_mysql_con;
-    atalk_uuid_t  cnid_mysql_voluuid;
     char         *cnid_mysql_voluuid_str;
     cnid_t        cnid_mysql_hint;
     MYSQL_STMT   *cnid_lookup_stmt;
index f5f825faa362f806e124cf3e0e32280166756a9c..c030ff99f404b2d99d09ef8d11b0a6d887c6e358 100644 (file)
@@ -5,9 +5,6 @@
 #ifndef _ATALK_CNID_PRIVATE_H
 #define _ATALK_CNID_PRIVATE_H 1
 
-#define CNID_DB_MAGIC   0x434E4944U  /* CNID */
-#define CNID_DATA_MAGIC 0x434E4945U  /* CNIE */
-
 #define CNID_OFS                 0
 #define CNID_LEN                 4
  
index d11a2d4927a4752da0593fb3e54c2acc976cf57e..c804d900bc08b46641c18b357668ae5871405975 100755 (executable)
 
 #include <atalk/globals.h>
 
+#define FCE_PACKET_VERSION  2
+
 /* fce_packet.mode */
 #define FCE_FILE_MODIFY     1
 #define FCE_FILE_DELETE     2
 #define FCE_DIR_DELETE      3
 #define FCE_FILE_CREATE     4
 #define FCE_DIR_CREATE      5
+#define FCE_FILE_MOVE       6
+#define FCE_DIR_MOVE        7
+#define FCE_LOGIN           8
+#define FCE_LOGOUT          9
 #define FCE_CONN_START     42
 #define FCE_CONN_BROKEN    99
 
 #define FCE_FIRST_EVENT     FCE_FILE_MODIFY /* keep in sync with last file event above */
-#define FCE_LAST_EVENT      FCE_DIR_CREATE  /* keep in sync with last file event above */
+#define FCE_LAST_EVENT      FCE_LOGOUT      /* keep in sync with last file event above */
 
 /* fce_packet.fce_magic */
 #define FCE_PACKET_MAGIC  "at_fcapi"
 
-/* This packet goes over the network, so we want to
- * be shure about datastructs and type sizes between platforms.
- * Format is network byte order.
+/* flags for "fce_ev_info" of additional info to send in events */
+#define FCE_EV_INFO_PID     (1 << 0)
+#define FCE_EV_INFO_USER    (1 << 1)
+#define FCE_EV_INFO_SRCPATH (1 << 2)
+
+/*
+ * Network payload of an FCE packet, version 1
+ *
+ *      1         2         3         4         5         6         7          8
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * |                                   FCE magic                                     |
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * | version |
+ * +---------+
+ * |  event  |
+ * +---------+-----------------------------+
+ * |               event ID                |
+ * +-------------------+-------------------+ . . . .
+ * |     pathlen       | path
+ * +-------------------+------ . . . . . . . . . . .
+ *
+ *
+ * Network payload of an FCE packet, version 2
+ *
+ *      1         2         3         4         5         6         7          8
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * |                                   FCE magic                                     |
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * | version |
+ * +---------+
+ * | options |
+ * +---------+
+ * |  event  |
+ * +---------+
+ * | padding |
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * |                                    reserved                                     |
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * |               event ID                |
+ * +---------+---------+---------+---------+
+ * ... optional:
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * |                                      pid                                        |
+ * +---------+---------+---------+---------+---------+---------+----------+----------+
+ * ...
+ * ... optional:
+ * +-------------------+----------  . . . .
+ * |  username length  | username
+ * +-------------------+----------  . . . .
+ * ...
+ * +-------------------+------  . . . . . .
+ * |     pathlen       | path
+ * +-------------------+------  . . . . . .
+ * ... optional:
+ * +-------------------+------------- . . .
+ * |     pathlen       | source path
+ * +-------------------+------------- . . .
+ *
+ * version      = 2
+ * options      = bitfield:
+ *                    0: pid present
+ *                    1: username present
+ *                    2: source path present
+ * pid          = optional pid
+ * username     = optional username
+ * source path  = optional source path
  */
-#define FCE_PACKET_HEADER_SIZE 8+1+1+4+2
-
-struct fce_packet
-{
-    char magic[8];
-    unsigned char version;
-    unsigned char mode;
-    uint32_t event_id;
-    uint16_t datalen;
-    char data[MAXPATHLEN];
+
+struct fce_packet {
+    char          fcep_magic[8];
+    unsigned char fcep_version;
+    unsigned char fcep_options;
+    unsigned char fcep_event;
+    uint32_t      fcep_event_id;
+    uint64_t      fcep_pid;
+    uint16_t      fcep_userlen;
+    char          fcep_user[MAXPATHLEN];
+    uint16_t      fcep_pathlen1;
+    char          fcep_path1[MAXPATHLEN];
+    uint16_t      fcep_pathlen2;
+    char          fcep_path2[MAXPATHLEN];
 };
 
 typedef uint32_t fce_ev_t;
-typedef enum { fce_file, fce_dir } fce_obj_t;
 
 struct path;
 struct ofork;
 
-void fce_pending_events(AFPObj *obj);
-int fce_register(fce_ev_t event, const char *path, const char *oldpath, fce_obj_t type);
+void fce_pending_events(const AFPObj *obj);
+int fce_register(const AFPObj *obj, fce_ev_t event, const char *path, const char *oldpath);
 int fce_add_udp_socket(const char *target );  // IP or IP:Port
 int fce_set_coalesce(const char *coalesce_opt ); // all|delete|create
 int fce_set_events(const char *events);     /* fmod,fdel,ddel,fcre,dcre */
index 21b8b4e82ae842fb84282e9ef6bae10661f2b67e..ed450520f28d072f15a3bce4fc84fe371a33a285 100644 (file)
@@ -60,6 +60,7 @@
 #define OPTION_SPOTLIGHT     (1 << 13) /* whether to initialize Spotlight support */
 #define OPTION_SPOTLIGHT_VOL (1 << 14) /* whether spotlight shall be enabled by default for volumes */
 #define OPTION_RECVFILE      (1 << 15)
+#define OPTION_SPOTLIGHT_EXPR (1 << 16) /* whether to allow Spotlight logic expressions */
 
 #define PASSWD_NONE     0
 #define PASSWD_SET     (1 << 0)
@@ -130,6 +131,7 @@ struct afp_options {
     char *cnid_mysql_pw;
     char *cnid_mysql_db;
     struct afp_volume_name volfile;
+    uint64_t sparql_limit;
 };
 
 typedef struct AFPObj {
@@ -155,6 +157,9 @@ typedef struct AFPObj {
     void (*exit)(int);
     int (*reply)(void *, int);
     int (*attention)(void *, AFPUserBytes);
+    int fce_version;
+    char *fce_ign_names;
+    char *fce_notify_script;
 } AFPObj;
 
 /* typedef for AFP functions handlers */
index 0ca8a24edd44467d6245c1863d32f65247992114..bafa52f53b83d9a88f714a0c5dddb8ffa3125992 100644 (file)
@@ -43,7 +43,7 @@ struct sl_module_export {
     int (*sl_mod_index_file)  (const void *);
 };
 
-extern int sl_mod_load(const char *path);
+extern int sl_mod_load(AFPObj *obj);
 extern void sl_index_file(const char *path);
 
 /**************************************************************************************************
@@ -105,6 +105,8 @@ typedef struct _slq_t {
     size_t            slq_cnids_num;      /* Size of slq_cnids array                                        */
     const char       *slq_path;           /* Path to file or dir, used in fetchAttributes                   */
     void             *slq_tracker_cursor; /* Tracker SPARQL query result cursor                             */
+    bool              slq_allow_expr;     /* Whether to allow logic expressions                             */
+    uint64_t          slq_result_limit;   /* Whether to LIMIT SPARQL results, default of 0 means no limit   */
 } slq_t;
 
 /**************************************************************************************************
@@ -114,5 +116,6 @@ typedef struct _slq_t {
 extern int afp_spotlight_rpc(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen);
 extern int sl_pack(DALLOC_CTX *query, char *buf);
 extern int sl_unpack(DALLOC_CTX *query, const char *buf);
+extern void configure_spotlight_attributes(const char *attributes);
 
 #endif /* SPOTLIGHT_H */
index 38e1e7b2dd4f36a115c4ca2a73ba5b0d8b60d326..6d92e15d3815d1270f212dcbd112863e69526fb6 100644 (file)
@@ -16,6 +16,7 @@
 #include <unistd.h>
 #include <poll.h>
 #include <sys/stat.h>
+#include <stdbool.h>
 
 #include <atalk/unicode.h>
 #include <atalk/bstrlib.h>
 #define ntoh64(x)       (hton64(x))
 #endif
 
+#ifndef SAFE_FREE
+#define SAFE_FREE(x) do { if ((x) != NULL) {free(x); x=NULL;} } while(0)
+#endif
+
 #ifdef WITH_SENDFILE
 extern ssize_t sys_sendfile (int __out_fd, int __in_fd, off_t *__offset,size_t __count);
 #endif
@@ -152,26 +157,32 @@ extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2);
 extern int tokenize_ip_port(const char *ipurl, char **address, char **port);
 
 /* Structures and functions dealing with dynamic pollfd arrays */
-enum fdtype {IPC_FD, LISTEN_FD};
-struct polldata {
-    enum fdtype fdtype; /* IPC fd or listening socket fd                 */
-    void *data;         /* pointer to AFPconfig for listening socket and *
-                         * pointer to afp_child_t for IPC fd             */
+
+enum asev_fdtype {IPC_FD, LISTEN_FD};
+
+/**
+ * atalk socket event data
+ **/
+struct asev_data {
+    enum asev_fdtype fdtype;  /* IPC fd or listening socket fd                 */
+    void            *private; /* pointer to AFPconfig for listening socket and *
+                               * pointer to afp_child_t for IPC fd             */
 };
 
-extern void fdset_add_fd(int maxconns,
-                         struct pollfd **fdsetp,
-                         struct polldata **polldatap,
-                         int *fdset_usedp,
-                         int *fdset_sizep,
-                         int fd,
-                         enum fdtype fdtype,
-                         void *data);
-extern void fdset_del_fd(struct pollfd **fdsetp,
-                         struct polldata **polldatap,
-                         int *fdset_usedp,
-                         int *fdset_sizep,
-                         int fd);
+/**
+ * atalk socket event
+ **/
+struct asev {
+    struct pollfd         *fdset; /* struct pollfd array for poll() */
+    struct asev_data      *data;  /* associated array of data       */
+    int                    max;
+    int                    used;
+};
+
+extern struct asev *asev_init(int max);
+extern bool asev_add_fd(struct asev *sev, int fd, enum asev_fdtype fdtype, void *private);
+extern bool asev_del_fd(struct asev *sev, int fd);
+
 extern int send_fd(int socket, int fd);
 extern int recv_fd(int fd, int nonblocking);
 
index e2728908a5010a6ffe388a62c0cecd4ea1d64679..ad8be2b8421ff98a384a907b45145e3a6c0cc298 100644 (file)
@@ -113,13 +113,12 @@ typedef enum {lv_none = 0, lv_all = 1} lv_flags_t;
 #define AFPVOL_USTATFS  (1<<3)
 #define AFPVOL_UQUOTA   (1<<4)
 
-/*
-  Flags that alter volume behaviour.
-  Keep in sync with libatalk/util/volinfo.c
-*/
 #define AFPVOL_NOV2TOEACONV (1 << 5) /* no adouble:v2 to adouble:ea conversion */
 #define AFPVOL_SPOTLIGHT (1 << 6)   /* Index volume for Spotlight searches */
 #define AFPVOL_RO        (1 << 8)   /* read-only volume */
+#define AFPVOL_CHMOD_PRESERVE_ACL (1 << 9) /* try to preserve ACLs */
+#define AFPVOL_CHMOD_IGNORE (1 << 10) /* try to preserve ACLs */
+#define AFPVOL_FORCE_STICKY_XATTR (1 << 11) /* write metadata xattr as root on sticky dirs */
 #define AFPVOL_NOSTAT    (1 << 16)  /* advertise the volume even if we can't stat() it
                                      * maybe because it will be mounted later in preexec */
 #define AFPVOL_UNIX_PRIV (1 << 17)  /* support unix privileges */
@@ -195,5 +194,7 @@ typedef enum {lv_none = 0, lv_all = 1} lv_flags_t;
 #define vol_unix_priv(vol) ((vol)->v_obj->afp_version >= 30 && ((vol)->v_flags & AFPVOL_UNIX_PRIV))
 #define vol_inv_dots(vol) (((vol)->v_flags & AFPVOL_INV_DOTS) ? 1 : 0)
 #define vol_syml_opt(vol) (((vol)->v_flags & AFPVOL_FOLLOWSYM) ? 0 : O_NOFOLLOW)
+#define vol_chmod_opt(vol) (((vol)->v_flags & AFPVOL_CHMOD_PRESERVE_ACL) ? O_NETATALK_ACL : \
+                            ((vol)->v_flags & AFPVOL_CHMOD_IGNORE) ? O_IGNORE : 0)
 
 #endif
index 118b0c883c85e80b9a6e4fb0ce71b4a6a158cc53..af0d8262dcd229445d0b1a068328942b83667e8a 100644 (file)
@@ -18,7 +18,7 @@
 #        current+1:0:0
 #
 
-VERSION_INFO = 12:0:0
+VERSION_INFO = 16:0:0
 
 # History:          VERSION_INFO
 #
@@ -36,6 +36,10 @@ VERSION_INFO = 12:0:0
 #   3.0.6           7:0:0
 
 #   3.1.0           12:0:0
+#   3.1.1           13:0:0
+#   3.1.2           14:0:0
+#   3.1.3           15:0:0
+#   3.1.4           16:0:0
 
 SUBDIRS = acl adouble bstring compat cnid dsi iniparser talloc util unicode vfs
 
@@ -111,4 +115,8 @@ EXTRA_DIST = \
        libatalk-3.0.4.abi \
        libatalk-3.0.5.abi \
        libatalk-3.0.6.abi \
-       libatalk-3.1.0.abi
+       libatalk-3.1.0.abi \
+       libatalk-3.1.1.abi \
+       libatalk-3.1.2.abi \
+       libatalk-3.1.3.abi \
+       libatalk-3.1.4.abi
index 2a75ec62b576bb25a6ade1a269cee52db5c98bba..43f4332baab3e4fe2a4ed464e62e2998fe2ff95d 100644 (file)
@@ -152,7 +152,7 @@ static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struc
         EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
 
         /* Create a adouble:ea resource fork */
-        EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) );
+        EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_RF|ADFLAGS_RDWR|ADFLAGS_CREATE|ADFLAGS_SETSHRMD, 0666) );
 
         EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) );
         adea.ad_rlen = adv2.ad_rlen;
index 76d44a98051a6820fc3c666491efec9beab499bb..f049876dca0d498a4175e5c912e2d1aaf533c7d6 100644 (file)
@@ -164,7 +164,7 @@ int ad_rebuild_adouble_header_osx(struct adouble *ad, char *adbuf)
     memcpy(buf, &temp, sizeof( temp ));
     buf += sizeof( temp );
 
-    memcpy(buf, "Netatalk        ", 16);
+    memcpy(buf, AD_FILLER_NETATALK, strlen(AD_FILLER_NETATALK));
     buf += sizeof( ad->ad_filler );
 
     nent = htons(ADEID_NUM_OSX);
@@ -217,15 +217,12 @@ int ad_copy_header(struct adouble *add, struct adouble *ads)
             continue;
 
         len = ads->ad_eid[ eid ].ade_len;
-        if (!len || len != add->ad_eid[ eid ].ade_len)
+        if (len == 0)
             continue;
 
         switch (eid) {
         case ADEID_COMMENT:
-        case ADEID_PRIVDEV:
-        case ADEID_PRIVINO:
-        case ADEID_PRIVSYN:
-        case ADEID_PRIVID:
+        case ADEID_RFORK:
             continue;
         default:
             ad_setentrylen( add, eid, len );
@@ -289,8 +286,33 @@ static int ad_flush_hf(struct adouble *ad)
                 if (ad->ad_adflags & ADFLAGS_DIR) {
                     EC_NEG1_LOG( cwd = open(".", O_RDONLY) );
                     EC_NEG1_LOG( fchdir(ad_data_fileno(ad)) );
-                    EC_ZERO_LOGSTR( sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0),
-                                    "sys_lsetxattr(\"%s\"): %s", fullpathname(".") ,strerror(errno));
+
+                    ret = sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0);
+
+                    if (ret != 0) {
+                        if (errno != EPERM)
+                            EC_FAIL;
+
+                        if (!(ad->ad_options & ADVOL_FORCE_STICKY_XATTR))
+                            EC_FAIL;
+
+                        /*
+                         * This may be a directory with a sticky bit
+                         * set, which means even though we may have
+                         * write access to the directory, only the
+                         * owner is allowed to write xattrs
+                         */
+
+                        become_root();
+                        ret = sys_lsetxattr(".", AD_EA_META, ad->ad_data, AD_DATASZ_EA, 0);
+                        unbecome_root();
+
+                        if (ret != 0) {
+                            LOG(log_error, logtype_ad, "ad_flush_hf: %s", strerror(errno));
+                            EC_FAIL;
+                        }
+                    }
+
                     EC_NEG1_LOG( fchdir(cwd) );
                     EC_NEG1_LOG( close(cwd) );
                     cwd = -1;
@@ -429,6 +451,17 @@ int ad_close(struct adouble *ad, int adflags)
     }
 
     if (adflags & ADFLAGS_RF) {
+        /* HF is automatically opened when opening an RF, close it. */
+        if ((ad->ad_vers == AD_VERSION2) && (ad_meta_fileno(ad) != -1)) {
+            if (ad->ad_meta_refcount)
+                ad->ad_meta_refcount--;
+            if (!(--ad->ad_mdp->adf_refcount)) {
+                if (close( ad_meta_fileno(ad)) < 0)
+                    err = -1;
+                ad_meta_fileno(ad) = -1;
+            }
+        }
+
         if (ad->ad_reso_refcount)
             if (--ad->ad_reso_refcount == 0)
                 adf_lock_free(ad->ad_rfp);
index ea221ff4ec62964f827a8e2e8771a945d18c8b27..53ec4eb97ba96c600580898ae8015a48addacf43 100644 (file)
@@ -343,6 +343,14 @@ int ad_init_offsets(struct adouble *ad)
         eid++;
     }
 
+    /*
+     * Ensure the resource fork offset is always set
+     */
+#ifndef HAVE_EAFD
+    if (ad->ad_vers == AD_VERSION_EA)
+        ad_setentryoff(ad, ADEID_RFORK, ADEDOFF_RFORK_OSX);
+#endif
+
     return 0;
 }
 
@@ -540,7 +548,9 @@ int ad_valid_header_osx(const char *path)
         EC_FAIL;
     }
 
-    if (strncmp(buf + ADEDOFF_FILLER, "Mac OS X", strlen("Mac OS X")) == 0)
+    if (strncmp(buf + ADEDOFF_FILLER,
+                AD_FILLER_NETATALK,
+                strlen(AD_FILLER_NETATALK)) != 0)
         /*
          * It's a split fork created by OS X, it's not our "own" ._ file
          * and thus not a valid header in this context.
@@ -586,7 +596,7 @@ static int ad_convert_osx(const char *path, struct adouble *ad)
 
     origlen = ad_getentryoff(ad, ADEID_RFORK) + ad_getentrylen(ad, ADEID_RFORK);
 
-    map = mmap(NULL, origlen, PROT_WRITE, MAP_SHARED, ad_reso_fileno(ad), 0);
+    map = mmap(NULL, origlen, PROT_READ | PROT_WRITE, MAP_SHARED, ad_reso_fileno(ad), 0);
     if (map == MAP_FAILED) {
         LOG(log_error, logtype_ad, "mmap AppleDouble: %s\n", strerror(errno));
         EC_FAIL;
@@ -637,7 +647,7 @@ static int ad_header_read_osx(const char *path, struct adouble *ad, const struct
 {
     EC_INIT;
     struct adouble      adosx;
-    char                *buf = &adosx.ad_data[0];
+    char                *buf;
     uint16_t            nentries;
     int                 len;
     ssize_t             header_len;
@@ -647,6 +657,7 @@ static int ad_header_read_osx(const char *path, struct adouble *ad, const struct
 reread:
     LOG(log_debug, logtype_ad, "ad_header_read_osx: %s", path ? fullpathname(path) : "");
     ad_init_old(&adosx, AD_VERSION_EA, ad->ad_options);
+    buf = &adosx.ad_data[0];
     memset(buf, 0, sizeof(adosx.ad_data));
     adosx.ad_rfp->adf_fd = ad_reso_fileno(ad);
 
@@ -792,6 +803,14 @@ static int ad_header_read_ea(const char *path, struct adouble *ad, const struct
         EC_FAIL;
     }
 
+    /*
+     * Ensure the resource fork offset is always set
+     */
+#ifndef HAVE_EAFD
+    if (ad->ad_vers == AD_VERSION_EA)
+        ad_setentryoff(ad, ADEID_RFORK, ADEDOFF_RFORK_OSX);
+#endif
+
 EC_CLEANUP:
     if (ret != 0 && errno == EINVAL) {
         become_root();
@@ -1806,6 +1825,12 @@ void ad_init(struct adouble *ad, const struct vol * restrict vol)
  * - we remember open fds for files because me must avoid a single close releasing fcntl locks for other
  *   fds of the same file
  *
+ * BUGS:
+ *
+ * * on Solaris (HAVE_EAFD) ADFLAGS_RF doesn't work without
+ *   ADFLAGS_HF, because it checks whether ad_meta_fileno() is already
+ *   openend. As a workaround pass ADFLAGS_SETSHRMD.
+ *
  * @returns 0 on success, any other value indicates an error
  */
 int ad_open(struct adouble *ad, const char *path, int adflags, ...)
@@ -1927,7 +1952,7 @@ int ad_metadataat(int dirfd, const char *name, int flags, struct adouble *adp)
     int cwdfd = -1;
 
     if (dirfd != -1) {
-        if ((cwdfd = open(".", O_RDONLY) == -1) || (fchdir(dirfd) != 0)) {
+        if (((cwdfd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
             ret = -1;
             goto exit;
         }
index 5cd3742d69f9890f3fa01a5148fc23fda7ae1e6f..4ae1cf60adf1cfcbd61907d20a5fc430c1f4d31a 100644 (file)
@@ -161,17 +161,22 @@ int ad_rtruncate(struct adouble *ad, const char *uname, const off_t size)
 {
     EC_INIT;
 
-#ifndef HAVE_EAFD
-    if (ad->ad_vers == AD_VERSION_EA && size == 0)
-        EC_NEG1( unlink(ad->ad_ops->ad_path(uname, 0)) );
-    else
-#endif
-        EC_NEG1( sys_ftruncate(ad_reso_fileno(ad), size + ad->ad_eid[ ADEID_RFORK ].ade_off) );
+    /*
+     * We can't delete 0 byte size resource forks either, because a
+     * fork may reference the adouble handle with an open fd for the
+     * file, which means we would only delete the directory entry, not
+     * the file. Subsequently all code that works with fork handles
+     * finds the fork open, so eg flushing a fork (ad_flush()) will
+     * recreate ._ files.  The correct place to delete 0 byte sized
+     * resource forks is in of_closefork().
+     */
+
+    EC_NEG1( sys_ftruncate(ad_reso_fileno(ad), size + ad->ad_eid[ ADEID_RFORK ].ade_off) );
+
+    ad->ad_rlen = size;
 
 EC_CLEANUP:
-    if (ret == 0)
-        ad->ad_rlen = size;    
-    else
+    if (ret != 0)
         LOG(log_error, logtype_ad, "ad_rtruncate(\"%s\"): %s",
             fullpathname(uname), strerror(errno));
     EC_EXIT;
index a1e69a76ac5446a37afde531b208c9cbdc1a46bf..18f42c3cc0ffc36c89fde8c2ba6310d2871bdba0 100644 (file)
@@ -173,7 +173,7 @@ cnid_t cnid_cdb_add(struct _cnid_db *cdb, const struct stat *st,
     cnid_t id;
     int rc;
 
-    if (!cdb || !(db = cdb->_private) || !st || !name) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) {
         errno = CNID_ERR_PARAM;
         return CNID_INVALID;
     }
@@ -192,7 +192,7 @@ cnid_t cnid_cdb_add(struct _cnid_db *cdb, const struct stat *st,
     memset(&key, 0, sizeof(key));
     memset(&data, 0, sizeof(data));
 
-    if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
+    if ((data.data = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) {
         LOG(log_error, logtype_default, "cnid_add: Path name is too long");
         errno = CNID_ERR_PATH;
         return CNID_INVALID;
@@ -248,7 +248,7 @@ int cnid_cdb_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
     int rc;
     CNID_private *db;
 
-    if (!cdb || !(db = cdb->_private) || !buffer || !len) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !buffer || !len) {
         errno = CNID_ERR_PARAM;
         return -1;
     }
index d34a418b7e3cef4b623912d2008a4f54cec5a04e..c5aeceec21b5ed4c1cde4f3a67fb7f34ffff2ed9 100644 (file)
@@ -16,7 +16,7 @@ void cnid_cdb_close(struct _cnid_db *cdb) {
            return;
     }
 
-    if (!(db = cdb->_private)) {
+    if (!(db = cdb->cnid_db_private)) {
         return;
     }
     db->db_didname->sync(db->db_didname, 0); 
@@ -30,7 +30,6 @@ void cnid_cdb_close(struct _cnid_db *cdb) {
     db->dbenv->close(db->dbenv, 0);
 
     free(db);
-    free(cdb->volpath);
     free(cdb);
 }
 
index ace358aa8b617b79a1f01fa0f4d8274b7c8e9822..deaeca44a816349a123bc9dbd5109c96658c0964 100644 (file)
@@ -21,7 +21,7 @@ int cnid_cdb_delete(struct _cnid_db *cdb, const cnid_t id) {
     DBT key;
     int rc;
 
-    if (!cdb || !(db = cdb->_private) || !id || (db->flags & CNIDFLAG_DB_RO)) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !id || (db->flags & CNIDFLAG_DB_RO)) {
         return -1;
     }
 
index d4e090550eab6f85e3de0aa6671f7aa7d6006453..9c682a8c1d260781ed3d734e994c74f34917995e 100644 (file)
@@ -14,7 +14,7 @@ cnid_t cnid_cdb_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t l
     cnid_t id;
     int rc;
 
-    if (!cdb || !(db = cdb->_private) || (len > MAXPATHLEN)) {
+    if (!cdb || !(db = cdb->cnid_db_private) || (len > MAXPATHLEN)) {
         return 0;
     }
 
index 7b2f933c5182b4e1c4d4974f5a46c3bd7aa695ac..950709d5d201a6d3081b8c301201f2e324a20cd6 100644 (file)
@@ -26,11 +26,11 @@ cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
     cnid_t id_devino, id_didname,id = 0;
     int rc;
 
-    if (!cdb || !(db = cdb->_private) || !st || !name) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) {
         return 0;
     }
     
-    if ((buf = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
+    if ((buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) {
         LOG(log_error, logtype_default, "cnid_lookup: Pathname is too long");
         return 0;
     }
@@ -63,7 +63,7 @@ cnid_t cnid_cdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
         type_devino = ntohl(type_devino);
     }
 
-    buf = make_cnid_data(cdb->flags, st, did, name, len);
+    buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len);
     key.data = buf +CNID_DID_OFS;
     key.size = CNID_DID_LEN + len + 1;
     
index 757d1b0da1e2c3c351ef618679e5ab37b2c64b48..0a8cfa39ed8fa4c9811747909e822c7f8d69c2d8 100644 (file)
@@ -38,6 +38,7 @@
 
 #ifdef CNID_BACKEND_CDB
 
+#include <atalk/volume.h>
 #include <atalk/cnid_private.h>
 #include "cnid_cdb_private.h"
 
@@ -109,7 +110,7 @@ static int my_open(DB * p, const char *f, const char *d, DBTYPE t, u_int32_t fla
 }
 
 /* --------------- */
-static struct _cnid_db *cnid_cdb_new(const char *volpath)
+static struct _cnid_db *cnid_cdb_new(struct vol *vol)
 {
     struct _cnid_db *cdb;
     int major, minor, patch;
@@ -127,13 +128,8 @@ static struct _cnid_db *cnid_cdb_new(const char *volpath)
     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;
-
+    cdb->cnid_db_vol = vol;
+    cdb->cnid_db_flags = CNID_FLAG_PERSISTENT;
     cdb->cnid_add = cnid_cdb_add;
     cdb->cnid_delete = cnid_cdb_delete;
     cdb->cnid_get = cnid_cdb_get;
@@ -188,19 +184,16 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
     int open_flag, len;
     static int first = 0;
     int rc;
-
-    if (!args->dir || *args->dir == 0) {
-        return NULL;
-    }
+    struct vol *vol = args->cnid_args_vol;
 
     /* this checks .AppleDB.
        We need space for dir + '/' + DBHOMELEN + '/' + DBLEN */
-    if ((len = strlen(args->dir)) > (MAXPATHLEN - DBHOMELEN - DBLEN - 2)) {
-        LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", args->dir);
+    if ((len = strlen(vol->v_path)) > (MAXPATHLEN - DBHOMELEN - DBLEN - 2)) {
+        LOG(log_error, logtype_default, "cnid_open: Pathname too large: %s", vol->v_path);
         return NULL;
     }
 
-    if ((cdb = cnid_cdb_new(args->dir)) == NULL) {
+    if ((cdb = cnid_cdb_new(vol)) == NULL) {
         LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database");
         return NULL;
     }
@@ -210,17 +203,16 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
         goto fail_cdb;
     }
 
-    cdb->_private = (void *) db;
-    db->magic = CNID_DB_MAGIC;
+    cdb->cnid_db_private = (void *) db;
 
-    strcpy(path, args->dir);
+    strcpy(path, vol->v_path);
     if (path[len - 1] != '/') {
         strcat(path, "/");
         len++;
     }
 
     strcpy(path + len, DBHOME);
-    if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) {
+    if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~vol->v_umask) < 0)) {
         LOG(log_error, logtype_default, "cnid_open: DBHOME mkdir failed for %s", path);
         goto fail_adouble;
     }
@@ -247,7 +239,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
     }
 
     /* Open the database environment. */
-    if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~args->mask)) != 0) {
+    if ((rc = db->dbenv->open(db->dbenv, path, DBOPTIONS, 0666 & ~vol->v_umask)) != 0) {
        LOG(log_error, logtype_default, "cnid_open: dbenv->open (rw) of %s failed: %s", path, db_strerror(rc));
        /* FIXME: This should probably go. Even if it worked, any use for a read-only DB? Didier? */
         if (rc == DB_RUNRECOVERY) {
@@ -260,10 +252,10 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
         /* We can't get a full transactional environment, so multi-access
          * is out of the question.  Let's assume a read-only environment,
          * and try to at least get a shared memory pool. */
-        if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~args->mask)) != 0) {
+        if ((rc = db->dbenv->open(db->dbenv, path, DB_INIT_MPOOL, 0666 & ~vol->v_umask)) != 0) {
             /* Nope, not a MPOOL, either.  Last-ditch effort: we'll try to
              * open the environment with no flags. */
-            if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~args->mask)) != 0) {
+            if ((rc = db->dbenv->open(db->dbenv, path, 0, 0666 & ~vol->v_umask)) != 0) {
                 LOG(log_error, logtype_default, "cnid_open: dbenv->open of %s failed: %s", path, db_strerror(rc));
                 goto fail_lock;
             }
@@ -282,7 +274,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
         goto fail_appinit;
     }
 
-    if ((rc = my_open(db->db_cnid, DBCNID, DBCNID, DB_BTREE, open_flag, 0666 & ~args->mask)) != 0) {
+    if ((rc = my_open(db->db_cnid, DBCNID, DBCNID, DB_BTREE, open_flag, 0666 & ~vol->v_umask)) != 0) {
         LOG(log_error, logtype_default, "cnid_open: Failed to open dev/ino database: %s",
             db_strerror(rc));
         goto fail_appinit;
@@ -297,7 +289,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
         goto fail_appinit;
     }
 
-    if ((rc = my_open(db->db_didname, DBCNID, DBDIDNAME, DB_BTREE, open_flag, 0666 & ~args->mask))) {
+    if ((rc = my_open(db->db_didname, DBCNID, DBDIDNAME, DB_BTREE, open_flag, 0666 & ~vol->v_umask))) {
         LOG(log_error, logtype_default, "cnid_open: Failed to open did/name database: %s",
             db_strerror(rc));
         goto fail_appinit;
@@ -312,7 +304,7 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
         goto fail_appinit;
     }
 
-    if ((rc = my_open(db->db_devino, DBCNID, DBDEVINO, DB_BTREE, open_flag, 0666 & ~args->mask)) != 0) {
+    if ((rc = my_open(db->db_devino, DBCNID, DBDEVINO, DB_BTREE, open_flag, 0666 & ~vol->v_umask)) != 0) {
         LOG(log_error, logtype_default, "cnid_open: Failed to open devino database: %s",
             db_strerror(rc));
         goto fail_appinit;
@@ -373,8 +365,6 @@ struct _cnid_db *cnid_cdb_open(struct cnid_open_args *args)
     free(db);
 
   fail_cdb:
-    if (cdb->volpath != NULL)
-        free(cdb->volpath);
     free(cdb);
 
     return NULL;
index 4620782e14057f4ce5cf29d7976ad7e6d3c9b885..951674656c85931f45edd6cdf7a4fa8c99fe8a4b 100644 (file)
@@ -79,7 +79,7 @@ cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
     DBT key, data;
     int rc;
 
-    if (!cdb || !(db = cdb->_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name || hint == CNID_INVALID || hint < CNID_START) {
         errno = CNID_ERR_PARAM;
         return CNID_INVALID;
     }
@@ -101,7 +101,7 @@ cnid_t cnid_cdb_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
     memset(&key, 0, sizeof(key));
     memset(&data, 0, sizeof(data));
 
-    if ((data.data = make_cnid_data(cdb->flags, st, did, name, len)) == NULL) {
+    if ((data.data = make_cnid_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) {
         LOG(log_error, logtype_default, "cnid_add: Path name is too long");
         errno = CNID_ERR_PATH;
         return CNID_INVALID;
index 63ed9f8a1c14b51c9de5837ef32e91ab2713d558..d3f6dab97a64099f763e9a62a93dc2439b7e329e 100644 (file)
@@ -14,7 +14,7 @@ char *cnid_cdb_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le
     DBT key, data;
     int rc;
 
-    if (!cdb || !(db = cdb->_private) || !id || !(*id)) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) {
         return NULL;
     }
 
index f7676c840054516c10be062dae3e874719b7e23e..90c7d93ff54655b82812b1699732fab60b5c3250 100644 (file)
@@ -20,7 +20,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     int notfound = 0;
     char getbuf[CNID_HEADER_LEN + MAXPATHLEN +1];
 
-    if (!cdb || !(db = cdb->_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) {
         return -1;
     }
 
@@ -28,7 +28,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     memset(&pkey, 0, sizeof(pkey));
     memset(&data, 0, sizeof(data));
 
-    buf = make_cnid_data(cdb->flags, st, did, name, len);
+    buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len);
 
     key.data = buf +CNID_DEVINO_OFS;
     key.size = CNID_DEVINO_LEN;
@@ -54,7 +54,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     }
 
     memset(&pkey, 0, sizeof(pkey));
-    buf = make_cnid_data(cdb->flags, st, did, name, len);
+    buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len);
     key.data = buf + CNID_DID_OFS;
     key.size = CNID_DID_LEN + len + 1;
 
@@ -83,7 +83,7 @@ int cnid_cdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
 
     memset(&data, 0, sizeof(data));
     /* Make a new entry. */
-    buf = make_cnid_data(cdb->flags, st, did, name, len);
+    buf = make_cnid_data(cdb->cnid_db_flags, st, did, name, len);
     data.data = buf;
     memcpy(data.data, &id, sizeof(id));
     data.size = CNID_HEADER_LEN + len + 1;
index 9212caccafa73ad1ef0c7585d4bdfa6a29782ed7..fde4d70f500298b3de09f6189de46e7f2eaffe22 100644 (file)
@@ -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);
@@ -91,8 +92,7 @@ static int cnid_dir(const char *dir, mode_t mask)
 }
 
 /* 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, const void *obj, char *uuid)
+struct _cnid_db *cnid_open(struct vol *vol, char *type, int flags)
 {
     struct _cnid_db *db;
     cnid_module *mod = NULL;
@@ -119,7 +119,7 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
             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);
@@ -128,7 +128,11 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
         }
     }
 
-    struct cnid_open_args args = {volpath, mask, flags, cnidsrv, cnidport, obj, uuid};
+    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)) {
@@ -140,16 +144,15 @@ struct _cnid_db *cnid_open(const char *volpath, mode_t mask, char *type, int fla
     }
 
     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);
@@ -207,7 +210,7 @@ void cnid_close(struct _cnid_db *db)
         return;
     }
     /* cnid_close free db */
-    flags = db->flags;
+    flags = db->cnid_db_flags;
     block_signal(flags);
     db->cnid_close(db);
     unblock_signal(flags);
@@ -222,9 +225,9 @@ cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
     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;
 }
 
@@ -233,9 +236,9 @@ int cnid_delete(struct _cnid_db *cdb, cnid_t id)
 {
 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;
 }
 
@@ -245,9 +248,9 @@ cnid_t cnid_get(struct _cnid_db *cdb, const cnid_t did, char *name,const size_t
 {
 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;
 }
 
@@ -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;
 }
 
@@ -278,9 +281,9 @@ cnid_t cnid_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did
 {
     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;
 }
 
@@ -294,9 +297,9 @@ int cnid_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buff
         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;
 }
 
@@ -305,9 +308,9 @@ char *cnid_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t len)
 {
 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;
@@ -321,9 +324,9 @@ int cnid_update   (struct _cnid_db *cdb, const cnid_t id, const struct stat *st,
 {
 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;
 }
                        
@@ -333,9 +336,9 @@ cnid_t cnid_rebuild_add(struct _cnid_db *cdb, const struct stat *st, const cnid_
 {
 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;
 }
 
@@ -344,9 +347,9 @@ int cnid_wipe(struct _cnid_db *cdb)
 {
     int ret = 0;
 
-    block_signal(cdb->flags);
+    block_signal(cdb->cnid_db_flags);
     if (cdb->cnid_wipe)
         ret = cdb->cnid_wipe(cdb);
-    unblock_signal(cdb->flags);
+    unblock_signal(cdb->cnid_db_flags);
     return ret;
 }
index 1b365065cdd79194d2b8329fbef496bfa8ffdcf6..d4606400aa1539e6bd64bf52b24c410bfa1a3b9e 100644 (file)
@@ -33,6 +33,7 @@
 #include <atalk/cnid.h>
 #include <atalk/cnid_bdb_private.h>
 #include <atalk/util.h>
+#include <atalk/volume.h>
 
 #include "cnid_dbd.h"
 
@@ -227,24 +228,46 @@ static int write_vec(int fd, struct iovec *iov, ssize_t towrite, int vecs)
 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;
-    iov[0].iov_len  = sizeof(int);
+    iov[0].iov_base = &len[0];
+    iov[0].iov_len  = DBD_NUM_OPEN_ARGS * sizeof(int);
 
-    iov[1].iov_base = db->db_dir;
-    iov[1].iov_len  = len;
+    iov[1].iov_base = vol->v_configname;
+    iov[1].iov_len  = len[0];
 
-    if (write_vec(fd, iov, len + sizeof(int), 2) != len + sizeof(int)) {
+    iov[2].iov_base = vol->v_path;
+    iov[2].iov_len  = len[1];
+
+    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;
@@ -275,8 +298,8 @@ static int send_packet(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst)
     }
 
     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;
     }
 
@@ -327,21 +350,21 @@ static int dbd_rpc(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cnid
     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;
     }
 
@@ -367,7 +390,7 @@ static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cni
             } else { /* db->notfirst == 0 */
                 db->notfirst = 1;
             }
-            LOG(log_debug, logtype_cnid, "transmit: attached to '%s'", db->db_dir);
+            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}");
@@ -381,14 +404,14 @@ static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cni
 
         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 */
@@ -402,20 +425,15 @@ static int transmit(CNID_bdb_private *db, struct cnid_dbd_rqst *rqst, struct cni
 }
 
 /* ---------------------- */
-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;
@@ -437,11 +455,7 @@ struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args)
     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;
     }
@@ -451,27 +465,19 @@ struct _cnid_db *cnid_dbd_open(struct cnid_open_args *args)
         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);
 
@@ -488,15 +494,14 @@ void cnid_dbd_close(struct _cnid_db *cdb)
         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;
@@ -537,7 +542,7 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
     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;
@@ -552,7 +557,7 @@ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st,
     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;
     }
 
@@ -601,7 +606,7 @@ cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t l
     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;
@@ -654,7 +659,7 @@ char *cnid_dbd_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t le
     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;
@@ -710,7 +715,7 @@ int cnid_dbd_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
 {
     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;
@@ -730,7 +735,7 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
     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;
@@ -745,7 +750,7 @@ cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
     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;
     }
 
@@ -791,7 +796,7 @@ int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *
     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;
@@ -846,7 +851,7 @@ int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     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;
@@ -861,7 +866,7 @@ int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     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;
@@ -901,7 +906,7 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
     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;
@@ -916,7 +921,7 @@ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st,
     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;
     }
 
@@ -962,7 +967,7 @@ int cnid_dbd_delete(struct _cnid_db *cdb, const cnid_t id)
     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;
@@ -999,7 +1004,7 @@ int cnid_dbd_wipe(struct _cnid_db *cdb)
     struct cnid_dbd_rqst rqst;
     struct cnid_dbd_rply rply;
 
-    if (!cdb || !(db = cdb->_private)) {
+    if (!cdb || !(db = cdb->cnid_db_private)) {
         LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error");
         errno = CNID_ERR_PARAM;
         return -1;
index cc2ae1c7d19e79ec3ef8ae13c14936bc491908b7..2314217cd50b1eb4c3109d98f3ccab85bfc1bfe4 100644 (file)
@@ -58,10 +58,10 @@ cnid_t cnid_last_add(struct _cnid_db *cdb, const struct stat *st,
 
     struct _cnid_last_private *priv;
 
-    if (!cdb || !(cdb->_private))
+    if (!cdb || !(cdb->cnid_db_private))
         return CNID_INVALID;
 
-    priv = (struct _cnid_last_private *) (cdb->_private);
+    priv = (struct _cnid_last_private *) (cdb->cnid_db_private);
 
     if (S_ISDIR(st->st_mode))
         return htonl(priv->last_did++);
@@ -73,8 +73,7 @@ cnid_t cnid_last_add(struct _cnid_db *cdb, const struct stat *st,
 
 void cnid_last_close(struct _cnid_db *cdb)
 {
-    free(cdb->volpath);
-    free(cdb->_private);
+    free(cdb->cnid_db_private);
     free(cdb);
 }
 
@@ -105,7 +104,7 @@ cnid_t cnid_last_lookup(struct _cnid_db *cdb _U_, const struct stat *st _U_, cni
 }
 
 
-static struct _cnid_db *cnid_last_new(const char *volpath)
+static struct _cnid_db *cnid_last_new(struct vol *vol)
 {
     struct _cnid_db *cdb;
     struct _cnid_last_private *priv;
@@ -113,23 +112,17 @@ static struct _cnid_db *cnid_last_new(const char *volpath)
     if ((cdb = (struct _cnid_db *) calloc(1, sizeof(struct _cnid_db))) == NULL)
         return NULL;
 
-    if ((cdb->volpath = strdup(volpath)) == NULL) {
-        free(cdb);
-        return NULL;
-    }
-
-    if ((cdb->_private = calloc(1, sizeof(struct _cnid_last_private))) == NULL) {
-        free(cdb->volpath);
+    if ((cdb->cnid_db_private = calloc(1, sizeof(struct _cnid_last_private))) == NULL) {
         free(cdb);
         return NULL;
     }
 
     /* Set up private state */
-    priv = (struct _cnid_last_private *) (cdb->_private);
+    priv = (struct _cnid_last_private *) (cdb->cnid_db_private);
     priv->last_did = 17;
 
     /* Set up standard fields */
-    cdb->flags = 0;
+    cdb->cnid_db_flags = 0;
     cdb->cnid_add = cnid_last_add;
     cdb->cnid_delete = cnid_last_delete;
     cdb->cnid_get = cnid_last_get;
@@ -147,11 +140,7 @@ struct _cnid_db *cnid_last_open(struct cnid_open_args *args)
 {
     struct _cnid_db *cdb;
 
-    if (!args->dir) {
-        return NULL;
-    }
-
-    if ((cdb = cnid_last_new(args->dir)) == NULL) {
+    if ((cdb = cnid_last_new(args->cnid_args_vol)) == NULL) {
         LOG(log_error, logtype_default, "cnid_open: Unable to allocate memory for database");
         return NULL;
     }
index c661f9ac3d5623e43a4ad9be700865125c8ec4fa..aa04bf81f259127585974ac9f2764e3a000a63e0 100644 (file)
@@ -7,6 +7,8 @@
 #include "config.h"
 #endif /* HAVE_CONFIG_H */
 
+#undef _FORTIFY_SOURCE
+
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/uio.h>
@@ -36,6 +38,8 @@
 #include <atalk/cnid_bdb_private.h>
 #include <atalk/errchk.h>
 #include <atalk/globals.h>
+#include <atalk/volume.h>
+
 
 static MYSQL_BIND lookup_param[4], lookup_result[5];
 static MYSQL_BIND add_param[4], put_param[5];
@@ -240,7 +244,7 @@ int cnid_mysql_delete(struct _cnid_db *cdb, const cnid_t id)
     EC_INIT;
     CNID_mysql_private *db;
 
-    if (!cdb || !(db = cdb->_private) || !id) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !id) {
         LOG(log_error, logtype_cnid, "cnid_mysql_delete: Parameter error");
         errno = CNID_ERR_PARAM;
         EC_FAIL;
@@ -268,8 +272,9 @@ void cnid_mysql_close(struct _cnid_db *cdb)
         return;
     }
 
-    if ((db = cdb->_private) != NULL) {
-        LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'", db->cnid_mysql_volname);
+    if ((db = cdb->cnid_db_private) != NULL) {
+        LOG(log_debug, logtype_cnid, "closing database connection for volume '%s'",
+            cdb->cnid_db_vol->v_localname);
 
         free(db->cnid_mysql_voluuid_str);
 
@@ -280,7 +285,6 @@ void cnid_mysql_close(struct _cnid_db *cdb)
         free(db);
     }
 
-    free(cdb->volpath);
     free(cdb);
 
     return;
@@ -297,7 +301,7 @@ int cnid_mysql_update(struct _cnid_db *cdb,
     CNID_mysql_private *db;
     cnid_t update_id;
 
-    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;
         EC_FAIL;
@@ -366,7 +370,7 @@ cnid_t cnid_mysql_lookup(struct _cnid_db *cdb,
     cnid_t id = CNID_INVALID;
     bool have_result = false;
 
-    if (!cdb || !(db = cdb->_private) || !st || !name) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) {
         LOG(log_error, logtype_cnid, "cnid_mysql_lookup: Parameter error");
         errno = CNID_ERR_PARAM;
         EC_FAIL;
@@ -505,7 +509,7 @@ cnid_t cnid_mysql_add(struct _cnid_db *cdb,
     MYSQL_STMT *stmt;
     my_ulonglong lastid;
 
-    if (!cdb || !(db = cdb->_private) || !st || !name) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) {
         LOG(log_error, logtype_cnid, "cnid_mysql_add: Parameter error");
         errno = CNID_ERR_PARAM;
         EC_FAIL;
@@ -609,7 +613,7 @@ cnid_t cnid_mysql_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t
     MYSQL_RES *result = NULL;
     MYSQL_ROW row;
 
-    if (!cdb || !(db = cdb->_private) || !name) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !name) {
         LOG(log_error, logtype_cnid, "cnid_mysql_get: Parameter error");
         errno = CNID_ERR_PARAM;
         EC_FAIL;
@@ -658,7 +662,7 @@ char *cnid_mysql_resolve(struct _cnid_db *cdb, cnid_t *id, void *buffer, size_t
     MYSQL_RES *result = NULL;
     MYSQL_ROW row;
 
-    if (!cdb || !(db = cdb->_private)) {
+    if (!cdb || !(db = cdb->cnid_db_private)) {
         LOG(log_error, logtype_cnid, "cnid_mysql_get: Parameter error");
         errno = CNID_ERR_PARAM;
         EC_FAIL;
@@ -700,7 +704,7 @@ int cnid_mysql_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
     MYSQL_RES *result = NULL;
     MYSQL_ROW row;
 
-    if (!cdb || !(db = cdb->_private)) {
+    if (!cdb || !(db = cdb->cnid_db_private)) {
         LOG(log_error, logtype_cnid, "cnid_find: Parameter error");
         errno = CNID_ERR_PARAM;
         return CNID_INVALID;
@@ -711,7 +715,7 @@ int cnid_mysql_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
 
     if (cnid_mysql_execute(db->cnid_mysql_con,
                            "SELECT Stamp FROM volumes WHERE VolPath='%s'",
-                           db->cnid_mysql_volname)) {
+                           cdb->cnid_db_vol->v_path)) {
         if (mysql_errno(db->cnid_mysql_con) != ER_DUP_ENTRY) {
             LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con));
             EC_FAIL;
@@ -724,7 +728,7 @@ int cnid_mysql_getstamp(struct _cnid_db *cdb, void *buffer, const size_t len)
         EC_FAIL;
     }
     if (!mysql_num_rows(result)) {
-        LOG(log_error, logtype_cnid, "Can't get DB stamp for volumes \"%s\"", db->cnid_mysql_volname);
+        LOG(log_error, logtype_cnid, "Can't get DB stamp for volumes \"%s\"", cdb->cnid_db_vol->v_path);
         EC_FAIL;
     }
     row = mysql_fetch_row(result);
@@ -758,7 +762,7 @@ int cnid_mysql_wipe(struct _cnid_db *cdb)
     CNID_mysql_private *db;
     MYSQL_RES *result = NULL;
 
-    if (!cdb || !(db = cdb->_private)) {
+    if (!cdb || !(db = cdb->cnid_db_private)) {
         LOG(log_error, logtype_cnid, "cnid_wipe: Parameter error");
         errno = CNID_ERR_PARAM;
         return -1;
@@ -787,19 +791,15 @@ EC_CLEANUP:
     EC_EXIT;
 }
 
-static struct _cnid_db *cnid_mysql_new(const char *volpath)
+static struct _cnid_db *cnid_mysql_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_mysql_add;
     cdb->cnid_delete = cnid_mysql_delete;
     cdb->cnid_get = cnid_mysql_get;
@@ -817,7 +817,6 @@ static struct _cnid_db *cnid_mysql_new(const char *volpath)
 
 static const char *printuuid(const unsigned char *uuid) {
     static char uuidstring[64];
-    const char *uuidmask;
     int i = 0;
     unsigned char c;
 
@@ -838,16 +837,13 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args)
     struct _cnid_db *cdb = NULL;
     MYSQL_RES *result = NULL;
     MYSQL_ROW row;
+    struct vol *vol = args->cnid_args_vol;
 
-    EC_NULL( cdb = cnid_mysql_new(args->dir) );
+    EC_NULL( cdb = cnid_mysql_new(vol) );
     EC_NULL( db = (CNID_mysql_private *)calloc(1, sizeof(CNID_mysql_private)) );
-    cdb->_private = db;
+    cdb->cnid_db_private = db;
 
-    db->cnid_mysql_volname = strdup(args->dir); /* db_dir contains the volume name */
-    db->cnid_mysql_magic = CNID_DB_MAGIC;
-    db->cnid_mysql_obj = args->obj;
-    memcpy(db->cnid_mysql_voluuid, args->voluuid, sizeof(atalk_uuid_t));
-    db->cnid_mysql_voluuid_str = strdup(printuuid(db->cnid_mysql_voluuid));
+    db->cnid_mysql_voluuid_str = strdup(printuuid(vol->v_uuid));
 
     /* Initialize and connect to MySQL server */
     EC_NULL( db->cnid_mysql_con = mysql_init(NULL) );
@@ -856,7 +852,7 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args)
     int my_timeout = 600;
     EC_ZERO( mysql_options(db->cnid_mysql_con, MYSQL_OPT_CONNECT_TIMEOUT, &my_timeout) );
 
-    const AFPObj *obj = db->cnid_mysql_obj;
+    const AFPObj *obj = vol->v_obj;
 
     EC_NULL( mysql_real_connect(db->cnid_mysql_con,
                                 obj->options.cnid_mysql_host,
@@ -883,7 +879,7 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args)
                            "INSERT INTO volumes (VolUUID,Volpath,Stamp,Depleted) "
                            "VALUES('%s','%s','%s',0)",
                            db->cnid_mysql_voluuid_str,
-                           db->cnid_mysql_volname,
+                           vol->v_path,
                            blob)) {
         if (mysql_errno(db->cnid_mysql_con) != ER_DUP_ENTRY) {
             LOG(log_error, logtype_cnid, "MySQL query error: %s", mysql_error(db->cnid_mysql_con));
@@ -934,18 +930,14 @@ struct _cnid_db *cnid_mysql_open(struct cnid_open_args *args)
     EC_ZERO( init_prepared_stmt(db) );
 
     LOG(log_debug, logtype_cnid, "Finished initializing MySQL CNID module for volume '%s'",
-        db->cnid_mysql_volname);
+        vol->v_path);
 
 EC_CLEANUP:
     if (result)
         mysql_free_result(result);
     if (ret != 0) {
-        if (cdb) {
-            if (cdb->volpath != NULL) {
-                free(cdb->volpath);
-            }
+        if (cdb)
             free(cdb);
-        }
         cdb = NULL;
         if (db)
             free(db);
index 3203eda94a9f80de30e180f44bd3744755d65b92..b3babcd35f2b87f58d9f08474dbf9bea15099ccd 100644 (file)
@@ -160,7 +160,7 @@ cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st,
     TDB_DATA key, data; 
     int rc;      
     
-    if (!cdb || !(priv = cdb->_private) || !st || !name) {
+    if (!cdb || !(priv = cdb->cnid_db_private) || !st || !name) {
         errno = CNID_ERR_PARAM;
         return CNID_INVALID;
     }
@@ -183,7 +183,7 @@ cnid_t cnid_tdb_add(struct _cnid_db *cdb, const struct stat *st,
 
     key.dptr = (unsigned char *)&hint;
     key.dsize = sizeof(cnid_t);
-    if ((data.dptr = make_tdb_data(cdb->flags, lstp, did, name, len)) == NULL) {
+    if ((data.dptr = make_tdb_data(cdb->cnid_db_flags, lstp, did, name, len)) == NULL) {
         LOG(log_error, logtype_default, "tdb_add: Path name is too long");
         errno = CNID_ERR_PATH;
         return CNID_INVALID;
index c500181611549fb49deeddfabe646c30ec6aa6c8..4879e10bba415ef75a4f1bcc201653430df19d1d 100644 (file)
@@ -13,10 +13,9 @@ void cnid_tdb_close(struct _cnid_db *cdb)
 {
     struct _cnid_tdb_private *db;
 
-    free(cdb->volpath);
-    db = (struct _cnid_tdb_private *)cdb->_private;
+    db = (struct _cnid_tdb_private *)cdb->cnid_db_private;
     tdb_close(db->tdb_cnid);
-    free(cdb->_private);
+    free(cdb->cnid_db_private);
     free(cdb);
 }
 
index a16a99519327bcab826589b3995524b44a67b2d0..95441098bf807938476cd60e6ed1c8500e0ec7de 100644 (file)
@@ -19,7 +19,7 @@ int cnid_tdb_delete(struct _cnid_db *cdb, const cnid_t id)
     struct _cnid_tdb_private *db;
     TDB_DATA key, data;
 
-    if (!cdb || !(db = cdb->_private) || !id) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !id) {
         return -1;
     }
     memset(&key, 0, sizeof(key));
index 4e7f638dd18debb62470bc4f19b7bcb58be589e7..5c7536777eca193a7c80da3411e3172a3ceaf91c 100644 (file)
@@ -14,7 +14,7 @@ cnid_t cnid_tdb_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t l
     TDB_DATA key, data;
     cnid_t id;
 
-    if (!cdb || !(db = cdb->_private) || (len > MAXPATHLEN)) {
+    if (!cdb || !(db = cdb->cnid_db_private) || (len > MAXPATHLEN)) {
         return 0;
     }
 
index c95631afee52574c292cb0534b85b6a407cc6e0f..7c7bdff14c2fdfd3b5dcc9dc01420a5bc2dc1faa 100644 (file)
@@ -21,11 +21,11 @@ cnid_t cnid_tdb_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did,
     int update = 0;
     cnid_t id_devino = 0, id_didname = 0,id = 0;
 
-    if (!cdb || !(db = cdb->_private) || !st || !name) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !st || !name) {
         return 0;
     }
 
-    if ((buf = (char *)make_tdb_data(cdb->flags, st, did, name, len)) == NULL) {
+    if ((buf = (char *)make_tdb_data(cdb->cnid_db_flags, st, did, name, len)) == NULL) {
         LOG(log_error, logtype_default, "tdb_lookup: Pathname is too long");
         return 0;
     }
index 0aee5b4df5469ddbb3282c8d23d67f35f3bb3837..7e2558fe3c34fc13592f24e40df6ccd0a78c31e6 100644 (file)
@@ -12,6 +12,8 @@
 
 #include "cnid_tdb.h"
 #include <atalk/logger.h>
+#include <atalk/volume.h>
+
 #include <stdlib.h>
 #define DBHOME       ".AppleDB"
 #define DBHOMELEN    9                  /* strlen(DBHOME) +1 for / */
 #define DBVERSION2       0x00000002U
 #define DBVERSION        DBVERSION2
 
-static struct _cnid_db *cnid_tdb_new(const char *volpath)
+static struct _cnid_db *cnid_tdb_new(struct vol *vol)
 {
     struct _cnid_db *cdb;
-    struct _cnid_tdb_private *priv;
 
     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->cnid_db_vol = vol;
 
-    if ((cdb->_private = calloc(1, sizeof(struct _cnid_tdb_private))) == NULL) {
-        free(cdb->volpath);
+    if ((cdb->cnid_db_private = calloc(1, sizeof(struct _cnid_tdb_private))) == NULL) {
         free(cdb);
         return NULL;
     }
 
-    /* Set up private state */
-    priv = (struct _cnid_tdb_private *) (cdb->_private);
-
     /* Set up standard fields */
-    cdb->flags = CNID_FLAG_PERSISTENT;
+    cdb->cnid_db_flags = CNID_FLAG_PERSISTENT;
 
     cdb->cnid_add = cnid_tdb_add;
     cdb->cnid_delete = cnid_tdb_delete;
@@ -72,31 +66,27 @@ struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
     TDB_DATA                  key, data;
     int                      hash_size = 131071;
     int                       tdb_flags = 0;
+    struct vol               *vol = args->cnid_args_vol;
 
-    if (!args->dir) {
-        /* note: dir and path are not used for in memory db */
+    if ((cdb = cnid_tdb_new(vol)) == NULL) {
+        LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
         return NULL;
     }
 
-    if ((len = strlen(args->dir)) > (MAXPATHLEN - DBLEN - 1)) {
-        LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", args->dir);
-        return NULL;
-    }
-    
-    if ((cdb = cnid_tdb_new(args->dir)) == NULL) {
-        LOG(log_error, logtype_default, "tdb_open: Unable to allocate memory for tdb");
+    if ((len = strlen(vol->v_path)) > (MAXPATHLEN - DBLEN - 1)) {
+        LOG(log_error, logtype_default, "tdb_open: Pathname too large: %s", vol->v_path);
         return NULL;
     }
     
-    strcpy(path, args->dir);
+    strcpy(path, vol->v_path);
     if (path[len - 1] != '/') {
         strcat(path, "/");
         len++;
     }
  
     strcpy(path + len, DBHOME);
-    if (!(args->flags & CNID_FLAG_MEMORY)) {
-        if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~args->mask) < 0)) {
+    if (!(args->cnid_args_flags & CNID_FLAG_MEMORY)) {
+        if ((stat(path, &st) < 0) && (ad_mkdir(path, 0777 & ~vol->v_umask) < 0)) {
             LOG(log_error, logtype_default, "tdb_open: DBHOME mkdir failed for %s", path);
             goto fail;
         }
@@ -107,12 +97,12 @@ struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
     }
     strcat(path, "/");
  
-    db = (struct _cnid_tdb_private *)cdb->_private;
+    db = (struct _cnid_tdb_private *)cdb->cnid_db_private;
 
     path[len + DBHOMELEN] = '\0';
     strcat(path, DBCNID);
 
-    db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~args->mask);
+    db->tdb_cnid = tdb_open(path, hash_size, tdb_flags , O_RDWR | O_CREAT, 0666 & ~vol->v_umask);
     if (!db->tdb_cnid) {
         LOG(log_error, logtype_default, "tdb_open: unable to open tdb", path);
         goto fail;
@@ -146,8 +136,7 @@ struct _cnid_db *cnid_tdb_open(struct cnid_open_args *args)
     return cdb;
 
 fail:
-    free(cdb->_private);
-    free(cdb->volpath);
+    free(cdb->cnid_db_private);
     free(cdb);
     
     return NULL;
index 851f9e55e7be86811bb4106018411f0cc98b5a30..b999ca3e001d73b6d5271149b52c3a3e814dc773 100644 (file)
@@ -15,7 +15,7 @@ char *cnid_tdb_resolve(struct _cnid_db *cdb, cnid_t * id, void *buffer, size_t l
     struct _cnid_tdb_private *db;
     TDB_DATA key, data;      
 
-    if (!cdb || !(db = cdb->_private) || !id || !(*id)) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !id || !(*id)) {
         return NULL;
     }
     key.dptr  = (unsigned char *)id;
index 6d23b109f528ab71aad7de553339d534fd85431e..9688d866c5c5490a16751de56d89ea144298e9b5 100644 (file)
@@ -13,7 +13,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     struct _cnid_tdb_private *db;
     TDB_DATA key, data, altdata;
 
-    if (!cdb || !(db = cdb->_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) {
+    if (!cdb || !(db = cdb->cnid_db_private) || !id || !st || !name || (db->flags & CNIDFLAG_DB_RO)) {
         return -1;
     }
 
@@ -22,7 +22,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
 
 
     /* Get the old info. search by dev/ino */
-    data.dptr = make_tdb_data(cdb->flags, st, did, name, len);
+    data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len);
     data.dsize = CNID_HEADER_LEN + len + 1;
     key.dptr = data.dptr +CNID_DEVINO_OFS;
     key.dsize = CNID_DEVINO_LEN;
@@ -47,7 +47,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     }
 
     /* search by did/name */
-    data.dptr = make_tdb_data(cdb->flags, st, did, name, len);
+    data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len);
     data.dsize = CNID_HEADER_LEN + len + 1;
     key.dptr = (unsigned char *)data.dptr +CNID_DID_OFS;
     key.dsize = data.dsize - CNID_DID_OFS;
@@ -71,7 +71,7 @@ int cnid_tdb_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st,
     
 
     /* Make a new entry. */
-    data.dptr = make_tdb_data(cdb->flags, st, did, name, len);
+    data.dptr = make_tdb_data(cdb->cnid_db_flags, st, did, name, len);
     data.dsize = CNID_HEADER_LEN + len + 1;
     memcpy(data.dptr, &id, sizeof(id));
 
diff --git a/libatalk/libatalk-3.1.1.abi b/libatalk/libatalk-3.1.1.abi
new file mode 100644 (file)
index 0000000..11fb887
--- /dev/null
@@ -0,0 +1,639 @@
+acl_ldap_freeconfig: void (void)
+acl_ldap_readconfig: int (dictionary *)
+ad_close: int (struct adouble *, int)
+ad_convert: int (const char *, const struct stat *, const struct vol *, const char **)
+ad_copy_header: int (struct adouble *, struct adouble *)
+add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int)
+add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int)
+add_charset: charset_t (const char *)
+ad_dir: char *(const char *)
+ad_dtruncate: int (struct adouble *, const off_t)
+adflags2logstr: const char *(int)
+ad_flush: int (struct adouble *)
+ad_forcegetid: uint32_t (struct adouble *)
+adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t)
+adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t)
+ad_getattr: int (const struct adouble *, uint16_t *)
+ad_getdate: int (const struct adouble *, unsigned int, uint32_t *)
+ad_getentryoff: off_t (const struct adouble *, int)
+ad_getfuid: uid_t (void)
+ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *)
+ad_hf_mode: mode_t (mode_t)
+ad_init: void (struct adouble *, const struct vol *)
+ad_init_offsets: int (struct adouble *)
+ad_init_old: void (struct adouble *, int, int)
+ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_metadata: int (const char *, int, struct adouble *)
+ad_metadataat: int (int, const char *, int, struct adouble *)
+ad_mkdir: int (const char *, mode_t)
+ad_mode: int (const char *, mode_t)
+ad_open: int (struct adouble *, const char *, int, ...)
+ad_openat: int (struct adouble *, int, const char *, int, ...)
+ad_openforks: uint16_t (struct adouble *, uint16_t)
+ad_path: const char *(const char *, int)
+ad_path_ea: const char *(const char *, int)
+ad_path_osx: const char *(const char *, int)
+ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t)
+ad_readfile_init: int (const struct adouble *, const int, off_t *, const int)
+ad_rebuild_adouble_header_ea: int (struct adouble *)
+ad_rebuild_adouble_header_osx: int (struct adouble *, char *)
+ad_rebuild_adouble_header_v2: int (struct adouble *)
+ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int)
+ad_refresh: int (const char *, struct adouble *)
+ad_reso_size: off_t (const char *, int, struct adouble *)
+ad_rtruncate: int (struct adouble *, const char *, const off_t)
+ad_setattr: int (const struct adouble *, const uint16_t)
+ad_setdate: int (struct adouble *, unsigned int, uint32_t)
+ad_setfuid: int (const uid_t)
+ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *)
+ad_setname: int (struct adouble *, const char *)
+ad_size: off_t (const struct adouble *, const uint32_t)
+ad_stat: int (const char *, struct stat *)
+ad_testlock: int (struct adouble *, int, const off_t)
+ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_unlock: void (struct adouble *, const int, int)
+ad_valid_header_osx: int (const char *)
+ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t)
+afp_config_free: void (AFPObj *)
+afp_config_parse: int (AFPObj *, char *)
+apply_ip_mask: void (struct sockaddr *, int)
+atalkdict_del: void (dictionary *)
+atalkdict_dump: void (dictionary *, FILE *)
+atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *)
+atalkdict_hash: unsigned int (char *)
+atalkdict_new: dictionary *(int)
+atalkdict_set: int (dictionary *, char *, char *, char *)
+atalkdict_unset: void (dictionary *, char *, char *)
+atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *)
+atalk_iconv_close: int (atalk_iconv_t)
+atalk_iconv_open: atalk_iconv_t (const char *, const char *)
+atalk_iniparser_dump: void (const dictionary *, FILE *)
+atalk_iniparser_dump_ini: void (const dictionary *, FILE *)
+atalk_iniparser_find_entry: int (const dictionary *, const char *)
+atalk_iniparser_freedict: void (dictionary *)
+atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int)
+atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double)
+atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int)
+atalk_iniparser_getnsec: int (const dictionary *)
+atalk_iniparser_getsecname: const char *(const dictionary *, int)
+atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *)
+atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *)
+atalk_iniparser_load: dictionary *(const char *)
+atalk_iniparser_set: int (dictionary *, char *, char *, char *)
+atalk_iniparser_unset: void (dictionary *, char *, char *)
+atalk_register_charset: int (struct charset_functions *)
+balloc: int (bstring, int)
+ballocmin: int (bstring, int)
+basename_safe: const char *(const char *)
+bassign: int (bstring, const_bstring)
+bassignblk: int (bstring, const void *, int)
+bassigncstr: int (bstring, const char *)
+bassignformat: int (bstring, const char *, ...)
+bassigngets: int (bstring, bNgetc, void *, char)
+bassignmidstr: int (bstring, const_bstring, int, int)
+bcatblk: int (bstring, const void *, int)
+bcatcstr: int (bstring, const char *)
+bconcat: int (bstring, const_bstring)
+bconchar: int (bstring, char)
+bcstrfree: int (char *)
+bdelete: int (bstring, int, int)
+bdestroy: int (bstring)
+become_root: void (void)
+bfindreplace: int (bstring, const_bstring, const_bstring, int)
+bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int)
+bformat: bstring (const char *, ...)
+bformata: int (bstring, const char *, ...)
+bfromcstr: bstring (const char *)
+bfromcstralloc: bstring (int, const char *)
+bgetsa: int (bstring, bNgetc, void *, char)
+bgetstream: bstring (bNgetc, void *, char)
+binchr: int (const_bstring, int, const_bstring)
+binchrr: int (const_bstring, int, const_bstring)
+binsert: int (bstring, int, const_bstring, unsigned char)
+binsertch: int (bstring, int, int, unsigned char)
+binstr: int (const_bstring, int, const_bstring)
+binstrcaseless: int (const_bstring, int, const_bstring)
+binstrr: int (const_bstring, int, const_bstring)
+binstrrcaseless: int (const_bstring, int, const_bstring)
+biseq: int (const_bstring, const_bstring)
+biseqcaseless: int (const_bstring, const_bstring)
+biseqcstr: int (const_bstring, const char *)
+biseqcstrcaseless: int (const_bstring, const char *)
+bisstemeqblk: int (const_bstring, const void *, int)
+bisstemeqcaselessblk: int (const_bstring, const void *, int)
+bjoin: bstring (const struct bstrList *, const_bstring)
+bjoinInv: bstring (const struct bstrList *, const_bstring)
+blk2bstr: bstring (const void *, int)
+bltrimws: int (bstring)
+bmidstr: bstring (const_bstring, int, int)
+bninchr: int (const_bstring, int, const_bstring)
+bninchrr: int (const_bstring, int, const_bstring)
+bpattern: int (bstring, int)
+bread: bstring (bNread, void *)
+breada: int (bstring, bNread, void *)
+brefcstr: bstring (char *)
+breplace: int (bstring, int, int, const_bstring, unsigned char)
+brtrimws: int (bstring)
+bsbufflength: int (struct bStream *, int)
+bsclose: void *(struct bStream *)
+bseof: int (const struct bStream *)
+bsetstr: int (bstring, int, const_bstring, unsigned char)
+bsopen: struct bStream *(bNread, void *)
+bspeek: int (bstring, const struct bStream *)
+bsplit: struct bstrList *(const_bstring, unsigned char)
+bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *)
+bsplits: struct bstrList *(const_bstring, const_bstring)
+bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsplitstr: struct bstrList *(const_bstring, const_bstring)
+bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsread: int (bstring, struct bStream *, int)
+bsreada: int (bstring, struct bStream *, int)
+bsreadln: int (bstring, struct bStream *, char)
+bsreadlna: int (bstring, struct bStream *, char)
+bsreadlns: int (bstring, struct bStream *, const_bstring)
+bsreadlnsa: int (bstring, struct bStream *, const_bstring)
+bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bstr2cstr: char *(const_bstring, char)
+bstrchrp: int (const_bstring, int, int)
+bstrcmp: int (const_bstring, const_bstring)
+bstrcpy: bstring (const_bstring)
+bstricmp: int (const_bstring, const_bstring)
+bstrListAlloc: int (struct bstrList *, int)
+bstrListAllocMin: int (struct bstrList *, int)
+bstrListCreate: struct bstrList *(void)
+bstrListCreateMin: struct bstrList *(int)
+bstrListDestroy: int (struct bstrList *)
+bstrListPop: bstring (struct bstrList *)
+bstrListPush: int (struct bstrList *, bstring)
+bstrncmp: int (const_bstring, const_bstring, int)
+bstrnicmp: int (const_bstring, const_bstring, int)
+bstrrchrp: int (const_bstring, int, int)
+bsunread: int (struct bStream *, const_bstring)
+btolower: int (bstring)
+btoupper: int (bstring)
+btrimws: int (bstring)
+btrunc: int (bstring, int)
+bunrefcstr: int (bstring)
+bvcformata: int (bstring, int, const char *, va_list)
+charset_decompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = <mac_centraleurope_pull>, push = <mac_centraleurope_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = <mac_chinese_simp_pull>, push = <mac_chinese_simp_push>, flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0}
+charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = <mac_chinese_trad_pull>, push = <mac_chinese_trad_push>, flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0}
+charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = <mac_cyrillic_pull>, push = <mac_cyrillic_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = <mac_greek_pull>, push = <mac_greek_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = <mac_hebrew_pull>, push = <mac_hebrew_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = <mac_japanese_pull>, push = <mac_japanese_push>, flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0}
+charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = <mac_korean_pull>, push = <mac_korean_push>, flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0}
+charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = <mac_roman_pull>, push = <mac_roman_push>, flags = 21, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = <mac_turkish_pull>, push = <mac_turkish_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_precompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *)
+charset_to_utf8_allocate: size_t (charset_t, char **, const char *)
+charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 22, iname = 0x0, prev = 0x0, next = 0x0}
+charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 27, iname = 0x0, prev = 0x0, next = 0x0}
+check_lockfile: int (const char *, const char *)
+cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *)
+cjk_char_push: size_t (uint16_t, uint8_t *)
+cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t)
+cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t)
+cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *)
+cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t)
+cnid_close: void (struct _cnid_db *)
+cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_close: void (struct _cnid_db *)
+cnid_dbd_delete: int (struct _cnid_db *, const cnid_t)
+cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_wipe: int (struct _cnid_db *)
+cnid_delete: int (struct _cnid_db *, cnid_t)
+cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *)
+cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t)
+cnid_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_init: void (void)
+cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_last_close: void (struct _cnid_db *)
+cnid_last_delete: int (struct _cnid_db *, const cnid_t)
+cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_last_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t)
+cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *, const void *, char *)
+cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t)
+cnid_register: void (struct _cnid_module *)
+cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_tdb_close: void (struct _cnid_db *)
+cnid_tdb_delete: int (struct _cnid_db *, const cnid_t)
+cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12}
+cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t)
+cnid_wipe: int (struct _cnid_db *)
+compare_ip: int (const struct sockaddr *, const struct sockaddr *)
+convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *)
+convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t)
+convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **)
+copy_ea: int (const char *, int, const char *, const char *, mode_t)
+copy_file: int (int, const char *, const char *, mode_t)
+copy_file_fd: int (int, int)
+copy_fork: int (int, struct adouble *, struct adouble *)
+create_lockfile: int (const char *, const char *)
+daemonize: int (int, int)
+dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t)
+dalloc_get: void *(const DALLOC_CTX *, ...)
+dalloc_size: int (DALLOC_CTX *)
+dalloc_strdup: char *(const void *, const char *)
+dalloc_strndup: char *(const void *, const char *, size_t)
+dalloc_value_for_key: void *(const DALLOC_CTX *, ...)
+decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+dequeue: void *(q_t *)
+_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...}
+_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...}
+dir_rx_set: int (mode_t)
+dsi_attention: int (DSI *, AFPUserBytes)
+dsi_close: void (DSI *)
+dsi_cmdreply: int (DSI *, const int)
+dsi_disconnect: int (DSI *)
+dsi_free: void (DSI *)
+dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **)
+dsi_getstatus: void (DSI *)
+dsi_init: DSI *(AFPObj *, const char *, const char *, const char *)
+dsi_opensession: void (DSI *)
+dsi_read: ssize_t (DSI *, void *, const size_t)
+dsi_readdone: void (DSI *)
+dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int)
+dsi_stream_read: size_t (DSI *, void *, const size_t)
+dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int)
+dsi_stream_receive: int (DSI *)
+dsi_stream_send: int (DSI *, void *, size_t)
+dsi_stream_write: ssize_t (DSI *, void *, const size_t, int)
+dsi_tcp_init: int (DSI *, const char *, const char *, const char *)
+dsi_tickle: int (DSI *)
+dsi_write: size_t (DSI *, void *, const size_t)
+dsi_writeflush: void (DSI *)
+dsi_writeinit: size_t (DSI *, void *, const size_t)
+ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chown: int (const struct vol *, const char *, uid_t, gid_t)
+ea_close: int (struct ea *)
+ea_copyfile: int (const struct vol *, int, const char *, const char *)
+ea_deletefile: int (const struct vol *, int, const char *)
+ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *)
+ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *)
+ea_path: char *(const struct ea *, const char *, int)
+ea_renamefile: int (const struct vol *, int, const char *, const char *)
+enqueue: qnode_t *(q_t *, void *)
+fault_setup: void (void (*)(void *))
+fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *)
+fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int)
+find_charset_functions: struct charset_functions *(const char *)
+_fini: <text variable, no debug info>
+free_charset_names: void (void)
+freeifacelist: void (char **)
+fullpathname: const char *(const char *)
+getcwdpath: const char *(void)
+getdefextmap: struct extmap *(void)
+get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+getextmap: struct extmap *(const char *)
+getifacelist: char **(void)
+getip_port: unsigned int (const struct sockaddr *)
+getip_string: const char *(const struct sockaddr *)
+getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *)
+getuuidfromname: int (const char *, uuidtype_t, unsigned char *)
+getvolbyname: struct vol *(const char *)
+getvolbypath: struct vol *(AFPObj *, const char *)
+getvolbyvid: struct vol *(const uint16_t)
+getvolumes: struct vol *(void)
+gmem: int (gid_t, int, gid_t *)
+_init: <text variable, no debug info>
+init_iconv: void (void)
+initline: void (int, char *)
+initvol_vfs: void (struct vol *)
+ipc_child_state: int (AFPObj *, uint16_t)
+ipc_child_write: int (int, uint16_t, int, void *)
+ipc_server_read: int (server_child_t *, int)
+islower_sp: int (uint32_t)
+islower_w: int (uint16_t)
+isupper_sp: int (uint32_t)
+isupper_w: int (uint16_t)
+ldap_auth_dn: 0x0
+ldap_auth_method: 0
+ldap_auth_pw: 0x0
+ldap_config_valid: 0
+ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *)
+ldap_getuuidfromname: int (const char *, uuidtype_t, char **)
+ldap_group_attr: 0x0
+ldap_groupbase: 0x0
+ldap_groupfilter: 0x0
+ldap_groupscope: 0
+ldap_name_attr: 0x0
+ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}}
+ldap_server: 0x0
+ldap_uid_attr: 0x0
+ldap_userbase: 0x0
+ldap_userfilter: 0x0
+ldap_userscope: 0
+ldap_uuid_attr: 0x0
+ldap_uuid_encoding: 0
+ldap_uuid_string: 0x0
+list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+load_charset: int (struct vol *)
+load_volumes: int (AFPObj *, lv_flags_t)
+localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int)
+lock_reg: int (int, int, int, off_t, int, off_t)
+log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' <repeats 15 times>, syslog_facility = 0, syslog_display_options = 0}
+make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...)
+make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t)
+mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *)
+mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *)
+netatalk_panic: void (const char *)
+netatalk_rmdir: int (int, const char *)
+netatalk_rmdir_all_errors: int (int, const char *)
+netatalk_unlink: int (const char *)
+netatalk_unlinkat: int (int, const char *)
+nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int)
+ochdir: int (const char *, int)
+ochmod: int (char *, mode_t, const struct stat *, int)
+ochown: int (const char *, uid_t, gid_t, int)
+opendirat: DIR *(int, const char *)
+openflags2logstr: const char *(int)
+ostat: int (const char *, struct stat *, int)
+ostatat: int (int, const char *, struct stat *, int)
+parseline: int (int, char *)
+posix_chmod: int (const char *, mode_t)
+posix_fchmod: int (int, mode_t)
+precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}}
+prequeue: qnode_t *(q_t *, void *)
+print_groups: const char *(int, gid_t *)
+queue_destroy: void (q_t *, void (*)(void *))
+queue_init: q_t *(void)
+randombytes: void (void *, int)
+readt: ssize_t (int, void *, const size_t, int, int)
+realpath_safe: char *(const char *)
+recv_fd: int (int, int)
+rel_path_in_vol: bstring (const char *, const char *)
+remove_acl_vfs: int (const char *)
+remove_ea: int (const struct vol *, const char *, const char *, int)
+run_cmd: int (const char *, char **)
+search_cachebyname: int (const char *, uuidtype_t *, unsigned char *)
+search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *)
+send_fd: int (int, int)
+server_child_add: afp_child_t *(server_child_t *, pid_t, int)
+server_child_alloc: server_child_t *(int)
+server_child_free: void (server_child_t *)
+server_child_kill: void (server_child_t *, int)
+server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t)
+server_child_remove: int (server_child_t *, pid_t)
+server_child_resolve: afp_child_t *(server_child_t *, id_t)
+server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t)
+server_lock: pid_t (char *, char *, int)
+server_reset_signal: void (void)
+set_charset_name: int (charset_t, const char *)
+set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+setfilmode: int (const struct vol *, const char *, mode_t, struct stat *)
+set_groups: int (AFPObj *, struct passwd *)
+setnonblock: int (int, int)
+set_processname: void (const char *)
+setuplog: void (const char *, const char *)
+statat: int (int, const char *, struct stat *)
+strcasechr_sp: uint16_t *(const uint16_t *, uint32_t)
+strcasechr_w: uint16_t *(const uint16_t *, uint16_t)
+strcasecmp_w: int (const uint16_t *, const uint16_t *)
+strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strcat_w: uint16_t *(uint16_t *, const uint16_t *)
+strchr_w: uint16_t *(const uint16_t *, uint16_t)
+strcmp_w: int (const uint16_t *, const uint16_t *)
+strdiacasecmp: int (const char *, const char *)
+strdup_w: uint16_t *(const uint16_t *)
+stripped_slashes_basename: char *(char *)
+strlcat: size_t (char *, const char *, size_t)
+strlcpy: size_t (char *, const char *, size_t)
+strlen_w: size_t (const uint16_t *)
+strlower_w: int (uint16_t *)
+strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strncmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strndiacasecmp: int (const char *, const char *, size_t)
+strndup_w: uint16_t *(const uint16_t *, size_t)
+strnlen_w: size_t (const uint16_t *, size_t)
+strstr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strtok_quote: char *(char *, const char *)
+strupper_w: int (uint16_t *)
+sys_ea_copyfile: int (const struct vol *, int, const char *, const char *)
+sys_fgetxattr: ssize_t (int, const char *, void *, size_t)
+sys_fsetxattr: int (int, const char *, const void *, size_t, int)
+sys_ftruncate: int (int, off_t)
+sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+sys_getxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_getxattrfd: int (int, const char *, int, ...)
+sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+sys_listxattr: ssize_t (const char *, char *, size_t)
+sys_llistxattr: ssize_t (const char *, char *, size_t)
+sys_lremovexattr: int (const char *, const char *)
+sys_lsetxattr: int (const char *, const char *, const void *, size_t, int)
+sys_remove_ea: int (const struct vol *, const char *, const char *, int)
+sys_removexattr: int (const char *, const char *)
+sys_sendfile: ssize_t (int, int, off_t *, size_t)
+sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+sys_setxattr: int (const char *, const char *, const void *, size_t, int)
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+_talloc_free: int (void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+_talloc_set_destructor: void (const void *, int (*)(void *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *)
+tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t)
+tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_convert: void *(void *, uint32_t)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_expand: int (struct tdb_context *, tdb_off_t)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_io_init: void (struct tdb_context *)
+tdb_lock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_mmap: void (struct tdb_context *)
+tdb_munmap: int (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: {dptr = 0x0, dsize = 0}
+tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_transaction_cancel: int (struct tdb_context *)
+_tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_lock: int (struct tdb_context *, int)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_recover: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_unlock: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_unlock_record: int (struct tdb_context *, tdb_off_t)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
+tdb_write_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t)
+tokenize_ip_port: int (const char *, char **, char **)
+tolower_sp: uint32_t (uint32_t)
+tolower_w: uint16_t (uint16_t)
+toupper_sp: uint32_t (uint32_t)
+toupper_w: uint16_t (uint16_t)
+type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}}
+ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t)
+ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *)
+unbecome_root: void (void)
+unix_rename: int (int, const char *, int, const char *)
+unix_strlower: size_t (const char *, size_t, char *, size_t)
+unix_strupper: size_t (const char *, size_t, char *, size_t)
+unload_volumes: void (AFPObj *)
+utf8_charlen: size_t (char *)
+utf8_decompose: size_t (char *, size_t, char *, size_t)
+utf8_precompose: size_t (char *, size_t, char *, size_t)
+utf8_strlen_validate: size_t (char *)
+utf8_strlower: size_t (const char *, size_t, char *, size_t)
+utf8_strupper: size_t (const char *, size_t, char *, size_t)
+utf8_to_charset_allocate: size_t (charset_t, char **, const char *)
+uuid_bin2string: const char *(const unsigned char *)
+uuidcache_dump: void (void)
+uuid_string2bin: void (const char *, unsigned char *)
+uuidtype: {"", "USER", "GROUP", "LOCAL"}
+volume_free: void (struct vol *)
+volume_unlink: void (struct vol *)
+writet: ssize_t (int, void *, const size_t, int, int)
diff --git a/libatalk/libatalk-3.1.2.abi b/libatalk/libatalk-3.1.2.abi
new file mode 100644 (file)
index 0000000..4535bbc
--- /dev/null
@@ -0,0 +1,639 @@
+acl_ldap_freeconfig: void (void)
+acl_ldap_readconfig: int (dictionary *)
+ad_close: int (struct adouble *, int)
+ad_convert: int (const char *, const struct stat *, const struct vol *, const char **)
+ad_copy_header: int (struct adouble *, struct adouble *)
+add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const long unsigned int)
+add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const long unsigned int)
+add_charset: charset_t (const char *)
+ad_dir: char *(const char *)
+ad_dtruncate: int (struct adouble *, const off_t)
+adflags2logstr: const char *(int)
+ad_flush: int (struct adouble *)
+ad_forcegetid: uint32_t (struct adouble *)
+adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t)
+adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t)
+ad_getattr: int (const struct adouble *, uint16_t *)
+ad_getdate: int (const struct adouble *, unsigned int, uint32_t *)
+ad_getentryoff: off_t (const struct adouble *, int)
+ad_getfuid: uid_t (void)
+ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *)
+ad_hf_mode: mode_t (mode_t)
+ad_init: void (struct adouble *, const struct vol *)
+ad_init_offsets: int (struct adouble *)
+ad_init_old: void (struct adouble *, int, int)
+ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_metadata: int (const char *, int, struct adouble *)
+ad_metadataat: int (int, const char *, int, struct adouble *)
+ad_mkdir: int (const char *, mode_t)
+ad_mode: int (const char *, mode_t)
+ad_open: int (struct adouble *, const char *, int, ...)
+ad_openat: int (struct adouble *, int, const char *, int, ...)
+ad_openforks: uint16_t (struct adouble *, uint16_t)
+ad_path: const char *(const char *, int)
+ad_path_ea: const char *(const char *, int)
+ad_path_osx: const char *(const char *, int)
+ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t)
+ad_readfile_init: int (const struct adouble *, const int, off_t *, const int)
+ad_rebuild_adouble_header_ea: int (struct adouble *)
+ad_rebuild_adouble_header_osx: int (struct adouble *, char *)
+ad_rebuild_adouble_header_v2: int (struct adouble *)
+ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int)
+ad_refresh: int (const char *, struct adouble *)
+ad_reso_size: off_t (const char *, int, struct adouble *)
+ad_rtruncate: int (struct adouble *, const char *, const off_t)
+ad_setattr: int (const struct adouble *, const uint16_t)
+ad_setdate: int (struct adouble *, unsigned int, uint32_t)
+ad_setfuid: int (const uid_t)
+ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *)
+ad_setname: int (struct adouble *, const char *)
+ad_size: off_t (const struct adouble *, const uint32_t)
+ad_stat: int (const char *, struct stat *)
+ad_testlock: int (struct adouble *, int, const off_t)
+ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_unlock: void (struct adouble *, const int, int)
+ad_valid_header_osx: int (const char *)
+ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t)
+afp_config_free: void (AFPObj *)
+afp_config_parse: int (AFPObj *, char *)
+apply_ip_mask: void (struct sockaddr *, int)
+atalkdict_del: void (dictionary *)
+atalkdict_dump: void (dictionary *, FILE *)
+atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *)
+atalkdict_hash: unsigned int (char *)
+atalkdict_new: dictionary *(int)
+atalkdict_set: int (dictionary *, char *, char *, char *)
+atalkdict_unset: void (dictionary *, char *, char *)
+atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *)
+atalk_iconv_close: int (atalk_iconv_t)
+atalk_iconv_open: atalk_iconv_t (const char *, const char *)
+atalk_iniparser_dump: void (const dictionary *, FILE *)
+atalk_iniparser_dump_ini: void (const dictionary *, FILE *)
+atalk_iniparser_find_entry: int (const dictionary *, const char *)
+atalk_iniparser_freedict: void (dictionary *)
+atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int)
+atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double)
+atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int)
+atalk_iniparser_getnsec: int (const dictionary *)
+atalk_iniparser_getsecname: const char *(const dictionary *, int)
+atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *)
+atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *)
+atalk_iniparser_load: dictionary *(const char *)
+atalk_iniparser_set: int (dictionary *, char *, char *, char *)
+atalk_iniparser_unset: void (dictionary *, char *, char *)
+atalk_register_charset: int (struct charset_functions *)
+balloc: int (bstring, int)
+ballocmin: int (bstring, int)
+basename_safe: const char *(const char *)
+bassign: int (bstring, const_bstring)
+bassignblk: int (bstring, const void *, int)
+bassigncstr: int (bstring, const char *)
+bassignformat: int (bstring, const char *, ...)
+bassigngets: int (bstring, bNgetc, void *, char)
+bassignmidstr: int (bstring, const_bstring, int, int)
+bcatblk: int (bstring, const void *, int)
+bcatcstr: int (bstring, const char *)
+bconcat: int (bstring, const_bstring)
+bconchar: int (bstring, char)
+bcstrfree: int (char *)
+bdelete: int (bstring, int, int)
+bdestroy: int (bstring)
+become_root: void (void)
+bfindreplace: int (bstring, const_bstring, const_bstring, int)
+bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int)
+bformat: bstring (const char *, ...)
+bformata: int (bstring, const char *, ...)
+bfromcstr: bstring (const char *)
+bfromcstralloc: bstring (int, const char *)
+bgetsa: int (bstring, bNgetc, void *, char)
+bgetstream: bstring (bNgetc, void *, char)
+binchr: int (const_bstring, int, const_bstring)
+binchrr: int (const_bstring, int, const_bstring)
+binsert: int (bstring, int, const_bstring, unsigned char)
+binsertch: int (bstring, int, int, unsigned char)
+binstr: int (const_bstring, int, const_bstring)
+binstrcaseless: int (const_bstring, int, const_bstring)
+binstrr: int (const_bstring, int, const_bstring)
+binstrrcaseless: int (const_bstring, int, const_bstring)
+biseq: int (const_bstring, const_bstring)
+biseqcaseless: int (const_bstring, const_bstring)
+biseqcstr: int (const_bstring, const char *)
+biseqcstrcaseless: int (const_bstring, const char *)
+bisstemeqblk: int (const_bstring, const void *, int)
+bisstemeqcaselessblk: int (const_bstring, const void *, int)
+bjoin: bstring (const struct bstrList *, const_bstring)
+bjoinInv: bstring (const struct bstrList *, const_bstring)
+blk2bstr: bstring (const void *, int)
+bltrimws: int (bstring)
+bmidstr: bstring (const_bstring, int, int)
+bninchr: int (const_bstring, int, const_bstring)
+bninchrr: int (const_bstring, int, const_bstring)
+bpattern: int (bstring, int)
+bread: bstring (bNread, void *)
+breada: int (bstring, bNread, void *)
+brefcstr: bstring (char *)
+breplace: int (bstring, int, int, const_bstring, unsigned char)
+brtrimws: int (bstring)
+bsbufflength: int (struct bStream *, int)
+bsclose: void *(struct bStream *)
+bseof: int (const struct bStream *)
+bsetstr: int (bstring, int, const_bstring, unsigned char)
+bsopen: struct bStream *(bNread, void *)
+bspeek: int (bstring, const struct bStream *)
+bsplit: struct bstrList *(const_bstring, unsigned char)
+bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *)
+bsplits: struct bstrList *(const_bstring, const_bstring)
+bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsplitstr: struct bstrList *(const_bstring, const_bstring)
+bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsread: int (bstring, struct bStream *, int)
+bsreada: int (bstring, struct bStream *, int)
+bsreadln: int (bstring, struct bStream *, char)
+bsreadlna: int (bstring, struct bStream *, char)
+bsreadlns: int (bstring, struct bStream *, const_bstring)
+bsreadlnsa: int (bstring, struct bStream *, const_bstring)
+bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bstr2cstr: char *(const_bstring, char)
+bstrchrp: int (const_bstring, int, int)
+bstrcmp: int (const_bstring, const_bstring)
+bstrcpy: bstring (const_bstring)
+bstricmp: int (const_bstring, const_bstring)
+bstrListAlloc: int (struct bstrList *, int)
+bstrListAllocMin: int (struct bstrList *, int)
+bstrListCreate: struct bstrList *(void)
+bstrListCreateMin: struct bstrList *(int)
+bstrListDestroy: int (struct bstrList *)
+bstrListPop: bstring (struct bstrList *)
+bstrListPush: int (struct bstrList *, bstring)
+bstrncmp: int (const_bstring, const_bstring, int)
+bstrnicmp: int (const_bstring, const_bstring, int)
+bstrrchrp: int (const_bstring, int, int)
+bsunread: int (struct bStream *, const_bstring)
+btolower: int (bstring)
+btoupper: int (bstring)
+btrimws: int (bstring)
+btrunc: int (bstring, int)
+bunrefcstr: int (bstring)
+bvcformata: int (bstring, int, const char *, va_list)
+charset_decompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = <mac_centraleurope_pull>, push = <mac_centraleurope_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = <mac_chinese_simp_pull>, push = <mac_chinese_simp_push>, flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0}
+charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = <mac_chinese_trad_pull>, push = <mac_chinese_trad_push>, flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0}
+charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = <mac_cyrillic_pull>, push = <mac_cyrillic_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = <mac_greek_pull>, push = <mac_greek_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = <mac_hebrew_pull>, push = <mac_hebrew_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = <mac_japanese_pull>, push = <mac_japanese_push>, flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0}
+charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = <mac_korean_pull>, push = <mac_korean_push>, flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0}
+charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = <mac_roman_pull>, push = <mac_roman_push>, flags = 21, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = <mac_turkish_pull>, push = <mac_turkish_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_precompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *)
+charset_to_utf8_allocate: size_t (charset_t, char **, const char *)
+charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 22, iname = 0x0, prev = 0x0, next = 0x0}
+charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 27, iname = 0x0, prev = 0x0, next = 0x0}
+check_lockfile: int (const char *, const char *)
+cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *)
+cjk_char_push: size_t (uint16_t, uint8_t *)
+cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t)
+cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t)
+cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *)
+cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t)
+cnid_close: void (struct _cnid_db *)
+cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_close: void (struct _cnid_db *)
+cnid_dbd_delete: int (struct _cnid_db *, const cnid_t)
+cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_wipe: int (struct _cnid_db *)
+cnid_delete: int (struct _cnid_db *, cnid_t)
+cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *)
+cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t)
+cnid_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_init: void (void)
+cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_last_close: void (struct _cnid_db *)
+cnid_last_delete: int (struct _cnid_db *, const cnid_t)
+cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_last_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t)
+cnid_open: struct _cnid_db *(struct vol *, char *, int)
+cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t)
+cnid_register: void (struct _cnid_module *)
+cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_tdb_close: void (struct _cnid_db *)
+cnid_tdb_delete: int (struct _cnid_db *, const cnid_t)
+cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12}
+cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t)
+cnid_wipe: int (struct _cnid_db *)
+compare_ip: int (const struct sockaddr *, const struct sockaddr *)
+convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *)
+convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t)
+convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **)
+copy_ea: int (const char *, int, const char *, const char *, mode_t)
+copy_file: int (int, const char *, const char *, mode_t)
+copy_file_fd: int (int, int)
+copy_fork: int (int, struct adouble *, struct adouble *)
+create_lockfile: int (const char *, const char *)
+daemonize: int (int, int)
+dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t)
+dalloc_get: void *(const DALLOC_CTX *, ...)
+dalloc_size: int (DALLOC_CTX *)
+dalloc_strdup: char *(const void *, const char *)
+dalloc_strndup: char *(const void *, const char *, size_t)
+dalloc_value_for_key: void *(const DALLOC_CTX *, ...)
+decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+dequeue: void *(q_t *)
+_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...}
+_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...}
+dir_rx_set: int (mode_t)
+dsi_attention: int (DSI *, AFPUserBytes)
+dsi_close: void (DSI *)
+dsi_cmdreply: int (DSI *, const int)
+dsi_disconnect: int (DSI *)
+dsi_free: void (DSI *)
+dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **)
+dsi_getstatus: void (DSI *)
+dsi_init: DSI *(AFPObj *, const char *, const char *, const char *)
+dsi_opensession: void (DSI *)
+dsi_read: ssize_t (DSI *, void *, const size_t)
+dsi_readdone: void (DSI *)
+dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int)
+dsi_stream_read: size_t (DSI *, void *, const size_t)
+dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int)
+dsi_stream_receive: int (DSI *)
+dsi_stream_send: int (DSI *, void *, size_t)
+dsi_stream_write: ssize_t (DSI *, void *, const size_t, int)
+dsi_tcp_init: int (DSI *, const char *, const char *, const char *)
+dsi_tickle: int (DSI *)
+dsi_write: size_t (DSI *, void *, const size_t)
+dsi_writeflush: void (DSI *)
+dsi_writeinit: size_t (DSI *, void *, const size_t)
+ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chown: int (const struct vol *, const char *, uid_t, gid_t)
+ea_close: int (struct ea *)
+ea_copyfile: int (const struct vol *, int, const char *, const char *)
+ea_deletefile: int (const struct vol *, int, const char *)
+ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *)
+ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *)
+ea_path: char *(const struct ea *, const char *, int)
+ea_renamefile: int (const struct vol *, int, const char *, const char *)
+enqueue: qnode_t *(q_t *, void *)
+fault_setup: void (void (*)(void *))
+fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *)
+fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int)
+find_charset_functions: struct charset_functions *(const char *)
+_fini: <text variable, no debug info>
+free_charset_names: void (void)
+freeifacelist: void (char **)
+fullpathname: const char *(const char *)
+getcwdpath: const char *(void)
+getdefextmap: struct extmap *(void)
+get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+getextmap: struct extmap *(const char *)
+getifacelist: char **(void)
+getip_port: unsigned int (const struct sockaddr *)
+getip_string: const char *(const struct sockaddr *)
+getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *)
+getuuidfromname: int (const char *, uuidtype_t, unsigned char *)
+getvolbyname: struct vol *(const char *)
+getvolbypath: struct vol *(AFPObj *, const char *)
+getvolbyvid: struct vol *(const uint16_t)
+getvolumes: struct vol *(void)
+gmem: int (gid_t, int, gid_t *)
+_init: <text variable, no debug info>
+init_iconv: void (void)
+initline: void (int, char *)
+initvol_vfs: void (struct vol *)
+ipc_child_state: int (AFPObj *, uint16_t)
+ipc_child_write: int (int, uint16_t, int, void *)
+ipc_server_read: int (server_child_t *, int)
+islower_sp: int (uint32_t)
+islower_w: int (uint16_t)
+isupper_sp: int (uint32_t)
+isupper_w: int (uint16_t)
+ldap_auth_dn: 0x0
+ldap_auth_method: 0
+ldap_auth_pw: 0x0
+ldap_config_valid: 0
+ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *)
+ldap_getuuidfromname: int (const char *, uuidtype_t, char **)
+ldap_group_attr: 0x0
+ldap_groupbase: 0x0
+ldap_groupfilter: 0x0
+ldap_groupscope: 0
+ldap_name_attr: 0x0
+ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}}
+ldap_server: 0x0
+ldap_uid_attr: 0x0
+ldap_userbase: 0x0
+ldap_userfilter: 0x0
+ldap_userscope: 0
+ldap_uuid_attr: 0x0
+ldap_uuid_encoding: 0
+ldap_uuid_string: 0x0
+list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+load_charset: int (struct vol *)
+load_volumes: int (AFPObj *, lv_flags_t)
+localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int)
+lock_reg: int (int, int, int, off_t, int, off_t)
+log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' <repeats 15 times>, syslog_facility = 0, syslog_display_options = 0}
+make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...)
+make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t)
+mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *)
+mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *)
+netatalk_panic: void (const char *)
+netatalk_rmdir: int (int, const char *)
+netatalk_rmdir_all_errors: int (int, const char *)
+netatalk_unlink: int (const char *)
+netatalk_unlinkat: int (int, const char *)
+nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int)
+ochdir: int (const char *, int)
+ochmod: int (char *, mode_t, const struct stat *, int)
+ochown: int (const char *, uid_t, gid_t, int)
+opendirat: DIR *(int, const char *)
+openflags2logstr: const char *(int)
+ostat: int (const char *, struct stat *, int)
+ostatat: int (int, const char *, struct stat *, int)
+parseline: int (int, char *)
+posix_chmod: int (const char *, mode_t)
+posix_fchmod: int (int, mode_t)
+precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}}
+prequeue: qnode_t *(q_t *, void *)
+print_groups: const char *(int, gid_t *)
+queue_destroy: void (q_t *, void (*)(void *))
+queue_init: q_t *(void)
+randombytes: void (void *, int)
+readt: ssize_t (int, void *, const size_t, int, int)
+realpath_safe: char *(const char *)
+recv_fd: int (int, int)
+rel_path_in_vol: bstring (const char *, const char *)
+remove_acl_vfs: int (const char *)
+remove_ea: int (const struct vol *, const char *, const char *, int)
+run_cmd: int (const char *, char **)
+search_cachebyname: int (const char *, uuidtype_t *, unsigned char *)
+search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *)
+send_fd: int (int, int)
+server_child_add: afp_child_t *(server_child_t *, pid_t, int)
+server_child_alloc: server_child_t *(int)
+server_child_free: void (server_child_t *)
+server_child_kill: void (server_child_t *, int)
+server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t)
+server_child_remove: int (server_child_t *, pid_t)
+server_child_resolve: afp_child_t *(server_child_t *, id_t)
+server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t)
+server_lock: pid_t (char *, char *, int)
+server_reset_signal: void (void)
+set_charset_name: int (charset_t, const char *)
+set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+setfilmode: int (const struct vol *, const char *, mode_t, struct stat *)
+set_groups: int (AFPObj *, struct passwd *)
+setnonblock: int (int, int)
+set_processname: void (const char *)
+setuplog: void (const char *, const char *)
+statat: int (int, const char *, struct stat *)
+strcasechr_sp: uint16_t *(const uint16_t *, uint32_t)
+strcasechr_w: uint16_t *(const uint16_t *, uint16_t)
+strcasecmp_w: int (const uint16_t *, const uint16_t *)
+strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strcat_w: uint16_t *(uint16_t *, const uint16_t *)
+strchr_w: uint16_t *(const uint16_t *, uint16_t)
+strcmp_w: int (const uint16_t *, const uint16_t *)
+strdiacasecmp: int (const char *, const char *)
+strdup_w: uint16_t *(const uint16_t *)
+stripped_slashes_basename: char *(char *)
+strlcat: size_t (char *, const char *, size_t)
+strlcpy: size_t (char *, const char *, size_t)
+strlen_w: size_t (const uint16_t *)
+strlower_w: int (uint16_t *)
+strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strncmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strndiacasecmp: int (const char *, const char *, size_t)
+strndup_w: uint16_t *(const uint16_t *, size_t)
+strnlen_w: size_t (const uint16_t *, size_t)
+strstr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strtok_quote: char *(char *, const char *)
+strupper_w: int (uint16_t *)
+sys_ea_copyfile: int (const struct vol *, int, const char *, const char *)
+sys_fgetxattr: ssize_t (int, const char *, void *, size_t)
+sys_fsetxattr: int (int, const char *, const void *, size_t, int)
+sys_ftruncate: int (int, off_t)
+sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+sys_getxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_getxattrfd: int (int, const char *, int, ...)
+sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+sys_listxattr: ssize_t (const char *, char *, size_t)
+sys_llistxattr: ssize_t (const char *, char *, size_t)
+sys_lremovexattr: int (const char *, const char *)
+sys_lsetxattr: int (const char *, const char *, const void *, size_t, int)
+sys_remove_ea: int (const struct vol *, const char *, const char *, int)
+sys_removexattr: int (const char *, const char *)
+sys_sendfile: ssize_t (int, int, off_t *, size_t)
+sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+sys_setxattr: int (const char *, const char *, const void *, size_t, int)
+_talloc: void *(const void *, size_t)
+_talloc_array: void *(const void *, size_t, unsigned int, const char *)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+_talloc_free: int (void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+_talloc_get_type_abort: void *(const void *, const char *, const char *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+_talloc_memdup: void *(const void *, const void *, size_t, const char *)
+_talloc_move: void *(const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+_talloc_realloc: void *(const void *, void *, size_t, const char *)
+_talloc_realloc_array: void *(const void *, void *, size_t, unsigned int, const char *)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+_talloc_reference_loc: void *(const void *, const void *, const char *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+_talloc_set_destructor: void (const void *, int (*)(void *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+_talloc_steal_loc: void *(const void *, const void *, const char *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, va_list)
+talloc_vasprintf_append: char *(char *, const char *, va_list)
+talloc_vasprintf_append_buffer: char *(char *, const char *, va_list)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
+_talloc_zero: void *(const void *, size_t, const char *)
+_talloc_zero_array: void *(const void *, size_t, unsigned int, const char *)
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *)
+tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t)
+tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_convert: void *(void *, uint32_t)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_expand: int (struct tdb_context *, tdb_off_t)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_io_init: void (struct tdb_context *)
+tdb_lock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_mmap: void (struct tdb_context *)
+tdb_munmap: int (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: {dptr = 0x0, dsize = 0}
+tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_transaction_cancel: int (struct tdb_context *)
+_tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_lock: int (struct tdb_context *, int)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_recover: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_unlock: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_unlock_record: int (struct tdb_context *, tdb_off_t)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
+tdb_write_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t)
+tokenize_ip_port: int (const char *, char **, char **)
+tolower_sp: uint32_t (uint32_t)
+tolower_w: uint16_t (uint16_t)
+toupper_sp: uint32_t (uint32_t)
+toupper_w: uint16_t (uint16_t)
+type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}}
+ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t)
+ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *)
+unbecome_root: void (void)
+unix_rename: int (int, const char *, int, const char *)
+unix_strlower: size_t (const char *, size_t, char *, size_t)
+unix_strupper: size_t (const char *, size_t, char *, size_t)
+unload_volumes: void (AFPObj *)
+utf8_charlen: size_t (char *)
+utf8_decompose: size_t (char *, size_t, char *, size_t)
+utf8_precompose: size_t (char *, size_t, char *, size_t)
+utf8_strlen_validate: size_t (char *)
+utf8_strlower: size_t (const char *, size_t, char *, size_t)
+utf8_strupper: size_t (const char *, size_t, char *, size_t)
+utf8_to_charset_allocate: size_t (charset_t, char **, const char *)
+uuid_bin2string: const char *(const unsigned char *)
+uuidcache_dump: void (void)
+uuid_string2bin: void (const char *, unsigned char *)
+uuidtype: {"", "USER", "GROUP", "LOCAL"}
+volume_free: void (struct vol *)
+volume_unlink: void (struct vol *)
+writet: ssize_t (int, void *, const size_t, int, int)
diff --git a/libatalk/libatalk-3.1.3.abi b/libatalk/libatalk-3.1.3.abi
new file mode 100644 (file)
index 0000000..9cc45db
--- /dev/null
@@ -0,0 +1,634 @@
+acl_ldap_freeconfig: void (void)
+acl_ldap_readconfig: int (dictionary *)
+ad_close: int (struct adouble *, int)
+ad_convert: int (const char *, const struct stat *, const struct vol *, const char **)
+ad_copy_header: int (struct adouble *, struct adouble *)
+add_cachebyname: int (const char *, const uuidp_t, const uuidtype_t, const unsigned long)
+add_cachebyuuid: int (uuidp_t, const char *, uuidtype_t, const unsigned long)
+add_charset: charset_t (const char *)
+ad_dir: char *(const char *)
+ad_dtruncate: int (struct adouble *, const off_t)
+adflags2logstr: const char *(int)
+ad_flush: int (struct adouble *)
+ad_forcegetid: uint32_t (struct adouble *)
+adf_pread: ssize_t (struct ad_fd *, void *, size_t, off_t)
+adf_pwrite: ssize_t (struct ad_fd *, const void *, size_t, off_t)
+ad_getattr: int (const struct adouble *, uint16_t *)
+ad_getdate: int (const struct adouble *, unsigned int, uint32_t *)
+ad_getentryoff: off_t (const struct adouble *, int)
+ad_getfuid: uid_t (void)
+ad_getid: uint32_t (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *)
+ad_hf_mode: mode_t (mode_t)
+ad_init: void (struct adouble *, const struct vol *)
+ad_init_offsets: int (struct adouble *)
+ad_init_old: void (struct adouble *, int, int)
+ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_metadata: int (const char *, int, struct adouble *)
+ad_metadataat: int (int, const char *, int, struct adouble *)
+ad_mkdir: int (const char *, mode_t)
+ad_mode: int (const char *, mode_t)
+ad_open: int (struct adouble *, const char *, int, ...)
+ad_openat: int (struct adouble *, int, const char *, int, ...)
+ad_openforks: uint16_t (struct adouble *, uint16_t)
+ad_path: const char *(const char *, int)
+ad_path_ea: const char *(const char *, int)
+ad_path_osx: const char *(const char *, int)
+ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t)
+ad_readfile_init: int (const struct adouble *, const int, off_t *, const int)
+ad_rebuild_adouble_header_ea: int (struct adouble *)
+ad_rebuild_adouble_header_osx: int (struct adouble *, char *)
+ad_rebuild_adouble_header_v2: int (struct adouble *)
+ad_recvfile: ssize_t (struct adouble *, int, int, off_t, size_t, int)
+ad_refresh: int (const char *, struct adouble *)
+ad_reso_size: off_t (const char *, int, struct adouble *)
+ad_rtruncate: int (struct adouble *, const char *, const off_t)
+ad_setattr: int (const struct adouble *, const uint16_t)
+ad_setdate: int (struct adouble *, unsigned int, uint32_t)
+ad_setfuid: int (const uid_t)
+ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *)
+ad_setname: int (struct adouble *, const char *)
+ad_size: off_t (const struct adouble *, const uint32_t)
+ad_stat: int (const char *, struct stat *)
+ad_testlock: int (struct adouble *, int, const off_t)
+ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_unlock: void (struct adouble *, const int, int)
+ad_valid_header_osx: int (const char *)
+ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t)
+afp_config_free: void (AFPObj *)
+afp_config_parse: int (AFPObj *, char *)
+apply_ip_mask: void (struct sockaddr *, int)
+atalkdict_del: void (dictionary *)
+atalkdict_dump: void (dictionary *, FILE *)
+atalkdict_get: const char *(const dictionary *, const char *, const char *, const char *)
+atalkdict_hash: unsigned int (char *)
+atalkdict_new: dictionary *(int)
+atalkdict_set: int (dictionary *, char *, char *, char *)
+atalkdict_unset: void (dictionary *, char *, char *)
+atalk_iconv: size_t (atalk_iconv_t, const char **, size_t *, char **, size_t *)
+atalk_iconv_close: int (atalk_iconv_t)
+atalk_iconv_open: atalk_iconv_t (const char *, const char *)
+atalk_iniparser_dump: void (const dictionary *, FILE *)
+atalk_iniparser_dump_ini: void (const dictionary *, FILE *)
+atalk_iniparser_find_entry: int (const dictionary *, const char *)
+atalk_iniparser_freedict: void (dictionary *)
+atalk_iniparser_getboolean: int (const dictionary *, const char *, const char *, int)
+atalk_iniparser_getdouble: double (const dictionary *, const char *, const char *, double)
+atalk_iniparser_getint: int (const dictionary *, const char *, const char *, int)
+atalk_iniparser_getnsec: int (const dictionary *)
+atalk_iniparser_getsecname: const char *(const dictionary *, int)
+atalk_iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *)
+atalk_iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *)
+atalk_iniparser_load: dictionary *(const char *)
+atalk_iniparser_set: int (dictionary *, char *, char *, char *)
+atalk_iniparser_unset: void (dictionary *, char *, char *)
+atalk_register_charset: int (struct charset_functions *)
+balloc: int (bstring, int)
+ballocmin: int (bstring, int)
+basename_safe: const char *(const char *)
+bassign: int (bstring, const_bstring)
+bassignblk: int (bstring, const void *, int)
+bassigncstr: int (bstring, const char *)
+bassignformat: int (bstring, const char *, ...)
+bassigngets: int (bstring, bNgetc, void *, char)
+bassignmidstr: int (bstring, const_bstring, int, int)
+bcatblk: int (bstring, const void *, int)
+bcatcstr: int (bstring, const char *)
+bconcat: int (bstring, const_bstring)
+bconchar: int (bstring, char)
+bcstrfree: int (char *)
+bdelete: int (bstring, int, int)
+bdestroy: int (bstring)
+become_root: void (void)
+bfindreplace: int (bstring, const_bstring, const_bstring, int)
+bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int)
+bformat: bstring (const char *, ...)
+bformata: int (bstring, const char *, ...)
+bfromcstr: bstring (const char *)
+bfromcstralloc: bstring (int, const char *)
+bgetsa: int (bstring, bNgetc, void *, char)
+bgetstream: bstring (bNgetc, void *, char)
+binchr: int (const_bstring, int, const_bstring)
+binchrr: int (const_bstring, int, const_bstring)
+binsert: int (bstring, int, const_bstring, unsigned char)
+binsertch: int (bstring, int, int, unsigned char)
+binstr: int (const_bstring, int, const_bstring)
+binstrcaseless: int (const_bstring, int, const_bstring)
+binstrr: int (const_bstring, int, const_bstring)
+binstrrcaseless: int (const_bstring, int, const_bstring)
+biseq: int (const_bstring, const_bstring)
+biseqcaseless: int (const_bstring, const_bstring)
+biseqcstr: int (const_bstring, const char *)
+biseqcstrcaseless: int (const_bstring, const char *)
+bisstemeqblk: int (const_bstring, const void *, int)
+bisstemeqcaselessblk: int (const_bstring, const void *, int)
+bjoin: bstring (const struct bstrList *, const_bstring)
+bjoinInv: bstring (const struct bstrList *, const_bstring)
+blk2bstr: bstring (const void *, int)
+bltrimws: int (bstring)
+bmidstr: bstring (const_bstring, int, int)
+bninchr: int (const_bstring, int, const_bstring)
+bninchrr: int (const_bstring, int, const_bstring)
+bpattern: int (bstring, int)
+bread: bstring (bNread, void *)
+breada: int (bstring, bNread, void *)
+brefcstr: bstring (char *)
+breplace: int (bstring, int, int, const_bstring, unsigned char)
+brtrimws: int (bstring)
+bsbufflength: int (struct bStream *, int)
+bsclose: void *(struct bStream *)
+bseof: int (const struct bStream *)
+bsetstr: int (bstring, int, const_bstring, unsigned char)
+bsopen: struct bStream *(bNread, void *)
+bspeek: int (bstring, const struct bStream *)
+bsplit: struct bstrList *(const_bstring, unsigned char)
+bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *)
+bsplits: struct bstrList *(const_bstring, const_bstring)
+bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsplitstr: struct bstrList *(const_bstring, const_bstring)
+bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsread: int (bstring, struct bStream *, int)
+bsreada: int (bstring, struct bStream *, int)
+bsreadln: int (bstring, struct bStream *, char)
+bsreadlna: int (bstring, struct bStream *, char)
+bsreadlns: int (bstring, struct bStream *, const_bstring)
+bsreadlnsa: int (bstring, struct bStream *, const_bstring)
+bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bstr2cstr: char *(const_bstring, char)
+bstrchrp: int (const_bstring, int, int)
+bstrcmp: int (const_bstring, const_bstring)
+bstrcpy: bstring (const_bstring)
+bstricmp: int (const_bstring, const_bstring)
+bstrListAlloc: int (struct bstrList *, int)
+bstrListAllocMin: int (struct bstrList *, int)
+bstrListCreate: struct bstrList *(void)
+bstrListCreateMin: struct bstrList *(int)
+bstrListDestroy: int (struct bstrList *)
+bstrListPop: bstring (struct bstrList *)
+bstrListPush: int (struct bstrList *, bstring)
+bstrncmp: int (const_bstring, const_bstring, int)
+bstrnicmp: int (const_bstring, const_bstring, int)
+bstrrchrp: int (const_bstring, int, int)
+bsunread: int (struct bStream *, const_bstring)
+btolower: int (bstring)
+btoupper: int (bstring)
+btrimws: int (bstring)
+btrunc: int (bstring, int)
+bunrefcstr: int (bstring)
+bvcformata: int (bstring, int, const char *, struct __va_list_tag *)
+charset_decompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = <mac_centraleurope_pull>, push = <mac_centraleurope_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = <mac_chinese_simp_pull>, push = <mac_chinese_simp_push>, flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0}
+charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = <mac_chinese_trad_pull>, push = <mac_chinese_trad_push>, flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0}
+charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = <mac_cyrillic_pull>, push = <mac_cyrillic_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = <mac_greek_pull>, push = <mac_greek_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = <mac_hebrew_pull>, push = <mac_hebrew_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = <mac_japanese_pull>, push = <mac_japanese_push>, flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0}
+charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = <mac_korean_pull>, push = <mac_korean_push>, flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0}
+charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = <mac_roman_pull>, push = <mac_roman_push>, flags = 21, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = <mac_turkish_pull>, push = <mac_turkish_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_precompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *)
+charset_to_utf8_allocate: size_t (charset_t, char **, const char *)
+charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 22, iname = 0x0, prev = 0x0, next = 0x0}
+charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 27, iname = 0x0, prev = 0x0, next = 0x0}
+check_lockfile: int (const char *, const char *)
+cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *)
+cjk_char_push: size_t (uint16_t, uint8_t *)
+cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t)
+cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t)
+cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *)
+cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t)
+cnid_close: void (struct _cnid_db *)
+cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_close: void (struct _cnid_db *)
+cnid_dbd_delete: int (struct _cnid_db *, const cnid_t)
+cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0}
+cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_wipe: int (struct _cnid_db *)
+cnid_delete: int (struct _cnid_db *, cnid_t)
+cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_for_path: cnid_t (struct _cnid_db *, const char *, const char *, cnid_t *)
+cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t)
+cnid_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_init: void (void)
+cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_last_close: void (struct _cnid_db *)
+cnid_last_delete: int (struct _cnid_db *, const cnid_t)
+cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0}
+cnid_last_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t)
+cnid_mysql_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_mysql_close: void (struct _cnid_db *)
+cnid_mysql_delete: int (struct _cnid_db *, const cnid_t)
+cnid_mysql_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_mysql_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_mysql_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_mysql_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_mysql_module: {name = "mysql", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 0}
+cnid_mysql_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_mysql_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_mysql_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_mysql_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_mysql_wipe: int (struct _cnid_db *)
+cnid_open: struct _cnid_db *(struct vol *, char *, int)
+cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t)
+cnid_register: void (struct _cnid_module *)
+cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_tdb_close: void (struct _cnid_db *)
+cnid_tdb_delete: int (struct _cnid_db *, const cnid_t)
+cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0x0, flags = 12}
+cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t)
+cnid_wipe: int (struct _cnid_db *)
+compare_ip: int (const struct sockaddr *, const struct sockaddr *)
+convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *)
+convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t)
+convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **)
+copy_ea: int (const char *, int, const char *, const char *, mode_t)
+copy_file: int (int, const char *, const char *, mode_t)
+copy_file_fd: int (int, int)
+copy_fork: int (int, struct adouble *, struct adouble *)
+create_lockfile: int (const char *, const char *)
+daemonize: int (int, int)
+dalloc_add_talloc_chunk: int (DALLOC_CTX *, void *, void *, size_t)
+dalloc_get: void *(const DALLOC_CTX *, ...)
+dalloc_size: int (DALLOC_CTX *)
+dalloc_strdup: char *(const void *, const char *)
+dalloc_strndup: char *(const void *, const char *, size_t)
+dalloc_value_for_key: void *(const DALLOC_CTX *, ...)
+decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+dequeue: void *(q_t *)
+dir_rx_set: int (mode_t)
+dsi_attention: int (DSI *, AFPUserBytes)
+dsi_close: void (DSI *)
+dsi_cmdreply: int (DSI *, const int)
+dsi_disconnect: int (DSI *)
+dsi_free: void (DSI *)
+dsi_getsession: int (DSI *, server_child_t *, int, afp_child_t **)
+dsi_getstatus: void (DSI *)
+dsi_init: DSI *(AFPObj *, const char *, const char *, const char *)
+dsi_opensession: void (DSI *)
+dsi_read: ssize_t (DSI *, void *, const size_t)
+dsi_readdone: void (DSI *)
+dsi_readinit: ssize_t (DSI *, void *, const size_t, const size_t, const int)
+dsi_stream_read: size_t (DSI *, void *, const size_t)
+dsi_stream_read_file: ssize_t (DSI *, const int, off_t, const size_t, const int)
+dsi_stream_receive: int (DSI *)
+dsi_stream_send: int (DSI *, void *, size_t)
+dsi_stream_write: ssize_t (DSI *, void *, const size_t, int)
+dsi_tcp_init: int (DSI *, const char *, const char *, const char *)
+dsi_tickle: int (DSI *)
+dsi_write: size_t (DSI *, void *, const size_t)
+dsi_writeflush: void (DSI *)
+dsi_writeinit: size_t (DSI *, void *, const size_t)
+ea_chmod_dir: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chmod_file: int (const struct vol *, const char *, mode_t, struct stat *)
+ea_chown: int (const struct vol *, const char *, uid_t, gid_t)
+ea_close: int (struct ea *)
+ea_copyfile: int (const struct vol *, int, const char *, const char *)
+ea_deletefile: int (const struct vol *, int, const char *)
+ea_open: int (const struct vol *, const char *, eaflags_t, struct ea *)
+ea_openat: int (const struct vol *, int, const char *, eaflags_t, struct ea *)
+ea_path: char *(const struct ea *, const char *, int)
+ea_renamefile: int (const struct vol *, int, const char *, const char *)
+enqueue: qnode_t *(q_t *, void *)
+fault_setup: void (void (*)(void *))
+fdset_add_fd: void (int, struct pollfd **, struct polldata **, int *, int *, int, enum fdtype, void *)
+fdset_del_fd: void (struct pollfd **, struct polldata **, int *, int *, int)
+find_charset_functions: struct charset_functions *(const char *)
+free_charset_names: void (void)
+freeifacelist: void (char **)
+fullpathname: const char *(const char *)
+getcwdpath: const char *(void)
+getdefextmap: struct extmap *(void)
+get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+getextmap: struct extmap *(const char *)
+getifacelist: char **(void)
+getip_port: unsigned int (const struct sockaddr *)
+getip_string: const char *(const struct sockaddr *)
+getnamefromuuid: int (const uuidp_t, char **, uuidtype_t *)
+getuuidfromname: int (const char *, uuidtype_t, unsigned char *)
+getvolbyname: struct vol *(const char *)
+getvolbypath: struct vol *(AFPObj *, const char *)
+getvolbyvid: struct vol *(const uint16_t)
+getvolumes: struct vol *(void)
+gmem: int (gid_t, int, gid_t *)
+init_iconv: void (void)
+initline: void (int, char *)
+initvol_vfs: void (struct vol *)
+ipc_child_state: int (AFPObj *, uint16_t)
+ipc_child_write: int (int, uint16_t, int, void *)
+ipc_server_read: int (server_child_t *, int)
+islower_sp: int (uint32_t)
+islower_w: int (uint16_t)
+isupper_sp: int (uint32_t)
+isupper_w: int (uint16_t)
+ldap_auth_dn: 0x0
+ldap_auth_method: 0
+ldap_auth_pw: 0x0
+ldap_config_valid: 0
+ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *)
+ldap_getuuidfromname: int (const char *, uuidtype_t, char **)
+ldap_group_attr: 0x0
+ldap_groupbase: 0x0
+ldap_groupfilter: 0x0
+ldap_groupscope: 0
+ldap_name_attr: 0x0
+ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap user filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap group filter", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}}
+ldap_server: 0x0
+ldap_uid_attr: 0x0
+ldap_userbase: 0x0
+ldap_userfilter: 0x0
+ldap_userscope: 0
+ldap_uuid_attr: 0x0
+ldap_uuid_encoding: 0
+ldap_uuid_string: 0x0
+list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+load_charset: int (struct vol *)
+load_volumes: int (AFPObj *, lv_flags_t)
+localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int)
+lock_reg: int (int, int, int, off_t, int, off_t)
+log_config: {inited = false, syslog_opened = false, console = false, processname = '\000' <repeats 15 times>, syslog_facility = 0, syslog_display_options = 0}
+make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...)
+make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t)
+mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *)
+mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *)
+netatalk_panic: void (const char *)
+netatalk_rmdir: int (int, const char *)
+netatalk_rmdir_all_errors: int (int, const char *)
+netatalk_unlink: int (const char *)
+netatalk_unlinkat: int (int, const char *)
+nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int)
+ochdir: int (const char *, int)
+ochmod: int (char *, mode_t, const struct stat *, int)
+ochown: int (const char *, uid_t, gid_t, int)
+opendirat: DIR *(int, const char *)
+openflags2logstr: const char *(int)
+ostat: int (const char *, struct stat *, int)
+ostatat: int (int, const char *, struct stat *, int)
+parseline: int (int, char *)
+posix_chmod: int (const char *, mode_t)
+posix_fchmod: int (int, mode_t)
+precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}}
+prequeue: qnode_t *(q_t *, void *)
+print_groups: const char *(int, gid_t *)
+queue_destroy: void (q_t *, void (*)(void *))
+queue_init: q_t *(void)
+randombytes: void (void *, int)
+readt: ssize_t (int, void *, const size_t, int, int)
+realpath_safe: char *(const char *)
+recv_fd: int (int, int)
+rel_path_in_vol: bstring (const char *, const char *)
+remove_acl_vfs: int (const char *)
+remove_ea: int (const struct vol *, const char *, const char *, int)
+run_cmd: int (const char *, char **)
+search_cachebyname: int (const char *, uuidtype_t *, unsigned char *)
+search_cachebyuuid: int (uuidp_t, char **, uuidtype_t *)
+send_fd: int (int, int)
+server_child_add: afp_child_t *(server_child_t *, pid_t, int)
+server_child_alloc: server_child_t *(int)
+server_child_free: void (server_child_t *)
+server_child_kill: void (server_child_t *, int)
+server_child_kill_one_by_id: void (server_child_t *, pid_t, uid_t, uint32_t, char *, uint32_t)
+server_child_remove: int (server_child_t *, pid_t)
+server_child_resolve: afp_child_t *(server_child_t *, id_t)
+server_child_transfer_session: int (server_child_t *, pid_t, uid_t, int, uint16_t)
+server_lock: pid_t (char *, char *, int)
+server_reset_signal: void (void)
+set_charset_name: int (charset_t, const char *)
+set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+setfilmode: int (const struct vol *, const char *, mode_t, struct stat *)
+set_groups: int (AFPObj *, struct passwd *)
+setnonblock: int (int, int)
+set_processname: void (const char *)
+setuplog: void (const char *, const char *)
+statat: int (int, const char *, struct stat *)
+strcasechr_sp: uint16_t *(const uint16_t *, uint32_t)
+strcasechr_w: uint16_t *(const uint16_t *, uint16_t)
+strcasecmp_w: int (const uint16_t *, const uint16_t *)
+strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strcat_w: uint16_t *(uint16_t *, const uint16_t *)
+strchr_w: uint16_t *(const uint16_t *, uint16_t)
+strcmp_w: int (const uint16_t *, const uint16_t *)
+strdiacasecmp: int (const char *, const char *)
+strdup_w: uint16_t *(const uint16_t *)
+stripped_slashes_basename: char *(char *)
+strlcat: size_t (char *, const char *, size_t)
+strlcpy: size_t (char *, const char *, size_t)
+strlen_w: size_t (const uint16_t *)
+strlower_w: int (uint16_t *)
+strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strncmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strndiacasecmp: int (const char *, const char *, size_t)
+strndup_w: uint16_t *(const uint16_t *, size_t)
+strnlen_w: size_t (const uint16_t *, size_t)
+strstr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strtok_quote: char *(char *, const char *)
+strupper_w: int (uint16_t *)
+sys_ea_copyfile: int (const struct vol *, int, const char *, const char *)
+sys_fgetxattr: ssize_t (int, const char *, void *, size_t)
+sys_fsetxattr: int (int, const char *, const void *, size_t, int)
+sys_ftruncate: int (int, off_t)
+sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+sys_getxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_getxattrfd: int (int, const char *, int, ...)
+sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+sys_listxattr: ssize_t (const char *, char *, size_t)
+sys_llistxattr: ssize_t (const char *, char *, size_t)
+sys_lremovexattr: int (const char *, const char *)
+sys_lsetxattr: int (const char *, const char *, const void *, size_t, int)
+sys_remove_ea: int (const struct vol *, const char *, const char *, int)
+sys_removexattr: int (const char *, const char *)
+sys_sendfile: ssize_t (int, int, off_t *, size_t)
+sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+sys_setxattr: int (const char *, const char *, const void *, size_t, int)
+talloc_asprintf: char *(const void *, const char *, ...)
+talloc_asprintf_append: char *(char *, const char *, ...)
+talloc_asprintf_append_buffer: char *(char *, const char *, ...)
+talloc_autofree_context: void *(void)
+talloc_check_name: void *(const void *, const char *)
+talloc_disable_null_tracking: void (void)
+talloc_enable_leak_report: void (void)
+talloc_enable_leak_report_full: void (void)
+talloc_enable_null_tracking: void (void)
+talloc_enable_null_tracking_no_autofree: void (void)
+talloc_find_parent_byname: void *(const void *, const char *)
+talloc_free_children: void (void *)
+talloc_get_name: const char *(const void *)
+talloc_get_size: size_t (const void *)
+talloc_increase_ref_count: int (const void *)
+talloc_init: void *(const char *, ...)
+talloc_is_parent: int (const void *, const void *)
+talloc_named: void *(const void *, size_t, const char *, ...)
+talloc_named_const: void *(const void *, size_t, const char *)
+talloc_parent: void *(const void *)
+talloc_parent_name: const char *(const void *)
+talloc_pool: void *(const void *, size_t)
+talloc_realloc_fn: void *(const void *, void *, size_t)
+talloc_reference_count: size_t (const void *)
+talloc_reparent: void *(const void *, const void *, const void *)
+talloc_report: void (const void *, FILE *)
+talloc_report_depth_cb: void (const void *, int, int, void (*)(const void *, int, int, int, void *), void *)
+talloc_report_depth_file: void (const void *, int, int, FILE *)
+talloc_report_full: void (const void *, FILE *)
+talloc_set_abort_fn: void (void (*)(const char *))
+talloc_set_log_fn: void (void (*)(const char *))
+talloc_set_log_stderr: void (void)
+talloc_set_name: const char *(const void *, const char *, ...)
+talloc_set_name_const: void (const void *, const char *)
+talloc_show_parents: void (const void *, FILE *)
+talloc_strdup: char *(const void *, const char *)
+talloc_strdup_append: char *(char *, const char *)
+talloc_strdup_append_buffer: char *(char *, const char *)
+talloc_strndup: char *(const void *, const char *, size_t)
+talloc_strndup_append: char *(char *, const char *, size_t)
+talloc_strndup_append_buffer: char *(char *, const char *, size_t)
+talloc_total_blocks: size_t (const void *)
+talloc_total_size: size_t (const void *)
+talloc_unlink: int (const void *, void *)
+talloc_vasprintf: char *(const void *, const char *, struct __va_list_tag *)
+talloc_vasprintf_append: char *(char *, const char *, struct __va_list_tag *)
+talloc_vasprintf_append_buffer: char *(char *, const char *, struct __va_list_tag *)
+talloc_version_major: int (void)
+talloc_version_minor: int (void)
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *)
+tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t)
+tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_convert: void *(void *, uint32_t)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_expand: int (struct tdb_context *, tdb_off_t)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_io_init: void (struct tdb_context *)
+tdb_lock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_mmap: void (struct tdb_context *)
+tdb_munmap: int (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: {dptr = 0x0, dsize = 0}
+tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_lock: int (struct tdb_context *, int)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_recover: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_unlock: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_unlock_record: int (struct tdb_context *, tdb_off_t)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
+tdb_write_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t)
+tokenize_ip_port: int (const char *, char **, char **)
+tolower_sp: uint32_t (uint32_t)
+tolower_w: uint16_t (uint16_t)
+toupper_sp: uint32_t (uint32_t)
+toupper_w: uint16_t (uint16_t)
+type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}}
+ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t)
+ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *)
+unbecome_root: void (void)
+unix_rename: int (int, const char *, int, const char *)
+unix_strlower: size_t (const char *, size_t, char *, size_t)
+unix_strupper: size_t (const char *, size_t, char *, size_t)
+unload_volumes: void (AFPObj *)
+utf8_charlen: size_t (char *)
+utf8_decompose: size_t (char *, size_t, char *, size_t)
+utf8_precompose: size_t (char *, size_t, char *, size_t)
+utf8_strlen_validate: size_t (char *)
+utf8_strlower: size_t (const char *, size_t, char *, size_t)
+utf8_strupper: size_t (const char *, size_t, char *, size_t)
+utf8_to_charset_allocate: size_t (charset_t, char **, const char *)
+uuid_bin2string: const char *(const unsigned char *)
+uuidcache_dump: void (void)
+uuid_string2bin: void (const char *, unsigned char *)
+uuidtype: {"", "USER", "GROUP", "LOCAL"}
+volume_free: void (struct vol *)
+volume_unlink: void (struct vol *)
+writet: ssize_t (int, void *, const size_t, int, int)
index 256c1fae06cbb849bf7e20f5d9b60c2f4cbfc9f7..cbf1a3970eac32f67d4285bdd134ceb6693c0623 100644 (file)
@@ -19,8 +19,8 @@
 #define DECOMP_COUNT 955
 #define MAXCOMBLEN 3
 
-#define PRECOMP_SP_COUNT 18
-#define DECOMP_SP_COUNT 18
+#define PRECOMP_SP_COUNT 25
+#define DECOMP_SP_COUNT 25
 #define MAXCOMBSPLEN 4
 
 #define COMBBUFLEN 4  /* max(MAXCOMBLEN,MAXCOMBSPLEN) */
@@ -1035,6 +1035,13 @@ static const struct {
 /*{ 0x000110AB, 0x000110A5, 0x000110BA },*/   /* KAITHI LETTER VA */
 /*{ 0x0001112E, 0x00011131, 0x00011127 },*/   /* CHAKMA VOWEL SIGN O */
 /*{ 0x0001112F, 0x00011132, 0x00011127 },*/   /* CHAKMA VOWEL SIGN AU */
+/*{ 0x0001134B, 0x00011347, 0x0001133E },*/   /* GRANTHA VOWEL SIGN OO */
+/*{ 0x0001134C, 0x00011347, 0x00011357 },*/   /* GRANTHA VOWEL SIGN AU */
+/*{ 0x000114BC, 0x000114B9, 0x000114B0 },*/   /* TIRHUTA VOWEL SIGN O */
+/*{ 0x000114BB, 0x000114B9, 0x000114BA },*/   /* TIRHUTA VOWEL SIGN AI */
+/*{ 0x000114BE, 0x000114B9, 0x000114BD },*/   /* TIRHUTA VOWEL SIGN AU */
+/*{ 0x000115BA, 0x000115B8, 0x000115AF },*/   /* SIDDHAM VOWEL SIGN O */
+/*{ 0x000115BB, 0x000115B9, 0x000115AF },*/   /* SIDDHAM VOWEL SIGN AU */
 /*{ 0x0001D15E, 0x0001D157, 0x0001D165 },*/   /* MUSICAL SYMBOL HALF NOTE */
 /*{ 0x0001D15F, 0x0001D158, 0x0001D165 },*/   /* MUSICAL SYMBOL QUARTER NOTE */
 /*{ 0x0001D160, 0x0001D15F, 0x0001D16E },*/   /* MUSICAL SYMBOL EIGHTH NOTE */
@@ -2060,6 +2067,13 @@ static const struct {
 /*{ 0x000110AB, 0x000110A5, 0x000110BA },*/   /* KAITHI LETTER VA */
 /*{ 0x0001112E, 0x00011131, 0x00011127 },*/   /* CHAKMA VOWEL SIGN O */
 /*{ 0x0001112F, 0x00011132, 0x00011127 },*/   /* CHAKMA VOWEL SIGN AU */
+/*{ 0x0001134B, 0x00011347, 0x0001133E },*/   /* GRANTHA VOWEL SIGN OO */
+/*{ 0x0001134C, 0x00011347, 0x00011357 },*/   /* GRANTHA VOWEL SIGN AU */
+/*{ 0x000114BB, 0x000114B9, 0x000114BA },*/   /* TIRHUTA VOWEL SIGN AI */
+/*{ 0x000114BC, 0x000114B9, 0x000114B0 },*/   /* TIRHUTA VOWEL SIGN O */
+/*{ 0x000114BE, 0x000114B9, 0x000114BD },*/   /* TIRHUTA VOWEL SIGN AU */
+/*{ 0x000115BA, 0x000115B8, 0x000115AF },*/   /* SIDDHAM VOWEL SIGN O */
+/*{ 0x000115BB, 0x000115B9, 0x000115AF },*/   /* SIDDHAM VOWEL SIGN AU */
 /*{ 0x0001D15E, 0x0001D157, 0x0001D165 },*/   /* MUSICAL SYMBOL HALF NOTE */
 /*{ 0x0001D15F, 0x0001D158, 0x0001D165 },*/   /* MUSICAL SYMBOL QUARTER NOTE */
 /*{ 0x0001D160, 0x0001D15F, 0x0001D16E },*/   /* MUSICAL SYMBOL EIGHTH NOTE */
@@ -2085,6 +2099,13 @@ static const struct {
   { 0xD804DCAB, 0xD804DCA5, 0xD804DCBA },     /* KAITHI LETTER VA */
   { 0xD804DD2E, 0xD804DD31, 0xD804DD27 },     /* CHAKMA VOWEL SIGN O */
   { 0xD804DD2F, 0xD804DD32, 0xD804DD27 },     /* CHAKMA VOWEL SIGN AU */
+  { 0xD804DF4B, 0xD804DF47, 0xD804DF3E },     /* GRANTHA VOWEL SIGN OO */
+  { 0xD804DF4C, 0xD804DF47, 0xD804DF57 },     /* GRANTHA VOWEL SIGN AU */
+  { 0xD805DCBC, 0xD805DCB9, 0xD805DCB0 },     /* TIRHUTA VOWEL SIGN O */
+  { 0xD805DCBB, 0xD805DCB9, 0xD805DCBA },     /* TIRHUTA VOWEL SIGN AI */
+  { 0xD805DCBE, 0xD805DCB9, 0xD805DCBD },     /* TIRHUTA VOWEL SIGN AU */
+  { 0xD805DDBA, 0xD805DDB8, 0xD805DDAF },     /* SIDDHAM VOWEL SIGN O */
+  { 0xD805DDBB, 0xD805DDB9, 0xD805DDAF },     /* SIDDHAM VOWEL SIGN AU */
   { 0xD834DD5E, 0xD834DD57, 0xD834DD65 },     /* MUSICAL SYMBOL HALF NOTE */
   { 0xD834DD5F, 0xD834DD58, 0xD834DD65 },     /* MUSICAL SYMBOL QUARTER NOTE */
   { 0xD834DD60, 0xD834DD5F, 0xD834DD6E },     /* MUSICAL SYMBOL EIGHTH NOTE */
@@ -2110,6 +2131,13 @@ static const struct {
   { 0xD804DCAB, 0xD804DCA5, 0xD804DCBA },     /* KAITHI LETTER VA */
   { 0xD804DD2E, 0xD804DD31, 0xD804DD27 },     /* CHAKMA VOWEL SIGN O */
   { 0xD804DD2F, 0xD804DD32, 0xD804DD27 },     /* CHAKMA VOWEL SIGN AU */
+  { 0xD804DF4B, 0xD804DF47, 0xD804DF3E },     /* GRANTHA VOWEL SIGN OO */
+  { 0xD804DF4C, 0xD804DF47, 0xD804DF57 },     /* GRANTHA VOWEL SIGN AU */
+  { 0xD805DCBB, 0xD805DCB9, 0xD805DCBA },     /* TIRHUTA VOWEL SIGN AI */
+  { 0xD805DCBC, 0xD805DCB9, 0xD805DCB0 },     /* TIRHUTA VOWEL SIGN O */
+  { 0xD805DCBE, 0xD805DCB9, 0xD805DCBD },     /* TIRHUTA VOWEL SIGN AU */
+  { 0xD805DDBA, 0xD805DDB8, 0xD805DDAF },     /* SIDDHAM VOWEL SIGN O */
+  { 0xD805DDBB, 0xD805DDB9, 0xD805DDAF },     /* SIDDHAM VOWEL SIGN AU */
   { 0xD834DD5E, 0xD834DD57, 0xD834DD65 },     /* MUSICAL SYMBOL HALF NOTE */
   { 0xD834DD5F, 0xD834DD58, 0xD834DD65 },     /* MUSICAL SYMBOL QUARTER NOTE */
   { 0xD834DD60, 0xD834DD5F, 0xD834DD6E },     /* MUSICAL SYMBOL EIGHTH NOTE */
index 3fc7ed36586081469f0423671d86b7d0ccc6cfea..ca9285cb5d1d6e61a0cbb20c58cc56ce0bc97a7a 100644 (file)
@@ -58,6 +58,9 @@ uint32_t toupper_sp(uint32_t val)
     if ( val >= 0xD801DC00 && val <= 0xD801DC7F)
         return upper_table_sp_1[val-0xD801DC00];
 
+    if ( val >= 0xD806DCC0 && val <= 0xD806DCFF)
+        return upper_table_sp_2[val-0xD806DCC0];
+
        return (val);
 }
 
@@ -110,6 +113,9 @@ uint32_t tolower_sp(uint32_t val)
     if ( val >= 0xD801DC00 && val <= 0xD801DC3F)
         return lower_table_sp_1[val-0xD801DC00];
 
+    if ( val >= 0xD806DC80 && val <= 0xD806DCBF)
+        return lower_table_sp_2[val-0xD806DC80];
+
        return (val);
 }
 
index 188e1ea75fb24df3d57a04bbfa854d5338b9f48f..4d32d78df84e74efc20fc091d851b4989f4807ea 100644 (file)
@@ -613,12 +613,12 @@ static const uint16_t upper_table_1[704] = {
   0x018F, /*U+0259*/ /*LATIN SMALL LETTER SCHWA*/
   0x025A, /*U+025A*/ /**/
   0x0190, /*U+025B*/ /*LATIN SMALL LETTER OPEN E*/
-  0x025C, /*U+025C*/ /**/
+  0xA7AB, /*U+025C*/ /*LATIN SMALL LETTER REVERSED OPEN E*/
   0x025D, /*U+025D*/ /**/
   0x025E, /*U+025E*/ /**/
   0x025F, /*U+025F*/ /**/
   0x0193, /*U+0260*/ /*LATIN SMALL LETTER G WITH HOOK*/
-  0x0261, /*U+0261*/ /**/
+  0xA7AC, /*U+0261*/ /*LATIN SMALL LETTER SCRIPT G*/
   0x0262, /*U+0262*/ /**/
   0x0194, /*U+0263*/ /*LATIN SMALL LETTER GAMMA*/
   0x0264, /*U+0264*/ /**/
@@ -629,7 +629,7 @@ static const uint16_t upper_table_1[704] = {
   0x0196, /*U+0269*/ /*LATIN SMALL LETTER IOTA*/
   0x026A, /*U+026A*/ /**/
   0x2C62, /*U+026B*/ /*LATIN SMALL LETTER L WITH MIDDLE TILDE*/
-  0x026C, /*U+026C*/ /**/
+  0xA7AD, /*U+026C*/ /*LATIN SMALL LETTER L WITH BELT*/
   0x026D, /*U+026D*/ /**/
   0x026E, /*U+026E*/ /**/
   0x019C, /*U+026F*/ /*LATIN SMALL LETTER TURNED M*/
@@ -656,7 +656,7 @@ static const uint16_t upper_table_1[704] = {
   0x0284, /*U+0284*/ /**/
   0x0285, /*U+0285*/ /**/
   0x0286, /*U+0286*/ /**/
-  0x0287, /*U+0287*/ /**/
+  0xA7B1, /*U+0287*/ /*LATIN SMALL LETTER TURNED T*/
   0x01AE, /*U+0288*/ /*LATIN SMALL LETTER T WITH RETROFLEX HOOK*/
   0x0244, /*U+0289*/ /*LATIN SMALL LETTER U BAR*/
   0x01B1, /*U+028A*/ /*LATIN SMALL LETTER UPSILON*/
@@ -679,7 +679,7 @@ static const uint16_t upper_table_1[704] = {
   0x029B, /*U+029B*/ /**/
   0x029C, /*U+029C*/ /**/
   0x029D, /*U+029D*/ /**/
-  0x029E, /*U+029E*/ /**/
+  0xA7B0, /*U+029E*/ /*LATIN SMALL LETTER TURNED K*/
   0x029F, /*U+029F*/ /**/
   0x02A0, /*U+02A0*/ /**/
   0x02A1, /*U+02A1*/ /**/
@@ -895,7 +895,7 @@ static const uint16_t upper_table_2[640] = {
   0x039A, /*U+03F0*/ /*GREEK KAPPA SYMBOL*/
   0x03A1, /*U+03F1*/ /*GREEK RHO SYMBOL*/
   0x03F9, /*U+03F2*/ /*GREEK LUNATE SIGMA SYMBOL*/
-  0x03F3, /*U+03F3*/ /**/
+  0x037F, /*U+03F3*/ /*GREEK LETTER YOT*/
   0x03F4, /*U+03F4*/ /**/
   0x0395, /*U+03F5*/ /*GREEK LUNATE EPSILON SYMBOL*/
   0x03F6, /*U+03F6*/ /**/
@@ -1205,13 +1205,13 @@ static const uint16_t upper_table_2[640] = {
   0x0526, /*U+0526*/ /**/
   0x0526, /*U+0527*/ /*CYRILLIC SMALL LETTER SHHA WITH DESCENDER*/
   0x0528, /*U+0528*/ /**/
-  0x0529, /*U+0529*/ /**/
+  0x0528, /*U+0529*/ /*CYRILLIC SMALL LETTER EN WITH LEFT HOOK*/
   0x052A, /*U+052A*/ /**/
-  0x052B, /*U+052B*/ /**/
+  0x052A, /*U+052B*/ /*CYRILLIC SMALL LETTER DZZHE*/
   0x052C, /*U+052C*/ /**/
-  0x052D, /*U+052D*/ /**/
+  0x052C, /*U+052D*/ /*CYRILLIC SMALL LETTER DCHE*/
   0x052E, /*U+052E*/ /**/
-  0x052F, /*U+052F*/ /**/
+  0x052E, /*U+052F*/ /*CYRILLIC SMALL LETTER EL WITH DESCENDER*/
   0x0530, /*U+0530*/ /**/
   0x0531, /*U+0531*/ /**/
   0x0532, /*U+0532*/ /**/
@@ -2551,9 +2551,9 @@ static const uint16_t upper_table_8[128] = {
   0xA696, /*U+A696*/ /**/
   0xA696, /*U+A697*/ /*CYRILLIC SMALL LETTER SHWE*/
   0xA698, /*U+A698*/ /**/
-  0xA699, /*U+A699*/ /**/
+  0xA698, /*U+A699*/ /*CYRILLIC SMALL LETTER DOUBLE O*/
   0xA69A, /*U+A69A*/ /**/
-  0xA69B, /*U+A69B*/ /**/
+  0xA69A, /*U+A69B*/ /*CYRILLIC SMALL LETTER CROSSED O*/
   0xA69C, /*U+A69C*/ /**/
   0xA69D, /*U+A69D*/ /**/
   0xA69E, /*U+A69E*/ /**/
@@ -2744,15 +2744,15 @@ static const uint16_t upper_table_9[192] = {
   0xA794, /*U+A794*/ /**/
   0xA795, /*U+A795*/ /**/
   0xA796, /*U+A796*/ /**/
-  0xA797, /*U+A797*/ /**/
+  0xA796, /*U+A797*/ /*LATIN SMALL LETTER B WITH FLOURISH*/
   0xA798, /*U+A798*/ /**/
-  0xA799, /*U+A799*/ /**/
+  0xA798, /*U+A799*/ /*LATIN SMALL LETTER F WITH STROKE*/
   0xA79A, /*U+A79A*/ /**/
-  0xA79B, /*U+A79B*/ /**/
+  0xA79A, /*U+A79B*/ /*LATIN SMALL LETTER VOLAPUK AE*/
   0xA79C, /*U+A79C*/ /**/
-  0xA79D, /*U+A79D*/ /**/
+  0xA79C, /*U+A79D*/ /*LATIN SMALL LETTER VOLAPUK OE*/
   0xA79E, /*U+A79E*/ /**/
-  0xA79F, /*U+A79F*/ /**/
+  0xA79E, /*U+A79F*/ /*LATIN SMALL LETTER VOLAPUK UE*/
   0xA7A0, /*U+A7A0*/ /**/
   0xA7A0, /*U+A7A1*/ /*LATIN SMALL LETTER G WITH OBLIQUE STROKE*/
   0xA7A2, /*U+A7A2*/ /**/
@@ -2985,6 +2985,73 @@ static const uint32_t upper_table_sp_1[128] = {
   0xD801DC7F, /*0xD801DC7F*/ /*U+01047F*/ /*U+01047F*/ /**/
 };
 
+static const uint32_t upper_table_sp_2[64] = {
+  0xD806DCA0, /*0xD806DCC0*/ /*U+0118A0*/ /*U+0118C0*/ /*WARANG CITI SMALL LETTER NGAA*/
+  0xD806DCA1, /*0xD806DCC1*/ /*U+0118A1*/ /*U+0118C1*/ /*WARANG CITI SMALL LETTER A*/
+  0xD806DCA2, /*0xD806DCC2*/ /*U+0118A2*/ /*U+0118C2*/ /*WARANG CITI SMALL LETTER WI*/
+  0xD806DCA3, /*0xD806DCC3*/ /*U+0118A3*/ /*U+0118C3*/ /*WARANG CITI SMALL LETTER YU*/
+  0xD806DCA4, /*0xD806DCC4*/ /*U+0118A4*/ /*U+0118C4*/ /*WARANG CITI SMALL LETTER YA*/
+  0xD806DCA5, /*0xD806DCC5*/ /*U+0118A5*/ /*U+0118C5*/ /*WARANG CITI SMALL LETTER YO*/
+  0xD806DCA6, /*0xD806DCC6*/ /*U+0118A6*/ /*U+0118C6*/ /*WARANG CITI SMALL LETTER II*/
+  0xD806DCA7, /*0xD806DCC7*/ /*U+0118A7*/ /*U+0118C7*/ /*WARANG CITI SMALL LETTER UU*/
+  0xD806DCA8, /*0xD806DCC8*/ /*U+0118A8*/ /*U+0118C8*/ /*WARANG CITI SMALL LETTER E*/
+  0xD806DCA9, /*0xD806DCC9*/ /*U+0118A9*/ /*U+0118C9*/ /*WARANG CITI SMALL LETTER O*/
+  0xD806DCAA, /*0xD806DCCA*/ /*U+0118AA*/ /*U+0118CA*/ /*WARANG CITI SMALL LETTER ANG*/
+  0xD806DCAB, /*0xD806DCCB*/ /*U+0118AB*/ /*U+0118CB*/ /*WARANG CITI SMALL LETTER GA*/
+  0xD806DCAC, /*0xD806DCCC*/ /*U+0118AC*/ /*U+0118CC*/ /*WARANG CITI SMALL LETTER KO*/
+  0xD806DCAD, /*0xD806DCCD*/ /*U+0118AD*/ /*U+0118CD*/ /*WARANG CITI SMALL LETTER ENY*/
+  0xD806DCAE, /*0xD806DCCE*/ /*U+0118AE*/ /*U+0118CE*/ /*WARANG CITI SMALL LETTER YUJ*/
+  0xD806DCAF, /*0xD806DCCF*/ /*U+0118AF*/ /*U+0118CF*/ /*WARANG CITI SMALL LETTER UC*/
+  0xD806DCB0, /*0xD806DCD0*/ /*U+0118B0*/ /*U+0118D0*/ /*WARANG CITI SMALL LETTER ENN*/
+  0xD806DCB1, /*0xD806DCD1*/ /*U+0118B1*/ /*U+0118D1*/ /*WARANG CITI SMALL LETTER ODD*/
+  0xD806DCB2, /*0xD806DCD2*/ /*U+0118B2*/ /*U+0118D2*/ /*WARANG CITI SMALL LETTER TTE*/
+  0xD806DCB3, /*0xD806DCD3*/ /*U+0118B3*/ /*U+0118D3*/ /*WARANG CITI SMALL LETTER NUNG*/
+  0xD806DCB4, /*0xD806DCD4*/ /*U+0118B4*/ /*U+0118D4*/ /*WARANG CITI SMALL LETTER DA*/
+  0xD806DCB5, /*0xD806DCD5*/ /*U+0118B5*/ /*U+0118D5*/ /*WARANG CITI SMALL LETTER AT*/
+  0xD806DCB6, /*0xD806DCD6*/ /*U+0118B6*/ /*U+0118D6*/ /*WARANG CITI SMALL LETTER AM*/
+  0xD806DCB7, /*0xD806DCD7*/ /*U+0118B7*/ /*U+0118D7*/ /*WARANG CITI SMALL LETTER BU*/
+  0xD806DCB8, /*0xD806DCD8*/ /*U+0118B8*/ /*U+0118D8*/ /*WARANG CITI SMALL LETTER PU*/
+  0xD806DCB9, /*0xD806DCD9*/ /*U+0118B9*/ /*U+0118D9*/ /*WARANG CITI SMALL LETTER HIYO*/
+  0xD806DCBA, /*0xD806DCDA*/ /*U+0118BA*/ /*U+0118DA*/ /*WARANG CITI SMALL LETTER HOLO*/
+  0xD806DCBB, /*0xD806DCDB*/ /*U+0118BB*/ /*U+0118DB*/ /*WARANG CITI SMALL LETTER HORR*/
+  0xD806DCBC, /*0xD806DCDC*/ /*U+0118BC*/ /*U+0118DC*/ /*WARANG CITI SMALL LETTER HAR*/
+  0xD806DCBD, /*0xD806DCDD*/ /*U+0118BD*/ /*U+0118DD*/ /*WARANG CITI SMALL LETTER SSUU*/
+  0xD806DCBE, /*0xD806DCDE*/ /*U+0118BE*/ /*U+0118DE*/ /*WARANG CITI SMALL LETTER SII*/
+  0xD806DCBF, /*0xD806DCDF*/ /*U+0118BF*/ /*U+0118DF*/ /*WARANG CITI SMALL LETTER VIYO*/
+  0xD806DCE0, /*0xD806DCE0*/ /*U+0118E0*/ /*U+0118E0*/ /**/
+  0xD806DCE1, /*0xD806DCE1*/ /*U+0118E1*/ /*U+0118E1*/ /**/
+  0xD806DCE2, /*0xD806DCE2*/ /*U+0118E2*/ /*U+0118E2*/ /**/
+  0xD806DCE3, /*0xD806DCE3*/ /*U+0118E3*/ /*U+0118E3*/ /**/
+  0xD806DCE4, /*0xD806DCE4*/ /*U+0118E4*/ /*U+0118E4*/ /**/
+  0xD806DCE5, /*0xD806DCE5*/ /*U+0118E5*/ /*U+0118E5*/ /**/
+  0xD806DCE6, /*0xD806DCE6*/ /*U+0118E6*/ /*U+0118E6*/ /**/
+  0xD806DCE7, /*0xD806DCE7*/ /*U+0118E7*/ /*U+0118E7*/ /**/
+  0xD806DCE8, /*0xD806DCE8*/ /*U+0118E8*/ /*U+0118E8*/ /**/
+  0xD806DCE9, /*0xD806DCE9*/ /*U+0118E9*/ /*U+0118E9*/ /**/
+  0xD806DCEA, /*0xD806DCEA*/ /*U+0118EA*/ /*U+0118EA*/ /**/
+  0xD806DCEB, /*0xD806DCEB*/ /*U+0118EB*/ /*U+0118EB*/ /**/
+  0xD806DCEC, /*0xD806DCEC*/ /*U+0118EC*/ /*U+0118EC*/ /**/
+  0xD806DCED, /*0xD806DCED*/ /*U+0118ED*/ /*U+0118ED*/ /**/
+  0xD806DCEE, /*0xD806DCEE*/ /*U+0118EE*/ /*U+0118EE*/ /**/
+  0xD806DCEF, /*0xD806DCEF*/ /*U+0118EF*/ /*U+0118EF*/ /**/
+  0xD806DCF0, /*0xD806DCF0*/ /*U+0118F0*/ /*U+0118F0*/ /**/
+  0xD806DCF1, /*0xD806DCF1*/ /*U+0118F1*/ /*U+0118F1*/ /**/
+  0xD806DCF2, /*0xD806DCF2*/ /*U+0118F2*/ /*U+0118F2*/ /**/
+  0xD806DCF3, /*0xD806DCF3*/ /*U+0118F3*/ /*U+0118F3*/ /**/
+  0xD806DCF4, /*0xD806DCF4*/ /*U+0118F4*/ /*U+0118F4*/ /**/
+  0xD806DCF5, /*0xD806DCF5*/ /*U+0118F5*/ /*U+0118F5*/ /**/
+  0xD806DCF6, /*0xD806DCF6*/ /*U+0118F6*/ /*U+0118F6*/ /**/
+  0xD806DCF7, /*0xD806DCF7*/ /*U+0118F7*/ /*U+0118F7*/ /**/
+  0xD806DCF8, /*0xD806DCF8*/ /*U+0118F8*/ /*U+0118F8*/ /**/
+  0xD806DCF9, /*0xD806DCF9*/ /*U+0118F9*/ /*U+0118F9*/ /**/
+  0xD806DCFA, /*0xD806DCFA*/ /*U+0118FA*/ /*U+0118FA*/ /**/
+  0xD806DCFB, /*0xD806DCFB*/ /*U+0118FB*/ /*U+0118FB*/ /**/
+  0xD806DCFC, /*0xD806DCFC*/ /*U+0118FC*/ /*U+0118FC*/ /**/
+  0xD806DCFD, /*0xD806DCFD*/ /*U+0118FD*/ /*U+0118FD*/ /**/
+  0xD806DCFE, /*0xD806DCFE*/ /*U+0118FE*/ /*U+0118FE*/ /**/
+  0xD806DCFF, /*0xD806DCFF*/ /*U+0118FF*/ /*U+0118FF*/ /**/
+};
+
 static const uint16_t lower_table_1[128] = {
   0x0000, /*U+0000*/ /**/
   0x0001, /*U+0001*/ /**/
@@ -3631,7 +3698,7 @@ static const uint16_t lower_table_3[576] = {
   0x037C, /*U+037C*/ /**/
   0x037D, /*U+037D*/ /**/
   0x037E, /*U+037E*/ /**/
-  0x037F, /*U+037F*/ /**/
+  0x03F3, /*U+037F*/ /*GREEK CAPITAL LETTER YOT*/
   0x0380, /*U+0380*/ /**/
   0x0381, /*U+0381*/ /**/
   0x0382, /*U+0382*/ /**/
@@ -4056,13 +4123,13 @@ static const uint16_t lower_table_3[576] = {
   0x0525, /*U+0525*/ /**/
   0x0527, /*U+0526*/ /*CYRILLIC CAPITAL LETTER SHHA WITH DESCENDER*/
   0x0527, /*U+0527*/ /**/
-  0x0528, /*U+0528*/ /**/
+  0x0529, /*U+0528*/ /*CYRILLIC CAPITAL LETTER EN WITH LEFT HOOK*/
   0x0529, /*U+0529*/ /**/
-  0x052A, /*U+052A*/ /**/
+  0x052B, /*U+052A*/ /*CYRILLIC CAPITAL LETTER DZZHE*/
   0x052B, /*U+052B*/ /**/
-  0x052C, /*U+052C*/ /**/
+  0x052D, /*U+052C*/ /*CYRILLIC CAPITAL LETTER DCHE*/
   0x052D, /*U+052D*/ /**/
-  0x052E, /*U+052E*/ /**/
+  0x052F, /*U+052E*/ /*CYRILLIC CAPITAL LETTER EL WITH DESCENDER*/
   0x052F, /*U+052F*/ /**/
   0x0530, /*U+0530*/ /**/
   0x0561, /*U+0531*/ /*ARMENIAN CAPITAL LETTER AYB*/
@@ -5466,9 +5533,9 @@ static const uint16_t lower_table_9[128] = {
   0xA695, /*U+A695*/ /**/
   0xA697, /*U+A696*/ /*CYRILLIC CAPITAL LETTER SHWE*/
   0xA697, /*U+A697*/ /**/
-  0xA698, /*U+A698*/ /**/
+  0xA699, /*U+A698*/ /*CYRILLIC CAPITAL LETTER DOUBLE O*/
   0xA699, /*U+A699*/ /**/
-  0xA69A, /*U+A69A*/ /**/
+  0xA69B, /*U+A69A*/ /*CYRILLIC CAPITAL LETTER CROSSED O*/
   0xA69B, /*U+A69B*/ /**/
   0xA69C, /*U+A69C*/ /**/
   0xA69D, /*U+A69D*/ /**/
@@ -5659,15 +5726,15 @@ static const uint16_t lower_table_10[192] = {
   0xA793, /*U+A793*/ /**/
   0xA794, /*U+A794*/ /**/
   0xA795, /*U+A795*/ /**/
-  0xA796, /*U+A796*/ /**/
+  0xA797, /*U+A796*/ /*LATIN CAPITAL LETTER B WITH FLOURISH*/
   0xA797, /*U+A797*/ /**/
-  0xA798, /*U+A798*/ /**/
+  0xA799, /*U+A798*/ /*LATIN CAPITAL LETTER F WITH STROKE*/
   0xA799, /*U+A799*/ /**/
-  0xA79A, /*U+A79A*/ /**/
+  0xA79B, /*U+A79A*/ /*LATIN CAPITAL LETTER VOLAPUK AE*/
   0xA79B, /*U+A79B*/ /**/
-  0xA79C, /*U+A79C*/ /**/
+  0xA79D, /*U+A79C*/ /*LATIN CAPITAL LETTER VOLAPUK OE*/
   0xA79D, /*U+A79D*/ /**/
-  0xA79E, /*U+A79E*/ /**/
+  0xA79F, /*U+A79E*/ /*LATIN CAPITAL LETTER VOLAPUK UE*/
   0xA79F, /*U+A79F*/ /**/
   0xA7A1, /*U+A7A0*/ /*LATIN CAPITAL LETTER G WITH OBLIQUE STROKE*/
   0xA7A1, /*U+A7A1*/ /**/
@@ -5680,13 +5747,13 @@ static const uint16_t lower_table_10[192] = {
   0xA7A9, /*U+A7A8*/ /*LATIN CAPITAL LETTER S WITH OBLIQUE STROKE*/
   0xA7A9, /*U+A7A9*/ /**/
   0x0266, /*U+A7AA*/ /*LATIN CAPITAL LETTER H WITH HOOK*/
-  0xA7AB, /*U+A7AB*/ /**/
-  0xA7AC, /*U+A7AC*/ /**/
-  0xA7AD, /*U+A7AD*/ /**/
+  0x025C, /*U+A7AB*/ /*LATIN CAPITAL LETTER REVERSED OPEN E*/
+  0x0261, /*U+A7AC*/ /*LATIN CAPITAL LETTER SCRIPT G*/
+  0x026C, /*U+A7AD*/ /*LATIN CAPITAL LETTER L WITH BELT*/
   0xA7AE, /*U+A7AE*/ /**/
   0xA7AF, /*U+A7AF*/ /**/
-  0xA7B0, /*U+A7B0*/ /**/
-  0xA7B1, /*U+A7B1*/ /**/
+  0x029E, /*U+A7B0*/ /*LATIN CAPITAL LETTER TURNED K*/
+  0x0287, /*U+A7B1*/ /*LATIN CAPITAL LETTER TURNED T*/
   0xA7B2, /*U+A7B2*/ /**/
   0xA7B3, /*U+A7B3*/ /**/
   0xA7B4, /*U+A7B4*/ /**/
@@ -5837,4 +5904,71 @@ static const uint32_t lower_table_sp_1[64] = {
   0xD801DC3F, /*0xD801DC3F*/ /*U+01043F*/ /*U+01043F*/ /**/
 };
 
+static const uint32_t lower_table_sp_2[64] = {
+  0xD806DC80, /*0xD806DC80*/ /*U+011880*/ /*U+011880*/ /**/
+  0xD806DC81, /*0xD806DC81*/ /*U+011881*/ /*U+011881*/ /**/
+  0xD806DC82, /*0xD806DC82*/ /*U+011882*/ /*U+011882*/ /**/
+  0xD806DC83, /*0xD806DC83*/ /*U+011883*/ /*U+011883*/ /**/
+  0xD806DC84, /*0xD806DC84*/ /*U+011884*/ /*U+011884*/ /**/
+  0xD806DC85, /*0xD806DC85*/ /*U+011885*/ /*U+011885*/ /**/
+  0xD806DC86, /*0xD806DC86*/ /*U+011886*/ /*U+011886*/ /**/
+  0xD806DC87, /*0xD806DC87*/ /*U+011887*/ /*U+011887*/ /**/
+  0xD806DC88, /*0xD806DC88*/ /*U+011888*/ /*U+011888*/ /**/
+  0xD806DC89, /*0xD806DC89*/ /*U+011889*/ /*U+011889*/ /**/
+  0xD806DC8A, /*0xD806DC8A*/ /*U+01188A*/ /*U+01188A*/ /**/
+  0xD806DC8B, /*0xD806DC8B*/ /*U+01188B*/ /*U+01188B*/ /**/
+  0xD806DC8C, /*0xD806DC8C*/ /*U+01188C*/ /*U+01188C*/ /**/
+  0xD806DC8D, /*0xD806DC8D*/ /*U+01188D*/ /*U+01188D*/ /**/
+  0xD806DC8E, /*0xD806DC8E*/ /*U+01188E*/ /*U+01188E*/ /**/
+  0xD806DC8F, /*0xD806DC8F*/ /*U+01188F*/ /*U+01188F*/ /**/
+  0xD806DC90, /*0xD806DC90*/ /*U+011890*/ /*U+011890*/ /**/
+  0xD806DC91, /*0xD806DC91*/ /*U+011891*/ /*U+011891*/ /**/
+  0xD806DC92, /*0xD806DC92*/ /*U+011892*/ /*U+011892*/ /**/
+  0xD806DC93, /*0xD806DC93*/ /*U+011893*/ /*U+011893*/ /**/
+  0xD806DC94, /*0xD806DC94*/ /*U+011894*/ /*U+011894*/ /**/
+  0xD806DC95, /*0xD806DC95*/ /*U+011895*/ /*U+011895*/ /**/
+  0xD806DC96, /*0xD806DC96*/ /*U+011896*/ /*U+011896*/ /**/
+  0xD806DC97, /*0xD806DC97*/ /*U+011897*/ /*U+011897*/ /**/
+  0xD806DC98, /*0xD806DC98*/ /*U+011898*/ /*U+011898*/ /**/
+  0xD806DC99, /*0xD806DC99*/ /*U+011899*/ /*U+011899*/ /**/
+  0xD806DC9A, /*0xD806DC9A*/ /*U+01189A*/ /*U+01189A*/ /**/
+  0xD806DC9B, /*0xD806DC9B*/ /*U+01189B*/ /*U+01189B*/ /**/
+  0xD806DC9C, /*0xD806DC9C*/ /*U+01189C*/ /*U+01189C*/ /**/
+  0xD806DC9D, /*0xD806DC9D*/ /*U+01189D*/ /*U+01189D*/ /**/
+  0xD806DC9E, /*0xD806DC9E*/ /*U+01189E*/ /*U+01189E*/ /**/
+  0xD806DC9F, /*0xD806DC9F*/ /*U+01189F*/ /*U+01189F*/ /**/
+  0xD806DCC0, /*0xD806DCA0*/ /*U+0118C0*/ /*U+0118A0*/ /*WARANG CITI CAPITAL LETTER NGAA*/
+  0xD806DCC1, /*0xD806DCA1*/ /*U+0118C1*/ /*U+0118A1*/ /*WARANG CITI CAPITAL LETTER A*/
+  0xD806DCC2, /*0xD806DCA2*/ /*U+0118C2*/ /*U+0118A2*/ /*WARANG CITI CAPITAL LETTER WI*/
+  0xD806DCC3, /*0xD806DCA3*/ /*U+0118C3*/ /*U+0118A3*/ /*WARANG CITI CAPITAL LETTER YU*/
+  0xD806DCC4, /*0xD806DCA4*/ /*U+0118C4*/ /*U+0118A4*/ /*WARANG CITI CAPITAL LETTER YA*/
+  0xD806DCC5, /*0xD806DCA5*/ /*U+0118C5*/ /*U+0118A5*/ /*WARANG CITI CAPITAL LETTER YO*/
+  0xD806DCC6, /*0xD806DCA6*/ /*U+0118C6*/ /*U+0118A6*/ /*WARANG CITI CAPITAL LETTER II*/
+  0xD806DCC7, /*0xD806DCA7*/ /*U+0118C7*/ /*U+0118A7*/ /*WARANG CITI CAPITAL LETTER UU*/
+  0xD806DCC8, /*0xD806DCA8*/ /*U+0118C8*/ /*U+0118A8*/ /*WARANG CITI CAPITAL LETTER E*/
+  0xD806DCC9, /*0xD806DCA9*/ /*U+0118C9*/ /*U+0118A9*/ /*WARANG CITI CAPITAL LETTER O*/
+  0xD806DCCA, /*0xD806DCAA*/ /*U+0118CA*/ /*U+0118AA*/ /*WARANG CITI CAPITAL LETTER ANG*/
+  0xD806DCCB, /*0xD806DCAB*/ /*U+0118CB*/ /*U+0118AB*/ /*WARANG CITI CAPITAL LETTER GA*/
+  0xD806DCCC, /*0xD806DCAC*/ /*U+0118CC*/ /*U+0118AC*/ /*WARANG CITI CAPITAL LETTER KO*/
+  0xD806DCCD, /*0xD806DCAD*/ /*U+0118CD*/ /*U+0118AD*/ /*WARANG CITI CAPITAL LETTER ENY*/
+  0xD806DCCE, /*0xD806DCAE*/ /*U+0118CE*/ /*U+0118AE*/ /*WARANG CITI CAPITAL LETTER YUJ*/
+  0xD806DCCF, /*0xD806DCAF*/ /*U+0118CF*/ /*U+0118AF*/ /*WARANG CITI CAPITAL LETTER UC*/
+  0xD806DCD0, /*0xD806DCB0*/ /*U+0118D0*/ /*U+0118B0*/ /*WARANG CITI CAPITAL LETTER ENN*/
+  0xD806DCD1, /*0xD806DCB1*/ /*U+0118D1*/ /*U+0118B1*/ /*WARANG CITI CAPITAL LETTER ODD*/
+  0xD806DCD2, /*0xD806DCB2*/ /*U+0118D2*/ /*U+0118B2*/ /*WARANG CITI CAPITAL LETTER TTE*/
+  0xD806DCD3, /*0xD806DCB3*/ /*U+0118D3*/ /*U+0118B3*/ /*WARANG CITI CAPITAL LETTER NUNG*/
+  0xD806DCD4, /*0xD806DCB4*/ /*U+0118D4*/ /*U+0118B4*/ /*WARANG CITI CAPITAL LETTER DA*/
+  0xD806DCD5, /*0xD806DCB5*/ /*U+0118D5*/ /*U+0118B5*/ /*WARANG CITI CAPITAL LETTER AT*/
+  0xD806DCD6, /*0xD806DCB6*/ /*U+0118D6*/ /*U+0118B6*/ /*WARANG CITI CAPITAL LETTER AM*/
+  0xD806DCD7, /*0xD806DCB7*/ /*U+0118D7*/ /*U+0118B7*/ /*WARANG CITI CAPITAL LETTER BU*/
+  0xD806DCD8, /*0xD806DCB8*/ /*U+0118D8*/ /*U+0118B8*/ /*WARANG CITI CAPITAL LETTER PU*/
+  0xD806DCD9, /*0xD806DCB9*/ /*U+0118D9*/ /*U+0118B9*/ /*WARANG CITI CAPITAL LETTER HIYO*/
+  0xD806DCDA, /*0xD806DCBA*/ /*U+0118DA*/ /*U+0118BA*/ /*WARANG CITI CAPITAL LETTER HOLO*/
+  0xD806DCDB, /*0xD806DCBB*/ /*U+0118DB*/ /*U+0118BB*/ /*WARANG CITI CAPITAL LETTER HORR*/
+  0xD806DCDC, /*0xD806DCBC*/ /*U+0118DC*/ /*U+0118BC*/ /*WARANG CITI CAPITAL LETTER HAR*/
+  0xD806DCDD, /*0xD806DCBD*/ /*U+0118DD*/ /*U+0118BD*/ /*WARANG CITI CAPITAL LETTER SSUU*/
+  0xD806DCDE, /*0xD806DCBE*/ /*U+0118DE*/ /*U+0118BE*/ /*WARANG CITI CAPITAL LETTER SII*/
+  0xD806DCDF, /*0xD806DCBF*/ /*U+0118DF*/ /*U+0118BF*/ /*WARANG CITI CAPITAL LETTER VIYO*/
+};
+
 /* EOF */
index 78c8f331687df3023afacf6deaeb142a48e24544..a1d27311a4c2e9d786efdd35dfc431acef4af60e 100644 (file)
@@ -547,6 +547,36 @@ static int getoption_bool(const dictionary *conf, const char *vol, const char *o
     return result;
 }
 
+/*!
+ * Get boolean option from volume, default section or global - use default value if not set
+ *
+ * Order of precedence: volume -> default section -> global -> default value
+ *
+ * "vdg" means volume, default section or global
+ *
+ * @param conf    (r) config handle
+ * @param vol     (r) volume name (must be section name ie wo vars expanded)
+ * @param opt     (r) option
+ * @param defsec  (r) if "option" is not found in "vol", try to find it in section "defsec"
+ * @param defval  (r) if neither "vol" nor "defsec" contain "opt" return "defval"
+ *
+ * @returns       const option string from "vol" or "defsec", or "defval" if not found
+ */
+static int vdgoption_bool(const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval)
+{
+    int result;
+
+    result = atalk_iniparser_getboolean(conf, vol, opt, -1);
+
+    if ((result == -1) && (defsec != NULL))
+        result = atalk_iniparser_getboolean(conf, defsec, opt, -1);
+
+    if (result == -1)
+        result = atalk_iniparser_getboolean(conf, INISEC_GLOBAL, opt, defval);
+
+    return result;
+}
+
 /*!
  * Create volume struct
  *
@@ -575,10 +605,12 @@ static struct vol *creatvol(AFPObj *obj,
     uint16_t    flags;
     const char  *val;
     char        *p, *q;
+    bstring     dbpath = NULL;
+    bstring     global_path_tmp = NULL;
 
     strlcpy(path, path_in, MAXPATHLEN);
 
-    LOG(log_debug, logtype_afpd, "createvol(volume: '%s', path: \"%s\", preset: '%s'): BEGIN",
+    LOG(log_debug, logtype_afpd, "creatvol(volume: '%s', path: \"%s\", preset: '%s'): BEGIN",
         name, path, preset ? preset : "-");
 
     if ( name == NULL || *name == '\0' ) {
@@ -671,16 +703,32 @@ static struct vol *creatvol(AFPObj *obj,
     if (atalk_iniparser_getboolean(obj->iniconfig, INISEC_GLOBAL, "vol dbnest", 0)) {
         EC_NULL( volume->v_dbpath = strdup(path) );
     } else {
-        bstring dbpath;
-        val = atalk_iniparser_getstring(obj->iniconfig, section, "vol dbpath", NULL);
+        char *global_path;
+        val = getoption(obj->iniconfig, section, "vol dbpath", preset, NULL);
+        if (val == NULL) {
+            /* check global option */
+            global_path = atalk_iniparser_getstring(obj->iniconfig,
+                                                    INISEC_GLOBAL,
+                                                    "vol dbpath",
+                                                    NULL);
+            if (global_path) {
+                /* check for pre 3.1.1 behaviour without variable */
+                if (strchr(global_path, '$') == NULL) {
+                    global_path_tmp = bformat("%s/%s/", global_path, tmpname);
+                    val = cfrombstr(global_path_tmp);
+                } else {
+                    val = global_path;
+                }
+            }
+        }
+
         if (val == NULL) {
             EC_NULL( dbpath = bformat("%s/%s/", _PATH_STATEDIR "CNID/", tmpname) );
         } else {
             EC_NULL( dbpath = bfromcstr(val));
         }
         EC_NULL( volume->v_dbpath = volxlate(obj, NULL, MAXPATHLEN + 1,
-                                             cfrombstr(dbpath), pwd, NULL, NULL) );
-        bdestroy(dbpath);
+                                             cfrombstr(dbpath), pwd, NULL, tmpname) );
     }
 
     if ((val = getoption(obj->iniconfig, section, "cnid scheme", preset, NULL)))
@@ -793,6 +841,8 @@ static struct vol *creatvol(AFPObj *obj,
         volume->v_preexec_close = 1;
     if (getoption_bool(obj->iniconfig, section, "root preexec close", preset, 0))
         volume->v_root_preexec_close = 1;
+    if (vdgoption_bool(obj->iniconfig, section, "force xattr with sticky bit", preset, 0))
+        volume->v_flags |= AFPVOL_FORCE_STICKY_XATTR;
 
     if ((val = getoption(obj->iniconfig, section, "ignored attributes", preset, obj->options.ignored_attr))) {
         if (strstr(val, "all")) {
@@ -809,6 +859,19 @@ static struct vol *creatvol(AFPObj *obj,
         }
     }
 
+    val = getoption(obj->iniconfig, section, "chmod request", preset, NULL);
+    if (val == NULL) {
+        val = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "chmod request", "preserve");
+    }
+    if (strcasecmp(val, "ignore") == 0) {
+        volume->v_flags |= AFPVOL_CHMOD_IGNORE;
+    } else if (strcasecmp(val, "preserve") == 0) {
+        volume->v_flags |= AFPVOL_CHMOD_PRESERVE_ACL;
+    } else if (strcasecmp(val, "simple") != 0) {
+        LOG(log_warning, logtype_afpd, "unknown 'chmod request' setting: '%s', using default", val);
+        volume->v_flags |= AFPVOL_CHMOD_PRESERVE_ACL;
+    }
+
     /*
      * Handle read-only behaviour. semantics:
      * 1) neither the rolist nor the rwlist exist -> rw
@@ -834,6 +897,8 @@ static struct vol *creatvol(AFPObj *obj,
         volume->v_ad_options |= ADVOL_FOLLO_SYML;
     if ((volume->v_flags & AFPVOL_RO))
         volume->v_ad_options |= ADVOL_RO;
+    if ((volume->v_flags & AFPVOL_FORCE_STICKY_XATTR))
+        volume->v_ad_options |= ADVOL_FORCE_STICKY_XATTR;
 
     /* Mac to Unix conversion flags*/
     if ((volume->v_flags & AFPVOL_EILSEQ))
@@ -881,7 +946,7 @@ static struct vol *creatvol(AFPObj *obj,
     if ( 0 >= ( u8mvlen = convert_string(CH_UTF8_MAC, CH_UCS2, tmpname, tmpvlen, u8mtmpname, AFPVOL_U8MNAMELEN*2)) )
         EC_FAIL;
 
-    LOG(log_maxdebug, logtype_afpd, "createvol: Volume '%s' -> UTF8-MAC Name: '%s'", name, tmpname);
+    LOG(log_maxdebug, logtype_afpd, "creatvol: Volume '%s' -> UTF8-MAC Name: '%s'", name, tmpname);
 
     /* Maccharset Volume Name */
     /* Firsty convert name from unixcharset to maccharset */
@@ -919,7 +984,7 @@ static struct vol *creatvol(AFPObj *obj,
                                          AFPVOL_U8MNAMELEN*2)) )
         EC_FAIL;
 
-    LOG(log_maxdebug, logtype_afpd, "createvol: Volume '%s' ->  Longname: '%s'", name, tmpname);
+    LOG(log_maxdebug, logtype_afpd, "creatvol: Volume '%s' ->  Longname: '%s'", name, tmpname);
 
     EC_NULL( volume->v_localname = strdup(name) );
     EC_NULL( volume->v_u8mname = strdup_w(u8mtmpname) );
@@ -967,7 +1032,11 @@ static struct vol *creatvol(AFPObj *obj,
     volume->v_obj = obj;
 
 EC_CLEANUP:
-    LOG(log_debug, logtype_afpd, "createvol: END: %d", ret);
+    LOG(log_debug, logtype_afpd, "creatvol: END: %d", ret);
+    if (dbpath)
+        bdestroy(dbpath);
+    if (global_path_tmp)
+        bdestroy(global_path_tmp);
     if (ret != 0) {
         if (volume)
             volume_free(volume);
@@ -1035,12 +1104,17 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
                 || strcmp(obj->username, obj->options.guest) == 0)
                 /* not an AFP session, but cnid daemon, dbd or ad util, or guest login */
                 continue;
-            if (pwent->pw_dir == NULL || STRCMP("", ==, pwent->pw_dir))
-                /* no user home */
+            if (pwent->pw_dir == NULL || STRCMP("", ==, pwent->pw_dir)) {
+                LOG(log_debug, logtype_afpd, "readvolfile: pwent->pw_dir: NULL or \"\" - no user home");
                 continue;
+            }
+            LOG(log_debug, logtype_afpd, "readvolfile: pwent->pw_dir: '%s'", pwent->pw_dir);
 
-            if ((realpath(pwent->pw_dir, tmp)) == NULL)
+            if ((realpath(pwent->pw_dir, tmp)) == NULL) {
+                LOG(log_debug, logtype_afpd, "readvolfile: Cannot get realpath '%s' (%s).", pwent->pw_dir, strerror(errno));
                 continue;
+            }
+            LOG(log_debug, logtype_afpd, "readvolfile: realpath pwent->pw_dir: '%s'", tmp);
 
             /* check if user home matches our "basedir regex" */
             if ((basedir = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL) {
@@ -1573,7 +1647,7 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     struct vol *tmp;
     const struct passwd *pw;
     char        volname[AFPVOL_U8MNAMELEN + 1];
-    char        abspath[MAXPATHLEN + 1];
+    char        *realabspath = NULL;
     char        volpath[MAXPATHLEN + 1], *realvolpath = NULL;
     char        tmpbuf[MAXPATHLEN + 1];
     const char *secname, *basedir, *p = NULL, *subpath = NULL, *subpathconfig;
@@ -1582,19 +1656,22 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
 
     LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\")", path);
 
-    if (path[0] != '/') {
-        /* relative path, build absolute path */
-        EC_NULL_LOG( getcwd(abspath, MAXPATHLEN) );
-        strlcat(abspath, "/", MAXPATHLEN);
-        strlcat(abspath, path, MAXPATHLEN);
-        path = abspath;
-    }
-
+    /*  build absolute path */
+    EC_NULL( realabspath = realpath_safe(path) );
+    path = realabspath;
 
     for (tmp = Volumes; tmp; tmp = tmp->v_next) { /* (1) */
-        if (strncmp(path, tmp->v_path, strlen(tmp->v_path)) == 0) {
-            vol = tmp;
-            goto EC_CLEANUP;
+        size_t v_path_len = strlen(tmp->v_path);
+        if (strncmp(path, tmp->v_path, v_path_len) == 0) {
+            if (v_path_len < strlen(path) && path[v_path_len] != '/') {
+                LOG(log_debug, logtype_afpd, "getvolbypath: path(\"%s\") != volume(\"%s\")", path, tmp->v_path);
+            } else {
+                LOG(log_debug, logtype_afpd, "getvolbypath: path(\"%s\") == volume(\"%s\")", path, tmp->v_path);
+                vol = tmp;
+                goto EC_CLEANUP;
+            }
+        } else {
+            LOG(log_debug, logtype_afpd, "getvolbypath: path(\"%s\") != volume(\"%s\")", path, tmp->v_path);
         }
     }
 
@@ -1639,7 +1716,7 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     strlcat(tmpbuf, "/", MAXPATHLEN);
 
     /* (5) */
-    p = path + strlen(basedir);
+    p = path + match[0].rm_eo - match[0].rm_so;
     while (*p == '/')
         p++;
     EC_NULL_LOG( user = strdup(p) );
@@ -1650,13 +1727,15 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
         subpath = prw;
 
     strlcat(tmpbuf, user, MAXPATHLEN);
-    if (getpwnam(user) == NULL) {
+    if ((pw = getpwnam(user)) == NULL) {
         /* (5b) */
         char *tuser;
         if ((tuser = getuserbypath(tmpbuf)) != NULL) {
             free(user);
             user = strdup(tuser);
         }
+        if ((pw = getpwnam(user)) == NULL)
+            EC_FAIL_LOG("unknown user: %s", user);
     }
     strlcpy(obj->username, user, MAXUSERLEN);
     strlcat(tmpbuf, "/", MAXPATHLEN);
@@ -1701,6 +1780,8 @@ EC_CLEANUP:
         free(user);
     if (realvolpath)
         free(realvolpath);
+    if (realabspath)
+        free(realabspath);
     if (ret != 0)
         vol = NULL;
     return vol;
@@ -1783,6 +1864,8 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
         options->passwdbits |= PASSWD_NOSAVE;
     if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0))
         options->passwdbits |= PASSWD_SET;
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "spotlight expr", 1))
+        options->flags |= OPTION_SPOTLIGHT_EXPR;
 
     /* figure out options w values */
     options->loginmesg      = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "login message",  NULL);
@@ -1821,6 +1904,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     options->sleep          = atalk_iniparser_getint   (config, INISEC_GLOBAL, "sleep time",     10);
     options->disconnected   = atalk_iniparser_getint   (config, INISEC_GLOBAL, "disconnect time",24);
     options->splice_size    = atalk_iniparser_getint   (config, INISEC_GLOBAL, "splice size",    64*1024);
+    options->sparql_limit   = atalk_iniparser_getint   (config, INISEC_GLOBAL, "sparql results limit", 0);
 
     p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "map acls", "rights");
     if (STRCMP(p, ==, "rights"))
index c7ef534a7e556567bda75e22eb3048a4616816ae..60768a618708488e52160c62ea91b69b13aa6b4e 100644 (file)
@@ -503,113 +503,112 @@ EC_CLEANUP:
     EC_EXIT;
 }
 
-/*!
- * Add a fd to a dynamic pollfd array that is allocated and grown as needed
- *
- * This uses an additional array of struct polldata which stores type information
- * (enum fdtype) and a pointer to anciliary user data.
- *
- * 1. Allocate the arrays with the size of "maxconns" if *fdsetp is NULL.
- * 2. Fill in both array elements and increase count of used elements
- * 
- * @param maxconns    (r)  maximum number of connections, determines array size
- * @param fdsetp      (rw) pointer to callers pointer to the pollfd array
- * @param polldatap   (rw) pointer to callers pointer to the polldata array
- * @param fdset_usedp (rw) pointer to an int with the number of used elements
- * @param fdset_sizep (rw) pointer to an int which stores the array sizes
- * @param fd          (r)  file descriptor to add to the arrays
- * @param fdtype      (r)  type of fd, currently IPC_FD or LISTEN_FD
- * @param data        (rw) pointer to data the caller want to associate with an fd
- */
-void fdset_add_fd(int maxconns,
-                  struct pollfd **fdsetp,
-                  struct polldata **polldatap,
-                  int *fdset_usedp,
-                  int *fdset_sizep,
-                  int fd,
-                  enum fdtype fdtype,
-                  void *data)
+/**
+ * Allocate and initialize atalk socket event struct
+ **/
+struct asev *asev_init(int max)
 {
-    struct pollfd *fdset = *fdsetp;
-    struct polldata *polldata = *polldatap;
-    int fdset_size = *fdset_sizep;
+    struct asev *asev = calloc(1, sizeof(struct asev));
+
+    if (asev == NULL) {
+        return NULL;
+    }
 
-    LOG(log_debug, logtype_default, "fdset_add_fd: adding fd %i in slot %i", fd, *fdset_usedp);
+    /* Initialize with space for all possibly active fds */
+    asev->fdset = calloc(max, sizeof(struct pollfd));
+    asev->data = calloc(max, sizeof(struct asev_data));
 
-    if (fdset == NULL) { /* 1 */
-        /* Initialize with space for all possibly active fds */
-        fdset = calloc(maxconns, sizeof(struct pollfd));
-        if (! fdset)
-            exit(EXITERR_SYS);
+    if (asev->fdset == NULL || asev->data == NULL) {
+        free(asev->fdset);
+        free(asev->data);
+        free(asev);
+        return NULL;
+    }
 
-        polldata = calloc(maxconns, sizeof(struct polldata));
-        if (! polldata)
-            exit(EXITERR_SYS);
+    asev->max = max;
+    asev->used = 0;
 
-        fdset_size = maxconns;
+    return asev;
+}
 
-        *fdset_sizep = fdset_size;
-        *fdsetp = fdset;
-        *polldatap = polldata;
+/**
+ * Add a fd to a dynamic pollfd array and associated data array
+ *
+ * This uses an additional array of struct polldata which stores type
+ * information (enum fdtype) and a pointer to anciliary user data.
+ **/
+bool asev_add_fd(struct asev *asev,
+                 int fd,
+                 enum asev_fdtype fdtype,
+                 void *private)
+{
+    if (asev == NULL) {
+        return false;
+    }
 
-        LOG(log_debug, logtype_default, "fdset_add_fd: initialized with space for %i conncections", 
-            maxconns);
+    if (!(asev->used < asev->max)) {
+        return false;
     }
 
-    /* 2 */
-    fdset[*fdset_usedp].fd = fd;
-    fdset[*fdset_usedp].events = POLLIN;
-    polldata[*fdset_usedp].fdtype = fdtype;
-    polldata[*fdset_usedp].data = data;
-    (*fdset_usedp)++;
+    asev->fdset[asev->used].fd = fd;
+    asev->fdset[asev->used].events = POLLIN;
+    asev->data[asev->used].fdtype = fdtype;
+    asev->data[asev->used].private = private;
+    asev->used++;
+
+    return true;
 }
 
-/*!
- * Remove a fd from our pollfd array
- *
- * 1. Search fd
- * 2a Matched last (or only) in the set ? null it and return
- * 2b If we remove the last array elemnt, just decrease count
- * 3. If found move all following elements down by one
- * 4. Decrease count of used elements in array
- *
- * This currently doesn't shrink the allocated storage of the array.
+/**
+ * Remove fd from asev
  *
- * @param fdsetp      (rw) pointer to callers pointer to the pollfd array
- * @param polldatap   (rw) pointer to callers pointer to the polldata array
- * @param fdset_usedp (rw) pointer to an int with the number of used elements
- * @param fdset_sizep (rw) pointer to an int which stores the array sizes
- * @param fd          (r)  file descriptor to remove from the arrays
- */
-void fdset_del_fd(struct pollfd **fdsetp,
-                  struct polldata **polldatap,
-                  int *fdset_usedp,
-                  int *fdset_sizep _U_,
-                  int fd)
+ * @returns true if the fd was deleted, otherwise false
+ **/
+bool asev_del_fd(struct asev *asev, int fd)
 {
-    struct pollfd *fdset = *fdsetp;
-    struct polldata *polldata = *polldatap;
-
-    if (*fdset_usedp < 1)
-        return;
-
-    for (int i = 0; i < *fdset_usedp; i++) {
-        if (fdset[i].fd == fd) { /* 1 */
-            if ((i + 1) == *fdset_usedp) { /* 2a */
-                fdset[i].fd = -1;
-                memset(&polldata[i], 0, sizeof(struct polldata));
-            } else if (i < (*fdset_usedp - 1)) { /* 2b */
-                memmove(&fdset[i],
-                        &fdset[i+1],
-                        (*fdset_usedp - i - 1) * sizeof(struct pollfd)); /* 3 */
-                memmove(&polldata[i],
-                        &polldata[i+1],
-                        (*fdset_usedp - i - 1) * sizeof(struct polldata)); /* 3 */
+    int i;
+    int numafter;
+
+    if (asev == NULL) {
+        return false;
+    }
+
+    if (asev->used == 0) {
+        LOG(log_error, logtype_cnid, "asev_del_fd: empty");
+        return false;
+    }
+
+    for (i = 0; i < asev->used; i++) {
+        /*
+         * Scan the array for a matching fd
+         */
+        if (asev->fdset[i].fd == fd) {
+            /*
+             * found fd
+             */
+            if ((i + 1) == asev->used) {
+                /*
+                 * it's the last (or only) array element, simply null it
+                 */
+                asev->fdset[i].fd = -1;
+                asev->data[i].fdtype = 0;
+                asev->data[i].private = NULL;
+            } else {
+                /*
+                 * Move down by one all subsequent elements
+                 */
+                numafter = asev->used - (i + 1);
+                memmove(&asev->fdset[i], &asev->fdset[i+1],
+                        numafter * sizeof(struct pollfd));
+                memmove(&asev->data[i], &asev->data[i+1],
+                        numafter * sizeof(struct asev_data));
             }
-            (*fdset_usedp)--;
-            break;
+            asev->used--;
+            return true;
         }
     }
+
+    return false;
 }
 
 /* Length of the space taken up by a padded control message of length len */
index 37bfe140fe3d1d0101ab966a55ee90db3f67b9d8..4572caddd454d36c1b0cd3e45b6b258b7aedadf3 100644 (file)
@@ -44,6 +44,7 @@
 #include <atalk/unix.h>
 #include <atalk/compat.h>
 #include <atalk/errchk.h>
+#include <atalk/acl.h>
 
 /* close all FDs >= a specified value */
 static void closeall(int fd)
@@ -262,11 +263,15 @@ int ochown(const char *path, uid_t owner, gid_t group, int options)
  * Options description:
  * O_NOFOLLOW: don't chmod() symlinks, do nothing, return 0
  * O_NETATALK_ACL: call chmod_acl() instead of chmod()
+ * O_IGNORE: ignore chmod() request, directly return 0
  */
 int ochmod(char *path, mode_t mode, const struct stat *st, int options)
 {
     struct stat sb;
 
+    if (options & O_IGNORE)
+        return 0;
+
     if (!st) {
         if (lstat(path, &sb) != 0)
             return -1;
@@ -436,7 +441,7 @@ char *realpath_safe(const char *path)
 
 #ifdef REALPATH_TAKES_NULL
     if ((resolved_path = realpath(path, NULL)) == NULL) {
-        LOG(log_error, logtype_afpd, "realpath() cannot resolve path \"%s\"", path);
+        LOG(log_debug, logtype_afpd, "realpath() cannot resolve path \"%s\"", path);
         return NULL;
     }
     return resolved_path;
@@ -445,7 +450,7 @@ char *realpath_safe(const char *path)
         return NULL;
     if (realpath(path, resolved_path) == NULL) {
         free(resolved_path);
-        LOG(log_error, logtype_afpd, "realpath() cannot resolve path \"%s\"", path);
+        LOG(log_debug, logtype_afpd, "realpath() cannot resolve path \"%s\"", path);
         return NULL;
     }
     /* Safe some memory */
index 73724d53080d66908ae3c07fa9166f58c10bd45e..4a338bae5a3869f2417bc2cdbe6f2f03290bf9bc 100644 (file)
@@ -240,17 +240,22 @@ ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t
        return lgetea(path, name, value, size);
 #elif defined(HAVE_EXTATTR_GET_LINK)
        ssize_t retval;
-       if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) {
-               if(retval > size) {
-                       errno = ERANGE;
-                       return -1;
-               }
-               if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0)
-                       return retval;
-       }
-       
-       LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno));
-       return -1;
+
+       retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0);
+    if (retval == -1) {
+        LOG(log_maxdebug, logtype_default, "extattr_get_link(): %s",
+            strerror(errno));
+        return -1;
+    }
+    if (size == 0)
+        /* Only interested in size of xattr */
+        return retval;
+    if (retval > size) {
+        errno = ERANGE;
+        return -1;
+    }
+    return extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size);
+
 #elif defined(HAVE_ATTR_GET)
        int retval, flags = ATTR_DONTFOLLOW;
        int valuelength = (int)size;
index 79e4fd33c29b151a08cd4afb4b157c638ea444b4..846aa7206933defac01a2efff09db8831bed77d1 100644 (file)
@@ -46,7 +46,11 @@ int setfilmode(const struct vol *vol, const char *name, mode_t mode, struct stat
 
     mode |= st->st_mode & ~mask; /* keep other bits from previous mode */
 
-    if (ochmod((char *)name, mode & ~vol->v_umask, st, vol_syml_opt(vol) | O_NETATALK_ACL) < 0 && errno != EPERM ) {
+    if (ochmod((char *)name,
+               mode & ~vol->v_umask,
+               st,
+               vol_syml_opt(vol) | vol_chmod_opt(vol)
+            ) < 0 && errno != EPERM ) {
         return -1;
     }
     return 0;
index 52c6ea84945b3bffe491df06942d266cc138b404..0d1961cfa92c393065c8ab0128e72031fd57e0d0 100644 (file)
@@ -172,7 +172,11 @@ static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE)
     const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
 
     if (dir_rx_set(mode)) {
-        if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0 ) 
+        if (ochmod(ad_dir(adouble),
+                   (DIRBITS | mode) & ~vol->v_umask,
+                   st,
+                   vol_syml_opt(vol) | vol_chmod_opt(vol)
+                ) < 0)
             return -1;
     }
 
@@ -180,7 +184,11 @@ static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE)
         return -1;
 
     if (!dir_rx_set(mode)) {
-        if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0 ) 
+        if (ochmod(ad_dir(adouble),
+                   (DIRBITS | mode) & ~vol->v_umask,
+                   st,
+                   vol_syml_opt(vol) | vol_chmod_opt(vol)
+                ) < 0)
             return  -1 ;
     }
     return 0;
@@ -212,7 +220,11 @@ static int RF_setdirmode_adouble(VFS_FUNC_ARGS_SETDIRMODE)
     const char  *adouble_p = ad_dir(adouble);
 
     if (dir_rx_set(mode)) {
-        if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0) 
+        if (ochmod(ad_dir(adouble),
+                   (DIRBITS | mode) & ~vol->v_umask,
+                   st,
+                   vol_syml_opt(vol) | vol_chmod_opt(vol)
+                ) < 0)
             return -1;
     }
 
@@ -220,7 +232,11 @@ static int RF_setdirmode_adouble(VFS_FUNC_ARGS_SETDIRMODE)
         return -1;
 
     if (!dir_rx_set(mode)) {
-        if (chmod_acl(ad_dir(adouble), (DIRBITS | mode) & ~vol->v_umask) < 0) 
+        if (ochmod(ad_dir(adouble),
+                   (DIRBITS | mode) & ~vol->v_umask,
+                   st,
+                   vol_syml_opt(vol) | vol_chmod_opt(vol)
+                ) < 0)
             return  -1 ;
     }
     return 0;
index ad233a9bd0d7493738f6792852ca363f74247224..fb60ce9a11ff817b57bc0308de69bf64fc6c9a76 100644 (file)
@@ -31,7 +31,7 @@
 dbd \- CNID database maintenance
 .SH "SYNOPSIS"
 .HP \w'\fBdbd\fR\fB\fR\ 'u
-\fBdbd\fR\fB\fR [\-fsv] \fIvolumepath\fR
+\fBdbd\fR\fB\fR [\-cfFstuvV] \fIvolumepath\fR
 .SH "DESCRIPTION"
 .PP
 \fBdbd\fR
@@ -63,6 +63,11 @@ scan volume: treat the volume as read only and don\*(Aqt perform any filesystem
 show statistics while running
 .RE
 .PP
+\-u
+.RS 4
+username for use with AFP volumes using user variable $u
+.RE
+.PP
 \-v
 .RS 4
 verbose
index a375d44a6a19562149ab7d09e2aa4c5554c358fd..2adf39a01518cf4d5c2551e2915ee264aa194275 100644 (file)
@@ -2,12 +2,12 @@
 .\"     Title: afp.conf
 .\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
 .\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\"      Date: 09 Feb 2013
+.\"      Date: 05 Jun 2014
 .\"    Manual: @NETATALK_VERSION@
 .\"    Source: @NETATALK_VERSION@
 .\"  Language: English
 .\"
-.TH "AFP\&.CONF" "5" "09 Feb 2013" "@NETATALK_VERSION@" "@NETATALK_VERSION@"
+.TH "AFP\&.CONF" "5" "05 Jun 2014" "@NETATALK_VERSION@" "@NETATALK_VERSION@"
 .\" -----------------------------------------------------------------
 .\" * Define some portability stuff
 .\" -----------------------------------------------------------------
@@ -174,7 +174,7 @@ in parentheses indicates that a parameter is specific to the [Global] section\&.
 indicates that a parameter can be specified in a volume specific section\&.
 .SH "VARIABLE SUBSTITUTIONS"
 .PP
-You can use variables in volume names\&. The use of variables in paths is not supported for now\&.
+You can use variables in volume names\&. The use of variables in paths is limited to $u\&.
 .sp
 .RS 4
 .ie n \{\
@@ -538,6 +538,50 @@ contains symlink, you must set the canonicalized absolute path\&. In the simple
 \fBbasedir regex = /home\fR
 .RE
 .PP
+chmod request = \fIpreserve (default) | ignore | simple\fR \fB(G/V)\fR
+.RS 4
+Advanced permission control that deals with ACLs\&.
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+
+\fBignore\fR
+\- UNIX chmod() requests are completely ignored
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+
+\fBpreserve\fR
+\- preserve ZFS ACEs for named users and groups or POSIX ACL group mask
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+
+\fBsimple\fR
+\- just to a chmod() as requested without any extra steps
+.RE
+.RE
+.PP
 close vol = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
 .RS 4
 Whether to close volumes possibly opened by clients when they\*(Aqre removed from the configuration and the configuration is reloaded\&.
@@ -586,6 +630,13 @@ extmap file = \fIpath\fR \fB(G)\fR
 Sets the path to the file which defines file extension type/creator mappings\&. (default is @pkgconfdir@/extmap\&.conf)\&.
 .RE
 .PP
+force xattr with sticky bit = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G/V)\fR
+.RS 4
+Writing metadata xattr on directories with the sticky bit set may fail even though we may have write access to a directory, because if the sticky bit is set only the owner is allowed to write xattrs\&.
+.sp
+By enabling this option Netatalk will write the metadata xattr as root\&.
+.RE
+.PP
 guest account = \fIname\fR \fB(G)\fR
 .RS 4
 Specifies the user that guests should use (default is "nobody")\&. The name should be quoted\&.
@@ -631,6 +682,11 @@ solaris share reservations = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(G)\fR
 Use share reservations on Solaris\&. Solaris CIFS server uses this too, so this makes a lock coherent multi protocol server\&.
 .RE
 .PP
+sparql results limit = \fINUMBER\fR (default: \fIUNLIMITED\fR) \fB(G)\fR
+.RS 4
+Impose a limit on the number of results queried from Tracker via SPARQL queries\&.
+.RE
+.PP
 spotlight = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)/(V)\fR
 .RS 4
 Whether to enable Spotlight searches\&. Note: once the global option is enabled, any volume that is not enabled won\*(Aqt be searchable at all\&. See also
@@ -638,15 +694,48 @@ Whether to enable Spotlight searches\&. Note: once the global option is enabled,
 option\&.
 .RE
 .PP
+spotlight attributes = \fICOMMA SEPERATED STRING\fR (default: \fIEMPTY\fR) \fB(G)\fR
+.RS 4
+A list of attributes that are allowed to be used in Spotlight searches\&. By default all attributes can be searched, passing a string limits attributes to elements of the string\&. Example:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+spotlight
+            attributes = *,kMDItemTextContent
+.fi
+.if n \{\
+.RE
+.\}
+.sp
+.RE
+.PP
+spotlight expr = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(G)\fR
+.RS 4
+Whether to allow the use of logic expression in searches\&.
+.RE
+.PP
+start dbus = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(G)\fR
+.RS 4
+Whether to start a dbus instance for use with Tracker\&.
+.RE
+.PP
+start tracker = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(G)\fR
+.RS 4
+Whether to start Tracker with
+\fItracker\-control \-s\fR\&.
+.RE
+.PP
 veto message = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
 .RS 4
 Send optional AFP messages for vetoed files\&. 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\&.
 .RE
 .PP
-vol dbpath = \fIpath\fR \fB(G)\fR
+vol dbpath = \fIpath\fR \fB(G)/(V)\fR
 .RS 4
 Sets the database information to be stored in path\&. You have to specify a writable location, even if the volume is read only\&. The default is
-@localstatedir@/netatalk/CNID/\&.
+@localstatedir@/netatalk/CNID/$v/\&.
 .RE
 .PP
 vol dbnest = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
@@ -719,6 +808,107 @@ Both logtype and loglevels are case insensitive\&.
 .PP
 Netatalk includes a nifty filesystem change event mechanism where afpd processes notify interested listeners about certain filesystem event by UDP network datagrams\&.
 .PP
+The following FCE events are defined:
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+file modification (\fBfmod\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+file deletion (\fBfdel\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+directory deletion (\fBddel\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+file creation (\fBfcre\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+directory creation (\fBdcre\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+file move or rename (\fBfmov\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+directory move or rename (\fBdmov\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+login (\fBlogin\fR)
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+logout (\fBlogout\fR)
+.RE
+.PP
 fce listener = \fIhost[:port]\fR \fB(G)\fR
 .RS 4
 Enables sending FCE events to the specified
@@ -727,7 +917,12 @@ Enables sending FCE events to the specified
 is 12250 if not specified\&. Specifying multiple listeners is done by having this option once for each of them\&.
 .RE
 .PP
-fce events = \fIfmod,fdel,ddel,fcre,dcre,tmsz\fR \fB(G)\fR
+fce version = \fI1|2\fR \fB(G)\fR
+.RS 4
+FCE protocol version, default is 1\&. You need version 2 for the fmov, dmov, login or logout events\&.
+.RE
+.PP
+fce events = \fIfmod,fdel,ddel,fcre,dcre,fmov,dmov,login,logout\fR \fB(G)\fR
 .RS 4
 Specifies which FCE events are active, default is
 \fIfmod,fdel,ddel,fcre,dcre\fR\&.
@@ -742,6 +937,16 @@ fce holdfmod = \fIseconds\fR \fB(G)\fR
 .RS 4
 This determines the time delay in seconds which is always waited if another file modification for the same file is done by a client before sending an FCE file modification event (fmod)\&. For example saving a file in Photoshop would generate multiple events by itself because the application is opening, modifying and closing a file multiple times for every "save"\&. Default: 60 seconds\&.
 .RE
+.PP
+fce ignore names = \fINAME[/NAME2/\&.\&.\&.]\fR \fB(G)\fR
+.RS 4
+Slash delimited list of filenames for which FCE events shall not be generated\&. Default: \&.DS_Store\&.
+.RE
+.PP
+fce notify script = \fIPATH\fR \fB(G)\fR
+.RS 4
+Script which will be executed for every FCE event, see contrib/shell_utils/fce_ev_script\&.shfrom the Netatalk sources for an example script\&.
+.RE
 .SS "Debug Parameters"
 .PP
 These options are useful for debugging only\&.