]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/xattr.c
Fix bug #1806 failure to save second and more xattr.
[bacula/bacula] / bacula / src / filed / xattr.c
index 7e187339fe3c977da15e84cfb3a586a7e5d7ad33..a181d4123fad6d2ad7c09f3321a5508830aef3a4 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2008-2009 Free Software Foundation Europe e.V.
+   Copyright (C) 2008-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
    This program is Free Software; you can redistribute it and/or
-   modify it under the terms of version two of the GNU General Public
+   modify it under the terms of version three of the GNU Affero General Public
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
    License as published by the Free Software Foundation and included
    in the file LICENSE.
 
@@ -15,7 +15,7 @@
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
+   You should have received a copy of the GNU Affero General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
  *   - NetBSD (Extended Attributes)
  *   - FreeBSD (Extended Attributes)
  *   - OpenBSD (Extended Attributes)
  *   - NetBSD (Extended Attributes)
  *   - FreeBSD (Extended Attributes)
  *   - OpenBSD (Extended Attributes)
+ *     (As it seems either they never implemented xattr or they are removed
+ *      the support as it stated it was in version 3.1 but the current syscall
+ *      tabled shows the extattr_ functions are not implemented. So as such we
+ *      might eventually support xattr on OpenBSD when they implemented them using
+ *      the same interface as FreeBSD and NetBSD.
  *   - Solaris (Extended Attributes and Extensible Attributes)
  *
  *   Written by Marco van Wieringen, November MMVIII
  *   - Solaris (Extended Attributes and Extensible Attributes)
  *
  *   Written by Marco van Wieringen, November MMVIII
@@ -140,7 +145,11 @@ static void xattr_drop_internal_table(alist *xattr_value_list)
 
       if (current_xattr->value_length > 0)
          free(current_xattr->value);
 
       if (current_xattr->value_length > 0)
          free(current_xattr->value);
+
+      free(current_xattr);
    }
    }
+
+   delete xattr_value_list;
 }
 
 /*
 }
 
 /*
@@ -184,7 +193,9 @@ static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len
       ser_bytes(current_xattr->name, current_xattr->name_length);
 
       ser_uint32(current_xattr->value_length);
       ser_bytes(current_xattr->name, current_xattr->name_length);
 
       ser_uint32(current_xattr->value_length);
-      ser_bytes(current_xattr->value, current_xattr->value_length);
+      if (current_xattr->value_length > 0 && current_xattr->value) {
+         ser_bytes(current_xattr->value, current_xattr->value_length);
+      }
    }
 
    ser_end(jcr->xattr_data->content, expected_serialize_len + 10);
    }
 
    ser_end(jcr->xattr_data->content, expected_serialize_len + 10);
@@ -193,15 +204,10 @@ static uint32_t serialize_xattr_stream(JCR *jcr, uint32_t expected_serialize_len
    return jcr->xattr_data->content_length;
 }
 
    return jcr->xattr_data->content_length;
 }
 
-/*
- * Forward declaration for restore function.
- */
-static bxattr_exit_code restore_xattr_on_file(JCR *jcr, xattr_t *xattr);
-
-static bxattr_exit_code unserialize_xattr_stream(JCR *jcr)
+static bxattr_exit_code unserialize_xattr_stream(JCR *jcr, alist *xattr_value_list)
 {
    unser_declare;
 {
    unser_declare;
-   xattr_t current_xattr;
+   xattr_t *current_xattr;
    bxattr_exit_code retval = bxattr_exit_ok;
 
    /*
    bxattr_exit_code retval = bxattr_exit_ok;
 
    /*
@@ -216,56 +222,58 @@ static bxattr_exit_code unserialize_xattr_stream(JCR *jcr)
        * First make sure the magic is present. This way we can easily catch corruption.
        * Any missing MAGIC is fatal we do NOT try to continue.
        */
        * First make sure the magic is present. This way we can easily catch corruption.
        * Any missing MAGIC is fatal we do NOT try to continue.
        */
-      unser_uint32(current_xattr.magic);
-      if (current_xattr.magic != XATTR_MAGIC) {
+
+      current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
+      unser_uint32(current_xattr->magic);
+      if (current_xattr->magic != XATTR_MAGIC) {
          Mmsg1(jcr->errmsg, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
                jcr->last_fname);
          Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n",
                jcr->last_fname);
          Mmsg1(jcr->errmsg, _("Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n"),
                jcr->last_fname);
          Dmsg1(100, "Illegal xattr stream, no XATTR_MAGIC on file \"%s\"\n",
                jcr->last_fname);
+         free(current_xattr);
          return bxattr_exit_error;
       }
 
       /*
        * Decode the valuepair. First decode the length of the name.
        */
          return bxattr_exit_error;
       }
 
       /*
        * Decode the valuepair. First decode the length of the name.
        */
-      unser_uint32(current_xattr.name_length);
+      unser_uint32(current_xattr->name_length);
+      if (current_xattr->name_length == 0) {
+         Mmsg1(jcr->errmsg, _("Illegal xattr stream, xattr name length <= 0 on file \"%s\"\n"),
+               jcr->last_fname);
+         Dmsg1(100, "Illegal xattr stream, xattr name length <= 0 on file \"%s\"\n",
+               jcr->last_fname);
+         free(current_xattr);
+         return bxattr_exit_error;
+      }
 
       /*
        * Allocate room for the name and decode its content.
        */
 
       /*
        * Allocate room for the name and decode its content.
        */
-      current_xattr.name = (char *)malloc(current_xattr.name_length + 1);
-      unser_bytes(current_xattr.name, current_xattr.name_length);
+      current_xattr->name = (char *)malloc(current_xattr->name_length + 1);
+      unser_bytes(current_xattr->name, current_xattr->name_length);
 
       /*
        * The xattr_name needs to be null terminated for lsetxattr.
        */
 
       /*
        * The xattr_name needs to be null terminated for lsetxattr.
        */
-      current_xattr.name[current_xattr.name_length] = '\0';
+      current_xattr->name[current_xattr->name_length] = '\0';
 
       /*
        * Decode the value length.
        */
 
       /*
        * Decode the value length.
        */
-      unser_uint32(current_xattr.value_length);
+      unser_uint32(current_xattr->value_length);
 
 
-      /*
-       * Allocate room for the value and decode its content.
-       */
-      current_xattr.value = (char *)malloc(current_xattr.value_length);
-      unser_bytes(current_xattr.value, current_xattr.value_length);
-
-      /*
-       * Try to set the extended attribute on the file.
-       * If we fail to set this attribute we flag the error but its not fatal,
-       * we try to restore the other extended attributes too.
-       */
-      if (restore_xattr_on_file(jcr, &current_xattr) != bxattr_exit_ok) {
-         retval = bxattr_exit_error;
+      if (current_xattr->value_length > 0) {
+         /*
+          * Allocate room for the value and decode its content.
+          */
+         current_xattr->value = (char *)malloc(current_xattr->value_length);
+         unser_bytes(current_xattr->value, current_xattr->value_length);
+      } else {
+         current_xattr->value = NULL;
       }
 
       }
 
-      /*
-       * Free the temporary buffers.
-       */
-      free(current_xattr.name);
-      free(current_xattr.value);
+      xattr_value_list->append(current_xattr);
    }
 
    unser_end(jcr->xattr_data->content, jcr->xattr_data->content_length);
    }
 
    unser_end(jcr->xattr_data->content, jcr->xattr_data->content_length);
