]> arthur.barton.de Git - netatalk.git/commitdiff
Merge branch 'branch-release-3.0.5'
authorRalph Boehme <sloowfranklin@gmail.com>
Wed, 14 Aug 2013 09:51:46 +0000 (11:51 +0200)
committerRalph Boehme <sloowfranklin@gmail.com>
Wed, 14 Aug 2013 09:51:46 +0000 (11:51 +0200)
57 files changed:
NEWS
VERSION
bin/misc/uuidtest.c
configure.ac
distrib/initscripts/rc.netbsd.tmpl
doc/DEVELOPER
doc/Makefile.am
doc/manpages/man1/Makefile.am
doc/manpages/man5/Makefile.am
doc/manpages/man5/afp.conf.5.xml
doc/manpages/man8/Makefile.am
doc/manual/.gitignore
doc/manual/Makefile.am
doc/manual/manual.xml.in
doc/manual/netatalk.html [new file with mode: 0644]
doc/manual/upgrade.xml
doc/netatalk.html [deleted file]
doc/www/.gitignore [new file with mode: 0644]
doc/www/ReleaseNotes
etc/afpd/afp_config.c
etc/afpd/directory.c
etc/afpd/file.c
etc/afpd/filedir.c
etc/afpd/filedir.h
etc/afpd/messages.c
etc/afpd/volume.c
etc/cnid_dbd/cnid_metad.c
include/atalk/adouble.h
include/atalk/dictionary.h
include/atalk/dsi.h
include/atalk/globals.h
include/atalk/iniparser.h
include/atalk/util.h
include/atalk/volume.h
libatalk/Makefile.am
libatalk/acl/ldap_config.c
libatalk/adouble/ad_open.c
libatalk/dsi/dsi_close.c
libatalk/dsi/dsi_cmdreply.c
libatalk/dsi/dsi_getsess.c
libatalk/dsi/dsi_getstat.c
libatalk/dsi/dsi_opensess.c
libatalk/dsi/dsi_read.c
libatalk/dsi/dsi_stream.c
libatalk/dsi/dsi_tcp.c
libatalk/dsi/dsi_write.c
libatalk/iniparser/dictionary.c
libatalk/iniparser/iniparser.c
libatalk/libatalk-3.0.5.abi [new file with mode: 0644]
libatalk/util/netatalk_conf.c
libatalk/util/socket.c
libatalk/vfs/unix.c
libatalk/vfs/vfs.c
macros/db3-check.m4
macros/netatalk.m4
macros/summary.m4
man/man5/afp.conf.5.in

diff --git a/NEWS b/NEWS
index 8eac3474d523b14d5345e3cc0a1a3835759330a9..98e2d2b5d969a81152012627bd00c48b2110f7aa 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,21 @@
+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
diff --git a/VERSION b/VERSION
index b38ebbfce26aa93c94f0743a690abe4929d6b5e1..7da3c16870e856cce1a539d478294b4030dac60d 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-3.0.4
\ No newline at end of file
+3.0.5
\ No newline at end of file
index 030a4f522d7d3fabafddbcc601caf130123aff17..d2548921283eabf15cada777a749f61377de6f2b 100644 (file)
@@ -48,7 +48,7 @@ static void parse_ldapconf()
 #ifdef HAVE_LDAP
         /* Parse afp.conf */
         printf("Start parsing afp.conf\n");
-        iniconfig = iniparser_load(_PATH_CONFDIR "afp.conf");
+        iniconfig = atalk_iniparser_load(_PATH_CONFDIR "afp.conf");
         acl_ldap_readconfig(iniconfig);
         printf("Finished parsing afp.conf\n");
         if (ldap_config_valid) {
index e4d910c33fdb4e998475e5ff1e3251e91fafe267..c3c695cebf6918dff60efd9cd8b340fd7c8b0584 100644 (file)
@@ -200,7 +200,7 @@ AC_NETATALK_LOCKFILE
 dnl Check for Docbook and build documentation if found
 AX_CHECK_DOCBOOK
 
-CFLAGS="-I\$(top_srcdir)/include -I\$(top_builddir)/include $CFLAGS"
+CPPFLAGS="-I\$(top_srcdir)/include -I\$(top_builddir)/include $CPPFLAGS"
 UAMS_PATH="${uams_path}"
 
 AC_SUBST(LIBS)
index 1f84c4398fa761bbd72d0ff71df7773dbf9959e4..af5602a581fc4dfe3e272718dc06e44225be1af7 100644 (file)
@@ -13,7 +13,7 @@ rcvar=$name
 command=":SBINDIR:/netatalk"
 etcdir=":ETCDIR:"
 pidfile="/var/run/${name}.pid"
-required_files="$etcdir/afp.conf
+required_files="$etcdir/afp.conf"
 
 load_rc_config $name
 run_rc_command "$1"
index 2ddb69f6fc410e91078436ff7b3ca81406592300..d0f8b5b58eb4dd51902d3d7d6d48ab1b7e6e933e 100644 (file)
@@ -200,9 +200,9 @@ The ini parser is taken from <http://ndevilla.free.fr/iniparser/>.
 It has been slightly modified:
 - case-sensitive
 - "include" directive added
-- iniparser_getstrdup() to complemnt iniparser_getstring(), it return allocated
+- atalk_iniparser_getstrdup() to complemnt atalk_iniparser_getstring(), it return allocated
   strings which the caller must free as necessary
-- the API has been modifed such that all iniparser_get* funcs take a section and
+- the API has been modifed such that all atalk_iniparser_get* funcs take a section and
   a parameter as sepereta args instead of one string of the form "section:parameter"
   in the original library
 
index e1b356f1a8b62786d6131a5023817d902ef90c66..c44790fa1921d44626b576b082ef07a54a634b68 100644 (file)
@@ -1,9 +1,9 @@
 SUBDIRS = manpages manual
-XSLTPROC=@XSLTPROC@
-XSLTPROC_FLAGS=@XSLTPROC_FLAGS@
-XHTML_STYLESHEET=$(top_srcdir)/doc/html.xsl
-
-htmldir = $(prefix)/share/doc/@PACKAGE@
-dist_html_DATA = @PACKAGE@.html
 
 DISTCLEANFILES = html.xsl man.xsl
+
+release-notes: www/ReleaseNotes
+       cd www && ./create-relnotes.sh
+
+upload-release-notes: release-notes
+       scp www/ReleaseNotes.html $$USER,netatalk@web.sourceforge.net:/home/project-web/netatalk/htdocs/3.0/ReleaseNotes$(VERSION).html
index dc3d65898cd0cbf553d601cac03ff0cf4aee9e99..fbb1848bce78ae6ce49154d0e9b5bcc024bd9292 100644 (file)
@@ -32,9 +32,9 @@ EXTRA_DIST = \
 if HAVE_XSLTPROC
 CLEANFILES += $(MAN_MANPAGES)
 
-%.1 : $(MAN_STYLESHEET) %.1.xml
+%.1 : %.1.xml
        @xsltproc $(MAN_STYLESHEET) $<
        @cp $@ $(top_builddir)/man/man1/$@.in
 
-html-local: $(MAN_MANPAGES)
-endif
\ No newline at end of file
+html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET)
+endif
index 82fee7c110334c8db899a405ca9393c46a3f44d7..1af573470cb980a23535d03c4a47b235c2528c73 100644 (file)
@@ -18,9 +18,9 @@ EXTRA_DIST = \
 if HAVE_XSLTPROC
 CLEANFILES += $(MAN_MANPAGES)
 
-%.5 : $(MAN_STYLESHEET) %.5.xml
+%.5 : %.5.xml
        @xsltproc $(MAN_STYLESHEET) $<
        @cp $@ $(top_builddir)/man/man5/$@.in
 
-html-local: $(MAN_MANPAGES)
+html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET)
 endif
\ No newline at end of file
index a09eec5bf018446be2704b75104d8b3303b95f57..27e8b14e81d3aff738e6a25aeeeea572392e252c 100644 (file)
             any incoming request. The network address may be specified either
             in dotted-decimal format for IPv4 or in hexadecimal format for
             IPv6.</para>
