From 85e291c2519d653a2bc9c4957a059e44e2af3c28 Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Sun, 16 May 2010 16:10:53 +0200 Subject: [PATCH] Added preliminary AFS acl support. The code may need some testing on a real AFS enabled server as most of the code was written using information available on the Internet. The code compiles and links on Linux using OpenAFS 1.4. --- bacula/autoconf/acconfig.h | 3 ++ bacula/autoconf/config.h.in | 5 +- bacula/autoconf/configure.in | 93 +++++++++++++++++++++++++++++++++- bacula/src/baconfig.h | 1 + bacula/src/filed/Makefile.in | 10 +++- bacula/src/filed/acl.c | 97 +++++++++++++++++++++++++++++++++++- bacula/src/filed/restore.c | 1 + 7 files changed, 205 insertions(+), 5 deletions(-) diff --git a/bacula/autoconf/acconfig.h b/bacula/autoconf/acconfig.h index 3f613ea35b..7b5e6aab1c 100644 --- a/bacula/autoconf/acconfig.h +++ b/bacula/autoconf/acconfig.h @@ -155,6 +155,9 @@ /* Define if you have libacl */ #undef HAVE_ACL +/* Define if you have AFS acls */ +#undef HAVE_AFS_ACL + /* General libs */ #undef LIBS diff --git a/bacula/autoconf/config.h.in b/bacula/autoconf/config.h.in index 4eed11add4..332e274640 100644 --- a/bacula/autoconf/config.h.in +++ b/bacula/autoconf/config.h.in @@ -87,7 +87,7 @@ #undef HAVE_GCC /* Define if you have the Andrew File System. */ -#undef AFS +#undef HAVE_AFS /* Define If you want find -nouser and -nogroup to make tables of used UIDs and GIDs at startup instead of using getpwuid or @@ -374,6 +374,9 @@ /* Extended acl support */ #undef HAVE_EXTENDED_ACL +/* AFS ACL support */ +#undef HAVE_AFS_ACL + /* Define to 1 if you have the `fchdir' function. */ #undef HAVE_FCHDIR diff --git a/bacula/autoconf/configure.in b/bacula/autoconf/configure.in index fa62cba428..77c92199fd 100644 --- a/bacula/autoconf/configure.in +++ b/bacula/autoconf/configure.in @@ -2392,6 +2392,7 @@ AC_FUNC_STRFTIME AC_FUNC_VPRINTF AC_FUNC_ALLOCA AC_FUNC_GETMNTENT +AC_CHECK_FUNCS(getmntinfo, [AC_DEFINE(HAVE_GETMNTINFO)]) AC_FUNC_CLOSEDIR_VOID AC_FUNC_SETPGRP dnl check for BSD setpgrp. # AC_FUNC_FNMATCH dnl use local version @@ -2409,6 +2410,84 @@ if test x$ZLIBS = x-lz; then fi AC_SUBST(ZLIBS) +dnl +dnl Check if we have AFS on this system +dnl +AFS_CFLAGS="" +AFS_LIBS="" +support_afs=auto +AC_ARG_ENABLE(afs, + AC_HELP_STRING([--disable-afs], [disable afs support @<:@default=auto@:>@]), + [ + if test x$enableval = xyes; then + support_afs=yes + elif test x$enableval = xno; then + support_afs=no + fi + ] +) + +have_afs=no +if test x$support_afs = xyes -o x$support_afs = xauto; then + AC_ARG_WITH(afsdir, + AC_HELP_STRING([--with-afsdir@<:@=DIR@:>@], [Directory holding AFS includes/libs]), + with_afsdir=$withval + ) + + dnl + dnl Search in standard places, or --with-afsdir not specified + dnl + if test x$with_afsdir = x; then + for root in /usr /usr/local; do + if test -d ${root}/include/afs/ ; then + with_afsdir=${root} + break + fi + done + fi + + AFS_CFLAGS="-I${with_afsdir}/include" + + saved_CFLAGS="${CFLAGS}" + CFLAGS="${AFS_CFLAGS} ${saved_CFLAGS}" + + AC_CHECK_HEADERS(afs/stds.h) + + CFLAGS="${saved_CFLAGS}" + + dnl + dnl See if we can find a libsys with the pioctl symbol in there + dnl + for dir in ${with_afsdir}/lib ${with_afsdir}/lib/afs + do + for arch_type in .a .so + do + A=`test -f ${dir}/libsys${arch_type} && nm ${dir}/libsys${arch_type} | grep pioctl` + pkg=$? + if test $pkg = 0; then + have_afs=yes + AFS_LIBS="-L${dir} -lsys -lrx -llwp ${dir}/util.a" + break + fi + done + done + + if test x$support_afs = xyes -a $have_afs != yes; then + AC_MSG_ERROR([afs support explicitly enabled but no supported afs implementation found, + please either load the afs libraries or rerun configure without --enable-afs]) + else + if test $have_afs = yes; then + AC_DEFINE([HAVE_AFS],1,[Defines if your system has AFS support]) + AC_DEFINE([HAVE_AFS_ACL],1,[Andrew FileSystem ACL support]) + fi + fi +fi + +AC_SUBST(AFS_CFLAGS) +AC_SUBST(AFS_LIBS) +AC_DEFINE(AFS_CFLAGS) +AC_DEFINE(AFS_LIBS) + dnl dnl Check for ACL support and libraries dnl @@ -2435,7 +2514,18 @@ if test x$support_acl = xyes -o x$support_acl = xauto; then AC_CHECK_LIB(acl, acl_get_file, [ have_acl=yes; - FDLIBS="-lacl $FDLIBS" + if test $have_afs = yes; then + dnl + dnl Because of possible naming conflict with AFS libacl make sure we use the one in /usr/lib64 or /usr/lib !!! + dnl + if test -d /usr/lib64/; then + FDLIBS="-L/usr/lib64 -lacl $FDLIBS" + else + FDLIBS="-L/usr/lib -lacl $FDLIBS" + fi + else + FDLIBS="-lacl $FDLIBS" + fi ], [ AC_CHECK_LIB(pacl, acl_get_file, [ @@ -3262,6 +3352,7 @@ Configuration on `date`: build-dird: ${build_dird} build-stored: ${build_stored} Plugin support: ${have_plugins} + AFS support: ${have_afs} ACL support: ${have_acl} XATTR support: ${have_xattr} Python support: ${support_python} ${PYTHON_LIBS} diff --git a/bacula/src/baconfig.h b/bacula/src/baconfig.h index 5f7bd43db7..ff9ca8c4db 100644 --- a/bacula/src/baconfig.h +++ b/bacula/src/baconfig.h @@ -295,6 +295,7 @@ void InitWinAPIWrapper(); #define STREAM_ACL_SOLARIS_ACE 1013 /* Solaris specific ace_t string representation from * from acl_totext (NFSv4 or ZFS acl) */ +#define STREAM_ACL_AFS_TEXT 1014 /* AFS specific string representation from pioctl */ #define STREAM_XATTR_OPENBSD 1993 /* OpenBSD specific extended attributes */ #define STREAM_XATTR_SOLARIS_SYS 1994 /* Solaris specific extensible attributes or * otherwise named extended system attributes. diff --git a/bacula/src/filed/Makefile.in b/bacula/src/filed/Makefile.in index b4b1e8fe08..192f9ddfaf 100644 --- a/bacula/src/filed/Makefile.in +++ b/bacula/src/filed/Makefile.in @@ -23,6 +23,8 @@ GETTEXT_LIBS = @LIBINTL@ PYTHON_LIBS = @PYTHON_LIBS@ PYTHON_INC = @PYTHON_INCDIR@ +AFS_CFLAGS = @AFS_CFLAGS@ +AFS_LIBS = @AFS_LIBS@ first_rule: all dummy: @@ -60,6 +62,10 @@ all: Makefile @WIN32@ bacula-fd @STATIC_FD@ @echo "==== Make of filed is good ====" @echo " " +acl.o: acl.c + @echo "Compiling $<" + $(NO_ECHO)$(CXX) $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) $(PYTHON_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $(AFS_CFLAGS) $< + win32/winlib.a: @if test -f win32/Makefile -a "${GMAKE}" != "none"; then \ (cd win32; $(GMAKE) DESTDIR=$(DESTDIR)); \ @@ -89,12 +95,12 @@ bacula-fd: Makefile $(SVROBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../ @echo "Linking $@ ..." $(LIBTOOL_LINK) $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(SVROBJS) \ $(WIN32LIBS) $(FDLIBS) $(ZLIBS) -lbacfind -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(LIBS) \ - $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS) + $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS) $(AFS_LIBS) static-bacula-fd: Makefile $(SVROBJS) ../findlib/libbacfind.a ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) @WIN32@ $(LIBTOOL_LINK) $(CXX) $(WLDFLAGS) $(LDFLAGS) -static -L../lib -L../findlib -o $@ $(SVROBJS) \ $(WIN32LIBS) $(FDLIBS) $(ZLIBS) -lbacfind -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(LIBS) \ - $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS) + $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS) $(AFS_LIBS) strip $@ Makefile: $(srcdir)/Makefile.in $(topdir)/config.status diff --git a/bacula/src/filed/acl.c b/bacula/src/filed/acl.c index 9735e1c631..4d6bb71251 100644 --- a/bacula/src/filed/acl.c +++ b/bacula/src/filed/acl.c @@ -52,7 +52,7 @@ #include "bacula.h" #include "filed.h" -#if !defined(HAVE_ACL) +#if !defined(HAVE_ACL) && !defined(HAVE_AFS_ACL) /* * Entry points when compiled without support for ACLs or on an unsupported platform. */ @@ -120,6 +120,10 @@ static bacl_exit_code send_acl_stream(JCR *jcr, int stream) return bacl_exit_ok; } +/* + * First the native ACLs. + */ +#if defined(HAVE_ACL) #if defined(HAVE_AIX_OS) #include @@ -1217,6 +1221,77 @@ static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = solari static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = solaris_parse_acl_streams; #endif /* HAVE_SUN_OS */ +#endif /* HAVE_ACL */ + +#if defined(HAVE_AFS_ACL) + +#include +#include +#include +#include +#include + +/* + * External references to functions in the libsys library function not in current include files. + */ +extern "C" { +long pioctl(char *pathp, long opcode, struct ViceIoctl *blobp, int follow); +} + +static bacl_exit_code afs_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) +{ + int error; + struct ViceIoctl vip; + char acl_text[BUFSIZ]; + berrno be; + + /* + * AFS ACLs can only be set on a directory, so no need to try to + * request them for anything other then that. + */ + if (ff_pkt->type != FT_DIREND) { + return bacl_exit_ok; + } + + vip.in = NULL; + vip.in_size = 0; + vip.out = acl_text; + vip.out_size = sizeof(acl_text); + memset((caddr_t)acl_text, 0, sizeof(acl_text)); + + if ((error = pioctl(jcr->last_fname, VIOCGETAL, &vip, 0)) < 0) { + Mmsg2(jcr->errmsg, _("pioctl VIOCGETAL error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "pioctl VIOCGETAL error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + return bacl_exit_error; + } + jcr->acl_data->content_length = pm_strcpy(jcr->acl_data->content, acl_text); + return send_acl_stream(jcr, STREAM_ACL_AFS_TEXT); +} + +static bacl_exit_code afs_parse_acl_stream(JCR *jcr, int stream) +{ + int error; + struct ViceIoctl vip; + berrno be; + + vip.in = jcr->acl_data->content; + vip.in_size = jcr->acl_data->content_length; + vip.out = NULL; + vip.out_size = 0; + + if ((error = pioctl(jcr->last_fname, VIOCSETAL, &vip, 0)) < 0) { + Mmsg2(jcr->errmsg, _("pioctl VIOCSETAL error on file \"%s\": ERR=%s\n"), + jcr->last_fname, be.bstrerror()); + Dmsg2(100, "pioctl VIOCSETAL error file=%s ERR=%s\n", + jcr->last_fname, be.bstrerror()); + + return bacl_exit_error; + } + return bacl_exit_ok; +} +#endif /* HAVE_AFS_ACL */ /* * Entry points when compiled with support for ACLs on a supported platform. @@ -1227,12 +1302,23 @@ static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = solaris_pa */ bacl_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt) { +#if defined(HAVE_AFS_ACL) + /* + * AFS is a non OS specific filesystem so see if this path is on an AFS filesystem + * and retrieve its ACL if it is. + */ + if (fstype_equals(jcr->last_fname, "afs")) { + return afs_build_acl_streams(jcr, ff_pkt); + } +#endif +#if defined(HAVE_ACL) /* * Call the appropriate function. */ if (os_build_acl_streams) { return (*os_build_acl_streams)(jcr, ff_pkt); } +#endif return bacl_exit_error; } @@ -1241,6 +1327,11 @@ bacl_exit_code parse_acl_streams(JCR *jcr, int stream) unsigned int cnt; switch (stream) { +#if defined(HAVE_AFS_ACL) + case STREAM_ACL_AFS_TEXT: + return afs_parse_acl_stream(jcr, stream); +#endif +#if defined(HAVE_ACL) case STREAM_UNIX_ACCESS_ACL: case STREAM_UNIX_DEFAULT_ACL: /* @@ -1270,6 +1361,10 @@ bacl_exit_code parse_acl_streams(JCR *jcr, int stream) } } break; +#else + default: + break; +#endif } Qmsg2(jcr, M_WARNING, 0, _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"), diff --git a/bacula/src/filed/restore.c b/bacula/src/filed/restore.c index 791520ed24..95447e532f 100644 --- a/bacula/src/filed/restore.c +++ b/bacula/src/filed/restore.c @@ -651,6 +651,7 @@ void do_restore(JCR *jcr) case STREAM_ACL_TRU64_ACCESS_ACL: case STREAM_ACL_SOLARIS_ACLENT: case STREAM_ACL_SOLARIS_ACE: + case STREAM_ACL_AFS_TEXT: /* * Do not restore ACLs when * a) The current file is not extracted -- 2.39.5