@@ -275,7 +283,6 @@ static bxattr_exit_code unserialize_xattr_stream(JCR *jcr)
 
 /*
  * This is a supported OS, See what kind of interface we should use.
 
 /*
  * This is a supported OS, See what kind of interface we should use.
- * Start with the generic interface used by most OS-es.
  */
 #if defined(HAVE_DARWIN_OS) || \
     defined(HAVE_LINUX_OS)
  */
 #if defined(HAVE_DARWIN_OS) || \
     defined(HAVE_LINUX_OS)
@@ -330,7 +337,7 @@ static const char *xattr_skiplist[1] = { NULL };
    #endif
 #endif
 
    #endif
 #endif
 
-static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
+static bxattr_exit_code linux_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
    bool skip_xattr;
    char *xattr_list, *bp;
 {
    bool skip_xattr;
    char *xattr_list, *bp;
@@ -347,7 +354,8 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
     * First get the length of the available list with extended attributes.
     */
    xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
     * First get the length of the available list with extended attributes.
     */
    xattr_list_len = llistxattr(jcr->last_fname, NULL, 0);
-   if (xattr_list_len < 0) {
+   switch (xattr_list_len) {
+   case -1:
       switch (errno) {
       case ENOENT:
          return bxattr_exit_ok;
       switch (errno) {
       case ENOENT:
          return bxattr_exit_ok;
@@ -358,8 +366,11 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
                jcr->last_fname, be.bstrerror());
          return bxattr_exit_error;
       }
                jcr->last_fname, be.bstrerror());
          return bxattr_exit_error;
       }
-   } else if (xattr_list_len == 0) {
+      break;
+   case 0:
       return bxattr_exit_ok;
       return bxattr_exit_ok;
+   default:
+      break;
    }
 
    /*
    }
 
    /*
@@ -372,7 +383,8 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
     * Get the actual list of extended attributes names for a file.
     */
    xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
     * Get the actual list of extended attributes names for a file.
     */
    xattr_list_len = llistxattr(jcr->last_fname, xattr_list, xattr_list_len);
-   if (xattr_list_len < 0) {
+   switch (xattr_list_len) {
+   case -1:
       switch (errno) {
       case ENOENT:
          retval = bxattr_exit_ok;
       switch (errno) {
       case ENOENT:
          retval = bxattr_exit_ok;
@@ -384,6 +396,9 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
                jcr->last_fname, be.bstrerror());
          goto bail_out;
       }
                jcr->last_fname, be.bstrerror());
          goto bail_out;
       }
+      break;
+   default:
+      break;
    }
    xattr_list[xattr_list_len] = '\0';
 
    }
    xattr_list[xattr_list_len] = '\0';
 