+            <para>IPv6 address + port combination must use URL the format
+            using square brackets [IPv6]:port</para>
           </listitem>
         </varlistentry>
 
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>ignored attributes = <replaceable>all | nowrite | nodelete | norename</replaceable>
+          <type>(G)/(V)</type></term>
+
+          <listitem>
+            <para>Speficy a set of file and directory attributes that shall
+            be ignored by the server, <attribute>all</attribute> includes all
+            the other options.</para>
+            <para>In OS X when the Finder sets a lock on a file/directory or you
+            set the BSD uchg flag in the Terminal, all three attributes are
+            used. Thus in order to ignore the Finder lock/BSD uchg flag, add
+            set <emphasis>ignored attributes = all</emphasis>.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>mimic model = <replaceable>model</replaceable>
           <type>(G)</type></term>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>veto message = <replaceable>BOOLEAN</replaceable> (default:
+          <emphasis>no</emphasis>) <type>(G)</type></term>
+
+          <listitem>
+            <para>Use section <option>name</option> as option preset for all
+            volumes (when set in the [Global] section) or for one volume (when
+            set in that volume's section).</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>vol dbpath = <replaceable>path</replaceable>
           <type>(G)</type></term>
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term>delete veto files = <replaceable>BOOLEAN</replaceable>
+          (default: <emphasis>no</emphasis>) <type>(V)</type></term>
+
+          <listitem>
+            <para>This option is used when Netatalk is attempting to delete a
+            directory that contains one or more vetoed files or directories
+            (see the veto files option). If this option is set to no (the
+            default) then if a directory contains any non-vetoed files or
+            directories then the directory delete will fail. This is usually
+            what you want.</para>
+            <para>If this option is set to yes, then Netatalk will attempt to
+            recursively delete any files and directories within the vetoed
+            directory.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term>follow symlinks = <replaceable>BOOLEAN</replaceable> (default:
           <emphasis>no</emphasis>) <type>(V)</type></term>
index 3f23a7847817b7891870265948ce9b5a773dcdbc..465977c4247c21866dc1a11b6b824dba1a4ee515 100644 (file)
@@ -18,9 +18,9 @@ EXTRA_DIST = \
 if HAVE_XSLTPROC
 CLEANFILES += $(MAN_MANPAGES)
 
-%.8 : $(MAN_STYLESHEET) %.8.xml
+%.8 : %.8.xml
        @xsltproc $(MAN_STYLESHEET) $<
        @cp $@ $(top_builddir)/man/man8/$@.in
 
-html-local: $(MAN_MANPAGES)
+html-local: $(MAN_MANPAGES) $(MAN_STYLESHEET)
 endif
\ No newline at end of file
index 8eb18aa7890f6df293ecbfa69edb0e6e96962797..ab1918eb62336aa2e955504bfa61bc0da150d9ca 100644 (file)
@@ -1 +1,2 @@
 manual.xml
+*.html
index 7f2b61d2a0d0733e14e4d2a9261aefc1ebe6ed9a..0b3141aba80cc91013ccd3221071f8be828a8c4a 100644 (file)
@@ -1,7 +1,63 @@
-EXTRA_DIST = \
+XSLTPROC=@XSLTPROC@
+XSLTPROC_FLAGS=@XSLTPROC_FLAGS@
+HTML_STYLESHEET=$(top_srcdir)/doc/html.xsl
+CLEANFILES =
+
+XML_PAGES = \
+       manual.xml \
        configuration.xml \
        install.xml \
        intro.xml \
        upgrade.xml
 
+EXTRA_DIST = \
+       manual.xml.in \
+       configuration.xml \
+       install.xml \
+       intro.xml \
+       upgrade.xml \
+       netatalk.html
+
+HTML_PAGES = \
+       ad.1.html \
+       afp.conf.5.html \
+       afpd.8.html \
+       afpldaptest.1.html \
+       afppasswd.1.html \
+       afp_signature.conf.5.html  \
+       afpstats.1.html \
+       afp_voluuid.conf.5.html \
+       apple_dump.1.html \
+       asip-status.pl.1.html \
+       cnid_dbd.8.html \
+       cnid_metad.8.html \
+       configuration.html \
+       dbd.1.html \
+       example-toc.html \
+       extmap.conf.5.html \
+       index.html \
+       installation.html \
+       intro.html \
+       macusers.1.html \
+       man-pages.html \
+       manual-index.html \
+       megatron.1.html \
+       netatalk.8.html \
+       netatalkconfig.1.html \
+       pr01.html \
+       table-toc.html \
+       uniconv.1.html \
+       upgrade.html
+
 DISTCLEANFILES = manual.xml
+
+if HAVE_XSLTPROC
+CLEANFILES += $(HTML_PAGES)
+
+html-local: $(XML_PAGES)
+       @xsltproc $(HTML_STYLESHEET) manual.xml
+
+html-upload: html-local
+       scp $(HTML_PAGES) $$USER,netatalk@web.sourceforge.net:/home/project-web/netatalk/htdocs/3.0/htmldocs/
+
+endif
index eab6e628afb36c73395e30cc8a2a428d7c9b11b2..64ebd6c7eb4260a29a71b1274a5e8bd36510c1ec 100644 (file)
@@ -2,30 +2,30 @@
 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
 "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd" [
 
-<!ENTITY Intro SYSTEM "netatalk/intro.xml">
-<!ENTITY Install SYSTEM "netatalk/install.xml">
-<!ENTITY Upgrade SYSTEM "netatalk/upgrade.xml">
-<!ENTITY Configuration SYSTEM "netatalk/configuration.xml">
-
-<!ENTITY ad.1 SYSTEM "man/man1/ad.1.xml">
-<!ENTITY afpd.8 SYSTEM "man/man8/afpd.8.xml">
-<!ENTITY cnid_dbd.8 SYSTEM "man/man8/cnid_dbd.8.xml">
-<!ENTITY cnid_metad.8 SYSTEM "man/man8/cnid_metad.8.xml">
-<!ENTITY afp.conf.5 SYSTEM "man/man5/afp.conf.5.xml">
-<!ENTITY afp_signature.conf.5 SYSTEM "man/man5/afp_signature.conf.5.xml">
-<!ENTITY afp_voluuid.conf.5 SYSTEM "man/man5/afp_voluuid.conf.5.xml">
-<!ENTITY afpldaptest.1 SYSTEM "man/man1/afpldaptest.1.xml">
-<!ENTITY afppasswd.1 SYSTEM "man/man1/afppasswd.1.xml">
-<!ENTITY afpstats.1 SYSTEM "man/man1/afpstats.1.xml">
-<!ENTITY apple_dump.1 SYSTEM "man/man1/apple_dump.1.xml">
-<!ENTITY extmap.conf.5 SYSTEM "man/man5/extmap.conf.5.xml">
-<!ENTITY macusers.1 SYSTEM "man/man1/macusers.1.xml">
-<!ENTITY megatron.1 SYSTEM "man/man1/megatron.1.xml">
-<!ENTITY netatalk.8 SYSTEM "man/man8/netatalk.8.xml">
-<!ENTITY netatalk-config.1 SYSTEM "man/man1/netatalk-config.1.xml">
-<!ENTITY uniconv.1 SYSTEM "man/man1/uniconv.1.xml">
-<!ENTITY asip-status.pl.1 SYSTEM "man/man1/asip-status.pl.1.xml">
-<!ENTITY dbd.1 SYSTEM "man/man1/dbd.1.xml">
+<!ENTITY Intro SYSTEM "intro.xml">
+<!ENTITY Install SYSTEM "install.xml">
+<!ENTITY Upgrade SYSTEM "upgrade.xml">
+<!ENTITY Configuration SYSTEM "configuration.xml">
+
+<!ENTITY ad.1 SYSTEM "../manpages/man1/ad.1.xml">
+<!ENTITY afpd.8 SYSTEM "../manpages//man8/afpd.8.xml">
+<!ENTITY cnid_dbd.8 SYSTEM "../manpages//man8/cnid_dbd.8.xml">
+<!ENTITY cnid_metad.8 SYSTEM "../manpages//man8/cnid_metad.8.xml">
+<!ENTITY afp.conf.5 SYSTEM "../manpages//man5/afp.conf.5.xml">
+<!ENTITY afp_signature.conf.5 SYSTEM "../manpages//man5/afp_signature.conf.5.xml">
+<!ENTITY afp_voluuid.conf.5 SYSTEM "../manpages//man5/afp_voluuid.conf.5.xml">
+<!ENTITY afpldaptest.1 SYSTEM "../manpages//man1/afpldaptest.1.xml">
+<!ENTITY afppasswd.1 SYSTEM "../manpages//man1/afppasswd.1.xml">
+<!ENTITY afpstats.1 SYSTEM "../manpages//man1/afpstats.1.xml">
+<!ENTITY apple_dump.1 SYSTEM "../manpages//man1/apple_dump.1.xml">
+<!ENTITY extmap.conf.5 SYSTEM "../manpages//man5/extmap.conf.5.xml">
+<!ENTITY macusers.1 SYSTEM "../manpages//man1/macusers.1.xml">
+<!ENTITY megatron.1 SYSTEM "../manpages//man1/megatron.1.xml">
+<!ENTITY netatalk.8 SYSTEM "../manpages//man8/netatalk.8.xml">
+<!ENTITY netatalk-config.1 SYSTEM "../manpages//man1/netatalk-config.1.xml">
+<!ENTITY uniconv.1 SYSTEM "../manpages//man1/uniconv.1.xml">
+<!ENTITY asip-status.pl.1 SYSTEM "../manpages//man1/asip-status.pl.1.xml">
+<!ENTITY dbd.1 SYSTEM "../manpages//man1/dbd.1.xml">
 ]>
 <book id="netatalk-manual">
   <title>Netatalk 3.0 Manual</title>
diff --git a/doc/manual/netatalk.html b/doc/manual/netatalk.html
new file mode 100644 (file)
index 0000000..b0b7904
--- /dev/null
@@ -0,0 +1,14 @@
+<html>
+    <div id="header">
+        <div id="logo"></div>
+        <div id="menlinks">
+          <a href="/" title="Return to Netatalk home">[main]</a>
+          <a href="http://netatalk.sourceforge.net/wiki/" title="Netatalk Wiki">[wiki]</a>
+          <a href="/3.0/htmldocs" title="Netatalk Manual">[documentation]</a>
+          <a href="http://sourceforge.net/project/showfiles.php?group_id=8642" title="Download Netatalk from sourceforge">[downloads]</a>
+          <a href="/support.php" title="Support">[support]</a>
+          <a href="/links.php" title="Netatalk related links">[links]</a>
+          <img src="/gfx/end.gif" alt="" width="125" height="7" />
+        </div>
+    </div>
+</html>
index ebd196339d16db93807070d76afd005c42aa0a7b..43e5e6967fcff4abcc729cf79f1cb996acf112a3 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <chapter id="upgrade">
   <chapterinfo>
-    <date>2.15.2013</date>
+    <date>7.29.2013</date>
 
     <author>
       <firstname>Frank</firstname>
@@ -9,7 +9,7 @@
       <surname>Lahm</surname>
     </author>
 
-    <pubdate>15 Feb, 2013</pubdate>
+    <pubdate>29 Jul, 2013</pubdate>
   </chapterinfo>
 
   <title>Upgrading from Netatalk 2</title>
@@ -95,7 +95,7 @@
                 <listitem>
                   <para>an Extended Attribute named
                   “<filename>org.netatalk.ResourceFork</filename>”
-                  on Solaris (FreeBSD?) w. ZFS, or in</para>
+                  on Solaris w. ZFS, or in</para>
                 </listitem>
 
                 <listitem>
       </orderedlist></para>
   </sect1>
 
-  <sect1>
-    <title>Notes</title>
-
-    <itemizedlist>
-      <listitem>
-        <para>Solaris ZFS permissions</para>
-
-        <para>On Solaris with ZFS you have to make sure users have
-        filesystem permissions to read, create, modify (default: yes) and
-        delete (default: no) extended attributes.</para>
-
-        <para>To grant this right to a group “staff” you’d use this
-        command:</para>
-
-        <para><command>pfexec chmod A+group:staff:RW:fd:allow
-        /Volumes/test/</command></para>
-
-        <para>Remember to run this once before you share a volume so that
-        this permission inherits appropiately (fd flags in above
-        command).</para>
-      </listitem>
-    </itemizedlist>
-  </sect1>
   <sect1>
     <title>Table with old and new configuration file names</title>
     <para><table frame="all">
               <entry>-noacl2maccess</entry>
               <entry>map acls</entry>
               <entry>-</entry>
-              <entry>yes</entry>
+              <entry>rights</entry>
               <entry>(G)</entry>
               <entry>-</entry>
             </row>
               <entry>(V)</entry>
               <entry>-</entry>
             </row>
+            <row>
+              <entry>options:followsymlinks</entry>
+              <entry>follow symlinks</entry>
+              <entry>-</entry>
+              <entry>no</entry>
+              <entry>(V)</entry>
+              <entry>-</entry>
+            </row>
             <row>
               <entry>options:nohex</entry>
               <entry>-</entry>
diff --git a/doc/netatalk.html b/doc/netatalk.html
deleted file mode 100644 (file)
index b0b7904..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
-    <div id="header">
-        <div id="logo"></div>
-        <div id="menlinks">
-          <a href="/" title="Return to Netatalk home">[main]</a>
-          <a href="http://netatalk.sourceforge.net/wiki/" title="Netatalk Wiki">[wiki]</a>
-          <a href="/3.0/htmldocs" title="Netatalk Manual">[documentation]</a>
-          <a href="http://sourceforge.net/project/showfiles.php?group_id=8642" title="Download Netatalk from sourceforge">[downloads]</a>
-          <a href="/support.php" title="Support">[support]</a>
-          <a href="/links.php" title="Netatalk related links">[links]</a>
-          <img src="/gfx/end.gif" alt="" width="125" height="7" />
-        </div>
-    </div>
-</html>
diff --git a/doc/www/.gitignore b/doc/www/.gitignore
new file mode 100644 (file)
index 0000000..402bcc5
--- /dev/null
@@ -0,0 +1 @@
+ReleaseNotes.html
index ab0441a93173067dc83d4d6c3ae65ca7607e04ad..850be9eadea0428c7814604bdb43439644b86efa 100644 (file)
@@ -1,9 +1,9 @@
-Netatalk 3.0.3
+Netatalk 3.0.5
 ==============
 
-The Netatalk development team is proud to announce version 3.0.3 of
+The Netatalk development team is proud to announce version 3.0.5 of
 the Netatalk File Sharing suite. This is the latest update to the 3.0
-release series. All users are encouraged to upgrade their systems to 3.0.3.
+release series. All users are encouraged to upgrade their systems to 3.0.5.
 
 Netatalk is a freely-available Open Source AFP fileserver.
 A *NIX/*BSD system running Netatalk is capable of serving many Macintosh
@@ -43,6 +43,51 @@ at:
 
   http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
 
+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
@@ -291,4 +336,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, January 2013
+ - The Netatalk Development Team, August 2013
index 5a5aaa35df9e6bd1cf51fe13d66368e41a44ab3a..94adb9938e0a668e6988355117cadd4a27323d09 100644 (file)
@@ -213,15 +213,15 @@ int configinit(AFPObj *obj)
         zeroconf_register(obj);
     }
 
-    if ((r = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce listener", NULL))) {
+    if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce listener", NULL))) {
                LOG(log_note, logtype_afpd, "Adding FCE listener: %s", r);
                fce_add_udp_socket(r);
     }
-    if ((r = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce coalesce", NULL))) {
+    if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce coalesce", NULL))) {
                LOG(log_note, logtype_afpd, "Fce coalesce: %s", r);
                fce_set_coalesce(r);
     }
-    if ((r = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce events", NULL))) {
+    if ((r = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "fce events", NULL))) {
                LOG(log_note, logtype_afpd, "Fce events: %s", r);
                fce_set_events(r);
     }
index b7dc0701f18eafbf006aba524be3bd9988e64e8c..07a2bb7d439cfa5721f148d59f6316a7a59d0369 100644 (file)
@@ -1172,6 +1172,14 @@ struct path *cname(struct vol *vol, struct dir *dir, char **cpath)
             /* the name is illegal */
             LOG(log_info, logtype_afpd, "cname: illegal path: '%s'", ret.u_name);
             afp_errno = AFPERR_PARAM;
+            if (vol->v_obj->options.flags & OPTION_VETOMSG) {
+                bstring message = bformat("Attempt to access vetoed file or directory \"%s\" in directory \"%s\"",
+                                          ret.u_name, bdata(dir->d_u_name));
+                if (setmessage(bdata(message)) == 0)
+                    /* Client may make multiple attempts, only send the message the first time */
+                    kill(getpid(), SIGUSR2);
+                bdestroy(message);
+            }
             return NULL;
         }
 
@@ -1478,6 +1486,7 @@ int getdirparams(const AFPObj *obj,
                 ashort = htons(ATTRBIT_INVISIBLE);
             } else
                 ashort = 0;
+            ashort &= ~htons(vol->v_ignattr);
             memcpy( data, &ashort, sizeof( ashort ));
             data += sizeof( ashort );
             break;
@@ -1866,6 +1875,7 @@ int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *bu
                 ad_getattr(&ad, &bshort);
                 oshort = bshort;
                 if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
+                    ashort &= ~htons(vol->v_ignattr);
                     bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
                 } else {
                     bshort &= ~ashort;
@@ -2278,7 +2288,6 @@ int deletecurdir(struct vol *vol)
     struct dirent *de;
     struct stat st;
     struct dir  *fdir, *pdir;
-    DIR *dp;
     struct adouble  ad;
     uint16_t       ashort;
     int err;
@@ -2295,39 +2304,17 @@ int deletecurdir(struct vol *vol)
 
         ad_getattr(&ad, &ashort);
         ad_close(&ad, ADFLAGS_HF);
-        if ((ashort & htons(ATTRBIT_NODELETE))) {
+        if (!(vol->v_ignattr & ATTRBIT_NODELETE) && (ashort & htons(ATTRBIT_NODELETE))) {
             return  AFPERR_OLOCK;
         }
     }
     err = vol->vfs->vfs_deletecurdir(vol);
     if (err) {
-        LOG(log_error, logtype_afpd, "deletecurdir: error deleting .AppleDouble in \"%s\"",
+        LOG(log_error, logtype_afpd, "deletecurdir: error deleting AppleDouble files in \"%s\"",
             cfrombstr(curdir->d_fullpath));
         return err;
     }
 
-    /* now get rid of dangling symlinks */
-    if ((dp = opendir("."))) {
-        while ((de = readdir(dp))) {
-            /* skip this and previous directory */
-            if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
-                continue;
-
-            /* bail if it's not a symlink */
-            if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) {
-                LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): not empty",
-                    bdata(curdir->d_fullpath));
-                closedir(dp);
-                return AFPERR_DIRNEMPT;
-            }
-
-            if ((err = netatalk_unlink(de->d_name))) {
-                closedir(dp);
-                return err;
-            }
-        }
-    }
-
     if (movecwd(vol, pdir) < 0) {
         err = afp_errno;
         goto delete_done;
@@ -2337,24 +2324,29 @@ int deletecurdir(struct vol *vol)
         cfrombstr(curdir->d_fullpath));
 
     err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name));
-    if ( err ==  AFP_OK || err == AFPERR_NOOBJ) {
-        AFP_CNID_START("cnid_delete");
-        cnid_delete(vol->v_cdb, fdir->d_did);
-        AFP_CNID_DONE();
-        dir_remove( vol, fdir );
-    } else {
+
+    switch (err) {
+    case AFP_OK:
+    case AFPERR_NOOBJ:
+        break;
+    case AFPERR_DIRNEMPT:
+        if (delete_vetoed_files(vol, bdata(fdir->d_u_name), false) != 0)
+            goto delete_done;
+        err = AFP_OK;
+        break;
+    default:
         LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error",
             cfrombstr(curdir->d_fullpath));
+        goto delete_done;
     }
 
+    AFP_CNID_START("cnid_delete");
+    cnid_delete(vol->v_cdb, fdir->d_did);
+    AFP_CNID_DONE();
+
+    dir_remove( vol, fdir );
+
 delete_done:
-    if (dp) {
-        /* inode is used as key for cnid.
-         * Close the descriptor only after cnid_delete
-         * has been called.
-         */
-        closedir(dp);
-    }
     return err;
 }
 
index be1fafe5517411e15ffeb5b31b110bd39fde18a2..f639c49baf7ea8809de4e923d43beaf9a5a0fe16 100644 (file)
@@ -377,6 +377,7 @@ int getmetadata(const AFPObj *obj,
                 ashort = htons(ATTRBIT_INVISIBLE);
             } else
                 ashort = 0;
+            ashort &= ~htons(vol->v_ignattr);
 #if 0
             /* FIXME do we want a visual clue if the file is read only
              */
