+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
-3.0.4
\ No newline at end of file
+3.0.5
\ No newline at end of file
#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) {
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)
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"
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
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
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
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
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>
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
-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
<!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>
--- /dev/null
+<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>
<?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>
<surname>Lahm</surname>
</author>
- <pubdate>15 Feb, 2013</pubdate>
+ <pubdate>29 Jul, 2013</pubdate>
</chapterinfo>
<title>Upgrading from Netatalk 2</title>
<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>
+++ /dev/null
-<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>
--- /dev/null
+ReleaseNotes.html
-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
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
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
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);
}
/* 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;
}
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
+ ashort &= ~htons(vol->v_ignattr);
memcpy( data, &ashort, sizeof( ashort ));
data += sizeof( ashort );
break;
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;
struct dirent *de;
struct stat st;
struct dir *fdir, *pdir;
- DIR *dp;
struct adouble ad;
uint16_t ashort;
int err;
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;
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;
}
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
*/
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;
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;
/*
* 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;
* 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;
}
}
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))
#include <atalk/globals.h>
#include <atalk/fce_api.h>
#include <atalk/netatalk_conf.h>
+#include <atalk/errchk.h>
#include "directory.h"
#include "dircache.h"
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;
}
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)
{
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:
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);
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)
*rbuflen += 1;
}
*rbuflen += outlen;
- *message = 0;
+// *message = 0;
return AFP_OK;
}
char *namebuf;
int vcnt;
size_t len;
+ uint32_t aint;
load_volumes(obj);
*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 );
}
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);
(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
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 *);
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
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 */
};
#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)
char *logfile;
char *mimicmodel;
char *adminauthuser;
+ char *ignored_attr;
struct afp_volume_name volfile;
};
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 */
#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
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};
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 */
#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 */
# current+1:0:0
#
-VERSION_INFO = 5:0:0
+VERSION_INFO = 6:0:0
# History: VERSION_INFO
#
# 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
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 */
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;
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);
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);
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);
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);
(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);
}
{
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;
/* 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. */
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)) {
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));
}
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
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);
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));
#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);
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;
}
guess_interface(dsi, hostname, port ? port : "548");
EC_CLEANUP:
- if (a)
- free(a);
+ if (address)
+ free(address);
+ if (port)
+ free(port);
EC_EXIT;
}
/* 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) {
by comparing the key itself in last resort.
*/
/*--------------------------------------------------------------------------*/
-unsigned dictionary_hash(char * key)
+unsigned atalkdict_hash(char * key)
{
int len ;
unsigned hash ;
dictionary, give size=0.
*/
/*--------------------------------------------------------------------------*/
-dictionary * dictionary_new(int size)
+dictionary * atalkdict_new(int size)
{
dictionary * d ;
Deallocate a dictionary object and all memory associated to it.
*/
/*--------------------------------------------------------------------------*/
-void dictionary_del(dictionary * d)
+void atalkdict_del(dictionary * d)
{
int i ;
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 ;
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
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 ;
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++) {
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 ;
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 ;
output file pointers.
*/
/*--------------------------------------------------------------------------*/
-void dictionary_dump(dictionary * d, FILE * out)
+void atalkdict_dump(dictionary * d, FILE * out)
{
int i ;
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 ;
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 ;
purposes mostly.
*/
/*--------------------------------------------------------------------------*/
-void iniparser_dump(const dictionary * d, FILE * f)
+void atalk_iniparser_dump(const dictionary * d, FILE * f)
{
int i ;
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];
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++) {
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);
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 ;
}
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;
}
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);
}
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);
}
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 ;
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 ;
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) ;
}
/*-------------------------------------------------------------------------*/
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);
}
/*-------------------------------------------------------------------------*/
@return line_status value
*/
/*--------------------------------------------------------------------------*/
-static line_status iniparser_line(
+static line_status atalk_iniparser_line(
char * input_line,
char * section,
char * key,
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;
return NULL ;
}
- dict = dictionary_new(0) ;
+ dict = atalkdict_new(0) ;
if (!dict) {
fclose(inifile);
return NULL ;
} 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) {
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",
}
}
if (errs) {
- dictionary_del(dict);
+ atalkdict_del(dict);
dict = NULL ;
}
fclose(in);
gets out of the current context.
*/
/*--------------------------------------------------------------------------*/
-void iniparser_freedict(dictionary * d)
+void atalk_iniparser_freedict(dictionary * d)
{
- dictionary_del(d);
+ atalkdict_del(d);
}
--- /dev/null
+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)
{
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;
{
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;
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);
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
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;
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;
}
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);
}
/* 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";
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;
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))
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));
}
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;
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;
}
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(®, basedir, REG_EXTENDED)) != 0) {
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;
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);
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"))
}
}
- 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 ) {
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;
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)
*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);
}
/* 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 {
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) {
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 {
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);
/* Free everything called from afp_config_parse() */
free_extmap();
- iniparser_freedict(obj->iniconfig);
+ atalk_iniparser_freedict(obj->iniconfig);
free_charset_names();
}
#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};
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
*
case ENOENT :
return AFPERR_NOOBJ;
case ENOTEMPTY :
+ case EEXIST:
return AFPERR_DIRNEMPT;
case EPERM:
case EACCES :
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;
}
#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)
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
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
;;
"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.])
;;
"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])
;;
"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])
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
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])
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
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\&.
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
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"\&.