@@ -395,6 +410,7 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
     */
    bp = xattr_list;
    while ((bp - xattr_list) + 1 < xattr_list_len) {
     */
    bp = xattr_list;
    while ((bp - xattr_list) + 1 < xattr_list_len) {
+      int name_len;
       skip_xattr = false;
 
       /*
       skip_xattr = false;
 
       /*
@@ -404,7 +420,7 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
        */
       if (ff_pkt->flags & FO_ACL) {
          for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
        */
       if (ff_pkt->flags & FO_ACL) {
          for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
-            if (!strcmp(bp, xattr_acl_skiplist[cnt])) {
+            if (bstrcmp(bp, xattr_acl_skiplist[cnt])) {
                skip_xattr = true;
                break;
             }
                skip_xattr = true;
                break;
             }
@@ -416,14 +432,15 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
        */
       if (!skip_xattr) {
          for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
        */
       if (!skip_xattr) {
          for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
-            if (!strcmp(bp, xattr_skiplist[cnt])) {
+            if (bstrcmp(bp, xattr_skiplist[cnt])) {
                skip_xattr = true;
                break;
             }
          }
       }
 
                skip_xattr = true;
                break;
             }
          }
       }
 
-      if (skip_xattr) {
+      name_len = strlen(bp);
+      if (skip_xattr || name_len == 0) {
          bp = strchr(bp, '\0') + 1;
          continue;
       }
          bp = strchr(bp, '\0') + 1;
          continue;
       }
@@ -438,7 +455,7 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
       /*
        * Allocate space for storing the name.
        */
       /*
        * Allocate space for storing the name.
        */
-      current_xattr->name_length = strlen(bp);
+      current_xattr->name_length = name_len;
       current_xattr->name = (char *)malloc(current_xattr->name_length);
       memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
 
       current_xattr->name = (char *)malloc(current_xattr->name_length);
       memcpy((caddr_t)current_xattr->name, (caddr_t)bp, current_xattr->name_length);
 
@@ -448,7 +465,8 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
        * First see how long the value is for the extended attribute.
        */
       xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
        * First see how long the value is for the extended attribute.
        */
       xattr_value_len = lgetxattr(jcr->last_fname, bp, NULL, 0);
-      if (xattr_value_len < 0) {
+      switch (xattr_value_len) {
+      case -1:
          switch (errno) {
          case ENOENT:
             retval = bxattr_exit_ok;
          switch (errno) {
          case ENOENT:
             retval = bxattr_exit_ok;
@@ -464,51 +482,57 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
             free(current_xattr);
             goto bail_out;
          }
             free(current_xattr);
             goto bail_out;
          }
-      }
+         break;
+      case 0:
+         current_xattr->value = NULL;
+         current_xattr->value_length = 0;
+         expected_serialize_len += sizeof(current_xattr->value_length);
+         break;
+      default:
+         /*
+          * Allocate space for storing the value.
+          */
+         current_xattr->value = (char *)malloc(xattr_value_len);
+         memset((caddr_t)current_xattr->value, 0, xattr_value_len);
 
 
-      /*
-       * Allocate space for storing the value.
-       */
-      current_xattr->value = (char *)malloc(xattr_value_len);
-      memset((caddr_t)current_xattr->value, 0, xattr_value_len);
+         xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
+         if (xattr_value_len < 0) {
+            switch (errno) {
+            case ENOENT:
+               retval = bxattr_exit_ok;
+               free(current_xattr->value);
+               free(current_xattr->name);
+               free(current_xattr);
+               goto bail_out;
+            default:
+               Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"),
+                     jcr->last_fname, be.bstrerror());
+               Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
+                     jcr->last_fname, be.bstrerror());
+               free(current_xattr->value);
+               free(current_xattr->name);
+               free(current_xattr);
+               goto bail_out;
+            }
+         }
+         /*
+          * Store the actual length of the value.
+          */
+         current_xattr->value_length = xattr_value_len;
+         expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
 
 
-      xattr_value_len = lgetxattr(jcr->last_fname, bp, current_xattr->value, xattr_value_len);
-      if (xattr_value_len < 0) {
-         switch (errno) {
-         case ENOENT:
-            retval = bxattr_exit_ok;
-            free(current_xattr->value);
-            free(current_xattr->name);
-            free(current_xattr);
-            goto bail_out;
-         default:
-            Mmsg2(jcr->errmsg, _("lgetxattr error on file \"%s\": ERR=%s\n"),
-                  jcr->last_fname, be.bstrerror());
-            Dmsg2(100, "lgetxattr error file=%s ERR=%s\n",
-                  jcr->last_fname, be.bstrerror());
+         /*
+          * Protect ourself against things getting out of hand.
+          */
+         if (expected_serialize_len >= MAX_XATTR_STREAM) {
+            Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
+                  jcr->last_fname, MAX_XATTR_STREAM);
             free(current_xattr->value);
             free(current_xattr->name);
             free(current_xattr);
             goto bail_out;
          }
             free(current_xattr->value);
             free(current_xattr->name);
             free(current_xattr);
             goto bail_out;
          }
-      }
-
-      /*
-       * Store the actual length of the value.
-       */
-      current_xattr->value_length = xattr_value_len;
-      expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
-
-      /*
-       * Protect ourself against things getting out of hand.
-       */
-      if (expected_serialize_len >= MAX_XATTR_STREAM) {
-         Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
-               jcr->last_fname, MAX_XATTR_STREAM);
-         free(current_xattr->value);
-         free(current_xattr->name);
-         free(current_xattr);
-         goto bail_out;
+         break;
       }
 
       xattr_value_list->append(current_xattr);
       }
 
       xattr_value_list->append(current_xattr);
@@ -535,8 +559,6 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
       }
 
       xattr_drop_internal_table(xattr_value_list);
       }
 
       xattr_drop_internal_table(xattr_value_list);
-      delete xattr_value_list;
-      xattr_value_list = NULL;
 
       /*
        * Send the datastream to the SD.
 
       /*
        * Send the datastream to the SD.
@@ -544,67 +566,69 @@ static bxattr_exit_code generic_xattr_build_streams(JCR *jcr, FF_PKT *ff_pkt)
       return send_xattr_stream(jcr, os_default_xattr_streams[0]);
    } else {
       xattr_drop_internal_table(xattr_value_list);
       return send_xattr_stream(jcr, os_default_xattr_streams[0]);
    } else {
       xattr_drop_internal_table(xattr_value_list);
-      delete xattr_value_list;
-      xattr_value_list = NULL;
 
       return bxattr_exit_ok;
    }
 
 bail_out:
 
       return bxattr_exit_ok;
    }
 
 bail_out:
-   if (xattr_list) {
+   if (xattr_list != NULL) {
       free(xattr_list);
    }
       free(xattr_list);
    }
-   if (xattr_value_list) {
+   if (xattr_value_list != NULL) {
       xattr_drop_internal_table(xattr_value_list);
       xattr_drop_internal_table(xattr_value_list);
-      delete xattr_value_list;
-      xattr_value_list = NULL;
    }
    return retval;
 }
 
    }
    return retval;
 }
 
-/*
- * This function gets called by the unserialize_xattr_stream function for the OS specific 
- * code to restore an extended attribute on a file.
- */
-static bxattr_exit_code restore_xattr_on_file(JCR *jcr, xattr_t *xattr)
+static bxattr_exit_code linux_xattr_parse_streams(JCR *jcr, int stream)
 {
 {
+   xattr_t *current_xattr;
+   alist *xattr_value_list;
    berrno be;
 
    berrno be;
 
-   if (lsetxattr(jcr->last_fname, xattr->name, xattr->value, xattr->value_length, 0) != 0) {
-      switch (errno) {
-      case ENOENT:
-         break;
-      default:
-         Mmsg2(jcr->errmsg, _("lsetxattr error on file \"%s\": ERR=%s\n"),
-               jcr->last_fname, be.bstrerror());
-         Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
-               jcr->last_fname, be.bstrerror());
-         return bxattr_exit_error;
-         break;
+   xattr_value_list = New(alist(10, not_owned_by_alist));
+
+   if (unserialize_xattr_stream(jcr, xattr_value_list) != bxattr_exit_ok) {
+      xattr_drop_internal_table(xattr_value_list);
+      return bxattr_exit_error;
+   }
+
+   foreach_alist(current_xattr, xattr_value_list) {
+      if (lsetxattr(jcr->last_fname, current_xattr->name, current_xattr->value, current_xattr->value_length, 0) != 0) {
+         switch (errno) {
+         case ENOENT:
+            goto bail_out;
+         default:
+            Mmsg2(jcr->errmsg, _("lsetxattr error on file \"%s\": ERR=%s\n"),
+                  jcr->last_fname, be.bstrerror());
+            Dmsg2(100, "lsetxattr error file=%s ERR=%s\n",
+                  jcr->last_fname, be.bstrerror());
+            goto bail_out;
+         }
       }
    }
 
       }
    }
 
+   xattr_drop_internal_table(xattr_value_list);
    return bxattr_exit_ok;
    return bxattr_exit_ok;
-}
 
 
-static bxattr_exit_code generic_xattr_parse_streams(JCR *jcr, int stream)
-{
-   return unserialize_xattr_stream(jcr);
+bail_out:
+   xattr_drop_internal_table(xattr_value_list);
+   return bxattr_exit_error;
 }
 
 /*
 }
 
 /*
- * For all these os-es setup the build and parse function pointer to the generic functions.
+ * Function pointers to the build and parse function to use for these xattrs.
  */
  */