@@ -1022,6 +1023,7 @@ int setfilparams(const AFPObj *obj, struct vol *vol,
             ad_getattr(adp, &bshort);
             oshort = bshort;
             if ( ntohs( ashort ) & ATTRBIT_SETCLR ) {
+                ashort &= ~htons(vol->v_ignattr);
                 bshort |= htons( ntohs( ashort ) & ~ATTRBIT_SETCLR );
             } else {
                 bshort &= ~ashort;
@@ -1526,7 +1528,7 @@ done:
    WRITE lock on read only file.
 */
 
-static int check_attrib(struct adouble *adp)
+static int check_attrib(const struct vol *vol, struct adouble *adp)
 {
 uint16_t   bshort = 0;
 
@@ -1534,10 +1536,10 @@ uint16_t   bshort = 0;
     /*
      * Does kFPDeleteInhibitBit (bit 8) set?
      */
-       if ((bshort & htons(ATTRBIT_NODELETE))) {
+       if (!(vol->v_ignattr & ATTRBIT_NODELETE) && (bshort & htons(ATTRBIT_NODELETE))) {
                return AFPERR_OLOCK;
        }
-    if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
+     if ((bshort & htons(ATTRBIT_DOPEN | ATTRBIT_ROPEN))) {
        return AFPERR_BUSY;
        }
        return 0;
@@ -1562,7 +1564,7 @@ int deletefile(const struct vol *vol, int dirfd, char *file, int checkAttrib)
          * ad_open would create a 0 byte resource fork
         */
         if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) {
-            if ((err = check_attrib(&ad))) {
+            if ((err = check_attrib(vol, &ad))) {
                 ad_close(&ad, ADFLAGS_HF | ADFLAGS_CHECK_OF);
                return err;
             }
@@ -2206,6 +2208,42 @@ int afp_exchangefiles(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U
         }
         goto err_temp_to_dest;
     }
+
+    if (AD_META_OPEN(adsp) || AD_META_OPEN(addp)) {
+        struct adouble adtmp;
+        bool opened_ads, opened_add;
+
+        ad_init(&adtmp, vol);
+        ad_init_offsets(&adtmp);
+
+        if (!AD_META_OPEN(adsp)) {
+            if (ad_open(adsp, p, ADFLAGS_HF) != 0)
+                return -1;
+            opened_ads = true;
+        }
+
+        if (!AD_META_OPEN(addp)) {
+            if (ad_open(addp, upath, ADFLAGS_HF) != 0)
+                return -1;
+            opened_add = true;
+        }
+
+        if (ad_copy_header(&adtmp, adsp) != 0)
+            goto err_temp_to_dest;
+        if (ad_copy_header(adsp, addp) != 0)
+            goto err_temp_to_dest;
+        if (ad_copy_header(addp, &adtmp) != 0)
+            goto err_temp_to_dest;
+        ad_flush(adsp);
+        ad_flush(addp);
+
+        if (opened_ads)
+            ad_close(adsp, ADFLAGS_HF);
+        if (opened_add)
+            ad_close(addp, ADFLAGS_HF);
+    }
+
+    /* FIXME: we should switch ressource fork too */
     
     /* here we need to reopen if crossdev */
     if (sid && ad_setid(addp, destst.st_dev, destst.st_ino,  sid, sdir->d_did, vol->v_stamp)) 
index 8feac755be3ad09082ec4627fb29e1b40c648207..f35edfc9ad6496e4cf3e00d949015b97b7964374 100644 (file)
@@ -26,6 +26,7 @@
 #include <atalk/globals.h>
 #include <atalk/fce_api.h>
 #include <atalk/netatalk_conf.h>
+#include <atalk/errchk.h>
 
 #include "directory.h"
 #include "dircache.h"
@@ -302,7 +303,7 @@ static int moveandrename(struct vol *vol,
         ad_getattr(adp, &bshort);
         
         ad_close(adp, ADFLAGS_HF);
-        if ((bshort & htons(ATTRBIT_NORENAME))) {
+        if (!(vol->v_ignattr & ATTRBIT_NORENAME) && (bshort & htons(ATTRBIT_NORENAME))) {
             rc = AFPERR_OLOCK;
             goto exit;
         }
@@ -468,6 +469,83 @@ int afp_rename(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
     return( rc );
 }
 
+/* 
+ * Recursivley delete vetoed files and directories if the volume option is set
+ *
+ * @param vol   (r) volume handle
+ * @param upath (r) path of directory
+ *
+ * If the volume option delete veto files is set, this function recursively scans the
+ * directory "upath" for vetoed files and tries deletes these, the it will try to delete
+ * the directory. That may fail if the directory contains normal files that aren't vetoed.
+ *
+ * @returns 0 if the directory upath and all of its contents were deleted, otherwise -1.
+ *            If the volume option is not set it returns -1.
+ */
+int delete_vetoed_files(struct vol *vol, const char *upath, bool in_vetodir)
+{
+    EC_INIT;
+    DIR            *dp = NULL;
+    struct dirent  *de;
+    struct stat     sb;
+    int             pwd = -1;
+    bool            vetoed;
+
+    if (!(vol->v_flags & AFPVOL_DELVETO))
+        return -1;
+
+    EC_NEG1( pwd = open(".", O_RDONLY));
+    EC_ZERO( chdir(upath) );
+    EC_NULL( dp = opendir(".") );
+
+    while ((de = readdir(dp))) {
+        if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
+            continue;
+
+        if (stat(de->d_name, &sb) != 0) {
+            LOG(log_error, logtype_afpd, "delete_vetoed_files(\"%s/%s\"): %s",
+                upath, de->d_name, strerror(errno));
+                EC_EXIT_STATUS(AFPERR_DIRNEMPT);
+        }
+
+        if (in_vetodir || veto_file(vol->v_veto, de->d_name))
+            vetoed = true;
+        else
+            vetoed = false;
+
+        if (vetoed) {
+            LOG(log_debug, logtype_afpd, "delete_vetoed_files(\"%s/%s\"): deleting vetoed file",
+                upath, de->d_name);
+            switch (sb.st_mode & S_IFMT) {
+            case S_IFDIR:
+                /* recursion */
+                EC_ZERO( delete_vetoed_files(vol, de->d_name, vetoed));
+                break;
+            case S_IFREG:
+            case S_IFLNK:
+                EC_ZERO( netatalk_unlink(de->d_name) );
+                break;
+            default:
+                break;
+            }
+        }
+    }
+
+    EC_ZERO_LOG( fchdir(pwd) );
+    pwd = -1;
+    EC_ZERO_LOG( rmdir(upath) );
+
+EC_CLEANUP:
+    if (dp)
+        closedir(dp);
+    if (pwd != -1) {
+        if (fchdir(pwd) != 0)
+            ret = -1;
+    }
+
+    EC_EXIT;
+}
+
 /* ------------------------------- */
 int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
 {
@@ -512,7 +590,9 @@ int afp_delete(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size
             if (rmdir(upath) != 0) {
                 switch (errno) {
                 case ENOTEMPTY:
-                    return AFPERR_DIRNEMPT;
+                    if (delete_vetoed_files(vol, upath, false) != 0)
+                        return AFPERR_DIRNEMPT;
+                    break;
                 case EACCES:
                     return AFPERR_ACCESS;
                 default:
index 02c9ac15b5382ed99c5ee4cf7a84166d4e85cfda..f72e5445b0f52b544dd6c2ddec7bfc40f0599981 100644 (file)
@@ -15,6 +15,7 @@ extern int            veto_file (const char *veto_str, const char *path);
 extern int             check_name (const struct vol *vol, char *name);
 
 extern int matchfile2dirperms (char *, struct vol *, int);
+extern int delete_vetoed_files(struct vol *vol, const char *upath, bool in_vetodir);
 
 /* FP functions */
 int afp_moveandrename (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf,  size_t *rbuflen);
index 3c85f6a3a505c7fe9ae4c5ade65a5c44f997e708..5bd965bd2a55fd569942f550173b80a44e27c1a5 100644 (file)
 static char servermesg[MAXPATHLEN] = "";
 static char localized_message[MAXPATHLEN] = "";
 
-void setmessage(const char *message)
+/*!
+ * Copy AFP message to message buffer
+ * @param message (r) message to send
+ * @returns 0 if this message is being set the first time, return 1 if the preceeding
+ *          message was the same
+ */
+int setmessage(const char *message)
 {
+    if (strncmp(message, servermesg, MAXMESGSIZE) == 0)
+        return 1;
     strlcpy(servermesg, message, MAXMESGSIZE);
+    return 0;
 }
 
 void readmessage(AFPObj *obj)
@@ -177,6 +186,6 @@ int afp_getsrvrmesg(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, siz
        *rbuflen += 1;
     }
     *rbuflen += outlen;
-    *message = 0;
+//    *message = 0;
     return AFP_OK;
 }
index f51223730c32a5047eedd749d935315613e24ff9..5f0d8a3786b3c945b84b5d59372e8d34cace4495 100644 (file)
@@ -530,6 +530,7 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf
     char        *namebuf;
     int         vcnt;
     size_t      len;
+    uint32_t    aint;
 
     load_volumes(obj);
 
@@ -575,12 +576,13 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf
     *rbuflen = data - rbuf;
     data = rbuf;
     if ( gettimeofday( &tv, NULL ) < 0 ) {
-        LOG(log_error, logtype_afpd, "afp_getsrvrparms(%s): gettimeofday: %s", volume->v_path, strerror(errno) );
+        LOG(log_error, logtype_afpd, "afp_getsrvrparms: gettimeofday: %s", strerror(errno) );
         *rbuflen = 0;
         return AFPERR_PARAM;
     }
-    tv.tv_sec = AD_DATE_FROM_UNIX(tv.tv_sec);
-    memcpy(data, &tv.tv_sec, sizeof( uint32_t));
+
+    aint = AD_DATE_FROM_UNIX(tv.tv_sec);
+    memcpy(data, &aint, sizeof( uint32_t));
     data += sizeof( uint32_t);
     *data = vcnt;
     return( AFP_OK );
@@ -856,7 +858,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t
         }
 
         const char *msg;
-        if ((msg = iniparser_getstring(obj->iniconfig, volume->v_configname, "login message",  NULL)) != NULL)
+        if ((msg = atalk_iniparser_getstring(obj->iniconfig, volume->v_configname, "login message",  NULL)) != NULL)
             setmessage(msg);
 
         free(vol_mname);
index 7b7664d52d6febb546718b1eaa42b710c2da5c76..3d71094b328e4c2907eaf547c69bb4bf38a45f99 100644 (file)
@@ -468,7 +468,7 @@ int main(int argc, char *argv[])
 
     (void)setlimits();
 
-    host = iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700");
+    host = atalk_iniparser_getstrdup(obj.iniconfig, INISEC_GLOBAL, "cnid listen", "localhost:4700");
     if ((port = strrchr(host, ':')))
         *port++ = 0;
     else
index c0f4098da7b3590da71d01a3c92f44b6a9f573c4..3b764a7689e42299e9d2b8f008dbfa78bd378ace 100644 (file)
@@ -402,6 +402,7 @@ extern int ad_mkdir       (const char *, mode_t);
 struct vol;
 extern void ad_init       (struct adouble *, const struct vol * restrict);
 extern void ad_init_old   (struct adouble *ad, int flags, int options);
+extern int ad_init_offsets(struct adouble *ad);
 extern int ad_open        (struct adouble *ad, const char *path, int adflags, ...);
 extern int ad_openat      (struct adouble *, int dirfd, const char *path, int adflags, ...);
 extern int ad_refresh     (const char *path, struct adouble *);
index b28d736e09855bed7cfee85c8d1d464bb8434c97..1aa22af85a154237c7899f884e20841d1d5e017a 100644 (file)
@@ -57,12 +57,12 @@ typedef struct _dictionary_ {
                                                        Function prototypes
  ---------------------------------------------------------------------------*/
 
-unsigned   dictionary_hash  (char * key);
-dictionary *dictionary_new  (int size);
-void       dictionary_del   (dictionary * vd);
-const char *dictionary_get  (const dictionary * d, const char *section, const char * key, const char * def);
-int        dictionary_set   (dictionary * vd, char *section, char * key, char * val);
-void       dictionary_unset (dictionary * d, char *section, char * key);
-void       dictionary_dump  (dictionary * d, FILE * out);
+unsigned   atalkdict_hash  (char * key);
+dictionary *atalkdict_new  (int size);
+void       atalkdict_del   (dictionary * vd);
+const char *atalkdict_get  (const dictionary * d, const char *section, const char * key, const char * def);
+int        atalkdict_set   (dictionary * vd, char *section, char * key, char * val);
+void       atalkdict_unset (dictionary * d, char *section, char * key);
+void       atalkdict_dump  (dictionary * d, FILE * out);
 
 #endif
index fc1af468ac3156934f4ce1771bb19e7ed18591b4..c31b522c39579489e02e4df4ba806298de033950 100644 (file)
@@ -48,7 +48,7 @@ struct dsi_block {
     union {
         uint32_t dsi_code;   /* error code */
         uint32_t dsi_doff;   /* data offset */
-    };
+    } dsi_data;
     uint32_t dsi_len;        /* total data length */
     uint32_t dsi_reserved;   /* reserved field */
 };
index b245601375afd4dae9f5d715d8050eed045eeb6f..61cf247fe9987ce9f1cbe74d621c7eac4ed981cb 100644 (file)
@@ -48,7 +48,7 @@
 #define OPTION_CLOSEVOL      (1 << 1)
 #define OPTION_SERVERNOTIF   (1 << 2)
 #define OPTION_NOSENDFILE    (1 << 3)
-/* #define OPTION_CUSTOMICON    (1 << 4) */
+#define OPTION_VETOMSG       (1 << 4) /* whether to send an AFP message for veto file access */
 #define OPTION_AFP_READ_LOCK (1 << 5) /* whether to do AFP spec conforming read locks (default: no) */
 #define OPTION_ANNOUNCESSH   (1 << 6)
 #define OPTION_UUID          (1 << 7)
@@ -117,6 +117,7 @@ struct afp_options {
     char *logfile;
     char *mimicmodel;
     char *adminauthuser;
+    char *ignored_attr;
     struct afp_volume_name volfile;
 };
 
@@ -161,7 +162,7 @@ extern const char         *Cnid_port;
 extern int  get_afp_errno   (const int param);
 extern void afp_options_init (struct afp_options *);
 extern void afp_options_parse_cmdline(AFPObj *obj, int ac, char **av);
-extern void setmessage (const char *);
+extern int setmessage (const char *);
 extern void readmessage (AFPObj *);
 
 /* afp_util.c */
index 8f94c5ca4a11f677c135a12794cbbff9be2114b4..186c90e458f474331f7e7b88e6a6ab1eca97bba6 100644 (file)
 
 #include "dictionary.h"
 
-int        iniparser_getnsec(const dictionary * d);
-const char *iniparser_getsecname(const dictionary * d, int n);
-void       iniparser_dump_ini(const dictionary * d, FILE * f);
-void       iniparser_dump(const dictionary * d, FILE * f);
-const char *iniparser_getstring(const dictionary * d, const char *section, const char * key, const char * def);
-char       *iniparser_getstrdup(const dictionary * d, const char *section, const char * key, const char * def);
-int        iniparser_getint(const dictionary * d, const char *section, const char * key, int notfound);
-double     iniparser_getdouble(const dictionary * d, const char *section, const char * key, double notfound);
-int        iniparser_getboolean(const dictionary * d, const char *section, const char * key, int notfound);
-int        iniparser_set(dictionary * ini, char *section, char * key, char * val);
-void       iniparser_unset(dictionary * ini, char *section, char * key);
-int        iniparser_find_entry(const dictionary * ini, const char * entry) ;
-dictionary *iniparser_load(const char * ininame);
-void       iniparser_freedict(dictionary * d);
+int        atalk_iniparser_getnsec(const dictionary * d);
+const char *atalk_iniparser_getsecname(const dictionary * d, int n);
+void       atalk_iniparser_dump_ini(const dictionary * d, FILE * f);
+void       atalk_iniparser_dump(const dictionary * d, FILE * f);
+const char *atalk_iniparser_getstring(const dictionary * d, const char *section, const char * key, const char * def);
+char       *atalk_iniparser_getstrdup(const dictionary * d, const char *section, const char * key, const char * def);
+int        atalk_iniparser_getint(const dictionary * d, const char *section, const char * key, int notfound);
+double     atalk_iniparser_getdouble(const dictionary * d, const char *section, const char * key, double notfound);
+int        atalk_iniparser_getboolean(const dictionary * d, const char *section, const char * key, int notfound);
+int        atalk_iniparser_set(dictionary * ini, char *section, char * key, char * val);
+void       atalk_iniparser_unset(dictionary * ini, char *section, char * key);
+int        atalk_iniparser_find_entry(const dictionary * ini, const char * entry) ;
+dictionary *atalk_iniparser_load(const char * ininame);
+void       atalk_iniparser_freedict(dictionary * d);
 
 #endif
index facc77636a476fdd05c9fffdbe92d0b8c9554c8a..7000499ba68198ed1943e983bcbde0747b06cef2 100644 (file)
@@ -147,6 +147,7 @@ extern const char *getip_string(const struct sockaddr *sa);
 extern unsigned int getip_port(const struct sockaddr *sa);
 extern void apply_ip_mask(struct sockaddr *ai, int maskbits);
 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};
index b185f994c1e2a0f7b0175a1e28c32735a7e6fb70..a9e497a6d76ddf4cf4053b673da181de09a03a79 100644 (file)
@@ -98,6 +98,7 @@ struct vol {
     int             v_preexec_close;
     char            *v_uuid;    /* For TimeMachine zeroconf record */
     int             v_qfd;
+    uint32_t        v_ignattr;  /* AFP attributes that shall be ignored */
 };
 
 /* load_volumes() flags */
@@ -133,6 +134,7 @@ struct vol {
 #define AFPVOL_SEARCHDB  (1 << 25)   /* Use fast CNID db search instead of filesystem */
 #define AFPVOL_NONETIDS  (1 << 26)   /* signal the client it shall do privelege mapping */
 #define AFPVOL_FOLLOWSYM (1 << 27)   /* follow symlinks on the server, default is not to */
+#define AFPVOL_DELVETO   (1 << 28)   /* delete veto files and dirs */
 
 /* Extended Attributes vfs indirection  */
 #define AFPVOL_EA_NONE           0   /* No EAs */
index a6df63bd7f3a2fc9e2ec5f1410df2800fb41c5fa..06e869a332e97583d5052a33acfb787a929494de 100644 (file)
@@ -18,7 +18,7 @@
 #        current+1:0:0
 #
 
-VERSION_INFO = 5:0:0
+VERSION_INFO = 6:0:0
 
 # History:          VERSION_INFO
 #
@@ -32,6 +32,7 @@ VERSION_INFO = 5:0:0
 #   3.0.2           3:0:0
 #   3.0.3           4:0:0
 #   3.0.4           5:0:0
+#   3.0.5           6:0:0
 
 SUBDIRS = acl adouble bstring compat cnid dsi iniparser tdb util unicode vfs
 
index 26a63fa9c76dab72f94af1fb812943d50f2ba804..9bf01c1818f4c8f403865ffb6790dec8c248408f 100644 (file)
@@ -49,7 +49,7 @@ int acl_ldap_readconfig(dictionary *iniconfig)
     i = 0;
     /* now see if its a correct pref */
     for (i = 0; ldap_prefs[i].name != NULL; i++) {
-        if ((val = iniparser_getstring(iniconfig, INISEC_GLOBAL, ldap_prefs[i].name, NULL))) {
+        if ((val = atalk_iniparser_getstring(iniconfig, INISEC_GLOBAL, ldap_prefs[i].name, NULL))) {
             /* check if we have pre-defined values */
             if (ldap_prefs[i].intfromarray == 0) {
                 /* no, its just a string */
index 6915cbb189aa3618680d3a1abcb3f5d39132c745..06c3c71e49a7cfaca6ada37276237d0a4ae66f4f 100644 (file)
@@ -311,19 +311,16 @@ static uint32_t get_eid(uint32_t eid)
     return 0;
 }
 
-/* ----------------------------------- */
-static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags)
+
+/**
+ * Initialize offset pointers
+ */
+int ad_init_offsets(struct adouble *ad)
 {
     const struct entry  *eid;
-    uint16_t            ashort;
-    struct stat         st;
 
-    LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path);
-
-    if (ad->ad_magic == AD_MAGIC) {
-        LOG(log_debug, logtype_ad, "new_ad_header(\"%s\"): already initialized", path);
+    if (ad->ad_magic == AD_MAGIC)
         return 0;
-    }
 
     ad->ad_magic = AD_MAGIC;
     ad->ad_version = ad->ad_vers & 0x0f0000;
@@ -346,6 +343,21 @@ static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp,
         eid++;
     }
 
+    return 0;
+}
+
+/* ----------------------------------- */
+static int new_ad_header(struct adouble *ad, const char *path, struct stat *stp, int adflags)
+{
+    const struct entry  *eid;
+    uint16_t            ashort;
+    struct stat         st;
+
+    LOG(log_debug, logtype_ad, "new_ad_header(\"%s\")", path);
+
+    if (ad_init_offsets(ad) != 0)
+        return -1;
+
     /* set default creator/type fields */
     memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRTYPEOFF,"\0\0\0\0", 4);
     memcpy(ad_entry(ad, ADEID_FINDERI) + FINDERINFO_FRCREATOFF,"\0\0\0\0", 4);
index 892b982eade06df3553c83ab2d7b00a876f1617b..199954fce69ccfdeca888cf4ab3277ccb0ca4d01 100644 (file)
@@ -21,7 +21,7 @@ void dsi_close(DSI *dsi)
       dsi->header.dsi_flags = DSIFL_REQUEST;
       dsi->header.dsi_command = DSIFUNC_CLOSE;
       dsi->header.dsi_requestID = htons(dsi_serverID(dsi));
-      dsi->header.dsi_code = dsi->header.dsi_reserved = htonl(0);
+      dsi->header.dsi_data.dsi_code = dsi->header.dsi_reserved = htonl(0);
       dsi->cmdlen = 0; 
       dsi_send(dsi);
       dsi->proto_close(dsi);
index 5b0d627de2c788e7356ffeb50219163d6007cb3c..04d17083351ea715cf89809c0cd3eb8189d4fef7 100644 (file)
@@ -25,7 +25,7 @@ int dsi_cmdreply(DSI *dsi, const int err)
 
     dsi->header.dsi_flags = DSIFL_REPLY;
     dsi->header.dsi_len = htonl(dsi->datalen);
-    dsi->header.dsi_code = htonl(err);
+    dsi->header.dsi_data.dsi_code = htonl(err);
 
     ret = dsi_stream_send(dsi, dsi->data, dsi->datalen);
 
index 38477be99e1ac18b9f7e22a22f8cc28500c4fe83..a928d34ee38d8f23f9fd34350198d00fffc91e75 100644 (file)
@@ -65,9 +65,9 @@ int dsi_getsession(DSI *dsi, server_child_t *serv_children, int tickleval, afp_c
       LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
       close(ipc_fds[0]);
       dsi->header.dsi_flags = DSIFL_REPLY;
-      dsi->header.dsi_code = DSIERR_SERVBUSY;
+      dsi->header.dsi_data.dsi_code = DSIERR_SERVBUSY;
       dsi_send(dsi);
-      dsi->header.dsi_code = DSIERR_OK;
+      dsi->header.dsi_data.dsi_code = DSIERR_OK;
       kill(pid, SIGKILL);
     }
     dsi->proto_close(dsi);
@@ -81,7 +81,7 @@ int dsi_getsession(DSI *dsi, server_child_t *serv_children, int tickleval, afp_c
       (dsi->header.dsi_command == DSIFUNC_OPEN)) {
     LOG(log_info, logtype_dsi, "dsi_getsess: too many connections");
     dsi->header.dsi_flags = DSIFL_REPLY;
-    dsi->header.dsi_code = DSIERR_TOOMANY;
+    dsi->header.dsi_data.dsi_code = DSIERR_TOOMANY;
     dsi_send(dsi);
     exit(EXITERR_CLNT);
   }
index dac4f76b3760efa38c650d5e7b21dc7ba42d71d6..4be9b802175fc218f3867a6655eb84a602783290 100644 (file)
@@ -20,7 +20,7 @@ void dsi_getstatus(DSI *dsi)
 {
   dsi->header.dsi_flags = DSIFL_REPLY;
   /*dsi->header.dsi_command = DSIFUNC_STAT;*/
-  dsi->header.dsi_code = dsi->header.dsi_reserved = 0;
+  dsi->header.dsi_data.dsi_code = dsi->header.dsi_reserved = 0;
   
   memcpy(dsi->commands, dsi->status, dsi->statuslen);
   dsi->cmdlen = dsi->statuslen; 
index a2dcb4c9b0d6c11177eca4cd0eea24344a63163f..2945f9b185f242de3a6a767f1c8d3a5e281ee38e 100644 (file)
@@ -44,7 +44,7 @@ void dsi_opensession(DSI *dsi)
   /* let the client know the server quantum. we don't use the
    * max server quantum due to a bug in appleshare client 3.8.6. */
   dsi->header.dsi_flags = DSIFL_REPLY;
-  dsi->header.dsi_code = 0;
+  dsi->header.dsi_data.dsi_code = 0;
   /* dsi->header.dsi_command = DSIFUNC_OPEN;*/
 
   dsi->cmdlen = 2 * (2 + sizeof(i)); /* length of data. dsi_send uses it. */
index a0cbd872c2851a7ef2ba14021a52138f4a03d7ad..31ee3bdff4a9191327b808061c6979c8ae4a0dcf 100644 (file)
@@ -31,7 +31,7 @@ ssize_t dsi_readinit(DSI *dsi, void *buf, const size_t buflen, const size_t size
     dsi->flags |= DSI_NOREPLY; /* we will handle our own replies */
     dsi->header.dsi_flags = DSIFL_REPLY;
     dsi->header.dsi_len = htonl(size);
-    dsi->header.dsi_code = htonl(err);
+    dsi->header.dsi_data.dsi_code = htonl(err);
 
     dsi->in_write++;
     if (dsi_stream_send(dsi, buf, buflen)) {
index 94890dd8014341bbe6ccb02393f35a5456c9775c..770258c5b6978839e9e4e00a926a43bd8dd486c7 100644 (file)
@@ -45,7 +45,7 @@ static void dsi_header_pack_reply(const DSI *dsi, char *buf)
     buf[0] = dsi->header.dsi_flags;
     buf[1] = dsi->header.dsi_command;
     memcpy(buf + 2, &dsi->header.dsi_requestID, sizeof(dsi->header.dsi_requestID));           
-    memcpy(buf + 4, &dsi->header.dsi_code, sizeof(dsi->header.dsi_code));
+    memcpy(buf + 4, &dsi->header.dsi_data.dsi_code, sizeof(dsi->header.dsi_data.dsi_code));
     memcpy(buf + 8, &dsi->header.dsi_len, sizeof(dsi->header.dsi_len));
     memcpy(buf + 12, &dsi->header.dsi_reserved, sizeof(dsi->header.dsi_reserved));
 }
@@ -366,7 +366,7 @@ ssize_t dsi_stream_read_file(DSI *dsi, const int fromfd, off_t offset, const siz
     dsi->flags |= DSI_NOREPLY;
     dsi->header.dsi_flags = DSIFL_REPLY;
     dsi->header.dsi_len = htonl(length);
-    dsi->header.dsi_code = htonl(err);
+    dsi->header.dsi_data.dsi_code = htonl(err);
     dsi_header_pack_reply(dsi, block);
 
 #ifdef HAVE_SENDFILEV
@@ -615,7 +615,7 @@ int dsi_stream_receive(DSI *dsi)
       return 0;
 
   memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID));
-  memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
+  memcpy(&dsi->header.dsi_data.dsi_code, block + 4, sizeof(dsi->header.dsi_data.dsi_code));
   memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
   memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved));
   dsi->clientID = ntohs(dsi->header.dsi_requestID);
index f73147a81a9565309bcbe518042edf1f6865e106..ad8a3a23715683d0c97b2fdc8e983aba72f27694 100644 (file)
@@ -209,7 +209,7 @@ static pid_t dsi_tcp_open(DSI *dsi)
         dsi->header.dsi_command = block[1];
         memcpy(&dsi->header.dsi_requestID, block + 2,
                sizeof(dsi->header.dsi_requestID));
-        memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
+        memcpy(&dsi->header.dsi_data.dsi_code, block + 4, sizeof(dsi->header.dsi_data.dsi_code));
         memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
         memcpy(&dsi->header.dsi_reserved, block + 12,
                sizeof(dsi->header.dsi_reserved));
@@ -304,25 +304,45 @@ iflist_done:
 #define AI_NUMERICSERV 0
 #endif
 
-/* this needs to accept passed in addresses */
+/*!
+ * Initialize DSI over TCP
+ *
+ * @param dsi        (rw) DSI handle
+ * @param hostname   (r)  pointer to hostname string
+ * @param inaddress  (r)  Optional IPv4 or IPv6 address with an optional port, may be NULL
+ * @param inport     (r)  pointer to port string
+ *
+ * Creates listening AFP/DSI socket. If the parameter inaddress is NULL, then we listen
+ * on the wildcard address, ie on all interfaces. That should mean listening on the IPv6
+ * address "::" on IPv4/IPv6 dual stack kernels, accepting both v4 and v6 requests.
+ *
+ * If the parameter inaddress is not NULL, then we only listen on the given address.
+ * The parameter may contain a port number using the URL format for address and port:
+ *
+ *   IPv4, IPv4:port, IPv6, [IPv6], [IPv6]:port
+ *
+ * Parameter inport must be a valid pointer to a port string and is used if the inaddress
+ * parameter doesn't contain a port.
+ *
+ * @returns 0 on success, -1 on failure
+ */
 int dsi_tcp_init(DSI *dsi, const char *hostname, const char *inaddress, const char *inport)
 {
     EC_INIT;
     int                flag, err;
-    char               *a = NULL, *b;
-    const char         *address;
-    const char         *port;
+    char              *address = NULL, *port = NULL;
     struct addrinfo    hints, *servinfo, *p;
 
-    /* Check whether address is of the from IP:PORT and split */
-    address = inaddress;
-    port = inport;
-    if (address && strchr(address, ':')) {
-        EC_NULL_LOG( address = a = strdup(address) );
-        b = strchr(a, ':');
-        *b = 0;
-        port = b + 1;
-    }
+    /* inaddress may be NULL */
+    AFP_ASSERT(dsi && hostname && inport);
+
+    if (inaddress)
+        /* Check whether address is of the from IP:PORT and split */
+        EC_ZERO( tokenize_ip_port(inaddress, &address, &port) );
+
+    if (port == NULL)
+        /* inport is supposed to always contain a valid port string */
+        EC_NULL( port = strdup(inport) );
 
     /* Prepare hint for getaddrinfo */
     memset(&hints, 0, sizeof hints);
@@ -343,8 +363,8 @@ int dsi_tcp_init(DSI *dsi, const char *hostname, const char *inaddress, const ch
         hints.ai_family = AF_UNSPEC;
 #endif
     }
-    if ((ret = getaddrinfo(address ? address : NULL, port, &hints, &servinfo)) != 0) {
-        LOG(log_error, logtype_dsi, "dsi_tcp_init: getaddrinfo: %s\n", gai_strerror(ret));
+    if ((ret = getaddrinfo(address, port, &hints, &servinfo)) != 0) {
+        LOG(log_error, logtype_dsi, "dsi_tcp_init(%s): getaddrinfo: %s\n", address ? address : "*", gai_strerror(ret));
         EC_FAIL;
     }
 
@@ -447,8 +467,10 @@ interfaces:
     guess_interface(dsi, hostname, port ? port : "548");
 
 EC_CLEANUP:
-    if (a)
-        free(a);
+    if (address)
+        free(address);
+    if (port)
+        free(port);
     EC_EXIT;
 }
 
index 65a479e1dac4a89d09fd5785b623715f382d6988..dc35cafa9307a76df2f407dddf9f2f4c704b577a 100644 (file)
@@ -32,7 +32,7 @@ size_t dsi_writeinit(DSI *dsi, void *buf, const size_t buflen _U_)
 
   /* figure out how much data we have. do a couple checks for 0 
    * data */
-  header = ntohl(dsi->header.dsi_doff);
+  header = ntohl(dsi->header.dsi_data.dsi_doff);
   dsi->datasize = header ? ntohl(dsi->header.dsi_len) - header : 0;
 
   if (dsi->datasize > 0) {
index f1ff81567aefcccb8da5c45730a8256a40f49920..191db576d52e95ece30eb1de5312dd71442073bc 100644 (file)
@@ -107,7 +107,7 @@ static char * xstrdup(char * s)
   by comparing the key itself in last resort.
  */
 /*--------------------------------------------------------------------------*/
-unsigned dictionary_hash(char * key)
+unsigned atalkdict_hash(char * key)
 {
        int                     len ;
        unsigned        hash ;
@@ -136,7 +136,7 @@ unsigned dictionary_hash(char * key)
   dictionary, give size=0.
  */
 /*--------------------------------------------------------------------------*/
-dictionary * dictionary_new(int size)
+dictionary * atalkdict_new(int size)
 {
        dictionary      *       d ;
 
@@ -162,7 +162,7 @@ dictionary * dictionary_new(int size)
   Deallocate a dictionary object and all memory associated to it.
  */
 /*--------------------------------------------------------------------------*/
-void dictionary_del(dictionary * d)
+void atalkdict_del(dictionary * d)
 {
        int             i ;
 
@@ -194,12 +194,12 @@ void dictionary_del(dictionary * d)
   dictionary object, you should not try to free it or modify it.
  */
 /*--------------------------------------------------------------------------*/
-const char * dictionary_get(const dictionary * d, const char *section, const char * key, const char * def)
+const char * atalkdict_get(const dictionary * d, const char *section, const char * key, const char * def)
 {
        unsigned        hash ;
        int                     i ;
 
-       hash = dictionary_hash(makekey(section, key));
+       hash = atalkdict_hash(makekey(section, key));
        for (i=0 ; i<d->size ; i++) {
         if (d->key[i]==NULL)
             continue ;
@@ -230,8 +230,8 @@ const char * dictionary_get(const dictionary * d, const char *section, const cha
   or the key are considered as errors: the function will return immediately
   in such a case.
 
-  Notice that if you dictionary_set a variable to NULL, a call to
-  dictionary_get will return a NULL value: the variable will be found, and
+  Notice that if you atalkdict_set a variable to NULL, a call to
+  atalkdict_get will return a NULL value: the variable will be found, and
   its value (NULL) is returned. In other words, setting the variable
   content to NULL is equivalent to deleting the variable from the
   dictionary. It is not possible (in this implementation) to have a key in
@@ -240,7 +240,7 @@ const char * dictionary_get(const dictionary * d, const char *section, const cha
   This function returns non-zero in case of failure.
  */
 /*--------------------------------------------------------------------------*/
-int dictionary_set(dictionary * d, char *section, char * key, char * val)
+int atalkdict_set(dictionary * d, char *section, char * key, char * val)
 {
        int                     i ;
        unsigned        hash ;
@@ -248,7 +248,7 @@ int dictionary_set(dictionary * d, char *section, char * key, char * val)
        if (d==NULL || section==NULL) return -1 ;
        
        /* Compute hash for this key */
-       hash = dictionary_hash(makekey(section, key));
+       hash = atalkdict_hash(makekey(section, key));
        /* Find if value is already in dictionary */
        if (d->n>0) {
                for (i=0 ; i<d->size ; i++) {
@@ -308,7 +308,7 @@ int dictionary_set(dictionary * d, char *section, char * key, char * val)
   key cannot be found.
  */
 /*--------------------------------------------------------------------------*/
-void dictionary_unset(dictionary * d, char *section, char * key)
+void atalkdict_unset(dictionary * d, char *section, char * key)
 {
        unsigned        hash ;
        int                     i ;
@@ -317,7 +317,7 @@ void dictionary_unset(dictionary * d, char *section, char * key)
                return;
        }
 
-       hash = dictionary_hash(makekey(section, key));
+       hash = atalkdict_hash(makekey(section, key));
        for (i=0 ; i<d->size ; i++) {
         if (d->key[i]==NULL)
             continue ;
@@ -357,7 +357,7 @@ void dictionary_unset(dictionary * d, char *section, char * key)
   output file pointers.
  */
 /*--------------------------------------------------------------------------*/
-void dictionary_dump(dictionary * d, FILE * out)
+void atalkdict_dump(dictionary * d, FILE * out)
 {
        int             i ;
 
index 93e14b6b46b55b6b29bbe7802b68ca70b416e881..53f6a108382513b51495251dec09fa8e2e14dcf4 100644 (file)
@@ -88,7 +88,7 @@ static char * strstrip(char * s)
   This function returns -1 in case of error.
  */
 /*--------------------------------------------------------------------------*/
-int iniparser_getnsec(const dictionary * d)
+int atalk_iniparser_getnsec(const dictionary * d)
 {
     int i ;
     int nsec ;
@@ -119,7 +119,7 @@ int iniparser_getnsec(const dictionary * d)
   This function returns NULL in case of error.
  */
 /*--------------------------------------------------------------------------*/
-const char * iniparser_getsecname(const dictionary * d, int n)
+const char * atalk_iniparser_getsecname(const dictionary * d, int n)
 {
     int i ;
     int foundsec ;
@@ -154,7 +154,7 @@ const char * iniparser_getsecname(const dictionary * d, int n)
   purposes mostly.
  */
 /*--------------------------------------------------------------------------*/
-void iniparser_dump(const dictionary * d, FILE * f)
+void atalk_iniparser_dump(const dictionary * d, FILE * f)
 {
     int     i ;
 
@@ -182,7 +182,7 @@ void iniparser_dump(const dictionary * d, FILE * f)
   It is Ok to specify @c stderr or @c stdout as output files.
  */
 /*--------------------------------------------------------------------------*/
-void iniparser_dump_ini(const dictionary * d, FILE * f)
+void atalk_iniparser_dump_ini(const dictionary * d, FILE * f)
 {
     int     i, j ;
     char    keym[ASCIILINESZ+1];
@@ -192,7 +192,7 @@ void iniparser_dump_ini(const dictionary * d, FILE * f)
 
     if (d==NULL || f==NULL) return ;
 
-    nsec = iniparser_getnsec(d);
+    nsec = atalk_iniparser_getnsec(d);
     if (nsec<1) {
         /* No section in file: dump all keys as they are */
         for (i=0 ; i<d->size ; i++) {
@@ -203,7 +203,7 @@ void iniparser_dump_ini(const dictionary * d, FILE * f)
         return ;
     }
     for (i=0 ; i<nsec ; i++) {
-        secname = iniparser_getsecname(d, i) ;
+        secname = atalk_iniparser_getsecname(d, i) ;
         seclen  = (int)strlen(secname);
         fprintf(f, "\n[%s]\n", secname);
         sprintf(keym, "%s:", secname);
@@ -238,14 +238,14 @@ void iniparser_dump_ini(const dictionary * d, FILE * f)
   the dictionary, do not free or modify it.
  */
 /*--------------------------------------------------------------------------*/
-const char * iniparser_getstring(const dictionary * d, const char *section, const char * key, const char * def)
+const char * atalk_iniparser_getstring(const dictionary * d, const char *section, const char * key, const char * def)
 {
     const char * sval ;
 
     if (d==NULL || key==NULL)
         return def ;
 
-    sval = dictionary_get(d, section, key, def);
+    sval = atalkdict_get(d, section, key, def);
     return sval ;
 }
 
@@ -264,14 +264,14 @@ const char * iniparser_getstring(const dictionary * d, const char *section, cons
   The returned char pointer a strdup'ed allocated string, so the caller must free it.
  */
 /*--------------------------------------------------------------------------*/
-char * iniparser_getstrdup(const dictionary * d, const char *section, const char * key, const char * def)
+char * atalk_iniparser_getstrdup(const dictionary * d, const char *section, const char * key, const char * def)
 {
     const char * sval ;
 
     if (d==NULL || key==NULL)
         return NULL;
 
-    if ((sval = dictionary_get(d, section, key, def)))
+    if ((sval = atalkdict_get(d, section, key, def)))
         return strdup(sval);
     return NULL;
 }
@@ -304,11 +304,11 @@ char * iniparser_getstrdup(const dictionary * d, const char *section, const char
   Credits: Thanks to A. Becker for suggesting strtol()
  */
 /*--------------------------------------------------------------------------*/
-int iniparser_getint(const dictionary * d, const char *section, const char * key, int notfound)
+int atalk_iniparser_getint(const dictionary * d, const char *section, const char * key, int notfound)
 {
     const char    *   str ;
 
-    str = iniparser_getstring(d, section, key, INI_INVALID_KEY);
+    str = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY);
     if (str==INI_INVALID_KEY) return notfound ;
     return (int)strtol(str, NULL, 0);
 }
@@ -327,11 +327,11 @@ int iniparser_getint(const dictionary * d, const char *section, const char * key
   the notfound value is returned.
  */
 /*--------------------------------------------------------------------------*/
-double iniparser_getdouble(const dictionary * d, const char *section, const char * key, double notfound)
+double atalk_iniparser_getdouble(const dictionary * d, const char *section, const char * key, double notfound)
 {
     const char    *   str ;
 
-    str = iniparser_getstring(d, section, key, INI_INVALID_KEY);
+    str = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY);
     if (str==INI_INVALID_KEY) return notfound ;
     return atof(str);
 }
@@ -369,12 +369,12 @@ double iniparser_getdouble(const dictionary * d, const char *section, const char
   necessarily have to be 0 or 1.
  */
 /*--------------------------------------------------------------------------*/
-int iniparser_getboolean(const dictionary * d, const char *section, const char * key, int notfound)
+int atalk_iniparser_getboolean(const dictionary * d, const char *section, const char * key, int notfound)
 {
     const char    *   c ;
     int         ret ;
 
-    c = iniparser_getstring(d, section, key, INI_INVALID_KEY);
+    c = atalk_iniparser_getstring(d, section, key, INI_INVALID_KEY);
     if (c==INI_INVALID_KEY) return notfound ;
     if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
         ret = 1 ;
@@ -398,10 +398,10 @@ int iniparser_getboolean(const dictionary * d, const char *section, const char *
   of querying for the presence of sections in a dictionary.
  */
 /*--------------------------------------------------------------------------*/
-int iniparser_find_entry(const dictionary *ini, const char *entry)
+int atalk_iniparser_find_entry(const dictionary *ini, const char *entry)
 {
     int found=0 ;
-    if (iniparser_getstring(ini, entry, NULL, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+    if (atalk_iniparser_getstring(ini, entry, NULL, INI_INVALID_KEY)!=INI_INVALID_KEY) {
         found = 1 ;
     }
     return found ;
@@ -421,9 +421,9 @@ int iniparser_find_entry(const dictionary *ini, const char *entry)
   It is Ok to set val to NULL.
  */
 /*--------------------------------------------------------------------------*/
-int iniparser_set(dictionary * ini, char *section, char * key, char * val)
+int atalk_iniparser_set(dictionary * ini, char *section, char * key, char * val)
 {
-    return dictionary_set(ini, section, key, val) ;
+    return atalkdict_set(ini, section, key, val) ;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -437,9 +437,9 @@ int iniparser_set(dictionary * ini, char *section, char * key, char * val)
   If the given entry can be found, it is deleted from the dictionary.
  */
 /*--------------------------------------------------------------------------*/
-void iniparser_unset(dictionary * ini, char *section, char * key)
+void atalk_iniparser_unset(dictionary * ini, char *section, char * key)
 {
-    dictionary_unset(ini, section, key);
+    atalkdict_unset(ini, section, key);
 }
 
 /*-------------------------------------------------------------------------*/
@@ -452,7 +452,7 @@ void iniparser_unset(dictionary * ini, char *section, char * key)
   @return   line_status value
  */
 /*--------------------------------------------------------------------------*/
-static line_status iniparser_line(
+static line_status atalk_iniparser_line(
     char * input_line,
     char * section,
     char * key,
@@ -522,10 +522,10 @@ static line_status iniparser_line(
   should not be accessed directly, but through accessor functions
   instead.
 
-  The returned dictionary must be freed using iniparser_freedict().
+  The returned dictionary must be freed using atalk_iniparser_freedict().
  */
 /*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(const char * ininame)
+dictionary * atalk_iniparser_load(const char * ininame)
 {
     FILE *in, *include = NULL, *inifile;
 
@@ -546,7 +546,7 @@ dictionary * iniparser_load(const char * ininame)
         return NULL ;
     }
 
-    dict = dictionary_new(0) ;
+    dict = atalkdict_new(0) ;
     if (!dict) {
         fclose(inifile);
         return NULL ;
@@ -587,14 +587,14 @@ dictionary * iniparser_load(const char * ininame)
         } else {
             last=0 ;
         }
-        switch (iniparser_line(line, section, key, val)) {
+        switch (atalk_iniparser_line(line, section, key, val)) {
         case LINE_EMPTY:
         case LINE_COMMENT:
             break ;
         case LINE_SECTION:
             if (strchr(section, ':') != NULL)
                 LOG(log_error, logtype_default, "iniparser: syntax error \"%s\" section name must not contain \":\".", section);
-            errs = dictionary_set(dict, section, NULL, NULL);
+            errs = atalkdict_set(dict, section, NULL, NULL);
             break ;
         case LINE_VALUE:
             if (strcmp(key, "include") == 0) {
@@ -605,7 +605,7 @@ dictionary * iniparser_load(const char * ininame)
                 in = include;
                 continue;
             }
-            errs = dictionary_set(dict, section, key, val) ;
+            errs = atalkdict_set(dict, section, key, val) ;
             break ;
         case LINE_ERROR:
             LOG(log_error, logtype_default, "iniparser: syntax error in %s (lineno: %d): %s",
@@ -623,7 +623,7 @@ dictionary * iniparser_load(const char * ininame)
         }
     }
     if (errs) {
-        dictionary_del(dict);
+        atalkdict_del(dict);
         dict = NULL ;
     }
     fclose(in);
@@ -641,8 +641,8 @@ dictionary * iniparser_load(const char * ininame)
   gets out of the current context.
  */
 /*--------------------------------------------------------------------------*/
-void iniparser_freedict(dictionary * d)
+void atalk_iniparser_freedict(dictionary * d)
 {
-    dictionary_del(d);
+    atalkdict_del(d);
 }
 
diff --git a/libatalk/libatalk-3.0.5.abi b/libatalk/libatalk-3.0.5.abi
new file mode 100644 (file)
index 0000000..2425dc6
--- /dev/null
@@ -0,0 +1,568 @@
+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_v2: int (struct adouble *)
+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 *)
+allow_severity: 5
+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 = 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_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 *)
+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)
+decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+deny_severity: 3
+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_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 = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}}
+ldap_server: 0x0
+ldap_uid_attr: 0x0
+ldap_userbase: 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 *)
+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 = '\0' <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)
+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}}
+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 923e9c84357ffdca3f42e8350467dee6f3aa52a1..02ed81f086e4721750212525b5ffc72018fce82d 100644 (file)
@@ -516,8 +516,8 @@ static const char *getoption(const dictionary *conf, const char *vol, const char
 {
     const char *result;
 
-    if ((!(result = iniparser_getstring(conf, vol, opt, NULL))) && (defsec != NULL))
-        result = iniparser_getstring(conf, defsec, opt, NULL);
+    if ((!(result = atalk_iniparser_getstring(conf, vol, opt, NULL))) && (defsec != NULL))
+        result = atalk_iniparser_getstring(conf, defsec, opt, NULL);
     
     if (result == NULL)
         result = defval;
@@ -539,8 +539,8 @@ static int getoption_bool(const dictionary *conf, const char *vol, const char *o
 {
     int result;
 
-    if (((result = iniparser_getboolean(conf, vol, opt, -1)) == -1) && (defsec != NULL))
-        result = iniparser_getboolean(conf, defsec, opt, -1);
+    if (((result = atalk_iniparser_getboolean(conf, vol, opt, -1)) == -1) && (defsec != NULL))
+        result = atalk_iniparser_getboolean(conf, defsec, opt, -1);
     
     if (result == -1)
         result = defval;
@@ -668,7 +668,7 @@ static struct vol *creatvol(AFPObj *obj,
         if(tmpname[i] == '/') tmpname[i] = ':';
 
     bstring dbpath;
-    EC_NULL( val = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") );
+    EC_NULL( val = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") );
     EC_NULL( dbpath = bformat("%s/%s/", val, tmpname) );
     EC_NULL( volume->v_dbpath = strdup(cfrombstr(dbpath)) );
     bdestroy(dbpath);
@@ -772,12 +772,29 @@ static struct vol *creatvol(AFPObj *obj,
         volume->v_flags |= AFPVOL_NOV2TOEACONV;
     if (getoption_bool(obj->iniconfig, section, "follow symlinks", preset, 0))
         volume->v_flags |= AFPVOL_FOLLOWSYM;
+    if (getoption_bool(obj->iniconfig, section, "delete veto files", preset, 0))
+        volume->v_flags |= AFPVOL_DELVETO;
 
     if (getoption_bool(obj->iniconfig, section, "preexec close", preset, 0))
         volume->v_preexec_close = 1;
     if (getoption_bool(obj->iniconfig, section, "root preexec close", preset, 0))
         volume->v_root_preexec_close = 1;
 
+    if ((val = getoption(obj->iniconfig, section, "ignored attributes", preset, obj->options.ignored_attr))) {
+        if (strstr(val, "all")) {
+            volume->v_ignattr |= ATTRBIT_NOWRITE | ATTRBIT_NORENAME | ATTRBIT_NODELETE;
+        }
+        if (strstr(val, "nowrite")) {
+            volume->v_ignattr |= ATTRBIT_NOWRITE;
+        }
+        if (strstr(val, "norename")) {
+            volume->v_ignattr |= ATTRBIT_NORENAME;
+        }
+        if (strstr(val, "nodelete")) {
+            volume->v_ignattr |= ATTRBIT_NODELETE;
+        }
+    }
+
     /*
      * Handle read-only behaviour. semantics:
      * 1) neither the rolist nor the rwlist exist -> rw
@@ -985,16 +1002,16 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
 
     LOG(log_debug, logtype_afpd, "readvolfile: BEGIN");
 
-    int secnum = iniparser_getnsec(obj->iniconfig);    
+    int secnum = atalk_iniparser_getnsec(obj->iniconfig);    
     LOG(log_debug, logtype_afpd, "readvolfile: sections: %d", secnum);
     const char *secname;
 
-    if ((default_preset = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol preset", NULL))) {
+    if ((default_preset = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol preset", NULL))) {
         LOG(log_debug, logtype_afpd, "readvolfile: default_preset: %s", default_preset);
     }
 
     for (i = 0; i < secnum; i++) { 
-        secname = iniparser_getsecname(obj->iniconfig, i);
+        secname = atalk_iniparser_getsecname(obj->iniconfig, i);
 
         if (!vol_section(secname))
             continue;
@@ -1012,7 +1029,7 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
                 continue;
 
             /* check if user home matches our "basedir regex" */
-            if ((basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL) {
+            if ((basedir = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL) {
                 LOG(log_error, logtype_afpd, "\"basedir regex =\" must be defined in [Homes] section");
                 continue;
             }
@@ -1031,13 +1048,13 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
                 continue;
             }
 
-            if ((p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
+            if ((p = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
                 strlcat(tmp, "/", MAXPATHLEN);
                 strlcat(tmp, p, MAXPATHLEN);
             }
         } else {
             /* Get path */
-            if ((p = iniparser_getstring(obj->iniconfig, secname, "path", NULL)) == NULL)
+            if ((p = atalk_iniparser_getstring(obj->iniconfig, secname, "path", NULL)) == NULL)
                 continue;
             strlcpy(tmp, p, MAXPATHLEN);
         }
@@ -1047,7 +1064,7 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
 
         /* do variable substitution for volume name */
         if (STRCMP(secname, ==, INISEC_HOMES)) {
-            p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
+            p = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
             if (strstr(p, "$u") == NULL) {
                 LOG(log_warning, logtype_afpd, "home name must contain $u.");
                 p = "$u's home";
@@ -1063,7 +1080,7 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
         if (volxlate(obj, volname, sizeof(volname) - 1, tmp, pwent, path, NULL) == NULL)
             continue;
 
-        preset = iniparser_getstring(obj->iniconfig, secname, "vol preset", NULL);
+        preset = atalk_iniparser_getstring(obj->iniconfig, secname, "vol preset", NULL);
 
         if ((realvolpath = realpath_safe(path)) == NULL)
             continue;
@@ -1317,16 +1334,34 @@ int load_charset(struct vol *vol)
 int load_volumes(AFPObj *obj)
 {
     EC_INIT;
-    int fd = -1;
-    struct passwd   *pwent = NULL;
+
+    static long         bufsize;
+    static char        *pwbuf = NULL;
+
+    int                 fd = -1;
+    struct passwd       pwent;
+    struct passwd      *pwresult = NULL;
     struct stat         st;
-    int retries = 0;
-    struct vol *vol;
+    int                 retries = 0;
+    struct vol         *vol;
 
     LOG(log_debug, logtype_afpd, "load_volumes: BEGIN");
 
-    if (obj->uid)
-        pwent = getpwuid(obj->uid);
+    if (pwbuf == NULL) {
+        bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
+        if (bufsize == -1)          /* Value was indeterminate */
+            bufsize = 16384;        /* Should be more than enough */
+        EC_NULL( pwbuf = malloc(bufsize) );
+    }
+
+    if (obj->uid) {
+        ret = getpwuid_r(obj->uid, &pwent, pwbuf, bufsize, &pwresult);
+        if (pwresult == NULL) {
+            LOG(log_error, logtype_afpd, "load_volumes: getpwuid_r: %s", strerror(errno));
+            EC_FAIL;
+        }
+        pwresult = &pwent;
+    }
 
     if (Volumes) {
         if (!volfile_changed(&obj->options))
@@ -1335,9 +1370,9 @@ int load_volumes(AFPObj *obj)
         for (vol = Volumes; vol; vol = vol->v_next) {
             vol->v_deleted = 1;
         }
-        if (obj->uid) {
+        if (obj->uid && pwresult) {
             become_root();
-            ret = set_groups(obj, pwent);
+            ret = set_groups(obj, pwresult);
             unbecome_root();
             if (ret != 0) {
                 LOG(log_error, logtype_afpd, "load_volumes: set_groups: %s", strerror(errno));
@@ -1369,11 +1404,11 @@ int load_volumes(AFPObj *obj)
     }
 
     if (obj->iniconfig)
-        iniparser_freedict(obj->iniconfig);
+        atalk_iniparser_freedict(obj->iniconfig);
     LOG(log_debug, logtype_afpd, "load_volumes: loading: %s", obj->options.configfile);
-    obj->iniconfig = iniparser_load(obj->options.configfile);
+    obj->iniconfig = atalk_iniparser_load(obj->options.configfile);
 
-    EC_ZERO_LOG( readvolfile(obj, pwent) );
+    EC_ZERO_LOG( readvolfile(obj, pwresult) );
 
     struct vol *p, *prevvol;
 
@@ -1554,10 +1589,10 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     if (!have_uservol) /* (2) */
         EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path);
 
-    int secnum = iniparser_getnsec(obj->iniconfig);
+    int secnum = atalk_iniparser_getnsec(obj->iniconfig);
 
     for (int i = 0; i < secnum; i++) { 
-        secname = iniparser_getsecname(obj->iniconfig, i);
+        secname = atalk_iniparser_getsecname(obj->iniconfig, i);
         if (STRCMP(secname, ==, INISEC_HOMES))
             break;
     }
@@ -1566,7 +1601,7 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
         EC_FAIL_LOG("getvolbypath(\"%s\"): no volume for path", path);
 
     /* (3) */
-    EC_NULL_LOG( basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL) );
+    EC_NULL_LOG( basedir = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL) );
     LOG(log_debug, logtype_afpd, "getvolbypath: user home section: '%s', basedir: '%s'", secname, basedir);
 
     if (regexerr != 0 && (regexerr = regcomp(&reg, basedir, REG_EXTENDED)) != 0) {
@@ -1615,7 +1650,7 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
     strlcat(tmpbuf, "/", MAXPATHLEN);
 
     /* (6) */
-    if ((subpathconfig = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
+    if ((subpathconfig = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))) {
         /*
         if (!subpath || strncmp(subpathconfig, subpath, strlen(subpathconfig)) != 0) {
             EC_FAIL;
@@ -1637,15 +1672,15 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
         path, user, pw->pw_dir, realvolpath);
 
     /* do variable substitution for volume name */
-    p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
+    p = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
     if (strstr(p, "$u") == NULL)
         p = "$u's home";
     strlcpy(tmpbuf, p, AFPVOL_U8MNAMELEN);
     EC_NULL_LOG( volxlate(obj, volname, sizeof(volname) - 1, tmpbuf, pw, realvolpath, NULL) );
 
     const char  *preset, *default_preset;
-    default_preset = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol preset", NULL);
-    preset = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "vol preset", NULL);
+    default_preset = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol preset", NULL);
+    preset = atalk_iniparser_getstring(obj->iniconfig, INISEC_HOMES, "vol preset", NULL);
 
     vol = creatvol(obj, pw, INISEC_HOMES, volname, realvolpath, preset ? preset : default_preset ? default_preset : NULL);
 
@@ -1696,71 +1731,74 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     options->uuidconf    = strdup(_PATH_STATEDIR "afp_voluuid.conf");
     options->flags       = OPTION_UUID | AFPObj->cmdlineflags;
     
-    if ((config = iniparser_load(AFPObj->options.configfile)) == NULL)
+    if ((config = atalk_iniparser_load(AFPObj->options.configfile)) == NULL)
         return -1;
     AFPObj->iniconfig = config;
 
     /* [Global] */
-    options->logconfig = iniparser_getstrdup(config, INISEC_GLOBAL, "log level", "default:note");
-    options->logfile   = iniparser_getstrdup(config, INISEC_GLOBAL, "log file",  NULL);
+    options->logconfig = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "log level", "default:note");
+    options->logfile   = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "log file",  NULL);
 
     setuplog(options->logconfig, options->logfile);
 
     /* "server options" boolean options */
-    if (!iniparser_getboolean(config, INISEC_GLOBAL, "zeroconf", 1))
+    if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "zeroconf", 1))
         options->flags |= OPTION_NOZEROCONF;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "advertise ssh", 0))
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "advertise ssh", 0))
         options->flags |= OPTION_ANNOUNCESSH;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0))
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0))
         options->flags |= OPTION_CLOSEVOL;
-    if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0))
+    if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0))
         options->flags |= OPTION_SERVERNOTIF;
-    if (!iniparser_getboolean(config, INISEC_GLOBAL, "use sendfile", 1))
+    if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "use sendfile", 1))
         options->flags |= OPTION_NOSENDFILE;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "solaris share reservations", 1))
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "solaris share reservations", 1))
         options->flags |= OPTION_SHARE_RESERV;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "afpstats", 0))
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "afpstats", 0))
         options->flags |= OPTION_DBUS_AFPSTATS;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "afp read locks", 0))
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "afp read locks", 0))
         options->flags |= OPTION_AFP_READ_LOCK;
-    if (!iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1))
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "veto message", 0))
+        options->flags |= OPTION_VETOMSG;
+    if (!atalk_iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1))
         options->passwdbits |= PASSWD_NOSAVE;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0))
+    if (atalk_iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0))
         options->passwdbits |= PASSWD_SET;
 
     /* figure out options w values */
-    options->loginmesg      = iniparser_getstrdup(config, INISEC_GLOBAL, "login message",  NULL);
-    options->guest          = iniparser_getstrdup(config, INISEC_GLOBAL, "guest account",  "nobody");
-    options->extmapfile     = iniparser_getstrdup(config, INISEC_GLOBAL, "extmap file",    _PATH_CONFDIR "extmap.conf");
-    options->passwdfile     = iniparser_getstrdup(config, INISEC_GLOBAL, "passwd file",    _PATH_AFPDPWFILE);
-    options->uampath        = iniparser_getstrdup(config, INISEC_GLOBAL, "uam path",       _PATH_AFPDUAMPATH);
-    options->uamlist        = iniparser_getstrdup(config, INISEC_GLOBAL, "uam list",       "uams_dhx.so uams_dhx2.so");
-    options->port           = iniparser_getstrdup(config, INISEC_GLOBAL, "afp port",       "548");
-    options->signatureopt   = iniparser_getstrdup(config, INISEC_GLOBAL, "signature",      "");
-    options->k5service      = iniparser_getstrdup(config, INISEC_GLOBAL, "k5 service",     NULL);
-    options->k5realm        = iniparser_getstrdup(config, INISEC_GLOBAL, "k5 realm",       NULL);
-    options->listen         = iniparser_getstrdup(config, INISEC_GLOBAL, "afp listen",     NULL);
-    options->interfaces     = iniparser_getstrdup(config, INISEC_GLOBAL, "afp interfaces", NULL);
-    options->ntdomain       = iniparser_getstrdup(config, INISEC_GLOBAL, "nt domain",      NULL);
-    options->addomain       = iniparser_getstrdup(config, INISEC_GLOBAL, "ad domain",      NULL);
-    options->ntseparator    = iniparser_getstrdup(config, INISEC_GLOBAL, "nt separator",   NULL);
-    options->mimicmodel     = iniparser_getstrdup(config, INISEC_GLOBAL, "mimic model",    NULL);
-    options->adminauthuser  = iniparser_getstrdup(config, INISEC_GLOBAL, "admin auth user",NULL);
-    options->connections    = iniparser_getint   (config, INISEC_GLOBAL, "max connections",200);
-    options->passwdminlen   = iniparser_getint   (config, INISEC_GLOBAL, "passwd minlen",  0);
-    options->tickleval      = iniparser_getint   (config, INISEC_GLOBAL, "tickleval",      30);
-    options->timeout        = iniparser_getint   (config, INISEC_GLOBAL, "timeout",        4);
-    options->dsireadbuf     = iniparser_getint   (config, INISEC_GLOBAL, "dsireadbuf",     12);
-    options->server_quantum = iniparser_getint   (config, INISEC_GLOBAL, "server quantum", DSI_SERVQUANT_DEF);
-    options->volnamelen     = iniparser_getint   (config, INISEC_GLOBAL, "volnamelen",     80);
-    options->dircachesize   = iniparser_getint   (config, INISEC_GLOBAL, "dircachesize",   DEFAULT_MAX_DIRCACHE_SIZE);
-    options->tcp_sndbuf     = iniparser_getint   (config, INISEC_GLOBAL, "tcpsndbuf",      0);
-    options->tcp_rcvbuf     = iniparser_getint   (config, INISEC_GLOBAL, "tcprcvbuf",      0);
-    options->fce_fmodwait   = iniparser_getint   (config, INISEC_GLOBAL, "fce holdfmod",   60);
-    options->sleep          = iniparser_getint   (config, INISEC_GLOBAL, "sleep time",     10);
-    options->disconnected   = iniparser_getint   (config, INISEC_GLOBAL, "disconnect time",24);
-
-    p = iniparser_getstring(config, INISEC_GLOBAL, "map acls", "rights");
+    options->loginmesg      = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "login message",  NULL);
+    options->guest          = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "guest account",  "nobody");
+    options->extmapfile     = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "extmap file",    _PATH_CONFDIR "extmap.conf");
+    options->passwdfile     = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "passwd file",    _PATH_AFPDPWFILE);
+    options->uampath        = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "uam path",       _PATH_AFPDUAMPATH);
+    options->uamlist        = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "uam list",       "uams_dhx.so uams_dhx2.so");
+    options->port           = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "afp port",       "548");
+    options->signatureopt   = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "signature",      "");
+    options->k5service      = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "k5 service",     NULL);
+    options->k5realm        = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "k5 realm",       NULL);
+    options->listen         = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "afp listen",     NULL);
+    options->interfaces     = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "afp interfaces", NULL);
+    options->ntdomain       = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "nt domain",      NULL);
+    options->addomain       = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "ad domain",      NULL);
+    options->ntseparator    = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "nt separator",   NULL);
+    options->mimicmodel     = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "mimic model",    NULL);
+    options->adminauthuser  = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "admin auth user",NULL);
+    options->ignored_attr   = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "ignored attributes", NULL);
+    options->connections    = atalk_iniparser_getint   (config, INISEC_GLOBAL, "max connections",200);
+    options->passwdminlen   = atalk_iniparser_getint   (config, INISEC_GLOBAL, "passwd minlen",  0);
+    options->tickleval      = atalk_iniparser_getint   (config, INISEC_GLOBAL, "tickleval",      30);
+    options->timeout        = atalk_iniparser_getint   (config, INISEC_GLOBAL, "timeout",        4);
+    options->dsireadbuf     = atalk_iniparser_getint   (config, INISEC_GLOBAL, "dsireadbuf",     12);
+    options->server_quantum = atalk_iniparser_getint   (config, INISEC_GLOBAL, "server quantum", DSI_SERVQUANT_DEF);
+    options->volnamelen     = atalk_iniparser_getint   (config, INISEC_GLOBAL, "volnamelen",     80);
+    options->dircachesize   = atalk_iniparser_getint   (config, INISEC_GLOBAL, "dircachesize",   DEFAULT_MAX_DIRCACHE_SIZE);
+    options->tcp_sndbuf     = atalk_iniparser_getint   (config, INISEC_GLOBAL, "tcpsndbuf",      0);
+    options->tcp_rcvbuf     = atalk_iniparser_getint   (config, INISEC_GLOBAL, "tcprcvbuf",      0);
+    options->fce_fmodwait   = atalk_iniparser_getint   (config, INISEC_GLOBAL, "fce holdfmod",   60);
+    options->sleep          = atalk_iniparser_getint   (config, INISEC_GLOBAL, "sleep time",     10);
+    options->disconnected   = atalk_iniparser_getint   (config, INISEC_GLOBAL, "disconnect time",24);
+
+    p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "map acls", "rights");
     if (STRCMP(p, ==, "rights"))
         options->flags |= OPTION_ACL2MACCESS;
     else if (STRCMP(p, ==, "mode"))
