--- /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
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;
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;
*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;
* 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;
}
+ 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;
}
#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;
#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 */
# 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
#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>
#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)
* 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>
#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)
{
#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
#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,
--- /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;
+}
}
#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;
}
--- /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
++])
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])