]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/acl.c
Ensure that StorageId is updated after write
[bacula/bacula] / bacula / src / filed / acl.c
index cf0f442ceb64f7ef6c15ecd7ddf9911e3bd85caa..4880d70ae8e6308b3809e077101a4cb9643e2f53 100644 (file)
@@ -152,7 +152,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 +193,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 +202,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 +240,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 +315,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 +329,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 +378,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 +404,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:
          /*
@@ -360,7 +435,7 @@ static bacl_exit_code aix_parse_acl_streams(JCR *jcr,
             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 +452,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 +754,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 +810,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 +820,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 +871,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 +880,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 +909,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 +925,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 +944,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 +1061,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 +1068,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 +1082,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 +1097,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 +1111,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 +1187,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 +1211,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 +1225,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 +1486,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 +1544,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 +1563,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 +1576,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 +1592,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 +1694,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 +1711,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 +1725,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 +1734,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 +1796,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 +1818,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 +1832,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 +1844,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 +1855,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,7 +1975,6 @@ 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)
@@ -1886,6 +2001,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 +2020,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 +2038,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);
@@ -2007,7 +2126,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 +2137,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 +2152,7 @@ bacl_exit_code parse_acl_streams(JCR *jcr,
          return bacl_exit_error;
       }
       break;
+   }
    case 0:
       break;
    }