@@ -1772,7 +1810,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
         }
     }
 
-    if ((p = iniparser_getstring(config, INISEC_GLOBAL, "hostname", NULL))) {
+    if ((p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "hostname", NULL))) {
         EC_NULL_LOG( options->hostname = strdup(p) );
     } else {
         if (gethostname(val, sizeof(val)) < 0 ) {
@@ -1784,21 +1822,21 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
         options->hostname = strdup(val);
     }
 
-    if ((p = iniparser_getstring(config, INISEC_GLOBAL, "k5 keytab", NULL))) {
+    if ((p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "k5 keytab", NULL))) {
         EC_NULL_LOG( options->k5keytab = malloc(strlen(p) + 14) );
         snprintf(options->k5keytab, strlen(p) + 14, "KRB5_KTNAME=%s", p);
         putenv(options->k5keytab);
     }
 
 #ifdef ADMIN_GRP
-    if ((p = iniparser_getstring(config, INISEC_GLOBAL, "admin group",  NULL))) {
+    if ((p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "admin group",  NULL))) {
          struct group *gr = getgrnam(p);
          if (gr != NULL)
              options->admingid = gr->gr_gid;
     }
 #endif /* ADMIN_GRP */
 
-    q = iniparser_getstrdup(config, INISEC_GLOBAL, "cnid server", "localhost:4700");
+    q = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "cnid server", "localhost:4700");
     r = strrchr(q, ':');
     if (r)
         *r = 0;
@@ -1811,7 +1849,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     if (q)
         free(q);
 
-    if ((q = iniparser_getstrdup(config, INISEC_GLOBAL, "fqdn", NULL))) {
+    if ((q = atalk_iniparser_getstrdup(config, INISEC_GLOBAL, "fqdn", NULL))) {
         /* do a little checking for the domain name. */
         r = strchr(q, ':');
         if (r)
@@ -1821,7 +1859,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
                 *r = ':';
             EC_NULL_LOG( options->fqdn = strdup(q) );
         } else {
-            LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", c);
+            LOG(log_error, logtype_afpd, "error parsing -fqdn, gethostbyname failed for: %s", q);
         }
         free(q);
     }
@@ -1829,7 +1867,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     /* Charset Options */
 
     /* unix charset is in [G] only */
-    if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "unix charset", NULL))) {
+    if (!(p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "unix charset", NULL))) {
         options->unixcodepage = strdup("UTF8");
         set_charset_name(CH_UNIX, "UTF8");
     } else {
@@ -1853,7 +1891,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     LOG(log_debug, logtype_afpd, "Global unix charset is %s", options->unixcodepage);
 
     /* vol charset is in [G] and [V] */
-    if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "vol charset", NULL))) {
+    if (!(p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "vol charset", NULL))) {
         options->volcodepage = strdup(options->unixcodepage);
     } else {
         if (strcasecmp(p, "UTF-8") == 0) {
@@ -1864,7 +1902,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     LOG(log_debug, logtype_afpd, "Global vol charset is %s", options->volcodepage);
     
     /* mac charset is in [G] and [V] */
-    if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "mac charset", NULL))) {
+    if (!(p = atalk_iniparser_getstring(config, INISEC_GLOBAL, "mac charset", NULL))) {
         options->maccodepage = strdup("MAC_ROMAN");
         set_charset_name(CH_MAC, "MAC_ROMAN");
     } else {
@@ -1964,6 +2002,8 @@ void afp_config_free(AFPObj *obj)
         CONFIG_ARG_FREE(obj->options.Cnid_port);
     if (obj->options.fqdn)
         CONFIG_ARG_FREE(obj->options.fqdn);
+    if (obj->options.ignored_attr)
+        CONFIG_ARG_FREE(obj->options.ignored_attr);
 
     if (obj->options.unixcodepage)
         CONFIG_ARG_FREE(obj->options.unixcodepage);
@@ -1977,6 +2017,6 @@ void afp_config_free(AFPObj *obj)
 
     /* Free everything called from afp_config_parse() */
     free_extmap();
-    iniparser_freedict(obj->iniconfig);
+    atalk_iniparser_freedict(obj->iniconfig);
     free_charset_names();
 }
index acea8ad39218dfa03fa6ec828abf4030c25433db..c7ef534a7e556567bda75e22eb3048a4616816ae 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <atalk/logger.h>
 #include <atalk/util.h>
+#include <atalk/errchk.h>
 
 static char ipv4mapprefix[] = {0,0,0,0,0,0,0,0,0,0,0xff,0xff};
 
@@ -417,6 +418,91 @@ int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2)
     return ret;
 }
 
+/*!
+ * Tokenize IP(4/6) addresses with an optional port into address and port
+ *
+ * @param ipurl    (r) IP URL string
+ * @param address  (w) IP address
+ * @param port     (w) IP port
+ *
+ * @returns 0 on success, -1 on failure
+ *
+ * Tokenize IPv4, IPv4:port, IPv6, [IPv6] or [IPv6:port] URL into address and
+ * port and return two allocated strings with the address and the port.
+ *
+ * If the function returns 0, then address point to a newly allocated
+ * valid address string, port may either be NULL or point to a newly
+ * allocated port number.
+ *
+ * If the function returns -1, then the contents of address and port are
+ * undefined.
+ */
+int tokenize_ip_port(const char *ipurl, char **address, char **port)
+{
+    EC_INIT;
+    char *p = NULL;
+    char *s;
+
+    AFP_ASSERT(ipurl && address && port);
+    EC_NULL( p = strdup(ipurl));
+
+    /* Either ipv4, ipv4:port, ipv6, [ipv6] or [ipv6]:port */
+
+    if (!strchr(p, ':')) {
+        /* IPv4 address without port */
+        *address = p;
+        p = NULL;  /* prevent free() */
+        *port = NULL;
+        EC_EXIT_STATUS(0);
+    }
+
+    /* Either ipv4:port, ipv6, [ipv6] or [ipv6]:port */
+
+    if (strchr(p, '.')) {
+        /* ipv4:port */
+        *address = p;
+        p = strchr(p, ':');
+        *p = '\0';
+        EC_NULL( *port = strdup(p + 1));
+        p = NULL; /* prevent free() */
+        EC_EXIT_STATUS(0);
+    }
+
+    /* Either ipv6, [ipv6] or [ipv6]:port */
+
+    if (p[0] != '[') {
+        /* ipv6 */
+        *address = p;
+        p = NULL;  /* prevent free() */
+        *port = NULL;
+        EC_EXIT_STATUS(0);
+    }
+
+    /* [ipv6] or [ipv6]:port */
+
+    EC_NULL( *address = strdup(p + 1) );
+
+    if ((s = strchr(*address, ']')) == NULL) {
+        LOG(log_error, logtype_dsi, "tokenize_ip_port: malformed ipv6 address %s\n", ipurl);
+        EC_FAIL;
+    }
+    *s = '\0';
+    /* address now points to the ipv6 address without [] */
+
+    if (s[1] == ':') {
+        /* [ipv6]:port */
+        EC_NULL( *port = strdup(s + 2) );
+    } else {
+        /* [ipv6] */
+        *port = NULL;
+    }
+
+EC_CLEANUP:
+    if (p)
+        free(p);
+    EC_EXIT;
+}
+
 /*!
  * Add a fd to a dynamic pollfd array that is allocated and grown as needed
  *
index bc90c75ad539bcdaa7f8a00e14271adf37538092..79e4fd33c29b151a08cd4afb4b157c638ea444b4 100644 (file)
@@ -74,6 +74,7 @@ int netatalk_rmdir_all_errors(int dirfd, const char *name)
         case ENOENT :
             return AFPERR_NOOBJ;
         case ENOTEMPTY :
+        case EEXIST:
             return AFPERR_DIRNEMPT;
         case EPERM:
         case EACCES :
index d79ac05e1142cb14d53bf226ba45e53722ef74ab..a793cd283f5aa34c394981be77cde3f33425a6e1 100644 (file)
@@ -467,9 +467,15 @@ static int deletecurdir_ea_osx_chkifempty_loop(const struct vol *vol, struct dir
 static int deletecurdir_ea_osx_loop(const struct vol *vol, struct dirent *de, char *name, void *data _U_, int flag _U_)
 {
     int ret;
-    
-    if ((ret = netatalk_unlink(name)) != 0)
-        return ret;
+    struct stat sb;
+
+    if (strncmp(name, "._", strlen("._")) == 0) {
+        if (lstat(name, &sb) != 0)
+            return -1;
+        if (S_ISREG(sb.st_mode))
+            if ((ret = netatalk_unlink(name)) != 0)
+                return ret;
+    }
 
     return 0;
 }
@@ -480,17 +486,6 @@ static int RF_deletecurdir_ea(VFS_FUNC_ARGS_DELETECURDIR)
 #ifndef HAVE_EAFD
     int err;
     /* delete stray ._AppleDouble files */
-
-    /* first check if there's really no other file besides files starting with ._ */
-    if ((err = for_each_adouble("deletecurdir_ea_osx", ".",
-                                deletecurdir_ea_osx_chkifempty_loop,
-                                vol, NULL, 0)) != 0) {
-        if (err == 1)
-            return AFPERR_DIRNEMPT;
-        return AFPERR_MISC;
-    }
-
-    /* Now delete orphaned ._ files */
     if ((err = for_each_adouble("deletecurdir_ea_osx", ".",
                                 deletecurdir_ea_osx_loop,
                                 vol, NULL, 0)) != 0)
index 902220befa3581e0a1d6a9dea9bc4a850e4ea599..4135e5ce2801915853e598ef0f8596726b4bcc42 100644 (file)
@@ -155,6 +155,9 @@ if test "x$bdb_required" = "xyes"; then
                         if test x"${atalk_cv_bdb_version}" = x"yes"; then
                             BDB_CFLAGS="-I${bdbdir}/include${subdir}"
                             BDB_LIBS="-L${bdblibdir} ${atalk_cv_lib_db}"
+                            if test x"$need_dash_r" = x"yes"; then
+                                BDB_LIBS="$BDB_LIBS -R${bdblibdir}"
+                            fi
                             BDB_BIN="$bdbbindir"
                             BDB_PATH="$bdbdir"
                             bdbfound=yes