-static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = generic_xattr_build_streams;
-static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = generic_xattr_parse_streams;
+static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = linux_xattr_build_streams;
+static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = linux_xattr_parse_streams;
 
 #elif defined(HAVE_FREEBSD_OS) || \
       defined(HAVE_NETBSD_OS) || \
       defined(HAVE_OPENBSD_OS)
 
 
 #elif defined(HAVE_FREEBSD_OS) || \
       defined(HAVE_NETBSD_OS) || \
       defined(HAVE_OPENBSD_OS)
 
-#if !defined(HAVE_EXTATTR_GET_LINK) || \
-    !defined(HAVE_EXTATTR_SET_LINK) || \
-    !defined(HAVE_EXTATTR_LIST_LINK) || \
+#if (!defined(HAVE_EXTATTR_GET_LINK) && !defined(HAVE_EXTATTR_GET_FILE)) || \
+    (!defined(HAVE_EXTATTR_SET_LINK) && !defined(HAVE_EXTATTR_SET_FILE)) || \
+    (!defined(HAVE_EXTATTR_LIST_LINK) && !defined(HAVE_EXTATTR_LIST_FILE)) || \
     !defined(HAVE_EXTATTR_NAMESPACE_TO_STRING) || \
     !defined(HAVE_EXTATTR_STRING_TO_NAMESPACE)
 #error "Missing full support for the extattr functions."
     !defined(HAVE_EXTATTR_NAMESPACE_TO_STRING) || \
     !defined(HAVE_EXTATTR_STRING_TO_NAMESPACE)
 #error "Missing full support for the extattr functions."
@@ -620,10 +644,20 @@ static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = generi
 #include <libutil.h>
 #endif
 
 #include <libutil.h>
 #endif
 
+#if !defined(HAVE_EXTATTR_GET_LINK) && defined(HAVE_EXTATTR_GET_FILE)
+#define extattr_get_link extattr_get_file
+#endif
+#if !defined(HAVE_EXTATTR_SET_LINK) && defined(HAVE_EXTATTR_SET_FILE)
+#define extattr_set_link extattr_set_file
+#endif
+#if !defined(HAVE_EXTATTR_LIST_LINK) && defined(HAVE_EXTATTR_LIST_FILE)
+#define extattr_list_link extattr_list_file
+#endif
+
 #if defined(HAVE_FREEBSD_OS)
 static int os_default_xattr_streams[1] = { STREAM_XATTR_FREEBSD };
 static int os_default_xattr_namespaces[2] = { EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM };
 #if defined(HAVE_FREEBSD_OS)
 static int os_default_xattr_streams[1] = { STREAM_XATTR_FREEBSD };
 static int os_default_xattr_namespaces[2] = { EXTATTR_NAMESPACE_USER, EXTATTR_NAMESPACE_SYSTEM };
-static const char *xattr_acl_skiplist[1] = { NULL };
+static const char *xattr_acl_skiplist[2] = { "system.posix1e.acl_access", NULL };
 static const char *xattr_skiplist[1] = { NULL };
 #elif defined(HAVE_NETBSD_OS)
 static int os_default_xattr_streams[1] = { STREAM_XATTR_NETBSD };
 static const char *xattr_skiplist[1] = { NULL };
 #elif defined(HAVE_NETBSD_OS)
 static int os_default_xattr_streams[1] = { STREAM_XATTR_NETBSD };
@@ -647,7 +681,8 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
    uint32_t expected_serialize_len = 0;
    unsigned int namespace_index;
    int attrnamespace;
    uint32_t expected_serialize_len = 0;
    unsigned int namespace_index;
    int attrnamespace;
-   char *current_attrnamespace, current_attrname[BUFSIZ], current_attrtuple[BUFSIZ];
+   char *current_attrnamespace = NULL;
+   char current_attrname[XATTR_BUFSIZ], current_attrtuple[XATTR_BUFSIZ];
    xattr_t *current_xattr;
    alist *xattr_value_list = NULL;
    bxattr_exit_code retval = bxattr_exit_error;
    xattr_t *current_xattr;
    alist *xattr_value_list = NULL;
    bxattr_exit_code retval = bxattr_exit_error;
@@ -661,15 +696,44 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
    for (namespace_index = 0; namespace_index < sizeof(os_default_xattr_namespaces) / sizeof(int); namespace_index++) {
       attrnamespace = os_default_xattr_namespaces[namespace_index];
 
    for (namespace_index = 0; namespace_index < sizeof(os_default_xattr_namespaces) / sizeof(int); namespace_index++) {
       attrnamespace = os_default_xattr_namespaces[namespace_index];
 
+      /*
+       * Convert the numeric attrnamespace into a string representation and make a private copy of that string.
+       * The extattr_namespace_to_string functions returns a strdupped string which we need to free.
+       */
+      if (extattr_namespace_to_string(attrnamespace, &current_attrnamespace) != 0) {
+         Mmsg2(jcr->errmsg, _("Failed to convert %d into namespace on file \"%s\"\n"),
+               attrnamespace, jcr->last_fname);
+         Dmsg2(100, "Failed to convert %d into namespace on file \"%s\"\n",
+               attrnamespace, jcr->last_fname);
+         goto bail_out;
+      }
+
       /*
        * First get the length of the available list with extended attributes.
       /*
        * First get the length of the available list with extended attributes.
+       * If we get EPERM on system namespace, don't return error.
+       * This is expected for normal users trying to archive the system
+       * namespace on FreeBSD 6.2 and later. On NetBSD 3.1 and later,
+       * they've decided to return EOPNOTSUPP instead.
        */
       xattr_list_len = extattr_list_link(jcr->last_fname, attrnamespace, NULL, 0);
        */
       xattr_list_len = extattr_list_link(jcr->last_fname, attrnamespace, NULL, 0);
-      if (xattr_list_len < 0) {
+      switch (xattr_list_len) {
+      case -1:
          switch (errno) {
          case ENOENT:
             retval = bxattr_exit_ok;
             goto bail_out;
          switch (errno) {
          case ENOENT:
             retval = bxattr_exit_ok;
             goto bail_out;
+#if defined(EOPNOTSUPP)
+         case EOPNOTSUPP:
+#endif
+         case EPERM:
+            if (attrnamespace == EXTATTR_NAMESPACE_SYSTEM) {
+               actuallyfree(current_attrnamespace);
+               current_attrnamespace = NULL;
+               continue;
+            }
+            /*
+             * FALLTHROUGH
+             */
          default:
             Mmsg2(jcr->errmsg, _("extattr_list_link error on file \"%s\": ERR=%s\n"),
                   jcr->last_fname, be.bstrerror());
          default:
             Mmsg2(jcr->errmsg, _("extattr_list_link error on file \"%s\": ERR=%s\n"),
                   jcr->last_fname, be.bstrerror());
@@ -677,8 +741,11 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
                   jcr->last_fname, be.bstrerror());
             goto bail_out;
          }
                   jcr->last_fname, be.bstrerror());
             goto bail_out;
          }
-      } else if (xattr_list_len == 0) {
+         break;
+      case 0:
          continue;
          continue;
+      default:
+         break;
       }
 
       /*
       }
 
       /*
@@ -691,7 +758,8 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
        * Get the actual list of extended attributes names for a file.
        */
       xattr_list_len = extattr_list_link(jcr->last_fname, attrnamespace, xattr_list, xattr_list_len);
        * Get the actual list of extended attributes names for a file.
        */
       xattr_list_len = extattr_list_link(jcr->last_fname, attrnamespace, xattr_list, xattr_list_len);
-      if (xattr_list_len < 0) {
+      switch (xattr_list_len) {
+      case -1:
          switch (errno) {
          case ENOENT:
             retval = bxattr_exit_ok;
          switch (errno) {
          case ENOENT:
             retval = bxattr_exit_ok;
@@ -703,6 +771,9 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
                   jcr->last_fname, be.bstrerror());
             goto bail_out;
          }
                   jcr->last_fname, be.bstrerror());
             goto bail_out;
          }
+         break;
+      default:
+         break;
       }
       xattr_list[xattr_list_len] = '\0';
 
       }
       xattr_list[xattr_list_len] = '\0';
 
