+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.
+
Changes in 3.0.2
================
* NEW: afpd: Put file extension type/creator mapping back in which had
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
================
-stp3
\ No newline at end of file
+stp4dev
\ No newline at end of file
struct flag_map flag_map[] = {
flag(CONV_ESCAPEHEX),
- flag(CONV_ALLOW_COLON),
flag(CONV_UNESCAPEHEX),
flag(CONV_ESCAPEDOTS),
flag(CONV_IGNORE),
dnl Check for Tracker
AC_NETATALK_SPOTLIGHT
+dnl libatalk API checks
+AC_DEVELOPER
+
dnl FHS stuff has to be done last because it overrides other defaults
AC_NETATALK_FHS
-AC_DEVELOPER
+dnl netatalk lockfile path, must come after AC_NETATALK_FHS
+AC_NETATALK_LOCKFILE
CFLAGS="-I\$(top_srcdir)/include -I\$(top_srcdir)/sys $CFLAGS"
UAMS_PATH="${uams_path}"
-e s@:SBINDIR:@${sbindir}@ \
-e s@:ETCDIR:@${pkgconfdir}@ \
-e s@:NETATALK_VERSION:@${NETATALK_VERSION}@ \
+ -e s@:PATH_NETATALK_LOCK:@${PATH_NETATALK_LOCK}@ \
<$< >$@
GENERATED_FILES = \
netatalk_startup() {
# Check that networking is up.
if [ ${NETWORKING} = "no" ]; then
- echo "[Network isn't started]";
+ echo "[Network isn't started]";
exit 1;
fi
fi
}
-# code to cause apfd and cnid_metad to restart
-netatalk_graceful() {
+# restart code
+netatalk_restart() {
+ netatalk_stop
+ netatalk_startup
+}
+
+# reload config files
+netatalk_reload() {
if [ -x ${NETATALK_SBIN}/netatalk ]; then
- echo -n $"Restarting cnid_metad and afpd: "
- killproc netatalk -QUIT
+ echo -n $"Reloading $prog: "
+ killproc netatalk -HUP
RETVAL=$?
echo
fi
'stop')
netatalk_stop
;;
- 'restart'|'reload')
- $0 stop
- $0 start
- RETVAL=$?
+ 'restart')
+ netatalk_restart
+ ;;
+ 'reload'|'graceful')
+ netatalk_reload
;;
'status')
status netatalk
RETVAL=$?
;;
- 'graceful')
- netatalk_graceful
+ 'condrestart')
+ [ -f /var/lock/subsys/netatalk ] && netatalk_restart || :
;;
*)
- echo "Usage: $0 {start|stop|restart|reload|status|graceful}"
+ echo "Usage: $0 {start|stop|restart|reload|status|condrestart}"
exit 2
esac
Type=forking
GuessMainPID=no
ExecStart=:SBINDIR:/netatalk
+PIDFile=:PATH_NETATALK_LOCK:
+ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=1
LOG(log_maxdebug, logtype_afpd, "check_acl_access(dir: \"%s\", path: \"%s\", curdir: \"%s\", 0x%08x)",
cfrombstr(dir->d_fullpath), path, getcwdpath(), requested_rights);
+ AFP_ASSERT(vol);
+
/* This check is not used anymore, as OS X Server seems to be ignoring too */
#if 0
/* Get uid or gid from UUID */
}
}
-/* SIGQUIT handler */
-static void ipc_reconnect_handler(int sig _U_)
-{
- if (reconnect_ipc(AFPobj) != 0) {
- LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC reconnect");
- afp_dsi_close(AFPobj);
- exit(EXITERR_SYS);
- }
-
- if (ipc_child_write(AFPobj->ipc_fd, IPC_GETSESSION, AFPobj->sinfo.clientid_len, AFPobj->sinfo.clientid) != 0) {
- LOG(log_error, logtype_afpd, "ipc_reconnect_handler: failed IPC ID resend");
- afp_dsi_close(AFPobj);
- exit(EXITERR_SYS);
- }
- LOG(log_note, logtype_afpd, "ipc_reconnect_handler: IPC reconnect done");
-}
-
/* SIGURG handler (primary reconnect) */
static void afp_dsi_transfer_session(int sig _U_)
{
}
/* install SIGQUIT */
- action.sa_handler = ipc_reconnect_handler;
+ action.sa_handler = afp_dsi_die;
if ( sigaction(SIGQUIT, &action, NULL ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_over_dsi: sigaction: %s", strerror(errno) );
afp_dsi_die(EXITERR_SYS);
if ( ibuf[0] != '\0' || ibuf[1] != '\0')
return AFPERR_PARAM;
ibuf += 2;
- len = MIN(sizeof(username), strlen(obj->username));
+ len = MIN(sizeof(username) - 1, strlen(obj->username));
memcpy(username, obj->username, len);
username[ len ] = '\0';
}
cnid_t id;
struct adouble ad;
struct adouble *adp = NULL;
- bstring fullpath;
+ bstring fullpath = NULL;
AFP_ASSERT(vol);
AFP_ASSERT(dir);
sd.sd_last += len + 1;
continue;
}
- memset(&s_path, 0, sizeof(s_path));
- /* conversions on the fly */
- const char *convname;
+ memset(&s_path, 0, sizeof(s_path));
s_path.u_name = sd.sd_last;
- if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) {
- s_path.u_name = (char *)convname;
- }
-
if (of_stat(vol, &s_path) < 0 ) {
/* so the next time it won't try to stat it again
* another solution would be to invalidate the cache with
continue;
}
+ /* conversions on the fly */
+ const char *convname;
+ if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) {
+ s_path.u_name = (char *)convname;
+ }
+
/* Fixup CNID db if ad_convert resulted in a rename (then convname != NULL) */
if (convname) {
s_path.id = cnid_lookup(vol->v_cdb, &s_path.st, curdir->d_did, sd.sd_last, strlen(sd.sd_last));
return AFP_OK;
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]);
+ path, type == fce_dir ? "dir" : "file", fce_event_names[event]);
bname = basename_safe(path);
/* No listeners configured */
return AFP_OK;
- if (path == NULL)
- return AFPERR_PARAM;
/* do some initialization on the fly the first time */
if (first_event) {
}
else {
memcpy(data, ufinderi, ADEDLEN_FINDERI);
+ chk_ext = 1;
if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
uint16_t ashort;
|| (bconchar(fullpath, '/') != BSTR_OK)
|| (bcatcstr(fullpath, upath)) != BSTR_OK) {
LOG(log_error, logtype_afpd, "getmetadata: fullpath: %s", strerror(errno));
+ bdestroy(fullpath);
return AFPERR_MISC;
}
adp = &ad;
}
- if ( adp && AD_RSRC_OPEN(adp) != -1 ) { /* there's a resource fork */
+ if ( adp && AD_RSRC_OPEN(adp) ) { /* there's a resource fork */
adflags |= ADFLAGS_RF;
/* FIXME we have a pb here because we want to know if a file is open
* there's a 'priority inversion' if you can't open the ressource fork RW
return NULL;
if (bcatcstr(path, u) != BSTR_OK)
return NULL;
- if (path->slen > MAXPATHLEN)
+ if (path->slen > MAXPATHLEN) {
+ bdestroy(path);
return NULL;
+ }
LOG(log_debug, logtype_afpd, "absupath: %s", cfrombstr(path));
ofork->of_refnum, (ofork->of_flags & AFPFORK_DATA) ? "data" : "rsrc");
if (of_closefork(obj, ofork) < 0 ) {
- LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) );
+ LOG(log_error, logtype_afpd, "afp_closefork: of_closefork: %s", strerror(errno) );
return( AFPERR_PARAM );
}
"s switch to non-functioning allocator\n"
"q quit";
- if (!h)
+ if (!h) {
puts("hash_create failed");
+ return 1;
+ }
for (;;) {
if (prompt)
puts("out of memory");
free((void *) key);
free(val);
+ break;
}
if (!hash_alloc_insert(h, key, val)) {
unsigned char nologin = 0;
static AFPObj obj;
-static server_child *server_children;
+static server_child_t *server_children;
static sig_atomic_t reloadconfig = 0;
static sig_atomic_t gotsigchld = 0;
static struct polldata *polldata;
static int fdset_size; /* current allocated size */
static int fdset_used; /* number of used elements */
-static int disasociated_ipc_fd; /* disasociated sessions uses this fd for IPC */
-static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child *server_children);
+static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child_t *server_children);
static void afp_exit(int ret)
{
LISTEN_FD,
dsi);
}
-
- if (config->options.flags & OPTION_KEEPSESSIONS)
- fdset_add_fd(config->options.connections + AFP_LISTENERS + FDSET_SAFETY,
- &fdset,
- &polldata,
- &fdset_used,
- &fdset_size,
- disasociated_ipc_fd,
- DISASOCIATED_IPC_FD,
- NULL);
}
static void fd_reset_listening_sockets(const AFPObj *config)
for (dsi = config->dsi; dsi; dsi = dsi->next) {
fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, dsi->serversock);
}
-
- if (config->options.flags & OPTION_KEEPSESSIONS)
- fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, disasociated_ipc_fd);
}
/* ------------------ */
case SIGTERM:
case SIGQUIT:
- switch (sig) {
- case SIGTERM:
- LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGTERM");
- break;
- case SIGQUIT:
- if (obj.options.flags & OPTION_KEEPSESSIONS) {
- LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT, NOT disconnecting clients");
- } else {
- LOG(log_note, logtype_afpd, "AFP Server shutting down on SIGQUIT");
- sig = SIGTERM;
- }
- break;
- }
+ LOG(log_note, logtype_afpd, "AFP Server shutting down");
if (server_children)
- server_child_kill(server_children, CHILD_DSIFORK, sig);
-
+ server_child_kill(server_children, SIGTERM);
_exit(0);
break;
LOG(log_info, logtype_afpd, "disallowing logins");
if (server_children)
- server_child_kill(server_children, CHILD_DSIFORK, sig);
+ server_child_kill(server_children, sig);
break;
case SIGHUP :
#endif /* ! WAIT_ANY */
while ((pid = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) {
- for (i = 0; i < server_children->nforks; i++) {
- if ((fd = server_child_remove(server_children, i, pid)) != -1) {
- fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd);
- break;
- }
+ if ((fd = server_child_remove(server_children, pid)) != -1) {
+ fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, fd);
+ break;
}
if (WIFEXITED(status)) {
/* install child handler for asp and dsi. we do this before afp_goaway
* as afp_goaway references stuff from here.
* XXX: this should really be setup after the initial connections. */
- if (!(server_children = server_child_alloc(obj.options.connections, CHILD_NFORKS))) {
+ if (!(server_children = server_child_alloc(obj.options.connections))) {
LOG(log_error, logtype_afpd, "main: server_child alloc: %s", strerror(errno) );
afp_exit(EXITERR_SYS);
}
cnid_init();
/* watch atp, dsi sockets and ipc parent/child file descriptor. */
-
- if (obj.options.flags & OPTION_KEEPSESSIONS) {
- LOG(log_note, logtype_afpd, "Activating continous service");
- disasociated_ipc_fd = ipc_server_uds(_PATH_AFP_IPC);
- }
-
fd_set_listening_sockets(&obj);
/* set limits */
&polldata,
&fdset_used,
&fdset_size,
- child->ipc_fd,
+ child->afpch_ipc_fd,
IPC_FD,
child);
}
case IPC_FD:
child = (afp_child_t *)polldata[i].data;
- LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->pid);
-
- if (ipc_server_read(server_children, child->ipc_fd) != 0) {
- fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->ipc_fd);
- close(child->ipc_fd);
- child->ipc_fd = -1;
- if ((obj.options.flags & OPTION_KEEPSESSIONS) && child->disasociated) {
- LOG(log_note, logtype_afpd, "main: removing reattached child[%u]", child->pid);
- server_child_remove(server_children, CHILD_DSIFORK, child->pid);
- }
- }
- break;
-
- case DISASOCIATED_IPC_FD:
- LOG(log_debug, logtype_afpd, "main: IPC reconnect request");
- if ((recon_ipc_fd = accept(disasociated_ipc_fd, NULL, NULL)) == -1) {
- LOG(log_error, logtype_afpd, "main: accept: %s", strerror(errno));
- break;
- }
- if (readt(recon_ipc_fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
- LOG(log_error, logtype_afpd, "main: readt: %s", strerror(errno));
- close(recon_ipc_fd);
- break;
- }
- LOG(log_note, logtype_afpd, "main: IPC reconnect from pid [%u]", pid);
+ LOG(log_debug, logtype_afpd, "main: IPC request from child[%u]", child->afpch_pid);
- if ((child = server_child_add(server_children, CHILD_DSIFORK, pid, recon_ipc_fd)) == NULL) {
- LOG(log_error, logtype_afpd, "main: server_child_add");
- close(recon_ipc_fd);
- break;
+ if (ipc_server_read(server_children, child->afpch_ipc_fd) != 0) {
+ fdset_del_fd(&fdset, &polldata, &fdset_used, &fdset_size, child->afpch_ipc_fd);
+ close(child->afpch_ipc_fd);
+ child->afpch_ipc_fd = -1;
}
- child->disasociated = 1;
- fdset_add_fd(obj.options.connections + AFP_LISTENERS + FDSET_SAFETY,
- &fdset,
- &polldata,
- &fdset_used,
- &fdset_size,
- recon_ipc_fd,
- IPC_FD,
- child);
break;
default:
return 0;
}
-static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child *server_children)
+static afp_child_t *dsi_start(AFPObj *obj, DSI *dsi, server_child_t *server_children)
{
afp_child_t *child = NULL;
}
krb5_unparse_name(context, entry.principal, &principal);
+#ifdef HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS
krb5_free_keytab_entry_contents(context, &entry);
-
+#elif defined(HAVE_KRB5_KT_FREE_ENTRY)
+ krb5_kt_free_entry(context, &entry);
+#endif
append_directoryname(&data,
offset,
&size,
EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") );
- if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1)
+ if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1) {
+ bdestroy(infoplist);
continue;
+ }
EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") );
- if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1)
+ if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1) {
+ bdestroy(infoplist);
+ bdestroy(bandsdir);
continue;
+ }
used += (links - 1) * bandsize;
LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes",
size_t namelen;
uint16_t bitmap;
char *vol_uname;
- char *vol_mname;
+ char *vol_mname = NULL;
char *volname_tmp;
ibuf += 2;
ret = AFPERR_MISC;
goto openvol_err;
}
- free(vol_mname);
volume->v_root = dir;
curdir = dir;
if ((msg = iniparser_getstring(obj->iniconfig, volume->v_configname, "login message", NULL)) != NULL)
setmessage(msg);
+ free(vol_mname);
return( AFP_OK );
}
cnid_close(volume->v_cdb);
volume->v_cdb = NULL;
}
+ free(vol_mname);
*rbuflen = 0;
return ret;
}
static char cwdbuf[MAXPATHLEN+1];
static struct vol *vol;
-static DBD *dbd_rebuild;
static dbd_flags_t dbd_flags;
static char stamp[CNID_DEV_LEN];
static char *netatalk_dirs[] = {
switch (st.st_mode & S_IFMT) {
case S_IFREG:
case S_IFDIR:
- break;
case S_IFLNK:
- dbd_log(LOGDEBUG, "Ignoring symlink %s/%s", cwdbuf, ep->d_name);
- continue;
+ break;
default:
dbd_log(LOGSTD, "Bad filetype: %s/%s", cwdbuf, ep->d_name);
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
if (ADDIR_OK)
adfile_ok = check_adfile(ep->d_name, &st, &name);
- if (name == NULL) {
- name = ep->d_name;
- } else {
- update_cnid(did, &st, ep->d_name, name);
- }
+ if (!S_ISLNK(st.st_mode)) {
+ if (name == NULL) {
+ name = ep->d_name;
+ } else {
+ update_cnid(did, &st, ep->d_name, name);
+ }
- /* Check CNIDs */
- cnid = check_cnid(name, did, &st, adfile_ok);
+ /* Check CNIDs */
+ cnid = check_cnid(name, did, &st, adfile_ok);
- /* Now add this object to our rebuild dbd */
- if (cnid && dbd_rebuild) {
- static uint count = 0;
- rqst.cnid = rply.cnid;
- ret = dbd_rebuild_add(dbd_rebuild, &rqst, &rply);
- if (dbif_txn_close(dbd_rebuild, ret) != 0)
- return -1;
- if (rply.result != CNID_DBD_RES_OK) {
- dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db",
- cnid, cwdbuf, name);
- return -1;
- }
- count++;
- if (count == 10000) {
- if (dbif_txn_checkpoint(dbd_rebuild, 0, 0, 0) < 0) {
- dbd_log(LOGSTD, "Error checkpointing!");
- return -1;
- }
- count = 0;
- }
+ /* Check EA files */
+ if (vol->v_vfs_ea == AFPVOL_EA_AD)
+ check_eafiles(name);
}
- /* Check EA files */
- if (vol->v_vfs_ea == AFPVOL_EA_AD)
- check_eafiles(name);
-
/**************************************************************************
Recursion
**************************************************************************/
time(&t);
if (!up) {
/* find an empty slot (i < maxvol) or the first free slot (i == maxvol)*/
- for (i = 0; i <= maxvol; i++) {
- if (srv[i].v_path == NULL && i < MAXVOLS) {
+ for (i = 0; i <= maxvol && i < MAXVOLS; i++) {
+ if (srv[i].v_path == NULL) {
up = &srv[i];
if ((up->v_path = strdup(volpath)) == NULL)
return -1;
LOG(log_warning, logtype_cnid, "Recreated CNID BerkeleyDB databases of volume \"%s\"", vol->v_localname);
EC_CLEANUP:
- if (cwd != -1)
+ if (cwd != -1) {
fchdir(cwd);
+ close(cwd);
+ }
EC_EXIT;
}
/* this get called when error conditions are met that require us to exit gracefully */
static void netatalk_exit(int ret)
{
- server_unlock(_PATH_NETATALK_LOCK);
+ server_unlock(PATH_NETATALK_LOCK);
exit(ret);
}
}
}
- if (check_lockfile("netatalk", _PATH_NETATALK_LOCK) != 0)
+ if (check_lockfile("netatalk", PATH_NETATALK_LOCK) != 0)
exit(EXITERR_SYS);
if (!debug && daemonize(0, 0) != 0)
exit(EXITERR_SYS);
- if (create_lockfile("netatalk", _PATH_NETATALK_LOCK) != 0)
+ if (create_lockfile("netatalk", PATH_NETATALK_LOCK) != 0)
exit(EXITERR_SYS);
sigfillset(&blocksigs);
#define DSI_DEFQUANT 2 /* default attention quantum size */
#define DSI_SERVQUANT_MAX 0xffffffff /* server quantum */
#define DSI_SERVQUANT_MIN 32000 /* minimum server quantum */
-#define DSI_SERVQUANT_DEF 0x0004A2E0L /* default server quantum */
+#define DSI_SERVQUANT_DEF 0x100000L /* default server quantum (1 MB) */
/* default port number */
#define DSI_AFPOVERTCP_PORT 548
extern void dsi_free(DSI *dsi);
/* in dsi_getsess.c */
-extern int dsi_getsession (DSI *, server_child *, const int, afp_child_t **);
+extern int dsi_getsession (DSI *, server_child_t *, const int, afp_child_t **);
extern void dsi_kill (int);
#define OPTION_UUID (1 << 7)
#define OPTION_ACL2MACCESS (1 << 8)
#define OPTION_NOZEROCONF (1 << 9)
-#define OPTION_KEEPSESSIONS (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
#define OPTION_SHARE_RESERV (1 << 11) /* whether to use Solaris fcntl F_SHARE locks */
#define OPTION_SPOTLIGHT (1 << 12) /* whether to enable Spotlight support */
#define PASSWD_NONE 0
#define ATALKPATHCAT(a,b) a/**/b
#endif
-
-/* lock file path. this should be re-organized a bit. */
-#if ! defined (_PATH_LOCKDIR)
-# if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
-# define _PATH_LOCKDIR "/var/run/"
-# elif defined (BSD4_4)
-# ifdef MACOSX_SERVER
-# define _PATH_LOCKDIR "/var/run/"
-# else
-# define _PATH_LOCKDIR "/var/spool/lock/"
-# endif
-# elif defined (linux)
-# define _PATH_LOCKDIR "/var/lock/"
-# else
-# define _PATH_LOCKDIR "/var/spool/locks/"
-# endif
-#endif
-
-
-/*
- * netatalk paths
- */
-#define _PATH_AFPTKT "/tmp/AFPtktXXXXXX"
-#define _PATH_AFP_IPC ATALKPATHCAT(_PATH_LOCKDIR,"afpd_ipc")
-#if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
-# define _PATH_NETATALK_LOCK ATALKPATHCAT(_PATH_LOCKDIR,"netatalk.pid")
-#else
-# define _PATH_NETATALK_LOCK ATALKPATHCAT(_PATH_LOCKDIR,"netatalk")
-#endif
-
#endif /* atalk/paths.h */
/* useful stuff for child processes. most of this is hidden in
* server_child.c to ease changes in implementation */
-#define CHILD_NFORKS 2
-#define CHILD_ASPFORK 0
-#define CHILD_PAPFORK 0
-#define CHILD_DSIFORK 1
-
-typedef struct server_child {
- void *fork;
- int count, nsessions, nforks;
-} server_child;
-
-typedef struct server_child_data {
- pid_t pid; /* afpd worker process pid (from the worker afpd process )*/
- uid_t uid; /* user id of connected client (from the worker afpd process) */
- int valid; /* 1 if we have a clientid */
- int killed; /* 1 if we already tried to kill the client */
- int disasociated; /* 1 if this is not a child, but a child from a previous afpd master */
- uint32_t time; /* client boot time (from the mac client) */
- uint32_t idlen; /* clientid len (from the Mac client) */
- char *clientid; /* clientid (from the Mac client) */
- int ipc_fd; /* socket for IPC bw afpd parent and childs */
- struct server_child_data **prevp, *next;
+#define CHILD_HASHSIZE 32
+
+/* One AFP session child process */
+typedef struct afp_child {
+ pid_t afpch_pid; /* afpd worker process pid (from the worker afpd process )*/
+ uid_t afpch_uid; /* user id of connected client (from the worker afpd process) */
+ int afpch_valid; /* 1 if we have a clientid */
+ int afpch_killed; /* 1 if we already tried to kill the client */
+ uint32_t afpch_time; /* client boot time (from the mac client) */
+ uint32_t afpch_idlen; /* clientid len (from the Mac client) */
+ char *afpch_clientid; /* clientid (from the Mac client) */
+ int afpch_ipc_fd; /* socket for IPC bw afpd parent and childs */
+ struct afp_child **afpch_prevp;
+ struct afp_child *afpch_next;
} afp_child_t;
+/* Info and table with all AFP session child processes */
+typedef struct {
+ pthread_mutex_t servch_lock; /* Lock */
+ int servch_count; /* Current count of active AFP sessions */
+ int servch_nsessions; /* Number of allowed AFP sessions */
+ afp_child_t *servch_table[CHILD_HASHSIZE]; /* Hashtable with data of AFP sesssions */
+ void (*servch_cleanup)(const pid_t); /* Cleanup handler */
+} server_child_t;
+
/* server_child.c */
-extern server_child *server_child_alloc (const int, const int);
-extern afp_child_t *server_child_add (server_child *, int, pid_t, int ipc_fd);
-extern int server_child_remove (server_child *, const int, const pid_t);
-extern void server_child_free (server_child *);
-
-extern void server_child_kill (server_child *, const int, const int);
-extern void server_child_kill_one_by_id (server_child *children, const int forkid, const pid_t pid, const uid_t,
- const uint32_t len, char *id, uint32_t boottime);
-extern int server_child_transfer_session(server_child *children, int forkid, pid_t, uid_t, int, uint16_t);
-extern void server_child_setup (server_child *, const int, void (*)(const pid_t));
-extern void server_child_handler (server_child *);
-extern void server_reset_signal (void);
+extern server_child_t *server_child_alloc(int);
+extern afp_child_t *server_child_add(server_child_t *, pid_t, int ipc_fd);
+extern int server_child_remove(server_child_t *, pid_t);
+extern void server_child_free(server_child_t *);
+
+extern void server_child_kill(server_child_t *, int);
+extern void server_child_kill_one_by_id(server_child_t *children, pid_t pid, uid_t,
+ uint32_t len, char *id, uint32_t boottime);
+extern int server_child_transfer_session(server_child_t *children, pid_t, uid_t, int, uint16_t);
+extern void server_child_handler(server_child_t *);
+extern void server_reset_signal(void);
#endif
#define IPC_DISCOLDSESSION 0
#define IPC_GETSESSION 1
-extern int ipc_server_uds(const char *name);
-extern int ipc_client_uds(const char *name);
-extern int reconnect_ipc(AFPObj *);
-extern int ipc_server_read(server_child *children, int fd);
+extern int ipc_server_read(server_child_t *children, int fd);
extern int ipc_child_write(int fd, uint16_t command, int len, void *token);
#endif /* IPC_GETSESSION_LOGIN */
#define CONV_DECOMPOSE (1<<7) /* precompose */
#define CONV_FORCE (1<<8) /* force convertion */
#define CONV__EILSEQ (1<<9) /* ignore EILSEQ, replace with IGNORE_CHAR (try USC2) */
-#define CONV_ALLOW_COLON (1<<10) /* Allow ':' in name. Needed for Extended Attributes */
-#define CONV_ALLOW_SLASH (1<<11) /* Allow '/' in name. Needed for volume name */
/* conversion return flags */
#define CONV_REQMANGLE (1<<14) /* mangling of returned name is required */
extern int compare_ip(const struct sockaddr *sa1, const struct sockaddr *sa2);
/* Structures and functions dealing with dynamic pollfd arrays */
-enum fdtype {IPC_FD, LISTEN_FD, DISASOCIATED_IPC_FD};
+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 *
.libs
dummy.o
libatalk.abi.tmp
+*dev.abi
# current+1:0:0
#
-VERSION_INFO = 2:0:0
+VERSION_INFO = 3:0:0
# History: VERSION_INFO
#
# 3.0.0-beta2 1:0:0
# 3.0 1:0:0
# 3.0.1 2:0:0
-# 3.0.2 3:0:1
+# 3.0.2 3:0:0
SUBDIRS = acl adouble bstring compat cnid dsi iniparser talloc tdb util unicode vfs
EXTRA_DIST = \
libatalk-3.0beta1.abi \
libatalk-3.0beta2.abi \
+ libatalk-3.0.abi \
libatalk-3.0.1.abi \
- libatalk-3.0.abi
+ libatalk-3.0.2.abi
/* Call chmod() first because there might be some special bits to be set which
* aren't related to access control.
*/
+#ifdef BSD4_4
+ /*
+ * On FreeBSD chmod_acl() ends up in here too, but on
+ * FreeBSD sine ~9.1 with ZFS doesn't allow setting the g+s bit.
+ * Fixes PR #491.
+ */
+ mode &= 0777;
+#endif
ret = chmod(name, mode);
if (ret)
become_root();
- EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
- EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
+ if (ad_conv_v22ea_hf(path, sp, vol) != 0)
+ goto delete;
+ if (ad_conv_v22ea_rf(path, sp, vol) != 0)
+ goto delete;
+delete:
EC_NULL( adpath = ad_path(path, adflags) );
LOG(log_debug, logtype_ad,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
path, fullpathname(adpath));
adosx.ad_version = ntohl(adosx.ad_version);
if ((adosx.ad_magic != AD_MAGIC) || (adosx.ad_version != AD_VERSION2)) {
- LOG(log_warning, logtype_ad, "ad_valid_header_osx: not an adouble:osx file");
+ LOG(log_warning, logtype_ad, "ad_valid_header_osx(\"%s\"): not an adouble:osx file", fullpathname(path));
EC_FAIL;
}
}
if (header_len < AD_HEADER_LEN) {
- LOG(log_error, logtype_ad, "ad_header_read_ea: bogus AppleDouble header.");
+ LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): bogus AppleDouble header.", fullpathname(path));
errno = EIO;
return -1;
}
ad->ad_version = ntohl( ad->ad_version );
if ((ad->ad_magic != AD_MAGIC) || (ad->ad_version != AD_VERSION2)) {
- LOG(log_error, logtype_ad, "ad_header_read_ea: wrong magic or version");
+ LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): wrong magic or version", fullpathname(path));
errno = EIO;
return -1;
}
if (len + AD_HEADER_LEN > sizeof(ad->ad_data))
len = sizeof(ad->ad_data) - AD_HEADER_LEN;
if (len > header_len - AD_HEADER_LEN) {
- LOG(log_error, logtype_ad, "ad_header_read_ea: can't read entry info.");
+ LOG(log_error, logtype_ad, "ad_header_read_ea(\"%s\"): can't read entry info.", fullpathname(path));
errno = EIO;
return -1;
}
EC_INIT;
int cwdfd = -1;
va_list args;
- mode_t mode;
+ mode_t mode = 0;
if (dirfd != -1) {
if ((cwdfd = open(".", O_RDONLY) == -1) || (fchdir(dirfd) != 0))
* @param childp (w) after fork: parent return pointer to child, child returns NULL
* @returns 0 on sucess, any other value denotes failure
*/
-int dsi_getsession(DSI *dsi, server_child *serv_children, int tickleval, afp_child_t **childp)
+int dsi_getsession(DSI *dsi, server_child_t *serv_children, int tickleval, afp_child_t **childp)
{
pid_t pid;
int ipc_fds[2];
/* using SIGKILL is hokey, but the child might not have
* re-established its signal handler for SIGTERM yet. */
close(ipc_fds[1]);
- if ((child = server_child_add(serv_children, CHILD_DSIFORK, pid, ipc_fds[0])) == NULL) {
+ if ((child = server_child_add(serv_children, pid, ipc_fds[0])) == NULL) {
LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno));
close(ipc_fds[0]);
dsi->header.dsi_flags = DSIFL_REPLY;
/* child: check number of open connections. this is one off the
* actual count. */
- if ((serv_children->count >= serv_children->nsessions) &&
+ if ((serv_children->servch_count >= serv_children->servch_nsessions) &&
(dsi->header.dsi_command == DSIFUNC_OPEN)) {
LOG(log_info, logtype_dsi, "dsi_getsess: too many connections");
dsi->header.dsi_flags = DSIFL_REPLY;
--- /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_old: void (struct adouble *, int, int)
+ad_lock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_metadata: int (const char *, int, struct adouble *)
+ad_metadataat: int (int, const char *, int, struct adouble *)
+ad_mkdir: int (const char *, mode_t)
+ad_mode: int (const char *, mode_t)
+ad_open: int (struct adouble *, const char *, int, ...)
+ad_openat: int (struct adouble *, int, const char *, int, ...)
+ad_openforks: uint16_t (struct adouble *, uint16_t)
+ad_path: const char *(const char *, int)
+ad_path_ea: const char *(const char *, int)
+ad_path_osx: const char *(const char *, int)
+ad_read: ssize_t (struct adouble *, const uint32_t, off_t, char *, const size_t)
+ad_readfile_init: int (const struct adouble *, const int, off_t *, const int)
+ad_rebuild_adouble_header_ea: int (struct adouble *)
+ad_rebuild_adouble_header_v2: int (struct adouble *)
+ad_refresh: int (const char *, struct adouble *)
+ad_rtruncate: int (struct adouble *, const off_t)
+ad_setattr: int (const struct adouble *, const uint16_t)
+ad_setdate: int (struct adouble *, unsigned int, uint32_t)
+ad_setfuid: int (const uid_t)
+ad_setid: int (struct adouble *, const dev_t, const ino_t, const uint32_t, const cnid_t, const void *)
+ad_setname: int (struct adouble *, const char *)
+ad_size: off_t (const struct adouble *, const uint32_t)
+ad_stat: int (const char *, struct stat *)
+ad_testlock: int (struct adouble *, int, const off_t)
+ad_tmplock: int (struct adouble *, uint32_t, int, off_t, off_t, int)
+ad_unlock: void (struct adouble *, const int, int)
+ad_valid_header_osx: int (const char *)
+ad_write: ssize_t (struct adouble *, uint32_t, off_t, int, const char *, size_t)
+afp_config_free: void (AFPObj *)
+afp_config_parse: int (AFPObj *, char *)
+allow_severity: 5
+apply_ip_mask: void (struct sockaddr *, int)
+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_register_charset: int (struct charset_functions *)
+balloc: int (bstring, int)
+ballocmin: int (bstring, int)
+basename_safe: const char *(const char *)
+bassign: int (bstring, const_bstring)
+bassignblk: int (bstring, const void *, int)
+bassigncstr: int (bstring, const char *)
+bassignformat: int (bstring, const char *, ...)
+bassigngets: int (bstring, bNgetc, void *, char)
+bassignmidstr: int (bstring, const_bstring, int, int)
+bcatblk: int (bstring, const void *, int)
+bcatcstr: int (bstring, const char *)
+bconcat: int (bstring, const_bstring)
+bconchar: int (bstring, char)
+bcstrfree: int (char *)
+bdelete: int (bstring, int, int)
+bdestroy: int (bstring)
+become_root: void (void)
+bfindreplace: int (bstring, const_bstring, const_bstring, int)
+bfindreplacecaseless: int (bstring, const_bstring, const_bstring, int)
+bformat: bstring (const char *, ...)
+bformata: int (bstring, const char *, ...)
+bfromcstr: bstring (const char *)
+bfromcstralloc: bstring (int, const char *)
+bgetsa: int (bstring, bNgetc, void *, char)
+bgetstream: bstring (bNgetc, void *, char)
+binchr: int (const_bstring, int, const_bstring)
+binchrr: int (const_bstring, int, const_bstring)
+binsert: int (bstring, int, const_bstring, unsigned char)
+binsertch: int (bstring, int, int, unsigned char)
+binstr: int (const_bstring, int, const_bstring)
+binstrcaseless: int (const_bstring, int, const_bstring)
+binstrr: int (const_bstring, int, const_bstring)
+binstrrcaseless: int (const_bstring, int, const_bstring)
+biseq: int (const_bstring, const_bstring)
+biseqcaseless: int (const_bstring, const_bstring)
+biseqcstr: int (const_bstring, const char *)
+biseqcstrcaseless: int (const_bstring, const char *)
+bisstemeqblk: int (const_bstring, const void *, int)
+bisstemeqcaselessblk: int (const_bstring, const void *, int)
+bjoin: bstring (const struct bstrList *, const_bstring)
+bjoinInv: bstring (const struct bstrList *, const_bstring)
+blk2bstr: bstring (const void *, int)
+bltrimws: int (bstring)
+bmidstr: bstring (const_bstring, int, int)
+bninchr: int (const_bstring, int, const_bstring)
+bninchrr: int (const_bstring, int, const_bstring)
+bpattern: int (bstring, int)
+bread: bstring (bNread, void *)
+breada: int (bstring, bNread, void *)
+brefcstr: bstring (char *)
+breplace: int (bstring, int, int, const_bstring, unsigned char)
+brtrimws: int (bstring)
+bsbufflength: int (struct bStream *, int)
+bsclose: void *(struct bStream *)
+bseof: int (const struct bStream *)
+bsetstr: int (bstring, int, const_bstring, unsigned char)
+bsopen: struct bStream *(bNread, void *)
+bspeek: int (bstring, const struct bStream *)
+bsplit: struct bstrList *(const_bstring, unsigned char)
+bsplitcb: int (const_bstring, unsigned char, int, int (*)(void *, int, int), void *)
+bsplits: struct bstrList *(const_bstring, const_bstring)
+bsplitscb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsplitstr: struct bstrList *(const_bstring, const_bstring)
+bsplitstrcb: int (const_bstring, const_bstring, int, int (*)(void *, int, int), void *)
+bsread: int (bstring, struct bStream *, int)
+bsreada: int (bstring, struct bStream *, int)
+bsreadln: int (bstring, struct bStream *, char)
+bsreadlna: int (bstring, struct bStream *, char)
+bsreadlns: int (bstring, struct bStream *, const_bstring)
+bsreadlnsa: int (bstring, struct bStream *, const_bstring)
+bssplitscb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bssplitstrcb: int (struct bStream *, const_bstring, int (*)(void *, int, const_bstring), void *)
+bstr2cstr: char *(const_bstring, char)
+bstrchrp: int (const_bstring, int, int)
+bstrcmp: int (const_bstring, const_bstring)
+bstrcpy: bstring (const_bstring)
+bstricmp: int (const_bstring, const_bstring)
+bstrListAlloc: int (struct bstrList *, int)
+bstrListAllocMin: int (struct bstrList *, int)
+bstrListCreate: struct bstrList *(void)
+bstrListCreateMin: struct bstrList *(int)
+bstrListDestroy: int (struct bstrList *)
+bstrListPop: bstring (struct bstrList *)
+bstrListPush: int (struct bstrList *, bstring)
+bstrncmp: int (const_bstring, const_bstring, int)
+bstrnicmp: int (const_bstring, const_bstring, int)
+bstrrchrp: int (const_bstring, int, int)
+bsunread: int (struct bStream *, const_bstring)
+btolower: int (bstring)
+btoupper: int (bstring)
+btrimws: int (bstring)
+btrunc: int (bstring, int)
+bunrefcstr: int (bstring)
+bvcformata: int (bstring, int, const char *, struct __va_list_tag *)
+charset_decompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_mac_centraleurope: {name = "MAC_CENTRALEUROPE", kTextEncoding = 29, pull = <mac_centraleurope_pull>, push = <mac_centraleurope_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_chinese_simp: {name = "MAC_CHINESE_SIMP", kTextEncoding = 25, pull = <mac_chinese_simp_pull>, push = <mac_chinese_simp_push>, flags = 85, iname = "EUC-CN", prev = 0x0, next = 0x0}
+charset_mac_chinese_trad: {name = "MAC_CHINESE_TRAD", kTextEncoding = 2, pull = <mac_chinese_trad_pull>, push = <mac_chinese_trad_push>, flags = 85, iname = "BIG-5", prev = 0x0, next = 0x0}
+charset_mac_cyrillic: {name = "MAC_CYRILLIC", kTextEncoding = 7, pull = <mac_cyrillic_pull>, push = <mac_cyrillic_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_greek: {name = "MAC_GREEK", kTextEncoding = 6, pull = <mac_greek_pull>, push = <mac_greek_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_hebrew: {name = "MAC_HEBREW", kTextEncoding = 5, pull = <mac_hebrew_pull>, push = <mac_hebrew_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_japanese: {name = "MAC_JAPANESE", kTextEncoding = 1, pull = <mac_japanese_pull>, push = <mac_japanese_push>, flags = 85, iname = "SHIFT_JIS", prev = 0x0, next = 0x0}
+charset_mac_korean: {name = "MAC_KOREAN", kTextEncoding = 3, pull = <mac_korean_pull>, push = <mac_korean_push>, flags = 85, iname = "EUC-KR", prev = 0x0, next = 0x0}
+charset_mac_roman: {name = "MAC_ROMAN", kTextEncoding = 0, pull = <mac_roman_pull>, push = <mac_roman_push>, flags = 21, iname = 0x0, prev = 0x0, next = 0x0}
+charset_mac_turkish: {name = "MAC_TURKISH", kTextEncoding = 35, pull = <mac_turkish_pull>, push = <mac_turkish_push>, flags = 17, iname = 0x0, prev = 0x0, next = 0x0}
+charset_precompose: size_t (charset_t, char *, size_t, char *, size_t)
+charset_strlower: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_strupper: size_t (charset_t, const char *, size_t, char *, size_t)
+charset_to_ucs2_allocate: size_t (charset_t, uint16_t **, const char *)
+charset_to_utf8_allocate: size_t (charset_t, char **, const char *)
+charset_utf8: {name = "UTF8", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 22, iname = 0x0, prev = 0x0, next = 0x0}
+charset_utf8_mac: {name = "UTF8-MAC", kTextEncoding = 134217987, pull = <utf8_pull>, push = <utf8_push>, flags = 27, iname = 0x0, prev = 0x0, next = 0x0}
+check_lockfile: int (const char *, const char *)
+cjk_char_pull: size_t (uint16_t, uint16_t *, const uint32_t *)
+cjk_char_push: size_t (uint16_t, uint8_t *)
+cjk_compose: uint16_t (uint16_t, uint16_t, const uint32_t *, size_t)
+cjk_compose_seq: uint16_t (const uint16_t *, size_t *, const uint32_t *, size_t)
+cjk_generic_pull: size_t (size_t (*)(uint16_t *, const uint8_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_generic_push: size_t (size_t (*)(uint8_t *, const uint16_t *, size_t *), void *, char **, size_t *, char **, size_t *)
+cjk_lookup: uint16_t (uint16_t, const cjk_index_t *, const uint16_t *)
+cnid_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, const char *, const size_t, cnid_t)
+cnid_close: void (struct _cnid_db *)
+cnid_dbd_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_close: void (struct _cnid_db *)
+cnid_dbd_delete: int (struct _cnid_db *, const cnid_t)
+cnid_dbd_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_dbd_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_dbd_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_dbd_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_module: {name = "dbd", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_dbd_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_dbd_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_dbd_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_dbd_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_dbd_wipe: int (struct _cnid_db *)
+cnid_delete: int (struct _cnid_db *, cnid_t)
+cnid_find: int (struct _cnid_db *, const char *, size_t, void *, size_t)
+cnid_get: cnid_t (struct _cnid_db *, const cnid_t, char *, const size_t)
+cnid_getstamp: int (struct _cnid_db *, void *, const size_t)
+cnid_init: void (void)
+cnid_last_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_last_close: void (struct _cnid_db *)
+cnid_last_delete: int (struct _cnid_db *, const cnid_t)
+cnid_last_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_last_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_last_module: {name = "last", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 0}
+cnid_last_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_last_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_last_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_lookup: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t)
+cnid_open: struct _cnid_db *(const char *, mode_t, char *, int, const char *, const char *)
+cnid_rebuild_add: cnid_t (struct _cnid_db *, const struct stat *, const cnid_t, char *, const size_t, cnid_t)
+cnid_register: void (struct _cnid_module *)
+cnid_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_add: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t, cnid_t)
+cnid_tdb_close: void (struct _cnid_db *)
+cnid_tdb_delete: int (struct _cnid_db *, const cnid_t)
+cnid_tdb_get: cnid_t (struct _cnid_db *, cnid_t, const char *, size_t)
+cnid_tdb_lookup: cnid_t (struct _cnid_db *, const struct stat *, cnid_t, const char *, size_t)
+cnid_tdb_module: {name = "tdb", db_list = {next = 0x0, prev = 0x0}, cnid_open = 0, flags = 12}
+cnid_tdb_open: struct _cnid_db *(struct cnid_open_args *)
+cnid_tdb_resolve: char *(struct _cnid_db *, cnid_t *, void *, size_t)
+cnid_tdb_update: int (struct _cnid_db *, cnid_t, const struct stat *, cnid_t, const char *, size_t)
+cnid_update: int (struct _cnid_db *, const cnid_t, const struct stat *, const cnid_t, char *, const size_t)
+cnid_wipe: int (struct _cnid_db *)
+compare_ip: int (const struct sockaddr *, const struct sockaddr *)
+convert_charset: size_t (charset_t, charset_t, charset_t, const char *, size_t, char *, size_t, uint16_t *)
+convert_string: size_t (charset_t, charset_t, const void *, size_t, void *, size_t)
+convert_string_allocate: size_t (charset_t, charset_t, const void *, size_t, char **)
+copy_ea: int (const char *, int, const char *, const char *, mode_t)
+copy_file: int (int, const char *, const char *, mode_t)
+copy_file_fd: int (int, int)
+copy_fork: int (int, struct adouble *, struct adouble *)
+create_lockfile: int (const char *, const char *)
+daemonize: int (int, int)
+decompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+deny_severity: 3
+dequeue: void *(q_t *)
+_diacasemap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 231, 203, 229, 128, 204, 129, 130, 131, 233, 230, 232, 234, 237, 235, 236, 132, 238, 241, 239, 133, 205, 242, 244, 243, 134, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 198, 183, 184, 184, 186, 187, 188, 189, 174, 175, 192, 193, 194, 195, 196, 197, 198, 199...}
+_dialowermap: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 138, 140, 141, 142, 150, 154, 159, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 132, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 190, 191, 176, 177, 178, 179, 180, 181, 198, 183, 185, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199...}
+dictionary_del: void (dictionary *)
+dictionary_dump: void (dictionary *, FILE *)
+dictionary_get: const char *(const dictionary *, const char *, const char *, const char *)
+dictionary_hash: unsigned int (char *)
+dictionary_new: dictionary *(int)
+dictionary_set: int (dictionary *, char *, char *, char *)
+dictionary_unset: void (dictionary *, char *, char *)
+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 *, 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 *)
+iniparser_dump: void (const dictionary *, FILE *)
+iniparser_dump_ini: void (const dictionary *, FILE *)
+iniparser_find_entry: int (const dictionary *, const char *)
+iniparser_freedict: void (dictionary *)
+iniparser_getboolean: int (const dictionary *, const char *, const char *, int)
+iniparser_getdouble: double (const dictionary *, const char *, const char *, double)
+iniparser_getint: int (const dictionary *, const char *, const char *, int)
+iniparser_getnsec: int (const dictionary *)
+iniparser_getsecname: const char *(const dictionary *, int)
+iniparser_getstrdup: char *(const dictionary *, const char *, const char *, const char *)
+iniparser_getstring: const char *(const dictionary *, const char *, const char *, const char *)
+iniparser_load: dictionary *(const char *)
+iniparser_set: int (dictionary *, char *, char *, char *)
+iniparser_unset: void (dictionary *, char *, char *)
+_init: <text variable, no debug info>
+init_iconv: void (void)
+initline: void (int, char *)
+initvol_vfs: void (struct vol *)
+ipc_child_write: int (int, uint16_t, int, void *)
+ipc_client_uds: int (const char *)
+ipc_server_read: int (server_child *, int)
+ipc_server_uds: int (const char *)
+islower_sp: int (uint32_t)
+islower_w: int (uint16_t)
+isupper_sp: int (uint32_t)
+isupper_w: int (uint16_t)
+ldap_auth_dn: 0x0
+ldap_auth_method: 0
+ldap_auth_pw: 0x0
+ldap_config_valid: 0
+ldap_getnamefromuuid: int (const char *, char **, uuidtype_t *)
+ldap_getuuidfromname: int (const char *, uuidtype_t, char **)
+ldap_group_attr: 0x0
+ldap_groupbase: 0x0
+ldap_groupscope: 0
+ldap_name_attr: 0x0
+ldap_prefs: {{pref = 0x0, name = "ldap server", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth method", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap auth dn", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap auth pw", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap userbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap userscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupbase", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap groupscope", strorint = 1, intfromarray = 1, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uuid string", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap name attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap group attr", strorint = 0, intfromarray = 0, valid = -1, valid_save = -1}, {pref = 0x0, name = "ldap uid attr", strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}, {pref = 0x0, name = "ldap uuid encoding", strorint = 1, intfromarray = 1, valid = 0, valid_save = 0}, {pref = 0x0, name = 0x0, strorint = 0, intfromarray = 0, valid = 0, valid_save = 0}}
+ldap_server: 0x0
+ldap_uid_attr: 0x0
+ldap_userbase: 0x0
+ldap_userscope: 0
+ldap_uuid_attr: 0x0
+ldap_uuid_encoding: 0
+ldap_uuid_string: 0x0
+list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+load_charset: int (struct vol *)
+load_volumes: int (AFPObj *)
+localuuid_from_id: void (unsigned char *, uuidtype_t, unsigned int)
+lock_reg: int (int, int, int, off_t, int, off_t)
+log_config: {inited = false, syslog_opened = false, console = false, processname = '\0' <repeats 15 times>, syslog_facility = 0, syslog_display_options = 0}
+make_log_entry: void (enum loglevels, enum logtypes, const char *, int, char *, ...)
+make_tdb_data: unsigned char *(uint32_t, const struct stat *, const cnid_t, const char *, const size_t)
+mb_generic_pull: size_t (int (*)(uint16_t *, const unsigned char *), void *, char **, size_t *, char **, size_t *)
+mb_generic_push: size_t (int (*)(unsigned char *, uint16_t), void *, char **, size_t *, char **, size_t *)
+netatalk_panic: void (const char *)
+netatalk_rmdir: int (int, const char *)
+netatalk_rmdir_all_errors: int (int, const char *)
+netatalk_unlink: int (const char *)
+netatalk_unlinkat: int (int, const char *)
+nftw: int (const char *, nftw_func_t, dir_notification_func_t, int, int)
+ochdir: int (const char *, int)
+ochmod: int (char *, mode_t, const struct stat *, int)
+ochown: int (const char *, uid_t, gid_t, int)
+opendirat: DIR *(int, const char *)
+openflags2logstr: const char *(int)
+ostat: int (const char *, struct stat *, int)
+ostatat: int (int, const char *, struct stat *, int)
+parseline: int (int, char *)
+posix_chmod: int (const char *, mode_t)
+posix_fchmod: int (int, mode_t)
+precompose_w: size_t (uint16_t *, size_t, uint16_t *, size_t *)
+prefs_array: {{pref = "ldap auth method", valuestring = "none", value = 0}, {pref = "ldap auth method", valuestring = "simple", value = 128}, {pref = "ldap auth method", valuestring = "sasl", value = 163}, {pref = "ldap userscope", valuestring = "base", value = 0}, {pref = "ldap userscope", valuestring = "one", value = 1}, {pref = "ldap userscope", valuestring = "sub", value = 2}, {pref = "ldap groupscope", valuestring = "base", value = 0}, {pref = "ldap groupscope", valuestring = "one", value = 1}, {pref = "ldap groupscope", valuestring = "sub", value = 2}, {pref = "ldap uuid encoding", valuestring = "ms-guid", value = 1}, {pref = "ldap uuid encoding", valuestring = "string", value = 0}, {pref = 0x0, valuestring = 0x0, value = 0}}
+prequeue: qnode_t *(q_t *, void *)
+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 *)
+reconnect_ipc: int (AFPObj *)
+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 *, int, pid_t, int)
+server_child_alloc: server_child *(const int, const int)
+server_child_free: void (server_child *)
+server_child_kill: void (server_child *, int, int)
+server_child_kill_one_by_id: void (server_child *, int, pid_t, uid_t, uint32_t, char *, uint32_t)
+server_child_remove: int (server_child *, const int, pid_t)
+server_child_setup: void (server_child *, const int, void (*)(const pid_t))
+server_child_transfer_session: int (server_child *, int, 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 *)
+setnonblock: int (int, int)
+set_processname: void (const char *)
+setuplog: void (const char *, const char *)
+statat: int (int, const char *, struct stat *)
+strcasechr_sp: uint16_t *(const uint16_t *, uint32_t)
+strcasechr_w: uint16_t *(const uint16_t *, uint16_t)
+strcasecmp_w: int (const uint16_t *, const uint16_t *)
+strcasestr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strcat_w: uint16_t *(uint16_t *, const uint16_t *)
+strchr_w: uint16_t *(const uint16_t *, uint16_t)
+strcmp_w: int (const uint16_t *, const uint16_t *)
+strdiacasecmp: int (const char *, const char *)
+strdup_w: uint16_t *(const uint16_t *)
+stripped_slashes_basename: char *(char *)
+strlcat: size_t (char *, const char *, size_t)
+strlcpy: size_t (char *, const char *, size_t)
+strlen_w: size_t (const uint16_t *)
+strlower_w: int (uint16_t *)
+strncasecmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncat_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strncmp_w: int (const uint16_t *, const uint16_t *, size_t)
+strncpy_w: uint16_t *(uint16_t *, const uint16_t *, const size_t)
+strndiacasecmp: int (const char *, const char *, size_t)
+strndup_w: uint16_t *(const uint16_t *, size_t)
+strnlen_w: size_t (const uint16_t *, size_t)
+strstr_w: uint16_t *(const uint16_t *, const uint16_t *)
+strtok_quote: char *(char *, const char *)
+strupper_w: int (uint16_t *)
+sys_ea_copyfile: int (const struct vol *, int, const char *, const char *)
+sys_fgetxattr: ssize_t (int, const char *, void *, size_t)
+sys_fsetxattr: int (int, const char *, const void *, size_t, int)
+sys_ftruncate: int (int, off_t)
+sys_get_eacontent: int (const struct vol *, char *, size_t *, const char *, int, const char *, int)
+sys_get_easize: int (const struct vol *, char *, size_t *, const char *, int, const char *)
+sys_getxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_getxattrfd: int (int, const char *, int, ...)
+sys_lgetxattr: ssize_t (const char *, const char *, void *, size_t)
+sys_list_eas: int (const struct vol *, char *, size_t *, const char *, int)
+sys_listxattr: ssize_t (const char *, char *, size_t)
+sys_llistxattr: ssize_t (const char *, char *, size_t)
+sys_lremovexattr: int (const char *, const char *)
+sys_lsetxattr: int (const char *, const char *, const void *, size_t, int)
+sys_remove_ea: int (const struct vol *, const char *, const char *, int)
+sys_removexattr: int (const char *, const char *)
+sys_sendfile: ssize_t (int, int, off_t *, size_t)
+sys_set_ea: int (const struct vol *, const char *, const char *, const char *, size_t, int)
+sys_setxattr: int (const char *, const char *, const void *, size_t, int)
+tdb_add_flags: void (struct tdb_context *, unsigned int)
+tdb_allocate: tdb_off_t (struct tdb_context *, tdb_len_t, struct tdb_record *)
+tdb_alloc_read: unsigned char *(struct tdb_context *, tdb_off_t, tdb_len_t)
+tdb_append: int (struct tdb_context *, TDB_DATA, TDB_DATA)
+tdb_brlock: int (struct tdb_context *, tdb_off_t, int, int, int, size_t)
+tdb_brlock_upgrade: int (struct tdb_context *, tdb_off_t, size_t)
+tdb_chainlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_mark: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_nonblock: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_chainlock_unmark: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock: int (struct tdb_context *, TDB_DATA)
+tdb_chainunlock_read: int (struct tdb_context *, TDB_DATA)
+tdb_check: int (struct tdb_context *, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_close: int (struct tdb_context *)
+tdb_convert: void *(void *, uint32_t)
+tdb_delete: int (struct tdb_context *, TDB_DATA)
+tdb_do_delete: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_dump_all: void (struct tdb_context *)
+tdb_enable_seqnum: void (struct tdb_context *)
+tdb_error: enum TDB_ERROR (struct tdb_context *)
+tdb_errorstr: const char *(struct tdb_context *)
+tdb_exists: int (struct tdb_context *, TDB_DATA)
+tdb_expand: int (struct tdb_context *, tdb_off_t)
+tdb_fd: int (struct tdb_context *)
+tdb_fetch: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_find_lock_hash: tdb_off_t (struct tdb_context *, TDB_DATA, uint32_t, int, struct tdb_record *)
+tdb_firstkey: TDB_DATA (struct tdb_context *)
+tdb_free: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_freelist_size: int (struct tdb_context *)
+tdb_get_flags: int (struct tdb_context *)
+tdb_get_logging_private: void *(struct tdb_context *)
+tdb_get_seqnum: int (struct tdb_context *)
+tdb_hash_size: int (struct tdb_context *)
+tdb_increment_seqnum_nonblock: void (struct tdb_context *)
+tdb_io_init: void (struct tdb_context *)
+tdb_lock: int (struct tdb_context *, int, int)
+tdb_lockall: int (struct tdb_context *)
+tdb_lockall_mark: int (struct tdb_context *)
+tdb_lockall_nonblock: int (struct tdb_context *)
+tdb_lockall_read: int (struct tdb_context *)
+tdb_lockall_read_nonblock: int (struct tdb_context *)
+tdb_lockall_unmark: int (struct tdb_context *)
+tdb_lock_nonblock: int (struct tdb_context *, int, int)
+tdb_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_log_fn: tdb_log_func (struct tdb_context *)
+tdb_map_size: size_t (struct tdb_context *)
+tdb_mmap: void (struct tdb_context *)
+tdb_munmap: int (struct tdb_context *)
+tdb_name: const char *(struct tdb_context *)
+tdb_nextkey: TDB_DATA (struct tdb_context *, TDB_DATA)
+tdb_null: {dptr = 0x0, dsize = 0}
+tdb_ofs_read: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_ofs_write: int (struct tdb_context *, tdb_off_t, tdb_off_t *)
+tdb_open: struct tdb_context *(const char *, int, int, int, mode_t)
+tdb_open_ex: struct tdb_context *(const char *, int, int, int, mode_t, const struct tdb_logging_context *, tdb_hash_func)
+tdb_parse_data: int (struct tdb_context *, TDB_DATA, tdb_off_t, tdb_len_t, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_parse_record: int (struct tdb_context *, TDB_DATA, int (*)(TDB_DATA, TDB_DATA, void *), void *)
+tdb_printfreelist: int (struct tdb_context *)
+tdb_rec_free_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_read: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_rec_write: int (struct tdb_context *, tdb_off_t, struct tdb_record *)
+tdb_remove_flags: void (struct tdb_context *, unsigned int)
+tdb_reopen: int (struct tdb_context *)
+tdb_reopen_all: int (int)
+tdb_repack: int (struct tdb_context *)
+tdb_setalarm_sigptr: void (struct tdb_context *, volatile sig_atomic_t *)
+tdb_set_logging_function: void (struct tdb_context *, const struct tdb_logging_context *)
+tdb_set_max_dead: void (struct tdb_context *, int)
+tdb_store: int (struct tdb_context *, TDB_DATA, TDB_DATA, int)
+_tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_cancel: int (struct tdb_context *)
+tdb_transaction_commit: int (struct tdb_context *)
+tdb_transaction_lock: int (struct tdb_context *, int)
+tdb_transaction_prepare_commit: int (struct tdb_context *)
+tdb_transaction_recover: int (struct tdb_context *)
+tdb_transaction_start: int (struct tdb_context *)
+tdb_transaction_unlock: int (struct tdb_context *)
+tdb_traverse: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_traverse_read: int (struct tdb_context *, tdb_traverse_func, void *)
+tdb_unlock: int (struct tdb_context *, int, int)
+tdb_unlockall: int (struct tdb_context *)
+tdb_unlockall_read: int (struct tdb_context *)
+tdb_unlock_record: int (struct tdb_context *, tdb_off_t)
+tdb_validate_freelist: int (struct tdb_context *, int *)
+tdb_wipe_all: int (struct tdb_context *)
+tdb_write_lock_record: int (struct tdb_context *, tdb_off_t)
+tdb_write_unlock_record: int (struct tdb_context *, tdb_off_t)
+tolower_sp: uint32_t (uint32_t)
+tolower_w: uint16_t (uint16_t)
+toupper_sp: uint32_t (uint32_t)
+toupper_w: uint16_t (uint16_t)
+type_configs: {{set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}, {set = false, syslog = false, fd = -1, level = log_none, display_options = 0}}
+ucs2_to_charset: size_t (charset_t, const uint16_t *, char *, size_t)
+ucs2_to_charset_allocate: size_t (charset_t, char **, const uint16_t *)
+unbecome_root: void (void)
+unix_rename: int (int, const char *, int, const char *)
+unix_strlower: size_t (const char *, size_t, char *, size_t)
+unix_strupper: size_t (const char *, size_t, char *, size_t)
+unload_volumes: void (AFPObj *)
+utf8_charlen: size_t (char *)
+utf8_decompose: size_t (char *, size_t, char *, size_t)
+utf8_precompose: size_t (char *, size_t, char *, size_t)
+utf8_strlen_validate: size_t (char *)
+utf8_strlower: size_t (const char *, size_t, char *, size_t)
+utf8_strupper: size_t (const char *, size_t, char *, size_t)
+utf8_to_charset_allocate: size_t (charset_t, char **, const char *)
+uuid_bin2string: const char *(const unsigned char *)
+uuidcache_dump: void (void)
+uuid_string2bin: void (const char *, unsigned char *)
+uuidtype: {"", "USER", "GROUP", "LOCAL"}
+volume_free: void (struct vol *)
+volume_unlink: void (struct vol *)
+writet: ssize_t (int, void *, const size_t, int, int)
* for e.g. HFS cdroms.
*/
-static size_t pull_charset_flags (charset_t from_set, charset_t cap_set, const char *src, size_t srclen, char* dest, size_t destlen, uint16_t *flags)
+static size_t pull_charset_flags (charset_t from_set, charset_t to_set, charset_t cap_set, const char *src, size_t srclen, char* dest, size_t destlen, uint16_t *flags)
{
const uint16_t option = (flags ? *flags : 0);
size_t i_len, o_len;
char* outbuf = dest;
atalk_iconv_t descriptor;
atalk_iconv_t descriptor_cap;
+ char escch; /* 150210: uninitialized OK, depends on j */
if (srclen == (size_t)-1)
srclen = strlen(src) + 1;
i_len=srclen;
o_len=destlen;
+ if ((option & CONV_ESCAPEDOTS) && i_len >= 2 && inbuf[0] == '.') {
+ if (o_len < 6) {
+ errno = E2BIG;
+ goto end;
+ }
+ ucs2_t ucs2 = ':';
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ ucs2 = '2';
+ memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ ucs2 = 'e';
+ memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ outbuf += 6;
+ o_len -= 6;
+ inbuf++;
+ i_len--;
+ *flags |= CONV_REQESCAPE;
+ }
+
while (i_len > 0) {
for (j = 0; j < i_len; ++j)
- if (inbuf[j] == ':')
+ if (inbuf[j] == ':' || inbuf[j] == '/') {
+ escch = inbuf[j];
break;
+ }
j = i_len - j;
i_len -= j;
}
if (j) {
- /* we have a ':' */
+ /* we have a ':' or '/' */
i_len = j, j = 0;
- if ((option & CONV_UNESCAPEHEX)) {
- /* treat it as a CAP hex encoded char */
- char h[MAXPATHLEN];
- size_t hlen = 0;
-
- while (i_len >= 3 && inbuf[0] == ':' &&
- isxdigit(inbuf[1]) && isxdigit(inbuf[2])) {
- h[hlen++] = (hextoint(inbuf[1]) << 4) | hextoint(inbuf[2]);
- inbuf += 3;
- i_len -= 3;
- }
- if (hlen) {
- const char *h_buf = h;
- if (atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len) == (size_t)-1) {
- i_len += hlen * 3;
- inbuf -= hlen * 3;
- if (errno == EILSEQ && (option & CONV_IGNORE)) {
+ if (escch == ':') {
+ if ((option & CONV_UNESCAPEHEX)) {
+ /* treat it as a CAP hex encoded char */
+ char h[MAXPATHLEN];
+ size_t hlen = 0;
+
+ while (i_len >= 3 && inbuf[0] == ':' &&
+ isxdigit(inbuf[1]) && isxdigit(inbuf[2])) {
+ h[hlen++] = (hextoint(inbuf[1]) << 4) | hextoint(inbuf[2]);
+ inbuf += 3;
+ i_len -= 3;
+ }
+ if (hlen) {
+ const char *h_buf = h;
+ if (atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len) == (size_t)-1) {
+ i_len += hlen * 3;
+ inbuf -= hlen * 3;
+ if (errno == EILSEQ && (option & CONV_IGNORE)) {
+ *flags |= CONV_REQMANGLE;
+ return destlen - o_len;
+ }
+ goto end;
+ }
+ } else {
+ /* We have an invalid :xx sequence */
+ errno = EILSEQ;
+ if ((option & CONV_IGNORE)) {
*flags |= CONV_REQMANGLE;
return destlen - o_len;
}
goto end;
}
- } else {
- /* We have an invalid :xx sequence */
- errno = EILSEQ;
- if ((option & CONV_IGNORE)) {
- *flags |= CONV_REQMANGLE;
- return destlen - o_len;
+ } else if (option & CONV_ESCAPEHEX) {
+ if (o_len < 6) {
+ errno = E2BIG;
+ goto end;
}
- goto end;
+ ucs2_t ucs2 = ':';
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ ucs2 = '3';
+ memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ ucs2 = 'a';
+ memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ outbuf += 6;
+ o_len -= 6;
+ inbuf++;
+ i_len--;
+ } else if (to_set == CH_UTF8_MAC || to_set == CH_MAC) {
+ /* convert to a '/' */
+ ucs2_t slash = 0x002f;
+ memcpy(outbuf, &slash, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
+ } else {
+ /* keep as ':' */
+ ucs2_t ucs2 = 0x003a;
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
}
} else {
- /* a ':' that we just convert to a '/' */
- ucs2_t slash = 0x002f;
- memcpy(outbuf, &slash, sizeof(ucs2_t));
- outbuf += 2;
- o_len -= 2;
- inbuf++;
- i_len--;
+ /* '/' */
+ if (option & CONV_ESCAPEHEX) {
+ if (o_len < 6) {
+ errno = E2BIG;
+ goto end;
+ }
+ ucs2_t ucs2 = ':';
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ ucs2 = '2';
+ memcpy(outbuf + sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ ucs2 = 'f';
+ memcpy(outbuf + 2 * sizeof(ucs2_t), &ucs2, sizeof(ucs2_t));
+ outbuf += 6;
+ o_len -= 6;
+ inbuf++;
+ i_len--;
+ } else if ((from_set == CH_UTF8_MAC || from_set == CH_MAC)
+ && (to_set != CH_UTF8_MAC || to_set != CH_MAC)) {
+ /* convert to ':' */
+ ucs2_t ucs2 = 0x003a;
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
+ } else {
+ /* keep as '/' */
+ ucs2_t ucs2 = 0x002f;
+ memcpy(outbuf, &ucs2, sizeof(ucs2_t));
+ outbuf += 2;
+ o_len -= 2;
+ inbuf++;
+ i_len--;
+ }
}
}
}
char* outbuf = (char*)dest;
atalk_iconv_t descriptor;
atalk_iconv_t descriptor_cap;
- char escch; /* 150210: uninitialized OK, depends on j */
descriptor = conv_handles[CH_UCS2][to_set];
descriptor_cap = conv_handles[CH_UCS2][cap_set];
i_len=srclen;
o_len=destlen;
- if ((option & CONV_ESCAPEDOTS) &&
- i_len >= 2 && SVAL(inbuf, 0) == 0x002e) { /* 0x002e = . */
- if (o_len < 3) {
- errno = E2BIG;
- goto end;
- }
- *outbuf++ = ':';
- *outbuf++ = '2';
- *outbuf++ = 'e';
- o_len -= 3;
- inbuf += 2;
- i_len -= 2;
- *flags |= CONV_REQESCAPE;
- }
-
while (i_len >= 2) {
- for (i = 0; i < i_len; i += 2) {
- ucs2_t c = SVAL(inbuf, i);
- switch (c) {
- case 0x003a: /* 0x003a = ':' */
- if ( ! (option & CONV_ALLOW_COLON)) {
- errno = EILSEQ;
- goto end;
- }
- escch = c;
- j = i_len - i;
- i_len = i;
- break;
- case 0x002f: /* 0x002f = '/' */
- if (option & CONV_ALLOW_SLASH) break;
- escch = c;
- j = i_len - i;
- i_len = i;
- break;
- }
- }
while (i_len > 0 &&
atalk_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len) == (size_t)-1) {
if (errno == EILSEQ) {
}
goto end;
}
+ } /* while (i_len >= 2) */
- if (j) {
- /* we have a ':' or '/' */
- i_len = j, j = 0;
-
- if ((option & CONV_ESCAPEHEX)) {
- /* CAP hex encode it */
- if (o_len < 3) {
- errno = E2BIG;
- goto end;
- }
- switch (escch) {
- case '/':
- *outbuf++ = ':';
- *outbuf++ = '2';
- *outbuf++ = 'f';
- break;
- case ':':
- *outbuf++ = ':';
- *outbuf++ = '3';
- *outbuf++ = 'a';
- break;
- default:
- /*
- * THIS SHOULD NEVER BE REACHED !!!
- * As a safety net I put in a ' ' here
- */
- *outbuf++ = ':';
- *outbuf++ = '2';
- *outbuf++ = '0';
- break;
- }
- o_len -= 3;
- inbuf += 2;
- i_len -= 2;
- } else {
- switch (escch) {
- case '/':
- case ':':
- *outbuf++ = ':';
- break;
- default: /* should never be reached */
- *outbuf++ = ' ';
- break;
- }
- o_len--;
- inbuf += 2;
- i_len -= 2;
- }
- }
- }
if (i_len > 0) errno = EINVAL;
end:
return (i_len + j == 0 || (option & CONV_FORCE)) ? destlen - o_len : (size_t)-1;
lazy_initialize_conv();
/* convert from_set to UCS2 */
- if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, cap_charset, src, src_len,
+ if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, to_set, cap_charset, src, src_len,
(char *) buffer, sizeof(buffer) -2, flags)) ) {
LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from_set));
return (size_t) -1;
/* Unicode Volume Name */
/* Firstly convert name from unixcharset to UTF8-MAC */
- flags = CONV_IGNORE | CONV_ALLOW_SLASH;
+ flags = CONV_IGNORE;
tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
if (tmpvlen <= 0) {
strcpy(tmpname, "???");
/* Do we have to mangle ? */
if ( (flags & CONV_REQMANGLE) || (tmpvlen > obj->options.volnamelen)) {
if (tmpvlen + suffixlen > obj->options.volnamelen) {
- flags = CONV_FORCE | CONV_ALLOW_SLASH;
+ flags = CONV_FORCE;
tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, obj->options.volnamelen - suffixlen, &flags);
tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0;
}
/* Maccharset Volume Name */
/* Firsty convert name from unixcharset to maccharset */
- flags = CONV_IGNORE | CONV_ALLOW_SLASH;
+ flags = CONV_IGNORE;
tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags);
if (tmpvlen <= 0) {
strcpy(tmpname, "???");
/* Do we have to mangle ? */
if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) {
if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) {
- flags = CONV_FORCE | CONV_ALLOW_SLASH;
+ flags = CONV_FORCE;
tmpvlen = convert_charset(obj->options.unixcharset,
obj->options.maccharset,
0,
options->flags |= OPTION_ANNOUNCESSH;
if (iniparser_getboolean(config, INISEC_GLOBAL, "map acls", 1))
options->flags |= OPTION_ACL2MACCESS;
- if (iniparser_getboolean(config, INISEC_GLOBAL, "keep sessions", 0))
- options->flags |= OPTION_KEEPSESSIONS;
if (iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0))
options->flags |= OPTION_CLOSEVOL;
if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0))
/*
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
+ * Copyright (c) 2013 Frank Lahm <franklahm@gmail.com
* All rights reserved. See COPYRIGHT.
*
- *
* handle inserting, removing, and freeing of children.
* this does it via a hash table. it incurs some overhead over
* a linear append/remove in total removal and kills, but it makes
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
+#include <pthread.h>
#include <atalk/logger.h>
#include <atalk/errchk.h>
#endif
/* hash/child functions: hash OR's pid */
-#define CHILD_HASHSIZE 32
#define HASH(i) ((((i) >> 8) ^ (i)) & (CHILD_HASHSIZE - 1))
-typedef struct server_child_fork {
- struct server_child_data *table[CHILD_HASHSIZE];
- void (*cleanup)(const pid_t);
-} server_child_fork;
-
-static inline void hash_child(struct server_child_data **htable,
- struct server_child_data *child)
+static inline void hash_child(afp_child_t **htable, afp_child_t *child)
{
- struct server_child_data **table;
+ afp_child_t **table;
- table = &htable[HASH(child->pid)];
- if ((child->next = *table) != NULL)
- (*table)->prevp = &child->next;
+ table = &htable[HASH(child->afpch_pid)];
+ if ((child->afpch_next = *table) != NULL)
+ (*table)->afpch_prevp = &child->afpch_next;
*table = child;
- child->prevp = table;
+ child->afpch_prevp = table;
}
-static inline void unhash_child(struct server_child_data *child)
+static inline void unhash_child(afp_child_t *child)
{
- if (child->prevp) {
- if (child->next)
- child->next->prevp = child->prevp;
- *(child->prevp) = child->next;
+ if (child->afpch_prevp) {
+ if (child->afpch_next)
+ child->afpch_next->afpch_prevp = child->afpch_prevp;
+ *(child->afpch_prevp) = child->afpch_next;
}
}
-static struct server_child_data *resolve_child(struct server_child_data **table, pid_t pid)
+static afp_child_t *resolve_child(afp_child_t **table, pid_t pid)
{
- struct server_child_data *child;
+ afp_child_t *child;
- for (child = table[HASH(pid)]; child; child = child->next) {
- if (child->pid == pid)
+ for (child = table[HASH(pid)]; child; child = child->afpch_next) {
+ if (child->afpch_pid == pid)
break;
}
}
/* initialize server_child structure */
-server_child *server_child_alloc(const int connections, const int nforks)
+server_child_t *server_child_alloc(int connections)
{
- server_child *children;
-
- children = (server_child *) calloc(1, sizeof(server_child));
- if (!children)
- return NULL;
-
- children->nsessions = connections;
- children->nforks = nforks;
- children->fork = (void *) calloc(nforks, sizeof(server_child_fork));
+ server_child_t *children;
- if (!children->fork) {
- free(children);
+ if (!(children = (server_child_t *)calloc(1, sizeof(server_child_t))))
return NULL;
- }
+ children->servch_nsessions = connections;
+ pthread_mutex_init(&children->servch_lock, NULL);
return children;
}
* add a child
* @return pointer to struct server_child_data on success, NULL on error
*/
-afp_child_t *server_child_add(server_child *children, int forkid, pid_t pid, int ipc_fd)
+afp_child_t *server_child_add(server_child_t *children, pid_t pid, int ipc_fd)
{
- server_child_fork *fork;
afp_child_t *child = NULL;
- sigset_t sig, oldsig;
- /* we need to prevent deletions from occuring before we get a
- * chance to add the child in. */
- sigemptyset(&sig);
- sigaddset(&sig, SIGCHLD);
- pthread_sigmask(SIG_BLOCK, &sig, &oldsig);
+ pthread_mutex_lock(&children->servch_lock);
/* it's possible that the child could have already died before the
* pthread_sigmask. we need to check for this. */
goto exit;
}
- fork = (server_child_fork *) children->fork + forkid;
-
/* if we already have an entry. just return. */
- if ((child = resolve_child(fork->table, pid)))
+ if ((child = resolve_child(children->servch_table, pid)))
goto exit;
if ((child = calloc(1, sizeof(afp_child_t))) == NULL)
goto exit;
- child->pid = pid;
- child->valid = 0;
- child->killed = 0;
- child->ipc_fd = ipc_fd;
+ child->afpch_pid = pid;
+ child->afpch_ipc_fd = ipc_fd;
- hash_child(fork->table, child);
- children->count++;
+ hash_child(children->servch_table, child);
+ children->servch_count++;
exit:
- pthread_sigmask(SIG_SETMASK, &oldsig, NULL);
+ pthread_mutex_unlock(&children->servch_lock);
return child;
}
/* remove a child and free it */
-int server_child_remove(server_child *children, const int forkid, pid_t pid)
+int server_child_remove(server_child_t *children, pid_t pid)
{
int fd;
- server_child_fork *fork;
- struct server_child_data *child;
+ afp_child_t *child;
- fork = (server_child_fork *) children->fork + forkid;
- if (!(child = resolve_child(fork->table, pid)))
+ if (!(child = resolve_child(children->servch_table, pid)))
return -1;
unhash_child(child);
- if (child->clientid) {
- free(child->clientid);
- child->clientid = NULL;
+ if (child->afpch_clientid) {
+ free(child->afpch_clientid);
+ child->afpch_clientid = NULL;
}
/* In main:child_handler() we need the fd in order to remove it from the pollfd set */
- fd = child->ipc_fd;
+ fd = child->afpch_ipc_fd;
if (fd != -1)
close(fd);
free(child);
- children->count--;
+ children->servch_count--;
- if (fork->cleanup)
- fork->cleanup(pid);
+ if (children->servch_cleanup)
+ children->servch_cleanup(pid);
return fd;
}
/* free everything: by using a hash table, this increases the cost of
* this part over a linked list by the size of the hash table */
-void server_child_free(server_child *children)
+void server_child_free(server_child_t *children)
{
- server_child_fork *fork;
- struct server_child_data *child, *tmp;
- int i, j;
-
- for (i = 0; i < children->nforks; i++) {
- fork = (server_child_fork *) children->fork + i;
- for (j = 0; j < CHILD_HASHSIZE; j++) {
- child = fork->table[j]; /* start at the beginning */
- while (child) {
- tmp = child->next;
- close(child->ipc_fd);
- if (child->clientid) {
- free(child->clientid);
- }
- free(child);
- child = tmp;
- }
+ afp_child_t *child, *tmp;
+ int j;
+
+ for (j = 0; j < CHILD_HASHSIZE; j++) {
+ child = children->servch_table[j]; /* start at the beginning */
+ while (child) {
+ tmp = child->afpch_next;
+ close(child->afpch_ipc_fd);
+ if (child->afpch_clientid)
+ free(child->afpch_clientid);
+ free(child);
+ child = tmp;
}
}
- free(children->fork);
+
free(children);
}
/* send signal to all child processes */
-void server_child_kill(server_child *children, int forkid, int sig)
+void server_child_kill(server_child_t *children, int sig)
{
- server_child_fork *fork;
- struct server_child_data *child, *tmp;
+ afp_child_t *child, *tmp;
int i;
- fork = (server_child_fork *) children->fork + forkid;
for (i = 0; i < CHILD_HASHSIZE; i++) {
- child = fork->table[i];
+ child = children->servch_table[i];
while (child) {
- tmp = child->next;
- kill(child->pid, sig);
+ tmp = child->afpch_next;
+ kill(child->afpch_pid, sig);
child = tmp;
}
}
}
-/* send kill to a child processes.
- * a plain-old linked list
- * FIXME use resolve_child ?
- */
-static int kill_child(struct server_child_data *child)
+/* send kill to a child processes */
+static int kill_child(afp_child_t *child)
{
- if (!child->killed) {
- kill(child->pid, SIGTERM);
+ if (!child->afpch_killed) {
+ kill(child->afpch_pid, SIGTERM);
/* we don't wait because there's no guarantee that we can really kill it */
- child->killed = 1;
+ child->afpch_killed = 1;
return 1;
} else {
- LOG(log_info, logtype_default, "Unresponsive child[%d], sending SIGKILL", child->pid);
- kill(child->pid, SIGKILL);
+ LOG(log_info, logtype_default, "Unresponsive child[%d], sending SIGKILL", child->afpch_pid);
+ kill(child->afpch_pid, SIGKILL);
}
return 1;
}
* Try to find an old session and pass socket
* @returns -1 on error, 0 if no matching session was found, 1 if session was found and socket passed
*/
-int server_child_transfer_session(server_child *children,
- int forkid,
+int server_child_transfer_session(server_child_t *children,
pid_t pid,
uid_t uid,
int afp_socket,
uint16_t DSI_requestID)
{
EC_INIT;
- server_child_fork *fork;
- struct server_child_data *child;
+ afp_child_t *child;
- fork = (server_child_fork *) children->fork + forkid;
- if ((child = resolve_child(fork->table, pid)) == NULL) {
+ if ((child = resolve_child(children->servch_table, pid)) == NULL) {
LOG(log_note, logtype_default, "Reconnect: no child[%u]", pid);
if (kill(pid, 0) == 0) {
LOG(log_note, logtype_default, "Reconnect: terminating old session[%u]", pid);
return 0;
}
- if (!child->valid) {
+ if (!child->afpch_valid) {
/* hmm, client 'guess' the pid, rogue? */
LOG(log_error, logtype_default, "Reconnect: invalidated child[%u]", pid);
return 0;
- } else if (child->uid != uid) {
+ } else if (child->afpch_uid != uid) {
LOG(log_error, logtype_default, "Reconnect: child[%u] not the same user", pid);
return 0;
}
LOG(log_note, logtype_default, "Reconnect: transfering session to child[%u]", pid);
- if (writet(child->ipc_fd, &DSI_requestID, 2, 0, 2) != 2) {
+ if (writet(child->afpch_ipc_fd, &DSI_requestID, 2, 0, 2) != 2) {
LOG(log_error, logtype_default, "Reconnect: error sending DSI id to child[%u]", pid);
EC_STATUS(-1);
goto EC_CLEANUP;
}
- EC_ZERO_LOG(send_fd(child->ipc_fd, afp_socket));
+ EC_ZERO_LOG(send_fd(child->afpch_ipc_fd, afp_socket));
EC_ZERO_LOG(kill(pid, SIGURG));
EC_STATUS(1);
/* see if there is a process for the same mac */
/* if the times don't match mac has been rebooted */
-void server_child_kill_one_by_id(server_child *children, int forkid, pid_t pid,
+void server_child_kill_one_by_id(server_child_t *children, pid_t pid,
uid_t uid, uint32_t idlen, char *id, uint32_t boottime)
{
- server_child_fork *fork;
- struct server_child_data *child, *tmp;
+ afp_child_t *child, *tmp;
int i;
- fork = (server_child_fork *)children->fork + forkid;
-
for (i = 0; i < CHILD_HASHSIZE; i++) {
- child = fork->table[i];
+ child = children->servch_table[i];
while (child) {
- tmp = child->next;
- if ( child->pid != pid) {
- if (child->idlen == idlen && memcmp(child->clientid, id, idlen) == 0) {
- if ( child->time != boottime ) {
+ tmp = child->afpch_next;
+ if (child->afpch_pid != pid) {
+ if (child->afpch_idlen == idlen && memcmp(child->afpch_clientid, id, idlen) == 0) {
+ if ( child->afpch_time != boottime ) {
/* Client rebooted */
- if (uid == child->uid) {
+ if (uid == child->afpch_uid) {
kill_child(child);
LOG(log_warning, logtype_default,
"Terminated disconnected child[%u], client rebooted.",
- child->pid);
+ child->afpch_pid);
} else {
LOG(log_warning, logtype_default,
- "Session with different pid[%u]", child->pid);
+ "Session with different pid[%u]", child->afpch_pid);
}
} else {
/* One client with multiple sessions */
LOG(log_debug, logtype_default,
- "Found another session[%u] for client[%u]", child->pid, pid);
+ "Found another session[%u] for client[%u]", child->afpch_pid, pid);
}
}
} else {
/* update childs own slot */
- child->time = boottime;
- if (child->clientid)
- free(child->clientid);
- LOG(log_debug, logtype_default, "Setting client ID for %u", child->pid);
- child->uid = uid;
- child->valid = 1;
- child->idlen = idlen;
- child->clientid = id;
+ child->afpch_time = boottime;
+ if (child->afpch_clientid)
+ free(child->afpch_clientid);
+ LOG(log_debug, logtype_default, "Setting client ID for %u", child->afpch_pid);
+ child->afpch_uid = uid;
+ child->afpch_valid = 1;
+ child->afpch_idlen = idlen;
+ child->afpch_clientid = id;
}
child = tmp;
}
}
}
-/* for extra cleanup if necessary */
-void server_child_setup(server_child *children, const int forkid,
- void (*fcn)(const pid_t))
-{
- server_child_fork *fork;
-
- fork = (server_child_fork *) children->fork + forkid;
- fork->cleanup = fcn;
-}
-
-
/* ---------------------------
* reset children signals
*/
* Pass afp_socket to old disconnected session if one has a matching token (token = pid)
* @returns -1 on error, 0 if no matching session was found, 1 if session was found and socket passed
*/
-static int ipc_kill_token(struct ipc_header *ipc, server_child *children)
+static int ipc_kill_token(struct ipc_header *ipc, server_child_t *children)
{
pid_t pid;
memcpy (&pid, ipc->msg, sizeof(pid_t));
return server_child_transfer_session(children,
- CHILD_DSIFORK,
pid,
ipc->uid,
ipc->afp_socket,
}
/* ----------------- */
-static int ipc_get_session(struct ipc_header *ipc, server_child *children)
+static int ipc_get_session(struct ipc_header *ipc, server_child_t *children)
{
uint32_t boottime;
uint32_t idlen;
ipc->child_pid, ipc->uid, boottime);
server_child_kill_one_by_id(children,
- CHILD_DSIFORK,
ipc->child_pid,
ipc->uid,
idlen,
* Public functions
***********************************************************************************/
-/*!
- * Listen on UNIX domain socket "name" for IPC from old sesssion
- *
- * @args name (r) file name to use for UNIX domain socket
- * @returns socket fd, -1 on error
- */
-int ipc_server_uds(const char *name)
-{
- EC_INIT;
- struct sockaddr_un address;
- socklen_t address_length;
- int fd = -1;
-
- EC_NEG1_LOG( fd = socket(PF_UNIX, SOCK_STREAM, 0) );
- EC_ZERO_LOG( setnonblock(fd, 1) );
- unlink(name);
- address.sun_family = AF_UNIX;
- address_length = sizeof(address.sun_family) + sprintf(address.sun_path, "%s", name);
- EC_ZERO_LOG( bind(fd, (struct sockaddr *)&address, address_length) );
- EC_ZERO_LOG( listen(fd, 1024) );
-
-EC_CLEANUP:
- if (ret != 0) {
- return -1;
- }
-
- return fd;
-}
-
-/*!
- * Connect to UNIX domain socket "name" for IPC with new afpd master
- *
- * 1. Connect
- * 2. send pid, which establishes a child structure for us in the master
- *
- * @args name (r) file name to use for UNIX domain socket
- * @returns socket fd, -1 on error
- */
-int ipc_client_uds(const char *name)
-{
- EC_INIT;
- struct sockaddr_un address;
- socklen_t address_length;
- int fd = -1;
- pid_t pid = getpid();
-
- EC_NEG1_LOG( fd = socket(PF_UNIX, SOCK_STREAM, 0) );
- address.sun_family = AF_UNIX;
- address_length = sizeof(address.sun_family) + sprintf(address.sun_path, "%s", name);
-
- EC_ZERO_LOG( connect(fd, (struct sockaddr *)&address, address_length) ); /* 1 */
- LOG(log_debug, logtype_afpd, "ipc_client_uds: connected to master");
-
- EC_ZERO_LOG( setnonblock(fd, 1) );
-
- if (writet(fd, &pid, sizeof(pid_t), 0, 1) != sizeof(pid_t)) {
- LOG(log_error, logtype_afpd, "ipc_client_uds: writet: %s", strerror(errno));
- EC_FAIL;
- }
-
-EC_CLEANUP:
- if (ret != 0) {
- return -1;
- }
- LOG(log_debug, logtype_afpd, "ipc_client_uds: fd: %d", fd);
- return fd;
-}
-
-int reconnect_ipc(AFPObj *obj)
-{
- int retrycount = 0;
-
- LOG(log_debug, logtype_afpd, "reconnect_ipc: start");
-
- close(obj->ipc_fd);
- obj->ipc_fd = -1;
-
- sleep((getpid() % 5) + 15); /* give it enough time to start */
-
- while (retrycount++ < 10) {
- if ((obj->ipc_fd = ipc_client_uds(_PATH_AFP_IPC)) == -1) {
- LOG(log_error, logtype_afpd, "reconnect_ipc: cant reconnect to master");
- sleep(1);
- continue;
- }
- LOG(log_debug, logtype_afpd, "reconnect_ipc: succesfull IPC reconnect");
- return 0;
- }
- return -1;
-}
-
/* -----------------
* Ipc format
* command
*
* @returns -1 on error, 0 on success
*/
-int ipc_server_read(server_child *children, int fd)
+int ipc_server_read(server_child_t *children, int fd)
{
int ret;
struct ipc_header ipc;
char *u;
size_t inplen;
size_t outlen;
- uint16_t flags = CONV_ESCAPEHEX | CONV_ALLOW_COLON;
+ uint16_t flags = CONV_ESCAPEHEX;
if (!mpath)
return NULL;
struct stat st;
int len;
+ if (stat(path, &st) == -1)
+ EC_FAIL;
+
if (S_ISDIR(st.st_mode)) {
len = snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path);
if (len < 0 || len >= MAXPATHLEN)
MAYBE_CORE =
endif
-GENERIC_LDFLAGS = -version-info $(VERSION_INFO) $(RELEASE) $(NO_UNDEFINED)
+GENERIC_LDFLAGS = -static
libevent_la_SOURCES = $(CORE_SRC) $(EXTRA_SRC)
libevent_la_LIBADD = @LTLIBOBJS@ $(SYS_LIBS)
DISTCLEANFILES = *~ libevent.pc ./include/event2/event-config.h
+install:
+
use_pam_so=yes
AC_DEFINE(FHS_COMPATIBILITY, 1, [Define if you want compatibily with the FHS])
AC_MSG_RESULT([yes])
+ atalk_cv_fhs_compat=yes
else
AC_MSG_RESULT([no])
+ atalk_cv_fhs_compat=no
fi
],[
AC_MSG_RESULT([no])
- ]
-)])
+ atalk_cv_fhs_compat=no
+])])
+
+dnl netatalk lockfile path
+AC_DEFUN([AC_NETATALK_LOCKFILE], [
+ AC_MSG_CHECKING([netatalk lockfile path])
+ AC_ARG_WITH(
+ lockfile,
+ [AS_HELP_STRING([--with-lockfile=PATH],[Path of netatalk lockfile])],
+ ac_cv_netatalk_lock=$withval,
+ ac_cv_netatalk_lock=""
+ )
+ if test -z "$ac_cv_netatalk_lock" ; then
+ ac_cv_netatalk_lock=/var/spool/locks/netatalk
+ if test x"$atalk_cv_fhs_compat" = x"yes" ; then
+ ac_cv_netatalk_lock=/var/run/netatalk.pid
+ else
+ case "$host_os" in
+ *freebsd*)
+ ac_cv_netatalk_lock=/var/spool/lock/netatalk
+ ;;
+ *netbsd*|*openbsd*)
+ ac_cv_netatalk_lock=/var/run/netatalk.pid
+ ;;
+ *linux*)
+ ac_cv_netatalk_lock=/var/lock/netatalk
+ ;;
+ esac
+ fi
+ fi
+ AC_DEFINE_UNQUOTED(PATH_NETATALK_LOCK, ["$ac_cv_netatalk_lock"], [netatalk lockfile path])
+ AC_SUBST(PATH_NETATALK_LOCK, ["$ac_cv_netatalk_lock"])
+ AC_MSG_RESULT([$ac_cv_netatalk_lock])
+])
dnl 64bit platform check
AC_DEFUN([AC_NETATALK_64BIT_LIBS], [
save_LIBS="$LIBS"
CFLAGS="$KRB5_CFLAGS"
LIBS="$KRB5_LIBS"
-AC_CHECK_FUNCS([krb5_free_unparsed_name krb5_free_error_message])
+AC_CHECK_FUNCS([krb5_free_unparsed_name krb5_free_error_message krb5_free_keytab_entry_contents krb5_kt_free_entry])
CFLAGS="$save_CFLAGS"
LIBS="$save_LIBS"
])
else
AC_MSG_RESULT([ none])
fi
+ AC_MSG_RESULT([ Netatalk lockfile:])
+ AC_MSG_RESULT([ $ac_cv_netatalk_lock])
AC_MSG_RESULT([ AFP:])
AC_MSG_RESULT([ Extended Attributes: $neta_cv_eas])
AC_MSG_RESULT([ ACL support: $with_acl_support])
'\" t
.\" Title: ad
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 02 Sep 2011
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AD" "1" "02 Sep 2011" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.SH "DESCRIPTION"
.PP
\fBad\fR
-is a UNIX file utlity suite with Netatalk compatibity\&. AppleDouble
+is a UNIX file utility suite with Netatalk compatibility\&. AppleDouble
files in
\&.AppleDouble
-directories and the CNID databases are updated as appropiate\&.
+directories and the CNID databases are updated as appropriate\&.
.SH "AVAILABLE COMMANDS"
.HP \w'\fBad\ ls\fR\ 'u
\fBad ls\fR [\-dRl\ [u]] {file|dir\ [\&.\&.\&.]}
l = No delete (f/d)
o = No copy (f)
-Note: any letter appearing in uppercase means the flag is set but it\'s a directory for which the flag is not allowed\&.
+Note: any letter appearing in uppercase means the flag is set but it\*(Aqs a directory for which the flag is not allowed\&.
.fi
.if n \{\
.RE
.PP
In the first synopsis form, the cp utility copies the contents of the source_file to the target_file\&. In the second synopsis form, the contents of each named source_file is copied to the destination target_directory\&. The names of the files themselves are not changed\&. If cp detects an attempt to copy a file to itself, the copy will fail\&.
.PP
-Netatalk AFP volumes are detected by means of their "\&.AppleDesktop" directory which is located in their volume root\&. When a copy targetting an AFP volume is detected, its CNID database daemon is connected and all copies will also go through the CNID database\&. AppleDouble files are also copied and created as needed when the target is an AFP volume\&.
+Netatalk AFP volumes are detected by means of their "\&.AppleDesktop" directory which is located in their volume root\&. When a copy targeting an AFP volume is detected, its CNID database daemon is connected and all copies will also go through the CNID database\&. AppleDouble files are also copied and created as needed when the target is an AFP volume\&.
.PP
Options:
.PP
.PP
\-i
.RS 4
-Cause cp to write a prompt to the standard error output before copying a file that would overwrite an existing file\&. If the response from the standard input begins with the character \'y\' or \'Y\', the file copy is attempted\&. (The \-i option overrides any pre\- vious \-f or \-n options\&.)
+Cause cp to write a prompt to the standard error output before copying a file that would overwrite an existing file\&. If the response from the standard input begins with the character \*(Aqy\*(Aq or \*(AqY\*(Aq, the file copy is attempted\&. (The \-i option overrides any pre\- vious \-f or \-n options\&.)
.RE
.PP
\-n
source AFP volume != destination AFP volume
.RE
.sp
-.RE
the files are copied and removed from the source\&.
.PP
Options:
.PP
\-i
.RS 4
-Cause mv to write a prompt to standard error before moving a file that would overwrite an existing file\&. If the response from the standard input begins with the character `y\' or `Y\', the move is attempted\&. (The \-i option overrides any previous \-f or \-n options\&.)
+Cause mv to write a prompt to standard error before moving a file that would overwrite an existing file\&. If the response from the standard input begins with the character `y\*(Aq or `Y\*(Aq, the move is attempted\&. (The \-i option overrides any previous \-f or \-n options\&.)
.RE
.PP
\-n
'\" t
.\" Title: afpldaptest
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 22 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFPLDAPTEST" "1" "22 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
'\" t
.\" Title: afppasswd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 22 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFPPASSWD" "1" "22 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.PP
With this utility you can only change the passwords used by two specific UAMs\&. As they provide only weak password encryption, the use of the "Randnum exchange" and "2\-Way Randnum exchange" UAMs is deprecated unless one has to support very old AFP clients, that can not deal with the more secure "DHCAST128" and "DHX2" UAM instead\&. Please compare with the
Authentication chapter
-inside Netatalk\'s documentation\&.
+inside Netatalk\*(Aqs documentation\&.
.sp .5v
.RE
.SH "EXAMPLE"
'\" t
.\" Title: apple_dump
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 16 Jul 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "APPLE_DUMP" "1" "16 Jul 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.RE
.SH "NOTE"
.PP
-There is no way to detect whether FinderInfo is FileInfo or DirInfo\&. By default, apple_dump examins whether file or directory, a parent directory is \&.AppleDouble, filename is \&._*, filename is \&.Parent, and so on\&.
+There is no way to detect whether FinderInfo is FileInfo or DirInfo\&. By default, apple_dump examines whether file or directory, a parent directory is \&.AppleDouble, filename is \&._*, filename is \&.Parent, and so on\&.
.PP
-If setting option \-e, \-f or \-d, assume FinderInfo and doesn\'t look for another file\&.
+If setting option \-e, \-f or \-d, assume FinderInfo and doesn\*(Aqt look for another file\&.
.SH "SEE ALSO"
.PP
\fBad\fR(1),
'\" t
.\" Title: asip-status.pl
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 24 Jul 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "ASIP\-STATUS\&.PL" "1" "24 Jul 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.SH "DESCRIPTION"
.PP
\fBasip\-status\&.pl\fR
-is a perl script that sends a FPGetSrvrInfo request to an AFP server at HOSTNAME:PORT and displays the results, namely "Machine type", the server\'s name, supported AFP versions, UAMs and AFP flags, the "server signature" and the network addresses, the server provides AFP services on\&.
+is a perl script that sends a FPGetSrvrInfo request to an AFP server at HOSTNAME:PORT and displays the results, namely "Machine type", the server\*(Aqs name, supported AFP versions, UAMs and AFP flags, the "server signature" and the network addresses, the server provides AFP services on\&.
.PP
-When you don\'t supply :PORT, then the default AFP port, 548, will be used\&.
+When you don\*(Aqt supply :PORT, then the default AFP port, 548, will be used\&.
.SH "OPTIONS"
.PP
\fB\-d\fR
.\" Title: dbd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
-.\" Date: 28 Dez 2012
+.\" Date: 28 Dec 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "DBD" "1" "28 Dez 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "DBD" "1" "28 Dec 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
.SH "DESCRIPTION"
.PP
\fBdbd\fR
-scans all file and directories of AFP volumes, updating the CNID database of the volume\&. It must be run with appropiate permissions i\&.e\&. as root\&.\&.
+scans all file and directories of AFP volumes, updating the CNID database of the volume\&. It must be run with appropriate permissions i\&.e\&. as root\&.\&.
.SH "OPTIONS"
.PP
\-c
-.so man1/megatron.1
+.so megatron.1
-.so man1/megatron.1
+.so megatron.1
'\" t
.\" Title: macusers
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 13 Oct 2011
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "MACUSERS" "1" "13 Oct 2011" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
'\" t
.\" Title: megatron
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 02 Sep 2011
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "MEGATRON" "1" "02 Sep 2011" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
\fBnetatalk\fR
Apple Filing Protocol (AppleShare) server\&. BinHex, MacBinary, and AppleSingle are commonly used formats for transferring Macintosh files between machines via email or file transfer protocols\&.
\fBmegatron\fR
-uses its name to determine what type of tranformation is being asked of it\&.
+uses its name to determine what type of transformation is being asked of it\&.
.PP
If
\fBmegatron\fR
,
\fBunbin\fR
or
-\fBunsingle\fR, it tries to convert file(s) from BinHex, MacBinary, or AppleSingle into AppleDouble format\&. BinHex is the format most often used to send Macintosh files by e\-mail\&. Usually these files have an extension of "\&.hqx"\&. MacBinary is the format most often used by terminal emulators "on the fly" when transferring Macintosh files in binary mode\&. MacBinary files often have an extension of "\&.bin"\&. Some Macintosh LAN\-based email packages use uuencoded AppleSingle format to "attach" or "enclose" files in email\&. AppleSingle files don\'t have a standard filename extension\&.
+\fBunsingle\fR, it tries to convert file(s) from BinHex, MacBinary, or AppleSingle into AppleDouble format\&. BinHex is the format most often used to send Macintosh files by e\-mail\&. Usually these files have an extension of "\&.hqx"\&. MacBinary is the format most often used by terminal emulators "on the fly" when transferring Macintosh files in binary mode\&. MacBinary files often have an extension of "\&.bin"\&. Some Macintosh LAN\-based email packages use uuencoded AppleSingle format to "attach" or "enclose" files in email\&. AppleSingle files don\*(Aqt have a standard filename extension\&.
.PP
If
\fBmegatron\fR
\fBsingle2bin\fR, or
\fBmacbinary\fR, it will try to convert the file(s) from BinHex, AppleSingle, or AppleDouble into MacBinary\&. This last translation may be useful in moving Macintosh files from your
\fBafpd\fR
-server to some other machine when you can\'t copy them from the server using a Macintosh for some reason\&.
+server to some other machine when you can\*(Aqt copy them from the server using a Macintosh for some reason\&.
.PP
If
\fBmegatron\fR
.PP
If no source file is given, or if
\fIsourcefile\fR
-is `\fB\-\fR\', and if the conversion is from a BinHex or MacBinary file,
+is `\fB\-\fR\*(Aq, and if the conversion is from a BinHex or MacBinary file,
\fBmegatron\fR
will read from standard input\&.
.PP
'\" t
.\" Title: netatalk-config
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 09 June 2001
.\" Manual: The Netatalk Project
.\" Source: Netatalk 3.0
.\"
.TH "NETATALK\-CONFIG" "1" "09 June 2001" "Netatalk 3.0" "The Netatalk Project"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
-.so man1/megatron.1
+.so megatron.1
-.so man1/megatron.1
+.so megatron.1
-.so man1/megatron.1
+.so megatron.1
'\" t
.\" Title: uniconv
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: 23 Mar 2012
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 19 Jan 2013
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "UNICONV" "1" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "UNICONV" "1" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.PP
\-d
.RS 4
-don\'t HEX encode leading dots (:2e), equivalent to
+don\*(Aqt HEX encode leading dots (:2e), equivalent to
\fBuse dots = yes\fR
in
\fBafp.conf\fR(5)
.PP
\-n
.RS 4
-"dry run", don\'t do any real changes
+"dry run", don\*(Aqt do any real changes
.RE
.PP
\-t
should
\fInot\fR
be running while you change the volume encoding\&. Remember to change
-\fBvolcodepage\fR
+\fBunix charset\fR
+or
+\fBvol charset\fR
in
-\fBAppleVolumes.default\fR(5)
+\fBafp.conf\fR(5)
to the new codepage, before restarting afpd\&.
.PP
In case of
.PP
The CNID backends maintains name to ID mappings\&. If you change a filename outside afpd(8) (shell, samba), the CNID db, i\&.e\&. the DIDNAME index, gets inconsistent\&. Netatalk tries to recover from such inconsistencies as gracefully as possible\&. The mechanisms to resolve such inconsistencies may fail sometimes, though, as this is not an easy task to accomplish\&. I\&.e\&. if several names in the path to the file or directory have changed, things may go wrong\&.
.PP
-If you change a lot of filenames at once, chances are higher that the afpds fallback mechanisms fail, i\&.e\&. files will be assigned new IDs, even though the file hasn\'t changed\&.
+If you change a lot of filenames at once, chances are higher that the afpds fallback mechanisms fail, i\&.e\&. files will be assigned new IDs, even though the file hasn\*(Aqt changed\&.
\fBuniconv\fR
therefore updates the CNID entry for each file/directory directly after it changes the name to avoid inconsistencies\&. The two supported backends for volumes, dbd and cdb, use the same CNID db format\&. Therefore, you
\fIcould\fR
-.so man1/megatron.1
+.so megatron.1
-e "s@:COMPILED_BACKENDS:@${compiled_backends}@g" \
<$< >$@
-GENERATED_MANS = afp.conf.5 afp_signature.conf.5 afp_voluuid.conf.5
-TEMPLATE_FILES = afp.conf.5.tmpl afp_signature.conf.5.tmpl afp_voluuid.conf.5.tmpl
+GENERATED_MANS = afp.conf.5 afp_signature.conf.5 afp_voluuid.conf.5 extmap.conf.5
+TEMPLATE_FILES = afp.conf.5.tmpl afp_signature.conf.5.tmpl afp_voluuid.conf.5.tmpl extmap.conf.5.tmpl
NONGENERATED_MANS =
man_MANS = $(GENERATED_MANS) $(NONGENERATED_MANS)
.\" 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: 06 Dez 2012
+.\" Date: 19 Jan 2013
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "AFP\&.CONF" "5" "06 Dez 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "AFP\&.CONF" "5" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
.\" * Define some portability stuff
.\" -----------------------------------------------------------------
\fIvol preset\fR
which can be selected in other volume sections via the
\fBvol preset\fR
-option and constitutes defaults for the volume\&. For any option speficied both in a preset
+option and constitutes defaults for the volume\&. For any option specified both in a preset
\fIand\fR
-in a volume section the volume section setting completly substitutes the preset option\&.
+in a volume section the volume section setting completely substitutes the preset option\&.
.PP
The access rights granted by the server are masked by the access rights granted to the specified or guest UNIX user by the host system\&. The server does not grant more access than the host system grants\&.
.PP
This section enable sharing of the UNIX server user home directories\&. Specifying an optional
\fBpath\fR
parameter means that not the whole user home will be shared but the subdirectory
-\fBpath\fR\&. It is neccessary to define the
+\fBpath\fR\&. It is necessary to define the
\fBbasedir regex\fR
option\&. It should be a regex which matches the parent directory of the user homes\&. Parameters denoted by a (H) belong to volume sections\&. The optional parameter
\fBhome name\fR
.RS 4
.\}
.nf
- [Homes] path = afp\-data basedir regex = /home
-
+ [Homes]
+ path = afp\-data
+ basedir regex = /home
.fi
.if n \{\
.RE
\fIjohn\fR
this results in an AFP home volume with a path of
/home/john/afp\-data\&.
+.PP
+If
+\fBbasedir regex\fR
+contains symlink, set the canonicalized absolute path\&. When
+/home
+links to
+/usr/home:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+ [Homes]
+ basedir regex = /usr/home
+.fi
+.if n \{\
+.RE
+.\}
.SH "PARAMETERS"
.PP
Parameters define the specific attributes of sections\&.
These are required if the server supports the Kerberos 5 authentication UAM\&.
.RE
.PP
-nt domain = \fIDOMAIN\fR \fB(G)\fR, nt separator = \fISEPERATOR\fR \fB(G)\fR
+nt domain = \fIDOMAIN\fR \fB(G)\fR, nt separator = \fISEPARATOR\fR \fB(G)\fR
.RS 4
-Use for eg\&. winbind authentication, prepends both strings before the username from login and then tries to authenticate with the result through the availabel and active UAM authentication modules\&.
+Use for eg\&. winbind authentication, prepends both strings before the username from login and then tries to authenticate with the result through the available and active UAM authentication modules\&.
.RE
.PP
save password = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(G)\fR
Specifies the servers unix charset, e\&.g\&.
\fIISO\-8859\-15\fR
or
-\fIEUC\-JP\fR\&. This is used to convert strings to/from the systems locale, e\&.g\&. for authenthication, server messages and volume names\&. If
+\fIEUC\-JP\fR\&. This is used to convert strings to/from the systems locale, e\&.g\&. for authentication, server messages and volume names\&. If
\fILOCALE\fR
is set, the systems locale is used\&. Defaults to
\fIUTF8\fR\&.
.RE
.RE
.PP
-afp listen = \fIip address[:port] [ip adress[:port] \&.\&.\&.]\fR \fB(G)\fR
+afp listen = \fIip address[:port] [ip address[:port] \&.\&.\&.]\fR \fB(G)\fR
.RS 4
Specifies the IP address that the server should advertise
\fBand\fR
option\&.
.RE
.PP
-cnid listen = \fIip address[:port] [ip adress[:port] \&.\&.\&.]\fR \fB(G)\fR
+cnid listen = \fIip address[:port] [ip address[:port] \&.\&.\&.]\fR \fB(G)\fR
.RS 4
Specifies the IP address that the CNID server should listen on\&. The default is
\fBlocalhost:4700\fR\&.
.PP
hostname = \fIname\fR \fB(G)\fR
.RS 4
-Use this instead of the result from calling hostname for dertermening which IP address to advertise, therfore the hostname is resolved to an IP which is the advertised\&. This is NOT used for listening and it is also overwritten by
+Use this instead of the result from calling hostname for determining which IP address to advertise, therefore the hostname is resolved to an IP which is the advertised\&. This is NOT used for listening and it is also overwritten by
\fBafp listen\fR\&.
.RE
.PP
.PP
server quantum = \fInumber\fR \fB(G)\fR
.RS 4
-This specifies the DSI server quantum\&. The default value is 303840\&. The maximum value is 0xFFFFFFFFF, the minimum is 32000\&. If you specify a value that is out of range, the default value will be set\&. Do not change this value unless you\*(Aqre absolutely sure, what you\*(Aqre doing
+This specifies the DSI server quantum\&. The default value is 1 MB\&. The maximum value is 0xFFFFFFFFF, the minimum is 32000\&. If you specify a value that is out of range, the default value will be set\&. Do not change this value unless you\*(Aqre absolutely sure, what you\*(Aqre doing
.RE
.PP
sleep time = \fInumber\fR \fB(G)\fR
.PP
basedir regex = \fIregex\fR \fB(H)\fR
.RS 4
-Regular expression which matches the parent directory of the user homes\&. In the simple case this is just a path ie
+Regular expression which matches the parent directory of the user homes\&. If
+\fBbasedir regex\fR
+contains symlink, you must set the canonicalized absolute path\&. In the simple case this is just a path ie
\fBbasedir regex = /home\fR
.RE
.PP
.PP
extmap file = \fIpath\fR \fB(G)\fR
.RS 4
-Sets the path to the file which defines file extension type/creator mappings\&. (default is :ETCDIR:/AppleVolumes\&.system)\&.
+Sets the path to the file which defines file extension type/creator mappings\&. (default is :ETCDIR:/extmap\&.conf)\&.
.RE
.PP
guest account = \fIname\fR \fB(G)\fR
home name = \fIname\fR \fB(H)\fR
.RS 4
AFP user home volume name\&. The default is
-\fIusers\*(Aqs home\fR\&.
-.RE
-.PP
-keep sessions = \fIBOOLEAN\fR (default: \fIno\fR) \fB(G)\fR
-.RS 4
-Enable "Continuous AFP Service"\&. This means restarting AFP and CNID service daemons master processes, but keeping the AFP session processes\&. This can be used to install (most) updates to Netatalk without interruping active AFP sessions\&. Existing AFP sessions will still run the version from before updating, but new AFP sessions will run the updated code\&. After enabling this option when sending SIGQUIT to the
-\fInetatalk\fR
-service controller process, the AFP and CNID daemons will exit and then the service controller will restart them\&. AFP session processes are notified of the master afpd shutdown, they will then sleep 15\-20 seconds and then try to reconnect their IPC channel to the master afpd process\&. The IPC channel between the AFP master service daemon and the AFP session child is used for keeping session state of AFP sessions in the AFP master process\&. The session state is needed when AFP clients experience eg network outages and try to reconnect to the AFP server\&.
+\fIuser\*(Aqs home\fR\&.
.RE
.PP
login message = \fImessage\fR \fB(G)/(V)\fR
.PP
vol dbpath = \fIpath\fR \fB(G)\fR
.RS 4
-Sets the database information to be stored in path\&. You have to specifiy a writable location, even if the volume is read only\&. The default is
+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
:STATEDIR:/netatalk/CNID/\&.
.RE
.PP
.RE
.\}
.sp
-Mac OS 9 and earlier are not influenced by this, because Maccharset volume name is always limitted to 27 bytes\&.
+Mac OS 9 and earlier are not influenced by this, because Maccharset volume name is always limited to 27 bytes\&.
.RE
.PP
vol preset = \fIname\fR \fB(G)/(V)\fR
.PP
log file = \fIlogfile\fR \fB(G)\fR
.RS 4
-If not specified Netatalk logs to syslogs daemon facilify\&. Otherwise it logs to
+If not specified Netatalk logs to syslogs daemon facility\&. Otherwise it logs to
\fBlogfile\fR\&.
.RE
.PP
.RE
.SS "Filesystem Change Events (FCE)"
.PP
-Netatalk includes a nifty filesystem change event mechanism where afpd processes notfiy interested listeners about certain filesytem event by UDP network datagrams\&.
+Netatalk includes a nifty filesystem change event mechanism where afpd processes notify interested listeners about certain filesystem event by UDP network datagrams\&.
.PP
fce listener = \fIhost[:port]\fR \fB(G)\fR
.RS 4
Enables sending FCE events to the specified
\fIhost\fR, default
\fIport\fR
-is 12250 if not specified\&. Specifying mutliple listeners is done by having this option once for each of them\&.
+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
.RS 4
-Speficies which FCE events are active, default is
+Specifies which FCE events are active, default is
\fIfmod,fdel,ddel,fcre,dcre\fR\&.
.RE
.PP
.PP
fce holdfmod = \fIseconds\fR \fB(G)\fR
.RS 4
-This determines the time delay in seconds which is always waited if another file modification for the same file is done by a client before sending an FCE file modification event (fmod)\&. For example saving a file in Photoshop would generate multiple events by itself because the application is opening, modifying and closing a file mutliple times for every "save"\&. Defautl: 60 seconds\&.
+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
.SS "Debug Parameters"
.PP
.PP
For a basic mode of operation there\*(Aqs nothing to configure\&. afpd reads ACLs on the fly, calculating effective permissions and returning the calculated permissions via the so called UARights permission bits\&. On a Mac the Finder uses these bits to adjust permission in Finder windows\&. For example folder whos UNIX mode would only result in in read\-only permissions for a user will not be displayed with a read\-only icon and the user will be able to write to the folder given the folder has an ACL giving the user write access\&.
.PP
-However, neither in Finder "Get Info" windows nor in Terminal will you be able to see the ACLs, that\*(Aqs a result of how ACLs in OS X are designed\&. If you want to be able to display ACLs on the client, things get more involed as you must then setup both client and server to be part on a authentication domain (directory service, eg LDAP, OpenDirectory)\&. The reason is, that in OS X ACLs are bound to UUIDs, not just uid\*(Aqs or gid\*(Aqs\&. Therefor afpd must be able to map every filesystem uid and gid to a UUID so that it can return the server side ACLs which are bound to UNIX uid and gid mapped to OS X UUIDs\&. Get it? Read on\&.
+However, neither in Finder "Get Info" windows nor in Terminal will you be able to see the ACLs, that\*(Aqs a result of how ACLs in OS X are designed\&. If you want to be able to display ACLs on the client, things get more involved as you must then setup both client and server to be part on a authentication domain (directory service, eg LDAP, OpenDirectory)\&. The reason is, that in OS X ACLs are bound to UUIDs, not just uid\*(Aqs or gid\*(Aqs\&. Therefor afpd must be able to map every filesystem uid and gid to a UUID so that it can return the server side ACLs which are bound to UNIX uid and gid mapped to OS X UUIDs\&. Get it? Read on\&.
.PP
Netatalk can query a directory server using LDAP queries\&. Either the directory server already provides an UUID attribute for user and groups (Active Directory, Open Directory) or you reuse an unused attribute (or add a new one) to you directory server (eg OpenLDAP)\&.
.PP
.PP
ldap uuid string = \fISTRING\fR \fB(G)\fR
.RS 4
-Format of the uuid string in the directory\&. A series of x and \-, where every x denotes a value 0\-9a\-f and every \- is a seperator\&.
+Format of the uuid string in the directory\&. A series of x and \-, where every x denotes a value 0\-9a\-f and every \- is a separator\&.
.sp
Default: xxxxxxxx\-xxxx\-xxxx\-xxxx\-xxxxxxxxxxxx
.RE
.RS 4
Useful for Time Machine: limits the reported volume size, thus preventing Time Machine from using the whole real disk space for backup\&. Example: "vol size limit = 1000" would limit the reported disk space to 1 GB\&.
\fBIMPORTANT: \fR
-This is an approimated calculation taking into accout the contents of Time Machine sparsebundle images\&. Therefor you MUST NOT use this volume to store other content when using this option, because it would NOT be accounted\&. The calculation works by reading the band size from the Info\&.plist XML file of the sparsebundle, reading the bands/ directory counting the number of band files, and then multiplying one with the other\&.
+This is an approximated calculation taking into account the contents of Time Machine sparsebundle images\&. Therefor you MUST NOT use this volume to store other content when using this option, because it would NOT be accounted\&. The calculation works by reading the band size from the Info\&.plist XML file of the sparsebundle, reading the bands/ directory counting the number of band files, and then multiplying one with the other\&.
.RE
.PP
valid users = \fIuser @group\fR \fB(V)\fR
Try
\fBsys\fR
(by setting an EA on the shared directory itself), fallback to
-\fBad\fR\&. Requires writeable volume for perfoming test\&. "\fBread only = yes\fR" overwrites
+\fBad\fR\&. Requires writable volume for performing test\&. "\fBread only = yes\fR" overwrites
\fBauto\fR
with
-\fBnone\fR\&. Use explicit "\fBea = sys|ad\fR" for read\-only volumes where appropiate\&.
+\fBnone\fR\&. Use explicit "\fBea = sys|ad\fR" for read\-only volumes where appropriate\&.
.RE
.PP
sys
\fBappledouble = v2\fR
to
\fBappledouble = ea\fR
-is performed when accessing filesystems from clients\&. This is generally useful, but costs some performance\&. It\*(Aqs recommdable to run
+is performed when accessing filesystems from clients\&. This is generally useful, but costs some performance\&. It\*(Aqs recommendable to run
\fBdbd\fR
on volumes and do the conversion with that\&. Then this option can be set to no\&.
.RE
.PP
time machine = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
.RS 4
-Whether to enable Time Machine suport for this volume\&.
+Whether to enable Time Machine support for this volume\&.
.RE
.PP
unix priv = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
.PP
cdb
.RS 4
-"Concurrent database", backend is based on Oracle Berkely DB\&. With this backend several
+"Concurrent database", backend is based on Oracle Berkley DB\&. With this backend several
\fBafpd\fR
-deamons access the CNID database directly\&. Berkeley DB locking is used to synchronize access, if more than one
+daemons access the CNID database directly\&. Berkeley DB locking is used to synchronize access, if more than one
\fBafpd\fR
process is active for a volume\&. The drawback is, that the crash of a single
\fBafpd\fR
With OS X Apple introduced the AFP3 protocol\&. One of the most important changes was that AFP3 uses unicode names encoded as UTF\-8 decomposed\&. Previous AFP/OS versions used codepages, like MacRoman, MacCentralEurope, etc\&.
.PP
\fBafpd\fR
-needs a way to preserve extended macintosh characters, or characters illegal in unix filenames, when saving files on a unix filesystem\&. Earlier versions used the the so called CAP encoding\&. An extended character (>0x7F) would be converted to a :xx sequence, e\&.g\&. the Apple Logo (MacRoman: 0xF0) was saved as
+needs a way to preserve extended Macintosh characters, or characters illegal in unix filenames, when saving files on a unix filesystem\&. Earlier versions used the the so called CAP encoding\&. An extended character (>0x7F) would be converted to a :xx sequence, e\&.g\&. the Apple Logo (MacRoman: 0xF0) was saved as
:f0\&. Some special characters will be converted as to :xx notation as well\&. \*(Aq/\*(Aq will be encoded to
:2f, if
\fBusedots\fR
\fBafpd\fR(8),
\fBafppasswd\fR(5),
\fBafp_signature.conf\fR(5),
+\fBextmap.conf\fR(5),
\fBcnid_metad\fR(8)
'\" t
.\" Title: afp_signature.conf
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 23 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFP_SIGNATURE\&.CONF" "5" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
'\" t
.\" Title: afp_voluuid.conf
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 23 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "AFP_VOLUUID\&.CONF" "5" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
--- /dev/null
+'\" t
+.\" Title: extmap.conf
+.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 19 Jan 2013
+.\" Manual: Netatalk 3.0
+.\" Source: Netatalk 3.0
+.\" Language: English
+.\"
+.TH "EXTMAP\&.CONF" "5" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+extmap.conf \- Configuration file used by afpd(8) to specify file name extension mappings\&.
+.SH "SYNOPSIS"
+.HP \w'\fB:ETCDIR:/extmap\&.conf\fR\fB\fR\ 'u
+\fB:ETCDIR:/extmap\&.conf\fR\fB\fR
+.SH "DESCRIPTION"
+.PP
+
+:ETCDIR:/extmap\&.conf
+is the configuration file used by
+\fBafpd\fR
+to specify file name extension mappings\&.
+.PP
+The configuration lines are composed like:
+.PP
+\&.extension
+\fI[ type [ creator ] ]\fR
+.PP
+Any line beginning with a hash (\(lq#\(rq) character is ignored\&. The leading\-dot lines specify file name extension mappings\&. The extension \*(Aq\&.\*(Aq sets the default creator and type for otherwise untyped Unix files\&.
+.SH "EXAMPLES"
+.PP
+\fBExample.\ \&Extension is jpg. Type is "JPEG". Creator is "ogle".\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\&.jpg "JPEG" "ogle"
+.fi
+.if n \{\
+.RE
+.\}
+.PP
+\fBExample.\ \&Extension is lzh. Type is "LHA ". Creator is not defined.\fR
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+\&.lzh "LHA "
+.fi
+.if n \{\
+.RE
+.\}
+.SH "SEE ALSO"
+.PP
+\fBafp.conf\fR(5),
+\fBafpd\fR(8)
'\" t
.\" Title: afpd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
-.\" Date: 23 Mar 2012
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
+.\" Date: 19 Jan 2013
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\" Language: English
.\"
-.TH "AFPD" "8" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
+.TH "AFPD" "8" "19 Jan 2013" "Netatalk 3.0" "Netatalk 3.0"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.RE
.SH "SIGNALS"
.PP
-To shut down a user\'s
+To shut down a user\*(Aqs
\fBafpd\fR
process it is recommended that
\fBSIGKILL (\-9)\fR
\fBafpd\fR
enables
\fImax_debug\fR
-logging for this process\&. The log is sent to fhe file
+logging for this process\&. The log is sent to the file
/tmp/afpd\&.PID\&.XXXXXX\&. Sending another
\fBSIGINT\fR
will revert to the original log settings\&.
list of UUID for Time Machine volume
.RE
.PP
+:ETCDIR:/extmap\&.conf
+.RS 4
+file name extension mapping
+.RE
+.PP
:ETCDIR:/msg/message\&.pid
.RS 4
contains messages to be sent to users\&.
\fBafp.conf\fR(5),
\fBafp_signature.conf\fR(5),
\fBafp_voluuid.conf\fR(5),
+\fBextmap.conf\fR(5),
\fBdbd\fR(1)\&.
'\" t
.\" Title: cnid_dbd
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 01 Jan 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "CNID_DBD" "8" "01 Jan 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.PP
\fBcnid_dbd\fR
uses the
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database library and uses transactionally protected updates\&. The
\fBdbd\fR
backend with transactions will avoid corruption of the CNID database even if the system crashes unexpectedly\&.
on startup, which is normally caused by
\fBafpd\fR
serving a netatalk volume to a client\&. It changes to the
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database home directory
\fIdbdir\fR
that is associated with the volume\&. If the userid inherited from
can be configured to run forever or to exit after a period of inactivity\&. If
\fBcnid_dbd\fR
receives a TERM or an INT signal it will exit cleanly after flushing dirty database buffers to disk and closing
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database environments\&. It is safe to terminate
\fBcnid_dbd\fR
this way, it will be restarted when necessary\&. Other signals are not handled and will cause an immediate exit, possibly leaving the CNID database in an inconsistent state (no transactions) or losing recent updates during recovery (transactions)\&.
.PP
The
-\fBBerkleley DB\fR
+\fBBerkeley DB\fR
database subsystem will create files named log\&.xxxxxxxxxx in the database home directory
-\fIdbdir\fR, where xxxxxxxxxx is a monotonically increasing integer\&. These files contain ithe transactional database changes\&. They will be removed regularily, unless the
+\fIdbdir\fR, where xxxxxxxxxx is a monotonically increasing integer\&. These files contain the transactional database changes\&. They will be removed regularly, unless the
\fBlogfile_autoremove\fR
option is specified in the
\fIdb_param\fR
configuration file (see below) with a value of 0 (default 1)\&.
-.PP
-Do not use
-\fBcnid_dbd\fR
-for databases on NFS mounted file systems\&. It makes the whole point of securing database changes properly moot\&. Use the dbdir: Option in the appropriate
-\fBAppleVolumes\fR
-configuration file to put the database onto a local disk\&.
.SH "OPTIONS"
.PP
\fB\-v, \-V\fR
.RS 4
If set to 0, unused Berkeley DB transactional logfiles (log\&.xxxxxxxxxx in the database home directory) are not removed on startup of
\fBcnid_dbd\fR
-and on a reqular basis\&. Default: 1\&.
+and on a regular basis\&. Default: 1\&.
.RE
.PP
\fBcachesize\fR
\fBdb_stat\fR
utility with the
\fB\-m\fR
-option that comes with Berkely DB can help you determine wether you need to change this value\&. The default is pretty conservative so that a large percentage of requests should be satisfied from the cache directly\&. If memory is not a bottleneck on your system you might want to leave it at that value\&. The
+option that comes with Berkley DB can help you determine ether you need to change this value\&. The default is pretty conservative so that a large percentage of requests should be satisfied from the cache directly\&. If memory is not a bottleneck on your system you might want to leave it at that value\&. The
\fBBerkeley DB Tutorial and Reference Guide\fR
has a section
\fBSelecting a cache size\fR
.PP
Note that the first version to appear
\fIafter\fR
-Netatalk 2\&.1 ie Netatalk 2\&.1\&.1, will support BerkeleyDB updates on the fly without manual intervention\&. In other words Netatalk 2\&.1 does contain code to prepare the BerkeleyDB database for upgrades and to upgrade it in case it has been prepared before\&. That means it can\'t upgrade a 2\&.0\&.x version because that one didn\'t prepare the database\&.
+Netatalk 2\&.1 ie Netatalk 2\&.1\&.1, will support BerkeleyDB updates on the fly without manual intervention\&. In other words Netatalk 2\&.1 does contain code to prepare the BerkeleyDB database for upgrades and to upgrade it in case it has been prepared before\&. That means it can\*(Aqt upgrade a 2\&.0\&.x version because that one didn\*(Aqt prepare the database\&.
.PP
In order to update between older Netatalk releases using different BerkeleyDB library versions, follow this steps:
.sp
'\" t
.\" Title: cnid_metad
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 23 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "CNID_METAD" "8" "23 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
.PP
\fBcnid_metad\fR
does not block or catch any signals apart from SIGPIPE\&. It will therefore exit on most signals received\&. This will also cause all instances of
-\fBcnid_dbd\'s\fR
+\fBcnid_dbd\*(Aqs\fR
started by that
\fBcnid_metad\fR
to exit gracefully\&. Since state about and IPC access to the subprocesses is only maintained in memory by
'\" t
.\" Title: netatalk
.\" Author: [FIXME: author] [see http://docbook.sf.net/el/author]
-.\" Generator: DocBook XSL Stylesheets v1.75.2 <http://docbook.sf.net/>
+.\" Generator: DocBook XSL Stylesheets v1.78.0 <http://docbook.sf.net/>
.\" Date: 22 Mar 2012
.\" Manual: Netatalk 3.0
.\" Source: Netatalk 3.0
.\"
.TH "NETATALK" "8" "22 Mar 2012" "Netatalk 3.0" "Netatalk 3.0"
.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\" -----------------------------------------------------------------
.\" * set default formatting
.\" -----------------------------------------------------------------
.\" disable hyphenation
Stop Netatalk service, AFP and CNID daemons
.RE
.PP
-SIGQUIT
-.RS 4
-Restart AFP and CNID master daemons, but keep all session AFP processes running\&. Can be used to implement
-AFP service without downtime\&.
-.RE
-.PP
SIGHUP
.RS 4
Sending a