ACLOCAL_AMFLAGS = -I macros
AUTOMAKE_OPTIONS = foreign
+if USE_BUILTIN_LIBEVENT
+ SUBDIRS += libevent
+endif
+
+if RUN_LDCONFIG
+install-exec-hook:
+ @printf "Running ldconfig to ensure libraries installed in system library directories are added to the dynamic linker cache ... "
+ @-@NETA_LDCONFIG@
+ @printf "done\n"
+endif
+Changes in 3.0 alpha2
+=====================
+
+* UPD: afpd: Store '.' as is and '/' as ':' on the server, don't
+ CAP hexencode as "2e" and "2f" respectively
+* UPD: afdp: Automatic name conversion, renaming files and directories
+ containing CAP sequences to their not enscaped forms
+* UPD: afpd: Correct handling of user homes and users without homes
+* UPD: afpd: Perform complete automatic adouble:v2 to adouble:ea conversion
+ as root. Previously only unlinking the adouble:v2 file was done as root
+* UPD: dbd: -C option removes CAP encoding
+* UPD: Add graceful option to RedHat init script
+* UPD: Add --disable-bundled-libevent configure options When set to yes,
+ we rely on a properly installed version on libevent CPPFLAGS and LDFLAGS
+ should be set properly to pick that up
+* UPD: Run ldconfig on Linux at the end of make install
+* FIX: afpd: ad cp on appledouble = ea volumes
+* FIX: dbd: ignore ._ appledouble files
+* REM: Volumes options "use dots" and "hex encoding"
+
Changes in 3.0 alpha1
=====================
+
* NEW: Central configuration file afp.conf which replaces all previous files
* NEW: netatalk: service controller starting and restarting afpd and cnid_metad
as necessary
* FIX: afpd: Dont use searchdb when doing partial name search
* FIX: afpd: Fix a possible bug handling disconnected sessions,
NetAFP Bug ID #16
+* FIX: dbd: Don't remove BerkeleyDB if it's still in use by eg cnid_dbd, fixes
+ bug introduced in 2.2.2
* FIX: debian initscript: start avahi-daemon (if available) before atalkd
Changes in 2.2.2
-3.0alpha1
\ No newline at end of file
+3.0alpha2
\ No newline at end of file
}
#endif
+#define ADVOL_V2_OR_EA(ad) ((ad) == AD_VERSION2 || (ad) == AD_VERSION_EA)
+
enum logtype {STD, DBG};
#define SLOG(...) \
dir = path;
else
dir++;
- if (check_netatalk_dirs(dir) != NULL)
+ if (!dvolume.vol->vfs->vfs_validupath(dvolume.vol, dir))
return FTW_SKIP_SUBTREE;
/*
}
/* Create ad dir and copy ".Parent" */
- if (dvolume.vol->v_path && dvolume.vol->v_adouble == AD_VERSION2) {
-
- /* Create ".AppleDouble" dir */
+ if (dvolume.vol->v_path && ADVOL_V2_OR_EA(dvolume.vol->v_adouble)) {
mode_t omask = umask(0);
- bstring addir = bfromcstr(to.p_path);
- bcatcstr(addir, "/.AppleDouble");
- mkdir(cfrombstr(addir), 02777);
- bdestroy(addir);
+ if (dvolume.vol->v_adouble == AD_VERSION2) {
+ /* Create ".AppleDouble" dir */
+ bstring addir = bfromcstr(to.p_path);
+ bcatcstr(addir, "/.AppleDouble");
+ mkdir(cfrombstr(addir), 02777);
+ bdestroy(addir);
+ }
- if (svolume.vol->v_path && svolume.vol->v_adouble == AD_VERSION2) {
- /* copy ".Parent" file */
+ if (svolume.vol->v_path && ADVOL_V2_OR_EA(svolume.vol->v_adouble)) {
+ /* copy metadata file */
if (dvolume.vol->vfs->vfs_copyfile(dvolume.vol, -1, path, to.p_path)) {
SLOG("Error copying adouble for %s -> %s", path, to.p_path);
badcp = rval = 1;
ERROR("Error opening adouble for: %s", to.p_path);
}
ad_setid( &ad, st.st_dev, st.st_ino, did, pdid, dvolume.db_stamp);
- ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
+ if (dvolume.vol->v_adouble == AD_VERSION2)
+ ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
ad_setdate(&ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime);
ad_setdate(&ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime);
ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
if (ftw_copy_file(ftw, path, statp, dne))
badcp = rval = 1;
- if (dvolume.vol->v_path && dvolume.vol->v_adouble == AD_VERSION2) {
+ if (dvolume.vol->v_path && ADVOL_V2_OR_EA(dvolume.vol->v_adouble)) {
mode_t omask = umask(0);
- if (svolume.vol->v_path && svolume.vol->v_adouble == AD_VERSION2) {
+ if (svolume.vol->v_path && ADVOL_V2_OR_EA(svolume.vol->v_adouble)) {
/* copy ad-file */
if (dvolume.vol->vfs->vfs_copyfile(dvolume.vol, -1, path, to.p_path)) {
SLOG("Error copying adouble for %s -> %s", path, to.p_path);
ERROR("Error opening adouble for: %s", to.p_path);
}
ad_setid( &ad, st.st_dev, st.st_ino, cnid, did, dvolume.db_stamp);
- ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
+ if (dvolume.vol->v_adouble == AD_VERSION2)
+ ad_setname(&ad, utompath(dvolume.vol, basename(to.p_path)));
ad_setdate(&ad, AD_DATE_CREATE | AD_DATE_UNIX, st.st_mtime);
ad_setdate(&ad, AD_DATE_MODIFY | AD_DATE_UNIX, st.st_mtime);
ad_setdate(&ad, AD_DATE_ACCESS | AD_DATE_UNIX, st.st_mtime);
if ( ! svol->vol->v_path) {
/* no source volume: escape special chars (eg ':') */
from = dvol->vol->v_volcharset; /* src = dst charset */
- flags |= CONV_ESCAPEHEX;
+ if (dvol->vol->v_adouble == AD_VERSION2)
+ flags |= CONV_ESCAPEHEX;
} else {
from = svol->vol->v_volcharset;
}
- if ( (svol->vol->v_path)
- && ! (svol->vol->v_flags & AFPVOL_USEDOTS)
- && (dvol->vol->v_flags & AFPVOL_USEDOTS)) {
- /* source is without dots, destination is with */
- flags |= CONV_UNESCAPEHEX;
- } else if (! (dvol->vol->v_flags & AFPVOL_USEDOTS)) {
- flags |= CONV_ESCAPEDOTS;
- }
-
int len = convert_charset(from,
dvol->vol->v_volcharset,
dvol->vol->v_maccharset,
dnl Check for sendfile()
AC_NETATALK_SENDFILE
+dnl Check whether bundled libevent shall not be used
+AC_NETATALK_LIBEVENT
+
dnl FHS stuff has to be done last because it overrides other defaults
AC_NETATALK_FHS
AM_CONDITIONAL(HAVE_LIBGCRYPT, test x$neta_cv_have_libgcrypt = xyes)
AM_CONDITIONAL(HAVE_OPENSSL, test x$neta_cv_have_openssl = xyes)
AM_CONDITIONAL(HAVE_ACLS, test x"$with_acl_support" = x"yes")
-AM_CONDITIONAL(HAVE_LDAP, test x"$with_ldap" = x"yes")
+AM_CONDITIONAL(HAVE_LDAP, test x"$netatalk_cv_ldap" = x"yes")
AM_CONDITIONAL(USE_DHX, test x$neta_cv_compile_dhx = xyes)
AM_CONDITIONAL(USE_DHX2, test x$neta_cv_compile_dhx2 = xyes)
AM_CONDITIONAL(USE_RANDNUM, test x$neta_cv_have_openssl = xyes)
AM_CONDITIONAL(USE_BDB, test x$bdb_required = xyes)
AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes")
-dnl --------------------- configure subpackages
-AC_CONFIG_SUBDIRS([libevent])
-
dnl --------------------- generate files
AC_OUTPUT([Makefile
bin/Makefile
fi
}
+# code to cause apfd and cnid_metad to restart
+netatalk_graceful() {
+ if [ -x ${NETATALK_SBIN}/netatalk ]; then
+ echo -n $"Restarting cnid_metad and afpd: "
+ killproc netatalk -QUIT
+ RETVAL=$?
+ echo
+ fi
+}
case "$1" in
'start')
status netatalk
RETVAL=$?
;;
+ 'graceful')
+ netatalk_graceful
+ ;;
*)
- echo "Usage: $0 {start|stop|restart|reload|status}"
+ echo "Usage: $0 {start|stop|restart|reload|status|graceful}"
exit 2
esac
afpd_LDADD = \
$(top_builddir)/libatalk/libatalk.la \
- @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@
+ @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@ @KRB5_LIBS@
afpd_LDFLAGS = -export-dynamic
afpd_CFLAGS = \
- @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ \
+ @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ @KRB5_CFLAGS@\
-DAPPLCNAME \
-DSERVERTEXT=\"$(SERVERTEXT)/\" \
-D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
#include "dircache.h"
#ifndef SOL_TCP
-#define SOL_TCP IPPROTO_TCPSOL_TCP
+#define SOL_TCP IPPROTO_TCP
#endif
/*
}
if (obj->options.mimicmodel) {
+ LOG(log_info, logtype_afpd, "Registering server '%s' with model '%s'",
+ dsi->bonjourname, obj->options.mimicmodel);
TXTRecordCreate(&txt_devinfo, 0, NULL);
- TXTRecordPrintf(&txt_devinfo, "model", obj->options.mimicmodel);
+ TXTRecordPrintf(&txt_devinfo, "model=%s", obj->options.mimicmodel);
error = DNSServiceRegister(&svc_refs[svc_ref_count++],
0, // no flags
0, // all network interfaces
DEV_INFO_SERVICE_TYPE,
"", // default domains
NULL, // default host name
- htons(port),
+ 0,
TXTRecordGetLength(&txt_devinfo),
TXTRecordGetBytesPtr(&txt_devinfo),
RegisterReply, // callback
continue;
}
memset(&s_path, 0, sizeof(s_path));
+
+ /* conversions on the fly */
+ const char *convname;
s_path.u_name = sd.sd_last;
- if (of_stat( &s_path) < 0 ) {
- /*
- * Somebody else plays with the dir, well it can be us with
- * "Empty Trash..."
- */
+ if (ad_convert(sd.sd_last, &s_path.st, vol, &convname) == 0 && convname) {
+ s_path.u_name = (char *)convname;
+ }
+ if (of_stat( &s_path) < 0 ) {
/* so the next time it won't try to stat it again
* another solution would be to invalidate the cache with
* sd.sd_did = 0 but if it's not ENOENT error it will start again
continue;
}
+ /* 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));
+ if (s_path.id != CNID_INVALID) {
+ if (cnid_update(vol->v_cdb, s_path.id, &s_path.st, curdir->d_did, convname, strlen(convname)) != 0)
+ LOG(log_error, logtype_afpd, "enumerate: error updating CNID of \"%s\"", fullpathname(convname));
+ }
+ }
+
sd.sd_last += len + 1;
s_path.m_name = NULL;
- /* Convert adouble:v2 to adouble:ea on the fly */
- (void)ad_convert(s_path.u_name, &s_path.st, vol);
-
/*
* If a fil/dir is not a dir, it's a file. This is slightly
* inaccurate, since that means /dev/null is a file, /dev/printer
goto exit;
}
}
- else if (adp && (adcnid != dbcnid)) { /* 4 */
+ else if (adp && adcnid && (adcnid != dbcnid)) { /* 4 */
/* Update the ressource fork. For a folder adp is always null */
LOG(log_debug, logtype_afpd, "get_id(%s/%s): calling ad_setid(old: %u, new: %u)",
getcwdpath(), upath, htonl(adcnid), htonl(dbcnid));
if (ad_setid(adp, st->st_dev, st->st_ino, dbcnid, did, vol->v_stamp)) {
- ad_flush(adp);
+ if (ad_flush(adp) != 0)
+ LOG(log_error, logtype_afpd, "get_id(\"%s\"): can't flush", fullpathname(upath));
}
}
}
*/
int check_name(const struct vol *vol, char *name)
{
- if ((vol->v_flags & AFPVOL_NOHEX) && strchr(name, '/'))
- return AFPERR_PARAM;
-
if (!vol->vfs->vfs_validupath(vol, name)) {
LOG(log_error, logtype_afpd, "check_name: illegal name: '%s'", name);
return AFPERR_EXIST;
an error. we can't do this with translation on. */
#ifdef WITH_SENDFILE
if (!(obj->options.flags & OPTION_NOSENDFILE)) {
- if (dsi_stream_read_file(dsi,
- ad_readfile_init(ofork->of_ad, eid, &offset, 0),
- offset,
- dsi->datasize) < 0) {
- switch (errno) {
+ int fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0);
+ if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) {
+ switch (errno) {
case EINVAL:
case ENOSYS:
goto afp_read_loop;
offset_calc:
/* Calculate and store offset for UTF8ServerName */
- *diroffset += sizeof(uint16_t);
+ if (uam_gss_enabled())
+ *diroffset += sizeof(uint16_t);
offset = htons(data - begin);
memcpy(begin + *diroffset, &offset, sizeof(uint16_t));
const DSI *dsi _U_,
const struct afp_options *options)
{
- char *Obj, *Type, *Zone;
uint16_t namelen;
size_t len;
char *begin = data;
offset = ntohs(offset);
data += offset;
- /* FIXME:
- * What is the valid character range for an nbpname?
- *
- * Apple's server likes to use the non-qualified hostname
- * This obviously won't work very well if multiple servers are running
- * on the box.
- */
+ LOG(log_info, logtype_afpd, "servername: %s", options->hostname);
- /* extract the obj part of the server */
- Obj = options->hostname;
- if ((size_t) -1 == (len = convert_string (
- options->unixcharset, CH_UTF8_MAC,
- Obj, -1, data+sizeof(namelen), maxstatuslen-offset )) ) {
- LOG ( log_error, logtype_afpd, "Could not set utf8 servername");
+ if ((len = convert_string(options->unixcharset,
+ CH_UTF8_MAC,
+ options->hostname,
+ -1,
+ data + sizeof(namelen),
+ maxstatuslen-offset)) == (size_t)-1) {
+ LOG(log_error, logtype_afpd, "Could not set utf8 servername");
/* set offset to 0 */
memset(begin + *nameoffset, 0, sizeof(offset));
* .Parent file here if it doesn't exist. */
/* Convert adouble:v2 to adouble:ea on the fly */
- (void)ad_convert(vol->v_path, st, vol);
+ (void)ad_convert(vol->v_path, st, vol, NULL);
ad_init(&ad, vol);
if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0 ) {
}
/* set conversion flags */
- if (!(myvol->v_flags & AFPVOL_NOHEX))
- flags |= CONV_ESCAPEHEX;
- if (!(myvol->v_flags & AFPVOL_USEDOTS))
- flags |= CONV_ESCAPEDOTS;
-
if ((myvol->v_casefold & AFPVOL_MTOUUPPER))
flags |= CONV_TOUPPER;
else if ((myvol->v_casefold & AFPVOL_MTOULOWER))
return( upath );
}
-/*
- Check for wrong encoding e.g. "." at the beginning is not CAP encoded (:2e) although volume is default !AFPVOL_USEDOTS.
- We do it by roundtripiping from volcharset to UTF8-MAC and back and then compare the result.
-*/
-static int check_name_encoding(char *uname)
-{
- char *roundtripped;
-
- roundtripped = mtoupath(utompath(uname));
- if (!roundtripped) {
- dbd_log( LOGSTD, "Error checking encoding for '%s/%s'", cwdbuf, uname);
- return -1;
- }
-
- if ( STRCMP(uname, !=, roundtripped)) {
- dbd_log( LOGSTD, "Bad encoding for '%s/%s'", cwdbuf, uname);
- return -1;
- }
-
- return 0;
-}
-
/*
Check for netatalk special folders e.g. ".AppleDB" or ".AppleDesktop"
Returns pointer to name or NULL.
return NULL;
}
+/*
+ * We unCAPed a name, update CNID db
+ */
+static int update_cnid(cnid_t did, const struct stat *sp, const char *oldname, const char *newname)
+{
+ int ret;
+ cnid_t id;
+
+ /* Prepare request data */
+ memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
+ memset(&rply, 0, sizeof(struct cnid_dbd_rply));
+ rqst.did = did;
+ rqst.cnid = 0;
+ if ( ! (myvol->v_flags & AFPVOL_NODEV))
+ rqst.dev = sp->st_dev;
+ rqst.ino = sp->st_ino;
+ rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
+ rqst.name = (char *)oldname;
+ rqst.namelen = strlen(oldname);
+
+ /* Query the database */
+ ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0);
+ if (dbif_txn_close(dbd, ret) != 0)
+ return -1;
+ if (rply.result != CNID_DBD_RES_OK)
+ return 0;
+ id = rply.cnid;
+
+ /* Prepare request data */
+ memset(&rqst, 0, sizeof(struct cnid_dbd_rqst));
+ memset(&rply, 0, sizeof(struct cnid_dbd_rply));
+ rqst.did = did;
+ rqst.cnid = id;
+ if ( ! (myvol->v_flags & AFPVOL_NODEV))
+ rqst.dev = sp->st_dev;
+ rqst.ino = sp->st_ino;
+ rqst.type = S_ISDIR(sp->st_mode) ? 1 : 0;
+ rqst.name = (char *)newname;
+ rqst.namelen = strlen(newname);
+
+ /* Update the database */
+ ret = dbd_update(dbd, &rqst, &rply);
+ if (dbif_txn_close(dbd, ret) != 0)
+ return -1;
+ if (rply.result != CNID_DBD_RES_OK)
+ return -1;
+
+ return 0;
+}
+
/*
Check for .AppleDouble file, create if missing
*/
-static int check_adfile(const char *fname, const struct stat *st)
+static int check_adfile(const char *fname, const struct stat *st, const char **newname)
{
int ret;
int adflags = ADFLAGS_HF;
struct adouble ad;
const char *adname;
+ *newname = NULL;
+
if (myvol->v_adouble == AD_VERSION_EA) {
if (!(dbd_flags & DBD_FLAGS_V2TOEA))
return 0;
- if (ad_convert(fname, st, myvol) != 0) {
+ if (ad_convert(fname, st, myvol, newname) != 0) {
switch (errno) {
case ENOENT:
break;
if (STRCMP(ep->d_name, == , ADv2_DIRNAME))
continue;
+ if (!myvol->vfs->vfs_validupath(myvol, ep->d_name)) {
+ dbd_log(LOGDEBUG, "Ignoring \"%s\"", ep->d_name);
+ continue;
+ }
+
if ((ret = lstat(ep->d_name, &st)) < 0) {
dbd_log( LOGSTD, "Lost file while reading dir '%s/%s', probably removed: %s",
cwdbuf, ep->d_name, strerror(errno));
Tests
**************************************************************************/
- /* Check encoding */
- if ( -1 == (encoding_ok = check_name_encoding(ep->d_name)) ) {
- /* If its a file: skipp all other tests now ! */
- /* For dirs we could try to get a CNID for it and recurse, but currently I prefer not to */
- continue;
- }
-
/* Check for appledouble file, create if missing, but only if we have addir */
+ const char *name = NULL;
adfile_ok = -1;
if (ADDIR_OK)
- adfile_ok = check_adfile(ep->d_name, &st);
+ 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 ( ! nocniddb) {
/* Check CNIDs */
- cnid = check_cnid(ep->d_name, did, &st, adfile_ok);
+ cnid = check_cnid(name, did, &st, adfile_ok);
/* Now add this object to our rebuild dbd */
if (cnid && dbd_rebuild) {
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, ep->d_name);
+ cnid, cwdbuf, name);
return -1;
}
count++;
/* Check EA files */
if (myvol->v_vfs_ea == AFPVOL_EA_AD)
- check_eafiles(ep->d_name);
+ check_eafiles(name);
/**************************************************************************
Recursion
**************************************************************************/
if (S_ISDIR(st.st_mode) && (cnid || nocniddb)) { /* If we have no cnid for it we cant recur */
strcat(cwdbuf, "/");
- strcat(cwdbuf, ep->d_name);
+ strcat(cwdbuf, name);
dbd_log( LOGDEBUG, "Entering directory: %s", cwdbuf);
if (-1 == (cwd = open(".", O_RDONLY))) {
dbd_log( LOGSTD, "Cant open directory '%s': %s", cwdbuf, strerror(errno));
continue;
}
- if (0 != chdir(ep->d_name)) {
+ if (0 != chdir(name)) {
dbd_log( LOGSTD, "Cant chdir to directory '%s': %s", cwdbuf, strerror(errno));
close(cwd);
continue;
if ((myvol->v_adouble == AD_VERSION_EA) && (dbd_flags & DBD_FLAGS_V2TOEA)) {
if (lstat(".", &st) != 0)
return -1;
- if (ad_convert(".", &st, vol) != 0) {
+ if (ad_convert(".", &st, vol, NULL) != 0) {
switch (errno) {
case ENOENT:
break;
int ret;
DBD *dbd;
- LOG(log_debug, logtype_cnid, "Reopening BerkeleyDB environment");
+ LOG(log_debug, logtype_cnid, "Trying to remove BerkeleyDB environment");
+
+ if (get_lock(LOCK_EXCL, path) != LOCK_EXCL) {
+ LOG(log_warning, logtype_cnid, "CNID db \"%s\" in use, can't remove BerkeleyDB environment", path);
+ return 0;
+ }
if (NULL == (dbd = dbif_init(path, "cnid2.db")))
return -1;
netatalk_SOURCES = netatalk.c
netatalk_CFLAGS = \
- -I$(top_srcdir)/libevent/include \
- -I$(top_builddir)/libevent/include \
-D_PATH_CONFDIR=\"$(pkgconfdir)/\" \
-D_PATH_AFPD=\"$(sbindir)/afpd\" \
-D_PATH_CNID_METAD=\"$(sbindir)/cnid_metad\"
netatalk_LDADD = \
- $(top_builddir)/libatalk/libatalk.la \
+ $(top_builddir)/libatalk/libatalk.la
+
+if USE_BUILTIN_LIBEVENT
+netatalk_CFLAGS += \
+ -I$(top_srcdir)/libevent/include \
+ -I$(top_builddir)/libevent/include
+
+netatalk_LDADD += \
$(top_builddir)/libevent/libevent.la
+endif
\ No newline at end of file
static pid_t afpd_pid = -1, cnid_metad_pid = -1;
static uint afpd_restarts, cnid_metad_restarts;
static struct event_base *base;
-struct event *sigterm_ev, *sigquit_ev, *sigchld_ev;
+struct event *sigterm_ev, *sigquit_ev, *sigchld_ev, *timer_ev;
static int in_shutdown;
/******************************************************************
/* SIGTERM callback */
static void sigterm_cb(evutil_socket_t fd, short what, void *arg)
{
- LOG(log_note, logtype_afpd, "Exiting on SIGTERM");
+ sigset_t sigs;
+ struct timeval tv;
+
+ LOG(log_info, logtype_afpd, "Exiting on SIGTERM");
+
+ if (in_shutdown)
+ return;
in_shutdown = 1;
- event_base_loopbreak(base);
+
+ /* block any signal but SIGCHLD */
+ sigfillset(&sigs);
+ sigdelset(&sigs, SIGCHLD);
+ sigprocmask(SIG_SETMASK, &sigs, NULL);
+
+ /* add 10 sec timeout timer, remove all events but SIGCHLD */
+ tv.tv_sec = KILL_GRACETIME;
+ tv.tv_usec = 0;
+ event_base_loopexit(base, &tv);
+ event_del(sigterm_ev);
+ event_del(sigquit_ev);
+ event_del(timer_ev);
+
+ kill_childs(SIGTERM, &afpd_pid, &cnid_metad_pid, NULL);
}
/* SIGQUIT callback */
LOG(log_info, logtype_afpd, "child[%d]: died", pid);
}
- if (pid == afpd_pid) {
- if (in_shutdown) {
- afpd_pid = -1;
- } else {
- sleep(1);
- afpd_restarts++;
- LOG(log_note, logtype_afpd, "Restarting 'afpd' (restarts: %u)", afpd_restarts);
- if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
- LOG(log_error, logtype_afpd, "Error starting 'afpd'");
- }
- }
- } else if (pid = cnid_metad_pid) {
- if (in_shutdown) {
- cnid_metad_pid = -1;
- } else {
- sleep(1);
- cnid_metad_restarts++;
- LOG(log_note, logtype_afpd, "Restarting 'cnid_metad' (restarts: %u)", cnid_metad_restarts);
- if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
- LOG(log_error, logtype_afpd, "Error starting 'cnid_metad'");
- }
- }
- } else {
+ if (pid == afpd_pid)
+ afpd_pid = -1;
+ else if (pid = cnid_metad_pid)
+ cnid_metad_pid = -1;
+ else
LOG(log_error, logtype_afpd, "Bad pid: %d", pid);
- }
}
if (in_shutdown && afpd_pid == -1 && cnid_metad_pid == -1)
event_base_loopbreak(base);
}
+/* timer callback */
+static void timer_cb(evutil_socket_t fd, short what, void *arg)
+{
+ static int i = 0;
+ LOG(log_debug, logtype_afpd, "looping: %i", i++);
+
+ if (in_shutdown)
+ return;
+
+ if (afpd_pid == -1) {
+ afpd_restarts++;
+ LOG(log_note, logtype_afpd, "Restarting 'afpd' (restarts: %u)", afpd_restarts);
+ if ((afpd_pid = run_process(_PATH_AFPD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
+ LOG(log_error, logtype_afpd, "Error starting 'afpd'");
+ }
+ }
+
+ if (cnid_metad_pid == -1) {
+ cnid_metad_restarts++;
+ LOG(log_note, logtype_afpd, "Restarting 'cnid_metad' (restarts: %u)", cnid_metad_restarts);
+ if ((cnid_metad_pid = run_process(_PATH_CNID_METAD, "-d", "-F", obj.options.configfile, NULL)) == -1) {
+ LOG(log_error, logtype_afpd, "Error starting 'cnid_metad'");
+ }
+ }
+}
+
/******************************************************************
* helper functions
******************************************************************/
const char *configfile = NULL;
int c, ret, debug = 0;
sigset_t blocksigs;
+ struct timeval tv;
/* Log SIGBUS/SIGSEGV SBT */
fault_setup(NULL);
sigterm_ev = event_new(base, SIGTERM, EV_SIGNAL, sigterm_cb, NULL);
sigquit_ev = event_new(base, SIGQUIT, EV_SIGNAL | EV_PERSIST, sigquit_cb, NULL);
sigchld_ev = event_new(base, SIGCHLD, EV_SIGNAL | EV_PERSIST, sigchld_cb, NULL);
+ timer_ev = event_new(base, -1, EV_PERSIST, timer_cb, NULL);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
event_add(sigterm_ev, NULL);
event_add(sigquit_ev, NULL);
event_add(sigchld_ev, NULL);
+ event_add(timer_ev, &tv);
sigfillset(&blocksigs);
sigdelset(&blocksigs, SIGTERM);
/* run the event loop */
ret = event_base_dispatch(base);
- /* got SIGTERM so we're going to shutdown */
-
- /* block any signal but SIGCHLD */
- sigfillset(&blocksigs);
- sigdelset(&blocksigs, SIGCHLD);
- sigprocmask(SIG_SETMASK, &blocksigs, NULL);
-
- /* setup new events: remove SIGTERM and SIGQUIT cbs, add timeout */
- struct timeval tv;
- tv.tv_sec = KILL_GRACETIME;
- tv.tv_usec = 0;
- event_base_loopexit(base, &tv);
- event_del(sigterm_ev);
- event_del(sigquit_ev);
-
- /* run the event loop again, waiting for child to exit on SIGTERM for KILL_GRACETIME seconds */
- kill_childs(SIGTERM, &afpd_pid, &cnid_metad_pid, NULL);
- ret = event_base_dispatch(base);
-
if (afpd_pid != -1 || cnid_metad_pid != -1) {
if (afpd_pid != -1)
LOG(log_error, logtype_afpd, "AFP service did not shutdown, killing it");
LOG(log_error, logtype_afpd, "CNID database service did not shutdown, killing it");
kill_childs(SIGKILL, &afpd_pid, &cnid_metad_pid, NULL);
}
+
+ LOG(log_note, logtype_afpd, "Netatalk AFP server exiting");
+
netatalk_exit(ret);
}
extern int ad_metadata (const char *, int, struct adouble *);
extern int ad_metadataat (int, const char *, int, struct adouble *);
extern mode_t ad_hf_mode(mode_t mode);
-extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol);
extern int ad_valid_header_osx(const char *path);
+
+/* ad_conv.c */
+extern int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath);
+
/* ad_read.c/ad_write.c */
extern int sys_ftruncate(int fd, off_t length);
extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
#define PASSWD_NOSAVE (1 << 1)
#define PASSWD_ALL (PASSWD_SET | PASSWD_NOSAVE)
+#define IS_AFP_SESSION(obj) ((obj)->dsi && (obj)->dsi->serversock == -1)
+
/**********************************************************************************************
* Ini config sections
**********************************************************************************************/
Keep in sync with libatalk/util/volinfo.c
*/
#define AFPVOL_NOV2TOEACONV (1 << 5) /* no adouble:v2 to adouble:ea conversion */
-#define AFPVOL_UNIX_CTXT (1 << 6) /* volume created by getvolbypath ie UNIX access, not afpd AFP user session */
#define AFPVOL_RO (1 << 8) /* read-only volume */
-#define AFPVOL_NOHEX (1 << 10) /* don't do :hex translation */
-#define AFPVOL_USEDOTS (1 << 11) /* use real dots */
#define AFPVOL_NOSTAT (1 << 16) /* advertise the volume even if we can't stat() it
* maybe because it will be mounted later in preexec */
#define AFPVOL_UNIX_PRIV (1 << 17) /* support unix privileges */
noinst_LTLIBRARIES = libacl.la
libacl_la_SOURCES = cache.c unix.c uuid.c
libacl_la_LDFLAGS =
+libacl_la_LIBADD =
if HAVE_LDAP
libacl_la_SOURCES += ldap.c ldap_config.c
-libacl_la_LDFLAGS += -lldap
+libacl_la_LIBADD += @LDAP_LIBS@
+libacl_la_LDFLAGS += @LDAP_LDLFLAGS@
endif
noinst_LTLIBRARIES = libadouble.la
-libadouble_la_SOURCES = ad_open.c ad_flush.c ad_read.c ad_write.c ad_size.c \
- ad_mmap.c ad_lock.c ad_date.c ad_attr.c ad_sendfile.c
+libadouble_la_SOURCES = \
+ ad_attr.c \
+ ad_conv.c \
+ ad_date.c \
+ ad_flush.c \
+ ad_lock.c \
+ ad_mmap.c \
+ ad_open.c \
+ ad_read.c \
+ ad_sendfile.c \
+ ad_size.c \
+ ad_write.c
noinst_HEADERS = ad_lock.h
--- /dev/null
+/*
+ * Copyright (c) 2012 Frank Lahm
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*!
+ * @file
+ * Part of Netatalk's AppleDouble implementatation
+ * @sa include/atalk/adouble.h
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <errno.h>
+#include <sys/param.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <arpa/inet.h>
+
+#include <atalk/logger.h>
+#include <atalk/adouble.h>
+#include <atalk/util.h>
+#include <atalk/unix.h>
+#include <atalk/ea.h>
+#include <atalk/bstrlib.h>
+#include <atalk/bstradd.h>
+#include <atalk/compat.h>
+#include <atalk/errchk.h>
+#include <atalk/volume.h>
+
+#include "ad_lock.h"
+
+static char emptyfilad[32] = {0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0};
+
+static char emptydirad[32] = {0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0};
+
+static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol)
+{
+ EC_INIT;
+ struct adouble adv2;
+ struct adouble adea;
+ const char *adpath;
+ int adflags;
+ uint32_t ctime, mtime, afpinfo = 0;
+ char *emptyad;
+
+ LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
+
+ ad_init(&adea, vol);
+ ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
+ adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+
+ /* Open and lock adouble:v2 file */
+ EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) );
+
+ EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
+ EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) );
+
+ /* Check if it's a non-empty header */
+ if (S_ISREG(sp->st_mode))
+ emptyad = &emptyfilad[0];
+ else
+ emptyad = &emptydirad[0];
+
+ if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0)
+ goto copy;
+ if (ad_getentryoff(&adv2, ADEID_FINDERI)
+ && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI)
+ && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0))
+ goto copy;
+ if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) {
+ EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) );
+ EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) );
+ if ((ctime != mtime) || (mtime != sp->st_mtime))
+ goto copy;
+ }
+ if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) {
+ if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0)
+ goto copy;
+ }
+
+ LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
+ goto EC_CLEANUP;
+
+copy:
+ /* Create a adouble:ea meta EA */
+ LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
+ EC_ZERO_LOGSTR( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE),
+ "ad_conv_v22ea_hf(\"%s\"): error creating metadata EA: %s",
+ fullpathname(path), strerror(errno));
+ EC_ZERO_LOG( ad_copy_header(&adea, &adv2) );
+ ad_flush(&adea);
+
+EC_CLEANUP:
+ EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
+ EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
+ LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret);
+ EC_EXIT;
+}
+
+static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol)
+{
+ EC_INIT;
+ struct adouble adv2;
+ struct adouble adea;
+
+ LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
+
+ if (S_ISDIR(sp->st_mode))
+ return 0;
+
+ ad_init(&adea, vol);
+ ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
+
+ /* Open and lock adouble:v2 file */
+ EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) );
+
+ if (adv2.ad_rlen > 0) {
+ EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
+
+ /* Create a adouble:ea resource fork */
+ EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) );
+
+ EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) );
+ adea.ad_rlen = adv2.ad_rlen;
+ ad_flush(&adea);
+ }
+
+EC_CLEANUP:
+ EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) );
+ EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) );
+ LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret);
+ EC_EXIT;
+}
+
+static int ad_conv_v22ea(const char *path, const struct stat *sp, const struct vol *vol)
+{
+ EC_INIT;
+ const char *adpath;
+ int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+
+ become_root();
+
+ EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
+ EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
+
+ EC_NULL( adpath = ad_path(path, adflags) );
+ LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
+ path, fullpathname(adpath));
+
+ unlink(adpath);
+
+EC_CLEANUP:
+ if (errno == ENOENT)
+ EC_STATUS(0);
+
+ unbecome_root();
+
+ EC_EXIT;
+}
+
+/*!
+ * Remove hexencoded dots and slashes (":2e" and ":2f")
+ */
+static int ad_conv_dehex(const char *path, const struct stat *sp, const struct vol *vol, const char **newpathp)
+{
+ EC_INIT;
+ static char buf[MAXPATHLEN];
+ const char *adpath, *p;
+ int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
+ bstring newpath = NULL;
+
+ LOG(log_debug, logtype_default,"ad_conv_dehex(\"%s\"): BEGIN", fullpathname(path));
+
+ *newpathp = NULL;
+
+ if ((p = strchr(path, ':')) == NULL)
+ goto EC_CLEANUP;
+
+ EC_NULL( newpath = bfromcstr(path) );
+
+ EC_ZERO( bfindreplace(newpath, bfromcstr(":2e"), bfromcstr("."), 0) );
+ EC_ZERO( bfindreplace(newpath, bfromcstr(":2f"), bfromcstr(":"), 0) );
+
+ become_root();
+ if (adflags != ADFLAGS_DIR)
+ rename(vol->ad_path(path, 0), vol->ad_path(bdata(newpath), 0));
+ rename(path, bdata(newpath));
+ unbecome_root();
+
+ strlcpy(buf, bdata(newpath), sizeof(buf));
+ *newpathp = buf;
+
+EC_CLEANUP:
+ if (newpath)
+ bdestroy(newpath);
+ EC_EXIT;
+}
+
+/*!
+ * AppleDouble and encoding conversion on the fly
+ *
+ * @param path (r) path to file or directory
+ * @param sp (r) stat(path)
+ * @param vol (r) volume handle
+ * @param newpath (w) if encoding changed, new name. Can be NULL.
+ *
+ * @returns -1 on internal error, otherwise 0. newpath is NULL if no character conversion was done,
+ * otherwise newpath points to a static string with the converted name
+ */
+int ad_convert(const char *path, const struct stat *sp, const struct vol *vol, const char **newpath)
+{
+ EC_INIT;
+ const char *p;
+
+ LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
+
+ if (newpath)
+ *newpath = NULL;
+
+ if ((vol->v_adouble == AD_VERSION_EA) && !(vol->v_flags & AFPVOL_NOV2TOEACONV))
+ EC_ZERO( ad_conv_v22ea(path, sp, vol) );
+
+ if (vol->v_adouble == AD_VERSION_EA) {
+ EC_ZERO( ad_conv_dehex(path, sp, vol, &p) );
+ if (p && newpath)
+ *newpath = p;
+ }
+
+EC_CLEANUP:
+ LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
+ EC_EXIT;
+}
+
return oflags;
}
-static char emptyfilad[32] = {0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0};
-
-static char emptydirad[32] = {0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,1,0,
- 0,0,0,0,0,0,0,0,
- 0,0,0,0,0,0,0,0};
-
-static int ad_conv_v22ea_hf(const char *path, const struct stat *sp, const struct vol *vol)
-{
- EC_INIT;
- struct adouble adv2;
- struct adouble adea;
- const char *adpath;
- int adflags;
- uint32_t ctime, mtime, afpinfo = 0;
- char *emptyad;
-
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): BEGIN", fullpathname(path));
-
- ad_init(&adea, vol);
- ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
- adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
-
- /* Open and lock adouble:v2 file */
- EC_ZERO( ad_open(&adv2, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR) );
- EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
- EC_NEG1_LOG( adv2.ad_ops->ad_header_read(path, &adv2, sp) );
-
- /* Check if it's a non-empty header */
- if (S_ISREG(sp->st_mode))
- emptyad = &emptyfilad[0];
- else
- emptyad = &emptydirad[0];
-
- if (ad_getentrylen(&adv2, ADEID_COMMENT) != 0)
- goto copy;
- if (ad_getentryoff(&adv2, ADEID_FINDERI)
- && (ad_getentrylen(&adv2, ADEID_FINDERI) == ADEDLEN_FINDERI)
- && (memcmp(ad_entry(&adv2, ADEID_FINDERI), emptyad, ADEDLEN_FINDERI) != 0))
- goto copy;
- if (ad_getentryoff(&adv2, ADEID_FILEDATESI)) {
- EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_CREATE | AD_DATE_UNIX, &ctime) );
- EC_ZERO_LOG( ad_getdate(&adv2, AD_DATE_MODIFY | AD_DATE_UNIX, &mtime) );
- if ((ctime != mtime) || (mtime != sp->st_mtime))
- goto copy;
- }
- if (ad_getentryoff(&adv2, ADEID_AFPFILEI)) {
- if (memcmp(ad_entry(&adv2, ADEID_AFPFILEI), &afpinfo, ADEDLEN_AFPFILEI) != 0)
- goto copy;
- }
-
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): default adouble", fullpathname(path), ret);
- goto EC_CLEANUP;
-
-copy:
- /* Create a adouble:ea meta EA */
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): copying adouble", fullpathname(path), ret);
- EC_ZERO_LOG( ad_open(&adea, path, adflags | ADFLAGS_HF | ADFLAGS_RDWR | ADFLAGS_CREATE) );
- EC_ZERO_LOG( ad_copy_header(&adea, &adv2) );
- ad_flush(&adea);
-
-EC_CLEANUP:
- EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
- EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_SETSHRMD) );
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): END: %d", fullpathname(path), ret);
- EC_EXIT;
-}
-
-static int ad_conv_v22ea_rf(const char *path, const struct stat *sp, const struct vol *vol)
-{
- EC_INIT;
- struct adouble adv2;
- struct adouble adea;
-
- LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): BEGIN", fullpathname(path));
-
- if (S_ISDIR(sp->st_mode))
- return 0;
-
- ad_init(&adea, vol);
- ad_init_old(&adv2, AD_VERSION2, adea.ad_options);
-
- /* Open and lock adouble:v2 file */
- EC_ZERO( ad_open(&adv2, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR) );
- if (adv2.ad_rlen > 0) {
- EC_NEG1_LOG( ad_tmplock(&adv2, ADEID_RFORK, ADLOCK_WR | ADLOCK_FILELOCK, 0, 0, 0) );
-
- /* Create a adouble:ea resource fork */
- EC_ZERO_LOG( ad_open(&adea, path, ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) );
-
- EC_ZERO_LOG( copy_fork(ADEID_RFORK, &adea, &adv2) );
- adea.ad_rlen = adv2.ad_rlen;
- ad_flush(&adea);
- }
-
-EC_CLEANUP:
- EC_ZERO_LOG( ad_close(&adv2, ADFLAGS_HF | ADFLAGS_RF) );
- EC_ZERO_LOG( ad_close(&adea, ADFLAGS_HF | ADFLAGS_RF) );
- LOG(log_debug, logtype_default,"ad_conv_v22ea_rf(\"%s\"): END: %d", fullpathname(path), ret);
- EC_EXIT;
-}
-
static int ad_open_df(const char *path, int adflags, mode_t mode, struct adouble *ad)
{
EC_INIT;
return ret;
}
-int ad_convert(const char *path, const struct stat *sp, const struct vol *vol)
-{
- EC_INIT;
- const char *adpath;
- int adflags = S_ISDIR(sp->st_mode) ? ADFLAGS_DIR : 0;
-
- LOG(log_debug, logtype_default,"ad_convert(\"%s\"): BEGIN", fullpathname(path));
-
- if (!(vol->v_adouble == AD_VERSION_EA) || (vol->v_flags & AFPVOL_NOV2TOEACONV))
- goto EC_CLEANUP;
-
- EC_ZERO( ad_conv_v22ea_hf(path, sp, vol) );
- EC_ZERO( ad_conv_v22ea_rf(path, sp, vol) );
-
- EC_NULL( adpath = ad_path(path, adflags) );
- LOG(log_debug, logtype_default,"ad_conv_v22ea_hf(\"%s\"): deleting adouble:v2 file: \"%s\"",
- path, fullpathname(adpath));
-
- become_root();
- EC_ZERO_LOG( unlink(adpath) );
- unbecome_root();
-
-EC_CLEANUP:
- LOG(log_debug, logtype_default,"ad_convert(\"%s\"): END: %d", fullpathname(path), ret);
- EC_EXIT;
-}
-
/* build a resource fork mode from the data fork mode:
* remove X mode and extend header to RW if R or W (W if R for locking),
*/
/* get rid of some stuff */
close(dsi->serversock);
+ dsi->serversock = -1;
server_child_free(serv_children);
switch (dsi->header.dsi_command) {
o_len=destlen;
while (i_len > 0) {
- if ((option & CONV_UNESCAPEHEX)) {
- for (j = 0; j < i_len; ++j) {
- if (inbuf[j] == ':') break;
- }
- j = i_len - j;
- i_len -= j;
- }
+ for (j = 0; j < i_len; ++j)
+ if (inbuf[j] == ':')
+ break;
+ j = i_len - j;
+ i_len -= j;
if (i_len > 0 &&
atalk_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len) == (size_t)-1) {
}
if (j) {
- /* we're at the start on an hex encoded ucs2 char */
- char h[MAXPATHLEN];
- size_t hlen = 0;
-
+ /* we have a ':' */
i_len = j, j = 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 ((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;
- }
- goto end;
+ /* 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--;
}
}
}
}
while (i_len >= 2) {
- if ((option & CONV_ESCAPEHEX)) {
- 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 = '/' */
- escch = c;
- j = i_len - i;
- i_len = i;
- break;
+ 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 = '/' */
+ escch = c;
+ j = i_len - i;
+ i_len = i;
+ break;
}
}
while (i_len > 0 &&
}
if (j) {
+ /* we have a ':' or '/' */
i_len = j, j = 0;
- 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;
+
+ 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;
}
- o_len -= 3;
- inbuf += 2;
- i_len -= 2;
}
}
if (i_len > 0) errno = EINVAL;
q++;
}
} else if (IS_VAR(p, "$c")) {
- DSI *dsi = obj->dsi;
- len = sprintf(dest, "%s:%u",
- getip_string((struct sockaddr *)&dsi->client),
- getip_port((struct sockaddr *)&dsi->client));
- dest += len;
- destlen -= len;
+ if (IS_AFP_SESSION(obj)) {
+ DSI *dsi = obj->dsi;
+ len = sprintf(dest, "%s:%u",
+ getip_string((struct sockaddr *)&dsi->client),
+ getip_port((struct sockaddr *)&dsi->client));
+ dest += len;
+ destlen -= len;
+ }
} else if (IS_VAR(p, "$d")) {
q = path;
} else if (pwd && IS_VAR(p, "$f")) {
q = getip_string((struct sockaddr *)&dsi->client);
} else if (IS_VAR(p, "$s")) {
q = obj->options.hostname;
- } else if (obj->username && IS_VAR(p, "$u")) {
+ } else if (obj->username[0] && IS_VAR(p, "$u")) {
char* sep = NULL;
if ( obj->options.ntseparator && (sep = strchr(obj->username, obj->options.ntseparator[0])) != NULL)
q = sep+1;
if (getoption_bool(obj->iniconfig, section, "read only", preset, 0))
volume->v_flags |= AFPVOL_RO;
- if (!getoption_bool(obj->iniconfig, section, "hex encoding", preset, 1))
- volume->v_flags |= AFPVOL_NOHEX;
- if (getoption_bool(obj->iniconfig, section, "use dots", preset, 1))
- volume->v_flags |= AFPVOL_USEDOTS;
if (getoption_bool(obj->iniconfig, section, "invisible dots", preset, 0))
volume->v_flags |= AFPVOL_INV_DOTS;
if (!getoption_bool(obj->iniconfig, section, "stat vol", preset, 1))
volume->v_ad_options |= ADVOL_INVDOTS;
/* Mac to Unix conversion flags*/
- if (!(volume->v_flags & AFPVOL_NOHEX))
- volume->v_mtou_flags |= CONV_ESCAPEHEX;
- if (!(volume->v_flags & AFPVOL_USEDOTS))
- volume->v_mtou_flags |= CONV_ESCAPEDOTS;
if ((volume->v_flags & AFPVOL_EILSEQ))
volume->v_mtou_flags |= CONV__EILSEQ;
volume->v_mtou_flags |= CONV_TOLOWER;
/* Unix to Mac conversion flags*/
- volume->v_utom_flags = CONV_IGNORE | CONV_UNESCAPEHEX;
+ volume->v_utom_flags = CONV_IGNORE;
if ((volume->v_casefold & AFPVOL_UTOMUPPER))
volume->v_utom_flags |= CONV_TOUPPER;
else if ((volume->v_casefold & AFPVOL_UTOMLOWER))
static int readvolfile(AFPObj *obj, const struct passwd *pwent)
{
EC_INIT;
+ static int regexerr = -1;
+ static regex_t reg;
char path[MAXPATHLEN + 1];
char volname[AFPVOL_U8MNAMELEN + 1];
char tmp[MAXPATHLEN + 1];
- const char *preset, *default_preset, *p;
+ const char *preset, *default_preset, *p, *basedir;
char *q, *u;
int i;
struct passwd *pw;
+ regmatch_t match[1];
LOG(log_debug, logtype_afpd, "readvolfile: BEGIN");
continue;
if (STRCMP(secname, ==, INISEC_HOMES)) {
have_uservol = 1;
- if (obj->username[0] == 0
+ if (!IS_AFP_SESSION(obj)
|| strcmp(obj->username, obj->options.guest) == 0)
/* not an AFP session, but cnid daemon, dbd or ad util, or guest login */
continue;
+ if (pwent->pw_dir == NULL || STRCMP("", ==, pwent->pw_dir))
+ /* no user home */
+ continue;
+
+ /* check if user home matches our "basedir regex" */
+ if ((basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL)
+ continue;
+ LOG(log_debug, logtype_afpd, "readvolfile: basedir regex: '%s'", basedir);
+
+ if (regexerr != 0 && (regexerr = regcomp(®, basedir, REG_EXTENDED)) != 0) {
+ char errbuf[1024];
+ regerror(regexerr, ®, errbuf, sizeof(errbuf));
+ LOG(log_debug, logtype_default, "readvolfile: bad basedir regex: %s", errbuf);
+ }
+
+ if (regexec(®, pwent->pw_dir, 1, match, 0) == REG_NOMATCH) {
+ LOG(log_debug, logtype_default, "readvolfile: user home \"%s\" doesn't match basedir regex \"%s\"",
+ pwent->pw_dir, basedir);
+ continue;
+ }
+
strlcpy(tmp, pwent->pw_dir, MAXPATHLEN);
strlcat(tmp, "/", MAXPATHLEN);
if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "path", NULL))
goto EC_CLEANUP;
have_uservol = 0;
for (vol = Volumes; vol; vol = vol->v_next) {
- if (vol->v_flags & AFPVOL_UNIX_CTXT)
- continue;
vol->v_deleted = 1;
}
} else {
struct vol *getvolbypath(AFPObj *obj, const char *path)
{
EC_INIT;
+ static int regexerr = -1;
+ static regex_t reg;
struct vol *vol;
struct vol *tmp;
const struct passwd *pw;
char tmpbuf[MAXPATHLEN + 1];
const char *secname, *basedir, *p = NULL, *subpath = NULL, *subpathconfig;
char *user = NULL, *prw;
- int regexerr = -1;
- static regex_t reg;
regmatch_t match[1];
LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\")", path);
if (prw != 0)
subpath = prw;
- strlcpy(obj->username, user, MAXUSERLEN);
strlcat(tmpbuf, user, MAXPATHLEN);
+ strlcat(obj->username, user, MAXUSERLEN);
strlcat(tmpbuf, "/", MAXPATHLEN);
/* (6) */
if (name[0] != '.')
return 1;
- if (!(vol->v_flags & AFPVOL_USEDOTS))
- return 0;
-
return netatalk_name(name) && strcmp(name,".AppleDouble") && strcasecmp(name,".Parent");
}
if (name[0] != '.')
return 1;
- if (!(vol->v_flags & AFPVOL_USEDOTS))
- return 0;
-
#ifndef HAVE_EAFD
if (name[1] == '_')
return ad_valid_header_osx(name);
)
if test x"$compilegssapi" != x"no"; then
-
- if test "x$compilegssapi" != "xyes" -a "x$compilegssapi" != "xauto"; then
- GSSAPI_CFLAGS="-I$withval/include"
- GSSAPI_CPPFLAGS="-I$withval/include"
- GSSAPI_LDFLAGS="-L$withval/${atalk_libname}"
- FOUND_GSSAPI=yes
+ if test "x$compilegssapi" != "xyes" -a "x$compilegssapi" != "xauto"; then
+ GSSAPI_CFLAGS="-I$withval/include"
+ GSSAPI_CPPFLAGS="-I$withval/include"
+ GSSAPI_LDFLAGS="-L$withval/${atalk_libname}"
+ FOUND_GSSAPI=yes
AC_MSG_CHECKING([checking for GSSAPI support in])
AC_MSG_RESULT([$compilegssapi])
- fi
+ fi
# Do no harm to the values of CFLAGS and LIBS while testing for
AC_PATH_PROG(KRB5_CONFIG, krb5-config)
AC_MSG_CHECKING(for working krb5-config)
if test -x "$KRB5_CONFIG"; then
+ CFLAGS=""; export CFLAGS
+ LDFLAGS=""; export LDFLAGS
TEMP="`$KRB5_CONFIG --libs gssapi`"
if test $? -eq 0 ; then
- save_CFLAGS=$CFLAGS
- CFLAGS="";export CFLAGS
- save_LDFLAGS=$LDFLAGS
- LDFLAGS="";export LDFLAGS
GSSAPI_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
GSSAPI_CPPFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
GSSAPI_LIBS="$TEMP"
- CFLAGS=$save_CFLAGS;export CFLAGS
- LDFLAGS=$save_LDFLAGS;export LDFLAGS
FOUND_GSSAPI=yes
AC_MSG_RESULT(yes)
else
AC_MSG_RESULT(no. Fallback to previous krb5 detection strategy)
fi
+ CFLAGS=$save_CFLAGS; export CFLAGS
+ LDFLAGS=$save_LDFLAGS; export LDFLAGS
else
AC_MSG_RESULT(no. Fallback to previous krb5 detection strategy)
fi
fi
fi
- CFLAGS="$CFLAGS $GSSAPI_CFLAGS"
- CPPFLAGS="$CPPFLAGS $GSSAPI_CPPFLAGS"
- LDFLAGS="$LDFLAGS $GSSAPI_LDFLAGS"
- LIBS="$LIBS $GSSAPI_LIBS"
-
+ CFLAGS="$GSSAPI_CFLAGS"
+ CPPFLAGS="$GSSAPI_CPPFLAGS"
+ LDFLAGS="$GSSAPI_LDFLAGS"
+ LIBS="$GSSAPI_LIBS"
# check for gssapi headers
if test x"$ac_cv_func_gss_acquire_cred" = x"yes"; then
AC_DEFINE(HAVE_GSSAPI,1,[Whether to enable GSSAPI support])
AC_MSG_RESULT([yes])
- GSSAPI_LIBS="$LDFLAGS $LIBS"
+# GSSAPI_LIBS="$LDFLAGS $LIBS"
else
AC_MSG_RESULT([no])
if test x"$compilegssapi" = x"yes"; then
dnl Kitchen sink for configuration macros
+dnl Whether to disable bundled libevent
+AC_DEFUN([AC_NETATALK_LIBEVENT], [
+ AC_MSG_CHECKING([whether to disable bundled libevent (define CPPFLAGS and LDFLAGS otherwise appropiately to pick up installed version)])
+ AC_ARG_ENABLE(
+ bundled-libevent,
+ [AC_HELP_STRING(
+ [--disable-bundled-libevent],
+ [whether the bundled version of libevent shall not be used (define CPPFLAGS and LDFLAGS otherwise appropiately to pick up installed version)]
+ )],
+ use_bundled_libevent=$enableval,
+ use_bundled_libevent=yes
+ )
+
+ if test x"$use_bundled_libevent" = x"yes" ; then
+ AC_CONFIG_SUBDIRS([libevent])
+ fi
+ AM_CONDITIONAL(USE_BUILTIN_LIBEVENT, test x"$use_bundled_libevent" = x"yes")
+])
+
dnl Filesystem Hierarchy Standard (FHS) compatibility
AC_DEFUN([AC_NETATALK_FHS], [
AC_MSG_CHECKING([whether to use Filesystem Hierarchy Standard (FHS) compatibility])
AC_SUBST(KLDFLAGS)
fi
+dnl Whether to run ldconfig after installing libraries
+AC_PATH_PROG(NETA_LDCONFIG, ldconfig, , [$PATH$PATH_SEPARATOR/sbin$PATH_SEPARATOR/bin$PATH_SEPARATOR/usr/sbin$PATH_SEPARATOR/usr/bin])
+echo NETA_LDCONFIG = $NETA_LDCONFIG
+AM_CONDITIONAL(RUN_LDCONFIG, test x"$this_os" = x"linux" -a x"$NETA_LDCONFIG" != x"")
])
dnl Check for building PGP UAM module
AM_CONDITIONAL(USE_GSSAPI, test x"$netatalk_cv_build_krb5_uam" = x"yes")
])
+dnl Check if we can directly use Kerberos 5 API, used for reading keytabs
+dnl and automatically construction DirectoryService names from that, instead
+dnl of requiring special configuration in afp.conf
AC_DEFUN([AC_NETATALK_KERBEROS], [
AC_MSG_CHECKING([for Kerberos 5 (necessary for GetSrvrInfo:DirectoryNames support)])
AC_ARG_WITH([kerberos],
AC_MSG_CHECKING([for krb5-config])
if test -x "$KRB5_CONFIG"; then
AC_MSG_RESULT([$KRB5_CONFIG])
- CFLAGS="$CFLAGS `$KRB5_CONFIG --cflags krb5`"
- LIBS="`$KRB5_CONFIG --libs krb5` $LIBS"
+ KRB5_CFLAGS="`$KRB5_CONFIG --cflags krb5`"
+ KRB5_LIBS="`$KRB5_CONFIG --libs krb5`"
+ AC_SUBST(KRB5_CFLAGS)
+ AC_SUBST(KRB5_LIBS)
with_kerberos="yes"
else
AC_MSG_RESULT([not found])
AC_ARG_WITH(ldap,
[AS_HELP_STRING([--with-ldap],
[LDAP support (default=auto)])],
- [ case "$withval" in
- yes|no)
- with_ldap="$withval"
- ;;
- *)
- with_ldap=auto
- ;;
- esac ])
-AC_MSG_RESULT($with_ldap)
+ netatalk_cv_ldap=$withval,
+ netatalk_cv_ldap=auto
+ )
+AC_MSG_RESULT($netatalk_cv_ldap)
-if test x"$with_ldap" != x"no" ; then
- AC_CHECK_HEADER([ldap.h], with_ldap=yes,
- [ if test x"$with_ldap" = x"yes" ; then
+save_CFLAGS=$CFLAGS
+save_LDLFLAGS=$LDLFLAGS
+CFLAGS=""
+LDLFLAGS=""
+
+if test x"$netatalk_cv_ldap" != x"no" ; then
+ if test x"$netatalk_cv_ldap" != x"yes" -a x"$netatalk_cv_ldap" != x"auto"; then
+ CFLAGS=-I$netatalk_cv_ldap/include
+ LDLFLAGS=-L$netatalk_cv_ldap/lib
+ fi
+ AC_CHECK_HEADER([ldap.h], netatalk_cv_ldap=yes,
+ [ if test x"$netatalk_cv_ldap" = x"yes" ; then
AC_MSG_ERROR([Missing LDAP headers])
fi
- with_ldap=no
+ netatalk_cv_ldap=no
])
- AC_CHECK_LIB(ldap, ldap_init, with_ldap=yes,
- [ if test x"$with_ldap" = x"yes" ; then
+ AC_CHECK_LIB(ldap, ldap_init, netatalk_cv_ldap=yes,
+ [ if test x"$netatalk_cv_ldap" = x"yes" ; then
AC_MSG_ERROR([Missing LDAP library])
fi
- with_ldap=no
+ netatalk_cv_ldap=no
])
fi
-if test x"$with_ldap" = x"yes"; then
+if test x"$netatalk_cv_ldap" = x"yes"; then
+ LDAP_CFLAGS=$CFLAGS
+ LDAP_LDLFLAGS=$LDLFLAGS
+ LDAP_LIBS=-lldap
AC_DEFINE(HAVE_LDAP,1,[Whether LDAP is available])
+ AC_SUBST(LDAP_CFLAGS)
+ AC_SUBST(LDAP_LDLFLAGS)
+ AC_SUBST(LDAP_LIBS)
fi
+
+CFLAGS=$save_CFLAGS
+LDLFLAGS=$save_LDLFLAGS
])
dnl Check for ACL support
AC_MSG_RESULT([ Samba sharemode interop: $neta_cv_have_smbshmd])
AC_MSG_RESULT([ ACL support: $with_acl_support])
AC_MSG_RESULT([ Kerberos support: $with_kerberos])
- AC_MSG_RESULT([ LDAP support: $with_ldap])
+ AC_MSG_RESULT([ LDAP support: $netatalk_cv_ldap])
if test x"$use_pam_so" = x"yes" -a x"$netatalk_cv_install_pam" = x"no"; then
AC_MSG_RESULT([])
AC_MSG_WARN([ PAM support was configured for your system, but the netatalk PAM configuration file])
AC_MSG_RESULT([ LIBS = $ZEROCONF_LIBS])
AC_MSG_RESULT([ CFLAGS = $ZEROCONF_CFLAGS])
fi
+ if test x"$netatalk_cv_ldap" = x"yes"; then
+ AC_MSG_RESULT([ LDAP:])
+ AC_MSG_RESULT([ LIBS = $LDAP_LDLFLAGS $LDAP_LIBS])
+ AC_MSG_RESULT([ CFLAGS = $LDAP_CFLAGS])
+ fi
])
on volumes and do the conversion with that\&. Then this option can be set to no\&.
.RE
.PP
-hex encoding = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
-.RS 4
-Whether :hex encoding is done for file and directory names containing the character
-/\&. Setting this option to no makes the
-/
-character illegal\&.
-.RE
-.PP
invisible dots = \fIBOOLEAN\fR (default: \fIno\fR) \fB(V)\fR
.RS 4
-make dot files invisible\&. If "\fBuse dots = no\fR", this parameter is not unnecessary\&.
+make dot files invisible\&.
.RE
.PP
network ids = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
and
\fBumask\fR\&.
.RE
-.PP
-use dots = \fIBOOLEAN\fR (default: \fIyes\fR) \fB(V)\fR
-.RS 4
-Whether to do :hex translation for dot files\&. See also
-\fBinvisible dots\fR\&.
-.RE
.SH "CNID BACKENDS"
.PP
The AFP protocol mostly refers to files and directories by ID and not by name\&. Netatalk needs a way to store these ID\'s in a persistent way, to achieve this several different CNID backends are available\&. The CNID Databases are by default located in the
-I$(top_srcdir)/etc/afpd \
-I$(top_srcdir)/include \
-I$(top_srcdir)/sys \
- @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ \
+ @ZEROCONF_CFLAGS@ @GSSAPI_CFLAGS@ @KRB5_CFLAGS@\
-DAPPLCNAME \
-DSERVERTEXT=\"$(SERVERTEXT)/\" \
-D_PATH_AFPDPWFILE=\"$(pkgconfdir)/afppasswd\" \
test_LDADD = \
$(top_builddir)/libatalk/libatalk.la \
- @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@
+ @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ @GSSAPI_LIBS@ @KRB5_LIBS@
test_LDFLAGS = -export-dynamic