]> git.sur5r.net Git - bacula/bacula/commitdiff
Add rudimentary support for saving AFS acls.
authorMarco van Wieringen <mvw@planets.elm.net>
Mon, 11 Jun 2012 15:16:40 +0000 (17:16 +0200)
committerKern Sibbald <kern@sibbald.com>
Sat, 20 Apr 2013 12:50:48 +0000 (14:50 +0200)
    Add support for saving and restoring AFS acls using the
    pioctl interface of (Open)AFS. This is mostly a proof of
    concept its no where ready for production and may put
    a enormous load on your AFS cell so please use it only
    for testing. It also only solves part of the AFS backup
    problem as we only save and restore acls on directories
    on an AFS filesystem but not the actual cell configuration
    etc. For that we advice you to use the native tooling
    using some script or the bpipe plugin.

bacula/autoconf/acconfig.h
bacula/autoconf/configure.in
bacula/src/filed/Makefile.in
bacula/src/filed/acl.c

index c60296ab6372409134635f6c55a49679907ea064..40a91d70e565d9a3ee3b8c299bf5e89dc178382d 100644 (file)
@@ -49,9 +49,6 @@
 /* Define if you have GCC */
 #undef HAVE_GCC
 
-/* Define if you have the Andrew File System.  */
-#undef AFS
-
 /* Define If you want find -nouser and -nogroup to make tables of
    used UIDs and GIDs at startup instead of using getpwuid or
    getgrgid when needed.  Speeds up -nouser and -nogroup unless you
 /* Define if you have libacl */
 #undef HAVE_ACL
 
-/* Define if you have AFS acls */
-#undef HAVE_AFS_ACL
-
 /* General libs */
 #undef LIBS
 
index ff06afc523925c84183335c6015d4ed3c87a9eb1..5f46fc30b8e256a0936b8f6ae6ca4ffe9840f3ec 100644 (file)
@@ -2517,6 +2517,113 @@ AC_CHECK_HEADER(lzo/lzoconf.h,
 ])
 AC_SUBST(LZOLIBS)
 
+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
+        if test -d ${root}/include/openafs/afs/ ; then
+           with_afsdir=${root}
+           break
+        fi
+      done
+   fi
+
+   if test -d ${with_afsdir}/include/afs/ ; then
+      AFS_CFLAGS="-I${with_afsdir}/include"
+   else
+      if test -d ${with_afsdir}/include/openafs/afs/ ; then
+         AFS_CFLAGS="-I${with_afsdir}/include/openafs"
+      fi
+   fi
+
+   saved_CFLAGS="${CFLAGS}"
+   saved_CPPFLAGS="${CPPFLAGS}"
+   CFLAGS="${AFS_CFLAGS} ${saved_CFLAGS}"
+   CPPFLAGS="${AFS_CFLAGS} ${saved_CPPFLAGS}"
+
+   AC_CHECK_HEADERS(afs/afsint.h)
+   AC_TRY_CPP(
+       [
+          #include <afs/afsint.h>
+          #include <afs/venus.h>
+       ],
+       AC_DEFINE(HAVE_AFS_VENUS_H,1,[Define to 1 if you have the <afs/venus.h> header file.])
+   )
+
+   CFLAGS="${saved_CFLAGS}"
+   CPPFLAGS="${saved_CPPFLAGS}"
+
+   dnl
+   dnl See if we can find a libsys with the pioctl symbol in there
+   dnl
+   AC_MSG_CHECKING(for pioctl in AFS libsys)
+   for dir in ${with_afsdir}/lib \
+              ${with_afsdir}/lib/afs \
+              ${with_afsdir}/lib/openafs \
+              ${with_afsdir}/lib64 \
+              ${with_afsdir}/lib64/afs \
+              ${with_afsdir}/lib64/openafs
+   do
+      for arch_type in .a .so
+      do
+        A=`test -f ${dir}/libsys${arch_type} && nm ${dir}/libsys${arch_type} 2>/dev/null | grep pioctl`
+        pkg=$?
+        if test $pkg = 0; then
+           have_afs=yes
+           AFS_LIBS="-L${dir} -lsys -lrx -llwp ${dir}/util${arch_type}"
+           break
+        fi
+      done
+   done
+
+   if test $have_afs = yes; then
+      AC_MSG_RESULT(yes)
+   else
+      AC_MSG_RESULT(no)
+   fi
+
+   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,[Define to 1 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)
+
 dnl
 dnl Check for ACL support and libraries
 dnl
@@ -2553,7 +2660,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
         ]
       )
    fi
