/*
- Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+ Copyright (c) 2009,2011 Frank Lahm <franklahm@gmail.com>
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
#ifndef AD_H
#define AD_H
- #if !defined(__FreeBSD__)
- # define _XOPEN_SOURCE 600
- #endif
+ #include <atalk/standards.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <signal.h>
+#include <arpa/inet.h>
#include <atalk/ftw.h>
#include <atalk/volinfo.h>
#include <atalk/cnid.h>
+#include <atalk/compat.h>
#define DIR_DOT_OR_DOTDOT(a) \
((strcmp(a, ".") == 0) || (strcmp(a, "..") == 0))
/*
- * $Id: afppasswd.c,v 1.19 2005-04-28 20:49:19 bfernhomberg Exp $
- *
* Copyright 1999 (c) Adrian Sun (asun@u.washington.edu)
* All Rights Reserved. See COPYRIGHT.
*
#include <stdlib.h>
#include <string.h>
#include <errno.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
#include <pwd.h>
-
-#include <netatalk/endian.h>
+#include <arpa/inet.h>
#include <des.h>
#define unhex(x) (isdigit(x) ? (x) - '0' : toupper(x) + 10 - 'A')
static void convert_passwd(char *buf, char *newpwd, const int keyfd)
{
- u_int8_t key[HEXPASSWDLEN];
+ uint8_t key[HEXPASSWDLEN];
Key_schedule schedule;
unsigned int i, j;
flags = ((uid = getuid()) == 0) ? OPT_ISROOT : 0;
if (((flags & OPT_ISROOT) == 0) && (argc > 1)) {
+ fprintf(stderr, "afppasswd (Netatalk %s)\n", VERSION);
fprintf(stderr, "Usage: afppasswd [-acfn] [-u minuid] [-p path] [username]\n");
fprintf(stderr, " -a add a new user\n");
fprintf(stderr, " -c create and initialize password file or specific user\n");
- /*
- * $Id: megatron.c,v 1.14 2010-01-27 21:27:53 didg Exp $
- */
-
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif /* HAVE_CONFIG_H */
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/uio.h>
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif /* HAVE_FCNTL_H */
#include <time.h>
#include <ctype.h>
#include <stdio.h>
*newname = '\0';
for ( c = 1 ; c < argc ; ++c ) {
+ if ( strcmp( argv [ c ], "--version" ) == 0 ) {
+ printf("%s (Netatalk %s megatron)\n", argv[0], VERSION);
+ return( -1 );
+ }
+ if ( strcmp( argv [ c ], "-v" ) == 0 ) {
+ printf("%s (Netatalk %s megatron)\n", argv[0], VERSION);
+ return( -1 );
+ }
if ( strcmp( argv [ c ], "--header" ) == 0 ) {
flags |= OPTION_HEADERONLY;
continue;
}
return( rv );
}
-
--- /dev/null
-
+ dnl configure.in for netatalk
+
+ AC_INIT(etc/afpd/main.c)
+
+ NETATALK_VERSION=`cat $srcdir/VERSION`
+ AC_SUBST(NETATALK_VERSION)
+
+ AC_CANONICAL_SYSTEM
+ AM_INIT_AUTOMAKE(netatalk, ${NETATALK_VERSION})
+ AM_CONFIG_HEADER(config.h)
+ AM_MAINTAINER_MODE([enable])
+
+ dnl Checks for programs.
+ AC_PROG_AWK
+ AC_PROG_CC
+ AC_PROG_CC_C99
+ AC_PROG_INSTALL
+ AC_PROG_LN_S
+ AC_PROG_MAKE_SET
+ AC_LIBTOOL_DLOPEN
+ AC_PROG_LIBTOOL
+ AC_PROG_PERL
+ AC_PROG_GREP
+ AC_PROG_PS
-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"
-)
+ AM_PROG_CC_C_O
+
-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
++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 <sys/param.h>
+ #endif
+ ])
+
-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)
++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
+ dnl --------------------------------------------------------------------------
+ AC_LTDL_DLLIB
+ AC_CHECK_FUNCS(dlopen dlsym dlclose)
+ AC_LTDL_DLSYM_USCORE
+ if test x"$libltdl_cv_need_uscore" = xyes; then
+ AC_DEFINE(DLSYM_PREPEND_UNDERSCORE, 1, [BSD compatibility macro])
+ fi
+
-
++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_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])])
+ AC_CHECK_MEMBERS(struct tm.tm_gmtoff,,, [#include <time.h>])
+
-AC_CACHE_SAVE
++dnl these tests have been comfirmed to be needed in 2011
++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)
-dnl Checks for (v)snprintf
-NETATALK_SNPRINTF_CHECK
+
-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])
- ]
-)
++AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW)
++
++AC_CACHE_SAVE
+
+ dnl --------------------------------------------------------------------------
+ dnl 64bit platform check
+ dnl --------------------------------------------------------------------------
+
+ AC_MSG_CHECKING([whether to check for 64bit libraries])
+ # Test if the compiler is in 64bit mode
+ echo 'int i;' > conftest.$ac_ext
+ atalk_cv_cc_64bit_output=no
+ if AC_TRY_EVAL(ac_compile); then
+ case `/usr/bin/file conftest.$ac_objext` in
+ *"ELF 64"*)
+ atalk_cv_cc_64bit_output=yes
+ ;;
+ esac
+ fi
+ rm -rf conftest*
+
+ case $host_cpu:$atalk_cv_cc_64bit_output in
+ powerpc64:yes | s390x:yes | sparc*:yes | x86_64:yes | i386:yes)
+ case $target_os in
+ solaris2*)
+ AC_MSG_RESULT([yes])
+ atalk_libname="lib/64"
+ ;;
+ *bsd* | dragonfly*)
+ AC_MSG_RESULT([no])
+ atalk_libname="lib"
+ ;;
+ *)
+ AC_MSG_RESULT([yes])
+ atalk_libname="lib64"
+ ;;
+ esac
+ ;;
+ *:*)
+ AC_MSG_RESULT([no])
+ atalk_libname="lib"
+ ;;
+ esac
+
+ dnl --------------------------------------------------------------------------
+ dnl specific configuration comes in here:
+ dnl --------------------------------------------------------------------------
+
++dnl Check for optional admin group support
++AC_NETATALK_ADMIN_GROUP
+
-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 Check for optional AFS support
++AC_NETATALK_AFS_CHECK
+
-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])
- ]
-)
++dnl --with-pkgconfdir check to change configuration directory location
++AC_NETATALK_CONFIG_DIRS
+
-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])
- ]
-)
-
-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 whethe to disable tickle SIGALARM stuff, which eases debugging
++AC_NETATALK_DEBUGGING
+
-bdb_required=no
++dnl Check for libiconv support
++AC_NETATALK_CHECK_ICONV
+
+ dnl Check for CNID database backends
-AC_CHECK_QUOTA
+ AC_NETATALK_CNID([bdb_required=yes],[bdb_required=no])
+
+ dnl Check for quota support
-NETATALK_SRVLOC
++AC_NETATALK_CHECK_QUOTA
+
+ dnl Check for optional server location protocol support (used by MacOS X)
-NETATALK_ZEROCONF
++AC_NETATALK_SRVLOC
+
+ dnl Check for optional Zeroconf support
-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])
-])
++AC_NETATALK_ZEROCONF
++
++dnl Check for optional TCP-wrappers support
++AC_NETATALK_TCP_WRAPPERS
+
+ dnl Check for PAM libs
-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]
-)
++AC_NETATALK_PATH_PAM
+
-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 optional shadow password support
++AC_NETATALK_SHADOW
++
++dnl Check for optional valid-shell-check support
++AC_NETATALK_SHELL_CHECK
+
-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
-
-
-
-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 Webmin
++AC_NETATALK_WEBMIN
+
-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 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 obsoleted ],[
- echo "ERROR: --enable-redhat is obsoleted. Use --enable-redhat-sysv or --enable-redhat-systemd."
- echo "exit 1"
- exit 1
- ]
-)
++dnl Check for libgcrypt, if found enables DHX2 UAM
++AC_NETATALK_PATH_LIBGCRYPT([1:1.2.3])
+
-AC_ARG_ENABLE(redhat-sysv,
- [ --enable-redhat-sysv use redhat-style sysv (upstart) configuration ],[
- if test "$enableval" = "yes"; then
- sysv_style=redhat-sysv
- fi
- AC_MSG_RESULT([enabling redhat-style sysv support])
- ]
-)
++dnl Check for openssl, if found enables DHX UAM and Randnum UAM
++AC_NETATALK_PATH_SSL
+
-AC_ARG_ENABLE(redhat-systemd,
- [ --enable-redhat-systemd use redhat-style systemd (>=Fedora15) configuration ],[
- if test "$enableval" = "yes"; then
- sysv_style=redhat-systemd
- fi
- AC_MSG_RESULT([enabling redhat-style systemd support])
- ]
-)
++dnl Check for Berkeley DB library
++AC_NETATALK_PATH_BDB
+
-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 crypt
++AC_NETATALK_CRYPT
+
-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 building PGP UAM module
++AC_NETATALK_PGP_UAM
+
-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 Kerberos V UAM module
++AC_NETATALK_KRB5_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 overwrite the config files or not
++AC_NETATALK_OVERWRITE_CONFIG
+
-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 LDAP support, for client-side ACL visibility
++AC_NETATALK_LDAP
+
-AC_ARG_WITH(uams-path,
- [ --with-uams-path=PATH path to UAMs [[PKGCONF/uams]]],[
- uams_path="$withval"
- ],[
- uams_path="${PKGCONFDIR}/uams"
- ]
-)
++dnl Check for ACL support
++AC_NETATALK_ACL
+
-NETATALK_AC_CUPS
++dnl Check for Extended Attributes support
++AC_NETATALK_EXTENDED_ATTRIBUTES
+
-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 libsmbsharemodes from Samba for Samba/Netatalk access/deny/share modes interop
++AC_NETATALK_SMB_SHAREMODES
+
-dnl ***** UAMS_PATH
-dnl AC_DEFINE_UNQUOTED(UAMS_PATH, "${uams_path}",
-dnl [path to UAMs [default=PKGCONF/uams]])
++dnl Check if realpath() takes NULL
++AC_NETATALK_REALPATH
++
++dnl Check for sendfile()
++AC_NETATALK_SENDFILE
+
+ dnl --------------------------------------------------------------------------
+ dnl FHS stuff has to be done last because it overrides other defaults
+ dnl --------------------------------------------------------------------------
+
+ AC_MSG_CHECKING([whether to use Filesystem Hierarchy Standard (FHS) compatibility])
+ AC_ARG_ENABLE(fhs,
+ [ --enable-fhs use Filesystem Hierarchy Standard (FHS) compatibility],[
+ if test "$enableval" = "yes"; then
+ uams_path="${libdir}/netatalk"
+ sysconfdir="/etc"
+ PKGCONFDIR=${sysconfdir}/netatalk
+ SERVERTEXT="${PKGCONFDIR}/msg"
+ use_pam_so=yes
+ mandir="/usr/share/man"
+ AC_DEFINE(FHS_COMPATIBILITY, 1, [Define if you want compatibily with the FHS])
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ fi
+ ],[
+ AC_MSG_RESULT([no])
+ ]
+ )
+
+ dnl --------------------------------------------------------------------------
+ dnl post-FHS substitutions, etc
+ dnl --------------------------------------------------------------------------
+
-LIBS="$LIBS -L\$(top_srcdir)/libatalk"
-CFLAGS="-I\$(top_srcdir)/include $CFLAGS -I\$(top_srcdir)/sys"
+ 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 --------------------------------------------------------------------------
+
+ 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.
-AC_DEFINE(OPEN_NOFOLLOW_ERRNO, ELOOP, errno returned by open with O_NOFOLLOW)
++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"
+
-dnl specific configuration comes in here:
+
+ 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 ;;
- *kfreebsd*-gnu) this_os=kfreebsd-gnu ;;
- *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])
- ;;
- kfreebsd-gnu) 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(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW)
-fi
-
-dnl ----- GNU/kFreeBSD specific -----
-if test x"$this_os" = "xkfreebsd-gnu"; then
- AC_MSG_RESULT([ * GNU/kFreeBSD specific configuration])
- AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
- AC_DEFINE(FREEBSD, 1, [Define if OS is FreeBSD])
- 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 <sys/socket.h>
-#include <asm/types.h>
-#include <linux/atalk.h>
-
- 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])
-
-
- 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])
- AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
- dnl ----- OpenBSD does not have crypt.h, uses unistd.h -----
- AC_DEFINE(UAM_DHX, 1, [Define if the DHX UAM modules should be compiled])
- AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
-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 <sys/stream.h>
-#include <sys/ddi.h>],
-[\
-timeout_id_t dummy;
-],
-netatalk_cv_HAVE_TIMEOUT_ID_T=yes,netatalk_cv_HAVE_TIMEOUT_ID_T=no,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 sendfile() --------
-netatalk_cv_search_sendfile=yes
-AC_ARG_ENABLE(sendfile,
- [ --disable-sendfile disable sendfile syscall],
- [if test x"$enableval" = x"no"; then
- netatalk_cv_search_sendfile=no
- fi]
-)
-
-if test x"$netatalk_cv_search_sendfile" = x"yes"; then
- case "$host_os" in
- *linux*)
- AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available])
- AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
- ;;
-
- *solaris*)
- AC_DEFINE(SENDFILE_FLAVOR_SOLARIS, 1, [Solaris sendfile()])
- AC_SEARCH_LIBS(sendfile, sendfile)
- AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
- ;;
-
- *freebsd*)
- AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics])
- AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
- ;;
-
- *)
- ;;
-
- esac
-
- if test x"$netatalk_cv_HAVE_SENDFILE" = x"yes"; then
- AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile() should be used])
- fi
-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 <sys/types.h>
- #include <sys/acl.h>
- ],[
- 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 <sys/types.h>
- #include <sys/acl.h>
- ],[
- acl_permset_t permset_d;
- acl_perm_t perm;
- return acl_get_perm_np(permset_d, perm);
- ],
- [netatalk_cv_HAVE_ACL_GET_PERM_NP=yes],
- [netatalk_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
-
- AC_CACHE_CHECK([for acl_from_mode], netatalk_cv_HAVE_ACL_FROM_MODE,[
- acl_LIBS=$LIBS
- LIBS="$LIBS $ACL_LIBS"
- AC_CHECK_FUNCS(acl_from_mode,
- [netatalk_cv_HAVE_ACL_FROM_MODE=yes],
- [netatalk_cv_HAVE_ACL_FROM_MODE=no])
- LIBS=$acl_LIBS
- ])
- if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then
- AC_DEFINE(HAVE_ACL_FROM_MODE,1,[Whether acl_from_mode() 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_CHECK_HEADERS([acl/libacl.h])
- 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 <sys/types.h>
- #if HAVE_ATTR_XATTR_H
- #include <attr/xattr.h>
- #elif HAVE_SYS_XATTR_H
- #include <sys/xattr.h>
- #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 <stdio.h>
- #include <limits.h>
- #include <signal.h>
-
- 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
-
++dnl Last minute substitutions
+ dnl --------------------------------------------------------------------------
+
-AC_SUBST(OVERWRITE_CONFIG)
+ AC_SUBST(LIBS)
+ AC_SUBST(CFLAGS)
-AM_CONDITIONAL(COMPILE_TIMELORD, test x$compile_timelord = xyes)
-AM_CONDITIONAL(COMPILE_A2BOOT, test x$compile_a2boot = xyes)
+
+ AM_CONDITIONAL(SOLARIS_MODULE, test x$solaris_module = xyes)
-AM_CONDITIONAL(USE_KERBEROS, test x$compile_kerberos = 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")
+ AM_CONDITIONAL(HAVE_LDAP, test x"$with_ldap" = x"yes")
+ AM_CONDITIONAL(USE_DHX, test x$neta_cv_compile_dhx = xyes)
+ AM_CONDITIONAL(USE_DHX2, test x$neta_cv_compile_dhx2 = xyes)
+ AM_CONDITIONAL(USE_RANDNUM, test x$neta_cv_have_openssl = xyes)
-AM_CONDITIONAL(USE_APPLETALK, test x$netatalk_cv_ddp_enabled = 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_NETBSD, test x$sysv_style = xnetbsd)
+ AM_CONDITIONAL(USE_REDHAT_SYSV, test x$sysv_style = xredhat-sysv)
+ AM_CONDITIONAL(USE_REDHAT_SYSTEMD, test x$sysv_style = xredhat-systemd)
+ AM_CONDITIONAL(USE_SUSE, test x$sysv_style = xsuse)
+ AM_CONDITIONAL(USE_SHADOWPW, test x$shadowpw = xyes)
+ AM_CONDITIONAL(USE_TRU64, test x$sysv_style = xtru64)
+ AM_CONDITIONAL(USE_SOLARIS, test x$sysv_style = xsolaris)
+ AM_CONDITIONAL(USE_GENTOO, test x$sysv_style = xgentoo)
+ 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)
- bin/adv1tov2/Makefile
- bin/aecho/Makefile
+ AM_CONDITIONAL(HAVE_ATFUNCS, test x"$ac_neta_haveatfuncs" = x"yes")
+
+ dnl --------------------- generate files
+
+ AC_OUTPUT([Makefile
+ bin/Makefile
+ bin/ad/Makefile
- bin/getzones/Makefile
+ bin/afppasswd/Makefile
+ bin/cnid/Makefile
+ bin/cnid/cnid2_create
- bin/misc/Makefile
- bin/nbp/Makefile
- bin/pap/Makefile
- bin/psorder/Makefile
+ bin/megatron/Makefile
- contrib/misc/Makefile
- contrib/printing/Makefile
++ bin/misc/Makefile
+ bin/uniconv/Makefile
+ config/Makefile
+ config/pam/Makefile
+ contrib/Makefile
+ contrib/macusers/Makefile
+ contrib/macusers/macusers
- contrib/timelord/Makefile
- contrib/a2boot/Makefile
+ contrib/shell_utils/Makefile
+ contrib/shell_utils/apple_dump
+ contrib/shell_utils/asip-status.pl
- etc/atalkd/Makefile
+ distrib/Makefile
+ distrib/config/Makefile
+ distrib/config/netatalk-config
+ distrib/initscripts/Makefile
+ distrib/m4/Makefile
+ distrib/systemd/Makefile
+ doc/Makefile
+ etc/Makefile
+ etc/afpd/Makefile
- etc/uams/uams_krb4/Makefile
- etc/papd/Makefile
- etc/psf/Makefile
+ etc/cnid_dbd/Makefile
++ etc/netalockd/Makefile
+ etc/uams/Makefile
- libatalk/asp/Makefile
- libatalk/atp/Makefile
+ include/Makefile
+ include/atalk/Makefile
+ libatalk/Makefile
+ libatalk/acl/Makefile
+ libatalk/adouble/Makefile
- libatalk/nbp/Makefile
- libatalk/netddp/Makefile
- libatalk/util/Makefile
+ libatalk/bstring/Makefile
+ libatalk/cnid/Makefile
+ libatalk/cnid/cdb/Makefile
+ libatalk/cnid/last/Makefile
+ libatalk/cnid/dbd/Makefile
+ libatalk/cnid/tdb/Makefile
+ libatalk/compat/Makefile
+ libatalk/dsi/Makefile
- man/man3/Makefile
- man/man4/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
- 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
+ man/man5/Makefile
+ man/man8/Makefile
+ test/Makefile
+ test/afpd/Makefile
++ test/netalockd/Makefile
+ ],
+ [chmod a+x distrib/config/netatalk-config contrib/shell_utils/apple_*]
+ )
+
+ AC_NETATALK_LIBS_SUMMARY
+ AC_NETATALK_CONFIG_SUMMARY
/*
Copyright (c) 2008, 2009, 2010 Frank Lahm <franklahm@gmail.com>
+ Copyright (c) 2011 Laura Mueller <laura-mueller@uni-duesseldorf.de>
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
#define MAP_MASK 31
#define IS_DIR 32
+ /* bit flags for set_acl() and map_aces_darwin_to_posix() */
+ #define HAS_DEFAULT_ACL 0x01
+ #define HAS_EXT_DEFAULT_ACL 0x02
+
/********************************************************
* Solaris funcs
********************************************************/
uint32_t *result)
{
EC_INIT;
- int havemask = 0;
int entry_id = ACL_FIRST_ENTRY;
- uint32_t rights = 0, maskrights = 0;
+ uint32_t rights = 0; /* rights which do not depend on ACL_MASK */
+ uint32_t acl_rights = 0; /* rights which are subject to limitations imposed by ACL_MASK */
+ uint32_t mask_rights = 0xffffffff;
uid_t *uid = NULL;
gid_t *gid = NULL;
acl_t acl = NULL;
acl_entry_t e;
acl_tag_t tag;
- EC_NULL_LOG(acl = acl_get_file(path, ACL_TYPE_ACCESS));
-
- /* itereate through all ACEs to get the mask */
- while (!havemask && acl_get_entry(acl, entry_id, &e) == 1) {
- entry_id = ACL_NEXT_ENTRY;
- EC_ZERO_LOG(acl_get_tag_type(e, &tag));
- switch (tag) {
- case ACL_MASK:
- maskrights = posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
- LOG(log_maxdebug, logtype_afpd, "maskrights: 0x%08x", maskrights);
- havemask = 1;
- break;
- default:
- continue;
- }
- }
+ EC_NULL_LOGSTR(acl = acl_get_file(path, ACL_TYPE_ACCESS),
+ "acl_get_file(\"%s\"): %s", fullpathname(path), strerror(errno));
- /* itereate through all ACEs */
- entry_id = ACL_FIRST_ENTRY;
+ /* Iterate through all ACEs. If we apply mask_rights later there is no need to iterate twice. */
while (acl_get_entry(acl, entry_id, &e) == 1) {
entry_id = ACL_NEXT_ENTRY;
EC_ZERO_LOG(acl_get_tag_type(e, &tag));
+
switch (tag) {
- case ACL_USER:
- EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e));
- if (*uid == uuid) {
- LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid);
- rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
- }
- acl_free(uid);
- uid = NULL;
- break;
- case ACL_USER_OBJ:
- if (sb->st_uid == uuid) {
- LOG(log_maxdebug, logtype_afpd, "ACL_USER_OBJ: %u", sb->st_uid);
- rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
- }
- break;
- case ACL_GROUP:
- EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e));
- if (gmem(*gid)) {
- LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid);
- rights |= (posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode)) & maskrights);
- }
- acl_free(gid);
- gid = NULL;
- break;
- case ACL_GROUP_OBJ:
- if (!(sb->st_uid == uuid) && gmem(sb->st_gid)) {
- LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
- rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
- }
- break;
- case ACL_OTHER:
- if (!(sb->st_uid == uuid) && !gmem(sb->st_gid)) {
- LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
- rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
- }
- break;
- default:
- continue;
+ case ACL_USER_OBJ:
+ if (sb->st_uid == uuid) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_USER_OBJ: %u", sb->st_uid);
+ rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ break;
+
+ case ACL_USER:
+ EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(e));
+
+ if (*uid == uuid) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid);
+ acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ acl_free(uid);
+ uid = NULL;
+ break;
+
+ case ACL_GROUP_OBJ:
+ if (!(sb->st_uid == uuid) && gmem(sb->st_gid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
+ acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ break;
+
+ case ACL_GROUP:
+ EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(e));
+
+ if (gmem(*gid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid);
+ acl_rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ acl_free(gid);
+ gid = NULL;
+ break;
+
+ case ACL_MASK:
+ mask_rights = posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ LOG(log_maxdebug, logtype_afpd, "maskrights: 0x%08x", mask_rights);
+ break;
+
+ case ACL_OTHER:
+ if (!(sb->st_uid == uuid) && !gmem(sb->st_gid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_OTHER");
+ rights |= posix_permset_to_darwin_rights(e, S_ISDIR(sb->st_mode));
+ }
+ break;
+
+ default:
+ continue;
}
} /* while */
+ /* apply the mask and collect the rights */
+ rights |= (acl_rights & mask_rights);
+
*result |= rights;
EC_CLEANUP:
EC_EXIT;
}
+ /*!
+ * Helper function for posix_acls_to_uaperms() to convert Posix ACL permissions
+ * into access rights needed to fill ua_permissions of a FPUnixPrivs structure.
+ *
+ * @param entry (r) Posix ACL entry
+ *
+ * @returns access rights
+ */
+ static u_char acl_permset_to_uarights(acl_entry_t entry) {
+ acl_permset_t permset;
+ u_char rights = 0;
+
+ if (acl_get_permset(entry, &permset) == -1)
+ return rights;
+
+ #ifdef HAVE_ACL_GET_PERM_NP
+ if (acl_get_perm_np(permset, ACL_READ))
+ #else
+ if (acl_get_perm(permset, ACL_READ))
+ #endif
+ rights |= AR_UREAD;
+
+ #ifdef HAVE_ACL_GET_PERM_NP
+ if (acl_get_perm_np(permset, ACL_WRITE))
+ #else
+ if (acl_get_perm(permset, ACL_WRITE))
+ #endif
+ rights |= AR_UWRITE;
+
+ #ifdef HAVE_ACL_GET_PERM_NP
+ if (acl_get_perm_np(permset, ACL_EXECUTE))
+ #else
+ if (acl_get_perm(permset, ACL_EXECUTE))
+ #endif
+ rights |= AR_USEARCH;
+
+ return rights;
+ }
+
+ /*!
+ * Update FPUnixPrivs for a file-system object on a volume supporting ACLs
+ *
+ * Checks permissions granted by ACLS for a user to one fs-object and
+ * updates user and group permissions in given struct maccess. As OS X
+ * doesn't conform to Posix 1003.1e Draft 17 it expects proper group
+ * permissions in st_mode of struct stat even if the fs-object has an
+ * ACL_MASK entry, st_mode gets modified to properly reflect group
+ * permissions.
+ *
+ * @param path (r) path to filesystem object
+ * @param sb (rw) struct stat of path
+ * @param maccess (rw) struct maccess of path
+ *
+ * @returns 0 or -1 on error
+ */
+ static int posix_acls_to_uaperms(const char *path, struct stat *sb, struct maccess *ma) {
+ EC_INIT;
+
+ int entry_id = ACL_FIRST_ENTRY;
+ acl_entry_t entry;
+ acl_tag_t tag;
+ acl_t acl = NULL;
+ uid_t *uid;
+ gid_t *gid;
+ uid_t whoami = geteuid();
+
+ u_char group_rights = 0x00;
+ u_char acl_rights = 0x00;
+ u_char mask = 0xff;
+
+ EC_NULL_LOG(acl = acl_get_file(path, ACL_TYPE_ACCESS));
+
+ /* iterate through all ACEs */
+ while (acl_get_entry(acl, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ EC_ZERO_LOG(acl_get_tag_type(entry, &tag));
+
+ switch (tag) {
+ case ACL_USER:
+ EC_NULL_LOG(uid = (uid_t *)acl_get_qualifier(entry));
+
+ if (*uid == uuid && !(whoami == sb->st_uid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_USER: %u", *uid);
+ acl_rights |= acl_permset_to_uarights(entry);
+ }
+ acl_free(uid);
+ break;
+
+ case ACL_GROUP_OBJ:
+ group_rights = acl_permset_to_uarights(entry);
+ LOG(log_maxdebug, logtype_afpd, "ACL_GROUP_OBJ: %u", sb->st_gid);
+
+ if (gmem(sb->st_gid) && !(whoami == sb->st_uid))
+ acl_rights |= group_rights;
+ break;
+
+ case ACL_GROUP:
+ EC_NULL_LOG(gid = (gid_t *)acl_get_qualifier(entry));
+
+ if (gmem(*gid) && !(whoami == sb->st_uid)) {
+ LOG(log_maxdebug, logtype_afpd, "ACL_GROUP: %u", *gid);
+ acl_rights |= acl_permset_to_uarights(entry);
+ }
+ acl_free(gid);
+ break;
+
+ case ACL_MASK:
+ mask = acl_permset_to_uarights(entry);
+ LOG(log_maxdebug, logtype_afpd, "ACL_MASK: 0x%02x", mask);
+ break;
+
+ default:
+ break;
+ }
+ }
+ /* apply the mask and adjust user and group permissions */
+ ma->ma_user |= (acl_rights & mask);
+ ma->ma_group = (group_rights & mask);
+
+ /* update st_mode to properly reflect group permissions */
+ sb->st_mode &= ~S_IRWXG;
+
+ if (ma->ma_group & AR_USEARCH)
+ sb->st_mode |= S_IXGRP;
+
+ if (ma->ma_group & AR_UWRITE)
+ sb->st_mode |= S_IWGRP;
+
+ if (ma->ma_group & AR_UREAD)
+ sb->st_mode |= S_IRGRP;
+
+ EC_CLEANUP:
+ if (acl) acl_free(acl);
+
+ EC_EXIT;
+ }
+
/*!
* Add entries of one acl to another acl
*
if (darwin_ace_rights & DARWIN_ACE_READ_DATA)
perm |= ACL_READ;
- if (darwin_ace_rights & (DARWIN_ACE_WRITE_DATA | (DARWIN_ACE_DELETE_CHILD & is_dir)))
+ if (darwin_ace_rights & (DARWIN_ACE_WRITE_DATA | (is_dir ? DARWIN_ACE_DELETE_CHILD : 0)))
perm |= ACL_WRITE;
if (darwin_ace_rights & DARWIN_ACE_EXECUTE)
EC_ZERO_LOG(acl_add_perm(permset, perm));
EC_ZERO_LOG(acl_set_permset(e, permset));
}
-
+
EC_CLEANUP:
if (eid) acl_free(eid);
* - we throw away DARWIN_ACE_FLAGS_LIMIT_INHERIT (can't be mapped), thus the ACL will
* not be limited
*
- * @param darwin_aces (r) pointer to darwin_aces buffer
- * @param def_aclp (rw) directories: pointer to an initialized acl_t with the default acl
- * files: *def_aclp will be NULL
- * @param acc_aclp (rw) pointer to an initialized acl_t with the access acl
- * @param ace_count (r) number of ACEs in darwin_aces buffer
+ * @param darwin_aces (r) pointer to darwin_aces buffer
+ * @param def_aclp (rw) directories: pointer to an initialized acl_t with
+ the default acl files: *def_aclp will be NULL
+ * @param acc_aclp (rw) pointer to an initialized acl_t with the access acl
+ * @param ace_count (r) number of ACEs in darwin_aces buffer
+ * @param default_acl_flags (rw) flags to indicate if the object has a basic default
+ * acl or an extended default acl.
*
- * @returns 0 on success storing the result in aclp, -1 on error.
+ * @returns 0 on success storing the result in aclp, -1 on error. default_acl_flags
+ * is set to HAS_DEFAULT_ACL|HAS_EXT_DEFAULT_ACL in case there is at least one
+ * extended default ace. Otherwise default_acl_flags is left unchanged.
*/
static int map_aces_darwin_to_posix(const darwin_ace_t *darwin_aces,
acl_t *def_aclp,
acl_t *acc_aclp,
- int ace_count)
+ int ace_count,
+ uint32_t *default_acl_flags)
{
EC_INIT;
char *name = NULL;
}
/* add it as default ace */
EC_ZERO_LOG(posix_acl_add_perm(def_aclp, tag, id, perm));
-
+ *default_acl_flags = (HAS_DEFAULT_ACL|HAS_EXT_DEFAULT_ACL);
if (! (darwin_ace_flags & DARWIN_ACE_FLAGS_ONLY_INHERIT))
/* if it not a "inherit only" ace, it must be added as access aces too */
EC_INIT;
int mapped_aces = 0;
int dirflag;
- uint32_t *darwin_ace_count = (u_int32_t *)rbuf;
+ uint32_t *darwin_ace_count = (uint32_t *)rbuf;
#ifdef HAVE_SOLARIS_ACLS
int ace_count = 0;
ace_t *aces = NULL;
uint32_t ace_count)
{
EC_INIT;
- acl_t def_acl = NULL;
- acl_t acc_acl = NULL;
+ struct stat st;
+ acl_t default_acl = NULL;
+ acl_t access_acl = NULL;
+ acl_entry_t entry;
+ acl_tag_t tag;
+ int entry_id = ACL_FIRST_ENTRY;
+ int has_def_acl = 0;
+ /* flags to indicate if the object has a minimal default acl and/or an extended
+ * default acl.
+ */
+ uint32_t default_acl_flags = 0;
LOG(log_maxdebug, logtype_afpd, "set_acl: BEGIN");
- struct stat st;
- EC_ZERO_LOG_ERR(lstat(name, &st), AFPERR_NOOBJ);
+ EC_NULL_LOG_ERR(access_acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC);
+
+ /* Iterate through acl and remove all extended acl entries. */
+ while (acl_get_entry(access_acl, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+ EC_ZERO_LOG(acl_get_tag_type(entry, &tag));
+
+ if ((tag == ACL_USER) || (tag == ACL_GROUP) || (tag == ACL_MASK)) {
+ EC_ZERO_LOG_ERR(acl_delete_entry(access_acl, entry), AFPERR_MISC);
+ }
+ } /* while */
- /* seed default ACL with access ACL */
- if (S_ISDIR(st.st_mode))
- EC_NULL_LOG_ERR(def_acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC);
+ /* In case we are acting on a directory prepare a default acl. For files default_acl will be NULL.
+ * If the directory already has a default acl it will be preserved.
+ */
+ EC_ZERO_LOG_ERR(lstat(name, &st), AFPERR_NOOBJ);
- /* for files def_acl will be NULL */
+ if (S_ISDIR(st.st_mode)) {
+ default_acl = acl_get_file(name, ACL_TYPE_DEFAULT);
- /* create access acl from mode */
- EC_NULL_LOG_ERR(acc_acl = acl_from_mode(st.st_mode), AFPERR_MISC);
+ if (default_acl) {
+ /* If default_acl is not empty then the dir has a default acl. */
+ if (acl_get_entry(default_acl, ACL_FIRST_ENTRY, &entry) == 1)
+ default_acl_flags = HAS_DEFAULT_ACL;
+ acl_free(default_acl);
+ }
+ default_acl = acl_dup(access_acl);
+ }
/* adds the clients aces */
- EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &def_acl, &acc_acl, ace_count), AFPERR_MISC);
+ EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &default_acl, &access_acl, ace_count, &default_acl_flags), AFPERR_MISC);
/* calcuate ACL mask */
- EC_ZERO_LOG_ERR(acl_calc_mask(&acc_acl), AFPERR_MISC);
+ EC_ZERO_LOG_ERR(acl_calc_mask(&access_acl), AFPERR_MISC);
/* is it ok? */
- EC_ZERO_LOG_ERR(acl_valid(acc_acl), AFPERR_MISC);
+ EC_ZERO_LOG_ERR(acl_valid(access_acl), AFPERR_MISC);
/* set it */
- EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, acc_acl), AFPERR_MISC);
- EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_ACCESS, 0, acc_acl), AFPERR_MISC);
-
- if (def_acl) {
- EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, def_acl), AFPERR_MISC);
- EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_DEFAULT, 0, def_acl), AFPERR_MISC);
+ EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, access_acl), AFPERR_MISC);
+ EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_ACCESS, 0, access_acl), AFPERR_MISC);
+
+ if (default_acl) {
+ /* If the dir has an extended default acl it's ACL_MASK must be updated.*/
+ if (default_acl_flags & HAS_EXT_DEFAULT_ACL)
+ EC_ZERO_LOG_ERR(acl_calc_mask(&default_acl), AFPERR_MISC);
+
+ if (default_acl_flags) {
+ EC_ZERO_LOG_ERR(acl_valid(default_acl), AFPERR_MISC);
+ EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, default_acl), AFPERR_MISC);
+ EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_DEFAULT, 0, default_acl), AFPERR_MISC);
+ }
}
EC_CLEANUP:
- acl_free(acc_acl);
- acl_free(def_acl);
+ if (access_acl) acl_free(access_acl);
+ if (default_acl) acl_free(default_acl);
LOG(log_maxdebug, logtype_afpd, "set_acl: END");
EC_EXIT;
LOG(log_maxdebug, logtype_afpd, "check_acl_access(dir: \"%s\", path: \"%s\", curdir: \"%s\", 0x%08x)",
cfrombstr(dir->d_fullpath), path, getcwdpath(), requested_rights);
+ /* This check is not used anymore, as OS X Server seems to be ignoring too */
+ #if 0
/* Get uid or gid from UUID */
EC_ZERO_ERR(getnamefromuuid(uuid, &username, &uuidtype), AFPERR_PARAM);
- EC_ZERO_LOG_ERR(lstat(path, &st), AFPERR_PARAM);
-
switch (uuidtype) {
case UUID_USER:
break;
EC_STATUS(AFPERR_MISC);
goto EC_CLEANUP;
}
+ #endif
+
+ EC_ZERO_LOG_ERR(lstat(path, &st), AFPERR_PARAM);
is_dir = !strcmp(path, ".");
if (allowed_rights & DARWIN_ACE_ADD_SUBDIRECTORY)
allowed_rights |= DARWIN_ACE_DELETE;
- dir->d_rights_cache = allowed_rights;
+ curdir->d_rights_cache = allowed_rights;
}
LOG(log_debug, logtype_afpd, "allowed rights: 0x%08x", allowed_rights);
}
* This is the magic function that makes ACLs usable by calculating
* the access granted by ACEs to the logged in user.
*/
- int acltoownermode(char *path, struct stat *st, struct maccess *ma)
+ int acltoownermode(const struct vol *vol, char *path, struct stat *st, struct maccess *ma)
{
EC_INIT;
uint32_t rights = 0;
if ( ! (AFPobj->options.flags & OPTION_ACL2MACCESS)
- || (current_vol == NULL)
- || ! (current_vol->v_flags & AFPVOL_ACLS))
+ || ! (vol->v_flags & AFPVOL_ACLS))
return 0;
LOG(log_maxdebug, logtype_afpd, "acltoownermode(\"%s/%s\", 0x%02x)",
#ifdef HAVE_SOLARIS_ACLS
EC_ZERO_LOG(solaris_acl_rights(path, st, &rights));
- #endif
- #ifdef HAVE_POSIX_ACLS
- EC_ZERO_LOG(posix_acl_rights(path, st, &rights));
- #endif
LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", rights);
ma->ma_user |= AR_UWRITE;
if (rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH))
ma->ma_user |= AR_USEARCH;
+ #endif
+
+ #ifdef HAVE_POSIX_ACLS
+ EC_ZERO_LOG(posix_acls_to_uaperms(path, st, ma));
+ #endif
- LOG(log_maxdebug, logtype_afpd, "resulting user maccess: 0x%02x", ma->ma_user);
+ LOG(log_maxdebug, logtype_afpd, "resulting user maccess: 0x%02x group maccess: 0x%02x", ma->ma_user, ma->ma_group);
EC_CLEANUP:
EC_EXIT;
#include <atalk/dsi.h>
#include <atalk/compat.h>
#include <atalk/util.h>
+#include <atalk/locking.h>
#include <atalk/uuid.h>
#include <atalk/paths.h>
#include <atalk/server_ipc.h>
#include <atalk/fce_api.h>
-
#include <atalk/globals.h>
+
#include "switch.h"
#include "auth.h"
#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
{
DSI *dsi = (DSI *) obj->handle;
int rc_idx;
- u_int32_t err, cmd;
- u_int8_t function;
+ uint32_t err, cmd;
+ uint8_t function;
struct sigaction action;
AFPobj = obj;
continue;
/* Blocking read on the network socket */
- cmd = dsi_receive(dsi);
+ cmd = dsi_stream_receive(dsi);
if (cmd == 0) {
/* cmd == 0 is the error condition */
/* AFP replay cache */
rc_idx = dsi->clientID % REPLAYCACHE_SIZE;
- LOG(log_debug, logtype_afpd, "DSI request ID: %u", dsi->clientID);
+ LOG(log_debug, logtype_dsi, "DSI request ID: %u", dsi->clientID);
if (replaycache[rc_idx].DSIreqID == dsi->clientID
&& replaycache[rc_idx].AFPcommand == function) {
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 */
if (dsi->flags & DSI_NOREPLY) {
dsi->flags &= ~DSI_NOREPLY;
break;
- }
-
- if (!dsi_cmdreply(dsi, err)) {
+ } else if (!dsi_cmdreply(dsi, err)) {
LOG(log_error, logtype_afpd, "dsi_cmdreply(%d): %s", dsi->socket, strerror(errno) );
if (dsi_disconnect(dsi) != 0)
afp_dsi_die(EXITERR_CLNT);
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;
free(opt->logconfig);
if (opt->mimicmodel && (opt->mimicmodel != save->mimicmodel))
free(opt->mimicmodel);
+ if (opt->adminauthuser && (opt->adminauthuser != save->adminauthuser))
+ free(opt->adminauthuser);
}
/* initialize options */
options->dsireadbuf = 12;
options->mimicmodel = NULL;
options->fce_fmodwait = 60; /* put fmod events 60 seconds on hold */
+ options->adminauthuser = NULL;
}
/* parse an afpd.conf line. i'm doing it this way because it's
if ((c = getoption(buf, "-port")))
options->port = strdup(c);
-#ifndef NO_DDP
- if ((c = getoption(buf, "-ddpaddr")))
- atalk_aton(c, &options->ddpaddr);
-#endif
if ((c = getoption(buf, "-signature")) && (opt = strdup(c)))
options->signatureopt = opt;
if ((c = getoption(buf, "-mimicmodel")) && (opt = strdup(c)))
options->mimicmodel = opt;
+ if ((c = getoption(buf, "-adminauthuser")) && (opt = strdup(c)))
+ options->adminauthuser = opt;
+
return 1;
}
}
puts( "" );
- printf( "DDP(AppleTalk) Support:\t" );
-#ifdef NO_DDP
- puts( "No" );
-#else
- puts( "Yes" );
-#endif
-
printf( " CNID backends:\t" );
#ifdef CNID_BACKEND_CDB
printf( "cdb ");
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" );
int afs_getvolspace( vol, bfree, btotal, bsize )
struct vol *vol;
VolSpace *bfree, *btotal;
-u_int32_t *bsize;
+uint32_t *bsize;
{
struct ViceIoctl vi;
struct VolumeStatus *vs;
struct vol *vol;
struct dir *dir;
struct path *path;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
ibuf += 2;
memcpy( &vid, ibuf, sizeof( vid ));
#undef accessmode
#endif
- void afsmode( path, ma, dir, st )
+ void afsmode( vol, path, ma, dir, st )
+ const struct volume *vol;
char *path;
struct maccess *ma;
struct dir *dir;
return;
}
- accessmode( path, ma, dir, st );
+ accessmode(vol, path, ma, dir, st );
return;
}
struct dir *dir;
char *iend;
struct path *path;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
*rbuflen = 0;
iend = ibuf + ibuflen;
char realm[ MAXKTCREALMLEN ];
char oldpw[ 9 ], newpw[ 9 ];
int len, rc;
- u_int16_t clen;
+ uint16_t clen;
struct ktc_encryptionKey oldkey, newkey;
struct ktc_token adtok;
struct ubik_client *conn;
struct finderinfo {
- u_int32_t f_type;
- u_int32_t creator;
- u_int16_t attrs; /* File attributes (high 8 bits)*/
- u_int16_t label; /* Label (low 8 bits )*/
+ uint32_t f_type;
+ uint32_t creator;
+ uint16_t attrs; /* File attributes (high 8 bits)*/
+ uint16_t label; /* Label (low 8 bits )*/
char reserved[22]; /* Unknown (at least for now...) */
};
/* This is our search-criteria structure. */
struct scrit {
- u_int32_t rbitmap; /* Request bitmap - which values should we check ? */
- u_int16_t fbitmap, dbitmap; /* file & directory bitmap - which values should we return ? */
- u_int16_t attr; /* File attributes */
+ uint32_t rbitmap; /* Request bitmap - which values should we check ? */
+ uint16_t fbitmap, dbitmap; /* file & directory bitmap - which values should we return ? */
+ uint16_t attr; /* File attributes */
time_t cdate; /* Creation date */
time_t mdate; /* Last modification date */
time_t bdate; /* Last backup date */
- u_int32_t pdid; /* Parent DID */
- u_int16_t offcnt; /* Offspring count */
+ uint32_t pdid; /* Parent DID */
+ uint16_t offcnt; /* Offspring count */
struct finderinfo finfo; /* Finder info */
char lname[64]; /* Long name */
char utf8name[514]; /* UTF8 or UCS2 name */ /* for convert_charset dest_len parameter +2 */
*/
static int crit_check(struct vol *vol, struct path *path) {
int result = 0;
- u_int16_t attr, flags = CONV_PRECOMPOSE;
+ uint16_t attr, flags = CONV_PRECOMPOSE;
struct finderinfo *finfo = NULL, finderinfo;
struct adouble *adp = NULL;
time_t c_date, b_date;
- u_int32_t ac_date, ab_date;
+ uint32_t ac_date, ab_date;
static char convbuf[514]; /* for convert_charset dest_len parameter +2 */
size_t len;
int islnk;
char *p = *buf;
int ret;
size_t tbuf =0;
- u_int16_t resultsize;
+ uint16_t resultsize;
int isdir = S_ISDIR(path->st.st_mode);
/* Skip resultsize */
int *rsize,
int ext)
{
- static u_int32_t cur_pos; /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
+ static uint32_t cur_pos; /* Saved position index (ID) - used to remember "position" across FPCatSearch calls */
static DIR *dirpos; /* UNIX structure describing currently opened directory. */
- struct dir *curdir; /* struct dir of current directory */
+ struct dir *currentdir; /* struct dir of current directory */
int cidx, r;
struct dirent *entry;
int result = AFP_OK;
start_time = time(NULL);
while ((cidx = reducestack()) != -1) {
+ LOG(log_debug, logtype_afpd, "catsearch: dir: \"%s\"", dstack[cidx].path);
+
error = lchdir(dstack[cidx].path);
if (!error && dirpos == NULL)
goto catsearch_end;
}
- if ((curdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
+ if ((currentdir = dirlookup_bypath(vol, dstack[cidx].path)) == NULL) {
result = AFPERR_MISC;
goto catsearch_end;
}
+ LOG(log_debug, logtype_afpd, "catsearch: current struct dir: \"%s\"", cfrombstr(currentdir->d_fullpath));
while ((entry = readdir(dirpos)) != NULL) {
(*pos)++;
if (!check_dirent(vol, entry->d_name))
continue;
+ LOG(log_debug, logtype_afpd, "catsearch(\"%s\"): dirent: \"%s\"",
+ cfrombstr(currentdir->d_fullpath), entry->d_name);
+
memset(&path, 0, sizeof(path));
path.u_name = entry->d_name;
if (of_stat(&path) != 0) {
*/
int unlen = strlen(path.u_name);
path.d_dir = dircache_search_by_name(vol,
- curdir,
+ currentdir,
path.u_name,
unlen);
if (path.d_dir == NULL) {
/* path.m_name is set by adddir */
if ((path.d_dir = dir_add(vol,
- curdir,
+ currentdir,
&path,
unlen)) == NULL) {
result = AFPERR_MISC;
goto catsearch_end;
}
} else {
- path.d_dir = curdir;
+ path.d_dir = currentdir;
}
ccr = crit_check(vol, &path);
char *rbuf, size_t *rbuflen, int ext)
{
struct vol *vol;
- u_int16_t vid;
- u_int16_t spec_len;
- u_int32_t rmatches, reserved;
- u_int32_t catpos[4];
- u_int32_t pdid = 0;
+ uint16_t vid;
+ uint16_t spec_len;
+ uint32_t rmatches, reserved;
+ uint32_t catpos[4];
+ uint32_t pdid = 0;
int ret, rsize;
- u_int32_t nrecs = 0;
+ uint32_t nrecs = 0;
unsigned char *spec1, *spec2, *bspec1, *bspec2;
size_t len;
- u_int16_t namelen;
- u_int16_t flags;
+ uint16_t namelen;
+ uint16_t flags;
char tmppath[256];
char *uname;
cnid = htonl(2);
dir = vol->v_root;
+ LOG(log_debug, logtype_afpd, "dirlookup_bypath(\"%s\")", path);
+
+ if (strcmp(vol->v_path, path) == 0)
+ return dir;
+
EC_NULL(rpath = rel_path_in_vol(path, vol->v_path)); /* 1. */
+
+ LOG(log_debug, logtype_afpd, "dirlookup_bypath: rpath: \"%s\"", cfrombstr(rpath));
+
EC_NULL(statpath = bfromcstr(vol->v_path)); /* 2. */
l = bsplit(rpath, '/');
did = cnid;
EC_ZERO(bcatcstr(statpath, "/"));
EC_ZERO(bconcat(statpath, l->entry[i]));
+
+ LOG(log_debug, logtype_afpd, "dirlookup_bypath: statpath: \"%s\"", cfrombstr(statpath));
+
EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
"lstat(rpath: %s, elem: %s): %s: %s",
cfrombstr(rpath), cfrombstr(l->entry[i]),
dir,
cfrombstr(l->entry[i]),
blength(l->entry[i]))) == NULL) {
+
if ((cnid = cnid_add(vol->v_cdb, /* 6. */
&st,
did,
cfrombstr(l->entry[i]),
blength(l->entry[i]),
- 0)) == CNID_INVALID) {
+ 0)) == CNID_INVALID)
EC_FAIL;
- }
if ((dir = dirlookup(vol, cnid)) == NULL) /* 7. */
EC_FAIL;
if (ret != 0)
return NULL;
+ LOG(log_debug, logtype_afpd, "dirlookup_bypath: result: \"%s\"",
+ cfrombstr(dir->d_fullpath));
+
return dir;
}
DIR *dp;
struct dirent *de;
int ret;
- static u_int32_t did = 0;
+ static uint32_t did = 0;
static char cname[MAXPATHLEN];
static char lname[MAXPATHLEN];
ucs2_t u2_path[MAXPATHLEN];
/* 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 */
struct dir *cdir;
char *data, *p;
int len;
- u_int32_t hint;
- u_int16_t len16;
+ uint32_t hint;
+ uint16_t len16;
int size = 0;
int toUTF8 = 0;
if (!p)
return -1;
- accessmode(p, &ma, curdir, NULL);
+ accessmode(current_vol, p, &ma, curdir, NULL);
if ((mode & OPENACC_WR) && !(ma.ma_user & AR_UWRITE))
return -1;
if ((mode & OPENACC_RD) && !(ma.ma_user & AR_UREAD))
{
struct maccess ma;
- accessmode(path->u_name, &ma, curdir, &path->st);
+ accessmode(current_vol, path->u_name, &ma, curdir, &path->st);
LOG(log_debug, logtype_afpd, "file_access(\"%s\"): mapped user mode: 0x%02x",
path->u_name, ma.ma_user);
}
/* --------------------- */
-void setdiroffcnt(struct dir *dir, struct stat *st, u_int32_t count)
+void setdiroffcnt(struct dir *dir, struct stat *st, uint32_t count)
{
dir->d_offcnt = count;
dir->d_ctime = st->st_ctime;
*/
int getdirparams(const struct vol *vol,
- u_int16_t bitmap, struct path *s_path,
+ uint16_t bitmap, struct path *s_path,
struct dir *dir,
char *buf, size_t *buflen )
{
struct adouble ad;
char *data, *l_nameoff = NULL, *utf_nameoff = NULL;
int bit = 0, isad = 0;
- u_int32_t aint;
- u_int16_t ashort;
+ uint32_t aint;
+ uint16_t ashort;
int ret;
- u_int32_t utf8 = 0;
+ uint32_t utf8 = 0;
cnid_t pdid;
struct stat *st = &s_path->st;
char *upath = s_path->u_name;
(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 */
ashort = htons(ATTRBIT_INVISIBLE);
} else
ashort = 0;
- ashort |= htons(ATTRBIT_SHARED);
memcpy( data, &ashort, sizeof( ashort ));
data += sizeof( ashort );
break;
if (dir->d_m_name) /* root of parent can have a null name */
l_nameoff = data;
else
- memset(data, 0, sizeof(u_int16_t));
- data += sizeof( u_int16_t );
+ memset(data, 0, sizeof(uint16_t));
+ data += sizeof( uint16_t );
break;
case DIRPBIT_SNAME :
- memset(data, 0, sizeof(u_int16_t));
- data += sizeof( u_int16_t );
+ memset(data, 0, sizeof(uint16_t));
+ data += sizeof( uint16_t );
break;
case DIRPBIT_DID :
break;
case DIRPBIT_ACCESS :
- accessmode( upath, &ma, dir , st);
+ accessmode(vol, upath, &ma, dir , st);
*data++ = ma.ma_user;
*data++ = ma.ma_world;
if (dir->d_m_name) /* root of parent can have a null name */
utf_nameoff = data;
else
- memset(data, 0, sizeof(u_int16_t));
- data += sizeof( u_int16_t );
+ memset(data, 0, sizeof(uint16_t));
+ data += sizeof( uint16_t );
aint = 0;
memcpy(data, &aint, sizeof( aint ));
data += sizeof( aint );
break;
case DIRPBIT_UNIXPR :
+ /* accessmode may change st_mode with ACLs */
+ accessmode(vol, upath, &ma, dir, st);
+
aint = htonl(st->st_uid);
memcpy( data, &aint, sizeof( aint ));
data += sizeof( aint );
memcpy( data, &aint, sizeof( aint ));
data += sizeof( aint );
- accessmode( upath, &ma, dir , st);
-
*data++ = ma.ma_user;
*data++ = ma.ma_world;
*data++ = ma.ma_group;
struct vol *vol;
struct dir *dir;
struct path *path;
- u_int16_t vid, bitmap;
- u_int32_t did;
+ uint16_t vid, bitmap;
+ uint32_t did;
int rc;
*rbuflen = 0;
*
* assume path == '\0' eg. it's a directory in canonical form
*/
-int setdirparams(struct vol *vol, struct path *path, u_int16_t d_bitmap, char *buf )
+int setdirparams(struct vol *vol, struct path *path, uint16_t d_bitmap, char *buf )
{
struct maccess ma;
struct adouble ad;
int bit, isad = 1;
int cdate, bdate;
int owner, group;
- u_int16_t ashort, bshort, oshort;
+ uint16_t ashort, bshort, oshort;
int err = AFP_OK;
int change_mdate = 0;
int change_parent_mdate = 0;
int newdate = 0;
- u_int16_t bitmap = d_bitmap;
+ uint16_t bitmap = d_bitmap;
u_char finder_buf[32];
- u_int32_t upriv;
+ uint32_t upriv;
mode_t mpriv = 0;
- u_int16_t upriv_bit = 0;
+ uint16_t upriv_bit = 0;
bit = 0;
upath = path->u_name;
}
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
* 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));
}
}
case DIRPBIT_FINFO :
if (isad) {
/* Fixes #2802236 */
- u_int16_t *fflags = (u_int16_t *)(finder_buf + FINDERINFO_FRFLAGOFF);
+ uint16_t *fflags = (uint16_t *)(finder_buf + FINDERINFO_FRFLAGOFF);
*fflags &= htons(~FINDERINFO_ISHARED);
/* #2802236 end */
if ( dir->d_did == DIRDID_ROOT ) {
int dfd;
struct vol *vol;
struct dir *dir;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
struct dir *dir;
char *upath;
struct path *s_path;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
int err;
*rbuflen = 0;
}
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 );
ad_close_metadata( &ad);
createdir_done:
- memcpy( rbuf, &dir->d_did, sizeof( u_int32_t ));
- *rbuflen = sizeof( u_int32_t );
+ memcpy( rbuf, &dir->d_did, sizeof( uint32_t ));
+ *rbuflen = sizeof( uint32_t );
setvoltime(obj, vol );
return( AFP_OK );
}
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);
struct dir *fdir, *pdir;
DIR *dp;
struct adouble ad;
- u_int16_t ashort;
+ uint16_t ashort;
int err;
if ((pdir = dirlookup(vol, curdir->d_pdid)) == NULL) {
dir_remove( vol, fdir );
} else {
LOG(log_error, logtype_afpd, "deletecurdir(\"%s\"): netatalk_rmdir_all_errors error",
- curdir->d_fullpath);
+ cfrombstr(curdir->d_fullpath));
}
delete_done:
struct passwd *pw;
struct group *gr;
char *name;
- u_int32_t id;
+ uint32_t id;
int len, sfunc;
int utf8 = 0;
len = strlen( name );
if (utf8) {
- u_int16_t tp = htons(len);
+ uint16_t tp = htons(len);
memcpy(rbuf, &tp, sizeof(tp));
rbuf += sizeof(tp);
*rbuflen += 2;
struct passwd *pw;
struct group *gr;
int len, sfunc;
- u_int32_t id;
- u_int16_t ulen;
+ uint32_t id;
+ uint16_t ulen;
ibuf++;
sfunc = (unsigned char) *ibuf++;
#if 0
struct vol *vol;
struct dir *dir;
- u_int16_t vid;
- u_int32_t did;
+ uint16_t vid;
+ uint32_t did;
#endif /* 0 */
*rbuflen = 0;
struct vol *vol;
struct dir *parentdir;
struct path *path;
- u_int32_t did;
- u_int16_t vid;
+ uint32_t did;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
#include <stdio.h>
#include <stdlib.h>
-/* STDC check */
-#if STDC_HEADERS
#include <string.h>
-#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 <utime.h>
#include <errno.h>
#include <sys/param.h>
memcpy(data, ufinderi, ADEDLEN_FINDERI);
chk_ext = 1;
if (vol_inv_dots(vol) && *upath == '.') { /* make it invisible */
- u_int16_t ashort;
+ uint16_t ashort;
ashort = htons(FINDERINFO_INVISIBLE);
memcpy((char *)data + FINDERINFO_FRFLAGOFF, &ashort, sizeof(ashort));
}
if (islink){
- u_int16_t linkflag;
+ uint16_t linkflag;
memcpy(&linkflag, (char *)data + FINDERINFO_FRFLAGOFF, 2);
linkflag |= htons(FINDERINFO_ISALIAS);
memcpy((char *)data + FINDERINFO_FRFLAGOFF, &linkflag, 2);
/* ---------------------
*/
-char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, u_int32_t utf8)
+char *set_name(const struct vol *vol, char *data, cnid_t pid, char *name, cnid_t id, uint32_t utf8)
{
- u_int32_t aint;
+ uint32_t aint;
char *tp = NULL;
char *src = name;
aint = strlen( name );
*data++ = aint;
}
else {
- u_int16_t temp;
+ uint16_t temp;
if (aint > UTF8FILELEN_EARLY) /* FIXME safeguard, anyway if no ascii char it's game over*/
aint = UTF8FILELEN_EARLY;
const int len)
{
static int first = 1; /* mark if this func is called the first time */
- u_int32_t adcnid;
- u_int32_t dbcnid = CNID_INVALID;
+ uint32_t adcnid;
+ uint32_t dbcnid = CNID_INVALID;
restart:
if (vol->v_cdb != NULL) {
/* -------------------------- */
int getmetadata(struct vol *vol,
- u_int16_t bitmap,
+ uint16_t bitmap,
struct path *path, struct dir *dir,
char *buf, size_t *buflen, struct adouble *adp)
{
char *data, *l_nameoff = NULL, *upath;
char *utf_nameoff = NULL;
int bit = 0;
- u_int32_t aint;
+ uint32_t aint;
cnid_t id = 0;
- u_int16_t ashort;
+ uint16_t ashort;
u_char achar, fdType[4];
- u_int32_t utf8 = 0;
+ uint32_t utf8 = 0;
struct stat *st;
struct maccess ma;
/* FIXME do we want a visual clue if the file is read only
*/
struct maccess ma;
- accessmode( ".", &ma, dir , NULL);
+ accessmode(vol, ".", &ma, dir , NULL);
if ((ma.ma_user & AR_UWRITE)) {
- accessmode( upath, &ma, dir , st);
+ accessmode(vol, upath, &ma, dir , st);
if (!(ma.ma_user & AR_UWRITE)) {
ashort |= htons(ATTRBIT_NOWRITE);
}
break;
case FILPBIT_PDID :
- memcpy(data, &dir->d_did, sizeof( u_int32_t ));
- data += sizeof( u_int32_t );
+ memcpy(data, &dir->d_did, sizeof( uint32_t ));
+ data += sizeof( uint32_t );
LOG(log_debug, logtype_afpd, "metadata('%s'): Parent DID: %u",
path->u_name, ntohl(dir->d_did));
break;
case FILPBIT_LNAME :
l_nameoff = data;
- data += sizeof( u_int16_t );
+ data += sizeof( uint16_t );
break;
case FILPBIT_SNAME :
- memset(data, 0, sizeof(u_int16_t));
- data += sizeof( u_int16_t );
+ memset(data, 0, sizeof(uint16_t));
+ data += sizeof( uint16_t );
break;
case FILPBIT_FNUM :
if (afp_version >= 30) { /* UTF8 name */
utf8 = kTextEncodingUTF8;
utf_nameoff = data;
- data += sizeof( u_int16_t );
+ data += sizeof( uint16_t );
aint = 0;
memcpy(data, &aint, sizeof( aint ));
data += sizeof( aint );
break;
case FILPBIT_UNIXPR :
/* accessmode may change st_mode with ACLs */
- accessmode( upath, &ma, dir , st);
+ accessmode(vol, upath, &ma, dir , st);
aint = htonl(st->st_uid);
memcpy( data, &aint, sizeof( aint ));
/* ----------------------- */
int getfilparams(struct vol *vol,
- u_int16_t bitmap,
+ uint16_t bitmap,
struct path *path, struct dir *dir,
char *buf, size_t *buflen )
{
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?",
}
}
rc = getmetadata(vol, bitmap, path, dir, buf, buflen, adp);
- if ( adp ) {
- ad_close_metadata( adp);
- }
+ ad_close_metadata( adp);
return( rc );
}
/* ----------------------------- */
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;
char *path, *upath;
int creatf, did, openf, retvalue = AFP_OK;
- u_int16_t vid;
+ uint16_t vid;
struct path *s_path;
*rbuflen = 0;
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;
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;
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);
+ ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF);
return AFPERR_MISC;
}
- (void)get_id(vol, adp, &st, dir->d_did, upath, strlen(upath));
-
- ad_flush( adp);
+ (void)get_id(vol, &ad, &st, dir->d_did, upath, strlen(upath));
+ ad_flush(&ad);
+ ad_close(&ad, ADFLAGS_DF|ADFLAGS_HF );
fce_register_new_file(s_path);
- ad_close( adp, ADFLAGS_DF|ADFLAGS_HF );
-
createfile_done:
curdir->d_offcnt++;
-#ifdef DROPKLUDGE
- if (vol->v_flags & AFPVOL_DROPBOX) {
- retvalue = matchfile2dirperms(upath, vol, did);
- }
-#endif /* DROPKLUDGE */
-
setvoltime(obj, vol );
return (retvalue);
struct dir *dir;
struct path *s_path;
int did, rc;
- u_int16_t vid, bitmap;
+ uint16_t vid, bitmap;
*rbuflen = 0;
ibuf += 2;
extern struct path Cur_Path;
int setfilparams(struct vol *vol,
- struct path *path, u_int16_t f_bitmap, char *buf )
+ struct path *path, uint16_t f_bitmap, char *buf )
{
struct adouble ad, *adp;
struct extmap *em;
int bit, isad = 1, err = AFP_OK;
char *upath;
u_char achar, *fdType, xyy[4]; /* uninitialized, OK 310105 */
- u_int16_t ashort, bshort, oshort;
- u_int32_t aint;
- u_int32_t upriv;
- u_int16_t upriv_bit = 0;
+ uint16_t ashort, bshort, oshort;
+ uint32_t aint;
+ uint32_t upriv;
+ uint16_t upriv_bit = 0;
struct utimbuf ut;
struct timeval tv;
uid_t f_uid;
gid_t f_gid;
- u_int16_t bitmap = f_bitmap;
- u_int32_t cdate,bdate;
+ uint16_t bitmap = f_bitmap;
+ uint32_t cdate,bdate;
u_char finder_buf[32];
#ifdef DEBUG
/* 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:
}
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);
}
if (isad) {
ad_flush( adp);
ad_close_metadata( adp);
-
}
if (change_parent_mdate && gettimeofday(&tv, NULL) == 0) {
}
}
- /* 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 );
{
char type = *ibuf;
size_t plen = 0;
-u_int16_t len16;
-u_int32_t hint;
+uint16_t len16;
+uint32_t hint;
if ( type != 2 && !(afp_version >= 30 && type == 3) ) {
return -1;
struct dir *dir;
char *newname, *p, *upath;
struct path *s_path;
- u_int32_t sdid, ddid;
+ uint32_t sdid, ddid;
int err, retvalue = AFP_OK;
- u_int16_t svid, dvid;
+ uint16_t svid, dvid;
struct adouble ad, *adp;
int denyreadset;
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;
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;
}
curdir->d_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:
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;
}
}
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) {
if (ad_reso_fileno(adp) == -1 || 0 == (err = copy_fork(ADEID_RFORK, &add, adp))){
/* copy the data fork */
if ((err = copy_fork(ADEID_DFORK, &add, adp)) == 0) {
- err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
+ if (ad_meta_fileno(adp) != -1)
+ err = d_vol->vfs->vfs_copyfile(d_vol, sfd, src, dst);
}
}
static int check_attrib(struct adouble *adp)
{
-u_int16_t bshort = 0;
+uint16_t bshort = 0;
ad_getattr(adp, &bshort);
/*
* 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;
/* 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;
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;
}
int err, retry=0;
size_t buflen;
cnid_t id, cnid;
- u_int16_t vid, bitmap;
+ uint16_t vid, bitmap;
static char buffer[12 + MAXPATHLEN + 1];
int len = 12 + MAXPATHLEN + 1;
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.
int crossdev;
int slen, dlen;
- u_int32_t sid, did;
- u_int16_t vid;
+ uint32_t sid, did;
+ uint16_t vid;
uid_t uid;
gid_t gid;
/*
- * $Id: fork.c,v 1.73 2010-03-30 12:55:26 franklahm Exp $
- *
* Copyright (c) 1990,1993 Regents of The University of Michigan.
+ * Copyright (c) 2010 Frank Lahm
+ *
* All Rights Reserved. See COPYRIGHT.
*/
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
-
#include <string.h>
#include <errno.h>
-
-#include <atalk/adouble.h>
-#include <atalk/logger.h>
-
#include <sys/param.h>
#include <sys/socket.h>
-
-#include <netatalk/at.h>
+#include <inttypes.h>
#include <atalk/dsi.h>
-#include <atalk/atp.h>
-#include <atalk/asp.h>
#include <atalk/afp.h>
+#include <atalk/adouble.h>
+#include <atalk/logger.h>
#include <atalk/util.h>
#include <atalk/cnid.h>
+#include <atalk/bstradd.h>
#include <atalk/globals.h>
#include "fork.h"
#include "desktop.h"
#include "volume.h"
-#ifdef DEBUG1
-#define Debug(a) ((a)->options.flags & OPTION_DEBUG)
-#else
-#define Debug(a) (0)
-#endif
-
#ifdef AFS
struct ofork *writtenfork;
#endif
-static int getforkparams(struct ofork *ofork, u_int16_t bitmap, char *buf, size_t *buflen)
+static int getforkparams(struct ofork *ofork, uint16_t bitmap, char *buf, size_t *buflen)
{
struct path path;
- struct stat *st;
+ struct stat *st;
+
+ struct adouble *adp;
+ struct dir *dir;
+ struct vol *vol;
- struct adouble *adp;
- struct dir *dir;
- struct vol *vol;
-
/* can only get the length of the opened fork */
- if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
- && (ofork->of_flags & AFPFORK_RSRC))
- ||
- ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
- && (ofork->of_flags & AFPFORK_DATA))) {
+ if ( ( (bitmap & ((1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN)))
+ && (ofork->of_flags & AFPFORK_RSRC))
+ ||
+ ( (bitmap & ((1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN)))
+ && (ofork->of_flags & AFPFORK_DATA))) {
return( AFPERR_BITMAP );
}
path.m_name = of_name(ofork);
path.id = 0;
st = &path.st;
- if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
- (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
+ if ( bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) |
+ (1<<FILPBIT_FNUM) | (1 << FILPBIT_CDATE) |
(1 << FILPBIT_MDATE) | (1 << FILPBIT_BDATE))) {
if ( ad_data_fileno( ofork->of_ad ) <= 0 ) {
/* 0 is for symlink */
return getmetadata(vol, bitmap, &path, dir, buf, buflen, adp );
}
-/* ---------------------------- */
static off_t get_off_t(char **ibuf, int is64)
{
- u_int32_t temp;
+ uint32_t temp;
off_t ret;
ret = 0;
ret = ntohl(temp)| (ret << 32);
}
else {
- ret = (int)ret; /* sign extend */
+ ret = (int)ret; /* sign extend */
}
return ret;
}
-/* ---------------------- */
static int set_off_t(off_t offset, char *rbuf, int is64)
{
- u_int32_t temp;
+ uint32_t temp;
int ret;
ret = 0;
return ret;
}
-/* ------------------------
-*/
static int is_neg(int is64, off_t val)
{
if (val < 0 || (sizeof(off_t) == 8 && !is64 && (val & 0x80000000U)))
- return 1;
+ return 1;
return 0;
}
-static int sum_neg(int is64, off_t offset, off_t reqcount)
+static int sum_neg(int is64, off_t offset, off_t reqcount)
{
- if (is_neg(is64, offset +reqcount) )
- return 1;
+ if (is_neg(is64, offset +reqcount) )
+ return 1;
return 0;
}
-/* -------------------------
-*/
-static int setforkmode(struct adouble *adp, int eid, int ofrefnum, off_t what)
-{
- return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, what, 1, ofrefnum);
-}
-
-/* -------------------------
-*/
-int getforkmode(struct adouble *adp, int eid, off_t what)
-{
- return ad_testlock(adp, eid, what);
-}
-
-/* -------------------------
-*/
static int fork_setmode(struct adouble *adp, int eid, int access, int ofrefnum)
{
int ret;
int denywriteset;
if (! (access & (OPENACC_WR | OPENACC_RD | OPENACC_DWR | OPENACC_DRD))) {
- return setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_NONE);
+ return ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_NONE, 1, ofrefnum);
}
if ((access & (OPENACC_RD | OPENACC_DRD))) {
- if ((readset = getforkmode(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
+ if ((readset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_RD)) <0)
return readset;
- if ((denyreadset = getforkmode(adp, eid, AD_FILELOCK_DENY_RD)) <0)
+ if ((denyreadset = ad_testlock(adp, eid, AD_FILELOCK_DENY_RD)) <0)
return denyreadset;
if ((access & OPENACC_RD) && denyreadset) {
if ((access & OPENACC_DRD) && readset) {
errno = EACCES;
return -1;
- }
+ }
/* boolean logic is not enough, because getforkmode is not always telling the
- * true
+ * true
*/
if ((access & OPENACC_RD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_RD);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_RD, 1, ofrefnum);
if (ret)
return ret;
}
if ((access & OPENACC_DRD)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_RD);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_RD, 1, ofrefnum);
if (ret)
return ret;
}
}
/* ------------same for writing -------------- */
if ((access & (OPENACC_WR | OPENACC_DWR))) {
- if ((writeset = getforkmode(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
+ if ((writeset = ad_testlock(adp, eid, AD_FILELOCK_OPEN_WR)) <0)
return writeset;
- if ((denywriteset = getforkmode(adp, eid, AD_FILELOCK_DENY_WR)) <0)
+ if ((denywriteset = ad_testlock(adp, eid, AD_FILELOCK_DENY_WR)) <0)
return denywriteset;
if ((access & OPENACC_WR) && denywriteset) {
if ((access & OPENACC_DWR) && writeset) {
errno = EACCES;
return -1;
- }
+ }
if ((access & OPENACC_WR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_OPEN_WR);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_OPEN_WR, 1, ofrefnum);
if (ret)
return ret;
}
if ((access & OPENACC_DWR)) {
- ret = setforkmode(adp, eid, ofrefnum, AD_FILELOCK_DENY_WR);
+ ret = ad_lock(adp, eid, ADLOCK_RD | ADLOCK_FILELOCK, AD_FILELOCK_DENY_WR, 1, ofrefnum);
if (ret)
return ret;
}
/* ----------------------- */
int afp_openfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
- struct vol *vol;
- struct dir *dir;
- struct ofork *ofork, *opened;
- struct adouble *adsame = NULL;
- size_t buflen;
- int ret, adflags, eid;
- u_int32_t did;
- u_int16_t vid, bitmap, access, ofrefnum;
- char fork, *path, *upath;
- struct stat *st;
- u_int16_t bshort;
- struct path *s_path;
-
+ struct vol *vol;
+ struct dir *dir;
+ struct ofork *ofork, *opened;
+ struct adouble *adsame = NULL;
+ size_t buflen;
+ int ret, adflags, eid;
+ uint32_t did;
+ uint16_t vid, bitmap, access, ofrefnum;
+ char fork, *path, *upath;
+ struct stat *st;
+ uint16_t bshort;
+ struct path *s_path;
+
ibuf++;
fork = *ibuf++;
memcpy(&vid, ibuf, sizeof( vid ));
ibuf += sizeof( int );
if (NULL == ( dir = dirlookup( vol, did ))) {
- return afp_errno;
+ return afp_errno;
}
memcpy(&bitmap, ibuf, sizeof( bitmap ));
}
if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
- return get_afp_errno(AFPERR_PARAM);
+ return get_afp_errno(AFPERR_PARAM);
}
if (*s_path->m_name == '\0') {
- /* it's a dir ! */
- return AFPERR_BADTYPE;
+ /* it's a dir ! */
+ return AFPERR_BADTYPE;
}
+ LOG(log_debug, logtype_afpd,
+ "afp_openfork(\"%s\", %s)",
+ abspath(s_path->u_name),
+ (fork & OPENFORK_RSCS) ? "OPENFORK_RSCS" : "OPENFORK_DATA");
+
/* stat() data fork st is set because it's not a dir */
switch ( s_path->st_errno ) {
case 0:
case EACCES:
return (access & OPENACC_WR) ? AFPERR_LOCK : AFPERR_ACCESS;
default:
- LOG(log_error, logtype_afpd, "afp_openfork(%s): ad_open: %s", s_path->m_name, strerror(errno) );
+ LOG(log_error, logtype_afpd, "afp_openfork(%s): %s", s_path->m_name, strerror(errno));
return AFPERR_PARAM;
}
/* FIXME should we check it first ? */
if (check_access(upath, access ) < 0) {
return AFPERR_ACCESS;
}
- }
- else {
+ } else {
if (file_access(s_path, access ) < 0) {
return AFPERR_ACCESS;
}
/* XXX: this probably isn't the best way to do this. the already
open bits should really be set if the fork is opened by any
program, not just this one. however, that's problematic to do
- if we can't write lock files somewhere. opened is also passed to
+ if we can't write lock files somewhere. opened is also passed to
ad_open so that we can keep file locks together.
- FIXME: add the fork we are opening?
+ FIXME: add the fork we are opening?
*/
if ((opened = of_findname(s_path))) {
adsame = opened->of_ad;
if ( fork == OPENFORK_DATA ) {
eid = ADEID_DFORK;
- adflags = ADFLAGS_DF|ADFLAGS_HF;
+ adflags = ADFLAGS_DF | ADFLAGS_HF ;
} else {
eid = ADEID_RFORK;
- adflags = ADFLAGS_HF;
+ adflags = ADFLAGS_RF | ADFLAGS_HF;
}
path = s_path->m_name;
ret = AFPERR_NOOBJ;
if (access & OPENACC_WR) {
/* try opening in read-write mode */
- if (ad_open(upath, adflags, O_RDWR, 0, ofork->of_ad) < 0) {
+ if (ad_open(ofork->of_ad, upath, adflags, O_RDWR, O_RDWR) < 0) {
switch ( errno ) {
case EROFS:
ret = AFPERR_VLOCK;
case ENOENT:
if (fork == OPENFORK_DATA) {
/* try to open only the data fork */
- if (ad_open(upath, ADFLAGS_DF, O_RDWR, 0, ofork->of_ad) < 0) {
+ if (ad_open(ofork->of_ad, upath, ADFLAGS_DF, O_RDWR) < 0) {
goto openfork_err;
}
adflags = ADFLAGS_DF;
- }
- else {
+ } else {
/* here's the deal. we only try to create the resource
- * fork if the user wants to open it for write acess. */
- if (ad_open(upath, adflags, O_RDWR | O_CREAT, 0666, ofork->of_ad) < 0)
+ * fork if the user wants to open it for write acess. */
+ if (ad_open(ofork->of_ad, upath, adflags, O_RDWR | O_CREAT, 0666, O_RDWR | O_CREAT, 0666) < 0)
goto openfork_err;
ofork->of_flags |= AFPFORK_OPEN;
}
} else {
/* try opening in read-only mode */
ret = AFPERR_NOOBJ;
- if (ad_open(upath, adflags, O_RDONLY, 0, ofork->of_ad) < 0) {
+ if (ad_open(ofork->of_ad, upath, adflags, O_RDONLY, O_RDONLY) < 0) {
switch ( errno ) {
case EROFS:
ret = AFPERR_VLOCK;
case ENOENT:
/* see if client asked for a read only data fork */
if (fork == OPENFORK_DATA) {
- if (ad_open(upath, ADFLAGS_DF, O_RDONLY, 0, ofork->of_ad) < 0) {
+ if (ad_open(ofork->of_ad, upath, ADFLAGS_DF, O_RDONLY) < 0) {
goto openfork_err;
}
adflags = ADFLAGS_DF;
}
- /* else we don't set AFPFORK_OPEN because there's no ressource fork file
+ /* else we don't set AFPFORK_OPEN because there's no ressource fork file
* We need to check AFPFORK_OPEN in afp_closefork(). eg fork open read-only
* then create in open read-write.
* FIXME , it doesn't play well with byte locking example:
* ressource fork open read only
* locking set on it (no effect, there's no file!)
* ressource fork open read write now
- */
+ */
break;
case EMFILE :
case ENFILE :
goto openfork_err;
break;
default:
- LOG(log_error, logtype_afpd, "afp_openfork('%s/%s'): ad_open: errno: %i (%s)",
- getcwdpath, s_path->m_name, errno, strerror(errno) );
+ LOG(log_error, logtype_afpd, "afp_openfork(\"%s\"): %s",
+ abspath(s_path->m_name), strerror(errno) );
goto openfork_err;
break;
}
}
}
- if ((adflags & ADFLAGS_HF) && (ad_get_HF_flags( ofork->of_ad) & O_CREAT)) {
+ if ((adflags & ADFLAGS_RF) && (ad_get_RF_flags( ofork->of_ad) & O_CREAT)) {
if (ad_setname(ofork->of_ad, path)) {
ad_flush( ofork->of_ad );
}
}
- if (( ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof( u_int16_t ),
- &buflen )) != AFP_OK ) {
+ if ((ret = getforkparams(ofork, bitmap, rbuf + 2 * sizeof(int16_t), &buflen)) != AFP_OK) {
ad_close( ofork->of_ad, adflags );
goto openfork_err;
}
- *rbuflen = buflen + 2 * sizeof( u_int16_t );
+ *rbuflen = buflen + 2 * sizeof( uint16_t );
bitmap = htons( bitmap );
- memcpy(rbuf, &bitmap, sizeof( u_int16_t ));
- rbuf += sizeof( u_int16_t );
+ memcpy(rbuf, &bitmap, sizeof( uint16_t ));
+ rbuf += sizeof( uint16_t );
/* check WriteInhibit bit if we have a ressource fork
- * the test is done here, after some Mac trafic capture
+ * the test is done here, after some Mac trafic capture
*/
if (ad_meta_fileno(ofork->of_ad) != -1) { /* META */
ad_getattr(ofork->of_ad, &bshort);
int afp_setforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen, char *rbuf _U_, size_t *rbuflen)
{
- struct ofork *ofork;
- off_t size;
- u_int16_t ofrefnum, bitmap;
+ struct ofork *ofork;
+ off_t size;
+ uint16_t ofrefnum, bitmap;
int err;
int is64;
int eid;
- off_t st_size;
-
+ off_t st_size;
+
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
} else
return AFPERR_PARAM;
- if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
- && eid == ADEID_RFORK
- ) ||
- ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
- && eid == ADEID_DFORK)) {
+ if ( ( (bitmap & ( (1<<FILPBIT_DFLEN) | (1<<FILPBIT_EXTDFLEN) ))
+ && eid == ADEID_RFORK
+ ) ||
+ ( (bitmap & ( (1<<FILPBIT_RFLEN) | (1<<FILPBIT_EXTRFLEN) ))
+ && eid == ADEID_DFORK)) {
return AFPERR_BITMAP;
}
-
+
is64 = 0;
if ((bitmap & ( (1<<FILPBIT_EXTDFLEN) | (1<<FILPBIT_EXTRFLEN) ))) {
if (afp_version >= 30) {
is64 = 4;
}
- else
- return AFPERR_BITMAP;
+ else
+ return AFPERR_BITMAP;
}
if (ibuflen < 2+ sizeof(ofrefnum) + sizeof(bitmap) + is64 +4)
return AFPERR_PARAM ;
-
+
size = get_off_t(&ibuf, is64);
if (size < 0)
if (bitmap == (1<<FILPBIT_DFLEN) || bitmap == (1<<FILPBIT_EXTDFLEN)) {
- st_size = ad_size(ofork->of_ad, eid);
- err = -2;
- if (st_size > size &&
- ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
+ st_size = ad_size(ofork->of_ad, eid);
+ err = -2;
+ if (st_size > size &&
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0)
goto afp_setfork_err;
err = ad_dtruncate( ofork->of_ad, size );
if (st_size > size)
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
if (err < 0)
goto afp_setfork_err;
} else if (bitmap == (1<<FILPBIT_RFLEN) || bitmap == (1<<FILPBIT_EXTRFLEN)) {
ad_refresh( ofork->of_ad );
- st_size = ad_size(ofork->of_ad, eid);
- err = -2;
- if (st_size > size &&
- ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
+ st_size = ad_size(ofork->of_ad, eid);
+ err = -2;
+ if (st_size > size &&
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_WR, size, st_size -size, ofork->of_refnum) < 0) {
goto afp_setfork_err;
- }
+ }
err = ad_rtruncate(ofork->of_ad, size);
if (st_size > size)
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
if (err < 0)
goto afp_setfork_err;
* read and write. that's most easily handled by always doing an
* appropriate check before each ad_read/ad_write. other things
* that can change files like truncate are handled internally to those
- * functions.
+ * functions.
*/
#define ENDBIT(a) ((a) & 0x80)
#define UNLOCKBIT(a) ((a) & 0x01)
/* ---------------------- */
static int byte_lock(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
{
- struct ofork *ofork;
+ struct ofork *ofork;
off_t offset, length;
int eid;
- u_int16_t ofrefnum;
- u_int8_t flags;
+ uint16_t ofrefnum;
+ uint8_t flags;
int lockop;
-
+
*rbuflen = 0;
/* figure out parameters */
/* FIXME AD_FILELOCK test is surely wrong */
if (length == -1)
length = BYTELOCK_MAX;
- else if (!length || is_neg(is64, length)) {
- return AFPERR_PARAM;
- } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
+ else if (!length || is_neg(is64, length)) {
+ return AFPERR_PARAM;
+ } else if ((length >= AD_FILELOCK_BASE) && -1 == (ad_reso_fileno(ofork->of_ad))) { /* HF ?*/
return AFPERR_LOCK;
}
if (ENDBIT(flags)) {
offset += ad_size(ofork->of_ad, eid);
- /* FIXME what do we do if file size > 2 GB and
+ /* FIXME what do we do if file size > 2 GB and
it's not byte_lock_ext?
*/
}
/* --------------------------- */
int afp_bytelock(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
{
- return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
+ return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 0);
}
/* --------------------------- */
int afp_bytelock_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
{
- return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
+ return byte_lock ( obj, ibuf, ibuflen, rbuf, rbuflen , 1);
}
#undef UNLOCKBIT
/* --------------------------- */
static int crlf(struct ofork *of)
{
- struct extmap *em;
+ struct extmap *em;
if ( ad_meta_fileno( of->of_ad ) == -1 || !memcmp( ufinderi, ad_entry( of->of_ad, ADEID_FINDERI),8)) { /* META */
/* no resource fork or no finderinfo, use our files extension mapping */
if (!( em = getextmap( of_name(of) )) || memcmp( "TEXT", em->em_type, sizeof( em->em_type ))) {
return 0;
- }
+ }
/* file type is TEXT */
return 1;
static ssize_t read_file(struct ofork *ofork, int eid,
- off_t offset, u_char nlmask,
- u_char nlchar, char *rbuf,
- size_t *rbuflen, const int xlate)
+ off_t offset, u_char nlmask,
+ u_char nlchar, char *rbuf,
+ size_t *rbuflen, const int xlate)
{
ssize_t cc;
int eof = 0;
}
/* -----------------------------
- * with ddp, afp_read can return fewer bytes than in reqcount
+ * with ddp, afp_read can return fewer bytes than in reqcount
* so return EOF only if read actually past end of file not
* if offset +reqcount > size of file
* e.g.:
* read fork offset 0 size 10752 ???? ==> 4264 bytes (without EOF)
* read fork offset 4264 size 6128 ==> 4264 (without EOF)
* read fork offset 9248 size 1508 ==> 1182 (EOF)
- * 10752 is a bug in Mac 7.5.x finder
+ * 10752 is a bug in Mac 7.5.x finder
*
- * with dsi, should we check that reqcount < server quantum?
-*/
+ * with dsi, should we check that reqcount < server quantum?
+ */
static int read_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
{
- struct ofork *ofork;
- off_t offset, saveoff, reqcount, savereqcount;
- ssize_t cc, err;
- int eid, xlate = 0;
- u_int16_t ofrefnum;
- u_char nlmask, nlchar;
+ struct ofork *ofork;
+ off_t offset, saveoff, reqcount, savereqcount;
+ ssize_t cc, err;
+ int eid, xlate = 0;
+ uint16_t ofrefnum;
+ u_char nlmask, nlchar;
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
offset = get_off_t(&ibuf, is64);
reqcount = get_off_t(&ibuf, is64);
+ LOG(log_debug, logtype_afpd,
+ "afp_read(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
+ cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount,
+ (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
+
if (is64) {
nlmask = nlchar = 0;
}
goto afp_read_err;
}
+ LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd)",
+ of_name(ofork), (intmax_t)offset, (intmax_t)reqcount);
+
savereqcount = reqcount;
saveoff = offset;
if (ad_tmplock(ofork->of_ad, eid, ADLOCK_RD, saveoff, savereqcount,ofork->of_refnum) < 0) {
goto afp_read_err;
}
++<<<<<<< HEAD
+#define min(a,b) ((a)<(b)?(a):(b))
+ *rbuflen = min( reqcount, *rbuflen );
++=======
+ *rbuflen = MIN(reqcount, *rbuflen);
+ LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): reading %jd bytes from file",
+ of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
++>>>>>>> netafp/master
err = read_file(ofork, eid, offset, nlmask, nlchar, rbuf, rbuflen, xlate);
if (err < 0)
goto afp_read_done;
+ LOG(log_debug, logtype_afpd, "afp_read(name: \"%s\", offset: %jd, reqcount: %jd): got %jd bytes from file",
+ of_name(ofork), (intmax_t)offset, (intmax_t)reqcount, (intmax_t)*rbuflen);
/* dsi can stream requests. we can only do this if we're not checking
* for an end-of-line character. oh well. */
/* subtract off the offset */
size -= offset;
if (reqcount > size) {
- reqcount = size;
- err = AFPERR_EOF;
+ reqcount = size;
+ err = AFPERR_EOF;
}
offset += *rbuflen;
*rbuflen = cc;
/* due to the nature of afp packets, we have to exit if we get
an error. we can't do this with translation on. */
-#ifdef WITH_SENDFILE
- if (!(xlate || Debug(obj) )) {
+#ifdef WITH_SENDFILE
+ if (!(xlate)) {
int fd;
-
+
fd = ad_readfile_init(ofork->of_ad, eid, &offset, 0);
+
if (dsi_stream_read_file(dsi, fd, offset, dsi->datasize) < 0) {
if (errno == EINVAL || errno == ENOSYS)
goto afp_read_loop;
goto afp_read_done;
}
-afp_read_loop:
-#endif
+ afp_read_loop:
+#endif
/* fill up our buffer. */
while (*rbuflen > 0) {
dsi_readdone(dsi);
goto afp_read_done;
-afp_read_exit:
+ afp_read_exit:
LOG(log_error, logtype_afpd, "afp_read(%s): %s", of_name(ofork), strerror(errno));
dsi_readdone(dsi);
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, savereqcount,ofork->of_refnum);
int afp_flush(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *vol;
- u_int16_t vid;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
return( AFP_OK );
}
-int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
+int afp_flushfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
- struct ofork *ofork;
- u_int16_t ofrefnum;
+ struct ofork *ofork;
+ uint16_t ofrefnum;
*rbuflen = 0;
ibuf += 2;
return( AFPERR_PARAM );
}
+ LOG(log_debug, logtype_afpd,
+ "afp_flushfork(\"%s\", fork: %s)",
+ cfrombstr(ofork->of_ad->ad_fullpath),
+ (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
+
if ( flushfork( ofork ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_flushfork(%s): %s", of_name(ofork), strerror(errno) );
}
There is a lot to tell about fsync, fdatasync, F_FULLFSYNC.
fsync(2) on OSX is implemented differently than on other platforms.
see: http://mirror.linux.org.au/pub/linux.conf.au/2007/video/talks/278.pdf.
- */
+*/
int afp_syncfork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct ofork *ofork;
- u_int16_t ofrefnum;
+ uint16_t ofrefnum;
*rbuflen = 0;
ibuf += 2;
return( AFPERR_PARAM );
}
+ LOG(log_debug, logtype_afpd,
+ "afp_syncfork(\"%s\", fork: %s)",
+ cfrombstr(ofork->of_ad->ad_fullpath),
+ (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
+
if ( flushfork( ofork ) < 0 ) {
- LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
- return AFPERR_MISC;
+ LOG(log_error, logtype_afpd, "flushfork(%s): %s", of_name(ofork), strerror(errno) );
+ return AFPERR_MISC;
}
return( AFP_OK );
int err = 0, doflush = 0;
if ( ad_data_fileno( ofork->of_ad ) != -1 &&
- fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
+ fsync( ad_data_fileno( ofork->of_ad )) < 0 ) {
LOG(log_error, logtype_afpd, "flushfork(%s): dfile(%d) %s",
of_name(ofork), ad_data_fileno(ofork->of_ad), strerror(errno) );
err = -1;
}
if ( ad_reso_fileno( ofork->of_ad ) != -1 && /* HF */
- (ofork->of_flags & AFPFORK_RSRC)) {
+ (ofork->of_flags & AFPFORK_RSRC)) {
/* read in the rfork length */
ad_refresh(ofork->of_ad);
/* flush the header */
if (doflush && ad_flush(ofork->of_ad) < 0)
- err = -1;
+ err = -1;
if (fsync( ad_reso_fileno( ofork->of_ad )) < 0)
err = -1;
int afp_closefork(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
- struct ofork *ofork;
- u_int16_t ofrefnum;
+ struct ofork *ofork;
+ uint16_t ofrefnum;
*rbuflen = 0;
ibuf += 2;
LOG(log_error, logtype_afpd, "afp_closefork: of_find(%d) could not locate fork", ofrefnum );
return( AFPERR_PARAM );
}
+
+ LOG(log_debug, logtype_afpd,
+ "afp_closefork(\"%s\", fork: %s)",
+ cfrombstr(ofork->of_ad->ad_fullpath),
+ (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
+
if ( of_closefork( ofork ) < 0 ) {
LOG(log_error, logtype_afpd, "afp_closefork(%s): of_closefork: %s", of_name(ofork), strerror(errno) );
return( AFPERR_PARAM );
static ssize_t write_file(struct ofork *ofork, int eid,
- off_t offset, char *rbuf,
- size_t rbuflen, const int xlate)
+ off_t offset, char *rbuf,
+ size_t rbuflen, const int xlate)
{
char *p, *q;
ssize_t cc;
/* FPWrite. NOTE: on an error, we always use afp_write_err as
- * the client may have sent us a bunch of data that's not reflected
+ * the client may have sent us a bunch of data that's not reflected
* in reqcount et al. */
static int write_fork(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen, int is64)
{
++<<<<<<< HEAD
+ struct ofork *ofork;
+ off_t offset, saveoff, reqcount;
+ int endflag, eid, xlate = 0, err = AFP_OK;
+ uint16_t ofrefnum;
++=======
+ struct ofork *ofork;
+ off_t offset, saveoff, reqcount, oldsize, newsize;
+ int endflag, eid, xlate = 0, err = AFP_OK;
+ u_int16_t ofrefnum;
++>>>>>>> netafp/master
ssize_t cc;
/* figure out parameters */
goto afp_write_err;
}
+ LOG(log_debug, logtype_afpd,
+ "afp_write(\"%s\", off: %" PRIu64 ", size: %" PRIu64 ", fork: %s)",
+ cfrombstr(ofork->of_ad->ad_fullpath), offset, reqcount,
+ (ofork->of_flags & AFPFORK_DATA) ? "d" : "r");
+
if ((ofork->of_flags & AFPFORK_ACCWR) == 0) {
err = AFPERR_ACCESS;
goto afp_write_err;
goto afp_write_err;
}
+ oldsize = ad_size(ofork->of_ad, eid);
if (endflag)
- offset += ad_size(ofork->of_ad, eid);
+ offset += oldsize;
/* handle bogus parameters */
if (reqcount < 0 || offset < 0) {
goto afp_write_err;
}
+ newsize = ((offset + reqcount) > oldsize) ? (offset + reqcount) : oldsize;
+
/* offset can overflow on 64-bit capable filesystems.
* report disk full if that's going to happen. */
- if (sum_neg(is64, offset, reqcount)) {
+ if (sum_neg(is64, offset, reqcount)) {
err = AFPERR_DFULL;
goto afp_write_err;
}
/* this is yucky, but dsi can stream i/o and asp can't */
switch (obj->proto) {
-#ifndef NO_DDP
- case AFPPROTO_ASP:
- if (asp_wrtcont(obj->handle, rbuf, rbuflen) < 0) {
- *rbuflen = 0;
- LOG(log_error, logtype_afpd, "afp_write: asp_wrtcont: %s", strerror(errno) );
- return( AFPERR_PARAM );
- }
+ case AFPPROTO_DSI:
+ {
+ DSI *dsi = obj->handle;
-#ifdef DEBUG1
- if (obj->options.flags & OPTION_DEBUG) {
- printf("(write) len: %d\n", *rbuflen);
- bprint(rbuf, *rbuflen);
- }
-#endif
- if ((cc = write_file(ofork, eid, offset, rbuf, *rbuflen,
- xlate)) < 0) {
+ /* find out what we have already and write it out. */
+ cc = dsi_writeinit(dsi, rbuf, *rbuflen);
+ if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
+ dsi_writeflush(dsi);
*rbuflen = 0;
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
return cc;
}
offset += cc;
- break;
-#endif /* no afp/asp */
-
- case AFPPROTO_DSI:
- {
- DSI *dsi = obj->handle;
- /* find out what we have already and write it out. */
- cc = dsi_writeinit(dsi, rbuf, *rbuflen);
- if (!cc || (cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
+#if 0 /*def HAVE_SENDFILE_WRITE*/
+ if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
+ if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
+ offset, dsi->datasize)) < 0) {
+ switch (errno) {
+ case EDQUOT :
+ case EFBIG :
+ case ENOSPC :
+ cc = AFPERR_DFULL;
+ break;
+ default :
+ LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
+ goto afp_write_loop;
+ }
dsi_writeflush(dsi);
*rbuflen = 0;
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
+ reqcount, ofork->of_refnum);
return cc;
}
- offset += cc;
-#if 0 /*def HAVE_SENDFILE_WRITE*/
- if (!(xlate || obj->options.flags & OPTION_DEBUG)) {
- if ((cc = ad_writefile(ofork->of_ad, eid, dsi->socket,
- offset, dsi->datasize)) < 0) {
- switch (errno) {
- case EDQUOT :
- case EFBIG :
- case ENOSPC :
- cc = AFPERR_DFULL;
- break;
- default :
- LOG(log_error, logtype_afpd, "afp_write: ad_writefile: %s", strerror(errno) );
- goto afp_write_loop;
- }
- dsi_writeflush(dsi);
- *rbuflen = 0;
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
- reqcount, ofork->of_refnum);
- return cc;
- }
-
- offset += cc;
- goto afp_write_done;
- }
+ offset += cc;
+ goto afp_write_done;
+ }
#endif /* 0, was HAVE_SENDFILE_WRITE */
- /* loop until everything gets written. currently
- * dsi_write handles the end case by itself. */
- while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
- if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
- dsi_writeflush(dsi);
- *rbuflen = 0;
- ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
- reqcount, ofork->of_refnum);
- return cc;
- }
- offset += cc;
+ /* loop until everything gets written. currently
+ * dsi_write handles the end case by itself. */
+ while ((cc = dsi_write(dsi, rbuf, *rbuflen))) {
+ if ((cc = write_file(ofork, eid, offset, rbuf, cc, xlate)) < 0) {
+ dsi_writeflush(dsi);
+ *rbuflen = 0;
+ ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff,
+ reqcount, ofork->of_refnum);
+ return cc;
}
+ offset += cc;
}
- break;
+ }
+ break;
}
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, saveoff, reqcount, ofork->of_refnum);
ofork->of_flags |= AFPFORK_MODIFIED;
/* update write count */
- ofork->of_vol->v_written += reqcount;
+ ofork->of_vol->v_appended += (newsize > oldsize) ? (newsize - oldsize) : 0;
*rbuflen = set_off_t (offset, rbuf, is64);
return( AFP_OK );
return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 0);
}
-/* ----------------------------
+/* ----------------------------
* FIXME need to deal with SIGXFSZ signal
-*/
+ */
int afp_write_ext(AFPObj *obj, char *ibuf, size_t ibuflen, char *rbuf, size_t *rbuflen)
{
return write_fork(obj, ibuf, ibuflen, rbuf, rbuflen, 1);
/* ---------------------------- */
int afp_getforkparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
{
- struct ofork *ofork;
+ struct ofork *ofork;
int ret;
- u_int16_t ofrefnum, bitmap;
+ uint16_t ofrefnum, bitmap;
size_t buflen;
ibuf += 2;
memcpy(&ofrefnum, ibuf, sizeof( ofrefnum ));
}
if (AFP_OK != ( ret = getforkparams( ofork, bitmap,
- rbuf + sizeof( u_short ), &buflen ))) {
+ rbuf + sizeof( u_short ), &buflen ))) {
return( ret );
}
#include <stdlib.h>
#include <string.h>
#include <signal.h>
-
#include <sys/param.h>
#include <sys/uio.h>
-#include <atalk/logger.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/poll.h>
#include <sys/wait.h>
#include <sys/resource.h>
+#include <atalk/logger.h>
#include <atalk/adouble.h>
-
-#include <netatalk/at.h>
#include <atalk/compat.h>
#include <atalk/dsi.h>
-#include <atalk/atp.h>
-#include <atalk/asp.h>
#include <atalk/afp.h>
#include <atalk/paths.h>
#include <atalk/util.h>
#include <atalk/server_child.h>
#include <atalk/server_ipc.h>
+#include <atalk/errchk.h>
+#include <atalk/locking.h>
#include <atalk/globals.h>
+#include "event2/event.h"
+#include "event2/http.h"
+#include "event2/rpc.h"
+
#include "afp_config.h"
#include "status.h"
#include "fork.h"
unsigned char nologin = 0;
struct afp_options default_options;
+
static AFPConfig *configs;
static server_child *server_children;
static sig_atomic_t reloadconfig = 0;
/* ------------------ */
static void afp_goaway(int sig)
{
- AFPConfig *config;
-
-#ifndef NO_DDP
- asp_kill(sig);
-#endif /* ! NO_DDP */
+ AFPConfig *config;
switch( sig ) {
struct rlimit rlim;
if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
- LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
- exit(1);
+ LOG(log_warning, logtype_afpd, "setlimits: reading current limits failed: %s", strerror(errno));
+ return -1;
}
if (rlim.rlim_cur != RLIM_INFINITY && rlim.rlim_cur < 65535) {
rlim.rlim_cur = 65535;
if (rlim.rlim_max != RLIM_INFINITY && rlim.rlim_max < 65535)
rlim.rlim_max = 65535;
if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
- LOG(log_error, logtype_afpd, "setlimits: %s", strerror(errno));
- exit(1);
+ LOG(log_warning, logtype_afpd, "setlimits: increasing limits failed: %s", strerror(errno));
+ return -1;
}
}
return 0;
}
pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
- /* Register CNID */
+ /* Initialize */
cnid_init();
-
+ if (locktable_init("XXX") != 0)
+ exit(EXITERR_SYS);
+#if 0
+ if (rpc_init("127.0.0.1", 4701) != 0)
+ exit(EXITERR_SYS);
+#endif
+
/* watch atp, dsi sockets and ipc parent/child file descriptor. */
if (default_options.flags & OPTION_KEEPSESSIONS) {
#include <stdio.h>
#include <stdlib.h>
-
-/* STDC check */
-#ifdef STDC_HEADERS
+ #include <inttypes.h>
#include <string.h>
-#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 <errno.h>
#include <limits.h>
#include <sys/param.h>
/*
* Get the free space on a partition.
*/
-int ustatfs_getvolspace(const struct vol *vol, VolSpace *bfree, VolSpace *btotal, u_int32_t *bsize)
+int ustatfs_getvolspace(const struct vol *vol, VolSpace *bfree, VolSpace *btotal, uint32_t *bsize)
{
- VolSpace maxVolSpace = (~(VolSpace)0);
+ VolSpace maxVolSpace = UINT64_MAX;
#ifdef ultrix
struct fs_data sfs;
struct statfs sfs;
#endif /*ultrix*/
-
if ( statfs( vol->v_path, &sfs ) < 0 ) {
LOG(log_error, logtype_afpd, "ustatfs_getvolspace unable to stat %s", vol->v_path);
return( AFPERR_PARAM );
*
* dir parameter is used by AFS
*/
- void accessmode(char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st)
+ void accessmode(const struct vol *vol, char *path, struct maccess *ma, struct dir *dir _U_, struct stat *st)
{
struct stat sb;
}
utommode( st, ma );
#ifdef HAVE_ACLS
- acltoownermode(path, st, ma);
+ acltoownermode(vol, path, st, ma);
#endif
}
}
if (S_ISDIR(st.st_mode)) {
- if ( chmod( modbuf, (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
+ if ( chmod_acl( modbuf, (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
}
- } else if ( chmod( modbuf, mode & ~(default_options.umask | EXEC_MODE) ) < 0 && errno != EPERM ) {
+ } else if ( chmod_acl( modbuf, mode & ~(default_options.umask | EXEC_MODE) ) < 0 && errno != EPERM ) {
LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
}
}
closedir( sub );
/* XXX: need to preserve special modes */
- if ( chmod( deskp->d_name, (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
+ if ( chmod_acl( deskp->d_name, (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) );
}
}
return -1;
}
/* XXX: need to preserve special modes */
- if ( chmod( ".AppleDesktop", (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
+ if ( chmod_acl( ".AppleDesktop", (DIRBITS | mode) & ~default_options.umask ) < 0 && errno != EPERM ) {
LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", fullpathname(".AppleDesktop"),strerror(errno) );
}
return( 0 );
/* --------------------- */
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);
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;
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;
}
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 ) {
}
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;
}
}
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 );
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 ) {
-/*
- * $Id: unix.h,v 1.23 2010-04-12 14:28:47 franklahm Exp $
- */
-
#ifndef AFPD_UNIX_H
#define AFPD_UNIX_H
-#ifdef HAVE_SYS_CDEFS_H
-#include <sys/cdefs.h>
-#endif /* HAVE_SYS_CDEFS_H */
-#include <netatalk/endian.h>
+#include <arpa/inet.h>
+
#include "config.h"
#include "volume.h"
#endif /* linux */
-extern int getnfsquota (struct vol *, const int, const u_int32_t,
- struct dqblk *);
+extern int getnfsquota (struct vol *, const int, const uint32_t,
+ struct dqblk *);
#endif /* ! HAVE_LIBQUOTA */
extern int uquota_getvolspace (struct vol *, VolSpace *, VolSpace *,
- const u_int32_t);
+ const uint32_t);
#endif /* NO_QUOTA_SUPPORT */
extern struct afp_options default_options;
extern int setdirowner (const struct vol *, const char *, const uid_t, const gid_t);
extern int setfilunixmode (const struct vol *, struct path*, const mode_t);
extern int setfilowner (const struct vol *, const uid_t, const gid_t, struct path*);
- extern void accessmode (char *, struct maccess *, struct dir *, struct stat *);
+ extern void accessmode (const struct vol *, char *, struct maccess *, struct dir *, struct stat *);
#ifdef AFS
#define accessmode afsmode
#include <grp.h>
#include <utime.h>
#include <errno.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-/* STDC check */
-#if STDC_HEADERS
#include <string.h>
-#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 <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <time.h>
-#include <atalk/asp.h>
#include <atalk/dsi.h>
#include <atalk/adouble.h>
#include <atalk/afp.h>
#include <atalk/logger.h>
#include <atalk/vfs.h>
#include <atalk/uuid.h>
+#include <atalk/ea.h>
#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
#include <atalk/ftw.h>
#include <atalk/globals.h>
#include <atalk/fce_api.h>
+ #include <atalk/errchk.h>
#ifdef CNID_DB
#include <atalk/cnid.h>
struct vol *current_vol; /* last volume from getvolbyvid() */
static struct vol *Volumes = NULL;
-static u_int16_t lastvid = 0;
+static uint16_t lastvid = 0;
static char *Trash = "\02\024Network Trash Folder";
static struct extmap *Extmap = NULL, *Defextmap = NULL;
#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
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 */
} else if (is_var(p, "$c")) {
if (afpmaster && xlatevolname)
return NULL;
-#ifndef NO_DDP
- 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;
-
- }
-#endif
- 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;
} else if (is_var(p, "$i")) {
if (afpmaster && xlatevolname)
return NULL;
-#ifndef NO_DDP
- 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;
-
- }
-#endif
- 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;
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;
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)
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);
char tmpname[AFPVOL_U8MNAMELEN+1];
ucs2_t u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2];
char suffix[6]; /* max is #FFFF */
- u_int16_t flags;
+ uint16_t flags;
LOG(log_debug, logtype_afpd, "createvol: Volume '%s'", name);
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);
int i;
struct passwd *pw;
struct vol_option save_options[VOLOPT_NUM];
+ struct vol_option default_options[VOLOPT_NUM];
struct vol_option options[VOLOPT_NUM];
struct stat st;
break;
}
- memset(save_options, 0, sizeof(save_options));
+ memset(default_options, 0, sizeof(default_options));
/* Enable some default options for all volumes */
- save_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
+ default_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
#ifdef HAVE_ACLS
- save_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS;
+ default_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS;
#endif
- save_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO;
+ default_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO;
LOG(log_maxdebug, logtype_afpd, "readvolfile: seeding default umask: %04o",
obj->options.umask);
- save_options[VOLOPT_UMASK].i_value = obj->options.umask;
+ default_options[VOLOPT_UMASK].i_value = obj->options.umask;
+ memcpy(save_options, default_options, sizeof(options));
LOG(log_debug, logtype_afpd, "readvolfile: \"%s\"", path);
case ':':
/* change the default options for this file */
if (strncmp(path, VOLOPT_DEFAULT, VOLOPT_DEFAULT_LEN) == 0) {
+ volfree(default_options, save_options);
+ memcpy(default_options, save_options, sizeof(options));
*tmp = '\0';
for (i = 0; i < VOLOPT_NUM; i++) {
if (parseline( sizeof( path ) - VOLOPT_DEFAULT_LEN - 1,
path + VOLOPT_DEFAULT_LEN) < 0)
break;
- volset(save_options, NULL, tmp, sizeof(tmp) - 1,
+ volset(default_options, NULL, tmp, sizeof(tmp) - 1,
path + VOLOPT_DEFAULT_LEN);
}
}
* able to specify things in any order, but i don't want to
* re-write everything. */
- memcpy(options, save_options, sizeof(options));
+ memcpy(options, default_options, sizeof(options));
*volname = '\0';
/* read in up to VOLOP_NUM possible options */
if (parseline( sizeof( tmp ) - 1, tmp ) < 0)
break;
- volset(options, save_options, volname, sizeof(volname) - 1, tmp);
+ volset(options, default_options, volname, sizeof(volname) - 1, tmp);
}
/* check allow/deny lists (if not afpd master loading volumes for Zeroconf reg.):
creatvol(obj, pwent, path, tmp, options, p2 != NULL);
}
- volfree(options, save_options);
+ volfree(options, default_options);
break;
case '.' :
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);
}
}
}
}
-
- static off_t getused_size; /* result of getused() */
-
/*!
- nftw callback for getused()
+ * Read band-size info from Info.plist XML file of an TM sparsebundle
+ *
+ * @param path (r) path to Info.plist file
+ * @return band-size in bytes, -1 on error
*/
- static int getused_stat(const char *path,
- const struct stat *statp,
- int tflag,
- struct FTW *ftw)
+ static long long int get_tm_bandsize(const char *path)
{
- off_t low, high;
+ EC_INIT;
+ FILE *file = NULL;
+ char buf[512];
+ long long int bandsize = -1;
+
+ EC_NULL_LOGSTR( file = fopen(path, "r"),
+ "get_tm_bandsize(\"%s\"): %s",
+ path, strerror(errno) );
+
+ while (fgets(buf, sizeof(buf), file) != NULL) {
+ if (strstr(buf, "band-size") == NULL)
+ continue;
- if (tflag == FTW_F || tflag == FTW_D) {
- getused_size += statp->st_blocks * 512;
+ if (fscanf(file, " <integer>%lld</integer>", &bandsize) != 1) {
+ LOG(log_error, logtype_afpd, "get_tm_bandsize(\"%s\"): can't parse band-size", path);
+ EC_FAIL;
+ }
+ break;
}
- return 0;
+ EC_CLEANUP:
+ if (file)
+ fclose(file);
+ LOG(log_debug, logtype_afpd, "get_tm_bandsize(\"%s\"): bandsize: %lld", path, bandsize);
+ return bandsize;
}
- #define GETUSED_CACHETIME 5
/*!
- * Calculate used size of a volume with nftw
+ * Return number on entries in a directory
*
- * The result is cached, we're try to avoid frequently calling nftw()
+ * @param path (r) path to dir
+ * @return number of entries, -1 on error
+ */
+ static long long int get_tm_bands(const char *path)
+ {
+ EC_INIT;
+ long long int count = 0;
+ DIR *dir = NULL;
+ const struct dirent *entry;
+
+ EC_NULL( dir = opendir(path) );
+
+ while ((entry = readdir(dir)) != NULL)
+ count++;
+ count -= 2; /* All OSens I'm aware of return "." and "..", so just substract them, avoiding string comparison in loop */
+
+ EC_CLEANUP:
+ if (dir)
+ closedir(dir);
+ if (ret != 0)
+ return -1;
+ return count;
+ }
+
+ /*!
+ * Calculate used size of a TimeMachine volume
*
- * 1) Call nftw an refresh if:
- * 1a) - we're called the first time
- * 1b) - volume modification date is not yet set and the last time we've been called is
- * longer then 30 sec ago
- * 1c) - the last volume modification is less then 30 sec old
+ * This assumes that the volume is used only for TimeMachine.
+ *
+ * 1) readdir(path of volume)
+ * 2) for every element that matches regex "\(.*\)\.sparsebundle$" :
+ * 3) parse "\1.sparsebundle/Info.plist" and read the band-size XML key integer value
+ * 4) readdir "\1.sparsebundle/bands/" counting files
+ * 5) calculate used size as: (file_count - 1) * band-size
+ *
+ * The result of the calculation is returned in "volume->v_tm_used".
+ * "volume->v_appended" gets reset to 0.
+ * "volume->v_tm_cachetime" is updated with the current time from time(NULL).
+ *
+ * "volume->v_tm_used" is cached for TM_USED_CACHETIME seconds and updated by
+ * "volume->v_appended". The latter is increased by X every time the client
+ * appends X bytes to a file (in fork.c).
*
* @param vol (rw) volume to calculate
+ * @return 0 on success, -1 on error
*/
- static int getused(struct vol *vol)
+ #define TM_USED_CACHETIME 60 /* cache for 60 seconds */
+ static int get_tm_used(struct vol * restrict vol)
{
- static time_t vol_mtime = 0;
- int ret = 0;
+ EC_INIT;
+ long long int bandsize;
+ VolSpace used = 0;
+ bstring infoplist = NULL;
+ bstring bandsdir = NULL;
+ DIR *dir = NULL;
+ const struct dirent *entry;
+ const char *p;
+ struct stat st;
+ long int links;
time_t now = time(NULL);
- if (!vol_mtime
- || (!vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < now))
- || (vol->v_mtime && ((vol_mtime + GETUSED_CACHETIME) < vol->v_mtime))
- ) {
- vol_mtime = now;
- getused_size = 0;
- vol->v_written = 0;
- ret = nftw(vol->v_path, getused_stat, NULL, 20, FTW_PHYS); /* 2 */
- LOG(log_debug, logtype_afpd, "volparams: from nftw: %" PRIu64 " bytes",
- getused_size);
- } else {
- getused_size += vol->v_written;
- vol->v_written = 0;
- LOG(log_debug, logtype_afpd, "volparams: cached used: %" PRIu64 " bytes",
- getused_size);
+ if (vol->v_tm_cachetime
+ && ((vol->v_tm_cachetime + TM_USED_CACHETIME) >= now)) {
+ if (vol->v_tm_used == -1)
+ EC_FAIL;
+ vol->v_tm_used += vol->v_appended;
+ vol->v_appended = 0;
+ LOG(log_debug, logtype_afpd, "getused(\"%s\"): cached: %" PRIu64 " bytes",
+ vol->v_path, vol->v_tm_used);
+ return 0;
}
- return ret;
+ vol->v_tm_cachetime = now;
+
+ EC_NULL( dir = opendir(vol->v_path) );
+
+ while ((entry = readdir(dir)) != NULL) {
+ if (((p = strstr(entry->d_name, "sparsebundle")) != NULL)
+ && (strlen(entry->d_name) == (p + strlen("sparsebundle") - entry->d_name))) {
+
+ EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") );
+
+ if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1)
+ continue;
+
+ EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") );
+
+ if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1)
+ continue;
+
+ used += (links - 1) * bandsize;
+ LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes",
+ cfrombstr(bandsdir), used);
+ }
+ }
+
+ vol->v_tm_used = used;
+
+ EC_CLEANUP:
+ if (infoplist)
+ bdestroy(infoplist);
+ if (bandsdir)
+ bdestroy(bandsdir);
+ if (dir)
+ closedir(dir);
+
+ LOG(log_debug, logtype_afpd, "getused(\"%s\"): %" PRIu64 " bytes", vol->v_path, vol->v_tm_used);
+
+ EC_EXIT;
}
static int getvolspace(struct vol *vol,
- u_int32_t *bfree, u_int32_t *btotal,
- VolSpace *xbfree, VolSpace *xbtotal, u_int32_t *bsize)
+ uint32_t *bfree, uint32_t *btotal,
+ VolSpace *xbfree, VolSpace *xbtotal, uint32_t *bsize)
{
int spaceflag, rc;
- u_int32_t maxsize;
+ uint32_t maxsize;
VolSpace used;
#ifndef NO_QUOTA_SUPPORT
VolSpace qfree, qtotal;
return( rc );
}
- #define min(a,b) ((a)<(b)?(a):(b))
#ifndef NO_QUOTA_SUPPORT
if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_UQUOTA ) {
if ( uquota_getvolspace( vol, &qfree, &qtotal, *bsize ) == AFP_OK ) {
vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_UQUOTA;
- *xbfree = min(*xbfree, qfree);
- *xbtotal = min( *xbtotal, qtotal);
+ *xbfree = MIN(*xbfree, qfree);
+ *xbtotal = MIN(*xbtotal, qtotal);
goto getvolspace_done;
}
}
getvolspace_done:
if (vol->v_limitsize) {
- if (getused(vol) != 0)
+ if (get_tm_used(vol) != 0)
return AFPERR_MISC;
- LOG(log_debug, logtype_afpd, "volparams: used on volume: %" PRIu64 " bytes",
- getused_size);
- vol->v_tm_used = getused_size;
- *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
- *xbfree = min(*xbfree, *xbtotal < getused_size ? 0 : *xbtotal - getused_size);
+ *xbtotal = MIN(*xbtotal, (vol->v_limitsize * 1024 * 1024));
+ *xbfree = MIN(*xbfree, *xbtotal < vol->v_tm_used ? 0 : *xbtotal - vol->v_tm_used);
+
+ LOG(log_debug, logtype_afpd,
+ "volparams: total: %" PRIu64 ", used: %" PRIu64 ", free: %" PRIu64 " bytes",
+ *xbtotal, vol->v_tm_used, *xbfree);
}
- *bfree = min( *xbfree, maxsize);
- *btotal = min( *xbtotal, maxsize);
+ *bfree = MIN(*xbfree, maxsize);
+ *btotal = MIN(*xbtotal, maxsize);
return( AFP_OK );
}
last = now;
for ( ; vol; vol = vol->v_next ) {
if (vol->v_flags & AFPVOL_TM)
- (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_written);
+ (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_appended);
}
}
}
* set volume creation date
* avoid duplicate, well at least it tries
*/
-static void vol_setdate(u_int16_t id, struct adouble *adp, time_t date)
+static void vol_setdate(uint16_t id, struct adouble *adp, time_t date)
{
struct vol *volume;
struct vol *vol = Volumes;
}
/* ----------------------- */
-static int getvolparams( u_int16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen)
+static int getvolparams( uint16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen)
{
struct adouble ad;
int bit = 0, isad = 1;
- u_int32_t aint;
+ uint32_t aint;
u_short ashort;
- u_int32_t bfree, btotal, bsize;
+ uint32_t bfree, btotal, bsize;
VolSpace xbfree, xbtotal; /* extended bytes */
char *data, *nameoff = NULL;
char *slash;
* .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);
#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 */
case VOLPBIT_NAME :
nameoff = data;
- data += sizeof( u_int16_t );
+ data += sizeof( uint16_t );
break;
case VOLPBIT_BSIZE: /* block size */
}
/* ------------------------- */
-static int stat_vol(u_int16_t bitmap, struct vol *vol, char *rbuf, size_t *rbuflen)
+static int stat_vol(uint16_t bitmap, struct vol *vol, char *rbuf, size_t *rbuflen)
{
struct stat st;
int ret;
if (!S_ISDIR(st.st_mode)) {
continue; /* not a dir */
}
- accessmode(volume->v_path, &ma, NULL, &st);
+ accessmode(volume, volume->v_path, &ma, NULL, &st);
if ((ma.ma_user & (AR_UREAD | AR_USEARCH)) != (AR_UREAD | AR_USEARCH)) {
continue; /* no r-x access */
}
return AFPERR_PARAM;
}
tv.tv_sec = AD_DATE_FROM_UNIX(tv.tv_sec);
- memcpy(data, &tv.tv_sec, sizeof( u_int32_t));
- data += sizeof( u_int32_t);
+ memcpy(data, &tv.tv_sec, sizeof( uint32_t));
+ data += sizeof( uint32_t);
*data = vcnt;
return( AFP_OK );
}
struct dir *dir;
int len, ret;
size_t namelen;
- u_int16_t bitmap;
+ uint16_t bitmap;
char path[ MAXPATHLEN + 1];
char *vol_uname;
char *vol_mname;
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);
}
}
}
-#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 );
int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *vol;
- u_int16_t vid;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
}
/* ------------------------- */
-struct vol *getvolbyvid(const u_int16_t vid )
+struct vol *getvolbyvid(const uint16_t vid )
{
struct vol *vol;
return( NULL );
}
-#ifdef FORCE_UIDGID
- set_uidgid ( vol );
-#endif /* FORCE_UIDGID */
-
current_vol = vol;
return( vol );
int afp_getvolparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,char *rbuf, size_t *rbuflen)
{
struct vol *vol;
- u_int16_t vid, bitmap;
+ uint16_t vid, bitmap;
ibuf += 2;
memcpy(&vid, ibuf, sizeof( vid ));
{
struct adouble ad;
struct vol *vol;
- u_int16_t vid, bitmap;
- u_int32_t aint;
+ uint16_t vid, bitmap;
+ uint32_t aint;
ibuf += 2;
*rbuflen = 0;
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;
{
char *p,*q,*r;
struct adouble ad;
- u_int16_t attr;
+ uint16_t attr;
struct stat st;
int ret;
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);
}
#include <atalk/ea.h>
#include <atalk/util.h>
#include <atalk/acl.h>
+#include <atalk/compat.h>
#include "cmd_dbd.h"
#include "dbif.h"
*/
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);
/* 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));
#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;
}
if ((dp = opendir(".")) == NULL) {
dbd_log(LOGSTD, "Couldn't open the directory '%s/%s': %s",
cwdbuf, ADv2_DIRNAME, strerror(errno));
- return;
+ goto exit;
}
while ((ep = readdir(dp))) {
} /* if */
} /* while */
+ exit:
if (dp)
closedir(dp);
-
+ if ((chdir("..")) != 0) {
+ dbd_log(LOGSTD, "Couldn't chdir to '%s': %s", cwdbuf, strerror(errno));
+ /* we can't proceed */
+ longjmp(jmp, 1); /* this jumps back to cmd_dbd_scanvol() */
+ }
}
/*
/* 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;
}
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 CNID_INVALID;
/* Everything is fine */
return db_cnid;
} else if (ad_cnid && db_cnid && (ad_cnid != db_cnid)) {
- /* Mismatch ? Delete both from db and re-add data from file */
+ /* Mismatch, overwrite ad file with value from db */
dbd_log( LOGSTD, "CNID mismatch for '%s/%s', db: %u, ad-file: %u", cwdbuf, name, ntohl(db_cnid), ntohl(ad_cnid));
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
- rqst.cnid = db_cnid;
- ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
- if (dbif_txn_close(dbd, ret) != 0)
- return CNID_INVALID;
-
- rqst.cnid = ad_cnid;
- ret = dbd_delete(dbd, &rqst, &rply, DBIF_CNID);
- if (dbif_txn_close(dbd, ret) != 0)
- return CNID_INVALID;
-
- ret = dbd_rebuild_add(dbd, &rqst, &rply);
- if (dbif_txn_close(dbd, ret) != 0)
+ dbd_log(LOGSTD, "Updating AppleDouble file for '%s/%s' with CNID: %u from database",
+ 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) {
+ dbd_log(LOGSTD, "Error opening AppleDouble file for '%s/%s': %s",
+ cwdbuf, name, strerror(errno));
return CNID_INVALID;
+ }
+ ad_setid( &ad, st->st_dev, st->st_ino, db_cnid, did, stamp);
+ ad_flush(&ad);
+ ad_close_metadata(&ad);
}
- return ad_cnid;
+ return db_cnid;
} else if (ad_cnid && (db_cnid == 0)) {
/* in ad-file but not in db */
if ( ! (dbd_flags & DBD_FLAGS_SCAN)) {
rqst.cnid = ad_cnid;
ret = dbd_resolve(dbd, &rqst, &rply);
- if (ret == CNID_DBD_RES_OK) {
+ if (rply.result == CNID_DBD_RES_OK) {
/* Occupied! Choose another, update ad-file */
ret = dbd_add(dbd, &rqst, &rply, 1);
if (dbif_txn_close(dbd, ret) != 0)
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 CNID_INVALID;
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 CNID_INVALID;
#include "config.h"
#endif
- #if !defined(__FreeBSD__) && !defined(__NetBSD__)
- #ifndef _XOPEN_SOURCE
- # define _XOPEN_SOURCE 600
- #endif
- #ifndef __EXTENSIONS__
- # define __EXTENSIONS__
- #endif
- #ifndef _GNU_SOURCE
- # define _GNU_SOURCE
- #endif
- #endif
+ #include <atalk/standards.h>
#include <stdio.h>
#include <stdlib.h>
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)
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);
}
/* 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);
#include <stdio.h>
#include <string.h>
+#include <arpa/inet.h>
+
#include <atalk/logger.h>
-#include <netatalk/endian.h>
#include <atalk/cnid_dbd_private.h>
-
#include "pack.h"
#include "dbif.h"
#include "dbd.h"
return -1;
}
+ LOG(log_debug, logtype_cnid,
+ "dbd_rebuild_add(CNID: %u, did: %u, name: \"%s\", dev/ino:0x%llx/0x%llx): success",
+ ntohl(rqst->cnid), ntohl(rqst->did), rqst->name,
+ (unsigned long long)rqst->dev, (unsigned long long)rqst->ino);
+
key.data = ROOTINFO_KEY;
key.size = ROOTINFO_KEYLEN;
#include <string.h>
#include <atalk/logger.h>
#include <errno.h>
-#include <netatalk/endian.h>
+#include <arpa/inet.h>
+
#include <atalk/cnid_dbd_private.h>
#include "dbif.h"
rply->namelen = data.size;
rply->name = (char *)data.data;
- LOG(log_debug, logtype_cnid, "dbd_resolve: Resolving CNID %u to did %u name %s",
- ntohl(rqst->cnid), ntohl(rply->did), rply->name);
+ LOG(log_debug, logtype_cnid, "dbd_resolve(CNID: %u): did: %u, name: \"%s\"",
+ ntohl(rqst->cnid), ntohl(rply->did), rply->name + CNID_NAME_OFS);
rply->result = CNID_DBD_RES_OK;
return 1;
static gcry_mpi_t serverNonce;
static char *K_MD5hash = NULL;
static int K_hash_len;
-static u_int16_t ID;
+static uint16_t ID;
/* The initialization vectors for CAST128 are fixed by Apple. */
static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' };
/* Session ID first */
ID = dhxhash(obj);
- *(u_int16_t *)rbuf = htons(ID);
+ *(uint16_t *)rbuf = htons(ID);
rbuf += 2;
*rbuflen += 2;
*rbuflen += 4;
/* len = length of p = PRIMEBITS/8 */
- *(u_int16_t *)rbuf = htons((u_int16_t) PRIMEBITS/8);
+ *(uint16_t *)rbuf = htons((uint16_t) PRIMEBITS/8);
rbuf += 2;
*rbuflen += 2;
{
char *username;
size_t len, ulen;
- u_int16_t temp16;
+ uint16_t temp16;
*rbuflen = 0;
/* ---- Start building reply packet ---- */
/* Session ID + 1 first */
- *(u_int16_t *)rbuf = htons(ID+1);
+ *(uint16_t *)rbuf = htons(ID+1);
rbuf += 2;
*rbuflen += 2;
return ret;
}
- static int logincont2(void *obj, struct passwd **uam_pwd,
+ /**
+ * Try to authenticate via PAM as "adminauthuser"
+ **/
+ static int loginasroot(const char *adminauthuser, const char **hostname, int status)
+ {
+ int PAM_error;
+
+ if ((PAM_error = pam_end(pamh, status)) != PAM_SUCCESS)
+ goto exit;
+ pamh = NULL;
+
+ if ((PAM_error = pam_start("netatalk", adminauthuser, &PAM_conversation, &pamh)) != PAM_SUCCESS) {
+ LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error));
+ goto exit;
+ }
+
+ /* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
+ pam_set_item(pamh, PAM_TTY, "afpd");
+ pam_set_item(pamh, PAM_RHOST, *hostname);
+ if ((PAM_error = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
+ goto exit;
+
+ LOG(log_warning, logtype_uams, "DHX2: Authenticated as \"%s\"", adminauthuser);
+
+ exit:
+ return PAM_error;
+ }
+
+ static int logincont2(void *obj_in, struct passwd **uam_pwd,
char *ibuf, size_t ibuflen,
char *rbuf _U_, size_t *rbuflen)
{
- int ret;
+ AFPObj *obj = obj_in;
+ int ret = AFPERR_MISC;
int PAM_error;
const char *hostname = NULL;
gcry_mpi_t retServerNonce;
gcry_cipher_hd_t ctx;
gcry_error_t ctxerror;
+ char *utfpass = NULL;
*rbuflen = 0;
/* ---- Start authentication with PAM --- */
+ /* The password is in legacy Mac encoding, convert it to host encoding */
+ if (convert_string_allocate(CH_MAC, CH_UNIX, ibuf, -1, &utfpass) == (size_t)-1) {
+ LOG(log_error, logtype_uams, "DHX2: conversion error");
+ goto error_ctx;
+ }
+ PAM_password = utfpass;
+
+ #ifdef DEBUG
+ LOG(log_maxdebug, logtype_default, "DHX2: password: %s", PAM_password);
+ #endif
+
/* Set these things up for the conv function */
- PAM_password = ibuf;
ret = AFPERR_NOTAUTH;
PAM_error = pam_start("netatalk", PAM_username, &PAM_conversation, &pamh);
if (PAM_error != PAM_SUCCESS) {
- LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
- pam_strerror(pamh,PAM_error));
+ LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh,PAM_error));
goto error_ctx;
}
/* solaris craps out if PAM_TTY and PAM_RHOST aren't set. */
pam_set_item(pamh, PAM_TTY, "afpd");
pam_set_item(pamh, PAM_RHOST, hostname);
+
PAM_error = pam_authenticate(pamh, 0);
if (PAM_error != PAM_SUCCESS) {
if (PAM_error == PAM_MAXTRIES)
ret = AFPERR_PWDEXPR;
- LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s",
- pam_strerror(pamh, PAM_error));
- goto error_ctx;
+ LOG(log_info, logtype_uams, "DHX2: PAM_Error: %s", pam_strerror(pamh, PAM_error));
+
+ if (!obj->options.adminauthuser)
+ goto error_ctx;
+ if (loginasroot(obj->options.adminauthuser, &hostname, PAM_error) != PAM_SUCCESS) {
+ goto error_ctx;
+ }
}
PAM_error = pam_acct_mgmt(pamh, 0);
else if (PAM_error == PAM_AUTHTOKEN_REQD)
ret = AFPERR_PWDCHNG;
#endif
- else
- goto error_ctx;
+ goto error_ctx;
}
#ifndef PAM_CRED_ESTABLISH
}
memset(ibuf, 0, 256); /* zero out the password */
+ if (utfpass)
+ memset(utfpass, 0, strlen(utfpass));
*uam_pwd = dhxpwd;
LOG(log_info, logtype_uams, "DHX2: PAM Auth OK!");
- if ( ret == AFPERR_PWDEXPR)
- return ret;
+
ret = AFP_OK;
error_ctx:
gcry_cipher_close(ctx);
error_noctx:
+ if (utfpass) free(utfpass);
free(K_MD5hash);
K_MD5hash=NULL;
gcry_mpi_release(serverNonce);
char *ibuf, size_t ibuflen,
char *rbuf, size_t *rbuflen)
{
- u_int16_t retID;
+ uint16_t retID;
int ret;
/* check for session id */
- retID = ntohs(*(u_int16_t *)ibuf);
+ retID = ntohs(*(uint16_t *)ibuf);
if (retID == ID)
ret = logincont1(obj, ibuf, ibuflen, rbuf, rbuflen);
else if (retID == ID+1)
#ifdef UAM_DHX2
+ #include <atalk/standards.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pwd.h>
-
-#ifdef HAVE_UNISTD_H
+#include <arpa/inet.h>
#include <unistd.h>
-#endif
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
-#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif
-
-#ifdef HAVE_TIME_H
#include <time.h>
-#endif
#ifdef SHADOWPW
#include <shadow.h>
static gcry_mpi_t serverNonce;
static char *K_MD5hash = NULL;
static int K_hash_len;
-static u_int16_t ID;
+static uint16_t ID;
/* The initialization vectors for CAST128 are fixed by Apple. */
static unsigned char dhx_c2siv[] = { 'L', 'W', 'a', 'l', 'l', 'a', 'c', 'e' };
/* Session ID first */
ID = dhxhash(obj);
- *(u_int16_t *)rbuf = htons(ID);
+ *(uint16_t *)rbuf = htons(ID);
rbuf += 2;
*rbuflen += 2;
*rbuflen += 4;
/* len = length of p = PRIMEBITS/8 */
- *(u_int16_t *)rbuf = htons((u_int16_t) PRIMEBITS/8);
+ *(uint16_t *)rbuf = htons((uint16_t) PRIMEBITS/8);
rbuf += 2;
*rbuflen += 2;
{
char *username;
size_t len, ulen;
- u_int16_t temp16;
+ uint16_t temp16;
*rbuflen = 0;
/* ---- Start building reply packet ---- */
/* Session ID + 1 first */
- *(u_int16_t *)rbuf = htons(ID+1);
+ *(uint16_t *)rbuf = htons(ID+1);
rbuf += 2;
*rbuflen += 2;
char *ibuf, size_t ibuflen,
char *rbuf, size_t *rbuflen)
{
- u_int16_t retID;
+ uint16_t retID;
int ret;
/* check for session id */
- retID = ntohs(*(u_int16_t *)ibuf);
+ retID = ntohs(*(uint16_t *)ibuf);
if (retID == ID)
ret = logincont1(obj, uam_pwd, ibuf, ibuflen, rbuf, rbuflen);
else if (retID == ID+1)
/*
- * $Id: uams_dhx_passwd.c,v 1.29 2010-03-30 12:44:35 franklahm Exp $
- *
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
* All Rights Reserved. See COPYRIGHT.
#include "config.h"
#endif /* HAVE_CONFIG_H */
- #ifdef NETBSD
- #define _XOPEN_SOURCE 500 /* for crypt() */
- #endif
- #ifdef FREEBSD
- #define _XOPEN_SOURCE /* for crypt() */
- #endif
+ #include <atalk/standards.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif /* ! HAVE_CRYPT_H */
-#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif
-#ifdef HAVE_TIME_H
#include <time.h>
-#endif
#include <pwd.h>
+#include <arpa/inet.h>
+
#ifdef SHADOWPW
#include <shadow.h>
#endif /* SHADOWPW */
+
#if defined(GNUTLS_DHX)
#include <gnutls/openssl.h>
#elif defined(OPENSSL_DHX)
/* the secret key */
static CAST_KEY castkey;
static struct passwd *dhxpwd;
-static u_int8_t randbuf[16];
+static uint8_t randbuf[16];
#ifdef TRU64
#include <sia.h>
char *rbuf, size_t *rbuflen)
{
unsigned char iv[] = "CJalbert";
- u_int8_t p[] = {0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4,
+ uint8_t p[] = {0xBA, 0x28, 0x73, 0xDF, 0xB0, 0x60, 0x57, 0xD4,
0x3F, 0x20, 0x24, 0x74, 0x4C, 0xEE, 0xE7, 0x5B };
- u_int8_t g = 0x07;
+ uint8_t g = 0x07;
#ifdef SHADOWPW
struct spwd *sp;
#endif /* SHADOWPW */
BIGNUM *bn, *gbn, *pbn;
- u_int16_t sessid;
+ uint16_t sessid;
size_t i;
DH *dh;
{
char *username;
size_t len, ulen;
- u_int16_t temp16;
+ uint16_t temp16;
*rbuflen = 0;
#endif /* SHADOWPW */
unsigned char iv[] = "LWallace";
BIGNUM *bn1, *bn2, *bn3;
- u_int16_t sessid;
+ uint16_t sessid;
char *p;
int err = AFPERR_NOTAUTH;
/*
- * $Id: uams_passwd.c,v 1.31 2010-03-30 12:44:35 franklahm Exp $
- *
* Copyright (c) 1990,1993 Regents of The University of Michigan.
* Copyright (c) 1999 Adrian Sun (asun@u.washington.edu)
* All Rights Reserved. See COPYRIGHT.
#include <config.h>
#endif /* HAVE_CONFIG_H */
- #include <sys/types.h>
- /* crypt needs _XOPEN_SOURCE (500) at least on BSD, but that breaks Solaris compile */
- #ifdef NETBSD
- #define _XOPEN_SOURCE 500 /* for crypt() */
- #endif
- #ifdef FREEBSD
- #define _XOPEN_SOURCE /* for crypt() */
- #endif
+ #include <atalk/standards.h>
+ #include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
-/* STDC check */
-#if STDC_HEADERS
#include <string.h>
-#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_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif /* ! HAVE_CRYPT_H */
#include <pwd.h>
-#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif
-#ifdef HAVE_TIME_H
#include <time.h>
-#endif
#ifdef SHADOWPW
#include <shadow.h>
#endif /* SHADOWPW */
+#include <arpa/inet.h>
#include <atalk/afp.h>
#include <atalk/logger.h>
#include <atalk/uam.h>
#include <atalk/util.h>
+#include <atalk/compat.h>
#define PASSWDLEN 8
{
char *username;
size_t len, ulen;
- u_int16_t temp16;
+ uint16_t temp16;
*rbuflen = 0;
#ifdef UAM_PGP
- /* for crypt() */
- #define _XOPEN_SOURCE
+ #include <atalk/standards.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* the secret key */
static struct passwd *pgppwd;
static CAST_KEY castkey;
-static u_int8_t randbuf[16];
+static uint8_t randbuf[16];
/* pgp passwd */
static int pgp_login(void *obj, struct passwd **uam_pwd,
{
unsigned char iv[] = "RJscorat";
BIGNUM *bn1, *bn2, *bn3;
- u_int16_t sessid;
+ uint16_t sessid;
char *p;
*rbuflen = 0;
# Makefile.am for include/atalk/
atalkincludedir = $(includedir)/atalk
+
atalkinclude_HEADERS = \
- adouble.h vfs.h aep.h afp.h asp.h atp.h \
- cnid.h compat.h ddp.h dsi.h ldapconfig.h list.h logger.h \
- nbp.h netddp.h pap.h paths.h queue.h rtmp.h server_child.h \
- server_ipc.h tdb.h uam.h unicode.h util.h uuid.h volinfo.h \
- zip.h ea.h acl.h unix.h directory.h hash.h volume.h
+ adouble.h \
+ afp.h \
+ vfs.h \
+ cnid.h \
+ locking.h \
+ logger.h \
+ paths.h \
+ unicode.h \
+ util.h \
+ volinfo.h \
+ ea.h \
+ acl.h \
+ unix.h \
+ volume.h
+
+noinst_HEADERS = \
+ directory.h \
+ hash.h \
+ zip.h \
+ uuid.h \
+ queue.h \
+ server_child.h \
+ server_ipc.h \
+ tdb.h \
+ uam.h \
+ cnid_dbd_private.h \
+ cnid_private.h \
+ bstradd.h \
+ bstrlib.h \
+ errchk.h \
+ ftw.h \
+ talloc.h \
+ tevent.h \
+ tsocket.h \
+ boolean.h \
+ compat.h \
+ dsi.h \
+ ldapconfig.h \
+ list.h \
+ globals.h \
- fce_api.h
++ fce_api.h \
++ standards.h
-noinst_HEADERS = cnid_dbd_private.h cnid_private.h bstradd.h bstrlib.h errchk.h ftw.h globals.h fce_api.h standards.h
+BUILT_SOURCES = lockrpc.gen.h
+EXTRADIST = lockrpc.gen.h
+lockrpc.gen.h: $(top_srcdir)/libevent/event_rpcgen.py $(top_srcdir)/libatalk/rpc/lockrpc.rpc
+ cd $(top_srcdir)/libatalk/rpc/ \
+ && $(top_srcdir)/libevent/event_rpcgen.py lockrpc.rpc \
+ && mv lockrpc.gen.h $(top_srcdir)/include/atalk
/*
- * $Id: adouble.h,v 1.55 2010-03-30 12:55:26 franklahm Exp $
* Copyright (c) 1990,1991 Regents of The University of Michigan.
* All Rights Reserved.
*
#include <config.h>
#endif
+ #include <atalk/standards.h>
+
+#include <inttypes.h>
#include <sys/types.h>
#include <sys/stat.h>
-
-#ifdef HAVE_UNISTD_H
-#undef __USE_MISC
-#define __USE_MISC
#include <unistd.h>
-#endif
-
-#include <sys/cdefs.h>
-
-#ifdef HAVE_FCNTL_H
#include <fcntl.h>
-#endif
#include <sys/mman.h>
-#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
-#endif
-#include <netatalk/endian.h>
-/* version info */
-#define AD_VERSION1 0x00010000
-#define SFM_VERSION AD_VERSION1
+#include <atalk/bstrlib.h>
+#include <atalk/locking.h>
+/* version info */
#define AD_VERSION2 0x00020000
-#define AD_VERSION2_OSX 0x00020001
-/*
- #define AD_VERSION1_ADS 0x00010002
-*/
-#define AD_VERSION1_SFM 0x00010003
+#define AD_VERSION_EA 0x00020002
+
+/* default */
#define AD_VERSION AD_VERSION2
/*
*/
#define ADEID_DFORK 1
#define ADEID_RFORK 2
-#define ADEID_NAME 3 /* Note: starting with Netatalk 2.1 we do NOT alway set the name */
+#define ADEID_NAME 3
#define ADEID_COMMENT 4
#define ADEID_ICONBW 5
#define ADEID_ICONCOL 6
#define ADEID_AFPFILEI 14 /* where the rest of the FILEI info goes */
#define ADEID_DID 15
-#if AD_VERSION == AD_VERSION1
-#define ADEID_MAX 16
-#else
/* netatalk private note fileid reused DID */
#define ADEID_PRIVDEV 16
#define ADEID_PRIVINO 17
#define ADEID_PRIVSYN 18 /* in synch with database */
#define ADEID_PRIVID 19
-#define ADEID_SFMRESERVE1 20
-#define ADEID_SFMRESERVE2 21
+#define ADEID_MAX (ADEID_PRIVID + 1)
+/* These are the real ids for these entries, as stored in the adouble file */
#define AD_DEV 0x80444556
#define AD_INO 0x80494E4F
#define AD_SYN 0x8053594E
#define AD_ID 0x8053567E
-#define ADEID_MAX 22
-#endif
/* magic */
#define AD_APPLESINGLE_MAGIC 0x00051600
#define AD_APPLEDOUBLE_MAGIC 0x00051607
#define AD_MAGIC AD_APPLEDOUBLE_MAGIC
-#define SFM_MAGIC 0x00504641
/* sizes of relevant entry bits */
#define ADEDLEN_MAGIC 4
#define ADEDLEN_VERSION 4
#define ADEDLEN_FILLER 16
#define ADEDLEN_NENTRIES 2
-
-/* 26 */
-#define AD_HEADER_LEN (ADEDLEN_MAGIC + ADEDLEN_VERSION + \
- ADEDLEN_FILLER + ADEDLEN_NENTRIES)
+#define AD_HEADER_LEN (ADEDLEN_MAGIC + ADEDLEN_VERSION + ADEDLEN_FILLER + ADEDLEN_NENTRIES)
#define AD_ENTRY_LEN 12 /* size of a single entry header */
-/* v1 field widths */
-#define ADEDLEN_NAME 255
-#define ADEDLEN_COMMENT 200
-#define ADEDLEN_FILEI 16
-#define ADEDLEN_FINDERI 32
-
-/* v2 field widths */
+/* field widths */
+#define ADEDLEN_NAME 255
+#define ADEDLEN_COMMENT 200
+#define ADEDLEN_FILEI 16
+#define ADEDLEN_FINDERI 32
#define ADEDLEN_FILEDATESI 16
#define ADEDLEN_SHORTNAME 12 /* length up to 8.3 */
#define ADEDLEN_AFPFILEI 4
#define ADEDLEN_PRIVSYN 8
#define ADEDLEN_PRIVID 4
-#define ADEID_NUM_V1 5
#define ADEID_NUM_V2 13
+#define ADEID_NUM_EA 5
-// #define ADEID_NUM_SFM 5
-/* sizeof SFM meta data */
-#define AD_SFM_LEN 60
-
-/* 589 */
-#define AD_DATASZ1 (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT + ADEDLEN_FILEI + ADEDLEN_FINDERI + \
- (ADEID_NUM_V1 * AD_ENTRY_LEN))
-
-#if AD_DATASZ1 != 589
-#error bad size for AD_DATASZ1
-#endif
-
-#define AD_NEWSZ2 (ADEDLEN_DID + ADEDLEN_AFPFILEI + ADEDLEN_SHORTNAME + ADEDLEN_PRODOSFILEI \
- + ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + ADEDLEN_PRIVSYN + ADEDLEN_PRIVID)
-
-/* 725 */
-#define AD_DATASZ2 (AD_DATASZ1 + AD_NEWSZ2 + ((ADEID_NUM_V2 - ADEID_NUM_V1) * AD_ENTRY_LEN))
-
+#define AD_DATASZ2 (AD_HEADER_LEN + ADEDLEN_NAME + ADEDLEN_COMMENT + ADEDLEN_FILEI + \
+ ADEDLEN_FINDERI + ADEDLEN_DID + ADEDLEN_AFPFILEI + ADEDLEN_SHORTNAME + \
+ ADEDLEN_PRODOSFILEI + ADEDLEN_PRIVDEV + ADEDLEN_PRIVINO + \
+ ADEDLEN_PRIVSYN + ADEDLEN_PRIVID + (ADEID_NUM_V2 * AD_ENTRY_LEN))
#if AD_DATASZ2 != 741
#error bad size for AD_DATASZ2
#endif
-#define AD_DATASZ_MAX 1024
-#if AD_VERSION == AD_VERSION1
-#define AD_DATASZ AD_DATASZ1 /* hold enough for the entries */
-#elif AD_VERSION == AD_VERSION2
-#define AD_DATASZ AD_DATASZ2
+#define AD_DATASZ_EA (AD_HEADER_LEN + (ADEID_NUM_EA * AD_ENTRY_LEN) + ADEDLEN_FINDERI + \
+ ADEDLEN_COMMENT + ADEDLEN_FILEDATESI + ADEDLEN_AFPFILEI + ADEDLEN_PRIVID)
+
+#if AD_DATASZ_EA != 342
+#error bad size for AD_DATASZ_EA
#endif
-/*
- * some legacy defines from netatalk-990130
- * (to keep from breaking certain packages)
- *
- */
+#define AD_DATASZ_MAX 1024
-#define ADEDOFF_RFORK 589
-#define ADEDOFF_NAME 86
-#define ADEDOFF_COMMENT 341
-#define ADEDOFF_FINDERI 557
-#ifndef ADEDOFF_FILEI
-#define ADEDOFF_FILEI 541
+#if AD_VERSION == AD_VERSION2
+#define AD_DATASZ AD_DATASZ2
+#elif AD_VERSION == AD_VERSION_EA
+#define AD_DATASZ AD_DATASZ_EA
#endif
-typedef u_int32_t cnid_t;
+#define RFORK_EA_ALLOCSIZE (128*1024) /* 128k */
-/*
- * The header of the AppleDouble Header File looks like this:
- *
- * NAME SIZE
- * ==== ====
- * Magic 4
- * Version 4
- * Home File System 16 (this becomes filler in ad v2)
- * Number of Entries 2
- * Entry Descriptors for each entry:
- * Entry ID 4
- * Offset 4
- * Length 4
- */
+typedef uint32_t cnid_t;
struct ad_entry {
- off_t ade_off;
+ off_t ade_off;
ssize_t ade_len;
};
struct ad_fd {
int adf_fd; /* -1: invalid, -2: symlink */
-
#ifndef HAVE_PREAD
off_t adf_off;
#endif
-
char *adf_syml;
int adf_flags;
int adf_excl;
+#if 0
adf_lock_t *adf_lock;
int adf_refcount, adf_lockcount, adf_lockmax;
+#endif
};
/* some header protection */
#define AD_INITED 0xad494e54 /* ad"INT" */
-struct adouble_fops;
-
-struct adouble {
- u_int32_t ad_magic;
- u_int32_t ad_version;
- char ad_filler[ 16 ];
- struct ad_entry ad_eid[ ADEID_MAX ];
- struct ad_fd ad_data_fork, ad_resource_fork, ad_metadata_fork;
- struct ad_fd *ad_md; /* either ad_resource or ad_metadata */
-
- int ad_flags; /* This really stores version info too (AD_VERSION*) */
- int ad_adflags; /* ad_open flags adflags like ADFLAGS_DIR */
- unsigned int ad_inited;
- int ad_options;
- int ad_fileordir;
- int ad_refcount; /* used in afpd/ofork.c */
- off_t ad_rlen; /* ressource fork len with AFP 3.0
- the header parameter size is too small.
- */
- char *ad_m_name; /* mac name for open fork */
- int ad_m_namelen;
- struct adouble_fops *ad_ops;
- u_int16_t ad_open_forks; /* open forks (by others) */
+#define AD_CLOSED 0xadc10ced
-#ifdef USE_MMAPPED_HEADERS
- char *ad_data;
-#else
- char ad_data[AD_DATASZ_MAX];
-#endif
-};
+struct adouble;
struct adouble_fops {
- char *(*ad_path)(const char *, int);
- int (*ad_mkrf)(char *);
+ const char *(*ad_path)(const char *, int);
+ int (*ad_mkrf)(const char *);
int (*ad_rebuild_header)(struct adouble *);
- int (*ad_check_header)(struct adouble *, struct stat *);
int (*ad_header_read)(struct adouble *, struct stat *);
- int (*ad_header_upgrade)(struct adouble *, char *);
+ int (*ad_header_upgrade)(struct adouble *, const char *);
+};
+
+struct adouble {
+ uint32_t ad_magic; /* Official adouble magic */
+ uint32_t ad_version; /* Official adouble version number */
+ char ad_filler[16];
+ struct ad_entry ad_eid[ADEID_MAX];
+ struct ad_fd ad_data_fork; /* the data fork */
+ struct ad_fd ad_resource_fork; /* adouble:v2 -> the adouble file *
+ * adouble:ea -> the rfork EA */
+ struct ad_fd ad_metadata_fork; /* adouble:v2 -> unused *
+ * adouble:ea -> the metadata EA */
+ struct ad_fd *ad_md; /* either ad_resource or ad_metadata */
+ int ad_flags; /* Our adouble version info (AD_VERSION*) */
+ int ad_adflags; /* ad_open flags adflags like ADFLAGS_DIR */
+ uint32_t ad_inited;
+ int ad_options;
+ int ad_refcount; /* multiple forks may open one adouble */
+ void *ad_resforkbuf; /* buffer for AD_VERSION_EA ressource fork */
+ size_t ad_resforkbufsize; /* size of ad_resforkbuf */
+ off_t ad_rlen; /* ressource fork len with AFP 3.0 *
+ * the header parameter size is too small. */
+ char *ad_m_name; /* mac name for open fork */
+ int ad_m_namelen;
+ bstring ad_fullpath; /* fullpath of file, adouble:ea need this */
+ struct adouble_fops *ad_ops;
+ uint16_t ad_open_forks; /* open forks (by others) */
+ char ad_data[AD_DATASZ_MAX];
};
#define ADFLAGS_DF (1<<0)
-#define ADFLAGS_HF (1<<1)
-#define ADFLAGS_DIR (1<<2)
-/*
-#define ADFLAGS_NOADOUBLE (1<<3)
-*/
-#define ADFLAGS_V1COMPAT (1<<4)
-#define ADFLAGS_NOHF (1<<5) /* not an error if no ressource fork */
-#define ADFLAGS_RDONLY (1<<6) /* don't try readwrite */
-#define ADFLAGS_OPENFORKS (1<<7) /* check for open fork in ad_metadata function */
-#define ADFLAGS_RF (1<<8)
-#define ADFLAGS_MD ADFLAGS_HF /* (1<<9) */
-#define ADFLAGS_CREATE (1<<9)
-
-/* adouble v2 cnid cache */
+#define ADFLAGS_RF (1<<1)
+#define ADFLAGS_HF (1<<2)
+#define ADFLAGS_DIR (1<<3)
+#define ADFLAGS_NOHF (1<<4) /* not an error if no ressource fork */
+#define ADFLAGS_CHECK_OF (1<<6) /* check for open forks from us and other afpd's */
+
#define ADVOL_NODEV (1 << 0)
#define ADVOL_CACHE (1 << 1)
#define ADVOL_UNIXPRIV (1 << 2) /* adouble unix priv */
#define ad_getentryoff(ad,eid) ((ad)->ad_eid[(eid)].ade_off)
#define ad_entry(ad,eid) ((caddr_t)(ad)->ad_data + (ad)->ad_eid[(eid)].ade_off)
-#define ad_get_HF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
+#define ad_get_RF_flags(ad) ((ad)->ad_resource_fork.adf_flags)
#define ad_get_MD_flags(ad) ((ad)->ad_md->adf_flags)
+/* Refcounting open forks using one struct adouble */
+#define ad_ref(ad) (ad)->ad_refcount++
+#define ad_unref(ad) --((ad)->ad_refcount)
+
/* ad_flush.c */
extern int ad_rebuild_adouble_header (struct adouble *);
extern int ad_rebuild_sfm_header (struct adouble *);
extern int ad_close (struct adouble *, int);
/* ad_lock.c */
-extern int ad_fcntl_lock (struct adouble *, const u_int32_t /*eid*/,
- const int /*type*/, const off_t /*offset*/,
- const off_t /*len*/, const int /*user*/);
-extern void ad_fcntl_unlock (struct adouble *, const int /*user*/);
-extern int ad_fcntl_tmplock (struct adouble *, const u_int32_t /*eid*/,
- const int /*type*/, const off_t /*offset*/,
- const off_t /*len*/, const int /*user*/);
-extern int ad_testlock (struct adouble * /*adp*/, int /*eid*/, off_t /*off*/);
-
-extern u_int16_t ad_openforks (struct adouble * /*adp*/, u_int16_t);
-extern int ad_excl_lock (struct adouble * /*adp*/, const u_int32_t /*eid*/);
-
-#define ad_lock ad_fcntl_lock
-#define ad_tmplock ad_fcntl_tmplock
-#define ad_unlock ad_fcntl_unlock
+extern int ad_testlock (struct adouble *adp, int eid, off_t off);
+extern uint16_t ad_openforks(struct adouble *adp, uint16_t);
+extern int ad_excl_lock (struct adouble *adp, uint32_t eid);
+
+extern int ad_lock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
+extern void ad_unlock(struct adouble *, int user);
+extern int ad_tmplock(struct adouble *, uint32_t eid, int type, off_t off, off_t len, int user);
/* ad_open.c */
+extern const char *oflags2logstr(int oflags);
+extern const char *adflags2logstr(int adflags);
extern int ad_setfuid (const uid_t );
extern uid_t ad_getfuid (void );
extern char *ad_dir (const char *);
-extern char *ad_path (const char *, int);
-extern char *ad_path_osx (const char *, int);
-extern char *ad_path_ads (const char *, int);
-extern char *ad_path_sfm (const char *, int);
+extern const char *ad_path (const char *, int);
+extern const char *ad_path_ea (const char *, int);
extern int ad_mode (const char *, int);
extern int ad_mkdir (const char *, int);
extern void ad_init (struct adouble *, int, int );
-extern int ad_open (const char *, int, int, int, struct adouble *);
-extern int ad_openat (int dirfd, const char *, int, int, int, struct adouble *);
+extern int ad_open (struct adouble *ad, const char *path, int adflags, ...);
+extern int ad_openat (struct adouble *, int dirfd, const char *path, int adflags, ...);
extern int ad_refresh (struct adouble *);
extern int ad_stat (const char *, struct stat *);
extern int ad_metadata (const char *, int, struct adouble *);
extern int ad_metadataat (int, const char *, int, struct adouble *);
+#if 0
#define ad_open_metadata(name, flags, mode, adp)\
- ad_open(name, ADFLAGS_MD|(flags), O_RDWR |(mode), 0666, (adp))
+ ad_open(name, ADFLAGS_HF | (flags), O_RDWR |(mode), 0666, (adp))
+#endif
-#define ad_close_metadata(adp) ad_close( (adp), ADFLAGS_MD)
+#define ad_close_metadata(adp) ad_close( (adp), ADFLAGS_HF)
/* build a resource fork mode from the data fork mode:
* remove X mode and extend header to RW if R or W (W if R for locking),
return mode;
}
-/* ad_ea.c */
-ssize_t sys_getxattr (const char *path, const char *name, void *value, size_t size);
-ssize_t sys_lgetxattr (const char *path, const char *name, void *value, size_t size);
-ssize_t sys_fgetxattr (int filedes, const char *name, void *value, size_t size);
-ssize_t sys_listxattr (const char *path, char *list, size_t size);
-ssize_t sys_llistxattr (const char *path, char *list, size_t size);
-ssize_t sys_flistxattr (int filedes, char *list, size_t size);
-int sys_removexattr (const char *path, const char *name);
-int sys_lremovexattr (const char *path, const char *name);
-int sys_fremovexattr (int filedes, const char *name);
-int sys_setxattr (const char *path, const char *name, const void *value, size_t size, int flags);
-int sys_lsetxattr (const char *path, const char *name, const void *value, size_t size, int flags);
-int sys_fsetxattr (int filedes, const char *name, const void *value, size_t size, int flags);
-int sys_copyxattr (const char *src, const char *dst);
-
/* ad_read.c/ad_write.c */
extern int sys_ftruncate(int fd, off_t length);
-
-extern ssize_t ad_read (struct adouble *, const u_int32_t,
- const off_t, char *, const size_t);
-extern ssize_t ad_pread (struct ad_fd *, void *, size_t, off_t);
-extern ssize_t ad_write (struct adouble *, const u_int32_t, off_t,
- const int, const char *, const size_t);
-extern ssize_t adf_pread (struct ad_fd *, void *, size_t, off_t);
-extern ssize_t adf_pwrite (struct ad_fd *, const void *, size_t, off_t);
-extern int ad_dtruncate (struct adouble *, const off_t);
-extern int ad_rtruncate (struct adouble *, const off_t);
+extern ssize_t ad_read(struct adouble *, uint32_t, off_t, char *, size_t);
+extern ssize_t ad_pread(struct ad_fd *, void *, size_t, off_t);
+extern ssize_t ad_write(struct adouble *, uint32_t, off_t, int, const char *, size_t);
+extern ssize_t adf_pread(struct ad_fd *, void *, size_t, off_t);
+extern ssize_t adf_pwrite(struct ad_fd *, const void *, size_t, off_t);
+extern int ad_dtruncate(struct adouble *, off_t);
+extern int ad_rtruncate(struct adouble *, off_t);
/* ad_size.c */
-extern off_t ad_size (const struct adouble *, const u_int32_t );
+extern off_t ad_size (const struct adouble *, uint32_t );
/* ad_mmap.c */
-extern void *ad_mmapread (struct adouble *, const u_int32_t,
- const off_t, const size_t);
-extern void *ad_mmapwrite (struct adouble *, const u_int32_t,
- const off_t, const int, const size_t);
+extern void *ad_mmapread(struct adouble *, uint32_t, off_t, size_t);
+extern void *ad_mmapwrite(struct adouble *, uint32_t, off_t, int, size_t);
#define ad_munmap(buf, len) (munmap((buf), (len)))
/* ad_date.c */
-extern int ad_setdate (struct adouble *, unsigned int, u_int32_t);
-extern int ad_getdate (const struct adouble *, unsigned int, u_int32_t *);
+extern int ad_setdate(struct adouble *, unsigned int, uint32_t);
+extern int ad_getdate(const struct adouble *, unsigned int, uint32_t *);
/* ad_attr.c */
-extern int ad_setattr (const struct adouble *, const u_int16_t);
-extern int ad_getattr (const struct adouble *, u_int16_t *);
-
-/* Note: starting with Netatalk 2.1 we do NOT alway set the name */
-extern int ad_setname (struct adouble *, const char *);
-
-#if AD_VERSION == AD_VERSION2
-extern int ad_setid (struct adouble *, const dev_t dev,const ino_t ino, const u_int32_t, const u_int32_t, const void *);
-extern u_int32_t ad_getid (struct adouble *, const dev_t, const ino_t, const cnid_t, const void *);
-extern u_int32_t ad_forcegetid (struct adouble *adp);
-#else
-#define ad_setid(a, b, c)
-#endif
+extern int ad_setattr(const struct adouble *, uint16_t);
+extern int ad_getattr(const struct adouble *, uint16_t *);
+extern int ad_setname(struct adouble *, const char *);
+extern int ad_setid(struct adouble *, dev_t dev, ino_t ino, uint32_t, uint32_t, const void *);
+extern uint32_t ad_getid(struct adouble *, dev_t, ino_t, cnid_t, const void *);
+extern uint32_t ad_forcegetid(struct adouble *adp);
#ifdef WITH_SENDFILE
-extern int ad_readfile_init(const struct adouble *ad,
- const int eid, off_t *off,
- const int end);
+extern int ad_readfile_init(const struct adouble *ad, int eid, off_t *off, int end);
#endif
#if 0
#ifdef HAVE_SENDFILE_WRITE
-extern ssize_t ad_writefile (struct adouble *, const int,
- const int, off_t, const int, const size_t);
+extern ssize_t ad_writefile(struct adouble *, int, int, off_t, int, size_t);
#endif /* HAVE_SENDFILE_WRITE */
#endif /* 0 */
#ifndef _ATALK_DSI_H
#define _ATALK_DSI_H
-#include <sys/cdefs.h>
#include <sys/types.h>
#include <sys/time.h>
-#include <signal.h>
#include <sys/socket.h>
+#include <signal.h>
+#include <arpa/inet.h>
#include <netinet/in.h>
#include <atalk/afp.h>
#include <atalk/server_child.h>
#include <atalk/globals.h>
-#include <netatalk/endian.h>
-
/* What a DSI packet looks like:
0 32
#define DSI_BLOCKSIZ 16
struct dsi_block {
- u_int8_t dsi_flags; /* packet type: request or reply */
- u_int8_t dsi_command; /* command */
- u_int16_t dsi_requestID; /* request ID */
- u_int32_t dsi_code; /* error code or data offset */
- u_int32_t dsi_len; /* total data length */
- u_int32_t dsi_reserved; /* reserved field */
+ uint8_t dsi_flags; /* packet type: request or reply */
+ uint8_t dsi_command; /* command */
+ uint16_t dsi_requestID; /* request ID */
+ uint32_t dsi_code; /* error code or data offset */
+ uint32_t dsi_len; /* total data length */
+ uint32_t dsi_reserved; /* reserved field */
};
#define DSI_CMDSIZ 8192
int msg_request; /* pending message to the client */
int down_request; /* pending SIGUSR1 down in 5 mn */
- u_int32_t attn_quantum, datasize, server_quantum;
- u_int16_t serverID, clientID;
+ uint32_t attn_quantum, datasize, server_quantum;
+ uint16_t serverID, clientID;
char *status;
- u_int8_t commands[DSI_CMDSIZ], data[DSI_DATASIZ];
+ uint8_t commands[DSI_CMDSIZ], data[DSI_DATASIZ];
size_t statuslen;
size_t datalen, cmdlen;
off_t read_count, write_count;
const char * /*program*/,
const char * /*host*/, const char * /*address*/,
const char * /*port*/, const int /*proxy*/,
- const u_int32_t /* server quantum */);
+ const uint32_t /* server quantum */);
extern void dsi_setstatus (DSI *, char *, const size_t);
/* in dsi_getsess.c */
extern ssize_t dsi_stream_write (DSI *, void *, const size_t, const int mode);
extern size_t dsi_stream_read (DSI *, void *, const size_t);
extern int dsi_stream_send (DSI *, void *, size_t);
- extern int dsi_stream_receive (DSI *, void *, const size_t, size_t *);
+ extern int dsi_stream_receive (DSI *);
extern int dsi_disconnect(DSI *dsi);
#ifdef WITH_SENDFILE
(x)->header.dsi_len = htonl((x)->cmdlen); \
dsi_stream_send((x), (x)->commands, (x)->cmdlen); \
} while (0)
- #define dsi_receive(x) (dsi_stream_receive((x), (x)->commands, \
- DSI_CMDSIZ, &(x)->cmdlen))
+
#endif /* atalk/dsi.h */
#define AFPD_GLOBALS_H 1
#include <sys/param.h>
-#include <sys/cdefs.h>
#ifdef ADMIN_GRP
#include <grp.h>
#define OPTION_NOZEROCONF (1 << 9)
#define OPTION_KEEPSESSIONS (1 << 10) /* preserve sessions across master afpd restart with SIGQUIT */
-#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 {
int fce_fmodwait; /* number of seconds FCE file mod events are put on hold */
unsigned int tcp_sndbuf, tcp_rcvbuf;
unsigned char passwdbits, passwdminlen, loginmaxfail;
- u_int32_t server_quantum;
+ uint32_t server_quantum;
int dsireadbuf; /* scale factor for sizefof(dsi->buffer) = server_quantum * dsireadbuf */
char hostname[MAXHOSTNAMELEN + 1], *server, *ipaddr, *port, *configfile;
-#ifndef NO_DDP
- struct at_addr ddpaddr;
-#endif
char *uampath, *fqdn;
char *pidfile;
char *sigconffile;
char *logconfig;
char *mimicmodel;
+ char *adminauthuser;
};
#define AFPOBJ_TMPSIZ (MAXPATHLEN)
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 */
/* 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 */
/* lock file path. this should be re-organized a bit. */
#if ! defined (_PATH_LOCKDIR)
- # if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ # if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
# define _PATH_LOCKDIR "/var/run/"
# elif defined (BSD4_4)
# ifdef MACOSX_SERVER
*/
#define _PATH_ATALKDEBUG "/tmp/atalkd.debug"
#define _PATH_ATALKDTMP "atalkd.tmp"
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
# define _PATH_ATALKDLOCK ATALKPATHCAT(_PATH_LOCKDIR,"atalkd.pid")
#else
# define _PATH_ATALKDLOCK ATALKPATHCAT(_PATH_LOCKDIR,"atalkd")
* psorder paths
*/
#define _PATH_TMPPAGEORDER "/tmp/psorderXXXXXX"
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
# define _PATH_PAPDLOCK ATALKPATHCAT(_PATH_LOCKDIR,"papd.pid")
#else
# define _PATH_PAPDLOCK ATALKPATHCAT(_PATH_LOCKDIR,"papd")
*/
#define _PATH_AFPTKT "/tmp/AFPtktXXXXXX"
#define _PATH_AFP_IPC ATALKPATHCAT(_PATH_LOCKDIR,"afpd_ipc")
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
# define _PATH_AFPDLOCK ATALKPATHCAT(_PATH_LOCKDIR,"afpd.pid")
#else
# define _PATH_AFPDLOCK ATALKPATHCAT(_PATH_LOCKDIR,"afpd")
/*
* cnid_metad paths
*/
- #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+ #if defined (FHS_COMPATIBILITY) || defined (__NetBSD__) || defined (__OpenBSD__)
# define _PATH_CNID_METAD_LOCK ATALKPATHCAT(_PATH_LOCKDIR,"cnid_metad.pid")
#else
# define _PATH_CNID_METAD_LOCK ATALKPATHCAT(_PATH_LOCKDIR,"cnid_metad")
#endif
+/*
+ * netalockd paths
+ */
+#if defined (FHS_COMPATIBILITY) || defined (__NetBSD__)
+# define _PATH_NETALOCKD_LOCK ATALKPATHCAT(_PATH_LOCKDIR,"netalockd.pid")
+#else
+# define _PATH_NETALOCKD_LOCK ATALKPATHCAT(_PATH_LOCKDIR,"netalockd")
+#endif
+
#endif /* atalk/paths.h */
#ifndef _ATALK_UTIL_H
#define _ATALK_UTIL_H 1
-#include <sys/cdefs.h>
#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
+#include <sys/socket.h>
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#include <poll.h>
-#include <netatalk/at.h>
#include <atalk/unicode.h>
#include <atalk/bstrlib.h>
#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))
+ #ifndef MAX
+ #define MAX(a,b) ((a) > (b) ? a : b)
+ #endif
+ #ifndef MIN
+ #define MIN(a,b) ((a) < (b) ? a : b)
+ #endif
#if BYTE_ORDER == BIG_ENDIAN
#define hton64(x) (x)
#define diatolower(x) _dialowermap[(unsigned char) (x)]
#define diatoupper(x) _diacasemap[(unsigned char) (x)]
-#ifndef NO_DDP
-extern int atalk_aton (char *, struct at_addr *);
-#endif
extern void bprint (char *, int);
extern int strdiacasecmp (const char *, const char *);
extern int strndiacasecmp (const char *, const char *, size_t);
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 *);
* unix.c
*****************************************************************/
+extern const char *abspath(const char *name);
extern const char *getcwdpath(void);
+ extern const char *fullpathname(const char *);
extern char *stripped_slashes_basename(char *p);
extern int lchdir(const char *dir);
extern void randombytes(void *buf, int n);
#ifndef ATALK_VOLUME_H
#define ATALK_VOLUME_H 1
+ #include <stdint.h>
+ #include <sys/cdefs.h>
#include <sys/types.h>
-// #include <netatalk/endian.h>
#include <atalk/unicode.h>
#include <atalk/cnid.h>
struct vol {
struct vol *v_next;
- u_int16_t v_vid;
+ uint16_t v_vid;
int v_flags;
char *v_path;
struct dir *v_root;
charset_t v_volcharset;
charset_t v_maccharset;
- u_int16_t v_mtou_flags; /* flags for convert_charset in mtoupath */
- u_int16_t v_utom_flags;
+ uint16_t v_mtou_flags; /* flags for convert_charset in mtoupath */
+ uint16_t v_utom_flags;
long v_kTextEncoding; /* mac charset encoding in network order
* FIXME: should be a u_int32_t ? */
size_t max_filename;
char *v_veto;
int v_adouble; /* adouble format: v1, v2, sfm ... */
int v_ad_options; /* adouble option NODEV, NOCACHE, etc.. */
- char *(*ad_path)(const char *, int);
+ const char *(*ad_path)(const char *, int);
struct _cnid_db *v_cdb;
char v_stamp[ADEDLEN_PRIVSYN];
VolSpace v_limitsize; /* Size limit, if any, in MiB */
char *v_gvs;
void *v_nfsclient;
int v_nfs;
- uintmax_t v_tm_used; /* used bytes on a TM volume */
- uintmax_t v_written; /* amount of data written in afp_write, reset every time a FCE_TM_SIZE event is sent */
+ VolSpace v_tm_used; /* used bytes on a TM volume */
+ time_t v_tm_cachetime; /* time at which v_tm_used was calculated last */
+ VolSpace v_appended; /* amount of data appended to files */
/* only when opening/closing volumes or in error */
int v_casefold;
int v_root_preexec_close;
int v_preexec_close;
char *v_uuid; /* For TimeMachine zeroconf record */
-#ifdef FORCE_UIDGID
- char *v_forceuid;
- char *v_forcegid;
-#endif
#ifdef __svr4__
int v_qfd;
#endif /*__svr4__*/
#define AFPVOL_USEDOTS (1 << 11) /* use real dots */
#define AFPVOL_LIMITSIZE (1 << 12) /* limit size for older macs */
#define AFPVOL_MAPASCII (1 << 13) /* map the ascii range as well */
-#define AFPVOL_DROPBOX (1 << 14) /* dropkludge dropbox support */
#define AFPVOL_NOFILEID (1 << 15) /* don't advertise createid resolveid and deleteid calls */
#define AFPVOL_NOSTAT (1 << 16) /* advertise the volume even if we can't stat() it
* maybe because it will be mounted later in preexec */
/*
- * $Id: ad_sendfile.c,v 1.11 2010-01-21 14:14:49 didg Exp $
- *
* Copyright (c) 1999 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
*
#endif /* HAVE_CONFIG_H */
#ifdef WITH_SENDFILE
-
-#include <atalk/adouble.h>
-
#include <stdio.h>
-
#include <sys/socket.h>
#include <sys/uio.h>
-
#include <errno.h>
+#include <atalk/adouble.h>
#include <atalk/logger.h>
-#include "ad_private.h"
+
+#include "ad_lock.h"
- #if defined(LINUX_BROKEN_SENDFILE_API)
-
- extern int32_t sendfile (int fdout, int fdin, int32_t *offset, u_int32_t count);
+ #if defined(SENDFILE_FLAVOR_LINUX)
+ #include <sys/sendfile.h>
ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
{
- u_int32_t small_total;
- int32_t small_offset;
- int32_t nwritten;
-
- /*
- * Fix for broken Linux 2.4 systems with no working sendfile64().
- * If the offset+count > 2 GB then pretend we don't have the
- * system call sendfile at all. The upper layer catches this
- * and uses a normal read. JRA.
- */
-
- if ((sizeof(off_t) >= 8) && (*offset + count > (off_t)0x7FFFFFFF)) {
- errno = ENOSYS;
- return -1;
- }
- small_offset = (int32_t)*offset;
- small_total = (u_int32_t)count;
- nwritten = sendfile(tofd, fromfd, &small_offset, small_total);
- if (nwritten > = 0)
- *offset += nwritten;
-
- return nwritten;
+ return sendfile(tofd, fromfd, offset, count);
}
- #elif defined(SENDFILE_FLAVOR_LINUX)
+ #elif defined(SENDFILE_FLAVOR_SOLARIS)
#include <sys/sendfile.h>
ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
}
#elif defined(SENDFILE_FLAVOR_BSD )
- /* FIXME untested */
- #error sendfile semantic broken
#include <sys/sendfile.h>
ssize_t sys_sendfile(int tofd, int fromfd, off_t *offset, size_t count)
{
#include <atalk/list.h>
#include <atalk/logger.h>
#include <atalk/util.h>
+#include <atalk/compat.h>
/* List of all registered modules. */
static struct list_head modules = ATALK_LIST_HEAD_INIT(modules);
}
/* ------------------- */
-static void block_signal( u_int32_t flags)
+static void block_signal(uint32_t flags)
{
if ((flags & CNID_FLAG_BLOCK)) {
pthread_sigmask(SIG_BLOCK, &sigblockset, NULL);
}
/* ------------------- */
-static void unblock_signal(u_int32_t flags)
+static void unblock_signal(uint32_t flags)
{
if ((flags & CNID_FLAG_BLOCK)) {
pthread_sigmask(SIG_UNBLOCK, &sigblockset, NULL);
/* Closes CNID database. Currently it's just a wrapper around db->cnid_close(). */
void cnid_close(struct _cnid_db *db)
{
-u_int32_t flags;
+ uint32_t flags;
if (NULL == db) {
LOG(log_error, logtype_afpd, "Error: cnid_close called with NULL argument !");
cnid_t cnid_add(struct _cnid_db *cdb, const struct stat *st, const cnid_t did,
const char *name, const size_t len, cnid_t hint)
{
- cnid_t ret;
+ cnid_t ret;
+
+ if (len == 0)
+ return CNID_INVALID;
block_signal(cdb->flags);
ret = valide(cdb->cnid_add(cdb, st, did, name, len, hint));
/*
- * $Id: dsi_cmdreply.c,v 1.5 2009-10-25 06:13:11 didg Exp $
- *
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
*/
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
+#include <arpa/inet.h>
+
#include <atalk/dsi.h>
+ #include <atalk/logger.h>
+ #include <netatalk/endian.h>
/* this assumes that the reply follows right after the command, saving
* on a couple assignments. specifically, command, requestID, and
* reserved field are assumed to already be set. */
int dsi_cmdreply(DSI *dsi, const int err)
{
- int ret;
- dsi->header.dsi_flags = DSIFL_REPLY;
- /*dsi->header.dsi_command = DSIFUNC_CMD;*/
- dsi->header.dsi_len = htonl(dsi->datalen);
- dsi->header.dsi_code = htonl(err);
-
- ret = dsi_stream_send(dsi, dsi->data, dsi->datalen);
- return ret;
+ int ret;
+
+ LOG(log_debug, logtype_dsi, "dsi_cmdreply(DSI ID: %u, len: %jd): START",
+ dsi->clientID, (intmax_t)dsi->datalen);
+
+ dsi->header.dsi_flags = DSIFL_REPLY;
+ dsi->header.dsi_len = htonl(dsi->datalen);
+ dsi->header.dsi_code = htonl(err);
+
+ ret = dsi_stream_send(dsi, dsi->data, dsi->datalen);
+
+ LOG(log_debug, logtype_dsi, "dsi_cmdreply(DSI ID: %u, len: %jd): END",
+ dsi->clientID, (intmax_t)dsi->datalen);
+
+ return ret;
}
/*
- * $Id: dsi_read.c,v 1.7 2009-10-25 06:13:11 didg Exp $
- *
* Copyright (c) 1997 Adrian Sun (asun@zoology.washington.edu)
* All rights reserved. See COPYRIGHT.
*/
#include <stdio.h>
#include <string.h>
-#ifdef HAVE_UNISTD_H
#include <unistd.h>
-#endif /* HAVE_UNISTD_H */
#include <signal.h>
#include <sys/types.h>
#include <sys/time.h>
-#ifdef HAVE_SYS_FILIO_H
-#include <sys/filio.h>
-#endif
#include <atalk/dsi.h>
-
- #ifndef min
- #define min(a,b) ((a) < (b) ? (a) : (b))
- #endif /* ! min */
+ #include <atalk/util.h>
+ #include <atalk/logger.h>
/* streaming i/o for afp_read. this is all from the perspective of the
* client. it basically does the reverse of dsi_write. on first entry,
* buffer. it returns the amount of stuff still to be read
* (constrained by the buffer size). */
ssize_t dsi_readinit(DSI *dsi, void *buf, const size_t buflen,
- const size_t size, const int err)
+ const size_t size, const int err)
{
+ LOG(log_maxdebug, logtype_dsi, "dsi_readinit: sending %zd bytes from buffer, total size: %zd",
+ buflen, size);
- dsi->flags |= DSI_NOREPLY; /* we will handle our own replies */
- dsi->header.dsi_flags = DSIFL_REPLY;
- /*dsi->header.dsi_command = DSIFUNC_CMD;*/
- dsi->header.dsi_len = htonl(size);
- dsi->header.dsi_code = htonl(err);
+ dsi->flags |= DSI_NOREPLY; /* we will handle our own replies */
+ dsi->header.dsi_flags = DSIFL_REPLY;
+ dsi->header.dsi_len = htonl(size);
+ dsi->header.dsi_code = htonl(err);
- dsi->in_write++;
- if (dsi_stream_send(dsi, buf, buflen)) {
- dsi->datasize = size - buflen;
- return min(dsi->datasize, buflen);
- }
+ dsi->in_write++;
+ if (dsi_stream_send(dsi, buf, buflen)) {
+ dsi->datasize = size - buflen;
+ LOG(log_maxdebug, logtype_dsi, "dsi_readinit: remaining data for sendfile: %zd", dsi->datasize);
+ return MIN(dsi->datasize, buflen);
+ }
- return -1; /* error */
+ return -1; /* error */
}
void dsi_readdone(DSI *dsi)
{
- dsi->in_write--;
+ dsi->in_write--;
}
/* send off the data */
ssize_t dsi_read(DSI *dsi, void *buf, const size_t buflen)
{
- size_t len;
-
- len = dsi_stream_write(dsi, buf, buflen, 0);
+ size_t len;
+
+ len = dsi_stream_write(dsi, buf, buflen, 0);
- if (len == buflen) {
- dsi->datasize -= len;
- return min(dsi->datasize, buflen);
- }
+ if (len == buflen) {
+ dsi->datasize -= len;
+ return MIN(dsi->datasize, buflen);
+ }
- return -1;
+ return -1;
}
#include <atalk/logger.h>
#include <atalk/dsi.h>
-#include <netatalk/endian.h>
#include <atalk/util.h>
#define min(a,b) ((a) < (b) ? (a) : (b))
/*
* Return all bytes up to count from dsi->buffer if there are any buffered there
*/
-static size_t from_buf(DSI *dsi, u_int8_t *buf, size_t count)
+static size_t from_buf(DSI *dsi, uint8_t *buf, size_t count)
{
size_t nbe = 0;
* Note: this may return fewer bytes then requested in count !!
* 3. If the buffer was empty, read from the socket.
*/
-static ssize_t buf_read(DSI *dsi, u_int8_t *buf, size_t count)
+static ssize_t buf_read(DSI *dsi, uint8_t *buf, size_t count)
{
ssize_t len;
* Get "length" bytes from buffer and/or socket. In order to avoid frequent small reads
* this tries to read larger chunks (8192 bytes) into a buffer.
*/
-static size_t dsi_buffered_stream_read(DSI *dsi, u_int8_t *data, const size_t length)
+static size_t dsi_buffered_stream_read(DSI *dsi, uint8_t *data, const size_t length)
{
size_t len;
size_t buflen;
dsi->in_write++;
written = 0;
- LOG(log_maxdebug, logtype_dsi, "dsi_stream_write: sending %u bytes", length);
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): START", length);
if (dsi->flags & DSI_DISCONNECTED)
return -1;
while (written < length) {
- len = send(dsi->socket, (u_int8_t *) data + written, length - written, flags);
+ len = send(dsi->socket, (uint8_t *) data + written, length - written, flags);
if (len >= 0) {
written += len;
continue;
}
dsi->write_count += written;
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_write(send: %zd bytes): END", length);
exit:
dsi->in_write--;
#ifdef WITH_SENDFILE
ssize_t dsi_stream_read_file(DSI *dsi, int fromfd, off_t offset, const size_t length)
{
+ int ret = 0;
size_t written;
ssize_t len;
+ off_t pos = offset;
- LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sending %u bytes", length);
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file(send %zd bytes): START", length);
if (dsi->flags & DSI_DISCONNECTED)
return -1;
written = 0;
while (written < length) {
- len = sys_sendfile(dsi->socket, fromfd, &offset, length - written);
+ len = sys_sendfile(dsi->socket, fromfd, &pos, length - written);
if (len < 0) {
if (errno == EINTR)
continue;
- if (errno == EINVAL || errno == ENOSYS)
- return -1;
-
+ if (errno == EINVAL || errno == ENOSYS) {
+ ret = -1;
+ goto exit;
+ }
if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ #ifdef SOLARIS
+ if (pos > offset) {
+ /* we actually have sent sth., adjust counters and keep trying */
+ len = pos - offset;
+ written += len;
+ offset = pos;
+ }
+ #endif
if (dsi_peek(dsi)) {
/* can't go back to blocking mode, exit, the next read
will return with an error and afpd will die.
}
else if (!len) {
/* afpd is going to exit */
- errno = EIO;
- return -1; /* I think we're at EOF here... */
+ ret = -1;
+ goto exit;
}
else
written += len;
}
dsi->write_count += written;
+
+ exit:
dsi->in_write--;
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_read_file: sent: %zd", written);
+ if (ret != 0)
+ return -1;
return written;
}
#endif
stored = 0;
while (stored < length) {
- len = buf_read(dsi, (u_int8_t *) data + stored, length - stored);
+ len = buf_read(dsi, (uint8_t *) data + stored, length - stored);
if (len == -1 && (errno == EINTR || errno == EAGAIN)) {
LOG(log_maxdebug, logtype_dsi, "dsi_stream_read: select read loop");
continue;
size_t towrite;
ssize_t len;
- LOG(log_maxdebug, logtype_dsi, "dsi_stream_send: %u bytes",
- length ? length : sizeof(block));
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): START", length);
if (dsi->flags & DSI_DISCONNECTED)
return 0;
sizeof(dsi->header.dsi_reserved));
if (!length) { /* just write the header */
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): DSI header, no data", sizeof(block));
length = (dsi_stream_write(dsi, block, sizeof(block), 0) == sizeof(block));
return length; /* really 0 on failure, 1 on success */
}
iov[1].iov_len -= len;
}
}
+
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_send(%u bytes): END", length);
unblock_sig(dsi);
return 1;
}
- /* ---------------------------------------
- * read data. function on success. 0 on failure. data length gets
- * stored in length variable. this should really use size_t's, but
- * that would require changes elsewhere. */
- int dsi_stream_receive(DSI *dsi, void *buf, const size_t ilength,
- size_t *rlength)
+ /*!
+ * Read DSI command and data
+ *
+ * @param dsi (rw) DSI handle
+ *
+ * @return DSI function on success, 0 on failure
+ */
+ int dsi_stream_receive(DSI *dsi)
{
char block[DSI_BLOCKSIZ];
- LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: %u bytes", ilength);
+ LOG(log_maxdebug, logtype_dsi, "dsi_stream_receive: START");
if (dsi->flags & DSI_DISCONNECTED)
return 0;
/* read in the header */
- if (dsi_buffered_stream_read(dsi, (u_int8_t *)block, sizeof(block)) != sizeof(block))
+ if (dsi_buffered_stream_read(dsi, (uint8_t *)block, sizeof(block)) != sizeof(block))
return 0;
dsi->header.dsi_flags = block[0];
dsi->header.dsi_command = block[1];
- /* FIXME, not the right place,
- but we get a server disconnect without reason in the log
- */
- if (!block[1]) {
- LOG(log_error, logtype_dsi, "dsi_stream_receive: invalid packet, fatal");
+
+ if (dsi->header.dsi_command == 0)
return 0;
- }
- memcpy(&dsi->header.dsi_requestID, block + 2,
- sizeof(dsi->header.dsi_requestID));
+ memcpy(&dsi->header.dsi_requestID, block + 2, sizeof(dsi->header.dsi_requestID));
memcpy(&dsi->header.dsi_code, block + 4, sizeof(dsi->header.dsi_code));
memcpy(&dsi->header.dsi_len, block + 8, sizeof(dsi->header.dsi_len));
- memcpy(&dsi->header.dsi_reserved, block + 12,
- sizeof(dsi->header.dsi_reserved));
+ memcpy(&dsi->header.dsi_reserved, block + 12, sizeof(dsi->header.dsi_reserved));
dsi->clientID = ntohs(dsi->header.dsi_requestID);
/* make sure we don't over-write our buffers. */
- *rlength = min(ntohl(dsi->header.dsi_len), ilength);
- if (dsi_stream_read(dsi, buf, *rlength) != *rlength)
+ dsi->cmdlen = min(ntohl(dsi->header.dsi_len), DSI_CMDSIZ);
+ if (dsi_stream_read(dsi, dsi->commands, dsi->cmdlen) != dsi->cmdlen)
return 0;
+ LOG(log_debug, logtype_dsi, "dsi_stream_receive: DSI cmdlen: %zd", dsi->cmdlen);
+
return block[1];
}
DO NOT EDIT BY HAND!!!
This file is generated by
- contrib/misc/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c
+ contrib/shell_utils/make-casetable.pl UnicodeData.txt utf16_casetable.h utf16_case.c
UnicodeData.txt is got from
http://www.unicode.org/Public/UNIDATA/UnicodeData.txt
*/
-static const u_int16_t upper_table_1[704] = {
+static const uint16_t upper_table_1[704] = {
0x0000, /*U+0000*/ /**/
0x0001, /*U+0001*/ /**/
0x0002, /*U+0002*/ /**/
0x02BF, /*U+02BF*/ /**/
};
-static const u_int16_t upper_table_2[640] = {
+static const uint16_t upper_table_2[640] = {
0x0340, /*U+0340*/ /**/
0x0341, /*U+0341*/ /**/
0x0342, /*U+0342*/ /**/
0x05BF, /*U+05BF*/ /**/
};
-static const u_int16_t upper_table_3[64] = {
+static const uint16_t upper_table_3[64] = {
0x1D40, /*U+1D40*/ /**/
0x1D41, /*U+1D41*/ /**/
0x1D42, /*U+1D42*/ /**/
0x1D7F, /*U+1D7F*/ /**/
};
-static const u_int16_t upper_table_4[512] = {
+static const uint16_t upper_table_4[512] = {
0x1E00, /*U+1E00*/ /**/
0x1E00, /*U+1E01*/ /*LATIN SMALL LETTER A WITH RING BELOW*/
0x1E02, /*U+1E02*/ /**/
0x1FFF, /*U+1FFF*/ /**/
};
-static const u_int16_t upper_table_5[128] = {
+static const uint16_t upper_table_5[128] = {
0x2140, /*U+2140*/ /**/
0x2141, /*U+2141*/ /**/
0x2142, /*U+2142*/ /**/
0x21BF, /*U+21BF*/ /**/
};
-static const u_int16_t upper_table_6[64] = {
+static const uint16_t upper_table_6[64] = {
0x24C0, /*U+24C0*/ /**/
0x24C1, /*U+24C1*/ /**/
0x24C2, /*U+24C2*/ /**/
0x24FF, /*U+24FF*/ /**/
};
-static const u_int16_t upper_table_7[320] = {
+static const uint16_t upper_table_7[320] = {
0x2C00, /*U+2C00*/ /**/
0x2C01, /*U+2C01*/ /**/
0x2C02, /*U+2C02*/ /**/
0x2D3F, /*U+2D3F*/ /**/
};
-static const u_int16_t upper_table_8[128] = {
+static const uint16_t upper_table_8[128] = {
0xA640, /*U+A640*/ /**/
0xA640, /*U+A641*/ /*CYRILLIC SMALL LETTER ZEMLYA*/
0xA642, /*U+A642*/ /**/
0xA6BF, /*U+A6BF*/ /**/
};
-static const u_int16_t upper_table_9[192] = {
+static const uint16_t upper_table_9[192] = {
0xA700, /*U+A700*/ /**/
0xA701, /*U+A701*/ /**/
0xA702, /*U+A702*/ /**/
0xA7BF, /*U+A7BF*/ /**/
};
-static const u_int16_t upper_table_10[64] = {
+static const uint16_t upper_table_10[64] = {
0xFF40, /*U+FF40*/ /**/
0xFF21, /*U+FF41*/ /*FULLWIDTH LATIN SMALL LETTER A*/
0xFF22, /*U+FF42*/ /*FULLWIDTH LATIN SMALL LETTER B*/
0xFF7F, /*U+FF7F*/ /**/
};
-static const u_int32_t upper_table_sp_1[128] = {
+static const uint32_t upper_table_sp_1[128] = {
0xD801DC00, /*0xD801DC00*/ /*U+010400*/ /*U+010400*/ /**/
0xD801DC01, /*0xD801DC01*/ /*U+010401*/ /*U+010401*/ /**/
0xD801DC02, /*0xD801DC02*/ /*U+010402*/ /*U+010402*/ /**/
0xD801DC7F, /*0xD801DC7F*/ /*U+01047F*/ /*U+01047F*/ /**/
};
-static const u_int16_t lower_table_1[128] = {
+static const uint16_t lower_table_1[128] = {
0x0000, /*U+0000*/ /**/
0x0001, /*U+0001*/ /**/
0x0002, /*U+0002*/ /**/
0x007F, /*U+007F*/ /**/
};
-static const u_int16_t lower_table_2[448] = {
+static const uint16_t lower_table_2[448] = {
0x00E0, /*U+00C0*/ /*LATIN CAPITAL LETTER A WITH GRAVE*/
0x00E1, /*U+00C1*/ /*LATIN CAPITAL LETTER A WITH ACUTE*/
0x00E2, /*U+00C2*/ /*LATIN CAPITAL LETTER A WITH CIRCUMFLEX*/
0x027F, /*U+027F*/ /**/
};
-static const u_int16_t lower_table_3[576] = {
+static const uint16_t lower_table_3[576] = {
0x0340, /*U+0340*/ /**/
0x0341, /*U+0341*/ /**/
0x0342, /*U+0342*/ /**/
0x057F, /*U+057F*/ /**/
};
-static const u_int16_t lower_table_4[128] = {
+static const uint16_t lower_table_4[128] = {
0x1080, /*U+1080*/ /**/
0x1081, /*U+1081*/ /**/
0x1082, /*U+1082*/ /**/
0x10FF, /*U+10FF*/ /**/
};
-static const u_int16_t lower_table_5[512] = {
+static const uint16_t lower_table_5[512] = {
0x1E01, /*U+1E00*/ /*LATIN CAPITAL LETTER A WITH RING BELOW*/
0x1E01, /*U+1E01*/ /**/
0x1E03, /*U+1E02*/ /*LATIN CAPITAL LETTER B WITH DOT ABOVE*/
0x1FFF, /*U+1FFF*/ /**/
};
-static const u_int16_t lower_table_6[192] = {
+static const uint16_t lower_table_6[192] = {
0x2100, /*U+2100*/ /**/
0x2101, /*U+2101*/ /**/
0x2102, /*U+2102*/ /**/
0x21BF, /*U+21BF*/ /**/
};
-static const u_int16_t lower_table_7[128] = {
+static const uint16_t lower_table_7[128] = {
0x2480, /*U+2480*/ /**/
0x2481, /*U+2481*/ /**/
0x2482, /*U+2482*/ /**/
0x24FF, /*U+24FF*/ /**/
};
-static const u_int16_t lower_table_8[256] = {
+static const uint16_t lower_table_8[256] = {
0x2C30, /*U+2C00*/ /*GLAGOLITIC CAPITAL LETTER AZU*/
0x2C31, /*U+2C01*/ /*GLAGOLITIC CAPITAL LETTER BUKY*/
0x2C32, /*U+2C02*/ /*GLAGOLITIC CAPITAL LETTER VEDE*/
0x2CFF, /*U+2CFF*/ /**/
};
-static const u_int16_t lower_table_9[128] = {
+static const uint16_t lower_table_9[128] = {
0xA641, /*U+A640*/ /*CYRILLIC CAPITAL LETTER ZEMLYA*/
0xA641, /*U+A641*/ /**/
0xA643, /*U+A642*/ /*CYRILLIC CAPITAL LETTER DZELO*/
0xA6BF, /*U+A6BF*/ /**/
};
-static const u_int16_t lower_table_10[192] = {
+static const uint16_t lower_table_10[192] = {
0xA700, /*U+A700*/ /**/
0xA701, /*U+A701*/ /**/
0xA702, /*U+A702*/ /**/
0xA7BF, /*U+A7BF*/ /**/
};
-static const u_int16_t lower_table_11[64] = {
+static const uint16_t lower_table_11[64] = {
0xFF00, /*U+FF00*/ /**/
0xFF01, /*U+FF01*/ /**/
0xFF02, /*U+FF02*/ /**/
0xFF3F, /*U+FF3F*/ /**/
};
-static const u_int32_t lower_table_sp_1[64] = {
+static const uint32_t lower_table_sp_1[64] = {
0xD801DC28, /*0xD801DC00*/ /*U+010428*/ /*U+010400*/ /*DESERET CAPITAL LETTER LONG I*/
0xD801DC29, /*0xD801DC01*/ /*U+010429*/ /*U+010401*/ /*DESERET CAPITAL LETTER LONG E*/
0xD801DC2A, /*0xD801DC02*/ /*U+01042A*/ /*U+010402*/ /*DESERET CAPITAL LETTER LONG A*/
#include <atalk/vfs.h>
#include <atalk/util.h>
#include <atalk/unix.h>
+#include <atalk/compat.h>
/* close all FDs >= a specified value */
static void closeall(int fd)
}
/*!
- * Make argument path absoulte
+ * @brief Request absolute path
*
- * @returns pointer to path or pointer to error messages on error
+ * @returns Absolute filesystem path to object
*/
- const char *abspath(const char *name)
+ const char *fullpathname(const char *name)
{
- static char buf[MAXPATHLEN + 1];
- char *p;
- int n;
+ static char wd[MAXPATHLEN + 1];
if (name[0] == '/')
return name;
- if ((p = getcwd(buf, MAXPATHLEN)) == NULL)
- return strerror(errno);
+ if (getcwd(wd , MAXPATHLEN)) {
+ strlcat(wd, "/", MAXPATHLEN);
+ strlcat(wd, name, MAXPATHLEN);
+ } else {
+ strlcpy(wd, name, MAXPATHLEN);
+ }
- n = strlen(buf);
- if (buf[n-1] != '/')
- buf[n++] = '/';
-
- strlcpy(buf + n, name, MAXPATHLEN - n);
- return buf;
+ return wd;
}
/*!
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef STDC_HEADERS
#include <string.h>
-#endif
#include <sys/param.h>
#include <atalk/adouble.h>
#include <atalk/logger.h>
#include <atalk/volinfo.h>
#include <atalk/volume.h>
+#include <atalk/compat.h>
#ifdef CNID_DB
#include <atalk/cnid.h>
#endif /* CNID_DB*/
{AFPVOL_USEDOTS, "USEDOTS"}, /* use real dots */
{AFPVOL_LIMITSIZE, "LIMITSIZE"}, /* limit size for older macs */
{AFPVOL_MAPASCII, "MAPASCII"}, /* map the ascii range as well */
- {AFPVOL_DROPBOX, "DROPBOX"}, /* dropkludge dropbox support */
{AFPVOL_NOFILEID, "NOFILEID"}, /* don't advertise createid resolveid and deleteid calls */
{AFPVOL_NOSTAT, "NOSTAT"}, /* advertise the volume even if we can't stat() it
* maybe because it will be mounted later in preexec */
strcpy(vol->v_dbpath, value);
break;
case ADOUBLE_VER:
- if (strcasecmp(value, "v1") == 0) {
- vol->v_adouble = AD_VERSION1;
- vol->ad_path = ad_path;
- }
-#if AD_VERSION == AD_VERSION2
- else if (strcasecmp(value, "v2") == 0) {
+ if (strcasecmp(value, "v2") == 0) {
vol->ad_path = ad_path;
vol->v_adouble = AD_VERSION2;
- }
- else if (strcasecmp(value, "osx") == 0) {
- vol->v_adouble = AD_VERSION2_OSX;
- vol->ad_path = ad_path_osx;
- }
-#endif
- else {
+ } else if (strcasecmp(value, "ea") == 0) {
+ vol->ad_path = ad_path_ea;
+ vol->v_adouble = AD_VERSION_EA;
+ } else {
+
fprintf (stderr, "unknown adouble version: %s, %s", buf, value);
return -1;
}
}
if ((fd = open(item, O_RDWR | O_CREAT , 0666)) <0 ) {
- LOG(log_error, logtype_afpd,"Error opening %s: %s", item, strerror(errno));
+ LOG(log_debug, logtype_default,"Error opening %s: %s", item, strerror(errno));
+ if (process_uid) {
+ if (seteuid(process_uid) == -1) {
+ LOG(log_error, logtype_default, "can't seteuid back %s", strerror(errno));
+ exit(EXITERR_SYS);
+ }
+ }
return (-1);
}
if (process_uid) {
if (seteuid(process_uid) == -1) {
- LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno));
+ LOG(log_error, logtype_default, "can't seteuid back %s", strerror(errno));
exit(EXITERR_SYS);
}
}
/* ignore, other process already writing the file */
return 0;
} else {
- LOG(log_error, logtype_cnid, "savevoloptions: cannot get lock: %s", strerror(errno));
+ LOG(log_error, logtype_default, "savevoloptions: cannot get lock: %s", strerror(errno));
return (-1);
}
}
strlcat(buf, item, sizeof(buf));
switch (vol->v_adouble) {
- case AD_VERSION1:
- strlcat(buf, "ADOUBLE_VER:v1\n", sizeof(buf));
- break;
case AD_VERSION2:
strlcat(buf, "ADOUBLE_VER:v2\n", sizeof(buf));
break;
- case AD_VERSION2_OSX:
- strlcat(buf, "ADOUBLE_VER:osx\n", sizeof(buf));
- break;
- case AD_VERSION1_SFM:
- strlcat(buf, "ADOUBLE_VER:sfm\n", sizeof(buf));
+ case AD_VERSION_EA:
+ strlcat(buf, "ADOUBLE_VER:ea\n", sizeof(buf));
break;
}
strlcat(buf, item, sizeof(buf));
if (strlen(buf) >= sizeof(buf)-1)
- LOG(log_debug, logtype_afpd,"Error writing .volinfo file: buffer too small, %s", buf);
+ LOG(log_debug, logtype_default, "Error writing .volinfo file: buffer too small, %s", buf);
if (write( fd, buf, strlen(buf)) < 0 || ftruncate(fd, strlen(buf)) < 0 ) {
- LOG(log_debug, logtype_afpd,"Error writing .volinfo file: %s", strerror(errno));
+ LOG(log_debug, logtype_default, "Error writing .volinfo file: %s", strerror(errno));
}
lock.l_type = F_UNLCK;
--- /dev/null
- LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion");
+/*
+ Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
+
+ 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.
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdint.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <arpa/inet.h>
+
+#include <atalk/adouble.h>
+#include <atalk/ea.h>
+#include <atalk/afp.h>
+#include <atalk/logger.h>
+#include <atalk/volume.h>
+#include <atalk/vfs.h>
+#include <atalk/util.h>
+#include <atalk/unix.h>
+#include <atalk/compat.h>
+
+/*
+ * Store Extended Attributes inside .AppleDouble folders as follows:
+ *
+ * filename "fileWithEAs" with EAs "testEA1" and "testEA2"
+ *
+ * - create header with with the format struct adouble_ea_ondisk, the file is written to
+ * ".AppleDouble/fileWithEAs::EA"
+ * - store EAs in files "fileWithEAs::EA::testEA1" and "fileWithEAs::EA::testEA2"
+ */
+
+/*
+ * Build mode for EA header from file mode
+ */
+static inline mode_t ea_header_mode(mode_t mode)
+{
+ /* Same as ad_hf_mode(mode) */
+ mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
+ /* Owner must be able to open, read and w-lock it, in order to chmod from eg 0000 -> 0xxxx*/
+ mode |= S_IRUSR | S_IWUSR;
+ return mode;
+}
+
+/*
+ * Build mode for EA file from file mode
+ */
+static inline mode_t ea_mode(mode_t mode)
+{
+ /* Same as ad_hf_mode(mode) */
+ mode &= ~(S_IXUSR | S_IXGRP | S_IXOTH);
+ return mode;
+}
+
+/*
+ Taken form afpd/desktop.c
+*/
+static char *mtoupath(const struct vol *vol, const char *mpath)
+{
+ static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
+ const char *m;
+ char *u;
+ size_t inplen;
+ size_t outlen;
+ uint16_t flags = CONV_ESCAPEHEX | CONV_ALLOW_COLON;
+
+ if (!mpath)
+ return NULL;
+
+ if ( *mpath == '\0' ) {
+ return( "." );
+ }
+
+ m = mpath;
+ u = upath;
+
+ inplen = strlen(m);
+ outlen = MAXPATHLEN;
+
+ if ((size_t)-1 == (outlen = convert_charset(CH_UTF8_MAC,
+ vol->v_volcharset,
+ vol->v_maccharset,
+ m, inplen, u, outlen, &flags)) ) {
+ return NULL;
+ }
+
+ return( upath );
+}
+
+
+/*
+ * Function: unpack_header
+ *
+ * Purpose: unpack and verify header file data buffer at ea->ea_data into struct ea
+ *
+ * Arguments:
+ *
+ * ea (rw) handle to struct ea
+ *
+ * Returns: 0 on success, -1 on error
+ *
+ * Effects:
+ *
+ * Verifies magic and version.
+ */
+static int unpack_header(struct ea * restrict ea)
+{
+ int ret = 0;
+ unsigned int count = 0;
+ uint32_t uint32;
+ char *buf;
+
+ /* Check magic and version */
+ buf = ea->ea_data;
+ if (*(uint32_t *)buf != htonl(EA_MAGIC)) {
+ LOG(log_error, logtype_afpd, "unpack_header: wrong magic 0x%08x", *(uint32_t *)buf);
+ ret = -1;
+ goto exit;
+ }
+ buf += 4;
+ if (*(uint16_t *)buf != htons(EA_VERSION)) {
+ LOG(log_error, logtype_afpd, "unpack_header: wrong version 0x%04x", *(uint16_t *)buf);
+ ret = -1;
+ goto exit;
+ }
+ buf += 2;
+
+ /* Get EA count */
+ ea->ea_count = ntohs(*(uint16_t *)buf);
+ LOG(log_debug, logtype_afpd, "unpack_header: number of EAs: %u", ea->ea_count);
+ buf += 2;
+
+ if (ea->ea_count == 0)
+ return 0;
+
+ /* Allocate storage for the ea_entries array */
+ ea->ea_entries = malloc(sizeof(struct ea_entry) * ea->ea_count);
+ if ( ! ea->ea_entries) {
+ LOG(log_error, logtype_afpd, "unpack_header: OOM");
+ ret = -1;
+ goto exit;
+ }
+
+ buf = ea->ea_data + EA_HEADER_SIZE;
+ while (count < ea->ea_count) {
+ memcpy(&uint32, buf, 4); /* EA size */
+ buf += 4;
+ (*(ea->ea_entries))[count].ea_size = ntohl(uint32);
+ (*(ea->ea_entries))[count].ea_name = strdup(buf);
+ if (! (*(ea->ea_entries))[count].ea_name) {
+ LOG(log_error, logtype_afpd, "unpack_header: OOM");
+ ret = -1;
+ goto exit;
+ }
+ (*(ea->ea_entries))[count].ea_namelen = strlen((*(ea->ea_entries))[count].ea_name);
+ buf += (*(ea->ea_entries))[count].ea_namelen + 1;
+
+ LOG(log_maxdebug, logtype_afpd, "unpack_header: entry no:%u,\"%s\", size: %u, namelen: %u", count,
+ (*(ea->ea_entries))[count].ea_name,
+ (*(ea->ea_entries))[count].ea_size,
+ (*(ea->ea_entries))[count].ea_namelen);
+
+ count++;
+ }
+
+exit:
+ return ret;
+}
+
+/*
+ * Function: pack_header
+ *
+ * Purpose: pack everything from struct ea into buffer at ea->ea_data
+ *
+ * Arguments:
+ *
+ * ea (rw) handle to struct ea
+ *
+ * Returns: 0 on success, -1 on error
+ *
+ * Effects:
+ *
+ * adjust ea->ea_count in case an ea entry deletetion is detected
+ */
+static int pack_header(struct ea * restrict ea)
+{
+ unsigned int count = 0, eacount = 0;
+ uint16_t uint16;
+ uint32_t uint32;
+ size_t bufsize = EA_HEADER_SIZE;
+
+ char *buf = ea->ea_data + EA_HEADER_SIZE;
+
+ LOG(log_debug, logtype_afpd, "pack_header('%s'): ea_count: %u, ea_size: %u",
+ ea->filename, ea->ea_count, ea->ea_size);
+
+ if (ea->ea_count == 0)
+ /* nothing to do, magic, version and count are still valid in buffer */
+ return 0;
+
+ while(count < ea->ea_count) { /* the names */
+ /* Check if its a deleted entry */
+ if ( ! ((*ea->ea_entries)[count].ea_name)) {
+ count++;
+ continue;
+ }
+
+ bufsize += (*(ea->ea_entries))[count].ea_namelen + 1;
+ count++;
+ eacount++;
+ }
+
+ bufsize += (eacount * 4); /* header + ea_size for each EA */
+ if (bufsize > ea->ea_size) {
+ /* we must realloc */
+ if ( ! (buf = realloc(ea->ea_data, bufsize)) ) {
+ LOG(log_error, logtype_afpd, "pack_header: OOM");
+ return -1;
+ }
+ ea->ea_data = buf;
+ }
+ ea->ea_size = bufsize;
+
+ /* copy count */
+ uint16 = htons(eacount);
+ memcpy(ea->ea_data + EA_COUNT_OFF, &uint16, 2);
+
+ count = 0;
+ buf = ea->ea_data + EA_HEADER_SIZE;
+ while (count < ea->ea_count) {
+ /* Check if its a deleted entry */
+ if ( ! ((*ea->ea_entries)[count].ea_name)) {
+ count++;
+ continue;
+ }
+
+ /* First: EA size */
+ uint32 = htonl((*(ea->ea_entries))[count].ea_size);
+ memcpy(buf, &uint32, 4);
+ buf += 4;
+
+ /* Second: EA name as C-string */
+ strcpy(buf, (*(ea->ea_entries))[count].ea_name);
+ buf += (*(ea->ea_entries))[count].ea_namelen + 1;
+
+ LOG(log_maxdebug, logtype_afpd, "pack_header: entry no:%u,\"%s\", size: %u, namelen: %u", count,
+ (*(ea->ea_entries))[count].ea_name,
+ (*(ea->ea_entries))[count].ea_size,
+ (*(ea->ea_entries))[count].ea_namelen);
+
+ count++;
+ }
+
+ ea->ea_count = eacount;
+
+ LOG(log_debug, logtype_afpd, "pack_header('%s'): ea_count: %u, ea_size: %u",
+ ea->filename, ea->ea_count, ea->ea_size);
+
+ return 0;
+}
+
+/*
+ * Function: ea_addentry
+ *
+ * Purpose: add one EA into ea->ea_entries[]
+ *
+ * Arguments:
+ *
+ * ea (rw) pointer to struct ea
+ * attruname (r) name of EA
+ * attrsize (r) size of ea
+ * bitmap (r) bitmap from FP func
+ *
+ * Returns: new number of EA entries, -1 on error
+ *
+ * Effects:
+ *
+ * Grow array ea->ea_entries[]. If ea->ea_entries is still NULL, start allocating.
+ * Otherwise realloc and put entry at the end. Increments ea->ea_count.
+ */
+static int ea_addentry(struct ea * restrict ea,
+ const char * restrict attruname,
+ size_t attrsize,
+ int bitmap)
+{
+ int ea_existed = 0;
+ unsigned int count = 0;
+ void *tmprealloc;
+
+ /* First check if an EA of the requested name already exist */
+ if (ea->ea_count > 0) {
+ while (count < ea->ea_count) {
+ if (strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
+ ea_existed = 1;
+ LOG(log_debug, logtype_afpd, "ea_addentry('%s', bitmap:0x%x): exists", attruname, bitmap);
+ if (bitmap & kXAttrCreate)
+ /* its like O_CREAT|O_EXCL -> fail */
+ return -1;
+ (*(ea->ea_entries))[count].ea_size = attrsize;
+ return 0;
+ }
+ count++;
+ }
+ }
+
+ if ((bitmap & kXAttrReplace) && ! ea_existed)
+ /* replace was requested, but EA didn't exist */
+ return -1;
+
+ if (ea->ea_count == 0) {
+ ea->ea_entries = malloc(sizeof(struct ea_entry));
+ if ( ! ea->ea_entries) {
+ LOG(log_error, logtype_afpd, "ea_addentry: OOM");
+ return -1;
+ }
+ } else if (! ea_existed) {
+ tmprealloc = realloc(ea->ea_entries, sizeof(struct ea_entry) * (ea->ea_count + 1));
+ if ( ! tmprealloc) {
+ LOG(log_error, logtype_afpd, "ea_addentry: OOM");
+ return -1;
+ }
+ ea->ea_entries = tmprealloc;
+ }
+
+ /* We've grown the array, now store the entry */
+ (*(ea->ea_entries))[ea->ea_count].ea_size = attrsize;
+ (*(ea->ea_entries))[ea->ea_count].ea_name = strdup(attruname);
+ if ( ! (*(ea->ea_entries))[ea->ea_count].ea_name) {
+ LOG(log_error, logtype_afpd, "ea_addentry: OOM");
+ goto error;
+ }
+ (*(ea->ea_entries))[ea->ea_count].ea_namelen = strlen(attruname);
+
+ ea->ea_count++;
+ return ea->ea_count;
+
+error:
+ if (ea->ea_count == 0 && ea->ea_entries) {
+ /* We just allocated storage but had an error somewhere -> free storage*/
+ free(ea->ea_entries);
+ ea->ea_entries = NULL;
+ }
+ ea->ea_count = 0;
+ return -1;
+}
+
+/*
+ * Function: create_ea_header
+ *
+ * Purpose: create EA header file, only called from ea_open
+ *
+ * Arguments:
+ *
+ * uname (r) filename for which we have to create a header
+ * ea (rw) ea handle with already allocated storage pointed to
+ * by ea->ea_data
+ *
+ * Returns: fd of open header file on success, -1 on error, errno semantics:
+ * EEXIST: open with O_CREAT | O_EXCL failed
+ *
+ * Effects:
+ *
+ * Creates EA header file and initialize ea->ea_data buffer.
+ * Possibe race condition with other afpd processes:
+ * we were called because header file didn't exist in eg. ea_open. We then
+ * try to create a file with O_CREAT | O_EXCL, but the whole process in not atomic.
+ * What do we do then? Someone else is in the process of creating the header too, but
+ * it might not have finished it. That means we cant just open, read and use it!
+ * We therefor currently just break with an error.
+ * On return the header file is still r/w locked.
+ */
+static int create_ea_header(const char * restrict uname,
+ struct ea * restrict ea)
+{
+ int fd = -1, err = 0;
+ char *ptr;
+
+ if ((fd = open(uname, O_RDWR | O_CREAT | O_EXCL, 0666 & ~ea->vol->v_umask)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_create: open race condition with ea header for file: %s", uname);
+ return -1;
+ }
+
+ /* lock it */
+ if ((write_lock(fd, 0, SEEK_SET, 0)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_create: lock race condition with ea header for file: %s", uname);
+ err = -1;
+ goto exit;
+ }
+
+ /* Now init it */
+ ptr = ea->ea_data;
+ *(uint32_t *)ptr = htonl(EA_MAGIC);
+ ptr += EA_MAGIC_LEN;
+ *(uint16_t *)ptr = htons(EA_VERSION);
+ ptr += EA_VERSION_LEN;
+ *(uint16_t *)ptr = 0; /* count */
+
+ ea->ea_size = EA_HEADER_SIZE;
+ ea->ea_inited = EA_INITED;
+
+exit:
+ if (err != 0) {
+ close(fd);
+ fd = -1;
+ }
+ return fd;
+}
+
+/*
+ * Function: write_ea
+ *
+ * Purpose: write an EA to disk
+ *
+ * Arguments:
+ *
+ * ea (r) struct ea handle
+ * attruname (r) EA name
+ * ibuf (r) buffer with EA content
+ * attrsize (r) size of EA
+ *
+ * Returns: 0 on success, -1 on error
+ *
+ * Effects:
+ *
+ * Creates/overwrites EA file.
+ *
+ */
+static int write_ea(const struct ea * restrict ea,
+ const char * restrict attruname,
+ const char * restrict ibuf,
+ size_t attrsize)
+{
+ int fd = -1, ret = AFP_OK;
+ struct stat st;
+ char *eaname;
+
+ if ((eaname = ea_path(ea, attruname, 1)) == NULL) {
+ LOG(log_error, logtype_afpd, "write_ea('%s'): ea_path error", attruname);
+ return AFPERR_MISC;
+ }
+
+ LOG(log_maxdebug, logtype_afpd, "write_ea('%s')", eaname);
+
+ /* Check if it exists, remove if yes*/
+ if ((stat(eaname, &st)) == 0) {
+ if ((unlink(eaname)) != 0) {
+ if (errno == EACCES)
+ return AFPERR_ACCESS;
+ else
+ return AFPERR_MISC;
+ }
+ }
+
+ if ((fd = open(eaname, O_RDWR | O_CREAT | O_EXCL, 0666 & ~ea->vol->v_umask)) == -1) {
+ LOG(log_error, logtype_afpd, "write_ea: open race condition: %s", eaname);
+ return -1;
+ }
+
+ /* lock it */
+ if ((write_lock(fd, 0, SEEK_SET, 0)) != 0) {
+ LOG(log_error, logtype_afpd, "write_ea: open race condition: %s", eaname);
+ ret = -1;
+ goto exit;
+ }
+
+ if (write(fd, ibuf, attrsize) != (ssize_t)attrsize) {
+ LOG(log_error, logtype_afpd, "write_ea('%s'): write: %s", eaname, strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+
+exit:
+ if (fd != -1)
+ close(fd); /* and unlock */
+ return ret;
+}
+
+/*
+ * Function: ea_delentry
+ *
+ * Purpose: delete one EA from ea->ea_entries[]
+ *
+ * Arguments:
+ *
+ * ea (rw) pointer to struct ea
+ * attruname (r) EA name
+ *
+ * Returns: new number of EA entries, -1 on error
+ *
+ * Effects:
+ *
+ * Remove entry from ea->ea_entries[]. Decrement ea->ea_count.
+ * Marks it as unused just by freeing name and setting it to NULL.
+ * ea_close and pack_buffer must honor this.
+ */
+static int ea_delentry(struct ea * restrict ea, const char * restrict attruname)
+{
+ int ret = 0;
+ unsigned int count = 0;
+
+ if (ea->ea_count == 0) {
- if (strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
++ LOG(log_error, logtype_afpd, "ea_delentry('%s'): illegal ea_count of 0 on deletion",
++ attruname);
+ return -1;
+ }
+
+ while (count < ea->ea_count) {
+ /* search matching EA */
++ if ((*ea->ea_entries)[count].ea_name &&
++ strcmp(attruname, (*ea->ea_entries)[count].ea_name) == 0) {
+ free((*ea->ea_entries)[count].ea_name);
+ (*ea->ea_entries)[count].ea_name = NULL;
+
+ LOG(log_debug, logtype_afpd, "ea_delentry('%s'): deleted no %u/%u",
+ attruname, count + 1, ea->ea_count);
+
+ break;
+ }
+ count++;
+ }
+
+ return ret;
+}
+
+/*
+ * Function: delete_ea_file
+ *
+ * Purpose: delete EA file from disk
+ *
+ * Arguments:
+ *
+ * ea (r) struct ea handle
+ * attruname (r) EA name
+ *
+ * Returns: 0 on success, -1 on error
+ */
+static int delete_ea_file(const struct ea * restrict ea, const char *eaname)
+{
+ int ret = 0;
+ char *eafile;
+ struct stat st;
+
+ if ((eafile = ea_path(ea, eaname, 1)) == NULL) {
+ LOG(log_error, logtype_afpd, "delete_ea_file('%s'): ea_path error", eaname);
+ return -1;
+ }
+
+ /* Check if it exists, remove if yes*/
+ if ((stat(eafile, &st)) == 0) {
+ if ((unlink(eafile)) != 0) {
+ LOG(log_error, logtype_afpd, "delete_ea_file('%s'): unlink: %s",
+ eafile, strerror(errno));
+ ret = -1;
+ } else
+ LOG(log_debug, logtype_afpd, "delete_ea_file('%s'): success", eafile);
+ }
+
+ return ret;
+}
+
+/*************************************************************************************
+ * ea_path, ea_open and ea_close are only global so that dbd can call them
+ *************************************************************************************/
+
+/*
+ * Function: ea_path
+ *
+ * Purpose: return name of ea header filename
+ *
+ * Arguments:
+ *
+ * ea (r) ea handle
+ * eaname (r) name of EA or NULL
+ * macname (r) if != 0 call mtoupath on eaname
+ *
+ * Returns: pointer to name in static buffer, NULL on error
+ *
+ * Effects:
+ *
+ * Calls ad_open, copies buffer, appends "::EA" and if supplied append eanme
+ * Files: "file" -> "file/.AppleDouble/file::EA"
+ * Dirs: "dir" -> "dir/.AppleDouble/.Parent::EA"
+ * "file" with EA "myEA" -> "file/.AppleDouble/file::EA:myEA"
+ */
+char *ea_path(const struct ea * restrict ea, const char * restrict eaname, int macname)
+{
+ const char *adname;
+ static char pathbuf[MAXPATHLEN + 1];
+
+ /* get name of a adouble file from uname */
+ adname = ea->vol->ad_path(ea->filename, (ea->ea_flags & EA_DIR) ? ADFLAGS_DIR : 0);
+ /* copy it so we can work with it */
+ strlcpy(pathbuf, adname, MAXPATHLEN + 1);
+ /* append "::EA" */
+ strlcat(pathbuf, "::EA", MAXPATHLEN + 1);
+
+ if (eaname) {
+ strlcat(pathbuf, "::", MAXPATHLEN + 1);
+ if (macname)
+ if ((eaname = mtoupath(ea->vol, eaname)) == NULL)
+ return NULL;
+ strlcat(pathbuf, eaname, MAXPATHLEN + 1);
+ }
+
+ return pathbuf;
+}
+
+/*
+ * Function: ea_open
+ *
+ * Purpose: open EA header file, create if it doesnt exits and called with O_CREATE
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * uname (r) filename for which we have to open a header
+ * flags (r) EA_CREATE: create if it doesn't exist (without it won't be created)
+ * EA_RDONLY: open read only
+ * EA_RDWR: open read/write
+ * Eiterh EA_RDONLY or EA_RDWR MUST be requested
+ * ea (w) pointer to a struct ea that we fill
+ *
+ * Returns: 0 on success
+ * -1 on misc error with errno = EFAULT
+ * -2 if no EA header exists with errno = ENOENT
+ *
+ * Effects:
+ *
+ * opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size.
+ * number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags.
+ * file is either read or write locked depending on the open flags.
+ * When you're done with struct ea you must call ea_close on it.
+ */
+int ea_open(const struct vol * restrict vol,
+ const char * restrict uname,
+ eaflags_t eaflags,
+ struct ea * restrict ea)
+{
+ int ret = 0;
+ char *eaname;
+ struct stat st;
+
+ /* Enforce usage rules! */
+ if ( ! (eaflags & (EA_RDONLY | EA_RDWR))) {
+ LOG(log_error, logtype_afpd, "ea_open: called without EA_RDONLY | EA_RDWR", uname);
+ return -1;
+ }
+
+ /* Set it all to 0 */
+ memset(ea, 0, sizeof(struct ea));
+
+ ea->vol = vol; /* ea_close needs it */
+ ea->ea_flags = eaflags;
+ ea->dirfd = -1; /* no *at (cf openat) semantics by default */
+
+ /* Dont care for errors, eg when removing the file is already gone */
+ if (!stat(uname, &st) && S_ISDIR(st.st_mode))
+ ea->ea_flags |= EA_DIR;
+
+ if ( ! (ea->filename = strdup(uname))) {
+ LOG(log_error, logtype_afpd, "ea_open: OOM");
+ return -1;
+ }
+
+ eaname = ea_path(ea, NULL, 0);
+ LOG(log_maxdebug, logtype_afpd, "ea_open: ea_path: %s", eaname);
+
+ /* Check if it exists, if not create it if EA_CREATE is in eaflags */
+ if ((stat(eaname, &st)) != 0) {
+ if (errno == ENOENT) {
+
+ /* It doesnt exist */
+
+ if ( ! (eaflags & EA_CREATE)) {
+ /* creation was not requested, so return with error */
+ ret = -2;
+ goto exit;
+ }
+
+ /* Now create a header file */
+
+ /* malloc buffer for minimal on disk data */
+ ea->ea_data = malloc(EA_HEADER_SIZE);
+ if (! ea->ea_data) {
+ LOG(log_error, logtype_afpd, "ea_open: OOM");
+ ret = -1;
+ goto exit;
+ }
+
+ /* create it */
+ ea->ea_fd = create_ea_header(eaname, ea);
+ if (ea->ea_fd == -1) {
+ ret = -1;
+ goto exit;
+ }
+
+ return 0;
+
+ } else {/* errno != ENOENT */
+ ret = -1;
+ goto exit;
+ }
+ }
+
+ /* header file exists, so read and parse it */
+
+ /* malloc buffer where we read disk file into */
+ if (st.st_size < EA_HEADER_SIZE) {
+ LOG(log_error, logtype_afpd, "ea_open('%s'): bogus EA header file", eaname);
+ ret = -1;
+ goto exit;
+ }
+ ea->ea_size = st.st_size;
+ ea->ea_data = malloc(st.st_size);
+ if (! ea->ea_data) {
+ LOG(log_error, logtype_afpd, "ea_open: OOM");
+ ret = -1;
+ goto exit;
+ }
+
+ /* Now lock, open and read header file from disk */
+ if ((ea->ea_fd = open(eaname, (ea->ea_flags & EA_RDWR) ? O_RDWR : O_RDONLY)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_open('%s'): error: %s", eaname, strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+
+ /* lock it */
+ if (ea->ea_flags & EA_RDONLY) {
+ /* read lock */
+ if ((read_lock(ea->ea_fd, 0, SEEK_SET, 0)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_open: lock error on header: %s", eaname);
+ ret = -1;
+ goto exit;
+ }
+ } else { /* EA_RDWR */
+ /* write lock */
+ if ((write_lock(ea->ea_fd, 0, SEEK_SET, 0)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_open: lock error on header: %s", eaname);
+ ret = -1;
+ goto exit;
+ }
+ }
+
+ /* read it */
+ if (read(ea->ea_fd, ea->ea_data, ea->ea_size) != (ssize_t)ea->ea_size) {
+ LOG(log_error, logtype_afpd, "ea_open: short read on header: %s", eaname);
+ ret = -1;
+ goto exit;
+ }
+
+ if ((unpack_header(ea)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_open: error unpacking header for: %s", eaname);
+ ret = -1;
+ goto exit;
+ }
+
+exit:
+ switch (ret) {
+ case 0:
+ ea->ea_inited = EA_INITED;
+ break;
+ case -1:
+ errno = EFAULT; /* force some errno distinguishable from ENOENT */
+ /* fall through */
+ case -2:
+ if (ea->ea_data) {
+ free(ea->ea_data);
+ ea->ea_data = NULL;
+ }
+ if (ea->ea_fd) {
+ close(ea->ea_fd);
+ ea->ea_fd = -1;
+ }
+ break;
+ }
+
+ return ret;
+}
+
+/*
+ * Function: ea_openat
+ *
+ * Purpose: openat like wrapper for ea_open, takes a additional file descriptor
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * sfd (r) openat like file descriptor
+ * uname (r) filename for which we have to open a header
+ * flags (r) EA_CREATE: create if it doesn't exist (without it won't be created)
+ * EA_RDONLY: open read only
+ * EA_RDWR: open read/write
+ * Eiterh EA_RDONLY or EA_RDWR MUST be requested
+ * ea (w) pointer to a struct ea that we fill
+ *
+ * Returns: 0 on success
+ * -1 on misc error with errno = EFAULT
+ * -2 if no EA header exists with errno = ENOENT
+ *
+ * Effects:
+ *
+ * opens header file and stores fd in ea->ea_fd. Size of file is put into ea->ea_size.
+ * number of EAs is stored in ea->ea_count. flags are remembered in ea->ea_flags.
+ * file is either read or write locked depending on the open flags.
+ * When you're done with struct ea you must call ea_close on it.
+ */
+int ea_openat(const struct vol * restrict vol,
+ int dirfd,
+ const char * restrict uname,
+ eaflags_t eaflags,
+ struct ea * restrict ea)
+{
+ int ret = 0;
+ int cwdfd = -1;
+
+ if (dirfd != -1) {
+ if (((cwdfd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
+ ret = -1;
+ goto exit;
+ }
+ }
+
+ ret = ea_open(vol, uname, eaflags, ea);
+ ea->dirfd = dirfd;
+
+ if (dirfd != -1) {
+ if (fchdir(cwdfd) != 0) {
+ LOG(log_error, logtype_afpd, "ea_openat: cant chdir back, exiting");
+ exit(EXITERR_SYS);
+ }
+ }
+
+
+exit:
+ if (cwdfd != -1)
+ close(cwdfd);
+
+ return ret;
+
+}
+
+/*
+ * Function: ea_close
+ *
+ * Purpose: flushes and closes an ea handle
+ *
+ * Arguments:
+ *
+ * ea (rw) pointer to ea handle
+ *
+ * Returns: 0 on success, -1 on error
+ *
+ * Effects:
+ *
+ * Flushes and then closes and frees all resouces held by ea handle.
+ * Pack data in ea into ea_data, then write ea_data to disk
+ */
+int ea_close(struct ea * restrict ea)
+{
+ int ret = 0;
+ unsigned int count = 0;
+ char *eaname;
+ struct stat st;
+
+ LOG(log_debug, logtype_afpd, "ea_close('%s')", ea->filename);
+
+ if (ea->ea_inited != EA_INITED) {
+ LOG(log_warning, logtype_afpd, "ea_close('%s'): non initialized ea", ea->filename);
+ return 0;
+ }
+
+ /* pack header and write it to disk if it was opened EA_RDWR*/
+ if (ea->ea_flags & EA_RDWR) {
+ if ((pack_header(ea)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_close: pack header");
+ ret = -1;
+ } else {
+ if (ea->ea_count == 0) {
+ /* Check if EA header exists and remove it */
+ eaname = ea_path(ea, NULL, 0);
+ if ((lstatat(ea->dirfd, eaname, &st)) == 0) {
+ if ((netatalk_unlinkat(ea->dirfd, eaname)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_close('%s'): unlink: %s",
+ eaname, strerror(errno));
+ ret = -1;
+ }
+ else
+ LOG(log_debug, logtype_afpd, "ea_close(unlink '%s'): success", eaname);
+ } else {
+ /* stat error */
+ if (errno != ENOENT) {
+ LOG(log_error, logtype_afpd, "ea_close('%s'): stat: %s",
+ eaname, strerror(errno));
+ ret = -1;
+ }
+ }
+ } else { /* ea->ea_count > 0 */
+ if ((lseek(ea->ea_fd, 0, SEEK_SET)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_close: lseek: %s", strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+
+ if ((ftruncate(ea->ea_fd, 0)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_close: ftruncate: %s", strerror(errno));
+ ret = -1;
+ goto exit;
+ }
+
+ if (write(ea->ea_fd, ea->ea_data, ea->ea_size) != (ssize_t)ea->ea_size) {
+ LOG(log_error, logtype_afpd, "ea_close: write: %s", strerror(errno));
+ ret = -1;
+ }
+ }
+ }
+ }
+
+exit:
+ /* free names */
+ while(count < ea->ea_count) {
+ if ( (*ea->ea_entries)[count].ea_name ) {
+ free((*ea->ea_entries)[count].ea_name);
+ (*ea->ea_entries)[count].ea_name = NULL;
+ }
+ count++;
+ }
+ ea->ea_count = 0;
+
+ if (ea->filename) {
+ free(ea->filename);
+ ea->filename = NULL;
+ }
+
+ if (ea->ea_entries) {
+ free(ea->ea_entries);
+ ea->ea_entries = NULL;
+ }
+
+ if (ea->ea_data) {
+ free(ea->ea_data);
+ ea->ea_data = NULL;
+ }
+ if (ea->ea_fd != -1) {
+ close(ea->ea_fd); /* also releases the fcntl lock */
+ ea->ea_fd = -1;
+ }
+
+ return 0;
+}
+
+
+
+/************************************************************************************
+ * VFS funcs called from afp_ea* funcs
+ ************************************************************************************/
+
+/*
+ * Function: get_easize
+ *
+ * Purpose: get size of an EA
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * rbuf (w) DSI reply buffer
+ * rbuflen (rw) current length of data in reply buffer
+ * uname (r) filename
+ * oflag (r) link and create flag
+ * attruname (r) name of attribute
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Copies EA size into rbuf in network order. Increments *rbuflen +4.
+ */
+int get_easize(VFS_FUNC_ARGS_EA_GETSIZE)
+{
+ int ret = AFPERR_MISC;
+ unsigned int count = 0;
+ uint32_t uint32;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "get_easize: file: %s", uname);
+
+ if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) {
+ if (errno != ENOENT)
+ LOG(log_error, logtype_afpd, "get_easize: error calling ea_open for file: %s", uname);
+
+ memset(rbuf, 0, 4);
+ *rbuflen += 4;
+ return ret;
+ }
+
+ while (count < ea.ea_count) {
+ if (strcmp(attruname, (*ea.ea_entries)[count].ea_name) == 0) {
+ uint32 = htonl((*ea.ea_entries)[count].ea_size);
+ memcpy(rbuf, &uint32, 4);
+ *rbuflen += 4;
+ ret = AFP_OK;
+
+ LOG(log_debug, logtype_afpd, "get_easize(\"%s\"): size: %u",
+ attruname, (*ea.ea_entries)[count].ea_size);
+ break;
+ }
+ count++;
+ }
+
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "get_easize: error closing ea handle for file: %s", uname);
+ return AFPERR_MISC;
+ }
+
+ return ret;
+}
+
+/*
+ * Function: get_eacontent
+ *
+ * Purpose: copy EA into rbuf
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * rbuf (w) DSI reply buffer
+ * rbuflen (rw) current length of data in reply buffer
+ * uname (r) filename
+ * oflag (r) link and create flag
+ * attruname (r) name of attribute
+ * maxreply (r) maximum EA size as of current specs/real-life
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Copies EA into rbuf. Increments *rbuflen accordingly.
+ */
+int get_eacontent(VFS_FUNC_ARGS_EA_GETCONTENT)
+{
+ int ret = AFPERR_MISC, fd = -1;
+ unsigned int count = 0;
+ uint32_t uint32;
+ size_t toread;
+ struct ea ea;
+ char *eafile;
+
+ LOG(log_debug, logtype_afpd, "get_eacontent('%s/%s')", uname, attruname);
+
+ if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) {
+ if (errno != ENOENT)
+ LOG(log_error, logtype_afpd, "get_eacontent('%s'): ea_open error", uname);
+ memset(rbuf, 0, 4);
+ *rbuflen += 4;
+ return ret;
+ }
+
+ while (count < ea.ea_count) {
+ if (strcmp(attruname, (*ea.ea_entries)[count].ea_name) == 0) {
+ if ( (eafile = ea_path(&ea, attruname, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ break;
+ }
+
+ if ((fd = open(eafile, O_RDONLY)) == -1) {
+ LOG(log_error, logtype_afpd, "get_eacontent('%s'): open error: %s", uname, strerror(errno));
+ ret = AFPERR_MISC;
+ break;
+ }
+
+ /* Check how much the client wants, give him what we think is right */
+ maxreply -= MAX_REPLY_EXTRA_BYTES;
+ if (maxreply > MAX_EA_SIZE)
+ maxreply = MAX_EA_SIZE;
+ toread = (maxreply < (*ea.ea_entries)[count].ea_size) ? maxreply : (*ea.ea_entries)[count].ea_size;
+ LOG(log_debug, logtype_afpd, "get_eacontent('%s'): sending %u bytes", attruname, toread);
+
+ /* Put length of EA data in reply buffer */
+ uint32 = htonl(toread);
+ memcpy(rbuf, &uint32, 4);
+ rbuf += 4;
+ *rbuflen += 4;
+
+ if (read(fd, rbuf, toread) != (ssize_t)toread) {
+ LOG(log_error, logtype_afpd, "get_eacontent('%s/%s'): short read", uname, attruname);
+ close(fd);
+ ret = AFPERR_MISC;
+ break;
+ }
+ *rbuflen += toread;
+ close(fd);
+
+ ret = AFP_OK;
+ break;
+ }
+ count++;
+ }
+
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "get_eacontent('%s'): error closing ea handle", uname);
+ return AFPERR_MISC;
+ }
+
+ return ret;
+
+}
+
+/*
+ * Function: list_eas
+ *
+ * Purpose: copy names of EAs into attrnamebuf
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * attrnamebuf (w) store names a consecutive C strings here
+ * buflen (rw) length of names in attrnamebuf
+ * uname (r) filename
+ * oflag (r) link and create flag
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Copies names of all EAs of uname as consecutive C strings into rbuf.
+ * Increments *buflen accordingly.
+ */
+int list_eas(VFS_FUNC_ARGS_EA_LIST)
+{
+ unsigned int count = 0;
+ int attrbuflen = *buflen, ret = AFP_OK, len;
+ char *buf = attrnamebuf;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "list_eas: file: %s", uname);
+
+ if ((ea_open(vol, uname, EA_RDONLY, &ea)) != 0) {
+ if (errno != ENOENT) {
+ LOG(log_error, logtype_afpd, "list_eas: error calling ea_open for file: %s", uname);
+ return AFPERR_MISC;
+ }
+ else
+ return AFP_OK;
+ }
+
+ while (count < ea.ea_count) {
+ /* Convert name to CH_UTF8_MAC and directly store in in the reply buffer */
+ if ( ( len = convert_string(vol->v_volcharset,
+ CH_UTF8_MAC,
+ (*ea.ea_entries)[count].ea_name,
+ (*ea.ea_entries)[count].ea_namelen,
+ buf + attrbuflen,
+ 255))
+ <= 0 ) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ if (len == 255)
+ /* convert_string didn't 0-terminate */
+ attrnamebuf[attrbuflen + 255] = 0;
+
+ LOG(log_debug7, logtype_afpd, "list_eas(%s): EA: %s",
+ uname, (*ea.ea_entries)[count].ea_name);
+
+ attrbuflen += len + 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, "list_eas(%s): running out of buffer for EA names", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ count++;
+ }
+
+exit:
+ *buflen = attrbuflen;
+
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "list_eas: error closing ea handle for file: %s", uname);
+ return AFPERR_MISC;
+ }
+
+ return ret;
+}
+
+/*
+ * Function: set_ea
+ *
+ * Purpose: set a Solaris native EA
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * uname (r) filename
+ * attruname (r) EA name
+ * ibuf (r) buffer with EA content
+ * attrsize (r) length EA in ibuf
+ * oflag (r) link and create flag
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Copies names of all EAs of uname as consecutive C strings into rbuf.
+ * Increments *rbuflen accordingly.
+ */
+int set_ea(VFS_FUNC_ARGS_EA_SET)
+{
+ int ret = AFP_OK;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "set_ea: file: %s", uname);
+
+ if ((ea_open(vol, uname, EA_CREATE | EA_RDWR, &ea)) != 0) {
+ LOG(log_error, logtype_afpd, "set_ea('%s'): ea_open error", uname);
+ return AFPERR_MISC;
+ }
+
+ if ((ea_addentry(&ea, attruname, attrsize, oflag)) == -1) {
+ LOG(log_error, logtype_afpd, "set_ea('%s'): ea_addentry error", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ if ((write_ea(&ea, attruname, ibuf, attrsize)) != 0) {
+ LOG(log_error, logtype_afpd, "set_ea('%s'): write_ea error", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+exit:
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "set_ea('%s'): ea_close error", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ return ret;
+}
+
+/*
+ * Function: remove_ea
+ *
+ * Purpose: remove a EA from a file
+ *
+ * Arguments:
+ *
+ * vol (r) current volume
+ * uname (r) filename
+ * attruname (r) EA name
+ * oflag (r) link and create flag
+ *
+ * Returns: AFP code: AFP_OK on success or appropiate AFP error code
+ *
+ * Effects:
+ *
+ * Removes EA attruname from file uname.
+ */
+int remove_ea(VFS_FUNC_ARGS_EA_REMOVE)
+{
+ int ret = AFP_OK;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "remove_ea('%s/%s')", uname, attruname);
+
+ if ((ea_open(vol, uname, EA_RDWR, &ea)) != 0) {
+ LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_open error", uname);
+ return AFPERR_MISC;
+ }
+
+ if ((ea_delentry(&ea, attruname)) == -1) {
+ LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_delentry error", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ if ((delete_ea_file(&ea, attruname)) != 0) {
+ LOG(log_error, logtype_afpd, "remove_ea('%s'): delete_ea error", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+exit:
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "remove_ea('%s'): ea_close error", uname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ return ret;
+}
+
+/******************************************************************************************
+ * EA VFS funcs that deal with file/dir cp/mv/rm
+ ******************************************************************************************/
+
+int ea_deletefile(VFS_FUNC_ARGS_DELETEFILE)
+{
+ unsigned int count = 0;
+ int ret = AFP_OK;
+ int cwd = -1;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "ea_deletefile('%s')", file);
+
+ /* Open EA stuff */
+ if ((ea_openat(vol, dirfd, file, EA_RDWR, &ea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else {
+ LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error calling ea_open", file);
+ return AFPERR_MISC;
+ }
+ }
+
+ if (dirfd != -1) {
+ if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+
+ while (count < ea.ea_count) {
+ if ((delete_ea_file(&ea, (*ea.ea_entries)[count].ea_name)) != 0) {
+ ret = AFPERR_MISC;
+ continue;
+ }
+ free((*ea.ea_entries)[count].ea_name);
+ (*ea.ea_entries)[count].ea_name = NULL;
+ count++;
+ }
+
+ /* ea_close removes the EA header file for us because all names are NULL */
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_deletefile('%s'): error closing ea handle", file);
+ ret = AFPERR_MISC;
+ }
+
+ if (dirfd != -1 && fchdir(cwd) != 0) {
+ LOG(log_error, logtype_afpd, "ea_deletefile: cant chdir back. exit!");
+ exit(EXITERR_SYS);
+ }
+
+exit:
+ if (cwd != -1)
+ close(cwd);
+
+ return ret;
+}
+
+int ea_renamefile(VFS_FUNC_ARGS_RENAMEFILE)
+{
+ unsigned int count = 0;
+ int ret = AFP_OK;
+ size_t easize;
+ char srceapath[ MAXPATHLEN + 1];
+ char *eapath;
+ char *eaname;
+ struct ea srcea;
+ struct ea dstea;
+ struct adouble ad;
+
+ LOG(log_debug, logtype_afpd, "ea_renamefile('%s'/'%s')", src, dst);
+
+
+ /* Open EA stuff */
+ if ((ea_openat(vol, dirfd, src, EA_RDWR, &srcea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s'/'%s'): ea_open error: '%s'", src, dst, src);
+ return AFPERR_MISC;
+ }
+ }
+
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ if (errno == ENOENT) {
+ /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
+ ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): ad_open error: '%s'", src, dst, dst);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ ad_close(&ad, ADFLAGS_HF);
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+ }
+
+ /* Loop through all EAs: */
+ while (count < srcea.ea_count) {
+ /* Move EA */
+ eaname = (*srcea.ea_entries)[count].ea_name;
+ easize = (*srcea.ea_entries)[count].ea_size;
+
+ /* Build src and dst paths for rename() */
+ if ((eapath = ea_path(&srcea, eaname, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ strcpy(srceapath, eapath);
+ if ((eapath = ea_path(&dstea, eaname, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ LOG(log_maxdebug, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+
+ /* Add EA to dstea */
+ if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ /* Remove EA entry from srcea */
+ if ((ea_delentry(&srcea, eaname)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ea_delentry(&dstea, eaname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ /* Now rename the EA */
+ if ((unix_rename(dirfd, srceapath, -1, eapath)) < 0) {
+ LOG(log_error, logtype_afpd, "ea_renamefile('%s/%s'): moving EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ count++;
+ }
+
+
+exit:
+ ea_close(&srcea);
+ ea_close(&dstea);
+ return ret;
+}
+
+int ea_copyfile(VFS_FUNC_ARGS_COPYFILE)
+{
+ unsigned int count = 0;
+ int ret = AFP_OK;
+ size_t easize;
+ char srceapath[ MAXPATHLEN + 1];
+ char *eapath;
+ char *eaname;
+ struct ea srcea;
+ struct ea dstea;
+ struct adouble ad;
+
+ LOG(log_debug, logtype_afpd, "ea_copyfile('%s'/'%s')", src, dst);
+
+ /* Open EA stuff */
+ if ((ea_openat(vol, sfd, src, EA_RDWR, &srcea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s'/'%s'): ea_open error: '%s'", src, dst, src);
+ return AFPERR_MISC;
+ }
+ }
+
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ if (errno == ENOENT) {
+ /* Possibly the .AppleDouble folder didn't exist, we create it and try again */
+ ad_init(&ad, vol->v_adouble, vol->v_ad_options);
+ if ((ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ad_open error: '%s'", src, dst, dst);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ ad_close(&ad, ADFLAGS_HF);
+ if ((ea_open(vol, dst, EA_RDWR | EA_CREATE, &dstea)) != 0) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+ }
+
+ /* Loop through all EAs: */
+ while (count < srcea.ea_count) {
+ /* Copy EA */
+ eaname = (*srcea.ea_entries)[count].ea_name;
+ easize = (*srcea.ea_entries)[count].ea_size;
+
+ /* Build src and dst paths for copy_file() */
+ if ((eapath = ea_path(&srcea, eaname, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ strcpy(srceapath, eapath);
+ if ((eapath = ea_path(&dstea, eaname, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ LOG(log_maxdebug, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+
+ /* Add EA to dstea */
+ if ((ea_addentry(&dstea, eaname, easize, 0)) == -1) {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): ea_addentry('%s') error",
+ src, dst, eaname);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ /* Now copy the EA */
+ if ((copy_file(sfd, srceapath, eapath, (0666 & ~vol->v_umask))) < 0) {
+ LOG(log_error, logtype_afpd, "ea_copyfile('%s/%s'): copying EA '%s' to '%s'",
+ src, dst, srceapath, eapath);
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+
+ count++;
+ }
+
+exit:
+ ea_close(&srcea);
+ ea_close(&dstea);
+ return ret;
+}
+
+int ea_chown(VFS_FUNC_ARGS_CHOWN)
+{
+
+ unsigned int count = 0;
+ int ret = AFP_OK;
+ char *eaname;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "ea_chown('%s')", path);
+ /* Open EA stuff */
+ if ((ea_open(vol, path, EA_RDWR, &ea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else {
+ LOG(log_error, logtype_afpd, "ea_chown('%s'): error calling ea_open", path);
+ return AFPERR_MISC;
+ }
+ }
+
+ if ((lchown(ea_path(&ea, NULL, 0), uid, gid)) != 0) {
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ ret = AFPERR_ACCESS;
+ goto exit;
+ default:
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+
+ while (count < ea.ea_count) {
+ if ((eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ if ((lchown(eaname, uid, gid)) != 0) {
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ ret = AFPERR_ACCESS;
+ goto exit;
+ default:
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ continue;
+ }
+
+ count++;
+ }
+
+exit:
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_chown('%s'): error closing ea handle", path);
+ return AFPERR_MISC;
+ }
+
+ return ret;
+}
+
+int ea_chmod_file(VFS_FUNC_ARGS_SETFILEMODE)
+{
+
+ unsigned int count = 0;
+ int ret = AFP_OK;
+ const char *eaname;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "ea_chmod_file('%s')", name);
+ /* Open EA stuff */
+ if ((ea_open(vol, name, EA_RDWR, &ea)) != 0) {
+ if (errno == ENOENT)
+ /* no EA files, nothing to do */
+ return AFP_OK;
+ else
+ return AFPERR_MISC;
+ }
+
+ /* Set mode on EA header file */
+ if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ ret = AFPERR_ACCESS;
+ goto exit;
+ default:
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+
+ /* Set mode on EA files */
+ while (count < ea.ea_count) {
+ if ((eaname = ea_path(&ea, (*ea.ea_entries)[count].ea_name, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): %s", eaname, strerror(errno));
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ ret = AFPERR_ACCESS;
+ goto exit;
+ default:
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ continue;
+ }
+
+ count++;
+ }
+
+exit:
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_chmod_file('%s'): error closing ea handle", name);
+ return AFPERR_MISC;
+ }
+
+ return ret;
+}
+
+int ea_chmod_dir(VFS_FUNC_ARGS_SETDIRUNIXMODE)
+{
+
+ int ret = AFP_OK;
+ unsigned int count = 0;
+ uid_t uid;
+ const char *eaname;
+ const char *eaname_safe = NULL;
+ struct ea ea;
+
+ LOG(log_debug, logtype_afpd, "ea_chmod_dir('%s')", name);
+ /* .AppleDouble already might be inaccesible, so we must run as id 0 */
+ uid = geteuid();
+ if (seteuid(0)) {
+ LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): seteuid: %s", name, strerror(errno));
+ return AFPERR_MISC;
+ }
+
+ /* Open EA stuff */
+ if ((ea_open(vol, name, EA_RDWR, &ea)) != 0) {
+ /* ENOENT --> no EA files, nothing to do */
+ if (errno != ENOENT)
+ ret = AFPERR_MISC;
+ if (seteuid(uid) < 0) {
+ LOG(log_error, logtype_afpd, "can't seteuid back: %s", strerror(errno));
+ exit(EXITERR_SYS);
+ }
+ return ret;
+ }
+
+ /* Set mode on EA header */
+ if ((setfilmode(ea_path(&ea, NULL, 0), ea_header_mode(mode), NULL, vol->v_umask)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", ea_path(&ea, NULL, 0), strerror(errno));
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ ret = AFPERR_ACCESS;
+ goto exit;
+ default:
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ }
+
+ /* Set mode on EA files */
+ while (count < ea.ea_count) {
+ eaname = (*ea.ea_entries)[count].ea_name;
+ /*
+ * Be careful with EA names from the EA header!
+ * Eg NFS users might have access to them, can inject paths using ../ or /.....
+ * FIXME:
+ * Until the EA code escapes / in EA name requests from the client, these therefor wont work.
+ */
+ if ((eaname_safe = strrchr(eaname, '/'))) {
+ LOG(log_warning, logtype_afpd, "ea_chmod_dir('%s'): contains a slash", eaname);
+ eaname = eaname_safe;
+ }
+ if ((eaname = ea_path(&ea, eaname, 1)) == NULL) {
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ if ((setfilmode(eaname, ea_mode(mode), NULL, vol->v_umask)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): %s", eaname, strerror(errno));
+ switch (errno) {
+ case EPERM:
+ case EACCES:
+ ret = AFPERR_ACCESS;
+ goto exit;
+ default:
+ ret = AFPERR_MISC;
+ goto exit;
+ }
+ continue;
+ }
+
+ count++;
+ }
+
+exit:
+ if (seteuid(uid) < 0) {
+ LOG(log_error, logtype_afpd, "can't seteuid back: %s", strerror(errno));
+ exit(EXITERR_SYS);
+ }
+
+ if ((ea_close(&ea)) != 0) {
+ LOG(log_error, logtype_afpd, "ea_chmod_dir('%s'): error closing ea handle", name);
+ return AFPERR_MISC;
+ }
+
+ return ret;
+}
#include <atalk/logger.h>
#include <atalk/unix.h>
#include <atalk/acl.h>
+#include <atalk/compat.h>
/* -----------------------------
a dropbox is a folder where w is set but not r eg:
{
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_acl( 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.
*/
- if ( (chmod( name, (DIRBITS | mode) & ~v_umask ) < 0) && errno != EPERM &&
+ if ( (chmod_acl( name, (DIRBITS | mode) & ~v_umask ) < 0) && errno != EPERM &&
!(errno == ENOENT && (dropbox & AFPVOL_NOADOUBLE)) )
{
LOG(log_error, logtype_afpd, "stickydirmode: chmod \"%s\": %s", fullpathname(name), strerror(errno) );
mode |= st->st_mode & ~mask; /* keep other bits from previous mode */
- if ( chmod( name, mode & ~v_umask ) < 0 && errno != EPERM ) {
+ if ( chmod_acl( name, mode & ~v_umask ) < 0 && errno != EPERM ) {
return -1;
}
return 0;
return AFP_OK;
}
- char *fullpathname(const char *name)
- {
- static char wd[ MAXPATHLEN + 1];
-
- if ( getcwd( wd , MAXPATHLEN) ) {
- strlcat(wd, "/", MAXPATHLEN);
- strlcat(wd, name, MAXPATHLEN);
- }
- else {
- strlcpy(wd, name, MAXPATHLEN);
- }
- return wd;
- }
-
-
/**************************************************************************
* *at semnatics support functions (like openat, renameat standard funcs)
**************************************************************************/
sfd = open(src, O_RDONLY);
#endif
if (sfd < 0) {
- LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
+ LOG(log_info, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
src, dst, src, strerror(errno));
return -1;
}
if ((dfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, mode)) < 0) {
- LOG(log_error, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
+ LOG(log_info, logtype_afpd, "copy_file('%s'/'%s'): open '%s' error: %s",
src, dst, dst, strerror(errno));
ret = -1;
goto exit;
#include <atalk/errchk.h>
#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
+#include <atalk/compat.h>
struct perm {
uid_t uid;
static int RF_chown_adouble(VFS_FUNC_ARGS_CHOWN)
{
struct stat st;
- char *ad_p;
+ const char *ad_p;
ad_p = vol->ad_path(path, ADFLAGS_HF );
/* ----------------- */
static int RF_setdirunixmode_adouble(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
+ const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
int dropbox = vol->v_flags;
if (dir_rx_set(mode)) {
{
int dropbox = vol->v_flags;
mode_t hf_mode = ad_hf_mode(mode);
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char *adouble_p = ad_dir(adouble);
+ const char *adouble = vol->ad_path(name, ADFLAGS_DIR );
+ const char *adouble_p = ad_dir(adouble);
if (dir_rx_set(mode)) {
if (stickydirmode(ad_dir(adouble), DIRBITS | mode, dropbox, vol->v_umask) < 0)
* use a diff one, it's not a pb,ie it's not the same file, yet.
*/
ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
+ if (ad_open(&ad, dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666) == 0) {
ad_close(&ad, ADFLAGS_HF);
if (!unix_rename(dirfd, adsrc, -1, vol->ad_path(dst, 0 )) )
err = 0;
}
#endif
-/*********************************************************************************
- * sfm adouble format
- *********************************************************************************/
-static int ads_chown_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
-{
- struct perm *owner = data;
-
- if (chown( name , owner->uid, owner->gid ) < 0) {
- return -1;
- }
- return 0;
-}
-
-static int RF_chown_ads(VFS_FUNC_ARGS_CHOWN)
-{
- struct stat st;
- char *ad_p;
- struct perm owner;
-
- owner.uid = uid;
- owner.gid = gid;
-
-
- ad_p = ad_dir(vol->ad_path(path, ADFLAGS_HF ));
-
- if ( stat( ad_p, &st ) < 0 ) {
- /* ignore */
- return 0;
- }
-
- if (chown( ad_p, uid, gid ) < 0) {
- return -1;
- }
- return for_each_adouble("chown_ads", ad_p, ads_chown_loop, &owner, 1, vol->v_umask);
-}
-
-/* --------------------------------- */
-static int deletecurdir_ads1_loop(struct dirent *de _U_, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
-{
- return netatalk_unlink(name);
-}
-
-static int ads_delete_rf(char *name)
-{
- int err;
-
- if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0)))
- return err;
- /* FIXME
- * it's a problem for a nfs mounted folder, there's .nfsxxx around
- * for linux the following line solve it.
- * but it could fail if rm .nfsxxx create a new .nfsyyy :(
- */
- if ((err = for_each_adouble("deletecurdir", name, deletecurdir_ads1_loop, NULL, 1, 0)))
- return err;
- return netatalk_rmdir(-1, name);
-}
-
-static int deletecurdir_ads_loop(struct dirent *de, char *name, void *data _U_, int flag _U_, mode_t v_umask _U_)
-{
- struct stat st;
-
- /* bail if the file exists in the current directory.
- * note: this will not fail with dangling symlinks */
-
- if (stat(de->d_name, &st) == 0) {
- return AFPERR_DIRNEMPT;
- }
- return ads_delete_rf(name);
-}
-
-static int RF_deletecurdir_ads(VFS_FUNC_ARGS_DELETECURDIR)
-{
- int err;
-
- /* delete stray .AppleDouble files. this happens to get .Parent files as well. */
- if ((err = for_each_adouble("deletecurdir", ".AppleDouble", deletecurdir_ads_loop, NULL, 1, 0)))
- return err;
-
- return netatalk_rmdir(-1, ".AppleDouble" );
-}
-
-/* ------------------- */
-struct set_mode {
- mode_t mode;
- struct stat *st;
-};
-
-static int ads_setfilmode_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask)
+/*************************************************************************
+ * EA adouble format
+ ************************************************************************/
+static int validupath_ea(VFS_FUNC_ARGS_VALIDUPATH)
{
- struct set_mode *param = data;
-
- return setfilmode(name, param->mode, param->st, v_umask);
-}
+ return 1;
+}
-static int ads_setfilmode(const char * name, mode_t mode, struct stat *st, mode_t v_umask)
+/* ----------------- */
+static int RF_chown_ea(VFS_FUNC_ARGS_CHOWN)
{
+ mode_t file_mode = ad_hf_mode(mode);
+ mode_t dir_mode = file_mode;
+ struct set_mode param;
+
+ if ((dir_mode & (S_IRUSR | S_IWUSR )))
+ dir_mode |= S_IXUSR;
+ if ((dir_mode & (S_IRGRP | S_IWGRP )))
+ dir_mode |= S_IXGRP;
+ if ((dir_mode & (S_IROTH | S_IWOTH )))
+ dir_mode |= S_IXOTH;
+
+ /* change folder */
+ dir_mode |= DIRBITS;
+ if (dir_rx_set(dir_mode)) {
+ if (chmod_acl( name, dir_mode ) < 0)
+ return -1;
+ }
+ param.st = st;
+ param.mode = file_mode;
+ if (for_each_adouble("setfilmode_ads", name, ads_setfilmode_loop, ¶m, 0, v_umask) < 0)
+ return -1;
+
+ if (!dir_rx_set(dir_mode)) {
+ if (chmod_acl( name, dir_mode ) < 0)
+ return -1;
+ }
+
return 0;
}
-static int RF_setfilmode_ads(VFS_FUNC_ARGS_SETFILEMODE)
+/* ---------------- */
+static int RF_renamedir_ea(VFS_FUNC_ARGS_RENAMEDIR)
{
- return ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_HF )), mode, st, vol->v_umask);
+ return 0;
}
-/* ------------------- */
-static int RF_setdirunixmode_ads(VFS_FUNC_ARGS_SETDIRUNIXMODE)
+/* ---------------- */
+static int RF_deletecurdir_ea(VFS_FUNC_ARGS_DELETECURDIR)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char ad_p[ MAXPATHLEN + 1];
- int dropbox = vol->v_flags;
-
- strlcpy(ad_p,ad_dir(adouble), MAXPATHLEN + 1);
-
- if (dir_rx_set(mode)) {
-
- /* .AppleDouble */
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
-
- /* .AppleDouble/.Parent */
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
- }
-
- if (ads_setfilmode(ad_dir(vol->ad_path(name, ADFLAGS_DIR)), mode, st, vol->v_umask) < 0)
- return -1;
-
- if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_p, DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1 ;
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, dropbox, vol->v_umask) < 0)
- return -1;
- }
return 0;
}
-/* ------------------- */
-struct dir_mode {
- mode_t mode;
- int dropbox;
-};
-
-static int setdirmode_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask)
+/* ---------------- */
+static int RF_setdirunixmode_ea(VFS_FUNC_ARGS_SETDIRUNIXMODE)
{
-
- struct dir_mode *param = data;
- int ret = 0; /* 0 ignore error, -1 */
-
- if (dir_rx_set(param->mode)) {
- if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
- if (flag) {
- return 0;
- }
- return ret;
- }
- }
- if (ads_setfilmode(name, param->mode, NULL, v_umask) < 0)
- return ret;
-
- if (!dir_rx_set(param->mode)) {
- if (stickydirmode(name, DIRBITS | param->mode, param->dropbox, v_umask) < 0) {
- if (flag) {
- return 0;
- }
- return ret;
- }
- }
return 0;
}
-static int RF_setdirmode_ads(VFS_FUNC_ARGS_SETDIRMODE)
+static int RF_setfilmode_ea(VFS_FUNC_ARGS_SETFILEMODE)
{
- char *adouble = vol->ad_path(name, ADFLAGS_DIR );
- char ad_p[ MAXPATHLEN + 1];
- struct dir_mode param;
-
- param.mode = mode;
- param.dropbox = vol->v_flags;
-
- strlcpy(ad_p,ad_dir(adouble), sizeof(ad_p));
-
- if (dir_rx_set(mode)) {
- /* .AppleDouble */
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0)
- return -1;
- }
-
- if (for_each_adouble("setdirmode_ads", ad_dir(ad_p), setdirmode_ads_loop, ¶m, vol_noadouble(vol), vol->v_umask))
- return -1;
-
- if (!dir_rx_set(mode)) {
- if (stickydirmode(ad_dir(ad_p), DIRBITS | mode, param.dropbox, vol->v_umask) < 0 )
- return -1;
- }
return 0;
}
-/* ------------------- */
-static int setdirowner_ads1_loop(struct dirent *de _U_, char *name, void *data, int flag _U_, mode_t v_umask _U_)
+/* ---------------- */
+static int RF_setdirmode_ea(VFS_FUNC_ARGS_SETDIRMODE)
{
- struct perm *owner = data;
-
- if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- owner->uid, owner->gid, fullpathname(name), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
return 0;
}
-static int setdirowner_ads_loop(struct dirent *de _U_, char *name, void *data, int flag, mode_t v_umask _U_)
+/* ---------------- */
+static int RF_setdirowner_ea(VFS_FUNC_ARGS_SETDIROWNER)
{
- struct perm *owner = data;
-
- if (for_each_adouble("setdirowner", name, setdirowner_ads1_loop, data, flag, 0) < 0)
- return -1;
-
- if ( chown( name, owner->uid, owner->gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- owner->uid, owner->gid, fullpathname(name), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
- return 0;
+ return 0;
}
-static int RF_setdirowner_ads(VFS_FUNC_ARGS_SETDIROWNER)
+static int RF_deletefile_ea(VFS_FUNC_ARGS_DELETEFILE)
{
- int noadouble = vol_noadouble(vol);
- char adouble_p[ MAXPATHLEN + 1];
- struct stat st;
- struct perm owner;
-
- owner.uid = uid;
- owner.gid = gid;
-
- strlcpy(adouble_p, ad_dir(vol->ad_path(name, ADFLAGS_DIR )), sizeof(adouble_p));
-
- if (for_each_adouble("setdirowner", ad_dir(adouble_p), setdirowner_ads_loop, &owner, noadouble, 0))
- return -1;
-
- /*
- * We cheat: we know that chown doesn't do anything.
- */
- if ( stat( ".AppleDouble", &st ) < 0) {
- if (errno == ENOENT && noadouble)
- return 0;
- LOG(log_error, logtype_afpd, "setdirowner: stat %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
- return -1;
- }
- if ( gid && gid != st.st_gid && chown( ".AppleDouble", uid, gid ) < 0 && errno != EPERM ) {
- LOG(log_debug, logtype_afpd, "setdirowner: chown %d/%d %s: %s",
- uid, gid,fullpathname(".AppleDouble"), strerror(errno) );
- /* return ( -1 ); Sometimes this is okay */
- }
return 0;
}
-
-/* ------------------- */
-static int RF_deletefile_ads(VFS_FUNC_ARGS_DELETEFILE)
+static int RF_copyfile_ea(VFS_FUNC_ARGS_COPYFILE)
{
- int ret = 0;
- int cwd = -1;
- char *ad_p;
-
- ad_p = ad_dir(vol->ad_path(file, ADFLAGS_HF ));
-
- if (dirfd != -1) {
- if (((cwd = open(".", O_RDONLY)) == -1) || (fchdir(dirfd) != 0)) {
- ret = AFPERR_MISC;
- goto exit;
- }
- }
-
- ret = ads_delete_rf(ad_p);
-
- if (dirfd != -1 && fchdir(cwd) != 0) {
- LOG(log_error, logtype_afpd, "RF_deletefile_ads: cant chdir back. exit!");
- exit(EXITERR_SYS);
- }
-
-exit:
- if (cwd != -1)
- close(cwd);
-
- return ret;
+ return 0;
}
-/* --------------------------- */
-static int RF_renamefile_ads(VFS_FUNC_ARGS_RENAMEFILE)
+/* ---------------- */
+static int RF_renamefile_ea(VFS_FUNC_ARGS_RENAMEFILE)
{
- char adsrc[ MAXPATHLEN + 1];
- int err = 0;
-
- strcpy( adsrc, ad_dir(vol->ad_path(src, 0 )));
- if (unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) < 0) {
- struct stat st;
-
- err = errno;
- if (errno == ENOENT) {
- struct adouble ad;
-
- if (lstatat(dirfd, adsrc, &st)) /* source has no ressource fork, */
- return 0;
-
- /* We are here because :
- * -there's no dest folder.
- * -there's no .AppleDouble in the dest folder.
- * if we use the struct adouble passed in parameter it will not
- * create .AppleDouble if the file is already opened, so we
- * use a diff one, it's not a pb,ie it's not the same file, yet.
- */
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if (!ad_open(dst, ADFLAGS_HF, O_RDWR | O_CREAT, 0666, &ad)) {
- ad_close(&ad, ADFLAGS_HF);
-
- /* We must delete it */
- RF_deletefile_ads(vol, -1, dst );
- if (!unix_rename(dirfd, adsrc, -1, ad_dir(vol->ad_path(dst, 0 ))) )
- err = 0;
- else
- err = errno;
- }
- else { /* it's something else, bail out */
- err = errno;
- }
- }
- }
- if (err) {
- errno = err;
- return -1;
- }
- return 0;
+ return 0;
}
+#if 0
/*************************************************************************
* osx adouble format
************************************************************************/
}
return 0;
}
+#endif
/********************************************************************************************
* VFS chaining
};
/*
- * Primary adouble modules: default, osx, sfm
+ * Primary adouble modules: v2, ea
*/
-static struct vfs_ops netatalk_adouble = {
+static struct vfs_ops netatalk_adouble_v2 = {
/* vfs_validupath: */ validupath_adouble,
/* vfs_chown: */ RF_chown_adouble,
/* vfs_renamedir: */ RF_renamedir_adouble,
NULL
};
-static struct vfs_ops netatalk_adouble_osx = {
- /* vfs_validupath: */ validupath_osx,
- /* vfs_chown: */ RF_chown_adouble,
- /* vfs_renamedir: */ RF_renamedir_osx,
- /* vfs_deletecurdir: */ RF_deletecurdir_osx,
- /* vfs_setfilmode: */ RF_setfilmode_adouble,
- /* vfs_setdirmode: */ RF_setdirmode_osx,
- /* vfs_setdirunixmode:*/ RF_setdirunixmode_osx,
- /* vfs_setdirowner: */ RF_setdirowner_osx,
- /* vfs_deletefile: */ RF_deletefile_adouble,
- /* vfs_renamefile: */ RF_renamefile_osx,
- /* vfs_copyfile: */ NULL,
- NULL
-};
-
-/* samba sfm format. ad_path shouldn't be set her */
-static struct vfs_ops netatalk_adouble_sfm = {
- /* vfs_validupath: */ validupath_adouble,
- /* vfs_chown: */ RF_chown_ads,
- /* vfs_renamedir: */ RF_renamedir_adouble,
- /* vfs_deletecurdir: */ RF_deletecurdir_ads,
- /* vfs_setfilmode: */ RF_setfilmode_ads,
- /* vfs_setdirmode: */ RF_setdirmode_ads,
- /* vfs_setdirunixmode:*/ RF_setdirunixmode_ads,
- /* vfs_setdirowner: */ RF_setdirowner_ads,
- /* vfs_deletefile: */ RF_deletefile_ads,
- /* vfs_renamefile: */ RF_renamefile_ads,
- /* vfs_copyfile: */ NULL,
+static struct vfs_ops netatalk_adouble_ea = {
+ /* vfs_validupath: */ validupath_ea,
+ /* vfs_chown: */ RF_chown_ea,
+ /* vfs_renamedir: */ RF_renamedir_ea,
+ /* vfs_deletecurdir: */ RF_deletecurdir_ea,
+ /* vfs_setfilmode: */ RF_setfilmode_ea,
+ /* vfs_setdirmode: */ RF_setdirmode_ea,
+ /* vfs_setdirunixmode:*/ RF_setdirunixmode_ea,
+ /* vfs_setdirowner: */ RF_setdirowner_ea,
+ /* vfs_deletefile: */ RF_deletefile_ea,
+ /* vfs_renamefile: */ RF_renamefile_ea,
+ /* vfs_copyfile: */ RF_copyfile_ea,
NULL
};
vol->vfs = &vfs_master_funcs;
/* Default adouble stuff */
- if (vol->v_adouble == AD_VERSION2_OSX) {
- vol->vfs_modules[0] = &netatalk_adouble_osx;
- vol->ad_path = ad_path_osx;
- }
- else if (vol->v_adouble == AD_VERSION1_SFM) {
- vol->vfs_modules[0] = &netatalk_adouble_sfm;
- vol->ad_path = ad_path_sfm;
- }
- else {
- vol->vfs_modules[0] = &netatalk_adouble;
+ if (vol->v_adouble == AD_VERSION2) {
+ vol->vfs_modules[0] = &netatalk_adouble_v2;
vol->ad_path = ad_path;
+ } else {
+ vol->vfs_modules[0] = &netatalk_adouble_ea;
+ vol->ad_path = ad_path_ea;
}
/* Extended Attributes */
# Do no harm to the values of CFLAGS and LIBS while testing for
# Kerberos support.
- ac_save_CFLAGS=$CFLAGS
- ac_save_CPPFLAGS=$CPPFLAGS
- ac_save_LDFLAGS=$LDFLAGS
- ac_save_LIBS=$LIBS
+ save_CFLAGS=$CFLAGS
+ save_CPPFLAGS=$CPPFLAGS
+ save_LDFLAGS=$LDFLAGS
+ save_LIBS=$LIBS
if test x$FOUND_GSSAPI = x"no"; then
#################################################
AC_PATH_PROG(KRB5_CONFIG, krb5-config)
AC_MSG_CHECKING(for working krb5-config)
if test -x "$KRB5_CONFIG"; then
- ac_save_CFLAGS=$CFLAGS
+ save_CFLAGS=$CFLAGS
CFLAGS="";export CFLAGS
- ac_save_LDFLAGS=$LDFLAGS
+ save_LDFLAGS=$LDFLAGS
LDFLAGS="";export LDFLAGS
GSSAPI_LIBS="`$KRB5_CONFIG --libs gssapi`"
GSSAPI_CFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
GSSAPI_CPPFLAGS="`$KRB5_CONFIG --cflags | sed s/@INCLUDE_des@//`"
- CFLAGS=$ac_save_CFLAGS;export CFLAGS
- LDFLAGS=$ac_save_LDFLAGS;export LDFLAGS
+ CFLAGS=$save_CFLAGS;export CFLAGS
+ LDFLAGS=$save_LDFLAGS;export LDFLAGS
FOUND_GSSAPI=yes
AC_MSG_RESULT(yes)
else
CFLAGS="$CFLAGS $GSSAPI_CFLAGS"
CPPFLAGS="$CPPFLAGS $GSSAPI_CPPFLAGS"
LDFLAGS="$LDFLAGS $GSSAPI_LDFLAGS"
- LIBS="$GSSAPI_LIBS"
+ LIBS="$LIBS $GSSAPI_LIBS"
# check for gssapi headers
GSSAPI_LIBS=""
fi
- LIBS="$ac_save_LIBS"
- CFLAGS="$ac_save_CFLAGS"
- LDFLAGS="$ac_save_LDFLAGS"
- CPPFLAGS="$ac_save_CPPFLAGS"
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+ LDFLAGS="$save_LDFLAGS"
+ CPPFLAGS="$save_CPPFLAGS"
fi
if test x"$ac_cv_func_gss_acquire_cred" = x"yes"; then
AC_SUBST(GSSAPI_LIBS)
AC_SUBST(GSSAPI_CFLAGS)
+ AC_SUBST(GSSAPI_LDFLAGS)
])
-AC_DEFUN([AC_CHECK_ICONV],
+AC_DEFUN([AC_NETATALK_CHECK_ICONV],
[
dnl #################################################
dnl # check for libiconv support
+ saved_CPPFLAGS="$CPPFLAGS"
savedcflags="$CFLAGS"
savedldflags="$LDFLAGS"
ICONV_CFLAGS=""
--- /dev/null
- AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics])
+dnl Kitchen sink for configuration macros
+
+dnl Check for optional admin group support
+AC_DEFUN([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 cracklib support
+AC_DEFUN([AC_NETATALK_CRACKLIB], [
+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])
+])
+
+dnl Check whether to enable debug code
+AC_DEFUN([AC_NETATALK_DEBUG], [
+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 whethe to disable tickle SIGALARM stuff, which eases debugging
+AC_DEFUN([AC_NETATALK_DEBUGGING], [
+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 for optional shadow password support
+AC_DEFUN([AC_NETATALK_SHADOW], [
+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
+
+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 valid-shell-check support
+AC_DEFUN([AC_NETATALK_SHELL_CHECK], [
+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 sysv initscript install
+AC_DEFUN([AC_NETATALK_SYSV_STYLE], [
+ AC_ARG_WITH(sysv-style,
+ [ --with-sysv-style use OS specific sysv config [[redhat-sysv|redhat-systemd|suse|gentoo|netbsd|debian]]],
+ sysv_style="$withval", sysv_style=none
+ )
+ case "$sysv_style" in
+ "redhat")
+ AC_MSG_ERROR([--enable-redhat is obsoleted. Use --enable-redhat-sysv or --enable-redhat-systemd.])
+ ;;
+ "redhat-sysv")
+ AC_MSG_RESULT([enabling redhat-style sysv (upstart) configuration])
+ ;;
+ "redhat-systemd")
+ AC_MSG_RESULT([enabling redhat-style systemd support])
+ ;;
+ "suse")
+ AC_MSG_RESULT([enabling suse-style sysv support])
+ ;;
+ "gentoo")
+ AC_MSG_RESULT([enabling gentoo-style sysv support])
+ ;;
+ "netbsd")
+ AC_MSG_RESULT([enabling netbsd-style sysv support])
+ ;;
+ "debian")
+ AC_MSG_RESULT([enabling debian-style sysv support])
+ ;;
+ *)
+ AC_MSG_RESULT([disabling sysv support])
+ ;;
+ esac
+])
+
+dnl OS specific configuration
+AC_DEFUN([AC_NETATALK_OS_SPECIFIC], [
+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])
++ ;;
++ kfreebsd-gnu) AC_DEFINE(_GNU_SOURCE, 1, [Whether to use GNU libc extensions])
++ ;;
++esac
++
+dnl --------------------- operating system specific flags (port from sys/*)
+
+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])
- 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 <sys/sendfile.h>],
- [\
- 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 <sys/sendfile.h>],
- [\
- 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
-
++ AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW)
++fi
++
++dnl ----- GNU/kFreeBSD specific -----
++if test x"$this_os" = "xkfreebsd-gnu"; then
++ AC_MSG_RESULT([ * GNU/kFreeBSD specific configuration])
++ AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
++ AC_DEFINE(FREEBSD, 1, [Define if OS is FreeBSD])
+ AC_DEFINE(OPEN_NOFOLLOW_ERRNO, EMLINK, errno returned by open with O_NOFOLLOW)
+fi
+
+dnl ----- Linux specific -----
+if test x"$this_os" = "xlinux"; then
+ AC_MSG_RESULT([ * Linux specific configuration])
+
+ dnl ----- check if we need the quotactl wrapper
+ 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])
+
- 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_QUOTA_SUPPORT, 1, [Define if Quota support should be disabled])
- AC_DEFINE(MACOSX_SERVER, 1, [Define if compiling for MacOS X Server])
- AC_DEFINE(NO_DDP, 1, [Define if DDP should be disabled])
- fi
-
+ need_dash_r=no
+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])
++ AC_DEFINE(BSD4_4, 1, [BSD compatiblity macro])
+ 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 <sys/stream.h>
+#include <sys/ddi.h>],
+[\
+timeout_id_t dummy;
+],
+netatalk_cv_HAVE_TIMEOUT_ID_T=yes,netatalk_cv_HAVE_TIMEOUT_ID_T=no,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 Check for building PGP UAM module
+AC_DEFUN([AC_NETATALK_PGP_UAM], [
+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 V UAM module
+AC_DEFUN([AC_NETATALK_KRB5_UAM], [
+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 Check for overwrite the config files or not
+AC_DEFUN([AC_NETATALK_OVERWRITE_CONFIG], [
+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])
+AC_SUBST(OVERWRITE_CONFIG)
+])
+
+dnl Check for LDAP support, for client-side ACL visibility
+AC_DEFUN([AC_NETATALK_LDAP], [
+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_DEFUN([AC_NETATALK_ACL], [
+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 <sys/types.h>
+ #include <sys/acl.h>
+ ],[
+ 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 <sys/types.h>
+ #include <sys/acl.h>
+ ],[
+ acl_permset_t permset_d;
+ acl_perm_t perm;
+ return acl_get_perm_np(permset_d, perm);
+ ],
+ [netatalk_cv_HAVE_ACL_GET_PERM_NP=yes],
+ [netatalk_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
+
+
+ AC_CACHE_CHECK([for acl_from_mode], netatalk_cv_HAVE_ACL_FROM_MODE,[
+ acl_LIBS=$LIBS
+ LIBS="$LIBS $ACL_LIBS"
+ AC_CHECK_FUNCS(acl_from_mode,
+ [netatalk_cv_HAVE_ACL_FROM_MODE=yes],
+ [netatalk_cv_HAVE_ACL_FROM_MODE=no])
+ LIBS=$acl_LIBS
+ ])
+ if test x"netatalk_cv_HAVE_ACL_FROM_MODE" = x"yes"; then
+ AC_DEFINE(HAVE_ACL_FROM_MODE,1,[Whether acl_from_mode() 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_CHECK_HEADERS([acl/libacl.h])
+ AC_DEFINE(HAVE_ACLS,1,[Whether ACLs support is available])
+ AC_SUBST(ACL_LIBS)
+fi
+])
+
+dnl Check for Extended Attributes support
+AC_DEFUN([AC_NETATALK_EXTENDED_ATTRIBUTES], [
+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 <sys/types.h>
+ #if HAVE_ATTR_XATTR_H
+ #include <attr/xattr.h>
+ #elif HAVE_SYS_XATTR_H
+ #include <sys/xattr.h>
+ #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 for libsmbsharemodes from Samba for Samba/Netatalk access/deny/share modes interop
+dnl Defines "neta_cv_have_smbshmd" to "yes" or "no"
+dnl AC_SUBST's "SMB_SHAREMODES_CFLAGS" and "SMB_SHAREMODES_LDFLAGS"
+dnl AM_CONDITIONAL's "USE_SMB_SHAREMODES"
+AC_DEFUN([AC_NETATALK_SMB_SHAREMODES], [
+ neta_cv_have_smbshmd=no
+ AC_ARG_WITH(smbsharemodes-lib,
+ [ --with-smbsharemodes-lib=PATH PATH to libsmbsharemodes lib from Samba],
+ [SMB_SHAREMODES_LDFLAGS="-L$withval -lsmbsharemodes"]
+ )
+ AC_ARG_WITH(smbsharemodes-include,
+ [ --with-smbsharemodes-include=PATH PATH to libsmbsharemodes header from Samba],
+ [SMB_SHAREMODES_CFLAGS="-I$withval"]
+ )
+ AC_ARG_WITH(smbsharemodes,
+ [AS_HELP_STRING([--with-smbsharemodes],[Samba interop (default is yes)])],
+ [use_smbsharemodes=$withval],
+ [use_smbsharemodes=yes]
+ )
+
+ if test x"$use_smbsharemodes" = x"yes" ; then
+ AC_MSG_CHECKING([whether to enable Samba/Netatalk access/deny/share-modes interop])
+
+ saved_CFLAGS="$CFLAGS"
+ saved_LDFLAGS="$LDFLAGS"
+ CFLAGS="$SMB_SHAREMODES_CFLAGS $CFLAGS"
+ LDFLAGS="$SMB_SHAREMODES_LDFLAGS $LDFLAGS"
+
+ AC_LINK_IFELSE(
+ [#include <unistd.h>
+ #include <stdio.h>
+ #include <sys/time.h>
+ #include <time.h>
+ #include <stdint.h>
+ /* From messages.h */
+ struct server_id {
+ pid_t pid;
+ };
+ #include "smb_share_modes.h"
+ int main(void) { (void)smb_share_mode_db_open(""); return 0;}],
+ [neta_cv_have_smbshmd=yes]
+ )
+
+ AC_MSG_RESULT($neta_cv_have_smbshmd)
+ AC_SUBST(SMB_SHAREMODES_CFLAGS, [$SMB_SHAREMODES_CFLAGS])
+ AC_SUBST(SMB_SHAREMODES_LDFLAGS, [$SMB_SHAREMODES_LDFLAGS])
+ CFLAGS="$saved_CFLAGS"
+ LDFLAGS="$saved_LDFLAGS"
+ fi
+
+ AM_CONDITIONAL(USE_SMB_SHAREMODES, test x"$neta_cv_have_smbshmd" = x"yes")
+])
++
++dnl ------ Check for sendfile() --------
++AC_DEFUN([AC_NETATALK_SENDFILE], [
++netatalk_cv_search_sendfile=yes
++AC_ARG_ENABLE(sendfile,
++ [ --disable-sendfile disable sendfile syscall],
++ [if test x"$enableval" = x"no"; then
++ netatalk_cv_search_sendfile=no
++ fi]
++)
++
++if test x"$netatalk_cv_search_sendfile" = x"yes"; then
++ case "$host_os" in
++ *linux*)
++ AC_DEFINE(SENDFILE_FLAVOR_LINUX,1,[Whether linux sendfile() API is available])
++ AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
++ ;;
++
++ *solaris*)
++ AC_DEFINE(SENDFILE_FLAVOR_SOLARIS, 1, [Solaris sendfile()])
++ AC_SEARCH_LIBS(sendfile, sendfile)
++ AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
++ ;;
++
++ *freebsd*)
++ AC_DEFINE(SENDFILE_FLAVOR_BSD, 1, [Define if the sendfile() function uses BSD semantics])
++ AC_CHECK_FUNC([sendfile], [netatalk_cv_HAVE_SENDFILE=yes])
++ ;;
++
++ *)
++ ;;
++
++ esac
++
++ if test x"$netatalk_cv_HAVE_SENDFILE" = x"yes"; then
++ AC_DEFINE(WITH_SENDFILE,1,[Whether sendfile() should be used])
++ fi
++fi
++])
++
++dnl --------------------- Check if realpath() takes NULL
++AC_DEFUN([AC_NETATALK_REALPATH], [
++AC_CACHE_CHECK([if the realpath function allows a NULL argument],
++ neta_cv_REALPATH_TAKES_NULL, [
++ AC_TRY_RUN([
++ #include <stdio.h>
++ #include <limits.h>
++ #include <signal.h>
++
++ 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_MSG_RESULT([ none])
fi
AC_MSG_RESULT([ AFP:])
- AC_MSG_RESULT([ Large file support (>2GB) for AFP3: $wx_largefile])
AC_MSG_RESULT([ Extended Attributes: $neta_cv_eas])
+ AC_MSG_RESULT([ ACL support: $with_acl_support])
AC_MSG_RESULT([ CNID:])
AC_MSG_RESULT([ backends: $compiled_backends])
AC_MSG_RESULT([ UAMS:])
AC_MSG_RESULT([ DHX2 ($uams_using_options)])
fi
if test "x$neta_cv_have_openssl" = "xyes"; then
- AC_MSG_RESULT([ RANDNUM ($uams_using_options)])
+ AC_MSG_RESULT([ RANDNUM])
fi
if test x"$netatalk_cv_build_krb5_uam" = x"yes"; then
AC_MSG_RESULT([ Kerberos V])
fi
- if test x"$compile_kerberos" = x"yes"; then
- AC_MSG_RESULT([ Kerberos IV])
- fi
if test x"$compile_pgp" = x"yes"; then
AC_MSG_RESULT([ PGP])
fi
- AC_MSG_RESULT([ passwd ($uams_using_options)])
+ AC_MSG_RESULT([ clrtxt ($uams_using_options)])
AC_MSG_RESULT([ guest])
AC_MSG_RESULT([ Options:])
- AC_MSG_RESULT([ DDP (AppleTalk) support: $netatalk_cv_ddp_enabled])
- if test "x$netatalk_cv_ddp_enabled" = "xyes"; then
- AC_MSG_RESULT([ CUPS support: $netatalk_cv_use_cups])
- AC_MSG_RESULT([ Apple 2 boot support: $compile_a2boot])
- fi
AC_MSG_RESULT([ SLP support: $netatalk_cv_srvloc])
AC_MSG_RESULT([ Zeroconf support: $netatalk_cv_zeroconf])
AC_MSG_RESULT([ tcp wrapper support: $netatalk_cv_tcpwrap])
AC_MSG_RESULT([ admin group support: $netatalk_cv_admin_group])
AC_MSG_RESULT([ valid shell check: $netatalk_cv_use_shellcheck])
AC_MSG_RESULT([ cracklib support: $netatalk_cv_with_cracklib])
- AC_MSG_RESULT([ dropbox kludge: $netatalk_cv_dropkludge])
- AC_MSG_RESULT([ force volume uid/gid: $netatalk_cv_force_uidgid])
+ AC_MSG_RESULT([ Samba sharemode interop: $neta_cv_have_smbshmd])
AC_MSG_RESULT([ ACL support: $with_acl_support])
AC_MSG_RESULT([ LDAP support: $with_ldap])
if test x"$use_pam_so" = x"yes" -a x"$netatalk_cv_install_pam" = x"no"; then