@@ -178,6 +181,9 @@ if test "x$bdb_required" = "xyes"; then
                            if test x"${atalk_cv_bdb_version}" = x"yes"; then
                               BDB_CFLAGS="-I${bdbdir}/include${subdir}"
                               BDB_LIBS="-L${bdblibdir} ${atalk_cv_lib_db}"
+                              if test x"$need_dash_r" = x"yes"; then
+                                 BDB_LIBS="$BDB_LIBS -R${bdblibdir}"
+                              fi
                               BDB_BIN="$bdbbindir"
                               BDB_PATH="$bdbdir"
                               bdbfound=yes
index 1a55276471d8e7c2066fd5db2b12006d0e22c189..4a87efcec2ea8e8d07bf42c910aa0fe02d63d146 100644 (file)
@@ -413,7 +413,7 @@ AC_DEFUN([AC_NETATALK_INIT_STYLE], [
            ;;
     "redhat-systemd")
            AC_MSG_RESULT([enabling redhat-style systemd support])
-           ac_cv_init_dir="/lib/systemd/system"
+           ac_cv_init_dir="/usr/lib/systemd/system"
            ;;
     "suse")
            AC_MSG_ERROR([--with-init-style=suse is obsoleted. Use suse-sysv or suse-systemd.])
@@ -424,7 +424,7 @@ AC_DEFUN([AC_NETATALK_INIT_STYLE], [
            ;;
     "suse-systemd")
            AC_MSG_RESULT([enabling suse-style systemd support (>=openSUSE12.1)])
-           ac_cv_init_dir="/lib/systemd/system"
+           ac_cv_init_dir="/usr/lib/systemd/system"
            ;;
     "gentoo")
            AC_MSG_RESULT([enabling gentoo-style initscript support])
@@ -444,7 +444,7 @@ AC_DEFUN([AC_NETATALK_INIT_STYLE], [
         ;;
     "systemd")
            AC_MSG_RESULT([enabling general systemd support])
-           ac_cv_init_dir="/lib/systemd/system"
+           ac_cv_init_dir="/usr/lib/systemd/system"
         ;;
     "none")
            AC_MSG_RESULT([disabling init-style support])
@@ -570,87 +570,8 @@ if test x"$this_os" = "xsolaris"; then
        AC_DEFINE(SOLARIS, 1, [Solaris compatibility macro])
     AC_DEFINE(_XOPEN_SOURCE, 600, [Solaris compilation environment])
     AC_DEFINE(__EXTENSIONS__,  1, [Solaris compilation environment])
-       CFLAGS="-I\$(top_srcdir)/sys/generic $CFLAGS"
        need_dash_r=yes
        init_style=solaris
-
-       solaris_module=no
-       AC_MSG_CHECKING([if we can build Solaris kernel module])
-       if test -x /usr/ccs/bin/ld && test x"$netatalk_cv_ddp_enabled" = x"yes" ; then
-               solaris_module=yes
-       fi
-       AC_MSG_RESULT([$solaris_module])
-
-       COMPILE_64BIT_KMODULE=no
-       KCFLAGS=""
-       KLDFLAGS=""
-       COMPILE_KERNEL_GCC=no
-
-       if test "$solaris_module" = "yes"; then
-          dnl Solaris kernel module stuff
-           AC_MSG_CHECKING([if we have to build a 64bit kernel module])
-
-          # check for isainfo, if not found it has to be a 32 bit kernel (<=2.6)       
-          if test -x /usr/bin/isainfo; then
-               # check for 64 bit platform
-               if isainfo -kv | grep '^64-bit'; then
-                       COMPILE_64BIT_KMODULE=yes
-               fi
-          fi
-
-          AC_MSG_RESULT([$COMPILE_64BIT_KMODULE])
-
-          if test "${GCC}" = yes; then
-               COMPILE_KERNEL_GCC=yes
-               if test "$COMPILE_64BIT_KMODULE" = yes; then
-               
-                        AC_MSG_CHECKING([if we can build a 64bit kernel module])
-                       
-                        case `$CC --version 2>/dev/null` in
-                       [[12]].* | 3.0.*)
-                               COMPILE_64BIT_KMODULE=no
-                               COMPILE_KERNEL_GCC=no   
-                               solaris_module=no;;
-                       *)
-                               # use for 64 bit
-                               KCFLAGS="-m64"
-                               #KLDFLAGS="-melf64_sparc"
-                               KLDFLAGS="-64";;
-                       esac    
-                       
-                       AC_MSG_RESULT([$COMPILE_64BIT_KMODULE])
-                       
-               else
-                       KCFLAGS=""
-                       KLDFLAGS=""
-               fi
-               KCFLAGS="$KCFLAGS -D_KERNEL -Wall -Wstrict-prototypes"
-           else
-               if test "$COMPILE_64BIT_KMODULE" = yes; then
-                # use Sun CC (for a 64-bit kernel, uncomment " -xarch=v9 -xregs=no%appl ")
-                       KCFLAGS="-xarch=v9 -xregs=no%appl"
-                       KLDFLAGS="-64"
-               else
-                       KCFLAGS=""
-                       KLDFLAGS=""
-               fi
-               KCFLAGS="-D_KERNEL $KCFLAGS -mno-app-regs -munaligned-doubles -fpcc-struct-return"
-          fi
-
-           AC_CACHE_CHECK([for timeout_id_t],netatalk_cv_HAVE_TIMEOUT_ID_T,[
-           AC_LINK_IFELSE([AC_LANG_PROGRAM([[\
-#include <sys/stream.h>
-#include <sys/ddi.h>]], [[\
-timeout_id_t dummy;
-]])],[netatalk_cv_HAVE_TIMEOUT_ID_T=yes],[netatalk_cv_HAVE_TIMEOUT_ID_T=no])])
-
-          AC_DEFINE(HAVE_TIMEOUT_ID_T, test x"$netatalk_cv_HAVE_TIMEOUT_ID" = x"yes", [define for timeout_id_t])
-       fi
-
-       AC_SUBST(COMPILE_KERNEL_GCC)
-       AC_SUBST(COMPILE_64BIT_KMODULE)
-       AC_SUBST(KCFLAGS)
-       AC_SUBST(KLDFLAGS)
 fi
 
 dnl Whether to run ldconfig after installing libraries
index ba8cde05a352b88523144b8a2d0f8fca5ef279da..3a4b2a3cd2f3e45b6255f11eaf56c6d4d2f796d8 100644 (file)
@@ -83,9 +83,10 @@ AC_DEFUN([AC_NETATALK_LIBS_SUMMARY], [
        dnl #################################################
        dnl # Display summary of libraries detected
 
-       AC_MSG_RESULT([Using libraries:])
-       AC_MSG_RESULT([    LIBS           = $LIBS])
+       AC_MSG_RESULT([Compilation summary:])
+       AC_MSG_RESULT([    CPPFLAGS       = $CPPFLAGS])
        AC_MSG_RESULT([    CFLAGS         = $CFLAGS])
+       AC_MSG_RESULT([    LIBS           = $LIBS])
        AC_MSG_RESULT([    PTHREADS:])
        AC_MSG_RESULT([        LIBS   = $PTHREAD_LIBS])
        AC_MSG_RESULT([        CFLAGS = $PTHREAD_CFLAGS])
index 90ac57ac921273f22f2725e4e455ab16083de163..7a1f56d5af83129550089c83264f302815e8022a 100644 (file)
@@ -424,6 +424,8 @@ afp listen = \fIip address[:port] [ip address[:port] \&.\&.\&.]\fR \fB(G)\fR
 Specifies the IP address that the server should advertise
 \fBand\fR
 listens to\&. The default is advertise the first IP address of the system, but to listen for any incoming request\&. The network address may be specified either in dotted\-decimal format for IPv4 or in hexadecimal format for IPv6\&.
+.sp
+IPv6 address + port combination must use URL the format using square brackets [IPv6]:port
 .RE
 .PP
 afp port = \fIport number\fR \fB(G)\fR
@@ -566,6 +568,16 @@ Sets a message to be displayed when clients logon to the server\&. The message s
 and should be quoted\&. Extended characters are allowed\&.
 .RE
 .PP
+ignored attributes = \fIall | nowrite | nodelete | norename\fR \fB(G)/(V)\fR
+.RS 4
+Speficy a set of file and directory attributes that shall be ignored by the server,
+<attribute>all</attribute>
+includes all the other options\&.
+.sp
+In OS X when the Finder sets a lock on a file/directory or you set the BSD uchg flag in the Terminal, all three attributes are used\&. Thus in order to ignore the Finder lock/BSD uchg flag, add set
+\fIignored attributes = all\fR\&.
+.RE
+.PP
 mimic model = \fImodel\fR \fB(G)\fR
 .RS 4
 Specifies the icon model that appears on clients\&. Defaults to off\&. Note that afpd must support Zeroconf\&. Examples: RackMac (same as Xserve), PowerBook, PowerMac, Macmini, iMac, MacBook, MacBookPro, MacBookAir, MacPro, AppleTV1,1, AirPort\&.
@@ -583,6 +595,13 @@ 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
+veto message = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
+.RS 4
+Use section
+\fBname\fR
+as option preset for all volumes (when set in the [Global] section) or for one volume (when set in that volume\*(Aqs section)\&.
+.RE
+.PP
 vol dbpath = \fIpath\fR \fB(G)\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
@@ -1044,6 +1063,13 @@ is performed when accessing filesystems from clients\&. This is generally useful
 on volumes and do the conversion with that\&. Then this option can be set to no\&.
 .RE
 .PP
+delete veto files = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
+.RS 4
+This option is used when Netatalk is attempting to delete a directory that contains one or more vetoed files or directories (see the veto files option)\&. If this option is set to no (the default) then if a directory contains any non\-vetoed files or directories then the directory delete will fail\&. This is usually what you want\&.
+.sp
+If this option is set to yes, then Netatalk will attempt to recursively delete any files and directories within the vetoed directory\&.
+.RE
+.PP
 follow symlinks = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
 .RS 4
 The default setting is false thus symlinks are not followed on the server\&. This is the same behaviour as OS X\*(Aqs 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\*(Aqt do any checks for "wide symlinks"\&.