@@ -712,24 +783,21 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
        */
       for (index = 0; index < xattr_list_len; index += xattr_list[index] + 1) {
          skip_xattr = false;
        */
       for (index = 0; index < xattr_list_len; index += xattr_list[index] + 1) {
          skip_xattr = false;
-         bsnprintf(current_attrname, sizeof(current_attrname), "%*.*s",
-                   xattr_list[index], xattr_list[index], xattr_list + (index + 1));
 
          /*
 
          /*
-          * First make a xattr tuple of the current namespace and the name of the xattr.
-          * e.g. something like user.<attrname> or system.<attrname>
+          * Print the current name into the buffer as its not null terminated we need to
+          * use the length encoded in the string for copying only the needed bytes.
           */
           */
-         if (extattr_namespace_to_string(attrnamespace, &current_attrnamespace) != 0) {
-            Mmsg2(jcr->errmsg, _("Failed to convert %d into namespace on file \"%s\"\n"),
-                  attrnamespace, jcr->last_fname);
-            Dmsg2(100, "Failed to convert %d into namespace on file \"%s\"\n",
-                  attrnamespace, jcr->last_fname);
-            goto bail_out;
+         cnt = xattr_list[index];
+         if (cnt > ((int)sizeof(current_attrname) - 1)) {
+            cnt = ((int)sizeof(current_attrname) - 1);
          }
          }
+         strncpy(current_attrname, xattr_list + (index + 1), cnt);
+         current_attrname[cnt] = '\0';
 
          /*
 
          /*
-          * print the current name into the buffer as its not null terminated we need to
-          * use the length encoded in the string for copying only the needed bytes.
+          * First make a xattr tuple of the current namespace and the name of the xattr.
+          * e.g. something like user.<attrname> or system.<attrname>
           */
          bsnprintf(current_attrtuple, sizeof(current_attrtuple), "%s.%s", current_attrnamespace, current_attrname);
 
           */
          bsnprintf(current_attrtuple, sizeof(current_attrtuple), "%s.%s", current_attrnamespace, current_attrname);
 
@@ -740,7 +808,7 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
           */
          if (ff_pkt->flags & FO_ACL) {
             for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
           */
          if (ff_pkt->flags & FO_ACL) {
             for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
-               if (!strcmp(current_attrtuple, xattr_acl_skiplist[cnt])) {
+               if (bstrcmp(current_attrtuple, xattr_acl_skiplist[cnt])) {
                   skip_xattr = true;
                   break;
                }
                   skip_xattr = true;
                   break;
                }
@@ -750,9 +818,9 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
          /*
           * On some OSes we want to skip certain xattrs which are in the xattr_skiplist array.
           */
          /*
           * On some OSes we want to skip certain xattrs which are in the xattr_skiplist array.
           */
-         if (skip_xattr) {
+         if (!skip_xattr) {
             for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
             for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
-               if (!strcmp(current_attrtuple, xattr_skiplist[cnt])) {
+               if (bstrcmp(current_attrtuple, xattr_skiplist[cnt])) {
                   skip_xattr = true;
                   break;
                }
                   skip_xattr = true;
                   break;
                }
@@ -783,7 +851,8 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
           * First see how long the value is for the extended attribute.
           */
          xattr_value_len = extattr_get_link(jcr->last_fname, attrnamespace, current_attrname, NULL, 0);
           * First see how long the value is for the extended attribute.
           */
          xattr_value_len = extattr_get_link(jcr->last_fname, attrnamespace, current_attrname, NULL, 0);
-         if (xattr_value_len < 0) {
+         switch (xattr_value_len) {
+         case -1:
             switch (errno) {
             case ENOENT:
                retval = bxattr_exit_ok;
             switch (errno) {
             case ENOENT:
                retval = bxattr_exit_ok;
@@ -799,57 +868,71 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
                free(current_xattr);
                goto bail_out;
             }
                free(current_xattr);
                goto bail_out;
             }
-         }
+            break;
+         case 0:
+            current_xattr->value = NULL;
+            current_xattr->value_length = 0;
+            expected_serialize_len += sizeof(current_xattr->value_length);
+            break;
+         default:
+            /*
+             * Allocate space for storing the value.
+             */
+            current_xattr->value = (char *)malloc(xattr_value_len);
+            memset((caddr_t)current_xattr->value, 0, xattr_value_len);
+
+            xattr_value_len = extattr_get_link(jcr->last_fname, attrnamespace, current_attrname, current_xattr->value, xattr_value_len);
+            if (xattr_value_len < 0) {
+               switch (errno) {
+               case ENOENT:
+                  retval = bxattr_exit_ok;
+                  free(current_xattr->value);
+                  free(current_xattr->name);
+                  free(current_xattr);
+                  goto bail_out;
+               default:
+                  Mmsg2(jcr->errmsg, _("extattr_get_link error on file \"%s\": ERR=%s\n"),
+                        jcr->last_fname, be.bstrerror());
+                  Dmsg2(100, "extattr_get_link error file=%s ERR=%s\n",
+                        jcr->last_fname, be.bstrerror());
+                  free(current_xattr->value);
+                  free(current_xattr->name);
+                  free(current_xattr);
+                  goto bail_out;
+               }
+            }
 
 
-         /*
-          * Allocate space for storing the value.
-          */
-         current_xattr->value = (char *)malloc(xattr_value_len);
-         memset((caddr_t)current_xattr->value, 0, xattr_value_len);
+            /*
+             * Store the actual length of the value.
+             */
+            current_xattr->value_length = xattr_value_len;
+            expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
 
 
-         xattr_value_len = extattr_get_link(jcr->last_fname, attrnamespace, current_attrname, current_xattr->value, xattr_value_len);
-         if (xattr_value_len < 0) {
-            switch (errno) {
-            case ENOENT:
-               retval = bxattr_exit_ok;
-               free(current_xattr->value);
-               free(current_xattr->name);
-               free(current_xattr);
-               goto bail_out;
-            default:
-               Mmsg2(jcr->errmsg, _("extattr_get_link error on file \"%s\": ERR=%s\n"),
-                     jcr->last_fname, be.bstrerror());
-               Dmsg2(100, "extattr_get_link error file=%s ERR=%s\n",
-                     jcr->last_fname, be.bstrerror());
+            /*
+             * Protect ourself against things getting out of hand.
+             */
+            if (expected_serialize_len >= MAX_XATTR_STREAM) {
+               Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
+                     jcr->last_fname, MAX_XATTR_STREAM);
                free(current_xattr->value);
                free(current_xattr->name);
                free(current_xattr);
                goto bail_out;
             }
                free(current_xattr->value);
                free(current_xattr->name);
                free(current_xattr);
                goto bail_out;
             }
-         }
-
-         /*
-          * Store the actual length of the value.
-          */
-         current_xattr->value_length = xattr_value_len;
-         expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
-
-         /*
-          * Protect ourself against things getting out of hand.
-          */
-         if (expected_serialize_len >= MAX_XATTR_STREAM) {
-            Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
-                  jcr->last_fname, MAX_XATTR_STREAM);
-            free(current_xattr->value);
-            free(current_xattr->name);
-            free(current_xattr);
-            goto bail_out;
+            break;
          }
 
          xattr_value_list->append(current_xattr);
          xattr_count++;
          }
 
          xattr_value_list->append(current_xattr);
          xattr_count++;
+
       }
 
       }
 
+      /*
+       * Drop the local copy of the current_attrnamespace.
+       */
+      actuallyfree(current_attrnamespace);
+      current_attrnamespace = NULL;
+
       /*
        * We are done with this xattr list.
        */
       /*
        * We are done with this xattr list.
        */
@@ -873,8 +956,6 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
       }
 
       xattr_drop_internal_table(xattr_value_list);
       }
 
       xattr_drop_internal_table(xattr_value_list);
-      delete xattr_value_list;
-      xattr_value_list = NULL;
 
       /*
        * Send the datastream to the SD.
 
       /*
        * Send the datastream to the SD.
@@ -882,84 +963,91 @@ static bxattr_exit_code bsd_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
       return send_xattr_stream(jcr, os_default_xattr_streams[0]);
    } else {
       xattr_drop_internal_table(xattr_value_list);
       return send_xattr_stream(jcr, os_default_xattr_streams[0]);
    } else {
       xattr_drop_internal_table(xattr_value_list);
-      delete xattr_value_list;
-      xattr_value_list = NULL;
 
       return bxattr_exit_ok;
    }
 
 bail_out:
 
       return bxattr_exit_ok;
    }
 
 bail_out:
-   if (xattr_list) {
+   if (current_attrnamespace != NULL) {
+      actuallyfree(current_attrnamespace);
+   }
+   if (xattr_list != NULL) {
       free(xattr_list);
    }
       free(xattr_list);
    }
-   if (xattr_value_list) {
+   if (xattr_value_list != NULL) {
       xattr_drop_internal_table(xattr_value_list);
       xattr_drop_internal_table(xattr_value_list);
-      delete xattr_value_list;
-      xattr_value_list = NULL;
    }
    return retval;
 }
 
    }
    return retval;
 }
 
-/*
- * This function gets called by the unserialize_xattr_stream function for the OS specific 
- * code to restore an extended attribute on a file.
- */
-static bxattr_exit_code restore_xattr_on_file(JCR *jcr, xattr_t *xattr)
+static bxattr_exit_code bsd_parse_xattr_streams(JCR *jcr, int stream)
 {
 {
-   berrno be;
+   xattr_t *current_xattr;
+   alist *xattr_value_list;
    int current_attrnamespace, cnt;
    char *attrnamespace, *attrname;
    int current_attrnamespace, cnt;
    char *attrnamespace, *attrname;
+   berrno be;
 
 
-   /*
-    * Try splitting the xattr_name into a namespace and name part.
-    * The splitting character is a .
-    */
-   attrnamespace = xattr->name;
-   if ((attrname = strchr(attrnamespace, '.')) == (char *)NULL) {
-      Mmsg2(jcr->errmsg, _("Failed to split %s into namespace and name part on file \"%s\"\n"),
-            xattr->name, jcr->last_fname);
-      Dmsg2(100, "Failed to split %s into namespace and name part on file \"%s\"\n",
-            xattr->name, jcr->last_fname);
-      return bxattr_exit_error;
-   }
-   *attrname++ = '\0';
+   xattr_value_list = New(alist(10, not_owned_by_alist));
 
 
-   /*
-    * Make sure the attrnamespace makes sense.
-    */
-   if (extattr_string_to_namespace(attrnamespace, &current_attrnamespace) != 0) {
-      Mmsg2(jcr->errmsg, _("Failed to convert %s into namespace on file \"%s\"\n"),
-            attrnamespace, jcr->last_fname);
-      Dmsg2(100, "Failed to convert %s into namespace on file \"%s\"\n",
-            attrnamespace, jcr->last_fname);
+   if (unserialize_xattr_stream(jcr, xattr_value_list) != bxattr_exit_ok) {
+      xattr_drop_internal_table(xattr_value_list);
       return bxattr_exit_error;
    }
 
       return bxattr_exit_error;
    }
 
-   /*
-    * Try restoring the extended attribute.
-    */
-   cnt = extattr_set_link(jcr->last_fname, current_attrnamespace,
-                          attrname, xattr->value, xattr->value_length);
-   if (cnt < 0 || cnt != xattr->value_length) {
-      switch (errno) {
-      case ENOENT:
-         break;
-      default:
-         Mmsg2(jcr->errmsg, _("extattr_set_link error on file \"%s\": ERR=%s\n"),
-               jcr->last_fname, be.bstrerror());
-         Dmsg2(100, "extattr_set_link error file=%s ERR=%s\n",
-               jcr->last_fname, be.bstrerror());
-         return bxattr_exit_error;
-         break;
+   foreach_alist(current_xattr, xattr_value_list) {
+      /*
+       * Try splitting the xattr_name into a namespace and name part.
+       * The splitting character is a .
+       */
+      attrnamespace = current_xattr->name;
+      if ((attrname = strchr(attrnamespace, '.')) == (char *)NULL) {
+         Mmsg2(jcr->errmsg, _("Failed to split %s into namespace and name part on file \"%s\"\n"),
+               current_xattr->name, jcr->last_fname);
+         Dmsg2(100, "Failed to split %s into namespace and name part on file \"%s\"\n",
+               current_xattr->name, jcr->last_fname);
+         goto bail_out;
+      }
+      *attrname++ = '\0';
+
+      /*
+       * Make sure the attrnamespace makes sense.
+       */
+      if (extattr_string_to_namespace(attrnamespace, &current_attrnamespace) != 0) {
+         Mmsg2(jcr->errmsg, _("Failed to convert %s into namespace on file \"%s\"\n"),
+               attrnamespace, jcr->last_fname);
+         Dmsg2(100, "Failed to convert %s into namespace on file \"%s\"\n",
+               attrnamespace, jcr->last_fname);
+         goto bail_out;
+      }
+
+      /*
+       * Try restoring the extended attribute.
+       */
+      cnt = extattr_set_link(jcr->last_fname, current_attrnamespace,
+                             attrname, current_xattr->value, current_xattr->value_length);
+      if (cnt < 0 || cnt != (int)current_xattr->value_length) {
+         switch (errno) {
+         case ENOENT:
+            goto bail_out;
+            break;
+         default:
+            Mmsg2(jcr->errmsg, _("extattr_set_link error on file \"%s\": ERR=%s\n"),
+                  jcr->last_fname, be.bstrerror());
+            Dmsg2(100, "extattr_set_link error file=%s ERR=%s\n",
+                  jcr->last_fname, be.bstrerror());
+            goto bail_out;
+            break;
+         }
       }
    }
 
       }
    }
 
+   xattr_drop_internal_table(xattr_value_list);
    return bxattr_exit_ok;
    return bxattr_exit_ok;
-}
 
 
-static bxattr_exit_code bsd_parse_xattr_streams(JCR *jcr, int stream)
-{
-   return unserialize_xattr_stream(jcr);
+bail_out:
+   xattr_drop_internal_table(xattr_value_list);
+   return bxattr_exit_error;
 }
 
 /*
 }
 
 /*
@@ -1064,9 +1152,9 @@ static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = bsd_pa
 #include <sys/acl.h>
 #endif
 
 #include <sys/acl.h>
 #endif
 
-#if !defined(HAVE_OPENAT) ||
-    !defined(HAVE_UNKINKAT) ||
-    !defined(HAVE_FCHOWNAT) ||
+#if !defined(HAVE_OPENAT) || \
+    !defined(HAVE_UNLINKAT) || \
+    !defined(HAVE_FCHOWNAT) || \
     !defined(HAVE_FUTIMESAT)
 #error "Unable to compile code because of missing openat, unlinkat, fchownat or futimesat function"
 #endif
     !defined(HAVE_FUTIMESAT)
 #error "Unable to compile code because of missing openat, unlinkat, fchownat or futimesat function"
 #endif
@@ -1342,7 +1430,7 @@ static bxattr_exit_code solaris_save_xattr(JCR *jcr, int fd, const char *xattr_n
    char link_source[PATH_MAX];
    char *acl_text = NULL;
    char attribs[MAXSTRING];
    char link_source[PATH_MAX];
    char *acl_text = NULL;
    char attribs[MAXSTRING];
-   char buffer[BUFSIZ];
+   char buffer[XATTR_BUFSIZ];
    bxattr_exit_code retval = bxattr_exit_error;
    berrno be;
 
    bxattr_exit_code retval = bxattr_exit_error;
    berrno be;
 
@@ -1614,7 +1702,7 @@ static bxattr_exit_code solaris_save_xattr(JCR *jcr, int fd, const char *xattr_n
    }
 
 bail_out:
    }
 
 bail_out:
-   if (acl_text) {
+   if (acl_text != NULL) {
       free(acl_text);
    }
    if (attrfd != -1) {
       free(acl_text);
    }
    if (attrfd != -1) {
@@ -1731,13 +1819,13 @@ static bxattr_exit_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespac
       /*
        * Skip only the toplevel . dir.
        */
       /*
        * Skip only the toplevel . dir.
        */
-      if (!attr_parent && !strcmp(dp->d_name, "."))
+      if (!attr_parent && bstrcmp(dp->d_name, "."))
          continue;
 
       /*
        * Skip all .. directories
        */
          continue;
 
       /*
        * Skip all .. directories
        */
-      if (!strcmp(dp->d_name, ".."))
+      if (bstrcmp(dp->d_name, ".."))
          continue;
 
       Dmsg3(400, "processing extended attribute %s%s on file \"%s\"\n",
          continue;
 
       Dmsg3(400, "processing extended attribute %s%s on file \"%s\"\n",
@@ -1747,7 +1835,7 @@ static bxattr_exit_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespac
       /*
        * We are not interested in read-only extensible attributes.
        */
       /*
        * We are not interested in read-only extensible attributes.
        */
-      if (!strcmp(dp->d_name, VIEW_READONLY)) {
+      if (bstrcmp(dp->d_name, VIEW_READONLY)) {
          Dmsg3(400, "Skipping readonly extensible attributes %s%s on file \"%s\"\n",
             current_xattr_namespace, dp->d_name, jcr->last_fname);
 
          Dmsg3(400, "Skipping readonly extensible attributes %s%s on file \"%s\"\n",
             current_xattr_namespace, dp->d_name, jcr->last_fname);
 
@@ -1758,7 +1846,7 @@ static bxattr_exit_code solaris_save_xattrs(JCR *jcr, const char *xattr_namespac
        * We are only interested in read-write extensible attributes
        * when they contain non-transient values.
        */
        * We are only interested in read-write extensible attributes
        * when they contain non-transient values.
        */
-      if (!strcmp(dp->d_name, VIEW_READWRITE)) {
+      if (bstrcmp(dp->d_name, VIEW_READWRITE)) {
          /*
           * Determine if there are non-transient system attributes at the toplevel.
           * We need to provide a fd to the open file.
          /*
           * Determine if there are non-transient system attributes at the toplevel.
           * We need to provide a fd to the open file.
@@ -2012,7 +2100,7 @@ static bxattr_exit_code solaris_restore_xattrs(JCR *jcr, bool is_extensible)
        * If its not the hidden_dir create the entry.
        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
        */
        * If its not the hidden_dir create the entry.
        * The current implementation of xattr on Solaris doesn't support this, but if it ever does we are prepared.
        */
-      if (strcmp(target_attrname, ".")) {
+      if (!bstrcmp(target_attrname, ".")) {
          unlinkat(attrdirfd, target_attrname, AT_REMOVEDIR);
          if (mkdir(target_attrname, st.st_mode) < 0) {
             Jmsg3(jcr, M_WARNING, 0, _("Unable to mkdir xattr %s on file \"%s\": ERR=%s\n"),
          unlinkat(attrdirfd, target_attrname, AT_REMOVEDIR);
          if (mkdir(target_attrname, st.st_mode) < 0) {
             Jmsg3(jcr, M_WARNING, 0, _("Unable to mkdir xattr %s on file \"%s\": ERR=%s\n"),
@@ -2241,9 +2329,7 @@ static bxattr_exit_code solaris_parse_xattr_streams(JCR *jcr, int stream)
 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
    case STREAM_XATTR_SOLARIS_SYS:
       if (pathconf(jcr->last_fname, _PC_SATTR_ENABLED) <= 0) {
 #if defined(HAVE_SYS_NVPAIR_H) && defined(_PC_SATTR_ENABLED)
    case STREAM_XATTR_SOLARIS_SYS:
       if (pathconf(jcr->last_fname, _PC_SATTR_ENABLED) <= 0) {
-         Qmsg1(jcr, M_WARNING, 0,
-               _("Failed to restore extensible attributes on file \"%s\"\n"),
-               jcr->last_fname);
+         Mmsg1(jcr->errmsg, _("Failed to restore extensible attributes on file \"%s\"\n"), jcr->last_fname);
          Dmsg1(100, "Unable to restore extensible attributes on file \"%s\", filesystem doesn't support this\n",
             jcr->last_fname);
          return bxattr_exit_error;
          Dmsg1(100, "Unable to restore extensible attributes on file \"%s\", filesystem doesn't support this\n",
             jcr->last_fname);
          return bxattr_exit_error;
@@ -2254,9 +2340,7 @@ static bxattr_exit_code solaris_parse_xattr_streams(JCR *jcr, int stream)
 #endif
    case STREAM_XATTR_SOLARIS:
       if (pathconf(jcr->last_fname, _PC_XATTR_ENABLED) <= 0) {
 #endif
    case STREAM_XATTR_SOLARIS:
       if (pathconf(jcr->last_fname, _PC_XATTR_ENABLED) <= 0) {
-         Qmsg1(jcr, M_WARNING, 0,
-               _("Failed to restore extended attributes on file \"%s\"\n"),
-               jcr->last_fname);
+         Mmsg1(jcr->errmsg, _("Failed to restore extended attributes on file \"%s\"\n"), jcr->last_fname);
          Dmsg1(100, "Unable to restore extended attributes on file \"%s\", filesystem doesn't support this\n",
             jcr->last_fname);
          return bxattr_exit_error;
          Dmsg1(100, "Unable to restore extended attributes on file \"%s\", filesystem doesn't support this\n",
             jcr->last_fname);
          return bxattr_exit_error;