From: Frank Lahm Date: Sat, 23 Apr 2011 07:43:31 +0000 (+0200) Subject: Merge master X-Git-Url: https://arthur.barton.de/gitweb/?a=commitdiff_plain;h=6d60f95c388da5f8f901d67e0018cf4896e6c6dc;hp=-c;p=netatalk.git Merge master --- 6d60f95c388da5f8f901d67e0018cf4896e6c6dc diff --combined bin/Makefile.am index 1742ea6b,7c633f74..f5d1448a --- a/bin/Makefile.am +++ b/bin/Makefile.am @@@ -1,3 -1,11 +1,7 @@@ # Makefile.am for bin/ - SUBDIRS = ad afppasswd cnid megatron uniconv misc -SUBDIRS = adv1tov2 afppasswd cnid megatron uniconv misc - -if USE_APPLETALK -SUBDIRS += aecho getzones nbp pap psorder -endif ++SUBDIRS = afppasswd cnid megatron uniconv misc + + if HAVE_ATFUNCS + SUBDIRS += ad + endif diff --combined bin/ad/ad_cp.c index 0ee0f405,ac0a737a..b0723b02 --- a/bin/ad/ad_cp.c +++ b/bin/ad/ad_cp.c @@@ -387,6 -387,10 +387,10 @@@ static int copy(const char *path if (alarmed) return -1; + /* This currently doesn't work with "." */ + if (strcmp(path, ".") == 0) { + ERROR("\".\" not supported"); + } const char *dir = strrchr(path, '/'); if (dir == NULL) dir = path; @@@ -540,7 -544,7 +544,7 @@@ break; } ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); - if (ad_open_metadata(to.p_path, ADFLAGS_DIR, O_RDWR | O_CREAT, &ad) != 0) { + if (ad_open(&ad, to.p_path, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0) { ERROR("Error opening adouble for: %s", to.p_path); } ad_setid( &ad, st.st_dev, st.st_ino, did, pdid, dvolume.db_stamp); @@@ -607,7 -611,7 +611,7 @@@ break; } ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); - if (ad_open_metadata(to.p_path, 0, O_RDWR | O_CREAT, &ad) != 0) { + if (ad_open(&ad, to.p_path, ADFLAGS_HF, O_RDWR | O_CREAT) != 0) { ERROR("Error opening adouble for: %s", to.p_path); } ad_setid( &ad, st.st_dev, st.st_ino, cnid, did, dvolume.db_stamp); diff --combined bin/ad/ad_mv.c index 03553643,4d23183a..156d648b --- a/bin/ad/ad_mv.c +++ b/bin/ad/ad_mv.c @@@ -186,7 -186,7 +186,7 @@@ int ad_mv(int argc, char *argv[] set_signal(); cnid_init(); if (openvol(argv[argc - 1], &dvolume) != 0) { - SLOG("Error opening CNID database for %s: ", argv[argc - 1]); + SLOG("Error opening CNID database for source \"%s\": ", argv[argc - 1]); return 1; } @@@ -198,7 -198,7 +198,7 @@@ if (argc > 2) usage_mv(); if (openvol(argv[0], &svolume) != 0) { - SLOG("Error opening CNID database for %s: ", argv[0]); + SLOG("Error opening CNID database for destination \"%s\": ", argv[0]); return 1; } rval = do_move(argv[0], argv[1]); @@@ -235,11 -235,8 +235,8 @@@ rval = 1; } else { memmove(endp, p, (size_t)len + 1); - if (openvol(*argv, &svolume) != 0) { - SLOG("Error opening CNID database for %s: ", argv[0]); - rval = 1; - goto exit; - } + openvol(*argv, &svolume); + if (do_move(*argv, path)) rval = 1; closevol(&svolume); @@@ -377,7 -374,7 +374,7 @@@ static int do_move(const char *from, co struct adouble ad; ad_init(&ad, dvolume.volinfo.v_adouble, dvolume.volinfo.v_ad_options); - if (ad_open_metadata(to, S_ISDIR(sb.st_mode) ? ADFLAGS_DIR : 0, O_RDWR, &ad) != 0) { + if (ad_open(&ad, to, S_ISDIR(sb.st_mode) ? (ADFLAGS_DIR | ADFLAGS_HF) : ADFLAGS_HF, O_RDWR) != 0) { SLOG("Error opening adouble for: %s", to); return 1; } diff --combined bin/uniconv/uniconv.c index 850c45d7,e6d1daeb..5dfc8231 --- a/bin/uniconv/uniconv.c +++ b/bin/uniconv/uniconv.c @@@ -35,13 -35,10 +35,13 @@@ #include #include #include +#include + #include #include #include #include +#include #include "atalk/cnid.h" #ifndef MAXPATHLEN @@@ -389,7 -386,7 +389,7 @@@ static int init(char* path { DIR* startdir; - if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, NULL, NULL)) ) { + if (NULL == (cdb = cnid_open (path, 0, cnid_type, 0, "localhost", "4700")) ) { fprintf (stderr, "ERROR: cannot open CNID database in '%s'\n", path); fprintf (stderr, "ERROR: check the logs for reasons, aborting\n"); return -1; diff --combined configure.in index 9da854d2,48449921..ea334e47 --- a/configure.in +++ b/configure.in @@@ -21,43 -21,35 +21,43 @@@ AC_PROG_LIBTOO AC_PROG_PERL AC_PROG_GREP AC_PROG_PS - AM_PROG_CC_C_O -dnl Checks for header files. -AC_HEADER_DIRENT -AC_HEADER_STDC -AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(fcntl.h limits.h stdint.h strings.h time.h sys/param.h sys/fcntl.h sys/file.h sys/ioctl.h sys/time.h sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h mntent.h syslog.h unistd.h termios.h sys/termios.h netdb.h sgtty.h ufs/quota.h mount.h statfs.h sys/types.h dlfcn.h errno.h sys/errno.h sys/uio.h langinfo.h locale.h sys/filio.h) -AC_CHECK_HEADER(sys/cdefs.h,, - AC_MSG_RESULT([enabling generic cdefs.h from tree]) - CFLAGS="-I\$(top_srcdir)/sys/generic $CFLAGS" -) +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_INLINE + +dnl Request SUSv3 standard interfaces plus anything else the platform may have +CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D__EXTENSIONS__ -D_GNU_SOURCE" + +dnl Check if we can use attribute unused (gcc only) from ethereal +AC_MSG_CHECKING(to see if we can add '__attribute__((unused))' to CFLAGS) +if test x$GCC != x ; then + CFLAGS="-D_U_=\"__attribute__((unused))\" $CFLAGS" + AC_MSG_RESULT(yes) +else + CFLAGS="-D_U_=\"\" $CFLAGS" + AC_MSG_RESULT(no) +fi + +dnl Configure libevent +AC_CONFIG_SUBDIRS([libevent]) + +dnl Checks for header files, some checks are obsolete, unfortunately the code +dnl uses the resulting macros, so the code has to cleaned up too before +dnl we can remove the checks here. +AC_CHECK_HEADERS(mntent.h unistd.h termios.h ufs/quota.h) +AC_CHECK_HEADERS(netdb.h sgtty.h statfs.h dlfcn.h langinfo.h locale.h) +AC_CHECK_HEADERS(sys/param.h sys/fcntl.h sys/termios.h) +AC_CHECK_HEADERS(sys/mnttab.h sys/statvfs.h sys/stat.h sys/vfs.h) +dnl Checks for header files, confirmed to be required as of 2011 +AC_CHECK_HEADERS(sys/epoll.h) AC_CHECK_HEADERS([sys/mount.h], , , [#ifdef HAVE_SYS_PARAM_H #include #endif ]) -dnl Checks for typedefs, structures, and compiler characteristics. -AC_C_CONST -AC_TYPE_UID_T -AC_C_INLINE -AC_TYPE_MODE_T -AC_TYPE_OFF_T -AC_TYPE_PID_T -AC_TYPE_SIZE_T -AC_STRUCT_ST_RDEV -AC_HEADER_TIME -AC_STRUCT_TM +AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.])) dnl -------------------------------------------------------------------------- dnl check if dlsym needs to add an underscore, uses libtool macros @@@ -69,55 -61,40 +69,60 @@@ if test x"$libltdl_cv_need_uscore" = xy AC_DEFINE(DLSYM_PREPEND_UNDERSCORE, 1, [BSD compatibility macro]) fi -dnl Checks for library functions. -AC_TYPE_GETGROUPS -AC_PROG_GCC_TRADITIONAL -AC_FUNC_MEMCMP -AC_HEADER_MAJOR -AC_FUNC_MMAP -AC_TYPE_SIGNAL -AC_FUNC_UTIME_NULL -AC_FUNC_WAIT3 -AC_CHECK_FUNCS(getcwd gethostname gettimeofday getusershell mkdir rmdir select socket strdup strcasestr strstr strtoul strchr memcpy) -AC_CHECK_FUNCS(backtrace_symbols setlocale nl_langinfo strlcpy strlcat setlinebuf dirfd pselect access pread pwrite) -AC_CHECK_FUNCS(waitpid getcwd strdup strndup strnlen strtoul strerror chown fchown chmod fchmod chroot link mknod mknod64) +dnl Special hecks + ac_neta_haveatfuncs=yes + AC_CHECK_FUNCS(openat renameat fstatat unlinkat, , ac_neta_haveatfuncs=no) + if test x"$ac_neta_haveatfuncs" = x"yes" ; then + AC_DEFINE([_ATFILE_SOURCE], 1, AT file source) + AC_DEFINE([HAVE_ATFUNCS], 1, whether at funcs are available) + fi - AC_CHECK_MEMBERS(struct tm.tm_gmtoff,,, [#include ]) -AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)]) -AC_CHECK_FUNC(connect,,[AC_CHECK_LIB(socket,connect)]) -dnl search for necessary libs for libpthread stuff -AC_SEARCH_LIBS(pthread_sigmask, pthread,, - [AC_MSG_ERROR([cannot find pthread_sigmask in libc or libpthread])]) +dnl these tests have been comfirmed to be needed in 2011 - AC_CHECK_FUNC(renameat, AC_DEFINE([_ATFILE_SOURCE], 1, AT file source)) +AC_CHECK_FUNC(epoll_create, AC_DEFINE([HAVE_EPOLL], 1, Whether Linux epoll is available)) +AC_CHECK_FUNCS(backtrace_symbols dirfd getusershell pread pwrite pselect) +AC_CHECK_FUNCS(setlinebuf strlcat strlcpy strnlen) +AC_CHECK_FUNCS(mmap utime getpagesize) dnl needed by tbd + +dnl search for necessary libraries +AC_SEARCH_LIBS(gethostbyname, nsl) +AC_SEARCH_LIBS(connect, socket) +AC_SEARCH_LIBS(pthread_sigmask, pthread,,[AC_MSG_ERROR([missing pthread_sigmask])]) if test x"$ac_cv_search_pthread_sigmask" != x"none required" ; then PTHREAD_LIBS=$ac_cv_search_pthread_sigmask fi AC_SUBST(PTHREAD_LIBS) -AC_CACHE_SAVE -dnl Checks for (v)snprintf -NETATALK_SNPRINTF_CHECK +dnl --------------------- Check if realpath() takes NULL +AC_CACHE_CHECK([if the realpath function allows a NULL argument], + neta_cv_REALPATH_TAKES_NULL, [ + AC_TRY_RUN([ + #include + #include + #include + + void exit_on_core(int ignored) { + exit(1); + } + + main() { + char *newpath; + signal(SIGSEGV, exit_on_core); + newpath = realpath("/tmp", NULL); + exit((newpath != NULL) ? 0 : 1); + }], + neta_cv_REALPATH_TAKES_NULL=yes, + neta_cv_REALPATH_TAKES_NULL=no, + neta_cv_REALPATH_TAKES_NULL=cross + ) + ] +) + +if test x"$neta_cv_REALPATH_TAKES_NULL" = x"yes"; then + AC_DEFINE(REALPATH_TAKES_NULL,1,[Whether the realpath function allows NULL]) +fi + +AC_CACHE_SAVE dnl -------------------------------------------------------------------------- dnl 64bit platform check @@@ -158,92 -135,347 +163,92 @@@ dnl ----------------------------------- dnl specific configuration comes in here: dnl -------------------------------------------------------------------------- +dnl Check for optional admin group support +AC_NETATALK_ADMIN_GROUP -netatalk_cv_admin_group=yes -AC_MSG_CHECKING([for administrative group support]) -AC_ARG_ENABLE(admin-group, - [ --disable-admin-group disable admin group],[ - if test x"$enableval" = x"no"; then - AC_DEFINE(ADMIN_GRP, 0, [Define if the admin group should be enabled]) - netatalk_cv_admin_group=no - AC_MSG_RESULT([no]) - else - AC_DEFINE(ADMIN_GRP, 1, [Define if the admin group should be enabled]) - AC_MSG_RESULT([yes]) - fi],[ - AC_DEFINE(ADMIN_GRP, 1, [Define if the admin group should be enabled]) - AC_MSG_RESULT([yes]) - ] -) +dnl Check for optional AFS support +AC_NETATALK_AFS_CHECK -NETATALK_AFS_CHECK - -NETATALK_CONFIG_DIRS - -netatalk_cv_with_cracklib=no -AC_ARG_WITH(cracklib, - [ --with-cracklib=DICT enable/set location of cracklib dictionary],[ - if test "x$withval" != "xno" ; then - cracklib="$withval" - AC_CHECK_LIB(crack, main, [ - AC_DEFINE(USE_CRACKLIB, 1, [Define if cracklib should be used]) - LIBS="$LIBS -lcrack" - if test "$cracklib" = "yes"; then - cracklib="/usr/$atalk_libname/cracklib_dict" - fi - AC_DEFINE_UNQUOTED(_PATH_CRACKLIB, "$cracklib", - [path to cracklib dictionary]) - AC_MSG_RESULT([setting cracklib dictionary to $cracklib]) - netatalk_cv_with_cracklib=yes - ],[ - AC_MSG_ERROR([cracklib not found!]) - ] - ) - fi - ] -) -AC_MSG_CHECKING([for cracklib support]) -AC_MSG_RESULT([$netatalk_cv_with_cracklib]) - -netatalk_cv_ddp_enabled=no -AC_MSG_CHECKING([whether to enable DDP]) -AC_ARG_ENABLE(ddp, - [ --enable-ddp enable DDP (AppleTalk)],[ - if test "$enableval" = "yes"; then - AC_MSG_RESULT([yes]) - netatalk_cv_ddp_enabled=yes - else - AC_MSG_RESULT([yes]) - AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled]) - fi - ],[ - AC_MSG_RESULT([no]) - AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled]) - ] -) +dnl --with-pkgconfdir check to change configuration directory location +AC_NETATALK_CONFIG_DIRS -AC_MSG_CHECKING([whether to enable debug code]) -AC_ARG_ENABLE(debug1, - [ --enable-debug1 enable debug code],[ - if test "$enableval" != "no"; then - if test "$enableval" = "yes"; then - AC_DEFINE(DEBUG1, 1, [Define if debugging information should be included]) - else - AC_DEFINE_UNQUOTED(DEBUG1, $enableval, [Define if debugging information should be included]) - fi - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ],[ - AC_MSG_RESULT([no]) - ] -) - -AC_MSG_CHECKING([whether to enable verbose debug code]) -AC_ARG_ENABLE(debug, - [ --enable-debug enable verbose debug code],[ - if test "$enableval" != "no"; then - if test "$enableval" = "yes"; then - AC_DEFINE(DEBUG, 1, [Define if verbose debugging information should be included]) - else - AC_DEFINE_UNQUOTED(DEBUG, $enableval, [Define if verbose debugging information should be included]) - fi - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_DEFINE(NDEBUG, 1, [Disable assertions]) - fi - ],[ - AC_MSG_RESULT([no]) - AC_DEFINE(NDEBUG, 1, [Disable assertions]) - ] -) +dnl Check for optional cracklib support +AC_NETATALK_CRACKLIB -AC_MSG_CHECKING([whether to enable debugging with debuggers]) -AC_ARG_ENABLE(debugging, - [ --enable-debugging disable SIGALRM timers and DSI tickles (eg for debugging with gdb/dbx/...)],[ - if test "$enableval" != "no"; then - if test "$enableval" = "yes"; then - AC_DEFINE(DEBUGGING, 1, [Define if you want to disable SIGALRM timers and DSI tickles]) - else - AC_DEFINE_UNQUOTED(DEBUGGING, $enableval, [Define if you want to disable SIGALRM timers and DSI tickles]) - fi - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ],[ - AC_MSG_RESULT([no]) - ] -) +dnl Check whether to enable debug code +AC_NETATALK_DEBUG -AC_SYS_LARGEFILE([], AC_MSG_ERROR([AFP 3.x support requires Large File Support.])) -AC_CHECK_ICONV - -dnl ----------- A NOTE ABOUT DROPKLUDGE -dnl The trouble with this fix is that if you know what the file is called, it -dnl can be read from the Unix side. That's okay for most academic institutions -dnl since the students don't have telnet access to the Mac servers. There is -dnl currently no one working on further development/fixes of DROPKLUDGE. -dnl ----------- - -netatalk_cv_dropkludge=no -AC_MSG_CHECKING([whether to enable experimental dropbox support]) -AC_ARG_ENABLE(dropkludge, - [ --enable-dropkludge enable the experimental dropbox fix (INSECURE!) ],[ - if test "$enableval" = "yes"; then - AC_DEFINE(DROPKLUDGE, 1, [Define if you want to use the experimental dropkludge support]) - AC_MSG_RESULT([yes]) - netatalk_cv_dropkludge=yes - else - AC_MSG_RESULT([no]) - fi - ],[ - AC_MSG_RESULT([no]) - ] -) +dnl Check whethe to disable tickle SIGALARM stuff, which eases debugging +AC_NETATALK_DEBUGGING -netatalk_cv_force_uidgid=no -AC_MSG_CHECKING([whether to enable forcing of uid/gid per volume]) -AC_ARG_ENABLE(force-uidgid, - [ --enable-force-uidgid allow forcing of uid/gid per volume (BROKEN) ],[ - if test "$enableval" = "yes"; then - AC_DEFINE(FORCE_UIDGID, 1, [Define if you want forcing of uid/gid per volume]) - AC_MSG_RESULT([enabling forcing of uid/gid per volume]) - AC_MSG_RESULT([yes]) - netatalk_cv_force_uidgid=yes - else - AC_MSG_RESULT([no]) - fi - ],[ - AC_MSG_RESULT([no]) - ] -) +dnl Check for libiconv support +AC_NETATALK_CHECK_ICONV dnl Check for CNID database backends -bdb_required=no AC_NETATALK_CNID([bdb_required=yes],[bdb_required=no]) dnl Check for quota support -AC_CHECK_QUOTA +AC_NETATALK_CHECK_QUOTA dnl Check for optional server location protocol support (used by MacOS X) -NETATALK_SRVLOC +AC_NETATALK_SRVLOC dnl Check for optional Zeroconf support -NETATALK_ZEROCONF +AC_NETATALK_ZEROCONF -dnl Check for PAM libs -netatalk_cv_use_pam=no -AC_PATH_PAM([ - use_pam_so=yes - compile_pam=yes - netatalk_cv_use_pam=yes - AC_DEFINE(USE_PAM, 1, [Define to enable PAM support]) -]) +dnl Check for optional TCP-wrappers support +AC_NETATALK_TCP_WRAPPERS -netatalk_cv_use_shadowpw=no -AC_ARG_WITH(shadow, - [ --with-shadow enable shadow password support [[auto]]], - [netatalk_cv_use_shadowpw="$withval"], - [netatalk_cv_use_shadowpw=auto] -) - -if test "x$netatalk_cv_use_shadowpw" != "xno"; then - AC_CHECK_HEADER([shadow.h]) - if test x"$ac_cv_header_shadow_h" = x"yes"; then - netatalk_cv_use_shadowpw=yes - AC_DEFINE(SHADOWPW, 1, [Define if shadow passwords should be used]) - else - if test "x$shadowpw" = "xyes"; then - AC_MSG_ERROR([shadow support not available]) - else - netatalk_cv_use_shadowpw=no - fi - fi -fi +dnl Check for PAM libs +AC_NETATALK_PATH_PAM -AC_MSG_CHECKING([whether shadow support should be enabled]) -if test "x$netatalk_cv_use_shadowpw" = "xyes"; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi - +dnl Check for optional shadow password support +AC_NETATALK_SHADOW - -netatalk_cv_use_shellcheck=yes -AC_MSG_CHECKING([whether checking for a valid shell should be enabled]) -AC_ARG_ENABLE(shell-check, - [ --disable-shell-check disable checking for a valid shell],[ - if test "$enableval" = "no"; then - AC_DEFINE(DISABLE_SHELLCHECK, 1, [Define if shell check should be disabled]) - AC_MSG_RESULT([no]) - netatalk_cv_use_shellcheck=no - else - AC_MSG_RESULT([yes]) - fi - ],[ - AC_MSG_RESULT([yes]) - ] -) +dnl Check for optional valid-shell-check support +AC_NETATALK_SHELL_CHECK -NETATALK_TCP_WRAPPERS - -AC_MSG_CHECKING([whether system (fcntl) locking should be disabled]) -AC_ARG_ENABLE(locking, - [ --disable-locking disable system locking],[ - if test "$enableval" = "no"; then - AC_DEFINE(DISABLE_LOCKING, 1, [Define if system (fcntl) locking should be disabled]) - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - - ],[ - AC_MSG_RESULT([no]) - ] +dnl Check for optional Webmin +AC_NETATALK_WEBMIN -) +dnl Check for optional sysv initscript install +AC_NETATALK_SYSV_STYLE +dnl Path where UAM modules shall be installed +AC_ARG_WITH(uams-path, [ --with-uams-path=PATH path to UAMs [[PKGCONF/uams]]], [uams_path="$withval"], [uams_path="${PKGCONFDIR}/uams"]) -AC_ARG_ENABLE(redhat, - [ --enable-redhat use redhat-style sysv configuration ],[ - if test "$enableval" = "yes"; then - sysv_style=redhat - fi - AC_MSG_RESULT([enabling redhat-style sysv support]) - ] -) +dnl Check for libgcrypt, if found enables DHX2 UAM +AC_NETATALK_PATH_LIBGCRYPT([1:1.2.3]) -AC_ARG_ENABLE(suse, - [ --enable-suse use suse-style sysv configuration ],[ - if test "$enableval" = "yes"; then - sysv_style=suse - fi - AC_MSG_RESULT([enabling suse-style sysv support]) - ] -) +dnl Check for openssl, if found enables DHX UAM and Randnum UAM +AC_NETATALK_PATH_SSL -AC_ARG_ENABLE(gentoo, - [ --enable-gentoo use gentoo-style sysv configuration ],[ - if test "$enableval" = "yes"; then - sysv_style=gentoo - fi - AC_MSG_RESULT([enabling gentoo-style sysv support]) - ] -) +dnl Check for Berkeley DB library +AC_NETATALK_PATH_BDB -AC_ARG_ENABLE(cobalt, - [ --enable-cobalt use cobalt-style sysv configuration ], - if test "$enableval" = "yes"; then - sysv_style=cobalt - fi - AC_MSG_RESULT([enabling cobalt-style sysv support]) -) +dnl Check for crypt +AC_NETATALK_CRYPT -AC_ARG_ENABLE(netbsd, - [ --enable-netbsd use NetBSD-style rc.d configuration ], - if test "x$enableval" = "xyes"; then - sysv_style=netbsd - fi - AC_MSG_RESULT([enabling NetBSD-style rc.d support]) -) +dnl Check for building PGP UAM module +AC_NETATALK_PGP_UAM -AC_ARG_ENABLE(debian, - [ --enable-debian use debian-style sysv configuration ],[ - if test "$enableval" = "yes"; then - sysv_style=debian - fi - AC_MSG_RESULT([enabling debian-style sysv support]) - ] -) +dnl Check for building Kerberos V UAM module +AC_NETATALK_KRB5_UAM -dnl ----- timelord compilation (disabled by default) -AC_MSG_CHECKING([whether timelord should be compiled]) -compile_timelord=no -AC_ARG_ENABLE(timelord, - [ --enable-timelord enable compilation of timelord server], - [compile_timelord="$enableval"], - [compile_timelord="no"] -) -AC_MSG_RESULT([$compile_timelord]) - -dnl ----- a2boot compilation (disabled by default) -AC_MSG_CHECKING([whether a2boot should be compiled]) -compile_a2boot=no -AC_ARG_ENABLE(a2boot, - [ --enable-a2boot enable compilation of Apple2 boot server], - [compile_a2boot="$enableval"], - [compile_a2boot="no"] -) -AC_MSG_RESULT([$compile_a2boot]) +dnl Check for overwrite the config files or not +AC_NETATALK_OVERWRITE_CONFIG -AC_ARG_WITH(uams-path, - [ --with-uams-path=PATH path to UAMs [[PKGCONF/uams]]],[ - uams_path="$withval" - ],[ - uams_path="${PKGCONFDIR}/uams" - ] -) +dnl Check for LDAP support, for client-side ACL visibility +AC_NETATALK_LDAP -NETATALK_AC_CUPS +dnl Check for ACL support +AC_NETATALK_ACL -dnl check if we can use attribute unused (gcc only) from ethereal -AC_MSG_CHECKING(to see if we can add '__attribute__((unused))' to CFLAGS) -if test x$GCC != x ; then - CFLAGS="-D_U_=\"__attribute__((unused))\" $CFLAGS" - AC_MSG_RESULT(yes) -else - CFLAGS="-D_U_=\"\" $CFLAGS" - AC_MSG_RESULT(no) -fi +dnl Check for Extended Attributes support +AC_NETATALK_EXTENDED_ATTRIBUTES + +dnl Check for libsmbsharemodes from Samba for Samba/Netatalk access/deny/share modes interop +AC_NETATALK_SMB_SHAREMODES dnl -------------------------------------------------------------------------- dnl FHS stuff has to be done last because it overrides other defaults @@@ -273,17 -505,12 +278,17 @@@ dnl ----------------------------------- dnl post-FHS substitutions, etc dnl -------------------------------------------------------------------------- -dnl ***** UAMS_PATH -dnl AC_DEFINE_UNQUOTED(UAMS_PATH, "${uams_path}", -dnl [path to UAMs [default=PKGCONF/uams]]) UAMS_PATH="${uams_path}" AC_SUBST(UAMS_PATH) + +dnl -------------------------------------------------------------------------- +dnl OS specific configuration comes in here: +dnl -------------------------------------------------------------------------- + +AC_NETATALK_OS_SPECIFIC + + dnl -------------------------------------------------------------------------- dnl drop in includes for top level directory structures here... dnl -------------------------------------------------------------------------- @@@ -291,19 -518,725 +296,19 @@@ dnl Note: $(top_srcdir)/include should be added before all other includes dnl so that includes from that directory a preferred to includes from dnl /usr/include or similar places. -LIBS="$LIBS -L\$(top_srcdir)/libatalk" -CFLAGS="-I\$(top_srcdir)/include $CFLAGS -I\$(top_srcdir)/sys" +LIBS="$LIBS -L\$(top_srcdir)/libatalk -L\$(top_srcdir)/libevent" +CFLAGS="-I\$(top_srcdir)/include -I\$(top_srcdir)/sys -I\$(top_srcdir)/libevent/include $CFLAGS" AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW) + dnl -------------------------------------------------------------------------- -dnl specific configuration comes in here: +dnl Last minute substitutions dnl -------------------------------------------------------------------------- - -dnl ac_cv_target_os is now host_os, ac_cv_target_cpu is now host_cpu - -dnl --------------------- determine operating system from "target" -case "$host_os" in - *aix*) this_os=aix ;; - *freebsd*) this_os=freebsd ;; - *hpux11*) this_os=hpux11 ;; - *irix*) this_os=irix ;; - *linux*) this_os=linux ;; - *osx*) this_os=macosx ;; - *darwin*) this_os=macosx ;; - *netbsd*) this_os=netbsd ;; - *openbsd*) this_os=openbsd ;; - *osf*) this_os=tru64 ;; - *solaris*) this_os=solaris ;; -esac - -case "$host_cpu" in - i386|i486|i586|i686|k7) this_cpu=x86 ;; - alpha) this_cpu=alpha ;; - mips) this_cpu=mips ;; - powerpc|ppc) this_cpu=ppc ;; -esac - -dnl --------------------- GNU source -case "$this_os" in - linux) AC_DEFINE(_GNU_SOURCE, 1, [Whether to use GNU libc extensions]) - ;; -esac - -dnl --------------------- operating system specific flags (port from sys/*) - -dnl ----- AIX specific ----- -if test x"$this_os" = "xaix"; then - AC_MSG_RESULT([ * AIX specific configuration]) - AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available]) - - dnl This is probably a lie; AIX 4.3 supports a 64-bit long - dnl compilation environment. It's enough to get things defined - dnl right in endian.h provided that long long is supported, though. - AC_DEFINE(HAVE_32BIT_LONGS, 1, [Define if the data type long has 32 bit]) -fi - -dnl ----- FreeBSD specific ----- -if test x"$this_os" = "xfreebsd"; then - AC_MSG_RESULT([ * FreeBSD specific configuration]) - AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro]) - AC_DEFINE(FREEBSD, 1, [Define if OS is FreeBSD]) - AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics]) - AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW) -fi - -dnl ----- HP-UX 11 specific ----- -if test x"$this_os" = "xhpux11"; then - AC_MSG_RESULT([ * HP-UX 11 specific configuration]) - - AC_DEFINE(_ISOC9X_SOURCE, 1, [Compatibility macro]) - AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available]) -fi - -dnl ----- IRIX specific ----- -if test x"$this_os" = "xirix"; then - AC_MSG_RESULT([ * IRIX specific configuration]) - - AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available]) -fi - -dnl ----- Linux specific ----- -if test x"$this_os" = "xlinux"; then - AC_MSG_RESULT([ * Linux specific configuration]) - - dnl ----- kernel 2.6 changed struct at_addr to atalk_addr - AC_MSG_CHECKING([for struct atalk_addr]) -dnl AC_COMPILE_IFELSE([ - AC_TRY_COMPILE([ -#include -#include -#include - - struct atalk_addr foo; -], -[ ], [ - ac_have_atalk_addr=yes - AC_MSG_RESULT([yes]) - ], [ - AC_MSG_RESULT([no]) - ]) - -if test "x$ac_have_atalk_addr" = "xyes"; then - AC_DEFINE(HAVE_ATALK_ADDR, 1, [set if struct at_addr is called atalk_addr]) -fi - - dnl ----- check if we need the quotactl wrapper -# AC_CHECK_HEADERS(sys/quota.h linux/quota.h) -# AC_CHECK_FUNC(quotactl,, -# AC_DEFINE(NEED_QUOTACTL_WRAPPER, 1, [Define if the quotactl wrapper is needed]) -# AC_MSG_RESULT([enabling quotactl wrapper]) -# ) - - # For quotas on Linux XFS filesystems - - # For linux > 2.5.56 - AC_CHECK_HEADERS(linux/dqblk_xfs.h,, - [AC_CHECK_HEADERS(linux/xqm.h linux/xfs_fs.h) - AC_CHECK_HEADERS(xfs/libxfs.h xfs/xqm.h xfs/xfs_fs.h)] - ) - - - dnl ----- as far as I can tell, dbtob always does the wrong thing - dnl ----- on every single version of linux I've ever played with. - dnl ----- see etc/afpd/quota.c - AC_DEFINE(HAVE_BROKEN_DBTOB, 1, [Define if dbtob is broken]) - - netatalk_cv_linux_sendfile=yes - AC_MSG_CHECKING([use sendfile syscall]) - AC_ARG_ENABLE(sendfile, - [ --disable-sendfile disable linux sendfile syscall],[ - if test x"$enableval" = x"no"; then - netatalk_cv_linux_sendfile=no - AC_MSG_RESULT([no]) - else - AC_MSG_RESULT([yes]) - - fi - ],[ - AC_MSG_RESULT([yes]) - ] - - ) - - if test x"$netatalk_cv_linux_sendfile" = "xyes"; then - AC_CACHE_CHECK([for linux sendfile support],netatalk_cv_HAVE_SENDFILE,[ - AC_TRY_LINK([#include ], -[\ -int tofd, fromfd; -off_t offset; -size_t total; -ssize_t nwritten = sendfile(tofd, fromfd, &offset, total); -], -netatalk_cv_HAVE_SENDFILE=yes,netatalk_cv_HAVE_SENDFILE=no)]) - -# Try and cope with broken Linux sendfile.... - AC_CACHE_CHECK([for broken linux sendfile support],netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE,[ - AC_TRY_LINK([\ -#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64) -#undef _FILE_OFFSET_BITS -#endif -#include ], -[\ -int tofd, fromfd; -off_t offset; -size_t total; -ssize_t nwritten = sendfile(tofd, fromfd, &offset, total); -], -netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE=yes,netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE=no,netatalk_cv_HAVE_BROKEN_SENDFILE=cross)]) - - if test x"$netatalk_cv_HAVE_SENDFILE" = x"yes"; then - AC_DEFINE(HAVE_SENDFILE,1,[Whether sendfile() is available]) - AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available]) - AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile() should be used]) - elif test x"$netatalk_cv_HAVE_BROKEN_LINUX_SENDFILE" = x"yes"; then - AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available]) - AC_DEFINE(LINUX_BROKEN_SENDFILE_API,1,[Whether (linux) sendfile() is broken]) - AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile should be used]) - else - netatalk_cv_linux_sendfile=no - AC_MSG_RESULT(no); - fi - fi - - dnl ----- Linux/alpha specific ----- - if test x"$this_cpu" = "xalpha"; then - AC_MSG_RESULT([enabling gcc memcpy bug workaround]) - AC_DEFINE(HAVE_GCC_MEMCPY_BUG, 1, [Define if memcpy is buggy]) - fi - need_dash_r=no - - -fi - -dnl ----- Mac OSX specific ----- -if test x"$this_os" = "xmacosx"; then - AC_MSG_RESULT([ * Mac OSX specific configuration]) - AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro]) - AC_DEFINE(HAVE_2ARG_DBTOB, 1, [Define if dbtob takes two arguments]) - dnl AC_DEFINE(NO_DLFCN_H) - AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled]) - AC_DEFINE(NO_QUOTA_SUPPORT, 1, [Define if Quota support should be disabled]) - AC_DEFINE(MACOSX_SERVER, 1, [Define if compiling for MacOS X Server]) -fi - -dnl ----- NetBSD specific ----- -if test x"$this_os" = "xnetbsd"; then - AC_MSG_RESULT([ * NetBSD specific configuration]) - AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro]) - AC_DEFINE(NETBSD, 1, [Define if OS is NetBSD]) - AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EFTYPE, errno returned by open with O_NOFOLLOW) - - CFLAGS="-I\$(top_srcdir)/sys/netbsd $CFLAGS" - need_dash_r=yes - - dnl ----- NetBSD does not have crypt.h, uses unistd.h ----- - AC_DEFINE(UAM_DHX, 1, [Define if the DHX UAM modules should be compiled]) -fi - -dnl ----- OpenBSD specific ----- -if test x"$this_os" = "xopenbsd"; then - AC_MSG_RESULT([ * OpenBSD specific configuration]) - dnl ----- OpenBSD does not have crypt.h, uses unistd.h ----- - AC_DEFINE(UAM_DHX, 1, [Define if the DHX UAM modules should be compiled]) -fi - -dnl ----- Solaris specific ----- -if test x"$this_os" = "xsolaris"; then - AC_MSG_RESULT([ * Solaris specific configuration]) - AC_DEFINE(__svr4__, 1, [Solaris compatibility macro]) - AC_DEFINE(_ISOC9X_SOURCE, 1, [Compatibility macro]) - AC_DEFINE(NO_STRUCT_TM_GMTOFF, 1, [Define if the gmtoff member of struct tm is not available]) - AC_DEFINE(SOLARIS, 1, [Solaris compatibility macro]) - CFLAGS="-I\$(top_srcdir)/sys/generic $CFLAGS" - need_dash_r=yes - sysv_style=solaris - - solaris_module=no - AC_MSG_CHECKING([if we can build Solaris kernel module]) - if test -x /usr/ccs/bin/ld && test x"$netatalk_cv_ddp_enabled" = x"yes" ; then - solaris_module=yes - fi - AC_MSG_RESULT([$solaris_module]) - - COMPILE_64BIT_KMODULE=no - KCFLAGS="" - KLDFLAGS="" - COMPILE_KERNEL_GCC=no - - if test "$solaris_module" = "yes"; then - dnl Solaris kernel module stuff - AC_MSG_CHECKING([if we have to build a 64bit kernel module]) - - # check for isainfo, if not found it has to be a 32 bit kernel (<=2.6) - if test -x /usr/bin/isainfo; then - # check for 64 bit platform - if isainfo -kv | grep '^64-bit'; then - COMPILE_64BIT_KMODULE=yes - fi - fi - - AC_MSG_RESULT([$COMPILE_64BIT_KMODULE]) - - if test "${GCC}" = yes; then - COMPILE_KERNEL_GCC=yes - if test "$COMPILE_64BIT_KMODULE" = yes; then - - AC_MSG_CHECKING([if we can build a 64bit kernel module]) - - case `$CC --version 2>/dev/null` in - [[12]].* | 3.0.*) - COMPILE_64BIT_KMODULE=no - COMPILE_KERNEL_GCC=no - solaris_module=no;; - *) - # use for 64 bit - KCFLAGS="-m64" - #KLDFLAGS="-melf64_sparc" - KLDFLAGS="-64";; - esac - - AC_MSG_RESULT([$COMPILE_64BIT_KMODULE]) - - else - KCFLAGS="" - KLDFLAGS="" - fi - KCFLAGS="$KCFLAGS -D_KERNEL -Wall -Wstrict-prototypes" - else - if test "$COMPILE_64BIT_KMODULE" = yes; then - # use Sun CC (for a 64-bit kernel, uncomment " -xarch=v9 -xregs=no%appl ") - KCFLAGS="-xarch=v9 -xregs=no%appl" - KLDFLAGS="-64" - else - KCFLAGS="" - KLDFLAGS="" - fi - KCFLAGS="-D_KERNEL $KCFLAGS -mno-app-regs -munaligned-doubles -fpcc-struct-return" - fi - - AC_CACHE_CHECK([for timeout_id_t],netatalk_cv_HAVE_TIMEOUT_ID_T,[ - AC_TRY_LINK([\ -#include -#include ], -[\ -timeout_id_t dummy; -], -netatalk_cv_HAVE_TIMEOUT_ID_T=yes,netatalk_cv_HAVE_TIMEOUT_ID_T=no,netatalk_cv_HAVE_TIMEOUT_ID_T=cross)]) - - AC_DEFINE(HAVE_TIMEOUT_ID_T, test x"$netatalk_cv_HAVE_TIMEOUT_ID" = x"yes", [define for timeout_id_t]) - fi - - AC_SUBST(COMPILE_KERNEL_GCC) - AC_SUBST(COMPILE_64BIT_KMODULE) - AC_SUBST(KCFLAGS) - AC_SUBST(KLDFLAGS) -fi - -dnl ----- Tru64 specific ----- -if test x"$this_os" = "xtru64"; then - AC_MSG_RESULT([ * Tru64 specific configuration]) - AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled]) - AC_DEFINE(HAVE_64BIT_LONGS, 1, [Define if the data type long has 64 bit]) - dnl AC_DEFINE(USE_MOUNT_H) - AC_DEFINE(USE_OLD_RQUOTA, 1, [Define to use old rquota]) - dnl AC_DEFINE(USE_UFS_QUOTA_H) - AC_DEFINE(TRU64, 1, [Define on Tru64 platforms]) - AC_DEFINE(_OSF_SOURCE, 1, [Define if the *passwd UAMs should be used]) - AC_DEFINE(_XOPEN_SOURCE_EXTENDED, 1, [Define for Berkeley DB 4]) - AC_CHECK_LIB(security,set_auth_parameters) - CFLAGS="-I\$(top_srcdir)/sys/tru64 $CFLAGS" - need_dash_r=no - sysv_style=tru64 -fi - -dnl -- check for libgcrypt, if found enables DHX UAM -AM_PATH_LIBGCRYPT([1:1.2.3],[neta_cv_compile_dhx2=yes - neta_cv_have_libgcrypt=yes - AC_MSG_NOTICE([Enabling DHX2 UAM]) - AC_DEFINE(HAVE_LIBGCRYPT, 1, [Define if the DHX2 modules should be built with libgcrypt]) - AC_DEFINE(UAM_DHX2, 1, [Define if the DHX2 UAM modules should be compiled]) - ]) - -dnl -- look for openssl, if found enables DHX UAM and Randnum UAM -AC_PATH_SSL - -dnl Check for Berkeley DB library -if test "x$bdb_required" = "xyes"; then - AC_PATH_BDB(, [ - AC_MSG_RESULT([]) - AC_MSG_RESULT([Make sure you have the required Berkeley DB libraries AND headers installed.]) - AC_MSG_RESULT([You can download the latest version from http://www.sleepycat.com.]) - AC_MSG_RESULT([If you have installed BDB in a non standard location use the]) - AC_MSG_RESULT([--with-bdb=/path/to/bdb configure option and make sure]) - AC_MSG_RESULT([your linker is configured to check for libraries there.]) - AC_MSG_ERROR([Berkeley DB library required but not found!]) - ]) -fi - -dnl -- check for crypt -AC_CRYPT - -dnl --------------------- check for building PGP UAM module - -AC_MSG_CHECKING([whether the PGP UAM should be build]) -AC_ARG_ENABLE(pgp-uam, - [ --enable-pgp-uam enable build of PGP UAM module],[ - if test "$enableval" = "yes"; then - if test "x$neta_cv_have_openssl" = "xyes"; then - AC_DEFINE(UAM_PGP, 1, [Define if the PGP UAM module should be compiled]) - compile_pgp=yes - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - fi - ],[ - AC_MSG_RESULT([no]) - ] -) - -dnl --------------------- check for building Kerberos v4 UAM module - -AC_MSG_CHECKING([whether the Kerberos IV UAM should be build]) -AC_ARG_ENABLE(krb4-uam, - [ --enable-krb4-uam enable build of Kerberos v4 UAM module],[ - if test "$enableval" = "yes"; then - AC_DEFINE(UAM_KRB4, 1, [Define if the Kerberos 4 UAM module should be compiled]) - compile_kerberos=yes - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - fi - ],[ - AC_MSG_RESULT([no]) - ] -) - -dnl --------------------- check for building Kerberos V UAM module - -netatalk_cv_build_krb5_uam=no -AC_ARG_ENABLE(krbV-uam, - [ --enable-krbV-uam enable build of Kerberos V UAM module], - [ - if test x"$enableval" = x"yes"; then - NETATALK_GSSAPI_CHECK([ - netatalk_cv_build_krb5_uam=yes - ],[ - AC_MSG_ERROR([need GSSAPI to build Kerberos V UAM]) - ]) - fi - ] - -) - -AC_MSG_CHECKING([whether Kerberos V UAM should be build]) -if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then - AC_MSG_RESULT([yes]) -else - AC_MSG_RESULT([no]) -fi -AM_CONDITIONAL(USE_GSSAPI, test x"$netatalk_cv_build_krb5_uam" = x"yes") - -dnl --------------------- overwrite the config files . . . or not. - -AC_MSG_CHECKING([whether configuration files should be overwritten]) -AC_ARG_ENABLE(overwrite, - [ --enable-overwrite overwrite configuration files during installation], - [OVERWRITE_CONFIG="${enable_overwrite}"], - [OVERWRITE_CONFIG="no"] -) -AC_MSG_RESULT([$OVERWRITE_CONFIG]) - -dnl --------------------- check for LDAP support, for client-side ACL visibility -AC_MSG_CHECKING(for LDAP (necessary for client-side ACL visibility)) -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) - -if test x"$with_ldap" != x"no" ; then - AC_CHECK_HEADER([ldap.h], with_ldap=yes, - [ if test x"$with_ldap" = x"yes" ; then - AC_MSG_ERROR([Missing LDAP headers]) - fi - with_ldap=no - ]) - AC_CHECK_LIB(ldap, ldap_init, with_ldap=yes, - [ if test x"$with_ldap" = x"yes" ; then - AC_MSG_ERROR([Missing LDAP library]) - fi - with_ldap=no - ]) -fi - -if test x"$with_ldap" = x"yes"; then - AC_DEFINE(HAVE_LDAP,1,[Whether LDAP is available]) -fi - -dnl --------------------- check for ACL support -AC_MSG_CHECKING(whether to support ACLs) -AC_ARG_WITH(acls, - [AS_HELP_STRING([--with-acls], - [Include ACL support (default=auto)])], - [ case "$withval" in - yes|no) - with_acl_support="$withval" - ;; - *) - with_acl_support=auto - ;; - esac ], - [with_acl_support=auto]) -AC_MSG_RESULT($with_acl_support) - -if test x"$with_acl_support" = x"no"; then - AC_MSG_RESULT(Disabling ACL support) - AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support should be built in]) -else - with_acl_support=yes -fi - -if test x"$with_acl_support" = x"yes" ; then - AC_MSG_NOTICE(checking whether ACL support is available:) - case "$host_os" in - *sysv5*) - AC_MSG_NOTICE(Using UnixWare ACLs) - AC_DEFINE(HAVE_UNIXWARE_ACLS,1,[Whether UnixWare ACLs are available]) - ;; - *solaris*) - AC_MSG_NOTICE(Using solaris ACLs) - AC_DEFINE(HAVE_SOLARIS_ACLS,1,[Whether solaris ACLs are available]) - ACL_LIBS="$ACL_LIBS -lsec" - ;; - *hpux*) - AC_MSG_NOTICE(Using HPUX ACLs) - AC_DEFINE(HAVE_HPUX_ACLS,1,[Whether HPUX ACLs are available]) - ;; - *irix*) - AC_MSG_NOTICE(Using IRIX ACLs) - AC_DEFINE(HAVE_IRIX_ACLS,1,[Whether IRIX ACLs are available]) - ;; - *aix*) - AC_MSG_NOTICE(Using AIX ACLs) - AC_DEFINE(HAVE_AIX_ACLS,1,[Whether AIX ACLs are available]) - ;; - *osf*) - AC_MSG_NOTICE(Using Tru64 ACLs) - AC_DEFINE(HAVE_TRU64_ACLS,1,[Whether Tru64 ACLs are available]) - ACL_LIBS="$ACL_LIBS -lpacl" - ;; - *darwin*) - AC_MSG_NOTICE(ACLs on Darwin currently not supported) - AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available]) - ;; - *) - AC_CHECK_LIB(acl,acl_get_file,[ACL_LIBS="$ACL_LIBS -lacl"]) - case "$host_os" in - *linux*) - AC_CHECK_LIB(attr,getxattr,[ACL_LIBS="$ACL_LIBS -lattr"]) - ;; - esac - AC_CACHE_CHECK([for POSIX ACL support],netatalk_cv_HAVE_POSIX_ACLS,[ - acl_LIBS=$LIBS - LIBS="$LIBS $ACL_LIBS" - AC_TRY_LINK([ - #include - #include - ],[ - acl_t acl; - int entry_id; - acl_entry_t *entry_p; - return acl_get_entry(acl, entry_id, entry_p); - ], - [netatalk_cv_HAVE_POSIX_ACLS=yes], - [netatalk_cv_HAVE_POSIX_ACLS=no - with_acl_support=no]) - LIBS=$acl_LIBS - ]) - if test x"$netatalk_cv_HAVE_POSIX_ACLS" = x"yes"; then - AC_MSG_NOTICE(Using POSIX ACLs) - AC_DEFINE(HAVE_POSIX_ACLS,1,[Whether POSIX ACLs are available]) - AC_CACHE_CHECK([for acl_get_perm_np],netatalk_cv_HAVE_ACL_GET_PERM_NP,[ - acl_LIBS=$LIBS - LIBS="$LIBS $ACL_LIBS" - AC_TRY_LINK([ - #include - #include - ],[ - acl_permset_t permset_d; - acl_perm_t perm; - return acl_get_perm_np(permset_d, perm); - ], - [samba_cv_HAVE_ACL_GET_PERM_NP=yes], - [samba_cv_HAVE_ACL_GET_PERM_NP=no]) - LIBS=$acl_LIBS - ]) - if test x"netatalk_cv_HAVE_ACL_GET_PERM_NP" = x"yes"; then - AC_DEFINE(HAVE_ACL_GET_PERM_NP,1,[Whether acl_get_perm_np() is available]) - fi - else - AC_MSG_NOTICE(ACL support is not avaliable) - AC_DEFINE(HAVE_NO_ACLS,1,[Whether no ACLs support is available]) - fi - ;; - esac -fi - -if test x"$with_acl_support" = x"yes" ; then - AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available]) - AC_SUBST(ACL_LIBS) -fi - -dnl --------------------- check for Extended Attributes support -neta_cv_eas="ad" -neta_cv_eas_sys_found=no -neta_cv_eas_sys_not_found=no - -AC_CHECK_HEADERS(sys/attributes.h attr/xattr.h sys/xattr.h sys/extattr.h sys/uio.h sys/ea.h) - -case "$this_os" in - - *osf*) - AC_SEARCH_LIBS(getproplist, [proplist]) - AC_CHECK_FUNCS([getproplist fgetproplist setproplist fsetproplist], - [neta_cv_eas_sys_found=yes], - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([delproplist fdelproplist add_proplist_entry get_proplist_entry],, - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([sizeof_proplist_entry],, - [neta_cv_eas_sys_not_found=yes]) - ;; - - *solaris*) - AC_CHECK_FUNCS([attropen], - [neta_cv_eas_sys_found=yes], - [neta_cv_eas_sys_not_found=yes]) - ;; - - 'freebsd') - AC_CHECK_FUNCS([extattr_delete_fd extattr_delete_file extattr_delete_link], - [neta_cv_eas_sys_found=yes], - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([extattr_get_fd extattr_get_file extattr_get_link],, - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([extattr_list_fd extattr_list_file extattr_list_link],, - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([extattr_set_fd extattr_set_file extattr_set_link],, - [neta_cv_eas_sys_not_found=yes]) - ;; - - *freebsd4* | *dragonfly* ) - AC_DEFINE(BROKEN_EXTATTR, 1, [Does extattr API work]) - ;; - - *) - AC_SEARCH_LIBS(getxattr, [attr]) - - if test "x$neta_cv_eas_sys_found" != "xyes" ; then - AC_CHECK_FUNCS([getxattr lgetxattr fgetxattr listxattr llistxattr], - [neta_cv_eas_sys_found=yes], - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([flistxattr removexattr lremovexattr fremovexattr],, - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([setxattr lsetxattr fsetxattr],, - [neta_cv_eas_sys_not_found=yes]) - fi - - if test "x$neta_cv_eas_sys_found" != "xyes" ; then - AC_CHECK_FUNCS([getea fgetea lgetea listea flistea llistea], - [neta_cv_eas_sys_found=yes], - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([removeea fremoveea lremoveea setea fsetea lsetea],, - [neta_cv_eas_sys_not_found=yes]) - fi - - if test "x$neta_cv_eas_sys_found" != "xyes" ; then - AC_CHECK_FUNCS([attr_get attr_list attr_set attr_remove],, - [neta_cv_eas_sys_not_found=yes]) - AC_CHECK_FUNCS([attr_getf attr_listf attr_setf attr_removef],, - [neta_cv_eas_sys_not_found=yes]) - fi - ;; -esac - -# Do xattr functions take additional options like on Darwin? -if test x"$ac_cv_func_getxattr" = x"yes" ; then - AC_CACHE_CHECK([whether xattr interface takes additional options], smb_attr_cv_xattr_add_opt, [ - old_LIBS=$LIBS - LIBS="$LIBS $ACL_LIBS" - AC_TRY_COMPILE([ - #include - #if HAVE_ATTR_XATTR_H - #include - #elif HAVE_SYS_XATTR_H - #include - #endif - ],[ - getxattr(0, 0, 0, 0, 0, 0); - ], - [smb_attr_cv_xattr_add_opt=yes], - [smb_attr_cv_xattr_add_opt=no;LIBS=$old_LIBS]) - ]) - if test x"$smb_attr_cv_xattr_add_opt" = x"yes"; then - AC_DEFINE(XATTR_ADD_OPT, 1, [xattr functions have additional options]) - fi -fi - -if test "x$neta_cv_eas_sys_found" = "xyes" ; then - if test "x$neta_cv_eas_sys_not_found" != "xyes" ; then - neta_cv_eas="$neta_cv_eas | sys" - fi -fi -AC_DEFINE_UNQUOTED(EA_MODULES,["$neta_cv_eas"],[Available Extended Attributes modules]) - -dnl --------------------- Check if realpath() takes NULL -AC_CACHE_CHECK([if the realpath function allows a NULL argument], - neta_cv_REALPATH_TAKES_NULL, [ - AC_TRY_RUN([ - #include - #include - #include - - void exit_on_core(int ignored) { - exit(1); - } - - main() { - char *newpath; - signal(SIGSEGV, exit_on_core); - newpath = realpath("/tmp", NULL); - exit((newpath != NULL) ? 0 : 1); - }], - neta_cv_REALPATH_TAKES_NULL=yes, - neta_cv_REALPATH_TAKES_NULL=no, - neta_cv_REALPATH_TAKES_NULL=cross - ) - ] -) - -if test x"$neta_cv_REALPATH_TAKES_NULL" = x"yes"; then - AC_DEFINE(REALPATH_TAKES_NULL,1,[Whether the realpath function allows NULL]) -fi - -dnl --------------------- Netatalk Webmin -NETATALK_WEBMIN - -dnl --------------------- last minute substitutions - AC_SUBST(LIBS) AC_SUBST(CFLAGS) -AC_SUBST(OVERWRITE_CONFIG) AM_CONDITIONAL(SOLARIS_MODULE, test x$solaris_module = xyes) -AM_CONDITIONAL(COMPILE_TIMELORD, test x$compile_timelord = xyes) -AM_CONDITIONAL(COMPILE_A2BOOT, test x$compile_a2boot = xyes) 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") @@@ -311,11 -1244,13 +316,11 @@@ AM_CONDITIONAL(HAVE_LDAP, test x"$with_ 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_KERBEROS, test x$compile_kerberos = xyes) AM_CONDITIONAL(USE_PAM_SO, test x$use_pam_so = xyes) AM_CONDITIONAL(USE_PAM, test x$netatalk_cv_install_pam = xyes) AM_CONDITIONAL(BUILD_PAM, test x$compile_pam = xyes) AM_CONDITIONAL(USE_PGP, test x$compile_pgp = xyes) AM_CONDITIONAL(DEFAULT_HOOK, test x$neta_cv_have_libgcrypt != xyes && test x$neta_cv_have_openssl != xyes) -AM_CONDITIONAL(USE_COBALT, test x$sysv_style = xcobalt) AM_CONDITIONAL(USE_NETBSD, test x$sysv_style = xnetbsd) AM_CONDITIONAL(USE_REDHAT, test x$sysv_style = xredhat) AM_CONDITIONAL(USE_SUSE, test x$sysv_style = xsuse) @@@ -326,27 -1261,38 +331,28 @@@ AM_CONDITIONAL(USE_GENTOO, test x$sysv_ AM_CONDITIONAL(USE_DEBIAN, test x$sysv_style = xdebian) AM_CONDITIONAL(USE_UNDEF, test x$sysv_style = x) AM_CONDITIONAL(USE_BDB, test x$bdb_required = xyes) -AM_CONDITIONAL(USE_APPLETALK, test x$netatalk_cv_ddp_enabled = xyes) + AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes") dnl --------------------- generate files AC_OUTPUT([Makefile bin/Makefile bin/ad/Makefile - bin/adv1tov2/Makefile - bin/aecho/Makefile bin/afppasswd/Makefile bin/cnid/Makefile bin/cnid/cnid2_create - bin/getzones/Makefile bin/megatron/Makefile bin/misc/Makefile - bin/nbp/Makefile - bin/pap/Makefile - bin/psorder/Makefile bin/uniconv/Makefile config/Makefile config/pam/Makefile contrib/Makefile contrib/macusers/Makefile contrib/macusers/macusers - contrib/printing/Makefile contrib/shell_utils/Makefile contrib/shell_utils/afpd-mtab.pl contrib/shell_utils/apple_dump contrib/shell_utils/asip-status.pl - contrib/timelord/Makefile - contrib/a2boot/Makefile distrib/Makefile distrib/config/Makefile distrib/config/netatalk-config @@@ -355,14 -1301,19 +361,14 @@@ doc/Makefile etc/Makefile etc/afpd/Makefile - etc/atalkd/Makefile etc/cnid_dbd/Makefile + etc/netalockd/Makefile etc/uams/Makefile - etc/uams/uams_krb4/Makefile - etc/papd/Makefile - etc/psf/Makefile include/Makefile include/atalk/Makefile libatalk/Makefile libatalk/acl/Makefile libatalk/adouble/Makefile - libatalk/asp/Makefile - libatalk/atp/Makefile libatalk/bstring/Makefile libatalk/cnid/Makefile libatalk/cnid/cdb/Makefile @@@ -371,24 -1322,31 +377,24 @@@ libatalk/cnid/tdb/Makefile libatalk/compat/Makefile libatalk/dsi/Makefile - libatalk/nbp/Makefile - libatalk/netddp/Makefile - libatalk/util/Makefile + libatalk/locking/Makefile + libatalk/rpc/Makefile + libatalk/talloc/Makefile + libatalk/tevent/Makefile + libatalk/tsocket/Makefile libatalk/tdb/Makefile libatalk/unicode/Makefile libatalk/unicode/charsets/Makefile + libatalk/util/Makefile libatalk/vfs/Makefile macros/Makefile man/Makefile man/man1/Makefile - man/man3/Makefile - man/man4/Makefile man/man5/Makefile man/man8/Makefile - sys/Makefile - sys/generic/Makefile - sys/generic/sys/Makefile - sys/netatalk/Makefile - sys/netbsd/Makefile - sys/netbsd/netatalk/Makefile - sys/solaris/Makefile - sys/sunos/Makefile - sys/ultrix/Makefile test/Makefile test/afpd/Makefile + test/netalockd/Makefile ], [chmod a+x distrib/config/netatalk-config contrib/shell_utils/apple_*] ) diff --combined etc/afpd/Makefile.am index a661a5e4,dd81a3f7..9b3fcae6 --- a/etc/afpd/Makefile.am +++ b/etc/afpd/Makefile.am @@@ -6,6 -6,7 +6,6 @@@ sbin_PROGRAMS = afp noinst_PROGRAMS = hash afpd_SOURCES = \ - afp_asp.c \ afp_avahi.c \ afp_config.c \ afp_dsi.c \ @@@ -43,10 -44,9 +43,10 @@@ afpd_LDADD = \ $(top_builddir)/libatalk/cnid/libcnid.la \ $(top_builddir)/libatalk/libatalk.la \ - @LIBGCRYPT_LIBS@ @ZEROCONF_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @PTHREAD_LIBS@ + $(top_builddir)/libevent/libevent.la \ - @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ ++ @LIBGCRYPT_LIBS@ @QUOTA_LIBS@ @SLP_LIBS@ @WRAP_LIBS@ @LIBADD_DL@ @ACL_LIBS@ @ZEROCONF_LIBS@ @PTHREAD_LIBS@ -afpd_LDFLAGS = -export-dynamic +afpd_LDFLAGS = -export-dynamic -static afpd_CFLAGS = \ -I$(top_srcdir)/include \ diff --combined etc/afpd/afp_config.c index f3adf7bf,7f5fd1f1..8c997ebe --- a/etc/afpd/afp_config.c +++ b/etc/afpd/afp_config.c @@@ -25,6 -25,9 +25,6 @@@ #include #include #include -#include -#include -#include #include #include #include @@@ -61,6 -64,15 +61,6 @@@ void configfree(AFPConfig *configs, con } switch (p->obj.proto) { -#ifndef NO_DDP - case AFPPROTO_ASP: - free(p->obj.Obj); - free(p->obj.Type); - free(p->obj.Zone); - atp_close(((ASP) p->obj.handle)->asp_atp); - free(p->obj.handle); - break; -#endif /* no afp/asp */ case AFPPROTO_DSI: close(p->fd); free(p->obj.handle); @@@ -86,6 -98,9 +86,6 @@@ static char * srvloc_encode(const struc char *conv_name; unsigned char *p; unsigned int i = 0; -#ifndef NO_DDP - char *Obj, *Type = "", *Zone = ""; -#endif /* Convert name to maccharset */ if ((size_t)-1 ==(convert_string_allocate( options->unixcharset, options->maccharset, @@@ -114,6 -129,15 +114,6 @@@ } buf[i] = '\0'; -#ifndef NO_DDP - /* Add ZONE, */ - if (nbp_name(options->server, &Obj, &Type, &Zone )) { - LOG(log_error, logtype_afpd, "srvloc_encode: can't parse %s", options->server ); - } - else { - snprintf( buf+i, sizeof(buf)-i-1 ,"&ZONE=%s", Zone); - } -#endif free (conv_name); return buf; @@@ -158,6 -182,38 +158,6 @@@ srvloc_dereg_err #endif /* USE_SRVLOC */ } -#ifndef NO_DDP -static void asp_cleanup(const AFPConfig *config) -{ - /* we need to stop tickle handler */ - asp_stop_tickle(); - nbp_unrgstr(config->obj.Obj, config->obj.Type, config->obj.Zone, - &config->obj.options.ddpaddr); -} - -/* these two are almost identical. it should be possible to collapse them - * into one with minimal junk. */ -static int asp_start(AFPConfig *config, AFPConfig *configs, - server_child *server_children) -{ - ASP asp; - - if (!(asp = asp_getsession(config->obj.handle, server_children, - config->obj.options.tickleval))) { - LOG(log_error, logtype_afpd, "main: asp_getsession: %s", strerror(errno) ); - exit( EXITERR_CLNT ); - } - - if (asp->child) { - configfree(configs, config); /* free a bunch of stuff */ - afp_over_asp(&config->obj); - exit (0); - } - - return 0; -} -#endif /* no afp/asp */ - static afp_child_t *dsi_start(AFPConfig *config, AFPConfig *configs, server_child *server_children) { @@@ -184,6 -240,102 +184,6 @@@ return child; } -#ifndef NO_DDP -static AFPConfig *ASPConfigInit(const struct afp_options *options, - unsigned char *refcount) -{ - AFPConfig *config; - ATP atp; - ASP asp; - char *Obj, *Type = "AFPServer", *Zone = "*"; - char *convname = NULL; - - if ((config = (AFPConfig *) calloc(1, sizeof(AFPConfig))) == NULL) - return NULL; - - if ((atp = atp_open(ATADDR_ANYPORT, &options->ddpaddr)) == NULL) { - LOG(log_error, logtype_afpd, "main: atp_open: %s", strerror(errno) ); - free(config); - return NULL; - } - - if ((asp = asp_init( atp )) == NULL) { - LOG(log_error, logtype_afpd, "main: asp_init: %s", strerror(errno) ); - atp_close(atp); - free(config); - return NULL; - } - - /* register asp server */ - Obj = (char *) options->hostname; - if (options->server && (size_t)-1 ==(convert_string_allocate( options->unixcharset, options->maccharset, - options->server, strlen(options->server), &convname)) ) { - if ((convname = strdup(options->server)) == NULL ) { - LOG(log_error, logtype_afpd, "malloc: %s", strerror(errno) ); - goto serv_free_return; - } - } - - if (nbp_name(convname, &Obj, &Type, &Zone )) { - LOG(log_error, logtype_afpd, "main: can't parse %s", options->server ); - goto serv_free_return; - } - if (convname) - free (convname); - - /* dup Obj, Type and Zone as they get assigned to a single internal - * buffer by nbp_name */ - if ((config->obj.Obj = strdup(Obj)) == NULL) - goto serv_free_return; - - if ((config->obj.Type = strdup(Type)) == NULL) { - free(config->obj.Obj); - goto serv_free_return; - } - - if ((config->obj.Zone = strdup(Zone)) == NULL) { - free(config->obj.Obj); - free(config->obj.Type); - goto serv_free_return; - } - - /* make sure we're not registered */ - nbp_unrgstr(Obj, Type, Zone, &options->ddpaddr); - if (nbp_rgstr( atp_sockaddr( atp ), Obj, Type, Zone ) < 0 ) { - LOG(log_error, logtype_afpd, "Can't register %s:%s@%s", Obj, Type, Zone ); - free(config->obj.Obj); - free(config->obj.Type); - free(config->obj.Zone); - goto serv_free_return; - } - - LOG(log_info, logtype_afpd, "%s:%s@%s started on %u.%u:%u (%s)", Obj, Type, Zone, - ntohs( atp_sockaddr( atp )->sat_addr.s_net ), - atp_sockaddr( atp )->sat_addr.s_node, - atp_sockaddr( atp )->sat_port, VERSION ); - - config->fd = atp_fileno(atp); - config->obj.handle = asp; - config->obj.config = config; - config->obj.proto = AFPPROTO_ASP; - - memcpy(&config->obj.options, options, sizeof(struct afp_options)); - config->optcount = refcount; - (*refcount)++; - - config->server_start = asp_start; - config->server_cleanup = asp_cleanup; - - return config; - -serv_free_return: - asp_close(asp); - free(config); - return NULL; -} -#endif /* no afp/asp */ - - static AFPConfig *DSIConfigInit(const struct afp_options *options, unsigned char *refcount, const dsi_proto protocol) @@@ -210,6 -362,7 +210,7 @@@ free(config); return NULL; } + dsi->dsireadbuf = options->dsireadbuf; if (options->flags & OPTION_PROXY) { LOG(log_note, logtype_afpd, "AFP/TCP proxy initialized for %s:%d (%s)", @@@ -320,7 -473,7 +321,7 @@@ srvloc_reg_err static AFPConfig *AFPConfigInit(struct afp_options *options, const struct afp_options *defoptions) { - AFPConfig *config = NULL, *next = NULL; + AFPConfig *next = NULL; unsigned char *refcount; if ((refcount = (unsigned char *) @@@ -329,6 -482,14 +330,6 @@@ return NULL; } -#ifndef NO_DDP - /* handle asp transports */ - if ((options->transports & AFPTRANS_DDP) && - (config = ASPConfigInit(options, refcount))) - config->defoptions = defoptions; -#endif /* NO_DDP */ - - /* set signature */ set_signature(options); @@@ -341,11 -502,10 +342,11 @@@ * (next = DSIConfigInit(options, refcount, i))) * next->defoptions = defoptions; */ - if ((options->transports & AFPTRANS_TCP) && - (((options->flags & OPTION_PROXY) == 0) || - ((options->flags & OPTION_PROXY) && config)) - && (next = DSIConfigInit(options, refcount, DSI_TCPIP))) + if ( (options->transports & AFPTRANS_TCP) + && + ((options->flags & OPTION_PROXY) == 0) + && + (next = DSIConfigInit(options, refcount, DSI_TCPIP))) next->defoptions = defoptions; /* load in all the authentication modules. we can load the same @@@ -357,7 -517,13 +358,7 @@@ /* this should be able to accept multiple dsi transports. i think * the only thing that gets affected is the net addresses. */ - status_init(config, next, options); - - /* attach dsi config to tail of asp config */ - if (config) { - config->next = next; - return config; - } + status_init(next, options); return next; } @@@ -425,8 -591,10 +426,10 @@@ AFPConfig *configinit(struct afp_option first = AFPConfigInit(cmdline, cmdline); /* Now register with zeroconf, we also need the volumes for that */ - load_volumes(&first->obj); - zeroconf_register(first); + if (! (first->obj.options.flags & OPTION_NOZEROCONF)) { + load_volumes(&first->obj); + zeroconf_register(first); + } return first; } diff --combined etc/afpd/afp_dsi.c index 11af0d10,0a735ea4..96188688 --- a/etc/afpd/afp_dsi.c +++ b/etc/afpd/afp_dsi.c @@@ -31,7 -31,6 +31,7 @@@ #include #include #include +#include #include "globals.h" #include "switch.h" @@@ -39,6 -38,11 +39,6 @@@ #include "fork.h" #include "dircache.h" -#ifdef FORCE_UIDGID -#warning UIDGID -#include "uid.h" -#endif /* FORCE_UIDGID */ - /* * We generally pass this from afp_over_dsi to all afp_* funcs, so it should already be * available everywhere. Unfortunately some funcs (eg acltoownermode) need acces to it @@@ -114,7 -118,7 +114,7 @@@ static void afp_dsi_die(int sig dsi_attention(AFPobj->handle, AFPATTN_SHUTDOWN); afp_dsi_close(AFPobj); - if (sig) /* if no signal, assume dieing because logins are disabled & + if (sig) /* if no signal, assume dieing because logins are disabled & don't log it (maintenance mode)*/ LOG(log_info, logtype_afpd, "Connection terminated"); if (sig == SIGTERM || sig == SIGALRM) { @@@ -280,7 -284,7 +280,7 @@@ static void alarm_handler(int sig _U_ if (dsi->flags & DSI_SLEEPING) { if (dsi->tickle > AFPobj->options.sleep) { - LOG(log_error, logtype_afpd, "afp_alarm: sleep time ended"); + LOG(log_note, logtype_afpd, "afp_alarm: sleep time ended"); afp_dsi_die(EXITERR_CLNT); } return; @@@ -288,7 -292,7 +288,7 @@@ if (dsi->flags & DSI_DISCONNECTED) { if (dsi->tickle > AFPobj->options.disconnected) { - LOG(log_error, logtype_afpd, "afp_alarm: no reconnect within 10 minutes, goodbye"); + LOG(log_error, logtype_afpd, "afp_alarm: reconnect timer expired, goodbye"); afp_dsi_die(EXITERR_CLNT); } return; @@@ -303,9 -307,11 +303,11 @@@ } if ((err = pollvoltime(AFPobj)) == 0) + LOG(log_debug, logtype_afpd, "afp_alarm: sending DSI tickle"); err = dsi_tickle(AFPobj->handle); if (err <= 0) { LOG(log_error, logtype_afpd, "afp_alarm: connection problem, entering disconnected state"); + dsi->proto_close(dsi); dsi->flags |= DSI_DISCONNECTED; } } @@@ -451,6 -457,26 +453,26 @@@ void afp_over_dsi(AFPObj *obj if (dircache_init(obj->options.dircachesize) != 0) afp_dsi_die(EXITERR_SYS); + /* set TCP snd/rcv buf */ + if (obj->options.tcp_rcvbuf) { + if (setsockopt(dsi->socket, + SOL_SOCKET, + SO_RCVBUF, + &obj->options.tcp_rcvbuf, + sizeof(obj->options.tcp_rcvbuf)) != 0) { + LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_RCVBUF): %s", strerror(errno)); + } + } + if (obj->options.tcp_sndbuf) { + if (setsockopt(dsi->socket, + SOL_SOCKET, + SO_SNDBUF, + &obj->options.tcp_sndbuf, + sizeof(obj->options.tcp_sndbuf)) != 0) { + LOG(log_error, logtype_dsi, "afp_over_dsi: setsockopt(SO_SNDBUF): %s", strerror(errno)); + } + } + /* get stuck here until the end */ while (1) { if (sigsetjmp(recon_jmp, 1) != 0) @@@ -469,6 -495,13 +491,13 @@@ } /* Some error on the client connection, enter disconnected state */ dsi->flags |= DSI_DISCONNECTED; + + /* the client sometimes logs out (afp_logout) but doesn't close the DSI session */ + if (dsi->flags & DSI_AFP_LOGGED_OUT) { + afp_dsi_close(obj); + exit(0); + } + pause(); /* gets interrupted by SIGALARM or SIGURG tickle */ continue; /* continue receiving until disconnect timer expires * or a primary reconnect succeeds */ @@@ -506,20 -539,24 +535,24 @@@ } } - if (cmd == DSIFUNC_TICKLE) { - /* timer is not every 30 seconds anymore, so we don't get killed on the client side. */ - if ((dsi->flags & DSI_DIE)) - dsi_tickle(dsi); - pending_request(dsi); - continue; - } dsi->flags |= DSI_DATA; + dsi->tickle = 0; + switch(cmd) { + case DSIFUNC_CLOSE: + LOG(log_debug, logtype_afpd, "DSI: close session request"); afp_dsi_close(obj); LOG(log_note, logtype_afpd, "done"); - return; + exit(0); + + case DSIFUNC_TICKLE: + dsi->flags &= ~DSI_DATA; /* thats no data in the sense we use it in alarm_handler */ + LOG(log_debug, logtype_afpd, "DSI: client tickle"); + /* timer is not every 30 seconds anymore, so we don't get killed on the client side. */ + if ((dsi->flags & DSI_DIE)) + dsi_tickle(dsi); break; case DSIFUNC_CMD: @@@ -535,12 -572,12 +568,12 @@@ function = (u_char) dsi->commands[0]; /* AFP replay cache */ - rc_idx = REPLAYCACHE_SIZE % dsi->clientID; + rc_idx = dsi->clientID % REPLAYCACHE_SIZE; LOG(log_debug, logtype_afpd, "DSI request ID: %u", dsi->clientID); if (replaycache[rc_idx].DSIreqID == dsi->clientID && replaycache[rc_idx].AFPcommand == function) { - LOG(log_debug, logtype_afpd, "AFP Replay Cache match: id: %u / cmd: %s", + LOG(log_note, logtype_afpd, "AFP Replay Cache match: id: %u / cmd: %s", dsi->clientID, AfpNum2name(function)); err = replaycache[rc_idx].result; /* AFP replay cache end */ @@@ -562,6 -599,11 +595,6 @@@ dir_free_invalid_q(); -#ifdef FORCE_UIDGID - /* bring everything back to old euid, egid */ - if (obj->force_uid) - restore_uidgid ( &obj->uidgid ); -#endif /* FORCE_UIDGID */ dsi->flags &= ~DSI_RUNNING; /* Add result to the AFP replay cache */ @@@ -603,6 -645,11 +636,6 @@@ AfpNum2name(function), AfpErr2name(err)); dsi->flags &= ~DSI_RUNNING; -#ifdef FORCE_UIDGID - /* bring everything back to old euid, egid */ - if (obj->force_uid) - restore_uidgid ( &obj->uidgid ); -#endif /* FORCE_UIDGID */ } else { LOG(log_error, logtype_afpd, "(write) bad function %x", function); dsi->datalen = 0; diff --combined etc/afpd/afp_options.c index fac01fde,f3724c13..ec4b762d --- a/etc/afpd/afp_options.c +++ b/etc/afpd/afp_options.c @@@ -186,6 -186,9 +186,9 @@@ void afp_options_init(struct afp_option options->dircachesize = DEFAULT_MAX_DIRCACHE_SIZE; options->flags |= OPTION_ACL2MACCESS; options->flags |= OPTION_UUID; + options->tcp_sndbuf = 0; /* 0 means don't change OS default */ + options->tcp_rcvbuf = 0; /* 0 means don't change OS default */ + options->dsireadbuf = 12; } /* parse an afpd.conf line. i'm doing it this way because it's @@@ -321,6 -324,12 +324,12 @@@ int afp_options_parseline(char *buf, st } } + if ((c = getoption(buf, "-dsireadbuf"))) { + options->dsireadbuf = atoi(c); + if (options->dsireadbuf < 6) + options->dsireadbuf = 6; + } + if ((c = getoption(buf, "-server_quantum"))) options->server_quantum = strtoul(c, NULL, 0); @@@ -407,6 -416,8 +416,6 @@@ if ((c = getoption(buf, "-port"))) options->port = strdup(c); - if ((c = getoption(buf, "-ddpaddr"))) - atalk_aton(c, &options->ddpaddr); if ((c = getoption(buf, "-signature")) && (opt = strdup(c))) options->signatureopt = opt; @@@ -461,6 -472,12 +470,12 @@@ if ((c = getoption(buf, "-dircachesize"))) options->dircachesize = atoi(c); + if ((c = getoption(buf, "-tcpsndbuf"))) + options->tcp_sndbuf = atoi(c); + + if ((c = getoption(buf, "-tcprcvbuf"))) + options->tcp_rcvbuf = atoi(c); + return 1; } @@@ -483,6 -500,13 +498,6 @@@ static void show_version( void printf( " TCP/IP Support:\t" ); puts( "Yes" ); - printf( "DDP(AppleTalk) Support:\t" ); -#ifdef NO_DDP - puts( "No" ); -#else - puts( "Yes" ); -#endif - printf( " CNID backends:\t" ); #ifdef CNID_BACKEND_CDB printf( "cdb "); @@@ -569,6 -593,20 +584,6 @@@ static void show_version_extended(void puts( "No" ); #endif - printf( " Dropbox kludge:\t" ); -#ifdef DROPKLUDGE - puts( "Yes" ); -#else - puts( "No" ); -#endif - - printf( " Force volume uid/gid:\t" ); -#ifdef FORCE_UIDGID - puts( "Yes" ); -#else - puts( "No" ); -#endif - printf( " ACL support:\t" ); #ifdef HAVE_ACLS puts( "Yes" ); diff --combined etc/afpd/auth.c index 9245293c,566a8d0e..0768d22d --- a/etc/afpd/auth.c +++ b/etc/afpd/auth.c @@@ -10,12 -10,13 +10,12 @@@ #include #include #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ #include #include #include -#include +#include + #include #include #include @@@ -72,6 -73,11 +72,6 @@@ int ngroups * These numbers are scattered throughout the code. */ static struct afp_versions afp_versions[] = { -#ifndef NO_DDP - { "AFPVersion 1.1", 11 }, - { "AFPVersion 2.0", 20 }, - { "AFPVersion 2.1", 21 }, -#endif /* ! NO_DDP */ { "AFP2.2", 22 }, { "AFPX03", 30 }, { "AFP3.1", 31 }, @@@ -88,7 -94,7 +88,7 @@@ static struct uam_obj uam_changepw = {" static struct uam_obj *afp_uam = NULL; -void status_versions( char *data, const ASP asp, const DSI *dsi) +void status_versions( char *data, const DSI *dsi) { char *start = data; u_int16_t status; @@@ -98,6 -104,9 +98,6 @@@ num = sizeof( afp_versions ) / sizeof( afp_versions[ 0 ] ); for ( i = 0; i < num; i++ ) { -#ifndef NO_DDP - if ( !asp && (afp_versions[ i ].av_number <= 21)) continue; -#endif /* ! NO_DDP */ if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue; count++; } @@@ -105,6 -114,9 +105,6 @@@ *data++ = count; for ( i = 0; i < num; i++ ) { -#ifndef NO_DDP - if ( !asp && (afp_versions[ i ].av_number <= 21)) continue; -#endif /* ! NO_DDP */ if ( !dsi && (afp_versions[ i ].av_number >= 22)) continue; len = strlen( afp_versions[ i ].av_name ); *data++ = len; @@@ -256,6 -268,45 +256,6 @@@ static int login(AFPObj *obj, struct pa LOG(log_note, logtype_afpd, "%s Login by %s", afp_versions[afp_version_index].av_name, pwd->pw_name); -#ifndef NO_DDP - if (obj->proto == AFPPROTO_ASP) { - ASP asp = obj->handle; - int addr_net = ntohs( asp->asp_sat.sat_addr.s_net ); - int addr_node = asp->asp_sat.sat_addr.s_node; - - if (obj->options.authprintdir) { - if(addr_net && addr_node) { /* Do we have a valid Appletalk address? */ - char nodename[256]; - FILE *fp; - int mypid = getpid(); - struct stat stat_buf; - - sprintf(nodename, "%s/net%d.%dnode%d", obj->options.authprintdir, - addr_net / 256, addr_net % 256, addr_node); - LOG(log_info, logtype_afpd, "registering %s (uid %d) on %u.%u as %s", - pwd->pw_name, pwd->pw_uid, addr_net, addr_node, nodename); - - if (stat(nodename, &stat_buf) == 0) { /* file exists */ - if (S_ISREG(stat_buf.st_mode)) { /* normal file */ - unlink(nodename); - fp = fopen(nodename, "w"); - fprintf(fp, "%s:%d\n", pwd->pw_name, mypid); - fclose(fp); - chown( nodename, pwd->pw_uid, -1 ); - } else { /* somebody is messing with us */ - LOG(log_error, logtype_afpd, "print authfile %s is not a normal file, it will not be modified", nodename ); - } - } else { /* file 'nodename' does not exist */ - fp = fopen(nodename, "w"); - fprintf(fp, "%s:%d\n", pwd->pw_name, mypid); - fclose(fp); - chown( nodename, pwd->pw_uid, -1 ); - } - } /* if (addr_net && addr_node ) */ - } /* if (options->authprintdir) */ - } /* if (obj->proto == AFPPROTO_ASP) */ -#endif - if (initgroups( pwd->pw_name, pwd->pw_gid ) < 0) { #ifdef RUN_AS_USER LOG(log_info, logtype_afpd, "running with uid %d", geteuid()); @@@ -376,16 -427,23 +376,18 @@@ obj->uid = geteuid(); obj->logout = logout; -#ifdef FORCE_UIDGID - obj->force_uid = 1; - save_uidgid ( &obj->uidgid ); -#endif - return( AFP_OK ); } /* ---------------------- */ - int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) + int afp_zzz(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen) { uint32_t data; DSI *dsi = (DSI *)AFPobj->handle; *rbuflen = 0; + ibuf += 2; + ibuflen -= 2; if (ibuflen < 4) return AFPERR_MISC; @@@ -401,19 -459,20 +403,20 @@@ if (data & AFPZZZ_EXT_WAKEUP) { /* wakeup request from exetended sleep */ if (dsi->flags & DSI_EXTSLEEP) { - LOG(log_debug, logtype_afpd, "afp_zzz: waking up from extended sleep"); + LOG(log_note, logtype_afpd, "afp_zzz: waking up from extended sleep"); dsi->flags &= ~(DSI_SLEEPING | DSI_EXTSLEEP); } } else { /* sleep request */ dsi->flags |= DSI_SLEEPING; if (data & AFPZZZ_EXT_SLEEP) { - LOG(log_debug, logtype_afpd, "afp_zzz: entering extended sleep"); + LOG(log_note, logtype_afpd, "afp_zzz: entering extended sleep"); dsi->flags |= DSI_EXTSLEEP; } else { - LOG(log_debug, logtype_afpd, "afp_zzz: entering normal sleep"); + LOG(log_note, logtype_afpd, "afp_zzz: entering normal sleep"); } } + /* * According to AFP 3.3 spec we should not return anything, * but eg 10.5.8 server still returns the numbers of hours @@@ -876,11 -935,15 +879,15 @@@ int afp_logincont(AFPObj *obj, char *ib } - int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen _U_) + int afp_logout(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { + DSI *dsi = (DSI *)(obj->handle); + LOG(log_note, logtype_afpd, "AFP logout by %s", obj->username); + of_close_all_forks(); close_all_vol(); - obj->exit(0); + dsi->flags = DSI_AFP_LOGGED_OUT; + *rbuflen = 0; return AFP_OK; } diff --combined etc/afpd/directory.c index 3edbec25,b981af66..488f900a --- a/etc/afpd/directory.c +++ b/etc/afpd/directory.c @@@ -28,6 -28,7 +28,7 @@@ #include #include #include + #include #include "directory.h" #include "dircache.h" @@@ -301,7 -302,7 +302,7 @@@ static int cname_mtouname(const struct { static char temp[ MAXPATHLEN + 1]; char *t; - cnid_t fileid; + cnid_t fileid = 0; if (afp_version >= 30) { if (toUTF8) { @@@ -429,6 -430,84 +430,84 @@@ int get_afp_errno(const int param return param; } + /*! + * Resolve struct dir for an absolute path + * + * Given a path like "/Volumes/volume/dir/subdir" in a volume "/Volumes/volume" return + * a pointer to struct dir of "subdir". + * 1. Remove volue path from absolute path + * 2. start path + * 3. loop through all elements of the remaining path from 1. + * 4. we only allow dirs + * 5. search dircache + * 6. if not found in the dircache query the CNID database for the DID + * 7. and use dirlookup to resolve the DID to a it's struct dir * + * + * @param vol (r) volume the path is in, must be known + * @param path (r) absoule path + * + * @returns pointer to struct dir or NULL on error + */ + struct dir *dirlookup_bypath(const struct vol *vol, const char *path) + { + EC_INIT; + + struct dir *dir = NULL; + cnid_t cnid, did; + bstring rpath = NULL; + bstring statpath = NULL; + struct bstrList *l = NULL; + struct stat st; + + cnid = htonl(2); + dir = vol->v_root; + + EC_NULL(rpath = rel_path_in_vol(path, vol->v_path)); /* 1. */ + EC_NULL(statpath = bfromcstr(vol->v_path)); /* 2. */ + + l = bsplit(rpath, '/'); + for (int i = 0; i < l->qty ; i++) { /* 3. */ + did = cnid; + EC_ZERO(bconcat(statpath, l->entry[i])); + EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st), + "lstat(rpath: %s, elem: %s): %s: %s", + cfrombstr(rpath), cfrombstr(l->entry[i]), + cfrombstr(statpath), strerror(errno)); + + if (!(S_ISDIR(st.st_mode))) /* 4. */ + EC_FAIL; + + if ((dir = dircache_search_by_name(vol, /* 5. */ + dir, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + st.st_ctime)) == NULL) { + if ((cnid = cnid_add(vol->v_cdb, /* 6. */ + &st, + did, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + 0)) == CNID_INVALID) { + EC_FAIL; + } + + if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */ + EC_FAIL; + } + + EC_ZERO(bcatcstr(statpath, "/")); + } + + EC_CLEANUP: + bdestroy(rpath); + bstrListDestroy(l); + bdestroy(statpath); + if (ret != 0) + return NULL; + + return dir; + } + /*! * @brief Resolve a DID * @@@ -446,9 -525,6 +525,6 @@@ * @param did (r) DID to resolve * * @returns pointer to struct dir - * - * @note FIXME: OSX calls it with bogus id, ie file ID not folder ID, - * and we are really bad in this case. */ struct dir *dirlookup(const struct vol *vol, cnid_t did) { @@@ -463,24 -539,28 +539,28 @@@ int utf8; int err = 0; - LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {start}", ntohl(did)); + LOG(log_debug, logtype_afpd, "dirlookup(did: %u)", ntohl(did)); /* check for did 0, 1 and 2 */ if (did == 0 || vol == NULL) { /* 1 */ afp_errno = AFPERR_PARAM; - return NULL; + ret = NULL; + goto exit; } else if (did == DIRDID_ROOT_PARENT) { rootParent.d_vid = vol->v_vid; - return (&rootParent); + ret = &rootParent; + goto exit; } else if (did == DIRDID_ROOT) { - return vol->v_root; + ret = vol->v_root; + goto exit; } /* Search the cache */ if ((ret = dircache_search_by_did(vol, did)) != NULL) { /* 2a */ if (ret->d_fullpath == NULL) { /* 2b */ afp_errno = AFPERR_BADTYPE; - return NULL; + ret = NULL; + goto exit; } if (lstat(cfrombstr(ret->d_fullpath), &st) != 0) { LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {lstat: %s}", ntohl(did), strerror(errno)); @@@ -491,14 -571,18 +571,18 @@@ LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {calling dir_remove()}", ntohl(did)); dir_remove(vol, ret); afp_errno = AFPERR_NOOBJ; - return NULL; + ret = NULL; + goto exit; default: - return ret; + ret = ret; + goto exit; } /* DEADC0DE */ - return NULL; + ret = NULL; + goto exit; } - return ret; + ret = ret; + goto exit; } utf8 = utf8_encoding(); @@@ -506,8 -590,12 +590,12 @@@ /* Get it from the database */ cnid = did; - if ( (upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL - || (upath = strdup(upath)) == NULL) { /* 3 */ + if ((upath = cnid_resolve(vol->v_cdb, &cnid, buffer, buflen)) == NULL) { + afp_errno = AFPERR_NOOBJ; + err = 1; + goto exit; + } + if ((upath = strdup(upath)) == NULL) { /* 3 */ afp_errno = AFPERR_NOOBJ; err = 1; goto exit; @@@ -519,6 -607,7 +607,7 @@@ * - DIRDID_ROOT is hit * - a cached entry is found */ + LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {recursion for did: %u}", ntohl(pdid)); if ((pdir = dirlookup(vol, pdid)) == NULL) { err = 1; goto exit; @@@ -573,14 -662,11 +662,11 @@@ } /* Add it to the cache only if it's a dir */ - if (dircache_add(ret) != 0) { /* 7 */ + if (dircache_add(vol, ret) != 0) { /* 7 */ err = 1; goto exit; } - LOG(log_debug, logtype_afpd, "dirlookup(did: %u) {end: did:%u, path:'%s'}", - ntohl(did), ntohl(pdid), cfrombstr(ret->d_fullpath)); - exit: if (upath) free(upath); if (err) { @@@ -593,6 -679,10 +679,10 @@@ ret = NULL; } } + if (ret) + LOG(log_debug, logtype_afpd, "dirlookup(did: %u): pdid: %u, \"%s\"", + ntohl(ret->d_did), ntohl(ret->d_pdid), cfrombstr(ret->d_fullpath)); + return ret; } @@@ -802,7 -892,7 +892,7 @@@ struct dir *dir_add(struct vol *vol, co /* get_id needs adp for reading CNID from adouble file */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ((ad_open_metadata(path->u_name, ADFLAGS_DIR, 0, &ad)) == 0) /* 1 */ + if ((ad_open(&ad, path->u_name, ADFLAGS_HF | ADFLAGS_DIR)) == 0) /* 1 */ adp = &ad; /* Get CNID */ @@@ -817,6 -907,7 +907,7 @@@ /* Get macname from unixname */ if (path->m_name == NULL) { if ((path->m_name = utompath(vol, path->u_name, id, utf8_encoding())) == NULL) { + LOG(log_error, logtype_afpd, "dir_add(\"%s\"): can't assign macname", path->u_name); err = 2; goto exit; } @@@ -837,7 -928,7 +928,7 @@@ goto exit; } - if ((dircache_add(cdir)) != 0) { /* 4 */ + if ((dircache_add(vol, cdir)) != 0) { /* 4 */ LOG(log_error, logtype_afpd, "dir_add: fatal dircache error: %s", cfrombstr(fullpath)); exit(EXITERR_SYS); } @@@ -880,9 -971,9 +971,9 @@@ void dir_free_invalid_q(void * @brief Remove a dir from a cache and queue it for freeing * * 1. Check if the dir is locked or has opened forks - * 2. If it's a request to remove curdir, just chdir to volume root - * 3. Remove it from the cache - * 4. Queue it for removal + * 2. Remove it from the cache + * 3. Queue it for removal + * 4. If it's a request to remove curdir, mark curdir as invalid * 5. Mark it as invalid * * @param (r) pointer to struct vol @@@ -896,27 -987,21 +987,21 @@@ int dir_remove(const struct vol *vol, s if (dir->d_did == DIRDID_ROOT_PARENT || dir->d_did == DIRDID_ROOT) return 0; - if (dir->d_flags & DIRF_CACHELOCK) { /* 1 */ - LOG(log_warning, logtype_afpd, "dir_remove(did:%u,'%s'): dir is locked", - ntohl(dir->d_did), cfrombstr(dir->d_u_name)); - return 0; - } - - if (curdir == dir) { /* 2 */ - if (movecwd(vol, vol->v_root) < 0) { - LOG(log_error, logtype_afpd, "dir_remove: can't chdir to : %s", vol->v_root); - } - } - LOG(log_debug, logtype_afpd, "dir_remove(did:%u,'%s'): {removing}", ntohl(dir->d_did), cfrombstr(dir->d_u_name)); - dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 3 */ - enqueue(invalid_dircache_entries, dir); /* 4 */ + dircache_remove(vol, dir, DIRCACHE | DIDNAME_INDEX | QUEUE_INDEX); /* 2 */ + enqueue(invalid_dircache_entries, dir); /* 3 */ + + if (curdir == dir) /* 4 */ + curdir = NULL; + dir->d_did = CNID_INVALID; /* 5 */ + return 0; } + #if 0 /* unused */ /*! * @brief Modify a struct dir, adjust cache * @@@ -988,13 -1073,14 +1073,14 @@@ int dir_modify(const struct vol *vol dir->d_m_name_ucs2 = NULL; /* Re-add it to the cache */ - if ((dircache_add(dir)) != 0) { + if ((dircache_add(vol, dir)) != 0) { dircache_dump(); AFP_PANIC("dir_modify"); } return ret; } + #endif /*! * @brief Resolve a catalog node name path @@@ -1104,7 -1190,7 +1190,7 @@@ struct path *cname(struct vol *vol, str /* 6*/ for ( p = path; *data != 0 && len > 0; len-- ) { *p++ = *data++; - if (p > &path[ MAXPATHLEN]) { + if (p > &path[UTF8FILELEN_EARLY]) { /* FIXME safeguard, limit of early Mac OS X */ afp_errno = AFPERR_PARAM; return NULL; } @@@ -1253,21 -1339,19 +1339,19 @@@ int movecwd(const struct vol *vol, stru AFP_ASSERT(vol); AFP_ASSERT(dir); - LOG(log_maxdebug, logtype_afpd, "movecwd(curdir:'%s', cwd:'%s')", - cfrombstr(curdir->d_fullpath), getcwdpath()); + LOG(log_maxdebug, logtype_afpd, "movecwd: from: curdir:\"%s\", cwd:\"%s\"", + curdir ? cfrombstr(curdir->d_fullpath) : "INVALID", getcwdpath()); - if ( dir == curdir) - return( 0 ); if (dir->d_did == DIRDID_ROOT_PARENT) { curdir = &rootParent; return 0; } - LOG(log_debug, logtype_afpd, "movecwd(did:%u, '%s')", + LOG(log_debug, logtype_afpd, "movecwd(to: did: %u, \"%s\")", ntohl(dir->d_did), cfrombstr(dir->d_fullpath)); if ((ret = lchdir(cfrombstr(dir->d_fullpath))) != 0 ) { - LOG(log_debug, logtype_afpd, "movecwd('%s'): ret: %u, %s", + LOG(log_debug, logtype_afpd, "movecwd(\"%s\"): ret: %u, %s", cfrombstr(dir->d_fullpath), ret, strerror(errno)); if (ret == 1) { /* p is a symlink or getcwd failed */ @@@ -1328,10 -1412,18 +1412,18 @@@ int file_access(struct path *path, int struct maccess ma; accessmode(path->u_name, &ma, curdir, &path->st); - if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) + + LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x", + path->u_name, ma.ma_user); + + if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE)) { + LOG(log_debug, logtype_afpd, "file_access(\"%s\"): write access denied", path->u_name); return -1; - if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) + } + if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD)) { + LOG(log_debug, logtype_afpd, "file_access(\"%s\"): read access denied", path->u_name); return -1; + } return 0; } @@@ -1382,8 -1474,20 +1474,8 @@@ int getdirparams(const struct vol *vol (1 << DIRPBIT_FINFO)))) { ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ( !ad_metadata( upath, ADFLAGS_CREATE|ADFLAGS_DIR, &ad) ) { + if ( !ad_metadata( upath, ADFLAGS_DIR, &ad) ) isad = 1; - if (ad.ad_md->adf_flags & O_CREAT) { - /* We just created it */ - ad_setname(&ad, s_path->m_name); - ad_setid( &ad, - s_path->st.st_dev, - s_path->st.st_ino, - dir->d_did, - dir->d_pdid, - vol->v_stamp); - ad_flush( &ad); - } - } } pdid = dir->d_pdid; @@@ -1787,7 -1891,7 +1879,7 @@@ int setdirparams(struct vol *vol, struc } ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open_metadata( upath, ADFLAGS_DIR, O_CREAT, &ad) < 0) { + if (ad_open(&ad, upath, ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) != 0) { /* * Check to see what we're trying to set. If it's anything * but ACCESS, UID, or GID, give an error. If it's any of those @@@ -1809,7 -1913,7 +1901,7 @@@ * Check to see if a create was necessary. If it was, we'll want * to set our name, etc. */ - if ( (ad_get_HF_flags( &ad ) & O_CREAT)) { + if ( (ad_get_MD_flags( &ad ) & O_CREAT)) { ad_setname(&ad, cfrombstr(curdir->d_m_name)); } } @@@ -2140,7 -2244,7 +2232,7 @@@ int afp_createdir(AFPObj *obj, char *ib } ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad ) < 0) { + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR, O_CREAT, 0777) < 0) { if (vol_noadouble(vol)) goto createdir_done; return( AFPERR_ACCESS ); @@@ -2206,7 -2310,7 +2298,7 @@@ int renamedir(const struct vol *vol ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (!ad_open_metadata( dst, ADFLAGS_DIR, 0, &ad)) { + if (ad_open(&ad, dst, ADFLAGS_HF | ADFLAGS_DIR) == 0) { ad_setname(&ad, newname); ad_flush( &ad); ad_close_metadata( &ad); @@@ -2220,13 -2324,13 +2312,13 @@@ int deletecurdir(struct vol *vol { struct dirent *de; struct stat st; - struct dir *fdir; + struct dir *fdir, *pdir; DIR *dp; struct adouble ad; u_int16_t ashort; int err; - if ( dirlookup(vol, curdir->d_pdid) == NULL ) { + if ((pdir = dirlookup(vol, curdir->d_pdid)) == NULL) { return( AFPERR_ACCESS ); } @@@ -2244,6 -2348,8 +2336,8 @@@ } err = vol->vfs->vfs_deletecurdir(vol); if (err) { + LOG(log_error, logtype_afpd, "deletecurdir: error deleting .AppleDouble in \"%s\"", + curdir->d_fullpath); return err; } @@@ -2256,6 -2362,8 +2350,8 @@@ /* bail if it's not a symlink */ if ((lstat(de->d_name, &st) == 0) && !S_ISLNK(st.st_mode)) { + LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): not empty", + curdir->d_fullpath); closedir(dp); return AFPERR_DIRNEMPT; } @@@ -2267,16 -2375,23 +2363,23 @@@ } } - if ( movecwd(vol, dirlookup(vol, curdir->d_pdid)) < 0 ) { + if (movecwd(vol, pdir) < 0) { err = afp_errno; goto delete_done; } + LOG(log_debug, logtype_afpd, "deletecurdir: moved to \"%s\"", + cfrombstr(curdir->d_fullpath)); + err = netatalk_rmdir_all_errors(-1, cfrombstr(fdir->d_u_name)); if ( err == AFP_OK || err == AFPERR_NOOBJ) { cnid_delete(vol->v_cdb, fdir->d_did); dir_remove( vol, fdir ); + } else { + LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error", + curdir->d_fullpath); } + delete_done: if (dp) { /* inode is used as key for cnid. diff --combined etc/afpd/directory.h index 731140ab,79c4a040..1504c649 --- a/etc/afpd/directory.h +++ b/etc/afpd/directory.h @@@ -24,8 -24,10 +24,8 @@@ #ifndef AFPD_DIRECTORY_H #define AFPD_DIRECTORY_H 1 -#include #include -/*#include */ /* including it here causes some confusion */ -#include +#include #include /* sys/types.h usually snarfs in major/minor macros. if they don't @@@ -46,7 -48,6 +46,6 @@@ #define DIRF_OFFCNT (1<<4) /* offsprings count is valid */ #define DIRF_CNID (1<<5) /* renumerate id */ - #define DIRF_CACHELOCK (1<<6) /* lock in cache, don't remove in dircache_eviction, for catsearch */ #define AFPDIR_READ (1<<0) @@@ -115,6 -116,8 +114,8 @@@ extern int dir_modify(const str const char *new_mname, const char *new_uname, bstring pdir_fullpath); extern int dir_remove(const struct vol *vol, struct dir *dir); extern struct dir *dirlookup (const struct vol *, cnid_t); + extern struct dir *dirlookup_bypath(const struct vol *vol, const char *path); + extern int movecwd (const struct vol *, struct dir *); extern struct path *cname (struct vol *, struct dir *, char **); diff --combined etc/afpd/file.c index bd0e935c,f7df6049..0459656f --- a/etc/afpd/file.c +++ b/etc/afpd/file.c @@@ -10,7 -10,22 +10,7 @@@ #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); - -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #include #include @@@ -150,8 -165,8 +150,8 @@@ char *set_name(const struct vol *vol, c else { u_int16_t temp; - if (aint > 255) /* FIXME safeguard, anyway if no ascii char it's game over*/ - aint = 255; + if (aint > UTF8FILELEN_EARLY) /* FIXME safeguard, anyway if no ascii char it's game over*/ + aint = UTF8FILELEN_EARLY; utf8 = vol->v_kTextEncoding; memcpy(data, &utf8, sizeof(utf8)); @@@ -301,6 -316,8 +301,8 @@@ int getmetadata(struct vol *vol struct stat *st; struct maccess ma; + LOG(log_debug, logtype_afpd, "getmetadata(\"%s\")", path->u_name); + upath = path->u_name; st = &path->st; data = buf; @@@ -333,7 -350,7 +335,7 @@@ exit(EXITERR_SYS); } - if ((dircache_add(cachedfile)) != 0) { + if ((dircache_add(vol, cachedfile)) != 0) { LOG(log_error, logtype_afpd, "getmetadata: fatal dircache error"); exit(EXITERR_SYS); } @@@ -598,17 -615,19 +600,19 @@@ int getfilparams(struct vol *vol int opened = 0; int rc; + LOG(log_debug, logtype_afpd, "getfilparams(\"%s\")", path->u_name); + opened = PARAM_NEED_ADP(bitmap); adp = NULL; if (opened) { char *upath; - int flags = (bitmap & (1 << FILPBIT_ATTR))?ADFLAGS_OPENFORKS:0; + int flags = (bitmap & (1 << FILPBIT_ATTR)) ? ADFLAGS_CHECK_OF : 0; adp = of_ad(vol, path, &ad); upath = path->u_name; - if ( ad_metadata( upath, flags|ADFLAGS_CREATE, adp) < 0 ) { + if ( ad_metadata( upath, flags, adp) < 0 ) { switch (errno) { case EACCES: LOG(log_error, logtype_afpd, "getfilparams(%s): %s: check resource fork permission?", @@@ -625,7 -644,9 +629,7 @@@ } } rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp); - if ( adp ) { - ad_close_metadata( adp); - } + ad_close_metadata( adp); return( rc ); } @@@ -633,7 -654,7 +637,7 @@@ /* ----------------------------- */ int afp_createfile(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { - struct adouble ad, *adp; + struct adouble ad; struct vol *vol; struct dir *dir; struct ofork *of = NULL; @@@ -649,8 -670,9 +653,8 @@@ memcpy(&vid, ibuf, sizeof( vid )); ibuf += sizeof( vid ); - if (NULL == ( vol = getvolbyvid( vid )) ) { + if (NULL == ( vol = getvolbyvid( vid )) ) return( AFPERR_PARAM ); - } if (vol->v_flags & AFPVOL_RO) return AFPERR_VLOCK; @@@ -658,35 -680,44 +662,35 @@@ memcpy(&did, ibuf, sizeof( did)); ibuf += sizeof( did ); - if (NULL == ( dir = dirlookup( vol, did )) ) { + if (NULL == ( dir = dirlookup( vol, did )) ) return afp_errno; - } - if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) { + if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) return get_afp_errno(AFPERR_PARAM); - } - if ( *s_path->m_name == '\0' ) { + if ( *s_path->m_name == '\0' ) return( AFPERR_BADTYPE ); - } upath = s_path->u_name; + ad_init(&ad, vol->v_adouble, vol->v_ad_options); /* if upath is deleted we already in trouble anyway */ if ((of = of_findname(s_path))) { - adp = of->of_ad; - } else { - ad_init(&ad, vol->v_adouble, vol->v_ad_options); - adp = &ad; - } - if ( creatf) { - /* on a hard create, fail if file exists and is open */ - if (of) + if (creatf) return AFPERR_BUSY; + else + return AFPERR_EXIST; + } + + if ( creatf) openf = O_RDWR|O_CREAT|O_TRUNC; - } else { + else /* on a soft create, if the file is open then ad_open won't fail - because open syscall is not called - */ - if (of) { - return AFPERR_EXIST; - } + because open syscall is not called */ openf = O_RDWR|O_CREAT|O_EXCL; - } - if ( ad_open( upath, ADFLAGS_DF|ADFLAGS_HF|ADFLAGS_NOHF|ADFLAGS_CREATE, - openf, 0666, adp) < 0 ) { + if ( ad_open(&ad, upath, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF, + openf, 0666, openf, 0666) < 0 ) { switch ( errno ) { case EROFS: return AFPERR_VLOCK; @@@ -703,28 -734,45 +707,39 @@@ return( AFPERR_PARAM ); } } - if ( ad_reso_fileno( adp ) == -1 ) { /* Hard META / HF */ + if ( ad_meta_fileno( &ad ) == -1 ) { /* Hard META / HF */ /* on noadouble volumes, just creating the data fork is ok */ if (vol_noadouble(vol)) { - ad_close( adp, ADFLAGS_DF ); + ad_close( &ad, ADFLAGS_DF ); goto createfile_done; } /* FIXME with hard create on an existing file, we already * corrupted the data file. */ netatalk_unlink( upath ); - ad_close( adp, ADFLAGS_DF ); + ad_close( &ad, ADFLAGS_DF ); return AFPERR_ACCESS; } path = s_path->m_name; - ad_setname(adp, path); + ad_setname(&ad, path); + + struct stat st; + if (lstat(upath, &st) != 0) { + LOG(log_error, logtype_afpd, "afp_createfile(\"%s\"): stat: %s", + upath, strerror(errno)); + ad_close( adp, ADFLAGS_DF|ADFLAGS_HF); + return AFPERR_MISC; + } + + (void)get_id(vol, adp, &st, dir->d_did, upath, strlen(upath)); + - ad_flush( adp); - ad_close( adp, ADFLAGS_DF|ADFLAGS_HF ); + ad_flush(&ad); + ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF ); createfile_done: curdir->offcnt++; -#ifdef DROPKLUDGE - if (vol->v_flags & AFPVOL_DROPBOX) { - retvalue = matchfile2dirperms(upath, vol, did); - } -#endif /* DROPKLUDGE */ - setvoltime(obj, vol ); return (retvalue); @@@ -939,7 -987,7 +954,7 @@@ int setfilparams(struct vol *vol /* second try with adouble open */ - if ( ad_open_metadata( upath, 0, O_CREAT, adp) < 0) { + if ( ad_open(adp, upath, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) < 0) { LOG(log_debug, logtype_afpd, "setfilparams: ad_open_metadata error"); /* * For some things, we don't need an adouble header: @@@ -952,7 -1000,7 +967,7 @@@ } LOG(log_debug, logtype_afpd, "setfilparams: no adouble perms, but only FILPBIT_MDATE and/or FILPBIT_UNIXPR"); isad = 0; - } else if ((ad_get_HF_flags( adp ) & O_CREAT) ) { + } else if ((ad_get_MD_flags( adp ) & O_CREAT) ) { ad_setname(adp, path->m_name); } @@@ -1033,6 -1081,7 +1048,6 @@@ setfilparam_done if (isad) { ad_flush( adp); ad_close_metadata( adp); - } if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) { @@@ -1063,6 -1112,9 +1078,9 @@@ int renamefile(const struct vol *vol, i { int rc; + LOG(log_debug, logtype_afpd, + "renamefile: src[%d, \"%s\"] -> dst[\"%s\"]", sdir_fd, src, dst); + if ( unix_rename( sdir_fd, src, -1, dst ) < 0 ) { switch ( errno ) { case ENOENT : @@@ -1115,8 -1167,9 +1133,8 @@@ } } - /* don't care if we can't open the newly renamed ressource fork - */ - if (!ad_open( dst, ADFLAGS_HF, O_RDWR, 0666, adp)) { + /* don't care if we can't open the newly renamed ressource fork */ + if (ad_open(adp, dst, ADFLAGS_HF, O_RDWR) == 0) { ad_setname(adp, newname); ad_flush( adp ); ad_close( adp, ADFLAGS_HF ); @@@ -1244,11 -1297,11 +1262,11 @@@ int afp_copyfile(AFPObj *obj, char *ibu adp = of_ad(s_vol, s_path, &ad); - if (ad_open(s_path->u_name , ADFLAGS_DF |ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) { + if (ad_open(adp, s_path->u_name, ADFLAGS_DF | ADFLAGS_HF | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) { return AFPERR_DENYCONF; } - denyreadset = (getforkmode(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || - getforkmode(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); + denyreadset = (ad_testlock(adp, ADEID_DFORK, AD_FILELOCK_DENY_RD) != 0 || + ad_testlock(adp, ADEID_RFORK, AD_FILELOCK_DENY_RD) != 0 ); if (denyreadset) { retvalue = AFPERR_DENYCONF; @@@ -1264,6 -1317,9 +1282,6 @@@ goto copy_exit; } -#ifdef FORCE_UIDGID - /* FIXME svid != dvid && dvid's user can't read svid */ -#endif if (NULL == ( d_vol = getvolbyvid( dvid )) ) { retvalue = AFPERR_PARAM; goto copy_exit; @@@ -1308,6 -1364,12 +1326,6 @@@ } curdir->offcnt++; -#ifdef DROPKLUDGE - if (vol->v_flags & AFPVOL_DROPBOX) { - retvalue=matchfile2dirperms(upath, vol, ddid); /* FIXME sdir or ddid */ - } -#endif /* DROPKLUDGE */ - setvoltime(obj, d_vol ); copy_exit: @@@ -1446,7 -1508,7 +1464,7 @@@ int copyfile(const struct vol *s_vol adflags |= ADFLAGS_HF; } - if (ad_openat(sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, 0, adp) < 0) { + if (ad_openat(adp, sfd, src, adflags | ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0) { ret_err = errno; goto done; } @@@ -1464,7 -1526,7 +1482,7 @@@ } ad_init(&add, d_vol->v_adouble, d_vol->v_ad_options); - if (ad_open(dst , adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, &add) < 0) { + if (ad_open(&add, dst, adflags, O_RDWR|O_CREAT|O_EXCL, st.st_mode, O_RDWR|O_CREAT|O_EXCL, st.st_mode) < 0) { ret_err = errno; ad_close( adp, adflags ); if (EEXIST != ret_err) { @@@ -1579,7 -1641,7 +1597,7 @@@ int deletefile(const struct vol *vol, i * moreover sometimes deletefile is called with a no existent file and * ad_open would create a 0 byte resource fork */ - if ( ad_metadataat(dirfd, file, ADFLAGS_OPENFORKS, &ad) == 0 ) { + if ( ad_metadataat(dirfd, file, ADFLAGS_CHECK_OF, &ad) == 0 ) { if ((err = check_attrib(&ad))) { ad_close_metadata(&ad); return err; @@@ -1590,7 -1652,7 +1608,7 @@@ /* try to open both forks at once */ adflags = ADFLAGS_DF; - if ( ad_openat(dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, 0, &ad ) < 0 ) { + if ( ad_openat(&ad, dirfd, file, adflags |ADFLAGS_HF|ADFLAGS_NOHF, O_RDONLY, O_RDONLY) < 0 ) { switch (errno) { case ENOENT: err = AFPERR_NOOBJ; @@@ -1733,12 -1795,32 +1751,12 @@@ static int reenumerate_loop(struct dire cnid_t did = param->did; cnid_t aint; - if ( lstat(de->d_name, &path.st)<0 ) + if ( lstat(de->d_name, &path.st) < 0 ) return 0; /* update or add to cnid */ aint = cnid_add(vol->v_cdb, &path.st, did, de->d_name, strlen(de->d_name), 0); /* ignore errors */ -#if AD_VERSION > AD_VERSION1 - if (aint != CNID_INVALID && !S_ISDIR(path.st.st_mode)) { - struct adouble ad, *adp; - - path.st_errno = 0; - path.st_valid = 1; - path.u_name = de->d_name; - - adp = of_ad(vol, &path, &ad); - - if ( ad_open_metadata( de->d_name, 0, 0, adp ) < 0 ) { - return 0; - } - if (ad_setid(adp, path.st.st_dev, path.st.st_ino, aint, did, vol->v_stamp)) { - ad_flush(adp); - } - ad_close_metadata(adp); - } -#endif /* AD_VERSION > AD_VERSION1 */ - return 0; } @@@ -2000,7 -2082,7 +2018,7 @@@ static struct adouble *find_adouble(str adp = (*of)->of_ad; } else { - ret = ad_open( path->u_name, ADFLAGS_HF, O_RDONLY, 0, adp); + ret = ad_open(adp, path->u_name, ADFLAGS_HF, O_RDONLY); /* META and HF */ if ( !ret && ad_reso_fileno(adp) != -1 && !(adp->ad_resource_fork.adf_flags & ( O_RDWR | O_WRONLY))) { /* from AFP spec. diff --combined etc/afpd/filedir.c index bb2bdd1d,8eb8bb4d..1478299e --- a/etc/afpd/filedir.c +++ b/etc/afpd/filedir.c @@@ -9,7 -9,24 +9,7 @@@ #include #include -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - -#ifdef HAVE_STRINGS_H -#include -#endif #include #include @@@ -34,6 -51,87 +34,6 @@@ #include "filedir.h" #include "unix.h" -#ifdef DROPKLUDGE -int matchfile2dirperms( -/* Since it's kinda' big; I decided against an - inline function */ - char *upath, - struct vol *vol, - int did) -/* The below code changes the way file ownership is determined in the name of - fixing dropboxes. It has known security problem. See the netatalk FAQ for - more information */ -{ - struct stat st, sb; - struct dir *dir; - char *adpath; - uid_t uid; - int ret = AFP_OK; -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "begin matchfile2dirperms:"); -#endif - - if (stat(upath, &st ) < 0) { - LOG(log_error, logtype_afpd, "Could not stat %s: %s", upath, strerror(errno)); - return AFPERR_NOOBJ ; - } - - adpath = vol->vfs->ad_path( upath, ADFLAGS_HF ); - /* FIXME dirsearch doesn't move cwd to did ! */ - if (( dir = dirlookup( vol, did )) == NULL ) { - LOG(log_error, logtype_afpd, "matchfile2dirperms: Unable to get directory info."); - ret = AFPERR_NOOBJ; - } - else if (stat(".", &sb) < 0) { - LOG(log_error, logtype_afpd, - "matchfile2dirperms: Error checking directory \"%s\": %s", - dir->d_m_name, strerror(errno)); - ret = AFPERR_NOOBJ; - } - else { - uid=geteuid(); - if ( uid != sb.st_uid ) - { - seteuid(0); - if (lchown(upath, sb.st_uid, sb.st_gid) < 0) - { - LOG(log_error, logtype_afpd, - "matchfile2dirperms(%s): Error changing owner/gid: %s", - upath, strerror(errno)); - ret = AFPERR_ACCESS; - } - else if ((!S_ISLNK(st->st_mode)) && (chmod(upath,(st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0)) - { - LOG(log_error, logtype_afpd, - "matchfile2dirperms(%s): Error adding file read permissions: %s", - upath, strerror(errno)); - ret = AFPERR_ACCESS; - } - else if (lchown(adpath, sb.st_uid, sb.st_gid) < 0) - { - LOG(log_error, logtype_afpd, - "matchfile2dirperms(%s): Error changing AppleDouble owner/gid: %s", - adpath, strerror(errno)); - ret = AFPERR_ACCESS; - } - else if (chmod(adpath, (st.st_mode&~default_options.umask)| S_IRGRP| S_IROTH) < 0) - { - LOG(log_error, logtype_afpd, - "matchfile2dirperms(%s): Error adding AD file read permissions: %s", - adpath, strerror(errno)); - ret = AFPERR_ACCESS; - } - seteuid(uid); - } - } /* end else if stat success */ - -#ifdef DEBUG - LOG(log_debug9, logtype_afpd, "end matchfile2dirperms:"); -#endif - return ret; -} -#endif - int afp_getfildirparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { struct stat *st; @@@ -230,7 -328,7 +230,7 @@@ static int moveandrename(const struct v char *newname, int isdir) { - char *p; + char *oldunixname = NULL; char *upath; int rc; struct stat *st, nst; @@@ -242,48 -340,52 +242,52 @@@ cnid_t id; int cwd_fd = -1; + LOG(log_debug, logtype_afpd, + "moveandrename: [\"%s\"/\"%s\"] -> \"%s\"", + cfrombstr(sdir->d_u_name), oldname, newname); + ad_init(&ad, vol->v_adouble, vol->v_ad_options); adp = &ad; adflags = 0; if (!isdir) { - if ((p = mtoupath(vol, oldname, sdir->d_did, utf8_encoding())) == NULL) + if ((oldunixname = strdup(mtoupath(vol, oldname, sdir->d_did, utf8_encoding()))) == NULL) return AFPERR_PARAM; /* can't convert */ + id = cnid_get(vol->v_cdb, sdir->d_did, oldunixname, strlen(oldunixname)); - #ifndef HAVE_RENAMEAT + #ifndef HAVE_ATFUNCS /* Need full path */ - id = cnid_get(vol->v_cdb, sdir->d_did, p, strlen(p)); - p = ctoupath( vol, sdir, oldname ); - if (!p) + free(oldunixname); + if ((oldunixname = strdup(ctoupath(vol, sdir, oldname))) == NULL) return AFPERR_PARAM; /* pathname too long */ - #endif /* HAVE_RENAMEAT */ + #endif /* HAVE_ATFUNCS */ path.st_valid = 0; - path.u_name = p; - #ifdef HAVE_RENAMEAT + path.u_name = oldunixname; + + #ifdef HAVE_ATFUNCS opened = of_findnameat(sdir_fd, &path); #else opened = of_findname(&path); - #endif /* HAVE_RENAMEAT */ + #endif /* HAVE_ATFUNCS */ + if (opened) { /* reuse struct adouble so it won't break locks */ adp = opened->of_ad; } } else { id = sdir->d_did; /* we already have the CNID */ - p = ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname ); - if (!p) { + if ((oldunixname = strdup(ctoupath( vol, dirlookup(vol, sdir->d_pdid), oldname))) == NULL) return AFPERR_PARAM; - } adflags = ADFLAGS_DIR; } /* - * p now points to either + * oldunixname now points to either * a) full pathname of the source fs object (if renameat is not available) * b) the oldname (renameat is available) * we are in the dest folder so we need to use - * a) p for ad_open + * a) oldunixname for ad_open * b) fchdir sdir_fd before eg ad_open or use *at functions where appropiate */ @@@ -295,11 -397,10 +299,11 @@@ goto exit; } } - if (!ad_metadata(p, adflags, adp)) { + if (!ad_metadata(oldunixname, adflags, adp)) { u_int16_t bshort; ad_getattr(adp, &bshort); + ad_close_metadata( adp); if ((bshort & htons(ATTRBIT_NORENAME))) { rc = AFPERR_OLOCK; @@@ -332,7 -433,7 +336,7 @@@ } if (stat(upath, st) == 0 || caseenumerate(vol, &path, curdir) == 0) { - if (!stat(p, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) { + if (!stat(oldunixname, &nst) && !(nst.st_dev == st->st_dev && nst.st_ino == st->st_ino) ) { /* not the same file */ rc = AFPERR_EXIST; goto exit; @@@ -350,12 -451,12 +354,12 @@@ if (of_findname(&path)) { rc = AFPERR_EXIST; /* was AFPERR_BUSY; */ } else { - rc = renamefile(vol, sdir_fd, p, upath, newname, adp ); + rc = renamefile(vol, sdir_fd, oldunixname, upath, newname, adp ); if (rc == AFP_OK) of_rename(vol, opened, sdir, oldname, curdir, newname); } } else { - rc = renamedir(vol, sdir_fd, p, upath, sdir, curdir, newname); + rc = renamedir(vol, sdir_fd, oldunixname, upath, sdir, curdir, newname); } if ( rc == AFP_OK && id ) { /* renaming may have moved the file/dir across a filesystem */ @@@ -371,6 -472,13 +375,13 @@@ (void)dir_remove(vol, cacheddir); } + /* Fixup adouble info */ + if (!ad_metadata(upath, adflags, adp)) { + ad_setid(adp, st->st_dev, st->st_ino, id, curdir->d_did, vol->v_stamp); + ad_flush(adp); + ad_close_metadata(adp); + } + /* fix up the catalog entry */ cnid_update(vol->v_cdb, id, st, curdir->d_did, upath, strlen(upath)); } @@@ -378,6 -486,8 +389,8 @@@ exit: if (cwd_fd != -1) close(cwd_fd); + if (oldunixname) + free(oldunixname); return rc; } @@@ -568,6 -678,9 +581,6 @@@ int afp_moveandrename(AFPObj *obj, cha int plen; u_int16_t vid; int rc; -#ifdef DROPKLUDGE - int retvalue; -#endif /* DROPKLUDGE */ int sdir_fd = -1; @@@ -612,7 -725,7 +625,7 @@@ memcpy(oldname, cfrombstr(sdir->d_m_name), blength(sdir->d_m_name) + 1); } - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if ((sdir_fd = open(".", O_RDONLY)) == -1) return AFPERR_MISC; #endif @@@ -656,18 -769,28 +669,18 @@@ } curdir->offcnt++; sdir->offcnt--; -#ifdef DROPKLUDGE - if (vol->v_flags & AFPVOL_DROPBOX) { - /* FIXME did is not always the source id */ - if ((retvalue=matchfile2dirperms (upath, vol, did)) != AFP_OK) { - rc = retvalue; - goto exit; - } - } - else -#endif /* DROPKLUDGE */ - /* if unix priv don't try to match perm with dest folder */ - if (!isdir && !vol_unix_priv(vol)) { - int admode = ad_mode("", 0777) | vol->v_fperm; + /* if unix priv don't try to match perm with dest folder */ + if (!isdir && !vol_unix_priv(vol)) { + int admode = ad_mode("", 0777) | vol->v_fperm; - setfilmode(upath, admode, NULL, vol->v_umask); - vol->vfs->vfs_setfilmode(vol, upath, admode, NULL); - } + setfilmode(upath, admode, NULL, vol->v_umask); + vol->vfs->vfs_setfilmode(vol, upath, admode, NULL); + } setvoltime(obj, vol ); } exit: - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if (sdir_fd != -1) close(sdir_fd); #endif diff --combined etc/afpd/fork.h index c1060dbe,7ea7a8a6..e950aa0f --- a/etc/afpd/fork.h +++ b/etc/afpd/fork.h @@@ -7,8 -7,9 +7,8 @@@ #define AFPD_FORK_H 1 #include -#include +#include -#include #include #include "volume.h" #include "directory.h" @@@ -64,20 -65,23 +64,21 @@@ extern int of_rename (cons struct dir *, const char *, struct dir *, const char *); extern int of_flush (const struct vol *); -extern void of_pforkdesc (FILE *); extern int of_stat (struct path *); extern int of_statdir (struct vol *vol, struct path *); extern int of_closefork (struct ofork *ofork); extern void of_closevol (const struct vol *vol); + extern void of_close_all_forks(void); extern struct adouble *of_ad (const struct vol *, struct path *, struct adouble *); - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS extern struct ofork *of_findnameat(int dirfd, struct path *path); extern int of_fstatat(int dirfd, struct path *path); - #endif /* HAVE_RENAMEAT */ + #endif /* HAVE_ATFUNCS */ /* in fork.c */ extern int flushfork (struct ofork *); -extern int getforkmode (struct adouble *, int , int ); /* FP functions */ int afp_openfork (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); diff --combined etc/afpd/globals.h index 3a9c229c,02dcf8b5..4d81463d --- a/etc/afpd/globals.h +++ b/etc/afpd/globals.h @@@ -7,6 -7,7 +7,6 @@@ #define AFPD_GLOBALS_H 1 #include -#include #ifdef ADMIN_GRP #include @@@ -23,7 -24,13 +23,13 @@@ #include #include - #define MACFILELEN 31 + /* #define DOSFILELEN 12 */ /* Type1, DOS-compat*/ + #define MACFILELEN 31 /* Type2, HFS-compat */ + #define UTF8FILELEN_EARLY 255 /* Type3, early Mac OS X 10.0-10.4.? */ + /* #define UTF8FILELEN_NAME_MAX 765 */ /* Type3, 10.4.?- , getconf NAME_MAX */ + /* #define UTF8FILELEN_SPEC 0xFFFF */ /* Type3, spec on document */ + /* #define HFSPLUSFILELEN 510 */ /* HFS+ spec, 510byte = 255codepoint */ + #define MAXUSERLEN 256 #define OPTION_DEBUG (1 << 0) @@@ -37,6 -44,14 +43,6 @@@ #define OPTION_ACL2MACCESS (1 << 8) #define OPTION_NOZEROCONF (1 << 9) -#ifdef FORCE_UIDGID -/* set up a structure for this */ -typedef struct uidgidset_t { - uid_t uid; - gid_t gid; -} uidgidset; -#endif /* FORCE_UIDGID */ - /* a couple of these options could get stuck in unions to save * space. */ struct afp_volume_name { @@@ -50,9 -65,12 +56,11 @@@ struct afp_options int connections, transports, tickleval, timeout, server_notif, flags, dircachesize; int sleep; /* Maximum time allowed to sleep (in tickles) */ int disconnected; /* Maximum time in disconnected state (in tickles) */ + unsigned int tcp_sndbuf, tcp_rcvbuf; unsigned char passwdbits, passwdminlen, loginmaxfail; u_int32_t server_quantum; + int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */ char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile; - struct at_addr ddpaddr; char *uampath, *fqdn; char *pidfile; char *sigconffile; @@@ -98,6 -116,10 +106,6 @@@ typedef struct _AFPObj struct session_info sinfo; uid_t uid; /* client running user id */ int ipc_fd; /* anonymous PF_UNIX socket for IPC with afpd parent */ -#ifdef FORCE_UIDGID - int force_uid; - uidgidset uidgid; -#endif } AFPObj; /* typedef for AFP functions handlers */ @@@ -136,6 -158,9 +144,6 @@@ extern const char *AfpErr2name(int err) /* directory.c */ extern struct dir rootParent; -#ifndef NO_DDP -extern void afp_over_asp (AFPObj *); -#endif /* NO_DDP */ extern void afp_over_dsi (AFPObj *); #endif /* globals.h */ diff --combined etc/afpd/ofork.c index c3ca09c1,e65c4024..7e2d3d57 --- a/etc/afpd/ofork.c +++ b/etc/afpd/ofork.c @@@ -69,6 -69,22 +69,6 @@@ static void of_unhash(struct ofork *of } } -#ifdef DEBUG1 -void of_pforkdesc( FILE *f) -{ - int ofrefnum; - - if (!oforks) - return; - - for ( ofrefnum = 0; ofrefnum < nforks; ofrefnum++ ) { - if ( oforks[ ofrefnum ] != NULL ) { - fprintf( f, "%hu <%s>\n", ofrefnum, of_name(oforks[ ofrefnum ])); - } - } -} -#endif - int of_flush(const struct vol *vol) { int refnum; @@@ -195,7 -211,7 +195,7 @@@ of_alloc(struct vol *vol ad_open really does reinitialize the structure. */ ad_init(ad, vol->v_adouble, vol->v_ad_options); - ad->ad_m_namelen = 255 +1; + ad->ad_m_namelen = UTF8FILELEN_EARLY +1; /* here's the deal: we allocate enough for the standard mac file length. * in the future, we'll reallocate in fairly large jumps in case * of long unicode names */ @@@ -207,9 -223,12 +207,9 @@@ return NULL; } strlcpy( ad->ad_m_name, path, ad->ad_m_namelen); - } else { - /* Increase the refcount on this struct adouble. This is - decremented again in oforc_dealloc. */ - ad->ad_refcount++; } + ad_ref(ad); of->of_ad = ad; of->of_vol = vol; of->of_did = dir->d_did; @@@ -253,7 -272,7 +253,7 @@@ int of_stat(struct path *path } - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS int of_fstatat(int dirfd, struct path *path) { int ret; @@@ -266,7 -285,7 +266,7 @@@ return ret; } - #endif /* HAVE_RENAMEAT */ + #endif /* HAVE_ATFUNCS */ /* -------------------------- stat the current directory. @@@ -346,7 -365,7 +346,7 @@@ struct ofork *of_findname(struct path * * @param dirfd (r) directory fd * @param path (rw) pointer to struct path */ - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS struct ofork *of_findnameat(int dirfd, struct path *path) { struct ofork *of; @@@ -379,6 -398,17 +379,6 @@@ void of_dealloc( struct ofork *of of_unhash(of); oforks[ of->of_refnum % nforks ] = NULL; - - /* decrease refcount */ - of->of_ad->ad_refcount--; - - if ( of->of_ad->ad_refcount <= 0) { - free( of->of_ad->ad_m_name ); - free( of->of_ad); - } else {/* someone's still using it. just free this user's locks */ - ad_unlock(of->of_ad, of->of_refnum); - } - free( of ); } @@@ -386,10 -416,15 +386,10 @@@ int of_closefork(struct ofork *ofork) { struct timeval tv; - int adflags, doflush = 0; + int doflush = 0; int ret; - adflags = 0; - if ((ofork->of_flags & AFPFORK_DATA) && (ad_data_fileno( ofork->of_ad ) != -1)) { - adflags |= ADFLAGS_DF; - } if ( (ofork->of_flags & AFPFORK_OPEN) && ad_reso_fileno( ofork->of_ad ) != -1 ) { - adflags |= ADFLAGS_HF; /* * Only set the rfork's length if we're closing the rfork. */ @@@ -405,13 -440,8 +405,13 @@@ } } ret = 0; - if ( ad_close( ofork->of_ad, adflags ) < 0 ) { - ret = -1; + + ad_unlock(ofork->of_ad, ofork->of_refnum); + + if (ad_unref(ofork->of_ad) == 0) { + if ( ad_close( ofork->of_ad, 0 ) < 0 ) { + ret = -1; + } } of_dealloc( ofork ); @@@ -455,3 -485,23 +455,23 @@@ void of_closevol(const struct vol *vol return; } + /* ---------------------- + close all forks for a volume + */ + void of_close_all_forks(void) + { + int refnum; + + if (!oforks) + return; + + for ( refnum = 0; refnum < nforks; refnum++ ) { + if (oforks[ refnum ] != NULL) { + if (of_closefork( oforks[ refnum ]) < 0 ) { + LOG(log_error, logtype_afpd, "of_close_all_forks: %s", strerror(errno) ); + } + } + } + return; + } + diff --combined etc/afpd/status.c index 1037f15a,cbf59892..24b6b807 --- a/etc/afpd/status.c +++ b/etc/afpd/status.c @@@ -28,9 -28,12 +28,9 @@@ #endif /* BSD4_4 */ #endif -#include -#include +#include + #include -#include -#include -#include #include #include @@@ -82,13 -85,14 +82,13 @@@ static int status_server(char *data, co /* extract the obj part of the server */ Obj = (char *) server; - nbp_name(server, &Obj, &Type, &Zone); if ((size_t)-1 == (len = convert_string( - options->unixcharset, options->maccharset, - Obj, -1, buf, sizeof(buf))) ) { - len = MIN(strlen(Obj), 31); + options->unixcharset, options->maccharset, + Obj, -1, buf, sizeof(buf))) ) { + len = MIN(strlen(Obj), 31); *data++ = len; memcpy( data, Obj, len ); - LOG ( log_error, logtype_afpd, "Could not set servername, using fallback"); + LOG ( log_error, logtype_afpd, "Could not set servername, using fallback"); } else { *data++ = len; memcpy( data, buf, len ); @@@ -169,7 -173,7 +169,7 @@@ static u_int16_t status_signature(char } static size_t status_netaddress(char *data, int *servoffset, - const ASP asp, const DSI *dsi, + const DSI *dsi, const struct afp_options *options) { char *begin; @@@ -193,7 -197,7 +193,7 @@@ /* number of addresses. this currently screws up if we have a dsi connection, but we don't have the ip address. to get around this, we turn off the status flag for tcp/ip. */ - *data++ = ((options->fqdn && dsi)? 1 : 0) + (dsi ? 1 : 0) + (asp ? 1 : 0) + + *data++ = ((options->fqdn && dsi)? 1 : 0) + (dsi ? 1 : 0) + (((options->flags & OPTION_ANNOUNCESSH) && options->fqdn && dsi)? 1 : 0); /* ip address */ @@@ -267,6 -271,23 +267,6 @@@ } } -#ifndef NO_DDP - if (asp) { - const struct sockaddr_at *ddpaddr = atp_sockaddr(asp->asp_atp); - - /* ddp address */ - *data++ = 6; - *data++ = 0x03; /* ddp address */ - memcpy(data, &ddpaddr->sat_addr.s_net, sizeof(ddpaddr->sat_addr.s_net)); - data += sizeof(ddpaddr->sat_addr.s_net); - memcpy(data, &ddpaddr->sat_addr.s_node, - sizeof(ddpaddr->sat_addr.s_node)); - data += sizeof(ddpaddr->sat_addr.s_node); - memcpy(data, &ddpaddr->sat_port, sizeof(ddpaddr->sat_port)); - data += sizeof(ddpaddr->sat_port); - } -#endif /* ! NO_DDP */ - /* calculate/store Directory Services Names offset */ offset = htons(data - begin); *servoffset += sizeof(offset); @@@ -353,15 -374,18 +353,15 @@@ static size_t status_utf8servername(cha /* extract the obj part of the server */ Obj = (char *) (options->server ? options->server : options->hostname); - nbp_name(options->server ? options->server : options->hostname, &Obj, &Type, &Zone); - 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"); + options->unixcharset, CH_UTF8_MAC, + Obj, -1, data+sizeof(namelen), maxstatuslen-offset )) ) { + LOG ( log_error, logtype_afpd, "Could not set utf8 servername"); - /* set offset to 0 */ - memset(begin + *nameoffset, 0, sizeof(offset)); + /* set offset to 0 */ + memset(begin + *nameoffset, 0, sizeof(offset)); data = begin + offset; - } - else { + } else { namelen = htons(len); memcpy( data, &namelen, sizeof(namelen)); data += sizeof(namelen); @@@ -401,16 -425,24 +401,16 @@@ static void status_icon(char *data, con /* --------------------- */ -void status_init(AFPConfig *aspconfig, AFPConfig *dsiconfig, +void status_init(AFPConfig *dsiconfig, const struct afp_options *options) { - ASP asp; DSI *dsi; char *status = NULL; size_t statuslen; int c, sigoff, ipok; - if (!(aspconfig || dsiconfig) || !options) + if (!dsiconfig || !options) return; - - if (aspconfig) { - status = aspconfig->status; - maxstatuslen=sizeof(aspconfig->status); - asp = aspconfig->obj.handle; - } else - asp = NULL; ipok = 0; if (dsiconfig) { @@@ -462,7 -494,7 +462,7 @@@ c = status_server(status, options->server ? options->server : options->hostname, options); status_machine(status); - status_versions(status, asp, dsi); + status_versions(status, dsi); status_uams(status, options->uamlist); if (options->flags & OPTION_CUSTOMICON) status_icon(status, icon, sizeof(icon), c); @@@ -472,7 -504,7 +472,7 @@@ sigoff = status_signature(status, &c, options); /* c now contains the offset where the netaddress offset lives */ - status_netaddress(status, &c, asp, dsi, options); + status_netaddress(status, &c, dsi, options); /* c now contains the offset where the Directory Names Count offset lives */ statuslen = status_directorynames(status, &c, dsi, options); @@@ -481,6 -513,16 +481,6 @@@ if ( statuslen < maxstatuslen) statuslen = status_utf8servername(status, &c, dsi, options); -#ifndef NO_DDP - if (aspconfig) { - if (dsiconfig) /* status is dsiconfig->status */ - memcpy(aspconfig->status, status, statuslen); - asp_setstatus(asp, status, statuslen); - aspconfig->signature = status + sigoff; - aspconfig->statuslen = statuslen; - } -#endif /* ! NO_DDP */ - if (dsiconfig) { if ((options->flags & OPTION_CUSTOMICON) == 0) { status_icon(status, apple_tcp_icon, sizeof(apple_tcp_icon), 0); @@@ -609,14 -651,14 +609,14 @@@ server_signature_auto options->sigconffile, strerror(errno)); goto server_signature_random; } - } else { /* conf file don't exist */ + } else { /* conf file don't exist */ if (( fd = creat(options->sigconffile, 0644 )) < 0 ) { - LOG(log_error, logtype_atalkd, "Cannot create %s (%s). Using one-time signature.", + LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s). Using one-time signature.", options->sigconffile, strerror(errno)); goto server_signature_random; } if (( fp = fdopen( fd, "w" )) == NULL ) { - LOG(log_error, logtype_atalkd, "Cannot fdopen %s (%s). Using one-time signature.", + LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s). Using one-time signature.", options->sigconffile, strerror(errno)); close(fd); goto server_signature_random; diff --combined etc/afpd/unix.c index efc72923,f604d79b..232fb303 --- a/etc/afpd/unix.c +++ b/etc/afpd/unix.c @@@ -9,7 -9,24 +9,7 @@@ #include #include - -/* STDC check */ -#ifdef STDC_HEADERS #include -#else /* STDC_HEADERS */ - -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); - -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ - #include #include #include @@@ -140,6 -157,7 +140,7 @@@ mode_t mode } #ifdef accessmode + #undef accessmode #endif /* @@@ -314,6 -332,9 +315,6 @@@ int setfilunixmode (const struct vol *v /* --------------------- */ int setdirunixmode(const struct vol *vol, const char *name, mode_t mode) { - - int dropbox = (vol->v_flags & AFPVOL_DROPBOX); - LOG(log_debug, logtype_afpd, "setdirunixmode('%s', mode:%04o) {v_dperm:%04o}", fullpathname(name), mode, vol->v_dperm); @@@ -321,14 -342,14 +322,14 @@@ if (dir_rx_set(mode)) { /* extending right? dir first then .AppleDouble in rf_setdirmode */ - if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 ) + if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 ) return -1; } if (vol->vfs->vfs_setdirunixmode(vol, name, mode, NULL) < 0 && !vol_noadouble(vol)) { return -1 ; } if (!dir_rx_set(mode)) { - if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 ) + if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 ) return -1; } return 0; @@@ -341,13 -362,15 +342,13 @@@ int setdirmode(const struct vol *vol, c struct dirent *dirp; DIR *dir; mode_t hf_mode; - int osx = vol->v_adouble == AD_VERSION2_OSX; - int dropbox = (vol->v_flags & AFPVOL_DROPBOX); mode |= vol->v_dperm; hf_mode = ad_hf_mode(mode); if (dir_rx_set(mode)) { /* extending right? dir first */ - if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 ) + if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 ) return -1; } @@@ -358,7 -381,7 +359,7 @@@ for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) { /* FIXME */ - if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) { + if (*dirp->d_name == '.') { continue; } if ( lstat( dirp->d_name, &st ) < 0 ) { @@@ -367,7 -390,9 +368,7 @@@ } if (!S_ISDIR(st.st_mode)) { - int setmode = (osx && *dirp->d_name == '.')?hf_mode:mode; - - if (setfilmode(dirp->d_name, setmode, &st, vol->v_umask) < 0) { + if (setfilmode(dirp->d_name, mode, &st, vol->v_umask) < 0) { LOG(log_error, logtype_afpd, "setdirmode: chmod %s: %s",dirp->d_name, strerror(errno) ); return -1; } @@@ -380,7 -405,7 +381,7 @@@ } if (!dir_rx_set(mode)) { - if ( stickydirmode(name, DIRBITS | mode, dropbox, vol->v_umask) < 0 ) + if ( stickydirmode(name, DIRBITS | mode, 0, vol->v_umask) < 0 ) return -1; } return( 0 ); @@@ -485,12 -510,13 +486,12 @@@ int setdirowner(const struct vol *vol, struct stat st; struct dirent *dirp; DIR *dir; - int osx = vol->v_adouble == AD_VERSION2_OSX; if (( dir = opendir( name )) == NULL ) { return( -1 ); } for ( dirp = readdir( dir ); dirp != NULL; dirp = readdir( dir )) { - if ( *dirp->d_name == '.' && (!osx || dirp->d_name[1] != '_')) { + if ( *dirp->d_name == '.') { continue; } if ( lstat( dirp->d_name, &st ) < 0 ) { diff --combined etc/afpd/volume.c index 2970bcc3,b73d13c2..60fc73e9 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@@ -14,12 -14,29 +14,12 @@@ #include #include #include -#ifdef HAVE_STRINGS_H -#include -#endif -/* STDC check */ -#if STDC_HEADERS #include -#else /* STDC_HEADERS */ -#ifndef HAVE_STRCHR -#define strchr index -#define strrchr index -#endif /* HAVE_STRCHR */ -char *strchr (), *strrchr (); -#ifndef HAVE_MEMCPY -#define memcpy(d,s,n) bcopy ((s), (d), (n)) -#define memmove(d,s,n) bcopy ((s), (d), (n)) -#endif /* ! HAVE_MEMCPY */ -#endif /* STDC_HEADERS */ #include #include #include #include -#include #include #include #include @@@ -28,8 -45,10 +28,10 @@@ #include #include #include +#include + #include + #include - #ifdef CNID_DB #include #endif /* CNID_DB*/ @@@ -95,7 -114,15 +97,7 @@@ static void free_extmap(voi #define VOLOPT_MACCHARSET 16 #define VOLOPT_CNIDSCHEME 17 #define VOLOPT_ADOUBLE 18 /* adouble version */ - -#ifdef FORCE_UIDGID -#warning UIDGID -#include "uid.h" - -#define VOLOPT_FORCEUID 19 /* force uid for username x */ -#define VOLOPT_FORCEGID 20 /* force gid for group x */ -#endif /* FORCE_UIDGID */ - +/* Usable slot: 19/20 */ #define VOLOPT_UMASK 21 #define VOLOPT_ALLOWED_HOSTS 22 #define VOLOPT_DENIED_HOSTS 23 @@@ -127,7 -154,12 +129,7 @@@ typedef struct _special_folder static const _special_folder special_folders[] = { {"Network Trash Folder", 1, 0777, 1}, - {"Temporary Items", 1, 0777, 1}, {".AppleDesktop", 1, 0777, 0}, -#if 0 - {"TheFindByContentFolder", 0, 0, 1}, - {"TheVolumeSettingsFolder", 0, 0, 1}, -#endif {NULL, 0, 0, 0}}; /* Forward declarations */ @@@ -135,6 -167,8 +137,8 @@@ static void handle_special_folders (con static void deletevol(struct vol *vol); static void volume_free(struct vol *vol); static void check_ea_sys_support(struct vol *vol); + static char *get_vol_uuid(const AFPObj *obj, const char *volname); + static int readvolfile(AFPObj *obj, struct afp_volume_name *p1,char *p2, int user, struct passwd *pwent); static void volfree(struct vol_option *options, const struct vol_option *save) { @@@ -239,12 -273,22 +243,12 @@@ static char *volxlate(AFPObj *obj } else if (is_var(p, "$c")) { if (afpmaster && xlatevolname) return NULL; - if (obj->proto == AFPPROTO_ASP) { - ASP asp = obj->handle; - - len = sprintf(dest, "%u.%u", ntohs(asp->asp_sat.sat_addr.s_net), - asp->asp_sat.sat_addr.s_node); - dest += len; - destlen -= len; - - } else if (obj->proto == AFPPROTO_DSI) { - DSI *dsi = obj->handle; - len = sprintf(dest, "%s:%u", - getip_string((struct sockaddr *)&dsi->client), - getip_port((struct sockaddr *)&dsi->client)); - dest += len; - destlen -= len; - } + DSI *dsi = obj->handle; + 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")) { if (afpmaster && xlatevolname) return NULL; @@@ -266,8 -310,17 +270,8 @@@ } else if (is_var(p, "$i")) { if (afpmaster && xlatevolname) return NULL; - if (obj->proto == AFPPROTO_ASP) { - ASP asp = obj->handle; - - len = sprintf(dest, "%u", ntohs(asp->asp_sat.sat_addr.s_net)); - dest += len; - destlen -= len; - - } else if (obj->proto == AFPPROTO_DSI) { - DSI *dsi = obj->handle; - q = getip_string((struct sockaddr *)&dsi->client); - } + DSI *dsi = obj->handle; + q = getip_string((struct sockaddr *)&dsi->client); } else if (is_var(p, "$s")) { if (obj->Obj) q = obj->Obj; @@@ -396,10 -449,16 +400,10 @@@ static void volset(struct vol_option *o else if (strcasecmp(val + 1, "xlateupper") == 0) options[VOLOPT_CASEFOLD].i_value = AFPVOL_ULOWERMUPPER; } else if (optionok(tmp, "adouble:", val)) { - if (strcasecmp(val + 1, "v1") == 0) - options[VOLOPT_ADOUBLE].i_value = AD_VERSION1; -#if AD_VERSION == AD_VERSION2 - else if (strcasecmp(val + 1, "v2") == 0) + if (strcasecmp(val + 1, "v2") == 0) options[VOLOPT_ADOUBLE].i_value = AD_VERSION2; - else if (strcasecmp(val + 1, "osx") == 0) - options[VOLOPT_ADOUBLE].i_value = AD_VERSION2_OSX; - else if (strcasecmp(val + 1, "sfm") == 0) - options[VOLOPT_ADOUBLE].i_value = AD_VERSION1_SFM; -#endif + else if (strcasecmp(val + 1, "ea") == 0) + options[VOLOPT_ADOUBLE].i_value = AD_VERSION_EA; } else if (optionok(tmp, "options:", val)) { char *p; @@@ -425,6 -484,11 +429,6 @@@ options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS | AFPVOL_INV_DOTS; else if (strcasecmp(p, "limitsize") == 0) options[VOLOPT_FLAGS].i_value |= AFPVOL_LIMITSIZE; - /* support for either "dropbox" or "dropkludge" */ - else if (strcasecmp(p, "dropbox") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX; - else if (strcasecmp(p, "dropkludge") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX; else if (strcasecmp(p, "nofileid") == 0) options[VOLOPT_FLAGS].i_value |= AFPVOL_NOFILEID; else if (strcasecmp(p, "nostat") == 0) @@@ -480,6 -544,16 +484,6 @@@ options[VOLOPT_DFLTPERM].i_value = (int)strtol(val+1, NULL, 8); } else if (optionok(tmp, "password:", val)) { setoption(options, save, VOLOPT_PASSWORD, val); - -#ifdef FORCE_UIDGID - - /* this code allows forced uid/gid per volume settings */ - } else if (optionok(tmp, "forceuid:", val)) { - setoption(options, save, VOLOPT_FORCEUID, val); - } else if (optionok(tmp, "forcegid:", val)) { - setoption(options, save, VOLOPT_FORCEGID, val); - -#endif /* FORCE_UIDGID */ } else if (optionok(tmp, "root_preexec:", val)) { setoption(options, save, VOLOPT_ROOTPREEXEC, val); @@@ -616,6 -690,7 +620,7 @@@ static int creatvol(AFPObj *obj, struc /* check duplicate */ for ( volume = Volumes; volume; volume = volume->v_next ) { if (( strcasecmp_w( volume->v_u8mname, u8mtmpname ) == 0 ) || ( strcasecmp_w( volume->v_macname, mactmpname ) == 0 )){ + LOG (log_error, logtype_afpd, "ERROR: Volume name is duplicated. Check AppleVolumes files."); if (volume->v_deleted) { volume->v_new = hide = 1; } @@@ -758,6 -833,19 +763,6 @@@ if ((volume->v_flags & AFPVOL_EILSEQ)) volume->v_utom_flags |= CONV__EILSEQ; -#ifdef FORCE_UIDGID - if (options[VOLOPT_FORCEUID].c_value) { - volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value); - } else { - volume->v_forceuid = NULL; /* set as null so as to return 0 later on */ - } - - if (options[VOLOPT_FORCEGID].c_value) { - volume->v_forcegid = strdup(options[VOLOPT_FORCEGID].c_value); - } else { - volume->v_forcegid = NULL; /* set as null so as to return 0 later on */ - } -#endif if (!user) { if (options[VOLOPT_PREEXEC].c_value) volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_PREEXEC].c_value, pwd, path, name); @@@ -784,7 -872,7 +789,7 @@@ /* get/store uuid from file */ if (volume->v_flags & AFPVOL_TM) { - char *uuid = get_uuid(obj, volume->v_localname); + char *uuid = get_vol_uuid(obj, volume->v_localname); if (!uuid) { LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID", volume->v_localname); @@@ -1075,7 -1163,7 +1080,7 @@@ static int volfile_changed(struct afp_v * TYPE [CREATOR] * */ - int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent) + static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent) { FILE *fp; char path[MAXPATHLEN + 1]; @@@ -1112,6 -1200,14 +1117,14 @@@ p1->mtime = st.st_mtime; } + if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) { + LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path); + if ( fclose( fp ) != 0 ) { + LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) ); + } + return -1; + } + memset(save_options, 0, sizeof(save_options)); /* Enable some default options for all volumes */ @@@ -1256,6 -1352,10 +1269,6 @@@ static void volume_free(struct vol *vol free(vol->v_cnidscheme); free(vol->v_dbpath); free(vol->v_gvs); -#ifdef FORCE_UIDGID - free(vol->v_forceuid); - free(vol->v_forcegid); -#endif /* FORCE_UIDGID */ if (vol->v_uuid) free(vol->v_uuid); } @@@ -1359,10 -1459,45 +1372,45 @@@ static int getvolspace(struct vol *vol getvolspace_done: if (vol->v_limitsize) { - /* FIXME: Free could be limit minus (total minus used), */ - /* which will confuse the client less ? */ - *xbfree = min(*xbfree, (vol->v_limitsize * 1024 * 1024)); + bstring cmdstr; + if ((cmdstr = bformat("du -sh \"%s\" 2> /dev/null | cut -f1", vol->v_path)) == NULL) + return AFPERR_MISC; + + FILE *cmd = popen(cfrombstr(cmdstr), "r"); + bdestroy(cmdstr); + if (cmd == NULL) + return AFPERR_MISC; + + char buf[100]; + fgets(buf, 100, cmd); + + if (pclose(cmd) == -1) + return AFPERR_MISC; + + size_t multi = 0; + if (buf[strlen(buf) - 2] == 'G' || buf[strlen(buf) - 2] == 'g') + /* GB */ + multi = 1024 * 1024 * 1024; + else if (buf[strlen(buf) - 2] == 'M' || buf[strlen(buf) - 2] == 'm') + /* MB */ + multi = 1024 * 1024; + else if (buf[strlen(buf) - 2] == 'K' || buf[strlen(buf) - 2] == 'k') + /* MB */ + multi = 1024; + + char *p; + if (p = strchr(buf, ',')) + /* ignore fraction */ + *p = 0; + else + /* remove G|M|K char */ + buf[strlen(buf) - 2] = 0; + /* now buf contains only digits */ + long long used = atoll(buf) * multi; + LOG(log_debug, logtype_afpd, "volparams: used on volume: %llu bytes", used); + *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024)); + *xbfree = min(*xbfree, *xbtotal < used ? 0 : *xbtotal - used); } *bfree = min( *xbfree, maxsize); @@@ -1411,7 -1546,7 +1459,7 @@@ static int getvolparams( u_int16_t bitm * .Parent file here if it doesn't exist. */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ( ad_open_metadata( vol->v_path, ADFLAGS_DIR, O_CREAT, &ad) < 0 ) { + if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0 ) { isad = 0; vol->v_ctime = AD_DATE_FROM_UNIX(st->st_mtime); @@@ -1542,13 -1677,21 +1590,13 @@@ #ifndef NO_LARGE_VOL_SUPPORT case VOLPBIT_XBFREE : xbfree = hton64( xbfree ); -#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG) - bcopy(&xbfree, data, sizeof(xbfree)); -#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */ memcpy(data, &xbfree, sizeof( xbfree )); -#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */ data += sizeof( xbfree ); break; case VOLPBIT_XBTOTAL : xbtotal = hton64( xbtotal ); -#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG) - bcopy(&xbtotal, data, sizeof(xbtotal)); -#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */ memcpy(data, &xbtotal, sizeof( xbtotal )); -#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */ data += sizeof( xbfree ); break; #endif /* ! NO_LARGE_VOL_SUPPORT */ @@@ -1890,7 -2033,7 +1938,7 @@@ static void check_ea_sys_support(struc if (vol->v_vfs_ea == AFPVOL_EA_AUTO) { if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) { - LOG(log_info, logtype_logger, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname); + LOG(log_info, logtype_afpd, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname); vol->v_vfs_ea = AFPVOL_EA_NONE; return; } @@@ -1900,7 -2043,7 +1948,7 @@@ process_uid = geteuid(); if (process_uid) if (seteuid(0) == -1) { - LOG(log_error, logtype_logger, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno)); + LOG(log_error, logtype_afpd, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno)); exit(EXITERR_SYS); } @@@ -1915,7 -2058,7 +1963,7 @@@ if (process_uid) { if (seteuid(process_uid) == -1) { - LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno)); + LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno)); exit(EXITERR_SYS); } } @@@ -1990,6 -2133,9 +2038,6 @@@ int afp_openvol(AFPObj *obj, char *ibuf if (( volume->v_flags & AFPVOL_OPEN ) ) { /* the volume is already open */ -#ifdef FORCE_UIDGID - set_uidgid ( volume ); -#endif return stat_vol(bitmap, volume, rbuf, rbuflen); } @@@ -2000,6 -2146,10 +2048,6 @@@ } } -#ifdef FORCE_UIDGID - set_uidgid ( volume ); -#endif - if (volume->v_preexec) { if ((ret = afprun(0, volume->v_preexec, NULL)) && volume->v_preexec_close) { LOG(log_error, logtype_afpd, "afp_openvol(%s): preexec : %d", volume->v_path, ret ); @@@ -2051,7 -2201,7 +2099,7 @@@ * FIXME file size */ if (utf8_encoding()) { - volume->max_filename = 255; + volume->max_filename = UTF8FILELEN_EARLY; } else { volume->max_filename = MACFILELEN; @@@ -2244,6 -2394,10 +2292,6 @@@ struct vol *getvolbyvid(const u_int16_ return( NULL ); } -#ifdef FORCE_UIDGID - set_uidgid ( vol ); -#endif /* FORCE_UIDGID */ - current_vol = vol; return( vol ); @@@ -2402,7 -2556,8 +2450,7 @@@ int afp_setvolparams(AFPObj *obj _U_, c return AFPERR_BITMAP; ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if ( ad_open( vol->v_path, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR, - 0666, &ad) < 0 ) { + if ( ad_open(&ad, vol->v_path, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR) < 0 ) { if (errno == EROFS) return AFPERR_VLOCK; @@@ -2497,8 -2652,8 +2545,8 @@@ static int create_special_folder (cons if ( !ret && folder->hide) { /* Hide it */ ad_init(&ad, vol->v_adouble, vol->v_ad_options); - if (ad_open_metadata( p, ADFLAGS_DIR, O_CREAT, &ad) < 0) { - free (p); + if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR, O_RDWR | O_CREAT, 0666) != 0) { + free(p); free(q); return (-1); } @@@ -2554,7 -2709,7 +2602,7 @@@ void unload_volumes_and_extmap(void * * Returns pointer to allocated storage on success, NULL on error. */ - char *get_uuid(const AFPObj *obj, const char *volname) + static char *get_vol_uuid(const AFPObj *obj, const char *volname) { char *volname_conf; char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p; @@@ -2606,12 -2761,12 +2654,12 @@@ if (stat(obj->options.uuidconf, &tmpstat)) { /* no file */ if (( fd = creat(obj->options.uuidconf, 0644 )) < 0 ) { - LOG(log_error, logtype_atalkd, "ERROR: Cannot create %s (%s).", + LOG(log_error, logtype_afpd, "ERROR: Cannot create %s (%s).", obj->options.uuidconf, strerror(errno)); return NULL; } if (( fp = fdopen( fd, "w" )) == NULL ) { - LOG(log_error, logtype_atalkd, "ERROR: Cannot fdopen %s (%s).", + LOG(log_error, logtype_afpd, "ERROR: Cannot fdopen %s (%s).", obj->options.uuidconf, strerror(errno)); close(fd); return NULL; @@@ -2642,5 -2797,5 +2690,5 @@@ fprintf(fp, "\"%s\"\t%36s\n", volname, cp); fclose(fp); - return strdup(uuid); + return strdup(cp); } diff --combined etc/afpd/volume.h index 883b1d56,fd2d2251..a0b45940 --- a/etc/afpd/volume.h +++ b/etc/afpd/volume.h @@@ -6,8 -6,9 +6,8 @@@ #ifndef AFPD_VOLUME_H #define AFPD_VOLUME_H 1 -#include #include -#include +#include #include #include @@@ -25,14 -26,8 +25,8 @@@ extern int ustatfs_getvols extern void setvoltime (AFPObj *, struct vol *); extern int pollvoltime (AFPObj *); extern void load_volumes (AFPObj *obj); - extern int readvolfile(AFPObj *obj, - struct afp_volume_name *p1, - char *p2, - int user, - struct passwd *pwent); extern const struct vol *getvolumes(void); extern void unload_volumes_and_extmap(void); - extern char *get_uuid(const AFPObj *obj, const char *volname); /* FP functions */ int afp_openvol (AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen); diff --combined etc/cnid_dbd/cmd_dbd_scanvol.c index f4122d84,daa13e41..8fb09624 --- a/etc/cnid_dbd/cmd_dbd_scanvol.c +++ b/etc/cnid_dbd/cmd_dbd_scanvol.c @@@ -34,7 -34,6 +34,7 @@@ #include #include #include +#include #include "cmd_dbd.h" #include "dbif.h" @@@ -293,16 -292,17 +293,16 @@@ static const char *check_special_dirs(c */ static int check_adfile(const char *fname, const struct stat *st) { - int ret, adflags; + int ret; + int adflags = ADFLAGS_HF; struct adouble ad; - char *adname; + const char *adname; if (dbd_flags & DBD_FLAGS_CLEANUP) return 0; if (S_ISREG(st->st_mode)) - adflags = 0; - else - adflags = ADFLAGS_DIR; + adflags |= ADFLAGS_DIR; adname = myvolinfo->ad_path(fname, adflags); @@@ -322,7 -322,7 +322,7 @@@ /* Create ad file */ ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if ((ret = ad_open_metadata( fname, adflags, O_CREAT, &ad)) != 0) { + if ((ret = ad_open(&ad, fname, adflags, O_CREAT | O_RDWR, 0666)) != 0) { dbd_log( LOGSTD, "Error creating AppleDouble file '%s/%s': %s", cwdbuf, adname, strerror(errno)); @@@ -341,7 -341,7 +341,7 @@@ #endif } else { ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open_metadata( fname, adflags, O_RDONLY, &ad) != 0) { + if (ad_open(&ad, fname, adflags, O_RDONLY) != 0) { dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s'", cwdbuf, fname); return -1; } @@@ -494,7 -494,7 +494,7 @@@ static int check_addir(int volroot /* Create ad dir and set name */ ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open_metadata( ".", ADFLAGS_DIR, O_CREAT, &ad) != 0) { + if (ad_open(&ad, ".", ADFLAGS_HF | ADFLAGS_DIR, O_CREAT | O_RDWR, 0777) != 0) { dbd_log( LOGSTD, "Error creating AppleDouble dir in %s: %s", cwdbuf, strerror(errno)); return -1; } @@@ -666,6 -666,8 +666,8 @@@ static int read_addir(void /* Check CNID for a file/dir, both from db and from ad-file. For detailed specs see intro. + + @return Correct CNID of object or CNID_INVALID (ie 0) on error */ static cnid_t check_cnid(const char *name, cnid_t did, struct stat *st, int adfile_ok, int adflags) { @@@ -673,17 -675,28 +675,28 @@@ cnid_t db_cnid, ad_cnid; struct adouble ad; + /* Force checkout every X items */ + static int cnidcount = 0; + cnidcount++; + if (cnidcount > 10000) { + cnidcount = 0; + if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) { + dbd_log(LOGSTD, "Error checkpointing!"); + return CNID_INVALID; + } + } + /* Get CNID from ad-file if volume is using AFPVOL_CACHE */ ad_cnid = 0; if ( (myvolinfo->v_flags & AFPVOL_CACHE) && ADFILE_OK) { ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) { + if (ad_open(&ad, name, adflags, O_RDWR) != 0) { if (dbd_flags & DBD_FLAGS_CLEANUP) - return 0; + return CNID_INVALID; dbd_log( LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); - return 0; + return CNID_INVALID; } if (dbd_flags & DBD_FLAGS_FORCE) { @@@ -719,7 -732,8 +732,8 @@@ /* Query the database */ ret = dbd_lookup(dbd, &rqst, &rply, (dbd_flags & DBD_FLAGS_SCAN) ? 1 : 0); - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return CNID_INVALID; if (rply.result == CNID_DBD_RES_OK) { db_cnid = rply.cnid; } else if (rply.result == CNID_DBD_RES_NOTFOUND) { @@@ -741,14 -755,17 +755,17 @@@ if ( ! (dbd_flags & DBD_FLAGS_SCAN)) { rqst.cnid = db_cnid; ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID); - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return CNID_INVALID; rqst.cnid = ad_cnid; ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID); - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return CNID_INVALID; ret = dbd_rebuild_add(dbd, &rqst, &rply); - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return CNID_INVALID; } return ad_cnid; } else if (ad_cnid && (db_cnid == 0)) { @@@ -763,7 -780,8 +780,8 @@@ if (ret == CNID_DBD_RES_OK) { /* Occupied! Choose another, update ad-file */ ret = dbd_add(dbd, &rqst, &rply, 1); - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return CNID_INVALID; db_cnid = rply.cnid; dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid)); @@@ -773,10 -791,10 +791,10 @@@ dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file", cwdbuf, name, ntohl(db_cnid)); ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) { + if (ad_open(&ad, name, adflags, O_RDWR) != 0) { dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); - return 0; + return CNID_INVALID; } ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp); ad_flush(&ad); @@@ -789,7 -807,8 +807,8 @@@ cwdbuf, name, ntohl(ad_cnid)); rqst.cnid = ad_cnid; ret = dbd_rebuild_add(dbd, &rqst, &rply); - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return CNID_INVALID; } return ad_cnid; } else if ((db_cnid == 0) && (ad_cnid == 0)) { @@@ -798,7 -817,8 +817,8 @@@ if ( ! (dbd_flags & DBD_FLAGS_SCAN)) { /* add to db */ ret = dbd_add(dbd, &rqst, &rply, 1); - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return CNID_INVALID; db_cnid = rply.cnid; dbd_log(LOGSTD, "New CNID for '%s/%s': %u", cwdbuf, name, ntohl(db_cnid)); } @@@ -811,10 -831,10 +831,10 @@@ dbd_log(LOGSTD, "Writing CNID data for '%s/%s' to AppleDouble file", cwdbuf, name, ntohl(db_cnid)); ad_init(&ad, myvolinfo->v_adouble, myvolinfo->v_ad_options); - if (ad_open_metadata( name, adflags, O_RDWR, &ad) != 0) { + if (ad_open(&ad, name, adflags, O_RDWR) != 0) { dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s", cwdbuf, name, strerror(errno)); - return 0; + return CNID_INVALID; } ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp); ad_flush(&ad); @@@ -824,7 -844,7 +844,7 @@@ return db_cnid; } - return 0; + return CNID_INVALID; } /* @@@ -921,6 -941,22 +941,22 @@@ static int dbd_readdir(int volroot, cni continue; } + /************************************************************************** + Statistics + **************************************************************************/ + static unsigned long long statcount = 0; + static time_t t = 0; + + if (t == 0) + t = time(NULL); + + statcount++; + if ((statcount % 10000) == 0) { + if (dbd_flags & DBD_FLAGS_STATS) + dbd_log(LOGSTD, "Scanned: %10llu, time: %10llu s", + statcount, (unsigned long long)(time(NULL) - t)); + } + /************************************************************************** Tests **************************************************************************/ @@@ -942,13 -978,24 +978,24 @@@ cnid = check_cnid(ep->d_name, did, &st, adfile_ok, adflags); /* Now add this object to our rebuild dbd */ - if (cnid) { + if (cnid && dbd_rebuild) { + static uint count = 0; rqst.cnid = rply.cnid; - dbd_rebuild_add(dbd_rebuild, &rqst, &rply); + 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( LOGDEBUG, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db", + dbd_log( LOGSTD, "Fatal error adding CNID: %u for '%s/%s' to in-memory rebuild-db", cnid, cwdbuf, ep->d_name); - longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */ + 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; } } } @@@ -980,7 -1027,7 +1027,7 @@@ close(cwd); *(strrchr(cwdbuf, '/')) = 0; if (ret < 0) - continue; + return -1; } } @@@ -1030,7 -1077,7 +1077,7 @@@ static int scanvol(struct volinfo *vi, */ static void delete_orphaned_cnids(DBD *dbd, DBD *dbd_rebuild, dbd_flags_t flags) { - int ret, deleted = 0; + int ret = 0, deleted = 0; cnid_t dbd_cnid = 0, rebuild_cnid = 0; struct cnid_dbd_rqst rqst; struct cnid_dbd_rply rply; @@@ -1051,7 -1098,7 +1098,7 @@@ if (alarmed) longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */ - if (deleted > 50) { + if (deleted > 1000) { deleted = 0; if (dbif_txn_checkpoint(dbd, 0, 0, 0) < 0) { dbd_log(LOGSTD, "Error checkpointing!"); @@@ -1077,7 -1124,8 +1124,8 @@@ goto cleanup; } - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return; deleted++; } /* Check if we got a termination signal */ @@@ -1100,19 -1148,21 +1148,21 @@@ (void)dbif_txn_abort(dbd); goto cleanup; } - dbif_txn_close(dbd, ret); + if (dbif_txn_close(dbd, ret) != 0) + return; deleted++; } continue; } if (dbd_cnid > rebuild_cnid) { + dbif_idwalk(dbd, NULL, 1); /* Close cursor */ + dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */ + (void)dbif_txn_close(dbd, 2); + (void)dbif_txn_close(dbd_rebuild, 2); dbd_log(LOGSTD, "Ghost CNID: %u. This is fatal! Dumping rebuild db:\n", rebuild_cnid); dbif_dump(dbd_rebuild, 0); dbd_log(LOGSTD, "Send this dump and a `dbd -d ...` dump to the Netatalk Dev team!"); - dbif_txn_close(dbd, ret); - dbif_idwalk(dbd, NULL, 1); /* Close cursor */ - dbif_idwalk(dbd_rebuild, NULL, 1); /* Close cursor */ goto cleanup; } } /* while ((dbif_idwalk(dbd, &dbd_cnid, 0)) == 1) */ @@@ -1123,6 -1173,16 +1173,16 @@@ cleanup return; } + static const char *get_tmpdb_path(void) + { + pid_t pid = getpid(); + static char path[MAXPATHLEN]; + snprintf(path, MAXPATHLEN, "/tmp/tmpdb-dbd.%u", pid); + if (mkdir(path, 0755) != 0) + return NULL; + return path; + } + /* Main func called from cmd_dbd.c */ @@@ -1130,9 -1190,13 +1190,13 @@@ int cmd_dbd_scanvol(DBD *dbd_ref, struc { int ret = 0; struct db_param db_param = { 0 }; + const char *tmpdb_path = NULL; /* Set cachesize for in-memory rebuild db */ - db_param.cachesize = 128 * 1024 * 1024; /* 128 MB */ + db_param.cachesize = 64 * 1024; /* 64 MB */ + db_param.maxlocks = DEFAULT_MAXLOCKS; + db_param.maxlockobjs = DEFAULT_MAXLOCKOBJS; + db_param.logfile_autoremove = 1; /* Make it accessible for all funcs */ dbd = dbd_ref; @@@ -1143,38 -1207,76 +1207,76 @@@ return -1; } - if (! nocniddb) { - /* Get volume stamp */ - dbd_getstamp(dbd, &rqst, &rply); - if (rply.result != CNID_DBD_RES_OK) - goto exit_cleanup; - memcpy(stamp, rply.name, CNID_DEV_LEN); - - /* open/create rebuild dbd, copy rootinfo key */ - if (NULL == (dbd_rebuild = dbif_init(NULL, NULL))) - return -1; - if (0 != (dbif_open(dbd_rebuild, &db_param, 0))) - return -1; - if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) - goto exit_cleanup; + /* Get volume stamp */ + dbd_getstamp(dbd, &rqst, &rply); + if (rply.result != CNID_DBD_RES_OK) { + ret = -1; + goto exit; } + memcpy(stamp, rply.name, CNID_DEV_LEN); + + /* temporary rebuild db, used with -re rebuild to delete unused CNIDs, not used with -f */ + if (! nocniddb && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE)) { + tmpdb_path = get_tmpdb_path(); + if (NULL == (dbd_rebuild = dbif_init(tmpdb_path, "cnid2.db"))) { + ret = -1; + goto exit; + } - if (setjmp(jmp) != 0) - goto exit_cleanup; /* Got signal, jump from dbd_readdir */ + if (dbif_env_open(dbd_rebuild, + &db_param, + DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN) < 0) { + dbd_log(LOGSTD, "error opening tmp database!"); + goto exit; + } + + if (0 != (dbif_open(dbd_rebuild, NULL, 0))) { + ret = -1; + goto exit; + } + + if (0 != (dbif_copy_rootinfokey(dbd, dbd_rebuild))) { + ret = -1; + goto exit; + } + } + + if (setjmp(jmp) != 0) { + ret = 0; /* Got signal, jump from dbd_readdir */ + goto exit; + } /* scanvol */ - if ( (scanvol(vi, flags)) != 0) - return -1; + if ( (scanvol(vi, flags)) != 0) { + ret = -1; + goto exit; + } + exit: if (! nocniddb) { - /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from - other clients in between our pass 1 and 2 */ - if (flags & DBD_FLAGS_EXCL) + if (dbif_txn_close(dbd, ret == 0 ? 1 : 0) != 0) + ret = -1; + if (dbd_rebuild) + if (dbif_txn_close(dbd_rebuild, ret == 0 ? 1 : 0) != 0) + ret = -1; + if ((ret == 0) && dbd_rebuild && (flags & DBD_FLAGS_EXCL) && !(flags & DBD_FLAGS_FORCE)) + /* We can only do this in exclusive mode, otherwise we might delete CNIDs added from + other clients in between our pass 1 and 2 */ delete_orphaned_cnids(dbd, dbd_rebuild, flags); } - exit_cleanup: - if (! nocniddb) + if (dbd_rebuild) { + dbd_log(LOGDEBUG, "Closing tmp db"); dbif_close(dbd_rebuild); + + if (tmpdb_path) { + char cmd[8 + MAXPATHLEN]; + snprintf(cmd, 8 + MAXPATHLEN, "rm -f %s/*", tmpdb_path); + dbd_log( LOGDEBUG, "Removing temp database '%s'", tmpdb_path); + system(cmd); + snprintf(cmd, 8 + MAXPATHLEN, "rmdir %s", tmpdb_path); + system(cmd); + } + } return ret; } diff --combined etc/cnid_dbd/cnid_metad.c index 2f3b9150,a51d15c4..11987cc7 --- a/etc/cnid_dbd/cnid_metad.c +++ b/etc/cnid_dbd/cnid_metad.c @@@ -43,7 -43,7 +43,7 @@@ #include #include #include -#define _XPG4_2 1 +// #define _XPG4_2 1 #include #include #include @@@ -89,7 -89,6 +89,7 @@@ #include #include #include +#include #include "usockfd.h" @@@ -580,7 -579,8 +580,8 @@@ int main(int argc, char *argv[] /* Load .volinfo file */ if ((volinfo = allocvolinfo(volpath)) == NULL) { - LOG(log_severe, logtype_cnid, "allocvolinfo: %s", strerror(errno)); + LOG(log_severe, logtype_cnid, "allocvolinfo(\"%s\"): %s", + volpath, strerror(errno)); goto loop_end; } diff --combined etc/cnid_dbd/comm.c index 65ed8604,083d27a7..64038714 --- a/etc/cnid_dbd/comm.c +++ b/etc/cnid_dbd/comm.c @@@ -9,6 -9,16 +9,16 @@@ #include "config.h" #endif + #ifndef _XOPEN_SOURCE + # define _XOPEN_SOURCE 600 + #endif + #ifndef __EXTENSIONS__ + # define __EXTENSIONS__ + #endif + #ifndef _GNU_SOURCE + # define _GNU_SOURCE + #endif + #include #include #include @@@ -18,7 -28,6 +28,6 @@@ #include #include #include - #define _XPG4_2 1 #include #include #include @@@ -209,7 -218,7 +218,7 @@@ int comm_rcv(struct cnid_dbd_rqst *rqst return -1; } - nametmp = rqst->name; + nametmp = (char *)rqst->name; if ((b = readt(cur_fd, rqst, sizeof(struct cnid_dbd_rqst), 1, CNID_DBD_TIMEOUT)) != sizeof(struct cnid_dbd_rqst)) { if (b) @@@ -219,7 -228,7 +228,7 @@@ return 0; } rqst->name = nametmp; - if (rqst->namelen && readt(cur_fd, rqst->name, rqst->namelen, 1, CNID_DBD_TIMEOUT) + if (rqst->namelen && readt(cur_fd, (char *)rqst->name, rqst->namelen, 1, CNID_DBD_TIMEOUT) != rqst->namelen) { LOG(log_error, logtype_cnid, "error reading message name: %s", strerror(errno)); invalidate_fd(cur_fd); @@@ -227,7 -236,7 +236,7 @@@ } /* We set this to make life easier for logging. None of the other stuff needs zero terminated strings. */ - rqst->name[rqst->namelen] = '\0'; + ((char *)(rqst->name))[rqst->namelen] = '\0'; LOG(log_maxdebug, logtype_cnid, "comm_rcv: got %u bytes", b + rqst->namelen); diff --combined etc/cnid_dbd/db_param.h index d8f3c910,f3a4827a..fce1cb5a --- a/etc/cnid_dbd/db_param.h +++ b/etc/cnid_dbd/db_param.h @@@ -8,7 -8,18 +8,17 @@@ #define CNID_DBD_DB_PARAM_H 1 #include -#include + #define DEFAULT_LOGFILE_AUTOREMOVE 1 + #define DEFAULT_CACHESIZE (8 * 1024) /* KB, so 8 MB */ + #define DEFAULT_MAXLOCKS 5000 + #define DEFAULT_MAXLOCKOBJS 5000 + #define DEFAULT_FLUSH_FREQUENCY 1000 + #define DEFAULT_FLUSH_INTERVAL 1800 + #define DEFAULT_USOCK_FILE "usock" + #define DEFAULT_FD_TABLE_SIZE 512 + #define DEFAULT_IDLE_TIMEOUT (10 * 60) + struct db_param { char *dir; int logfile_autoremove; diff --combined etc/cnid_dbd/dbif.c index 87ff2e9a,792ebe91..91d9bec0 --- a/etc/cnid_dbd/dbif.c +++ b/etc/cnid_dbd/dbif.c @@@ -14,8 -14,8 +14,8 @@@ #include #include #include -#include #include +#include #include @@@ -321,6 -321,91 +321,91 @@@ exit return ret; } + /*! + * Get lock on db lock file + * + * @args cmd (r) lock command: + * LOCK_FREE: close lockfd + * LOCK_UNLOCK: unlock lockm keep lockfd open + * LOCK_EXCL: F_WRLCK on lockfd + * LOCK_SHRD: F_RDLCK on lockfd + * @args dbpath (r) path to lockfile, only used on first call, + * later the stored fd is used + * @returns LOCK_FREE/LOCK_UNLOCK return 0 on success, -1 on error + * LOCK_EXCL/LOCK_SHRD return LOCK_EXCL or LOCK_SHRD respectively on + * success, 0 if the lock couldn't be acquired, -1 on other errors + */ + int get_lock(int cmd, const char *dbpath) + { + static int lockfd = -1; + int ret; + char lockpath[PATH_MAX]; + struct stat st; + + switch (cmd) { + case LOCK_FREE: + if (lockfd == -1) + return -1; + close(lockfd); + lockfd = -1; + return 0; + + case LOCK_UNLOCK: + if (lockfd == -1) + return -1; + return unlock(lockfd, 0, SEEK_SET, 0); + + case LOCK_EXCL: + case LOCK_SHRD: + if (lockfd == -1) { + if ( (strlen(dbpath) + strlen(LOCKFILENAME+1)) > (PATH_MAX - 1) ) { + LOG(log_error, logtype_cnid, ".AppleDB pathname too long"); + return -1; + } + strncpy(lockpath, dbpath, PATH_MAX - 1); + strcat(lockpath, "/"); + strcat(lockpath, LOCKFILENAME); + + if ((lockfd = open(lockpath, O_RDWR | O_CREAT, 0644)) < 0) { + LOG(log_error, logtype_cnid, "Error opening lockfile: %s", strerror(errno)); + return -1; + } + + if ((stat(dbpath, &st)) != 0) { + LOG(log_error, logtype_cnid, "Error statting lockfile: %s", strerror(errno)); + return -1; + } + + if ((chown(lockpath, st.st_uid, st.st_gid)) != 0) { + LOG(log_error, logtype_cnid, "Error inheriting lockfile permissions: %s", + strerror(errno)); + return -1; + } + } + + if (cmd == LOCK_EXCL) + ret = write_lock(lockfd, 0, SEEK_SET, 0); + else + ret = read_lock(lockfd, 0, SEEK_SET, 0); + + if (ret != 0) { + if (cmd == LOCK_SHRD) + LOG(log_error, logtype_cnid, "Volume CNID db is locked, try again..."); + return 0; + } + + LOG(log_debug, logtype_cnid, "get_lock: got %s lock", + cmd == LOCK_EXCL ? "LOCK_EXCL" : "LOCK_SHRD"); + return cmd; + + default: + return -1; + } /* switch(cmd) */ + + /* deadc0de, never get here */ + return -1; + } + /* --------------- */ DBD *dbif_init(const char *envhome, const char *filename) { @@@ -386,6 -471,8 +471,8 @@@ int dbif_env_open(DBD *dbd, struct db_p return -1; } + dbd->db_param = *dbp; + if ((dbif_openlog(dbd)) != 0) return -1; @@@ -1005,25 -1092,30 +1092,30 @@@ int dbif_txn_abort(DBD *dbd } /* - ret = 1 -> commit txn - ret = 0 -> abort txn -> exit! + ret = 1 -> commit txn if db_param.txn_frequency + ret = 0 -> abort txn db_param.txn_frequency -> exit! anything else -> exit! + + @returns 0 on success (abort or commit), -1 on error */ - void dbif_txn_close(DBD *dbd, int ret) + int dbif_txn_close(DBD *dbd, int ret) { if (ret == 0) { if (dbif_txn_abort(dbd) < 0) { LOG( log_error, logtype_cnid, "Fatal error aborting transaction. Exiting!"); - exit(EXIT_FAILURE); + return -1; } } else if (ret == 1) { ret = dbif_txn_commit(dbd); if ( ret < 0) { LOG( log_error, logtype_cnid, "Fatal error committing transaction. Exiting!"); - exit(EXIT_FAILURE); + return -1; } - } else - exit(EXIT_FAILURE); + } else { + return -1; + } + + return 0; } int dbif_txn_checkpoint(DBD *dbd, u_int32_t kbyte, u_int32_t min, u_int32_t flags) diff --combined etc/cnid_dbd/dbif.h index 2be8c0b1,c936a2b9..8c71de36 --- a/etc/cnid_dbd/dbif.h +++ b/etc/cnid_dbd/dbif.h @@@ -53,6 -53,7 +53,6 @@@ #ifndef CNID_DBD_DBIF_H #define CNID_DBD_DBIF_H 1 -#include #include #include #include "db_param.h" @@@ -64,6 -65,13 +64,13 @@@ #define DBIF_IDX_DIDNAME 2 #define DBIF_IDX_NAME 3 + /* get_lock cmd and return value */ + #define LOCKFILENAME "lock" + #define LOCK_FREE 0 + #define LOCK_UNLOCK 1 + #define LOCK_EXCL 2 + #define LOCK_SHRD 3 + /* Structures */ typedef struct { char *name; @@@ -75,6 -83,7 +82,7 @@@ typedef struct { DB_ENV *db_env; + struct db_param db_param; DB_TXN *db_txn; DBC *db_cur; /* for dbif_walk */ char *db_envhome; @@@ -84,6 -93,8 +92,8 @@@ } DBD; /* Functions */ + extern int get_lock(int cmd, const char *dbpath); + extern DBD *dbif_init(const char *envhome, const char *dbname); extern int dbif_env_open(DBD *dbd, struct db_param *dbp, uint32_t dbenv_oflags); extern int dbif_open(DBD *dbd, struct db_param *dbp, int reindex); @@@ -100,7 -111,7 +110,7 @@@ extern int dbif_copy_rootinfokey(DBD *s extern int dbif_txn_begin(DBD *); extern int dbif_txn_commit(DBD *); extern int dbif_txn_abort(DBD *); - extern void dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */ + extern int dbif_txn_close(DBD *dbd, int ret); /* Switch between commit+abort */ extern int dbif_txn_checkpoint(DBD *, u_int32_t, u_int32_t, u_int32_t); extern int dbif_dump(DBD *dbd, int dumpindexes); diff --combined etc/cnid_dbd/main.c index 1c951cb9,64734396..4f5fd725 --- a/etc/cnid_dbd/main.c +++ b/etc/cnid_dbd/main.c @@@ -8,20 -8,28 +8,20 @@@ #include "config.h" #endif /* HAVE_CONFIG_H */ -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ -#ifdef HAVE_FCNTL_H #include -#endif /* HAVE_FCNTL_H */ #include #include #include #include #include -#ifdef HAVE_SYS_TYPES_H #include -#endif /* HAVE_SYS_TYPES_H */ #include -#ifdef HAVE_SYS_STAT_H #include -#endif /* HAVE_SYS_STAT_H */ #include #include +#include -#include #include #include #include @@@ -31,19 -39,18 +31,18 @@@ #include "dbd.h" #include "comm.h" - #define LOCKFILENAME "lock" - /* Note: DB_INIT_LOCK is here so we can run the db_* utilities while netatalk is running. It's a likey performance hit, but it might we worth it. */ - #define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN | DB_RECOVER) + #define DBOPTIONS (DB_CREATE | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_LOCK | DB_INIT_TXN) /* Global, needed by pack.c:idxname() */ struct volinfo volinfo; static DBD *dbd; static int exit_sig = 0; + static int db_locked; static void sig_exit(int signo) { @@@ -248,34 -255,6 +247,6 @@@ static void switch_to_user(char *dir } } - /* ------------------------ */ - static int get_lock(void) - { - int lockfd; - struct flock lock; - - if ((lockfd = open(LOCKFILENAME, O_RDWR | O_CREAT, 0644)) < 0) { - LOG(log_error, logtype_cnid, "main: error opening lockfile: %s", strerror(errno)); - exit(1); - } - - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - lock.l_type = F_WRLCK; - - if (fcntl(lockfd, F_SETLK, &lock) < 0) { - if (errno == EACCES || errno == EAGAIN) { - LOG(log_error, logtype_cnid, "get_lock: locked"); - exit(0); - } else { - LOG(log_error, logtype_cnid, "main: fcntl F_WRLCK lockfile: %s", strerror(errno)); - exit(1); - } - } - - return lockfd; - } /* ----------------------- */ static void set_signal(void) @@@ -299,25 -278,12 +270,12 @@@ } } - /* ----------------------- */ - static void free_lock(int lockfd) - { - struct flock lock; - - lock.l_start = 0; - lock.l_whence = SEEK_SET; - lock.l_len = 0; - lock.l_type = F_UNLCK; - fcntl(lockfd, F_SETLK, &lock); - close(lockfd); - } - /* ------------------------ */ int main(int argc, char *argv[]) { struct db_param *dbp; int err = 0; - int lockfd, ctrlfd, clntfd; + int ctrlfd, clntfd; char *logconfig; set_processname("cnid_dbd"); @@@ -355,9 -321,18 +313,18 @@@ switch_to_user(dbpath); - /* Before we do anything else, check if there is an instance of cnid_dbd - running already and silently exit if yes. */ - lockfd = get_lock(); + /* Get db lock */ + if ((db_locked = get_lock(LOCK_EXCL, dbpath)) == -1) { + LOG(log_error, logtype_cnid, "main: fatal db lock error"); + exit(1); + } + if (db_locked != LOCK_EXCL) { + /* Couldn't get exclusive lock, try shared lock */ + if ((db_locked = get_lock(LOCK_SHRD, NULL)) != LOCK_SHRD) { + LOG(log_error, logtype_cnid, "main: fatal db lock error"); + exit(1); + } + } set_signal(); @@@ -371,7 -346,10 +338,10 @@@ if (NULL == (dbd = dbif_init(dbpath, "cnid2.db"))) exit(2); - if (dbif_env_open(dbd, dbp, DBOPTIONS) < 0) + /* Only recover if we got the lock */ + if (dbif_env_open(dbd, + dbp, + (db_locked == LOCK_EXCL) ? DBOPTIONS | DB_RECOVER : DBOPTIONS) < 0) exit(2); /* FIXME: same exit code as failure for dbif_open() */ LOG(log_debug, logtype_cnid, "Finished initializing BerkeleyDB environment"); @@@ -381,6 -359,19 +351,19 @@@ } LOG(log_debug, logtype_cnid, "Finished opening BerkeleyDB databases"); + /* Downgrade db lock */ + if (db_locked == LOCK_EXCL) { + if (get_lock(LOCK_UNLOCK, NULL) != 0) { + dbif_close(dbd); + exit(2); + } + if (get_lock(LOCK_SHRD, NULL) != LOCK_SHRD) { + dbif_close(dbd); + exit(2); + } + } + + if (comm_init(dbp, ctrlfd, clntfd) < 0) { dbif_close(dbd); exit(3); @@@ -395,8 -386,6 +378,6 @@@ if (dbif_env_remove(dbpath) < 0) err++; - free_lock(lockfd); - if (err) exit(4); else if (exit_sig) diff --combined include/atalk/dsi.h index e16681a4,babd8288..7b90b38e --- a/include/atalk/dsi.h +++ b/include/atalk/dsi.h @@@ -6,15 -6,19 +6,15 @@@ #ifndef _ATALK_DSI_H #define _ATALK_DSI_H -#include #include #include +#include #include +#include #include #include #include -#include - -#ifdef __OpenBSD__ -#include -#endif /* What a DSI packet looks like: 0 32 @@@ -51,6 -55,7 +51,7 @@@ struct dsi_block #define DSI_CMDSIZ 8192 #define DSI_DATASIZ 8192 + /* child and parent processes might interpret a couple of these * differently. */ typedef struct DSI { @@@ -87,16 -92,16 +88,16 @@@ #endif #ifdef USE_ZEROCONF + char *bonjourname; /* server name as UTF8 maxlen MAXINSTANCENAMELEN */ int zeroconf_registered; #endif - /* buffer for OSX deadlock */ + /* DSI readahead buffer used for buffered reads in dsi_peek */ + size_t dsireadbuf; /* size of the DSI readahead buffer used in dsi_peek() */ char *buffer; char *start; char *eof; char *end; - int maxsize; - } DSI; /* DSI flags */ @@@ -151,6 -156,7 +152,7 @@@ #define DSI_NOREPLY (1 << 6) /* in dsi_write we generate our own replies */ #define DSI_RECONSOCKET (1 << 7) /* we have a new socket from primary reconnect */ #define DSI_RECONINPROG (1 << 8) /* used in the new session in reconnect */ + #define DSI_AFP_LOGGED_OUT (1 << 9) /* client called afp_logout, quit on next EOF from socket */ /* basic initialization: dsi_init.c */ extern DSI *dsi_init (const dsi_proto /*protocol*/, diff --combined include/atalk/unicode.h index 1bb2ee3e,325b7ac2..27441549 --- a/include/atalk/unicode.h +++ b/include/atalk/unicode.h @@@ -1,6 -1,8 +1,6 @@@ #ifndef _ATALK_UNICODE_H #define _ATALK_UNICODE_H 1 -#include -#include #include #include @@@ -90,9 -92,13 +90,13 @@@ extern int atalk_iconv_close (atalk_ico extern struct charset_functions *find_charset_functions (const char *); extern int atalk_register_charset (struct charset_functions *); + /* from utf16_case.c */ + extern ucs2_t toupper_w (ucs2_t); + extern u_int32_t toupper_sp (u_int32_t); + extern ucs2_t tolower_w (ucs2_t); + extern u_int32_t tolower_sp (u_int32_t); + /* from util_unistr.c */ - extern ucs2_t toupper_w (ucs2_t); - extern ucs2_t tolower_w (ucs2_t); extern int strupper_w (ucs2_t *); extern int strlower_w (ucs2_t *); extern int islower_w (ucs2_t); diff --combined include/atalk/util.h index 7b1b10fb,999f14da..1a428bda --- a/include/atalk/util.h +++ b/include/atalk/util.h @@@ -11,11 -11,16 +11,13 @@@ #ifndef _ATALK_UTIL_H #define _ATALK_UTIL_H 1 -#include #include -#ifdef HAVE_UNISTD_H +#include #include -#endif /* HAVE_UNISTD_H */ #include -#include + #include + #include /* exit error codes */ #define EXITERR_CLNT 1 /* client related error */ @@@ -41,17 -46,7 +43,17 @@@ #define AFP_ASSERT(b) #endif /* NDEBUG */ +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + #define STRCMP(a,b,c) (strcmp(a,c) b 0) +#define ZERO_STRUCT(a) memset(&(a), 0, sizeof(a)) +#define ZERO_STRUCTP(a) memset((a), 0, sizeof(a)) #ifdef WITH_SENDFILE extern ssize_t sys_sendfile (int __out_fd, int __in_fd, off_t *__offset,size_t __count); @@@ -64,6 -59,7 +66,6 @@@ extern void freeifacelist(char **) #define diatolower(x) _dialowermap[(unsigned char) (x)] #define diatoupper(x) _diacasemap[(unsigned char) (x)] -extern int atalk_aton (char *, struct at_addr *); extern void bprint (char *, int); extern int strdiacasecmp (const char *, const char *); extern int strndiacasecmp (const char *, const char *, size_t); @@@ -72,6 -68,19 +74,6 @@@ extern void fault_setup (void (*fn)(v extern void netatalk_panic(const char *why); #define server_unlock(x) (unlink(x)) -/* strlcpy and strlcat are used by pam modules */ -#ifndef UAM_MODULE_EXPORT -#define UAM_MODULE_EXPORT -#endif - -#ifndef HAVE_STRLCPY -UAM_MODULE_EXPORT size_t strlcpy (char *, const char *, size_t); -#endif - -#ifndef HAVE_STRLCAT -UAM_MODULE_EXPORT size_t strlcat (char *, const char *, size_t); -#endif - #ifndef HAVE_DLFCN_H extern void *mod_open (const char *); extern void *mod_symbol (void *, const char *); @@@ -155,9 -164,14 +157,15 @@@ extern int recv_fd(int fd, int nonblock * unix.c *****************************************************************/ +extern const char *abspath(const char *name); extern const char *getcwdpath(void); extern char *stripped_slashes_basename(char *p); extern int lchdir(const char *dir); extern void randombytes(void *buf, int n); #endif /* _ATALK_UTIL_H */ + + /****************************************************************** + * cnid.c + *****************************************************************/ + + extern bstring rel_path_in_vol(const char *path, const char *volpath); diff --combined libatalk/acl/unix.c index 57933f08,f72d9aae..0ff0ea5b --- a/libatalk/acl/unix.c +++ b/libatalk/acl/unix.c @@@ -52,7 -52,7 +52,7 @@@ int get_nfsv4_acl(const char *name, ace /* sorry, no ACLs for symlinks */ return 0; - if ( ! (S_ISREG(st.st_mode) || S_ISDIR(st.st_mode))) { + if ( ! ((S_ISREG(st.st_mode)) || (S_ISDIR(st.st_mode)))) { LOG(log_warning, logtype_afpd, "get_nfsv4_acl(\"%s/%s\"): special", getcwdpath(), name); return 0; } @@@ -217,7 -217,7 +217,7 @@@ int nfsv4_chmod(char *name, mode_t mode { int ret = -1; int noaces, nnaces; - ace_t *oacl = NULL, *nacl = NULL, *cacl; + ace_t *oacl = NULL, *nacl = NULL, *cacl = NULL; LOG(log_debug, logtype_afpd, "nfsv4_chmod(\"%s/%s\", %04o)", getcwdpath(), name, mode); diff --combined libatalk/cnid/dbd/cnid_dbd.c index 12287ff0,4ad68831..b7e1f403 --- a/libatalk/cnid/dbd/cnid_dbd.c +++ b/libatalk/cnid/dbd/cnid_dbd.c @@@ -11,8 -11,15 +11,8 @@@ #ifdef CNID_BACKEND_DBD #include -#ifdef HAVE_SYS_STAT_H #include -#endif /* HAVE_SYS_STAT_H */ -#ifdef HAVE_SYS_UIO_H #include -#endif /* HAVE_SYS_UIO_H */ -#ifdef HAVE_STRINGS_H -#include -#endif #include #include #include @@@ -26,8 -33,8 +26,8 @@@ #include #include #include +#include -#include #include #include #include @@@ -97,7 -104,7 +97,7 @@@ static int tsock_getfd(const char *host } if (setnonblock(sock, 1) != 0) { - LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(err)); + LOG(log_error, logtype_cnid, "getfd: setnonblock: %s", strerror(errno)); close(sock); sock = -1; return -1; @@@ -266,7 -273,7 +266,7 @@@ static int send_packet(CNID_private *db vecs = 1; if (rqst->namelen) { - iov[1].iov_base = rqst->name; + iov[1].iov_base = (char *)rqst->name; iov[1].iov_len = rqst->namelen; towrite += rqst->namelen; vecs++; @@@ -531,7 -538,8 +531,7 @@@ void cnid_dbd_close(struct _cnid_db *cd /* ---------------------- */ cnid_t cnid_dbd_add(struct _cnid_db *cdb, const struct stat *st, - const cnid_t did, char *name, const size_t len, - cnid_t hint) + cnid_t did, const char *name, size_t len, cnid_t hint) { CNID_private *db; struct cnid_dbd_rqst rqst; @@@ -595,7 -603,7 +595,7 @@@ } /* ---------------------- */ -cnid_t cnid_dbd_get(struct _cnid_db *cdb, const cnid_t did, char *name, const size_t len) +cnid_t cnid_dbd_get(struct _cnid_db *cdb, cnid_t did, const char *name, size_t len) { CNID_private *db; struct cnid_dbd_rqst rqst; @@@ -721,8 -729,8 +721,8 @@@ int cnid_dbd_getstamp(struct _cnid_db * } /* ---------------------- */ -cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, const cnid_t did, - char *name, const size_t len) +cnid_t cnid_dbd_lookup(struct _cnid_db *cdb, const struct stat *st, cnid_t did, + const char *name, size_t len) { CNID_private *db; struct cnid_dbd_rqst rqst; @@@ -783,7 -791,7 +783,7 @@@ } /* ---------------------- */ -int cnid_dbd_find(struct _cnid_db *cdb, char *name, size_t namelen, void *buffer, size_t buflen) +int cnid_dbd_find(struct _cnid_db *cdb, const char *name, size_t namelen, void *buffer, size_t buflen) { CNID_private *db; struct cnid_dbd_rqst rqst; @@@ -838,8 -846,8 +838,8 @@@ } /* ---------------------- */ -int cnid_dbd_update(struct _cnid_db *cdb, const cnid_t id, const struct stat *st, - const cnid_t did, char *name, const size_t len) +int cnid_dbd_update(struct _cnid_db *cdb, cnid_t id, const struct stat *st, + cnid_t did, const char *name, size_t len) { CNID_private *db; struct cnid_dbd_rqst rqst; @@@ -893,7 -901,8 +893,7 @@@ /* ---------------------- */ cnid_t cnid_dbd_rebuild_add(struct _cnid_db *cdb, const struct stat *st, - const cnid_t did, char *name, const size_t len, - cnid_t hint) + cnid_t did, const char *name, size_t len, cnid_t hint) { CNID_private *db; struct cnid_dbd_rqst rqst; diff --combined libatalk/dsi/dsi_close.c index 42a65ecd,6362182b..80bee3fe --- a/libatalk/dsi/dsi_close.c +++ b/libatalk/dsi/dsi_close.c @@@ -11,14 -11,13 +11,14 @@@ #include #include +#include + #include -#include void dsi_close(DSI *dsi) { /* server generated. need to set all the fields. */ - if (!(dsi->flags & DSI_SLEEPING)) { + if (!(dsi->flags & DSI_SLEEPING) && !(dsi->flags & DSI_DISCONNECTED)) { dsi->header.dsi_flags = DSIFL_REQUEST; dsi->header.dsi_command = DSIFUNC_CLOSE; dsi->header.dsi_requestID = htons(dsi_serverID(dsi)); diff --combined libatalk/dsi/dsi_getsess.c index 180049f2,221ac47a..5ea32b01 --- a/libatalk/dsi/dsi_getsess.c +++ b/libatalk/dsi/dsi_getsess.c @@@ -18,8 -18,18 +18,8 @@@ #include #include -/* POSIX.1 sys/wait.h check */ #include -#ifdef HAVE_SYS_WAIT_H #include -#endif /* HAVE_SYS_WAIT_H */ -#ifndef WEXITSTATUS -#define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) -#endif /* ! WEXITSTATUS */ -#ifndef WIFEXITED -#define WIFEXITED(stat_val) (((stat_val) & 255) == 0) -#endif /* ! WIFEXITED */ - #include #include #include @@@ -35,12 -45,12 +35,12 @@@ afp_child_t *dsi_getsession(DSI *dsi, s afp_child_t *child; if (socketpair(PF_UNIX, SOCK_STREAM, 0, ipc_fds) < 0) { - LOG(log_error, logtype_afpd, "dsi_getsess: %s", strerror(errno)); + LOG(log_error, logtype_dsi, "dsi_getsess: %s", strerror(errno)); exit( EXITERR_CLNT ); } if (setnonblock(ipc_fds[0], 1) != 0 || setnonblock(ipc_fds[1], 1) != 0) { - LOG(log_error, logtype_afpd, "dsi_getsess: setnonblock: %s", strerror(errno)); + LOG(log_error, logtype_dsi, "dsi_getsess: setnonblock: %s", strerror(errno)); exit(EXITERR_CLNT); } diff --combined libatalk/dsi/dsi_stream.c index 149bc208,680967e8..90df884e --- a/libatalk/dsi/dsi_stream.c +++ b/libatalk/dsi/dsi_stream.c @@@ -1,6 -1,4 +1,4 @@@ /* - * $Id: dsi_stream.c,v 1.20 2009-10-26 12:35:56 franklahm Exp $ - * * Copyright (c) 1998 Adrian Sun (asun@zoology.washington.edu) * All rights reserved. See COPYRIGHT. * @@@ -15,8 -13,6 +13,6 @@@ #include "config.h" #endif /* HAVE_CONFIG_H */ - #define USE_WRITEV - #include #include @@@ -28,13 -24,11 +24,10 @@@ #include #include #include - - #ifdef USE_WRITEV #include - #endif #include #include -#include #include #define min(a,b) ((a) < (b) ? (a) : (b)) @@@ -47,47 -41,44 +40,44 @@@ #define MSG_DONTWAIT 0x40 #endif - /* ------------------------- - * we don't use a circular buffer. - */ - static void dsi_init_buffer(DSI *dsi) - { - if (!dsi->buffer) { - /* XXX config options */ - dsi->maxsize = 6 * dsi->server_quantum; - if (!dsi->maxsize) - dsi->maxsize = 6 * DSI_SERVQUANT_DEF; - dsi->buffer = malloc(dsi->maxsize); - if (!dsi->buffer) { - return; - } - dsi->start = dsi->buffer; - dsi->eof = dsi->buffer; - dsi->end = dsi->buffer + dsi->maxsize; - } - } - - /* ---------------------- - afpd is sleeping too much while trying to send something. - May be there's no reader or the reader is also sleeping in write, - look if there's some data for us to read, hopefully it will wake up - the reader so we can write again. - */ + /* + * afpd is sleeping too much while trying to send something. + * May be there's no reader or the reader is also sleeping in write, + * look if there's some data for us to read, hopefully it will wake up + * the reader so we can write again. + * + * @returns 0 when is possible to send again, -1 on error + */ static int dsi_peek(DSI *dsi) { + static int warned = 0; fd_set readfds, writefds; int len; int maxfd; int ret; - FD_ZERO(&readfds); - FD_ZERO(&writefds); - FD_SET( dsi->socket, &readfds); - FD_SET( dsi->socket, &writefds); - maxfd = dsi->socket +1; + LOG(log_debug, logtype_dsi, "dsi_peek"); + + maxfd = dsi->socket + 1; while (1) { - FD_SET( dsi->socket, &readfds); + FD_ZERO(&readfds); + FD_ZERO(&writefds); + + if (dsi->eof < dsi->end) { + /* space in read buffer */ + FD_SET( dsi->socket, &readfds); + } else { + if (!warned) { + warned = 1; + LOG(log_note, logtype_dsi, "dsi_peek: readahead buffer is full, possibly increase -dsireadbuf option"); + LOG(log_note, logtype_dsi, "dsi_peek: dsireadbuf: %d, DSI quantum: %d, effective buffer size: %d", + dsi->dsireadbuf, + dsi->server_quantum ? dsi->server_quantum : DSI_SERVQUANT_DEF, + dsi->end - dsi->buffer); + } + } + FD_SET( dsi->socket, &writefds); /* No timeout: if there's nothing to read nor nothing to write, @@@ -97,29 -88,35 +87,35 @@@ /* we might have been interrupted by out timer, so restart select */ continue; /* give up */ + LOG(log_error, logtype_dsi, "dsi_peek: unexpected select return: %d %s", + ret, ret < 0 ? strerror(errno) : ""); + return -1; + } + + if (FD_ISSET(dsi->socket, &writefds)) { + /* we can write again */ + LOG(log_debug, logtype_dsi, "dsi_peek: can write again"); break; } /* Check if there's sth to read, hopefully reading that will unblock the client */ if (FD_ISSET(dsi->socket, &readfds)) { - dsi_init_buffer(dsi); - len = dsi->end - dsi->eof; - - if (len <= 0) { - /* ouch, our buffer is full ! fall back to blocking IO - * could block and disconnect but it's better than a cpu hog */ - break; + len = dsi->end - dsi->eof; /* it's ensured above that there's space */ + + if ((len = read(dsi->socket, dsi->eof, len)) <= 0) { + if (len == 0) { + LOG(log_error, logtype_dsi, "dsi_peek: EOF"); + return -1; + } + LOG(log_error, logtype_dsi, "dsi_peek: read: %s", strerror(errno)); + if (errno == EAGAIN) + continue; + return -1; } + LOG(log_debug, logtype_dsi, "dsi_peek: read %d bytes", len); - len = read(dsi->socket, dsi->eof, len); - if (len <= 0) - break; dsi->eof += len; } - - if (FD_ISSET(dsi->socket, &writefds)) - /* we can write again at last */ - break; } return 0; @@@ -140,12 -137,6 +136,6 @@@ ssize_t dsi_stream_write(DSI *dsi, voi LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length); - /* non blocking mode */ - if (setnonblock(dsi->socket, 1) < 0) { - LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno)); - return -1; - } - while (written < length) { len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags); if (len >= 0) { @@@ -157,6 -148,8 +147,8 @@@ continue; if (errno == EAGAIN || errno == EWOULDBLOCK) { + LOG(log_debug, logtype_dsi, "dsi_stream_write: send: %s", strerror(errno)); + if (mode == DSI_NOWAIT && written == 0) { /* DSI_NOWAIT is used by attention give up in this case. */ written = -1; @@@ -180,11 -173,6 +172,6 @@@ dsi->write_count += written; exit: - if (setnonblock(dsi->socket, 0) < 0) { - LOG(log_error, logtype_dsi, "dsi_stream_write: setnonblock: %s", strerror(errno)); - written = -1; - } - dsi->in_write--; return written; } @@@ -198,15 -186,11 +185,11 @@@ ssize_t dsi_stream_read_file(DSI *dsi, size_t written; ssize_t len; + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length); + dsi->in_write++; written = 0; - /* non blocking mode */ - if (setnonblock(dsi->socket, 1) < 0) { - LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno)); - return -1; - } - while (written < length) { len = sys_sendfile(dsi->socket, fromfd, &offset, length - written); @@@ -225,7 -209,7 +208,7 @@@ } continue; } - LOG(log_error, logtype_dsi, "dsi_stream_write: %s", strerror(errno)); + LOG(log_error, logtype_dsi, "dsi_stream_read_file: %s", strerror(errno)); break; } else if (!len) { @@@ -237,11 -221,6 +220,6 @@@ written += len; } - if (setnonblock(dsi->socket, 0) < 0) { - LOG(log_error, logtype_dsi, "dsi_stream_read_file: setnonblock: %s", strerror(errno)); - return -1; - } - dsi->write_count += written; dsi->in_write--; return written; @@@ -254,20 -233,27 +232,27 @@@ static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count) { size_t nbe = 0; - - if (dsi->start) { - nbe = dsi->eof - dsi->start; - if (nbe > 0) { - nbe = min((size_t)nbe, count); - memcpy(buf, dsi->start, nbe); - dsi->start += nbe; + if (dsi->buffer == NULL) + /* afpd master has no DSI buffering */ + return 0; - if (dsi->eof == dsi->start) - dsi->start = dsi->eof = dsi->buffer; + LOG(log_maxdebug, logtype_dsi, "from_buf: %u bytes", count); + + nbe = dsi->eof - dsi->start; - } + if (nbe > 0) { + nbe = min((size_t)nbe, count); + memcpy(buf, dsi->start, nbe); + dsi->start += nbe; + + if (dsi->eof == dsi->start) + dsi->start = dsi->eof = dsi->buffer; } + + LOG(log_debug, logtype_dsi, "from_buf(read: %u, unread:%u , space left: %u): returning %u", + dsi->start - dsi->buffer, dsi->eof - dsi->start, dsi->end - dsi->eof, nbe); + return nbe; } @@@ -281,46 -267,61 +266,61 @@@ */ static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count) { - ssize_t nbe; - + ssize_t len; + + LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes)", count); + if (!count) return 0; - nbe = from_buf(dsi, buf, count); /* 1. */ - if (nbe) - return nbe; /* 2. */ + len = from_buf(dsi, buf, count); /* 1. */ + if (len) + return len; /* 2. */ - return read(dsi->socket, buf, count); /* 3. */ + len = readt(dsi->socket, buf, count, 0, 1); /* 3. */ + + LOG(log_maxdebug, logtype_dsi, "buf_read(%u bytes): got: %d", count, len); + + return len; } /* * Essentially a loop around buf_read() to ensure "length" bytes are read * from dsi->buffer and/or the socket. + * + * @returns length on success, some value smaller then length indicates an error */ size_t dsi_stream_read(DSI *dsi, void *data, const size_t length) { size_t stored; ssize_t len; + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes)", length); + stored = 0; while (stored < length) { - len = buf_read(dsi, (u_int8_t *) data + stored, length - stored); - if (len == -1 && errno == EINTR) { - continue; - } else if (len > 0) { - stored += len; - } else { /* eof or error */ - /* don't log EOF error if it's just after connect (OSX 10.3 probe) */ - if (len || stored || dsi->read_count) { - if (! (dsi->flags & DSI_DISCONNECTED)) - LOG(log_error, logtype_dsi, "dsi_stream_read(fd: %i): len:%d, %s", - dsi->socket, len, (len < 0) ? strerror(errno) : "unexpected EOF"); + len = buf_read(dsi, (u_int8_t *) data + stored, length - stored); + if (len == -1 && (errno == EINTR || errno == EAGAIN)) { + LOG(log_debug, logtype_dsi, "dsi_stream_read: select read loop"); + continue; + } else if (len > 0) { + stored += len; + } else { /* eof or error */ + /* don't log EOF error if it's just after connect (OSX 10.3 probe) */ + if (len || stored || dsi->read_count) { + if (! (dsi->flags & DSI_DISCONNECTED)) { + LOG(log_error, logtype_dsi, "dsi_stream_read: len:%d, %s", + len, (len < 0) ? strerror(errno) : "unexpected EOF"); + } + return 0; + } + break; } - break; - } } dsi->read_count += stored; + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_read(%u bytes): got: %u", length, stored); return stored; } @@@ -332,8 -333,9 +332,9 @@@ static size_t dsi_buffered_stream_read( { size_t len; size_t buflen; + + LOG(log_maxdebug, logtype_dsi, "dsi_buffered_stream_read: %u bytes", length); - dsi_init_buffer(dsi); len = from_buf(dsi, data, length); /* read from buffer dsi->buffer */ dsi->read_count += len; if (len == length) { /* got enough bytes from there ? */ @@@ -375,11 -377,12 +376,12 @@@ static void unblock_sig(DSI *dsi int dsi_stream_send(DSI *dsi, void *buf, size_t length) { char block[DSI_BLOCKSIZ]; - #ifdef USE_WRITEV struct iovec iov[2]; size_t towrite; ssize_t len; - #endif /* USE_WRITEV */ + + LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes", + length ? length : sizeof(block)); block[0] = dsi->header.dsi_flags; block[1] = dsi->header.dsi_command; @@@ -397,7 -400,6 +399,6 @@@ /* block signals */ block_sig(dsi); - #ifdef USE_WRITEV iov[0].iov_base = block; iov[0].iov_len = sizeof(block); iov[1].iov_base = buf; @@@ -406,46 -408,36 +407,36 @@@ towrite = sizeof(block) + length; dsi->write_count += towrite; while (towrite > 0) { - if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || - !len) - continue; + if (((len = writev(dsi->socket, iov, 2)) == -1 && errno == EINTR) || (len == 0)) + continue; - if ((size_t)len == towrite) /* wrote everything out */ - break; - else if (len < 0) { /* error */ - if (errno == EAGAIN || errno == EWOULDBLOCK) { - if (!dsi_peek(dsi)) { - continue; + if ((size_t)len == towrite) /* wrote everything out */ + break; + else if (len < 0) { /* error */ + if (errno == EAGAIN || errno == EWOULDBLOCK) { + if (!dsi_peek(dsi)) { + continue; + } } + LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno)); + unblock_sig(dsi); + return 0; } - LOG(log_error, logtype_dsi, "dsi_stream_send: %s", strerror(errno)); - unblock_sig(dsi); - return 0; - } - towrite -= len; - if (towrite > length) { /* skip part of header */ - iov[0].iov_base = (char *) iov[0].iov_base + len; - iov[0].iov_len -= len; - } else { /* skip to data */ - if (iov[0].iov_len) { - len -= iov[0].iov_len; - iov[0].iov_len = 0; + towrite -= len; + if (towrite > length) { /* skip part of header */ + iov[0].iov_base = (char *) iov[0].iov_base + len; + iov[0].iov_len -= len; + } else { /* skip to data */ + if (iov[0].iov_len) { + len -= iov[0].iov_len; + iov[0].iov_len = 0; + } + iov[1].iov_base = (char *) iov[1].iov_base + len; + iov[1].iov_len -= len; } - iov[1].iov_base = (char *) iov[1].iov_base + len; - iov[1].iov_len -= len; - } } - #else /* USE_WRITEV */ - /* write the header then data */ - if ((dsi_stream_write(dsi, block, sizeof(block), 1) != sizeof(block)) || - (dsi_stream_write(dsi, buf, length, 0) != length)) { - unblock_sig(dsi); - return 0; - } - #endif /* USE_WRITEV */ - unblock_sig(dsi); return 1; } @@@ -460,6 -452,8 +451,8 @@@ int dsi_stream_receive(DSI *dsi, void * { char block[DSI_BLOCKSIZ]; + LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength); + /* read in the header */ if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block)) return 0; diff --combined libatalk/unicode/util_unistr.c index da61a437,070ca93b..5e4ae859 --- a/libatalk/unicode/util_unistr.c +++ b/libatalk/unicode/util_unistr.c @@@ -9,59 -9,13 +9,12 @@@ #include #include #include - -#include +#include #include - #include "ucs2_casetable.h" #include "precompose.h" #include "byteorder.h" - /******************************************************************* - Convert a wide character to upper/lower case. - ********************************************************************/ - ucs2_t toupper_w(ucs2_t val) - { - if ( val >= 0x0040 && val <= 0x007F) - return upcase_table_1[val-0x0040]; - if ( val >= 0x00C0 && val <= 0x02BF) - return upcase_table_2[val-0x00C0]; - if ( val >= 0x0380 && val <= 0x04FF) - return upcase_table_3[val-0x0380]; - if ( val >= 0x0540 && val <= 0x05BF) - return upcase_table_4[val-0x0540]; - if ( val >= 0x1E00 && val <= 0x1FFF) - return upcase_table_5[val-0x1E00]; - if ( val >= 0x2140 && val <= 0x217F) - return upcase_table_6[val-0x2140]; - if ( val >= 0x24C0 && val <= 0x24FF) - return upcase_table_7[val-0x24C0]; - if ( val >= 0xFF40 && val <= 0xFF7F) - return upcase_table_8[val-0xFF40]; - - return (val); - } - - - ucs2_t tolower_w(ucs2_t val) - { - if ( val >= 0x0040 && val <= 0x007F) - return lowcase_table_1[val-0x0040]; - if ( val >= 0x00C0 && val <= 0x023F) - return lowcase_table_2[val-0x00C0]; - if ( val >= 0x0380 && val <= 0x057F) - return lowcase_table_3[val-0x0380]; - if ( val >= 0x1E00 && val <= 0x1FFF) - return lowcase_table_4[val-0x1E00]; - if ( val >= 0x2140 && val <= 0x217F) - return lowcase_table_5[val-0x2140]; - if ( val >= 0x2480 && val <= 0x24FF) - return lowcase_table_6[val-0x2480]; - if ( val >= 0xFF00 && val <= 0xFF3F) - return lowcase_table_7[val-0xFF00]; - - return (val); - } - /******************************************************************* Convert a string to lower case. return True if any char is converted diff --combined libatalk/util/Makefile.am index 957bf527,af5d3c9f..17ae747c --- a/libatalk/util/Makefile.am +++ b/libatalk/util/Makefile.am @@@ -1,13 -1,14 +1,13 @@@ # Makefile.am for libatalk/util/ -noinst_LTLIBRARIES = libutil.la +pkgconfdir = @PKGCONFDIR@ -AM_CFLAGS = -I$(top_srcdir)/sys +noinst_LTLIBRARIES = libutil.la libutil_la_SOURCES = \ - atalk_addr.c \ bprint.c \ + cnid.c \ fault.c \ - ftw.c \ getiface.c \ locking.c \ logger.c \ @@@ -17,8 -18,12 +17,12 @@@ server_ipc.c \ server_lock.c \ socket.c \ - strcasestr.c \ strdicasecmp.c \ - strlcpy.c \ - volinfo.c \ + volinfo.c \ unix.c - libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\" ++libutil_la_CFLAGS = -D_PATH_AFPDCONF=\"$(pkgconfdir)/afpd.conf\" ++ + if HAVE_ATFUNCS + libutil_la_SOURCES += ftw.c + endif diff --combined libatalk/util/server_child.c index e8ed4d4d,ecefbd2c..47e9baa2 --- a/libatalk/util/server_child.c +++ b/libatalk/util/server_child.c @@@ -18,11 -18,17 +18,11 @@@ #include #include -#ifdef HAVE_UNISTD_H #include -#endif /* HAVE_UNISTD_H */ #include #include - -/* POSIX.1 sys/wait.h check */ #include -#ifdef HAVE_SYS_WAIT_H #include -#endif /* HAVE_SYS_WAIT_H */ #include #include @@@ -331,9 -337,9 +331,9 @@@ void server_child_kill_one_by_id(server "Session with different pid[%u]", child->pid); } } else { - kill_child(child); - LOG(log_note, logtype_default, - "Terminated disconnected session[%u]", child->pid); + /* One client with multiple sessions */ + LOG(log_debug, logtype_default, + "Found another session[%u] for client[%u]", child->pid, pid); } } } else { @@@ -341,7 -347,7 +341,7 @@@ child->time = boottime; if (child->clientid) free(child->clientid); - LOG(log_debug, logtype_default, "Setting client ID for %d", child->pid); + LOG(log_debug, logtype_default, "Setting client ID for %u", child->pid); child->uid = uid; child->valid = 1; child->idlen = idlen; diff --combined libatalk/vfs/ea_sys.c index a4fa75b5,77ab783b..5b210d81 --- a/libatalk/vfs/ea_sys.c +++ b/libatalk/vfs/ea_sys.c @@@ -1,4 -1,5 +1,4 @@@ /* - $Id: ea_sys.c,v 1.8 2010-04-13 08:05:06 franklahm Exp $ Copyright (c) 2009 Frank Lahm This program is free software; you can redistribute it and/or modify @@@ -25,7 -26,20 +25,7 @@@ #include #include #include - -#if HAVE_ATTR_XATTR_H -#include -#elif HAVE_SYS_XATTR_H -#include -#endif - -#ifdef HAVE_SYS_EA_H -#include -#endif - -#ifdef HAVE_SYS_EXTATTR_H -#include -#endif +#include #include #include @@@ -37,6 -51,11 +37,6 @@@ #include #include -#ifndef ENOATTR -#define ENOATTR ENODATA -#endif - - /********************************************************************************** * EA VFS funcs for storing EAs in nativa filesystem EAs **********************************************************************************/ @@@ -196,8 -215,6 +196,8 @@@ int sys_get_eacontent(VFS_FUNC_ARGS_EA_ * * Copies names of all EAs of uname as consecutive C strings into rbuf. * Increments *rbuflen accordingly. + * We hide the adouble:ea extended attributes here, but we currently + * allow reading, writing and deleteting them. */ int sys_list_eas(VFS_FUNC_ARGS_EA_LIST) { @@@ -236,27 -253,26 +236,27 @@@ ptr = buf; while (ret > 0) { len = strlen(ptr); - - /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */ - if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) { - ret = AFPERR_MISC; - goto exit; - } - - LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr); - - attrbuflen += nlen + 1; - if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) { - /* Next EA name could overflow, so bail out with error. - FIXME: evantually malloc/memcpy/realloc whatever. - Is it worth it ? */ - LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname); - ret = AFPERR_MISC; - goto exit; + if (NOT_NETATALK_EA(ptr)) { + /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */ + if ( 0 >= ( nlen = convert_string(vol->v_volcharset, CH_UTF8_MAC, ptr, len, attrnamebuf + attrbuflen, 256)) ) { + ret = AFPERR_MISC; + goto exit; + } + + LOG(log_debug7, logtype_afpd, "sys_list_extattr(%s): attribute: %s", uname, ptr); + + attrbuflen += nlen + 1; + if (attrbuflen > (ATTRNAMEBUFSIZ - 256)) { + /* Next EA name could overflow, so bail out with error. + FIXME: evantually malloc/memcpy/realloc whatever. + Is it worth it ? */ + LOG(log_warning, logtype_afpd, "sys_list_extattr(%s): running out of buffer for EA names", uname); + ret = AFPERR_MISC; + goto exit; + } } - ret -= len +1; - ptr += len +1; + ret -= len + 1; + ptr += len + 1; } ret = AFP_OK; @@@ -309,15 -325,20 +309,20 @@@ int sys_set_ea(VFS_FUNC_ARGS_EA_SET switch(errno) { case OPEN_NOFOLLOW_ERRNO: /* its a symlink and client requested O_NOFOLLOW */ - LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): encountered symlink with kXAttrNoFollow", - uname, attruname); + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): encountered symlink with kXAttrNoFollow", + getcwdpath(), uname, attruname); return AFP_OK; case EEXIST: - LOG(log_debug, logtype_afpd, "sys_set_ea(%s/%s): EA already exists", - uname, attruname); + LOG(log_debug, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s'): EA already exists", + getcwdpath(), uname, attruname); return AFPERR_EXIST; default: - LOG(log_error, logtype_afpd, "sys_set_ea(%s/%s): error: %s", uname, attruname, strerror(errno)); + LOG(log_error, logtype_afpd, "sys_set_ea(\"%s/%s\", ea:'%s', size: %u, flags: %s|%s|%s): %s", + getcwdpath(), uname, attruname, attrsize, + oflag & O_CREAT ? "XATTR_CREATE" : "-", + oflag & O_TRUNC ? "XATTR_REPLACE" : "-", + oflag & O_NOFOLLOW ? "O_NOFOLLOW" : "-", + strerror(errno)); return AFPERR_MISC; } } diff --combined libatalk/vfs/extattr.c index 0115c153,00000000..bdae873e mode 100644,000000..100644 --- a/libatalk/vfs/extattr.c +++ b/libatalk/vfs/extattr.c @@@ -1,874 -1,0 +1,876 @@@ +/* + Unix SMB/CIFS implementation. + Samba system utilities + Copyright (C) Andrew Tridgell 1992-1998 + Copyright (C) Jeremy Allison 1998-2005 + Copyright (C) Timur Bakeyev 2005 + Copyright (C) Bjoern Jacke 2006-2007 + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + sys_copyxattr modified from LGPL2.1 libattr copyright + Copyright (C) 2001-2002 Silicon Graphics, Inc. All Rights Reserved. + Copyright (C) 2001 Andreas Gruenbacher. + + Samba 3.0.28, modified for netatalk. +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#if HAVE_ATTR_XATTR_H +#include +#elif HAVE_SYS_XATTR_H +#include +#endif + +#ifdef HAVE_SYS_EA_H +#include +#endif + +#ifdef HAVE_ATTROPEN + +#include +#endif + +#ifdef HAVE_SYS_EXTATTR_H +#include +#endif + +#include +#include +#include +#include +#include + +/******** Solaris EA helper function prototypes ********/ +#ifdef HAVE_ATTROPEN +#define SOLARIS_ATTRMODE S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP +static int solaris_write_xattr(int attrfd, const char *value, size_t size); +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size); +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size); +static int solaris_unlinkat(int attrdirfd, const char *name); +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode); +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode); +#endif + +/************************************************************************** + Wrappers for extented attribute calls. Based on the Linux package with + support for IRIX and (Net|Free)BSD also. Expand as other systems have them. +****************************************************************************/ +static char attr_name[256 +5] = "user."; + +static const char *prefix(const char *uname) +{ +#if defined(HAVE_ATTROPEN) + return uname; +#else + strlcpy(attr_name +5, uname, 256); + return attr_name; +#endif +} + +ssize_t sys_getxattr (const char *path, const char *uname, void *value, size_t size) +{ + const char *name = prefix(uname); + +#if defined(HAVE_GETXATTR) +#ifndef XATTR_ADD_OPT + return getxattr(path, name, value, size); +#else + int options = 0; + return getxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_GETEA) + return getea(path, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FILE) + ssize_t retval; + /* + * The BSD implementation has a nasty habit of silently truncating + * the returned value to the size of the buffer, so we have to check + * that the buffer is large enough to fit the returned value. + */ + if((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) { + if (size == 0) + /* size == 0 means only return size */ + return retval; + if (retval > size) { + errno = ERANGE; + return -1; + } + if ((retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0) + return retval; + } + + LOG(log_maxdebug, logtype_default, "sys_getxattr: extattr_get_file() failed with: %s\n", strerror(errno)); + return -1; +#elif defined(HAVE_ATTR_GET) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_attropen(path, name, O_RDONLY, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_fgetxattr (int filedes, const char *uname, void *value, size_t size) +{ + const char *name = prefix(uname); + +#if defined(HAVE_FGETXATTR) +#ifndef XATTR_ADD_OPT + return fgetxattr(filedes, name, value, size); +#else + int options = 0; + return fgetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_FGETEA) + return fgetea(filedes, name, value, size); +#elif defined(HAVE_EXTATTR_GET_FD) + char *s; + ssize_t retval; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0)) >= 0) { + if(retval > size) { + errno = ERANGE; + return -1; + } + if((retval=extattr_get_fd(filedes, attrnamespace, attrname, value, size)) >= 0) + return retval; + } + + LOG(log_debug, logtype_default, "sys_fgetxattr: extattr_get_fd(): %s", + strerror(errno))); + return -1; +#elif defined(HAVE_ATTR_GETF) + int retval, flags = 0; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_getf(filedes, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_openat(filedes, name, O_RDONLY|O_XATTR, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_lgetxattr (const char *path, const char *uname, void *value, size_t size) +{ + const char *name = prefix(uname); + +#if defined(HAVE_LGETXATTR) + return lgetxattr(path, name, value, size); +#elif defined(HAVE_GETXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return getxattr(path, name, value, size, 0, options); +#elif defined(HAVE_LGETEA) + return lgetea(path, name, value, size); +#elif defined(HAVE_EXTATTR_GET_LINK) + ssize_t retval; + if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0)) >= 0) { + if(retval > size) { + errno = ERANGE; + return -1; + } + if((retval=extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, value, size)) >= 0) + return retval; + } + + LOG(log_maxdebug, logtype_default, "sys_lgetxattr: extattr_get_link() failed with: %s\n", strerror(errno)); + return -1; +#elif defined(HAVE_ATTR_GET) + int retval, flags = ATTR_DONTFOLLOW; + int valuelength = (int)size; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + retval = attr_get(path, attrname, (char *)value, &valuelength, flags); + + return retval ? retval : valuelength; +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrfd = solaris_attropen(path, name, O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + if (attrfd >= 0) { + ret = solaris_read_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +#if defined(HAVE_EXTATTR_LIST_FILE) + +#define EXTATTR_PREFIX(s) (s), (sizeof((s))-1) + +static struct { + int space; + const char *name; + size_t len; +} +extattr[] = { + { EXTATTR_NAMESPACE_SYSTEM, EXTATTR_PREFIX("") }, + { EXTATTR_NAMESPACE_USER, EXTATTR_PREFIX("") }, +}; + +typedef union { + const char *path; + int filedes; +} extattr_arg; + +static ssize_t bsd_attr_list (int type, extattr_arg arg, char *list, size_t size) +{ + ssize_t list_size; + int i, len; + + switch(type) { +#if defined(HAVE_EXTATTR_LIST_FILE) + case 0: + list_size = extattr_list_file(arg.path, EXTATTR_NAMESPACE_USER, list, size); + break; +#endif +#if defined(HAVE_EXTATTR_LIST_LINK) + case 1: + list_size = extattr_list_link(arg.path, EXTATTR_NAMESPACE_USER, list, size); + break; +#endif +#if defined(HAVE_EXTATTR_LIST_FD) + case 2: + list_size = extattr_list_fd(arg.filedes, EXTATTR_NAMESPACE_USER, list, size); + break; +#endif + default: + errno = ENOSYS; + return -1; + } + + /* Some error happend. Errno should be set by the previous call */ + if(list_size < 0) + return -1; + + /* No attributes */ + if(list_size == 0) + return 0; + + /* XXX: Call with an empty buffer may be used to calculate + necessary buffer size. Unfortunately, we can't say, how + many attributes were returned, so here is the potential + problem with the emulation. + */ + if(list == NULL) + return list_size; + + /* Buffer is too small to fit the results */ + if(list_size > size) { + errno = ERANGE; + return -1; + } + + /* Convert from pascal strings to C strings */ + len = list[0]; + memmove(list, list + 1, list_size); + + for(i = len; i < list_size; ) { + LOG(log_maxdebug, logtype_afpd, "len: %d, i: %d", len, i); + + len = list[i]; + list[i] = '\0'; + i += len + 1; + } + + return list_size; +} + +#endif + +#if defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) +static char attr_buffer[ATTR_MAX_VALUELEN]; + +static ssize_t irix_attr_list(const char *path, int filedes, char *list, size_t size, int flags) +{ + int retval = 0, index; + attrlist_cursor_t *cursor = 0; + int total_size = 0; + attrlist_t * al = (attrlist_t *)attr_buffer; + attrlist_ent_t *ae; + size_t ent_size, left = size; + char *bp = list; + + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("user."); + if (left >= ent_size) { + strncpy(bp, "user.", sizeof("user.")); + strncat(bp, ae->a_name, ent_size - sizeof("user.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + if (retval == 0) { + flags |= ATTR_ROOT; + cursor = 0; + while (True) { + if (filedes) + retval = attr_listf(filedes, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + else + retval = attr_list(path, attr_buffer, ATTR_MAX_VALUELEN, flags, cursor); + if (retval) break; + for (index = 0; index < al->al_count; index++) { + ae = ATTR_ENTRY(attr_buffer, index); + ent_size = strlen(ae->a_name) + sizeof("system."); + if (left >= ent_size) { + strncpy(bp, "system.", sizeof("system.")); + strncat(bp, ae->a_name, ent_size - sizeof("system.")); + bp += ent_size; + left -= ent_size; + } else if (size) { + errno = ERANGE; + retval = -1; + break; + } + total_size += ent_size; + } + if (al->al_more == 0) break; + } + } + return (ssize_t)(retval ? retval : total_size); +} + +#endif + +#if defined(HAVE_LISTXATTR) +static ssize_t remove_user(ssize_t ret, char *list, size_t size) +{ + size_t len; + char *ptr; + char *ptr1; + ssize_t ptrsize; + + if (ret <= 0 || size == 0) + return ret; + ptrsize = ret; + ptr = ptr1 = list; + while (ptrsize > 0) { + len = strlen(ptr1) +1; + ptrsize -= len; + if (strncmp(ptr1, "user.",5)) { + ptr1 += len; + continue; + } + memmove(ptr, ptr1 +5, len -5); + ptr += len -5; + ptr1 += len; + } + return ptr -list; +} +#endif + +ssize_t sys_listxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_LISTXATTR) + ssize_t ret; + +#ifndef XATTR_ADD_OPT + ret = listxattr(path, list, size); +#else + int options = 0; + ret = listxattr(path, list, size, options); +#endif + return remove_user(ret, list, size); + +#elif defined(HAVE_LISTEA) + return listea(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_FILE) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(0, arg, list, size); +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) + return irix_attr_list(path, 0, list, size, 0); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +ssize_t sys_llistxattr (const char *path, char *list, size_t size) +{ +#if defined(HAVE_LLISTXATTR) + ssize_t ret; + + ret = llistxattr(path, list, size); + return remove_user(ret, list, size); +#elif defined(HAVE_LISTXATTR) && defined(XATTR_ADD_OPT) + ssize_t ret; + int options = XATTR_NOFOLLOW; + + ret = listxattr(path, list, size, options); + return remove_user(ret, list, size); + +#elif defined(HAVE_LLISTEA) + return llistea(path, list, size); +#elif defined(HAVE_EXTATTR_LIST_LINK) + extattr_arg arg; + arg.path = path; + return bsd_attr_list(1, arg, list, size); +#elif defined(HAVE_ATTR_LIST) && defined(HAVE_SYS_ATTRIBUTES_H) + return irix_attr_list(path, 0, list, size, ATTR_DONTFOLLOW); +#elif defined(HAVE_ATTROPEN) + ssize_t ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + if (attrdirfd >= 0) { + ret = solaris_list_xattr(attrdirfd, list, size); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_removexattr (const char *path, const char *uname) +{ + const char *name = prefix(uname); +#if defined(HAVE_REMOVEXATTR) +#ifndef XATTR_ADD_OPT + return removexattr(path, name); +#else + int options = 0; + return removexattr(path, name, options); +#endif +#elif defined(HAVE_REMOVEEA) + return removeea(path, name); +#elif defined(HAVE_EXTATTR_DELETE_FILE) + return extattr_delete_file(path, EXTATTR_NAMESPACE_USER, uname); +#elif defined(HAVE_ATTR_REMOVE) + int flags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lremovexattr (const char *path, const char *uname) +{ + const char *name = prefix(uname); +#if defined(HAVE_LREMOVEXATTR) + return lremovexattr(path, name); +#elif defined(HAVE_REMOVEXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return removexattr(path, name, options); +#elif defined(HAVE_LREMOVEEA) + return lremoveea(path, name); +#elif defined(HAVE_EXTATTR_DELETE_LINK) + return extattr_delete_link(path, EXTATTR_NAMESPACE_USER, uname); +#elif defined(HAVE_ATTR_REMOVE) + int flags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) flags |= ATTR_ROOT; + + return attr_remove(path, attrname, flags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int attrdirfd = solaris_attropen(path, ".", O_RDONLY|AT_SYMLINK_NOFOLLOW, 0); + if (attrdirfd >= 0) { + ret = solaris_unlinkat(attrdirfd, name); + close(attrdirfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_setxattr (const char *path, const char *uname, const void *value, size_t size, int flags) +{ + const char *name = prefix(uname); +#if defined(HAVE_SETXATTR) +#ifndef XATTR_ADD_OPT + return setxattr(path, name, value, size, flags); +#else + int options = 0; + return setxattr(path, name, value, size, 0, options); +#endif +#elif defined(HAVE_SETEA) + return setea(path, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_FILE) + int retval = 0; + if (flags) { + /* Check attribute existence */ + retval = extattr_get_file(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_file(path, EXTATTR_NAMESPACE_USER, uname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SET) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_fsetxattr (int filedes, const char *uname, const void *value, size_t size, int flags) +{ + const char *name = prefix(uname); + +#if defined(HAVE_FSETXATTR) +#ifndef XATTR_ADD_OPT + return fsetxattr(filedes, name, value, size, flags); +#else + int options = 0; + return fsetxattr(filedes, name, value, size, 0, options); +#endif +#elif defined(HAVE_FSETEA) + return fsetea(filedes, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_FD) + char *s; + int retval = 0; + int attrnamespace = (strncmp(name, "system", 6) == 0) ? + EXTATTR_NAMESPACE_SYSTEM : EXTATTR_NAMESPACE_USER; + const char *attrname = ((s=strchr_m(name, '.')) == NULL) ? name : s + 1; + if (flags) { + /* Check attribute existence */ + retval = extattr_get_fd(filedes, attrnamespace, attrname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + log_error, logtype_default /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + retval = extattr_set_fd(filedes, attrnamespace, attrname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SETF) + int myflags = 0; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_setf(filedes, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | O_XATTR; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_openat(filedes, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +int sys_lsetxattr (const char *path, const char *uname, const void *value, size_t size, int flags) +{ + const char *name = prefix(uname); +#if defined(HAVE_LSETXATTR) + return lsetxattr(path, name, value, size, flags); +#elif defined(HAVE_SETXATTR) && defined(XATTR_ADD_OPT) + int options = XATTR_NOFOLLOW; + return setxattr(path, name, value, size, 0, options); +#elif defined(LSETEA) + return lsetea(path, name, value, size, flags); +#elif defined(HAVE_EXTATTR_SET_LINK) + int retval = 0; + if (flags) { + /* Check attribute existence */ + retval = extattr_get_link(path, EXTATTR_NAMESPACE_USER, uname, NULL, 0); + if (retval < 0) { + /* REPLACE attribute, that doesn't exist */ + if (flags & XATTR_REPLACE && errno == ENOATTR) { + errno = ENOATTR; + return -1; + } + /* Ignore other errors */ + } + else { + /* CREATE attribute, that already exists */ + if (flags & XATTR_CREATE) { + errno = EEXIST; + return -1; + } + } + } + + retval = extattr_set_link(path, EXTATTR_NAMESPACE_USER, uname, value, size); + return (retval < 0) ? -1 : 0; +#elif defined(HAVE_ATTR_SET) + int myflags = ATTR_DONTFOLLOW; + char *attrname = strchr(name,'.') + 1; + + if (strncmp(name, "system", 6) == 0) myflags |= ATTR_ROOT; + if (flags & XATTR_CREATE) myflags |= ATTR_CREATE; + if (flags & XATTR_REPLACE) myflags |= ATTR_REPLACE; + + return attr_set(path, attrname, (const char *)value, size, myflags); +#elif defined(HAVE_ATTROPEN) + int ret = -1; + int myflags = O_RDWR | AT_SYMLINK_NOFOLLOW; + int attrfd; + if (flags & XATTR_CREATE) myflags |= O_EXCL; + if (!(flags & XATTR_REPLACE)) myflags |= O_CREAT; + attrfd = solaris_attropen(path, name, myflags, (mode_t) SOLARIS_ATTRMODE); + if (attrfd >= 0) { + ret = solaris_write_xattr(attrfd, value, size); + close(attrfd); + } + return ret; +#else + errno = ENOSYS; + return -1; +#endif +} + +/************************************************************************** + helper functions for Solaris' EA support +****************************************************************************/ +#ifdef HAVE_ATTROPEN +static ssize_t solaris_read_xattr(int attrfd, void *value, size_t size) +{ + struct stat sbuf; + + if (fstat(attrfd, &sbuf) == -1) { + return -1; + } + + /* This is to return the current size of the named extended attribute */ + if (size == 0) { + return sbuf.st_size; + } + + /* check size and read xattr */ + if (sbuf.st_size > size) { + return -1; + } + + return read(attrfd, value, sbuf.st_size); +} + +static ssize_t solaris_list_xattr(int attrdirfd, char *list, size_t size) +{ + ssize_t len = 0; + DIR *dirp; + struct dirent *de; + int newfd = dup(attrdirfd); + /* CAUTION: The originating file descriptor should not be + used again following the call to fdopendir(). + For that reason we dup() the file descriptor + here to make things more clear. */ + dirp = fdopendir(newfd); + + while ((de = readdir(dirp))) { + size_t listlen; + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..") || + !strcmp(de->d_name, "SUNWattr_ro") || !strcmp(de->d_name, "SUNWattr_rw")) + { + /* we don't want "." and ".." here: */ + LOG(log_maxdebug, logtype_default, "skipped EA %s\n",de->d_name); + continue; + } + + listlen = strlen(de->d_name); + if (size == 0) { + /* return the current size of the list of extended attribute names*/ + len += listlen + 1; + } else { + /* check size and copy entry + nul into list. */ + if ((len + listlen + 1) > size) { + errno = ERANGE; + len = -1; + break; + } else { + strcpy(list + len, de->d_name); + len += listlen; + list[len] = '\0'; + ++len; + } + } + } + + if (closedir(dirp) == -1) { - LOG(log_debug, logtype_default, "closedir dirp failed: %s\n",strerror(errno)); ++ LOG(log_error, logtype_default, "closedir dirp: %s",strerror(errno)); + return -1; + } + return len; +} + +static int solaris_unlinkat(int attrdirfd, const char *name) +{ + if (unlinkat(attrdirfd, name, 0) == -1) { + return -1; + } + return 0; +} + +static int solaris_attropen(const char *path, const char *attrpath, int oflag, mode_t mode) +{ + int filedes = attropen(path, attrpath, oflag, mode); + if (filedes == -1) { - LOG(log_maxdebug, logtype_default, "attropen FAILED: path: %s, name: %s, errno: %s", - path, attrpath, strerror(errno)); ++ if (errno != ENOENT) ++ LOG(log_error, logtype_default, "attropen(\"%s\", ea:'%s'): %s", ++ path, attrpath, strerror(errno)); + errno = ENOATTR; + } + return filedes; +} + +static int solaris_openat(int fildes, const char *path, int oflag, mode_t mode) +{ + int filedes = openat(fildes, path, oflag, mode); + if (filedes == -1) { - LOG(log_maxdebug, logtype_default, "openat FAILED: fd: %d, path: %s, errno: %s", - filedes, path, strerror(errno)); ++ LOG(log_error, logtype_default, "openat(\"%s\"): %s", ++ path, strerror(errno)); + } + return filedes; +} + +static int solaris_write_xattr(int attrfd, const char *value, size_t size) +{ + if ((ftruncate(attrfd, 0) == 0) && (write(attrfd, value, size) == size)) { + return 0; + } else { - LOG(log_maxdebug, logtype_default, "solaris_write_xattr FAILED!"); ++ LOG(log_error, logtype_default, "solaris_write_xattr: %s", ++ strerror(errno)); + return -1; + } +} + +#endif /*HAVE_ATTROPEN*/ + diff --combined libatalk/vfs/unix.c index 83c60169,229f1b7a..5e0588df --- a/libatalk/vfs/unix.c +++ b/libatalk/vfs/unix.c @@@ -22,7 -22,6 +22,7 @@@ #include #include #include +#include /* ----------------------------- a dropbox is a folder where w is set but not r eg: @@@ -33,6 -32,29 +33,6 @@@ int stickydirmode(const char *name, con { int retval = 0; -#ifdef DROPKLUDGE - /* Turn on the sticky bit if this is a drop box, also turn off the setgid bit */ - if ((dropbox & AFPVOL_DROPBOX)) { - int uid; - - if ( ( (mode & S_IWOTH) && !(mode & S_IROTH)) || - ( (mode & S_IWGRP) && !(mode & S_IRGRP)) ) - { - uid=geteuid(); - if ( seteuid(0) < 0) { - LOG(log_error, logtype_afpd, "stickydirmode: unable to seteuid root: %s", strerror(errno)); - } - if ( (retval=chmod( name, ( (DIRBITS | mode | S_ISVTX) & ~v_umask) )) < 0) { - LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) ); - } else { - LOG(log_debug, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(retval) ); - } - seteuid(uid); - return retval; - } - } -#endif /* DROPKLUDGE */ - /* * Ignore EPERM errors: We may be dealing with a directory that is * group writable, in which case chmod will fail. @@@ -79,15 -101,15 +79,15 @@@ int setfilmode(const char * name, mode_ /* * @brief system rmdir with afp error code. * - * Supports *at semantics (cf openat) if HAVE_RENAMEAT. Pass dirfd=-1 to ignore this. + * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this. */ int netatalk_rmdir_all_errors(int dirfd, const char *name) { int err; - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if (dirfd == -1) - dirfd = ATFD_CWD; + dirfd = AT_FDCWD; err = unlinkat(dirfd, name, AT_REMOVEDIR); #else err = rmdir(name); @@@ -114,7 -136,7 +114,7 @@@ /* * @brief System rmdir with afp error code, but ENOENT is not an error. * - * Supports *at semantics (cf openat) if HAVE_RENAMEAT. Pass dirfd=-1 to ignore this. + * Supports *at semantics (cf openat) if HAVE_ATFUNCS. Pass dirfd=-1 to ignore this. */ int netatalk_rmdir(int dirfd, const char *name) { @@@ -166,7 -188,7 +166,7 @@@ char *fullpathname(const char *name **************************************************************************/ /* - * Supports *at semantics if HAVE_RENAMEAT, pass dirfd=-1 to ignore this + * Supports *at semantics if HAVE_ATFUNCS, pass dirfd=-1 to ignore this */ int copy_file(int dirfd, const char *src, const char *dst, mode_t mode) { @@@ -177,9 -199,9 +177,9 @@@ size_t buflen; char filebuf[8192]; - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if (dirfd == -1) - dirfd = ATFD_CWD; + dirfd = AT_FDCWD; sfd = openat(dirfd, src, O_RDONLY); #else sfd = open(src, O_RDONLY); @@@ -245,7 -267,7 +245,7 @@@ exit */ int netatalk_unlinkat(int dirfd, const char *name) { - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if (dirfd == -1) dirfd = AT_FDCWD; @@@ -274,17 -296,17 +274,17 @@@ /* * @brief This is equivalent of unix rename() * - * unix_rename mulitplexes rename and renameat. If we dont HAVE_RENAMEAT, sfd and dfd + * unix_rename mulitplexes rename and renameat. If we dont HAVE_ATFUNCS, sfd and dfd * are ignored. * - * @param sfd (r) if we HAVE_RENAMEAT, -1 gives AT_FDCWD + * @param sfd (r) if we HAVE_ATFUNCS, -1 gives AT_FDCWD * @param oldpath (r) guess what * @param dfd (r) same as sfd * @param newpath (r) guess what */ int unix_rename(int sfd, const char *oldpath, int dfd, const char *newpath) { - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if (sfd == -1) sfd = AT_FDCWD; if (dfd == -1) @@@ -295,7 -317,7 +295,7 @@@ #else if (rename(oldpath, newpath) < 0) return -1; - #endif /* HAVE_RENAMEAT */ + #endif /* HAVE_ATFUNCS */ return 0; } @@@ -303,15 -325,15 +303,15 @@@ /* * @brief stat/fsstatat multiplexer * - * statat mulitplexes stat and fstatat. If we dont HAVE_RENAMEAT, dirfd is ignored. + * statat mulitplexes stat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored. * - * @param dirfd (r) Only used if HAVE_RENAMEAT, ignored else, -1 gives AT_FDCWD + * @param dirfd (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD * @param path (r) pathname * @param st (rw) pointer to struct stat */ int statat(int dirfd, const char *path, struct stat *st) { - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if (dirfd == -1) dirfd = AT_FDCWD; return (fstatat(dirfd, path, st, 0)); @@@ -326,15 -348,15 +326,15 @@@ /* * @brief lstat/fsstatat multiplexer * - * lstatat mulitplexes lstat and fstatat. If we dont HAVE_RENAMEAT, dirfd is ignored. + * lstatat mulitplexes lstat and fstatat. If we dont HAVE_ATFUNCS, dirfd is ignored. * - * @param dirfd (r) Only used if HAVE_RENAMEAT, ignored else, -1 gives AT_FDCWD + * @param dirfd (r) Only used if HAVE_ATFUNCS, ignored else, -1 gives AT_FDCWD * @param path (r) pathname * @param st (rw) pointer to struct stat */ int lstatat(int dirfd, const char *path, struct stat *st) { - #ifdef HAVE_RENAMEAT + #ifdef HAVE_ATFUNCS if (dirfd == -1) dirfd = AT_FDCWD; return (fstatat(dirfd, path, st, AT_SYMLINK_NOFOLLOW)); diff --combined macros/db3-check.m4 index 6fae6187,2cc59cbb..902220be --- a/macros/db3-check.m4 +++ b/macros/db3-check.m4 @@@ -1,3 -1,4 +1,3 @@@ -dnl $Id: db3-check.m4,v 1.23 2010-04-12 14:28:48 franklahm Exp $ dnl Autoconf macros to check for the Berkeley DB library dnl -- check header for minimum version and return version in @@@ -82,12 -83,11 +82,12 @@@ AC_DEFUN([NETATALK_BDB_TRY_LINK], ]) dnl -- This is called from configure -AC_DEFUN([AC_PATH_BDB],[ +AC_DEFUN([AC_NETATALK_PATH_BDB],[ +if test "x$bdb_required" = "xyes"; then trybdbdir="" dobdbsearch=yes bdb_search_dirs="/usr/local /usr" - search_subdirs="/ /db5 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4" + search_subdirs="/ /db5 /db5.1 /db51 /db5.0 /db50 /db4.8 /db48 /db4.7 /db47 /db4.6 /db46 /db4" bdbfound=no savedcflags="$CFLAGS" @@@ -206,7 -206,6 +206,7 @@@ ifelse([$1], , :, [$1]) else ifelse([$2], , :, [$2]) + AC_MSG_ERROR([Berkeley DB library required but not found!]) fi CFLAGS_REMOVE_USR_INCLUDE(BDB_CFLAGS) @@@ -215,7 -214,6 +215,7 @@@ AC_SUBST(BDB_LIBS) AC_SUBST(BDB_BIN) AC_SUBST(BDB_PATH) +fi ]) diff --combined man/man1/Makefile.am index ef56aadb,0154fc32..52564afb --- a/man/man1/Makefile.am +++ b/man/man1/Makefile.am @@@ -12,14 -12,33 +12,14 @@@ SUFFIXES= .tmpl -e s@:DEFAULT_CNID_SCHEME:@${DEFAULT_CNID_SCHEME}@ \ <$< >$@ - GENERATED_MANS = uniconv.1 asip-status.pl.1 - TEMPLATE_FILES = uniconv.1.tmpl asip-status.pl.1.tmpl + GENERATED_MANS = uniconv.1 asip-status.pl.1 afpldaptest.1 + TEMPLATE_FILES = uniconv.1.tmpl asip-status.pl.1.tmpl afpldaptest.1.tmpl + NONGENERATED_MANS = ad.1 \ afppasswd.1 \ apple_dump.1 \ dbd.1 \ - hqx2bin.1 \ - macbinary.1 \ - megatron.1 \ - netatalk-config.1 \ - single2bin.1 \ - unbin.1 \ - unhex.1 \ - unsingle.1 -ATALK_MANS = aecho.1 \ - getzones.1 \ - nbp.1 \ - nbplkup.1 \ - nbprgstr.1 \ - nbpunrgstr.1 \ - pap.1 \ - papstatus.1 \ - psorder.1 - -if USE_APPLETALK -NONGENERATED_MANS += $(ATALK_MANS) -endif + netatalk-config.1 man_MANS = $(GENERATED_MANS) $(NONGENERATED_MANS) CLEANFILES = $(GENERATED_MANS) diff --combined man/man5/Makefile.am index 84dd7b9c,a382039e..2f7ec5b6 --- a/man/man5/Makefile.am +++ b/man/man5/Makefile.am @@@ -17,18 -17,27 +17,20 @@@ GENERATED_MANS = AppleVolumes.default. afpd.conf.5 \ netatalk.conf.5 \ afp_ldap.conf.5 \ - afp_signature.conf.5 + afp_signature.conf.5 \ + afp_voluuid.conf.5 TEMPLATE_FILES = AppleVolumes.default.5.tmpl \ afpd.conf.5.tmpl \ netatalk.conf.5.tmpl \ afp_ldap.conf.5.tmpl \ - afp_signature.conf.5.tmpl + afp_signature.conf.5.tmpl \ + afp_voluuid.conf.5.tmpl -ATALK_MANS = atalkd.conf.5.tmpl papd.conf.5.tmpl - -if USE_APPLETALK -GENERATED_MANS += atalkd.conf.5 papd.conf.5 -TEMPLATE_FILES += $(ATALK_MANS) -endif - NONGENERATED_MANS = AppleVolumes.5 AppleVolumes.system.5 man_MANS = $(GENERATED_MANS) $(NONGENERATED_MANS) CLEANFILES = $(GENERATED_MANS) -EXTRA_DIST = $(TEMPLATE_FILES) $(NONGENERATED_MANS) $(ATALK_MANS) +EXTRA_DIST = $(TEMPLATE_FILES) $(NONGENERATED_MANS)