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