@@ -3523,6 +3641,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}
index c67a2e032045ed954c0a3a5ea56f73aace08dd45..d2f452888b29fbf9cbdbbebccfa90d60b036cd02 100644 (file)
@@ -24,6 +24,8 @@ GETTEXT_LIBS = @LIBINTL@
 
 PYTHON_LIBS = @PYTHON_LIBS@
 PYTHON_INC = @PYTHON_INCDIR@
+AFS_CFLAGS = @AFS_CFLAGS@
+AFS_LIBS = @AFS_LIBS@
 
 first_rule: all
 dummy:
@@ -64,7 +66,7 @@ all: Makefile @WIN32@ bacula-fd @STATIC_FD@
 
 acl.o: acl.c
        @echo "Compiling $<"
-       $(NO_ECHO)$(CXX) $(DEFS) $(DEBUG) -c $(WCFLAGS) $(CPPFLAGS) $(PYTHON_INC) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $<
+       $(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 \
@@ -94,13 +96,13 @@ win32:      $(WIN32OBJS)
 bacula-fd:  Makefile $(SVROBJS) ../findlib/libbacfind$(DEFAULT_ARCHIVE_TYPE) ../lib/libbacpy$(DEFAULT_ARCHIVE_TYPE) ../lib/libbaccfg$(DEFAULT_ARCHIVE_TYPE) ../lib/libbac$(DEFAULT_ARCHIVE_TYPE) @WIN32@
        @echo "Linking $@ ..."
        $(LIBTOOL_LINK) $(CXX) $(WLDFLAGS) $(LDFLAGS) -L../lib -L../findlib -o $@ $(SVROBJS) \
-         $(WIN32LIBS) $(FDLIBS) $(ZLIBS) $(LZOLIBS) -lbacfind -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(LIBS) \
-         $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS)
+         $(WIN32LIBS) $(FDLIBS) $(ZLIBS) -lbacfind -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(LIBS) \
+         $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS) $(AFS_LIBS) $(LZOLIBS)
 
 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) $(LZOLIBS) -lbacfind -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(LIBS) \
-          $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS)
+          $(WIN32LIBS) $(FDLIBS) $(ZLIBS) -lbacfind -lbacpy -lbaccfg -lbac -lm $(PYTHON_LIBS) $(LIBS) \
+          $(DLIB) $(WRAPLIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS) $(CAP_LIBS) $(AFS_LIBS) $(LZOLIBS)
        strip $@
 
 Makefile: $(srcdir)/Makefile.in $(topdir)/config.status
@@ -170,7 +172,7 @@ depend:
        @$(MV) Makefile Makefile.bak
        @$(SED) "/^# DO NOT DELETE:/,$$ d" Makefile.bak > Makefile
        @$(ECHO) "# DO NOT DELETE: nice dependency list follows" >> Makefile
-       @$(CXX) -S -M $(CPPFLAGS) $(XINC) $(PYTHON_INC) -I$(srcdir) -I$(basedir) *.c >> Makefile
+       @$(CXX) -S -M $(CPPFLAGS) $(AFS_CFLAGS) $(XINC) $(PYTHON_INC) -I$(srcdir) -I$(basedir) *.c >> Makefile
        @if test -f Makefile ; then \
            $(RMF) Makefile.bak; \
        else \
index 4880d70ae8e6308b3809e077101a4cb9643e2f53..b83bd7a19ef63a643e33611e3831750e09bf6cb2 100644 (file)
@@ -38,6 +38,8 @@
  *   - Solaris (POSIX and NFSv4/ZFS acls)
  *   - Tru64
  *
+ * Next to OS specific acls we support AFS acls using the pioctl interface.
+ *
  * We handle two different types of ACLs: access and default ACLS.
  * On most systems that support default ACLs they only apply to directories.
  *
@@ -63,7 +65,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.
  */
@@ -431,7 +433,9 @@ static bacl_exit_code aix_parse_acl_streams(JCR *jcr,
                if (cnt < 3) {
                   continue;
                }
-               /* FALL THROUGH */
+               /*
+                * FALLTHROUGH
+                */
             default:
                Mmsg2(jcr->errmsg,
                      _("aclx_scanStr error on file \"%s\": ERR=%s\n"),
@@ -1977,8 +1981,9 @@ static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
    char *acl_text;
 
    n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
-   if (n < MIN_ACL_ENTRIES)
+   if (n < MIN_ACL_ENTRIES) {
       return bacl_exit_error;
+   }
 
    acls = (aclent_t *)malloc(n * sizeof(aclent_t));
    if (acl(jcr->last_fname, GETACL, n, acls) == n) {
@@ -2072,7 +2077,86 @@ static bacl_exit_code (*os_parse_acl_streams)
 #endif /* HAVE_SUN_OS */
 #endif /* HAVE_ACL */
 
-/*
+#if defined(HAVE_AFS_ACL)
+
+#if defined(HAVE_AFS_AFSINT_H) && defined(HAVE_AFS_VENUS_H)
+#include <afs/afsint.h>
+#include <afs/venus.h>
+#else
+#error "configure failed to detect availability of afs/afsint.h and/or afs/venus.h"
+#endif
+
+/**
+ * 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];
+
+   /*
+    * 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) {
+      berrno be;
+
+      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->u.build->content_length =
+   pm_strcpy(jcr->acl_data->u.build->content, acl_text);
+   return send_acl_stream(jcr, STREAM_ACL_AFS_TEXT);
+}
+
+static bacl_exit_code afs_parse_acl_stream(JCR *jcr,
+                                           int stream,
+                                           char *content,
+                                           uint32_t content_length)
+{
+   int error;
+   struct ViceIoctl vip;
+
+   vip.in = content;
+   vip.in_size = content_length;
+   vip.out = NULL;
+   vip.out_size = 0;
+
+   if ((error = pioctl(jcr->last_fname, VIOCSETAL, &vip, 0)) < 0) {
+      berrno be;
+
+      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.
  */
 
@@ -2083,7 +2167,7 @@ bacl_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
    /*
     * See if we are changing from one device to an other.
-    * We save the current device we are restoring to and compare
+    * We save the current device we are scanning and compare
     * it with the current st_dev in the last stat performed on
     * the file we are currently storing.
     */
@@ -2093,14 +2177,35 @@ bacl_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
        */
       jcr->acl_data->flags = 0;
 
+#if defined(HAVE_AFS_ACL)
+      /*
+       * AFS is a non OS specific filesystem so see if this path is on an AFS filesystem
+       * Set the BACL_FLAG_SAVE_AFS flag if it is. If not set the BACL_FLAG_SAVE_NATIVE flag.
+       */
+      if (fstype_equals(jcr->last_fname, "afs")) {
+         jcr->acl_data->flags |= BACL_FLAG_SAVE_AFS;
+      } else {
+         jcr->acl_data->flags |= BACL_FLAG_SAVE_NATIVE;
+      }
+#else
       jcr->acl_data->flags |= BACL_FLAG_SAVE_NATIVE;
+#endif
 
-      /**
+      /*
        * Save that we started scanning a new filesystem.
        */
       jcr->acl_data->current_dev = ff_pkt->statp.st_dev;
    }
 
+#if defined(HAVE_AFS_ACL)
+   /*
+    * See if the BACL_FLAG_SAVE_AFS flag is set which lets us know if we should
+    * save AFS ACLs.
+    */
+   if (jcr->acl_data->flags & BACL_FLAG_SAVE_AFS) {
+      return afs_build_acl_streams(jcr, ff_pkt);
+   }
+#endif
 #if defined(HAVE_ACL)
    /*
     * See if the BACL_FLAG_SAVE_NATIVE flag is set which lets us know if we should
@@ -2161,7 +2266,20 @@ bacl_exit_code parse_acl_streams(JCR *jcr,
        * Reset the acl save flags.
        */
       jcr->acl_data->flags = 0;
+
+#if defined(HAVE_AFS_ACL)
+      /*
+       * AFS is a non OS specific filesystem so see if this path is on an AFS filesystem
+       * Set the BACL_FLAG_RESTORE_AFS flag if it is. If not set the BACL_FLAG_RETORE_NATIVE flag.
+       */
+      if (fstype_equals(jcr->last_fname, "afs")) {
+         jcr->acl_data->flags |= BACL_FLAG_RESTORE_AFS;
+      } else {
+         jcr->acl_data->flags |= BACL_FLAG_RESTORE_NATIVE;
+      }
+#else
       jcr->acl_data->flags |= BACL_FLAG_RESTORE_NATIVE;
+#endif
 
       /*
        * Save that we started restoring to a new filesystem.
@@ -2170,6 +2288,18 @@ bacl_exit_code parse_acl_streams(JCR *jcr,
    }
 
    switch (stream) {
+#if defined(HAVE_AFS_ACL)
+   case STREAM_ACL_AFS_TEXT:
+      if (jcr->acl_data->flags & BACL_FLAG_RESTORE_AFS) {
+         return afs_parse_acl_stream(jcr, stream, content, content_length);
+      } else {
+         /*
+          * Increment error count but don't log an error again for the same filesystem.
+          */
+         jcr->acl_data->u.parse->nr_errors++;
+         return bacl_exit_ok;
+      }
+#endif
 #if defined(HAVE_ACL)
    case STREAM_UNIX_ACCESS_ACL:
    case STREAM_UNIX_DEFAULT_ACL: