]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/acl.c
Add rudimentary support for saving AFS acls.
[bacula/bacula] / bacula / src / filed / acl.c
index cf0f442ceb64f7ef6c15ecd7ddf9911e3bd85caa..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.
  */
@@ -152,7 +154,31 @@ static bool acl_is_trivial(struct acl *acl)
 
 static bool acl_nfs4_is_trivial(nfs4_acl_int_t *acl)
 {
+#if 0
    return (acl->aclEntryN > 0 ? false : true);
+#else
+   int i;
+   int count = acl->aclEntryN;
+   nfs4_ace_int_t *ace;
+
+   for (i = 0; i < count; i++) {
+      ace = &acl->aclEntry[i];
+      if (!((ace->flags & ACE4_ID_SPECIAL) != 0 &&
+            (ace->aceWho.special_whoid == ACE4_WHO_OWNER ||
+             ace->aceWho.special_whoid == ACE4_WHO_GROUP ||
+             ace->aceWho.special_whoid == ACE4_WHO_EVERYONE) &&
+             ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE &&
+             ace->aceFlags == 0 &&
+            (ace->aceMask & ~(ACE4_READ_DATA |
+                              ACE4_LIST_DIRECTORY |
+                              ACE4_WRITE_DATA |
+                              ACE4_ADD_FILE |
+                              ACE4_EXECUTE)) == 0)) {
+         return false;
+      }
+   }
+   return true;
+#endif
 }
 
 /*
@@ -169,7 +195,6 @@ static int os_default_acl_streams[1] = {
 
 static bacl_exit_code aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
-   berrno be;
    mode_t mode;
    acl_type_t type;
    size_t aclsize, acltxtsize;
@@ -179,12 +204,25 @@ static bacl_exit_code aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
    /*
     * First see how big the buffers should be.
     */
+   memset(&type, 0, sizeof(acl_type_t));
    type.u64 = ACL_ANY;
-   if (aclx_get(jcr->last_fname, GET_ACLINFO_ONLY, &type, NULL, &aclsize, NULL) < 0) {
+   if (aclx_get(jcr->last_fname, GET_ACLINFO_ONLY, &type, NULL, &aclsize, &mode) < 0) {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          retval = bacl_exit_ok;
          goto bail_out;
+      case ENOSYS:
+         /*
+          * If the filesystem reports it doesn't support ACLs we clear the
+          * BACL_FLAG_SAVE_NATIVE flag so we skip ACL saves on all other files
+          * on the same filesystem. The BACL_FLAG_SAVE_NATIVE flag gets set again
+          * when we change from one filesystem to an other.
+          */
+         jcr->acl_data->flags &= ~BACL_FLAG_SAVE_NATIVE;
+         retval = bacl_exit_ok;
+         goto bail_out;
       default:
          Mmsg2(jcr->errmsg,
                _("aclx_get error on file \"%s\": ERR=%s\n"),
@@ -204,6 +242,8 @@ static bacl_exit_code aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
     * Retrieve the ACL info.
     */
    if (aclx_get(jcr->last_fname, 0, &type, aclbuf, &aclsize, &mode) < 0) {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          retval = bacl_exit_ok;
@@ -277,7 +317,7 @@ static bacl_exit_code aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
       }
    }
 
-   jcr->acl_data->u.build->u.build->content_length = strlen(jcr->acl_data->u.build->content) + 1;
+   jcr->acl_data->u.build->content_length = strlen(jcr->acl_data->u.build->content) + 1;
    switch (type.u64) {
    case ACL_AIXC:
       retval = send_acl_stream(jcr, STREAM_ACL_AIX_AIXC);
@@ -291,13 +331,38 @@ bail_out:
    return retval;
 }
 
+/*
+ * See if a specific type of ACLs are supported on the filesystem
+ * the file is located on.
+ */
+static inline bool aix_query_acl_support(JCR *jcr,
+                                         uint64_t aclType,
+                                         acl_type_t *pacl_type_info)
+{
+   unsigned int i;
+   acl_types_list_t acl_type_list;
+   size_t acl_type_list_len = sizeof(acl_types_list_t);
+
+   memset(&acl_type_list, 0, sizeof(acl_type_list));
+   if (aclx_gettypes(jcr->last_fname, &acl_type_list, &acl_type_list_len)) {
+      return false;
+   }
+
+   for (i = 0; i < acl_type_list.num_entries; i++) {
+      if (acl_type_list.entries[i].u64 == aclType) {
+         memcpy(pacl_type_info, acl_type_list.entries + i, sizeof(acl_type_t));
+         return true;
+      }
+   }
+   return false;
+}
+
 static bacl_exit_code aix_parse_acl_streams(JCR *jcr,
                                             int stream,
                                             char *content,
                                             uint32_t content_length)
 {
    int cnt;
-   berrno be;
    acl_type_t type;
    size_t aclsize;
    bacl_exit_code retval = bacl_exit_error;
@@ -315,10 +380,20 @@ static bacl_exit_code aix_parse_acl_streams(JCR *jcr,
       retval = bacl_exit_ok;
       goto bail_out;
    case STREAM_ACL_AIX_AIXC:
-      type.u64 = ACL_AIXC;
+      if (!aix_query_acl_support(jcr, ACL_AIXC, &type)) {
+         Mmsg1(jcr->errmsg,
+               _("Trying to restore POSIX acl on file \"%s\" on filesystem without AIXC acl support\n"),
+               jcr->last_fname);
+         goto bail_out;
+      }
       break;
    case STREAM_ACL_AIX_NFS4:
-      type.u64 = ACL_NFS4;
+      if (!aix_query_acl_support(jcr, ACL_NFS4, &type)) {
+         Mmsg1(jcr->errmsg,
+               _("Trying to restore NFSv4 acl on file \"%s\" on filesystem without NFS4 acl support\n"),
+               jcr->last_fname);
+         goto bail_out;
+      }
       break;
    default:
       goto bail_out;
@@ -331,6 +406,8 @@ static bacl_exit_code aix_parse_acl_streams(JCR *jcr,
    aclbuf = check_pool_memory_size(aclbuf, content_length);
    aclsize = content_length;
    if (aclx_scanStr(content, aclbuf, &aclsize, type) < 0) {
+      berrno be;
+
       switch (errno) {
       case ENOSPC:
          /*
@@ -356,11 +433,13 @@ 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"),
-                     jcr->last_fname, be.bstrerror());
+                     jcr->last_fname, be.bstrerror(errno));
                Dmsg2(100, "aclx_scanStr error file=%s ERR=%s\n",
                      jcr->last_fname, be.bstrerror());
                goto bail_out;
@@ -377,10 +456,22 @@ static bacl_exit_code aix_parse_acl_streams(JCR *jcr,
    }
 
    if (aclx_put(jcr->last_fname, SET_ACL, type, aclbuf, aclsize, 0) < 0) {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          retval = bacl_exit_ok;
          goto bail_out;
+      case ENOSYS:
+         /*
+          * If the filesystem reports it doesn't support ACLs we clear the
+          * BACL_FLAG_RESTORE_NATIVE flag so we skip ACL restores on all other files
+          * on the same filesystem. The BACL_FLAG_RESTORE_NATIVE flag gets set again
+          * when we change from one filesystem to an other.
+          */
+         jcr->acl_data->flags &= ~BACL_FLAG_RESTORE_NATIVE;
+         retval = bacl_exit_ok;
+         goto bail_out;
       default:
          Mmsg2(jcr->errmsg,
                _("aclx_put error on file \"%s\": ERR=%s\n"),
@@ -667,7 +758,6 @@ static bacl_exit_code generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
    acl_t acl;
    acl_type_t ostype;
    char *acl_text;
-   berrno be;
    bacl_exit_code retval = bacl_exit_ok;
 
    ostype = bac_to_os_acltype(acltype);
@@ -724,6 +814,7 @@ static bacl_exit_code generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
          return bacl_exit_ok;
       }
 
+      berrno be;
       Mmsg2(jcr->errmsg,
             _("acl_to_text error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -733,6 +824,8 @@ static bacl_exit_code generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
       retval = bacl_exit_error;
       goto bail_out;
    } else {
+      berrno be;
+
       /*
        * Handle errors gracefully.
        */
@@ -782,7 +875,6 @@ static bacl_exit_code generic_set_acl_on_os(JCR *jcr,
 {
    acl_t acl;
    acl_type_t ostype;
-   berrno be;
 
    /*
     * If we get empty default ACLs, clear ACLs now
@@ -792,6 +884,8 @@ static bacl_exit_code generic_set_acl_on_os(JCR *jcr,
       if (acl_delete_def_file(jcr->last_fname) == 0) {
          return bacl_exit_ok;
       }
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          return bacl_exit_ok;
@@ -819,6 +913,8 @@ static bacl_exit_code generic_set_acl_on_os(JCR *jcr,
 
    acl = acl_from_text(content);
    if (acl == NULL) {
+      berrno be;
+
       Mmsg2(jcr->errmsg,
             _("acl_from_text error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -833,6 +929,8 @@ static bacl_exit_code generic_set_acl_on_os(JCR *jcr,
     * As it does the right thing, given valid input, just ignore acl_valid().
     */
    if (acl_valid(acl) != 0) {
+      berrno be;
+
       Mmsg2(jcr->errmsg,
             _("acl_valid error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -850,6 +948,8 @@ static bacl_exit_code generic_set_acl_on_os(JCR *jcr,
     * don't save acls of symlinks (which cannot have acls anyhow)
     */
    if (acl_set_file(jcr->last_fname, ostype, acl) != 0 && jcr->last_type != FT_LNK) {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          acl_free(acl);
@@ -965,7 +1065,6 @@ static bacl_exit_code freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
    int acl_enabled = 0;
    bacl_type acltype = BACL_TYPE_NONE;
-   berrno be;
 
 #if defined(_PC_ACL_NFS4)
    /*
@@ -973,7 +1072,9 @@ static bacl_exit_code freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
     */
    acl_enabled = pathconf(jcr->last_fname, _PC_ACL_NFS4);
    switch (acl_enabled) {
-   case -1:
+   case -1: {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          return bacl_exit_ok;
@@ -985,6 +1086,7 @@ static bacl_exit_code freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
                jcr->last_fname, be.bstrerror());
          return bacl_exit_error;
       }
+   }
    case 0:
       break;
    default:
@@ -999,7 +1101,9 @@ static bacl_exit_code freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
        */
       acl_enabled = pathconf(jcr->last_fname, _PC_ACL_EXTENDED);
       switch (acl_enabled) {
-      case -1:
+      case -1: {
+         berrno be;
+
          switch (errno) {
          case ENOENT:
             return bacl_exit_ok;
@@ -1011,6 +1115,7 @@ static bacl_exit_code freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
                   jcr->last_fname, be.bstrerror());
             return bacl_exit_error;
          }
+      }
       case 0:
          break;
       default:
@@ -1086,7 +1191,6 @@ static bacl_exit_code freebsd_parse_acl_streams(JCR *jcr,
 {
    int acl_enabled = 0;
    const char *acl_type_name;
-   berrno be;
 
    /*
     * First make sure the filesystem supports acls.
@@ -1111,7 +1215,9 @@ static bacl_exit_code freebsd_parse_acl_streams(JCR *jcr,
    }
 
    switch (acl_enabled) {
-   case -1:
+   case -1: {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          return bacl_exit_ok;
@@ -1123,6 +1229,7 @@ static bacl_exit_code freebsd_parse_acl_streams(JCR *jcr,
                content, jcr->last_fname, be.bstrerror());
          return bacl_exit_error;
       }
+   }
    case 0:
       /*
        * If the filesystem reports it doesn't support ACLs we clear the
@@ -1383,9 +1490,10 @@ static bacl_exit_code hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
    int n;
    struct acl_entry acls[NACLENTRIES];
    char *acl_text;
-   berrno be;
 
    if ((n = getacl(jcr->last_fname, 0, acls)) < 0) {
+      berrno be;
+
       switch (errno) {
 #if defined(BACL_ENOTSUP)
       case BACL_ENOTSUP:
@@ -1440,6 +1548,8 @@ static bacl_exit_code hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 
          return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY);
       }
+
+      berrno be;
       Mmsg2(jcr->errmsg,
             _("acltostr error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -1457,10 +1567,11 @@ static bacl_exit_code hpux_parse_acl_streams(JCR *jcr,
 {
    int n, stat;
    struct acl_entry acls[NACLENTRIES];
-   berrno be;
 
    n = strtoacl(content, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
    if (n <= 0) {
+      berrno be;
+
       Mmsg2(jcr->errmsg,
             _("strtoacl error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -1469,6 +1580,8 @@ static bacl_exit_code hpux_parse_acl_streams(JCR *jcr,
       return bacl_exit_error;
    }
    if (strtoacl(content, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) {
+      berrno be;
+
       Mmsg2(jcr->errmsg,
             _("strtoacl error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -1483,8 +1596,9 @@ static bacl_exit_code hpux_parse_acl_streams(JCR *jcr,
     * This is only true for the old acl streams as in the new implementation we
     * don't save acls of symlinks (which cannot have acls anyhow)
     */
-   if (setacl(jcr->last_fname, n, acls) != 0 &&
-       jcr->last_type != FT_LNK) {
+   if (setacl(jcr->last_fname, n, acls) != 0 && jcr->last_type != FT_LNK) {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          return bacl_exit_ok;
@@ -1584,7 +1698,6 @@ static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
    acl_t *aclp;
    char *acl_text;
    bacl_exit_code stream_status = bacl_exit_error;
-   berrno be;
 
    /*
     * See if filesystem supports acls.
@@ -1602,7 +1715,9 @@ static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
       pm_strcpy(jcr->acl_data->u.build->content, "");
       jcr->acl_data->u.build->content_length = 0;
       return bacl_exit_ok;
-   case -1:
+   case -1: {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          return bacl_exit_ok;
@@ -1614,6 +1729,7 @@ static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
                jcr->last_fname, be.bstrerror());
          return bacl_exit_error;
       }
+   }
    default:
       break;
    }
@@ -1622,6 +1738,8 @@ static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
     * Get ACL info: don't bother allocating space if there is only a trivial ACL.
     */
    if (acl_get(jcr->last_fname, ACL_NO_TRIVIAL, &aclp) != 0) {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          return bacl_exit_ok;
@@ -1682,7 +1800,6 @@ static bacl_exit_code solaris_parse_acl_streams(JCR *jcr,
 {
    acl_t *aclp;
    int acl_enabled, error;
-   berrno be;
 
    switch (stream) {
    case STREAM_UNIX_ACCESS_ACL:
@@ -1705,7 +1822,9 @@ static bacl_exit_code solaris_parse_acl_streams(JCR *jcr,
                _("Trying to restore acl on file \"%s\" on filesystem without acl support\n"),
                jcr->last_fname);
          return bacl_exit_error;
-      case -1:
+      case -1: {
+         berrno be;
+
          switch (errno) {
          case ENOENT:
             return bacl_exit_ok;
@@ -1717,6 +1836,7 @@ static bacl_exit_code solaris_parse_acl_streams(JCR *jcr,
                   content, jcr->last_fname, be.bstrerror());
             return bacl_exit_error;
          }
+      }
       default:
          /*
           * On a filesystem with ACL support make sure this particular ACL type can be restored.
@@ -1728,7 +1848,7 @@ static bacl_exit_code solaris_parse_acl_streams(JCR *jcr,
              */
             if ((acl_enabled & (_ACL_ACLENT_ENABLED | _ACL_ACE_ENABLED)) == 0) {
                Mmsg1(jcr->errmsg,
-                     _("Trying to restore acl on file \"%s\" on filesystem without aclent acl support\n"),
+                     _("Trying to restore POSIX acl on file \"%s\" on filesystem without aclent acl support\n"),
                      jcr->last_fname);
                return bacl_exit_error;
             }
@@ -1739,7 +1859,7 @@ static bacl_exit_code solaris_parse_acl_streams(JCR *jcr,
              */
             if ((acl_enabled & _ACL_ACE_ENABLED) == 0) {
                Mmsg1(jcr->errmsg,
-                     _("Trying to restore acl on file \"%s\" on filesystem without ace acl support\n"),
+                     _("Trying to restore NFSv4 acl on file \"%s\" on filesystem without ace acl support\n"),
                      jcr->last_fname);
                return bacl_exit_error;
             }
@@ -1859,11 +1979,11 @@ static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
    int n;
    aclent_t *acls;
    char *acl_text;
-   berrno be;
 
    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) {
@@ -1886,6 +2006,7 @@ static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
          return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT);
       }
 
+      berrno be;
       Mmsg2(jcr->errmsg,
             _("acltotext error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -1904,10 +2025,11 @@ static bacl_exit_code solaris_parse_acl_streams(JCR *jcr,
 {
    int n;
    aclent_t *acls;
-   berrno be;
 
    acls = aclfromtext(content, &n);
    if (!acls) {
+      berrno be;
+
       Mmsg2(jcr->errmsg,
             _("aclfromtext error on file \"%s\": ERR=%s\n"),
             jcr->last_fname, be.bstrerror());
@@ -1921,6 +2043,8 @@ static bacl_exit_code solaris_parse_acl_streams(JCR *jcr,
     * not have attributes, and the file it is linked to may not yet be restored.
     */
    if (acl(jcr->last_fname, SETACL, n, acls) == -1 && jcr->last_type != FT_LNK) {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          actuallyfree(acls);
@@ -1953,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.
  */
 
@@ -1964,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.
     */
@@ -1974,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
@@ -2007,7 +2231,6 @@ bacl_exit_code parse_acl_streams(JCR *jcr,
                                  uint32_t content_length)
 {
    int ret;
-   berrno be;
    struct stat st;
    unsigned int cnt;
 
@@ -2019,7 +2242,9 @@ bacl_exit_code parse_acl_streams(JCR *jcr,
     */
    ret = lstat(jcr->last_fname, &st);
    switch (ret) {
-   case -1:
+   case -1: {
+      berrno be;
+
       switch (errno) {
       case ENOENT:
          return bacl_exit_ok;
@@ -2032,6 +2257,7 @@ bacl_exit_code parse_acl_streams(JCR *jcr,
          return bacl_exit_error;
       }
       break;
+   }
    case 0:
       break;
    }
@@ -2040,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.
@@ -2049,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: