]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/filed/acl.c
Tweak retry count handling
[bacula/bacula] / bacula / src / filed / acl.c
index 11b8ea47d3f7af7219c9013d9dcb8cccf1c789a9..17b79d3ece0818f775bf90056127e26022da8fd5 100644 (file)
@@ -1,12 +1,12 @@
 /*
    Bacula® - The Network Backup Solution
 
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2004-2008 Free Software Foundation Europe e.V.
+   Copyright (C) 2004-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.
@@ -25,7 +25,7 @@
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
-/*
+/**
  * Functions to handle ACLs for bacula.
  *
  * We handle two different types of ACLs: access and default ACLS.
  * Functions to handle ACLs for bacula.
  *
  * We handle two different types of ACLs: access and default ACLS.
  * Its also interesting to see what the exact format of acl text is on
  * certain platforms and if they use they same encoding we might allow
  * different platform streams to be decoded on an other similar platform.
  * Its also interesting to see what the exact format of acl text is on
  * certain platforms and if they use they same encoding we might allow
  * different platform streams to be decoded on an other similar platform.
- * As we implement the decoding/restoring process as a big switch based
- * on the stream number being passed in extending the switching code is
- * easy.
  *
  *   Original written by Preben 'Peppe' Guldberg, December MMIV
  *   Major rewrite by Marco van Wieringen, November MMVIII
  *
  *   Original written by Preben 'Peppe' Guldberg, December MMIV
  *   Major rewrite by Marco van Wieringen, November MMVIII
- *
- *   Version $Id$
  */
   
 #include "bacula.h"
 #include "filed.h"
   
  */
   
 #include "bacula.h"
 #include "filed.h"
   
-/*
- * List of supported OSs.
- * Not sure if all the HAVE_XYZ_OS are correct for autoconf.
- * The ones that says man page, are coded according to man pages only.
- */
-#if !defined(HAVE_ACL)              /* ACL support is required, of course */ \
-   || !( defined(HAVE_AIX_OS)       /* man page -- may need flags         */ \
-      || defined(HAVE_DARWIN_OS)    /* tested   -- compile without flags  */ \
-      || defined(HAVE_FREEBSD_OS)   /* tested   -- compile without flags  */ \
-      || defined(HAVE_HPUX_OS)      /* man page -- may need flags         */ \
-      || defined(HAVE_IRIX_OS)      /* man page -- compile without flags  */ \
-      || defined(HAVE_LINUX_OS)     /* tested   -- compile with -lacl     */ \
-      || defined(HAVE_OSF1_OS)      /* man page -- may need -lpacl        */ \
-      || defined(HAVE_SUN_OS)       /* tested   -- compile with -lsec     */ \
-       )
-
-/*
+#if !defined(HAVE_ACL) && !defined(HAVE_AFS_ACL)
+/**
  * Entry points when compiled without support for ACLs or on an unsupported platform.
  */
  * Entry points when compiled without support for ACLs or on an unsupported platform.
  */
-bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+bacl_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
 {
-   Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
-   return false;
+   return bacl_exit_fatal;
 }
 
 }
 
-bool parse_acl_stream(JCR *jcr, int stream)
+bacl_exit_code parse_acl_streams(JCR *jcr, int stream)
 {
 {
-   Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
-   return false;
+   return bacl_exit_fatal;
 }
 }
-
 #else
 #else
-
-/*
+/**
  * Send an ACL stream to the SD.
  */
  * Send an ACL stream to the SD.
  */
-static bool send_acl_stream(JCR *jcr, int stream, int len)
+static bacl_exit_code send_acl_stream(JCR *jcr, int stream)
 {
    BSOCK *sd = jcr->store_bsock;
    POOLMEM *msgsave;
 #ifdef FD_NO_SEND_TEST
 {
    BSOCK *sd = jcr->store_bsock;
    POOLMEM *msgsave;
 #ifdef FD_NO_SEND_TEST
-   return true;
+   return bacl_exit_ok;
 #endif
 
 #endif
 
-   /*
+   /**
+    * Sanity check
+    */
+   if (jcr->acl_data->content_length <= 0) {
+      return bacl_exit_ok;
+   }
+
+   /**
     * Send header
     */
    if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
             sd->bstrerror());
     * Send header
     */
    if (!sd->fsend("%ld %d 0", jcr->JobFiles, stream)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
             sd->bstrerror());
-
-      return false;
+      return bacl_exit_fatal;
    }
 
    }
 
-   /*
+   /**
     * Send the buffer to the storage deamon
     */
     * Send the buffer to the storage deamon
     */
-   Dmsg1(400, "Backing up ACL <%s>\n", jcr->acl_data);
+   Dmsg1(400, "Backing up ACL <%s>\n", jcr->acl_data->content);
    msgsave = sd->msg;
    msgsave = sd->msg;
-   sd->msg = jcr->acl_data;
-   sd->msglen = len + 1;
+   sd->msg = jcr->acl_data->content;
+   sd->msglen = jcr->acl_data->content_length + 1;
    if (!sd->send()) {
       sd->msg = msgsave;
       sd->msglen = 0;
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
             sd->bstrerror());
    if (!sd->send()) {
       sd->msg = msgsave;
       sd->msglen = 0;
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
             sd->bstrerror());
-
-      return false;
+      return bacl_exit_fatal;
    }
 
    jcr->JobBytes += sd->msglen;
    }
 
    jcr->JobBytes += sd->msglen;
@@ -132,48 +113,302 @@ static bool send_acl_stream(JCR *jcr, int stream, int len)
    if (!sd->signal(BNET_EOD)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
             sd->bstrerror());
    if (!sd->signal(BNET_EOD)) {
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
             sd->bstrerror());
-
-      return false;
+      return bacl_exit_fatal;
    }
 
    Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
    }
 
    Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
-
-   return true;
+   return bacl_exit_ok;
 }
 
 }
 
+/**
+ * First the native ACLs.
+ */
+#if defined(HAVE_ACL)
 #if defined(HAVE_AIX_OS)
 
 #if defined(HAVE_AIX_OS)
 
+#if defined(HAVE_EXTENDED_ACL)
+
 #include <sys/access.h>
 #include <sys/access.h>
+#include <sys/acl.h>
 
 
-static bool aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+static bool acl_is_trivial(struct acl *acl)
 {
 {
-   char *acl_text;
-   int len;
+   return (acl_last(acl) != acl->acl_ext ? false : true);
+}
 
 
-   if ((acl_text = acl_get(jcr->last_fname)) != NULL) {
-      len = pm_strcpy(jcr->acl_data, acl_text);
-      actuallyfree(acl_text);
+static bool acl_nfs4_is_trivial(nfs4_acl_int_t *acl)
+{
+   return (acl->aclEntryN > 0 ? false : true);
+}
+
+/**
+ * Define the supported ACL streams for this OS
+ */
+static int os_access_acl_streams[3] = { STREAM_ACL_AIX_TEXT, STREAM_ACL_AIX_AIXC, STREAM_ACL_AIX_NFS4 };
+static int os_default_acl_streams[1] = { -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;
+   bacl_exit_code retval = bacl_exit_error;
+   POOLMEM *aclbuf = get_pool_memory(PM_MESSAGE);
+
+   /**
+    * First see how big the buffers should be.
+    */
+   type.u64 = ACL_ANY;
+   if (aclx_get(jcr->last_fname, GET_ACLINFO_ONLY, &type, NULL, &aclsize, NULL) < 0) {
+      switch (errno) {
+      case ENOENT:
+         retval = bacl_exit_ok;
+         goto bail_out;
+      default:
+         Mmsg2(jcr->errmsg, _("aclx_get error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "aclx_get error file=%s ERR=%s\n",
+               jcr->last_fname, be.bstrerror());
+         goto bail_out;
+      }
+   }
+
+   /**
+    * Make sure the buffers are big enough.
+    */
+   aclbuf = check_pool_memory_size(aclbuf, aclsize + 1);
+
+   /**
+    * Retrieve the ACL info.
+    */
+   if (aclx_get(jcr->last_fname, 0, &type, aclbuf, &aclsize, &mode) < 0) {
+      switch (errno) {
+      case ENOENT:
+         retval = bacl_exit_ok;
+         goto bail_out;
+      default:
+         Mmsg2(jcr->errmsg, _("aclx_get error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "aclx_get error file=%s ERR=%s\n",
+               jcr->last_fname, be.bstrerror());
+         goto bail_out;
+      }
+   }
+
+   /**
+    * See if the acl is non trivial.
+    */
+   switch (type.u64) {
+   case ACL_AIXC:
+      if (acl_is_trivial((struct acl *)aclbuf)) {
+         retval = bacl_exit_ok;
+         goto bail_out;
+      }
+      break;
+   case ACL_NFS4:
+      if (acl_nfs4_is_trivial((nfs4_acl_int_t *)aclbuf)) {
+         retval = bacl_exit_ok;
+         goto bail_out;
+      }
+      break;
+   default:
+      Mmsg2(jcr->errmsg, _("Unknown acl type encountered on file \"%s\": %ld\n"),
+            jcr->last_fname, type.u64);
+      Dmsg2(100, "Unknown acl type encountered on file \"%s\": %ld\n",
+            jcr->last_fname, type.u64);
+      goto bail_out;
+   }
 
 
-      return send_acl_stream(jcr, STREAM_ACL_AIX_TEXT, len);
+   /**
+    * We have a non-trivial acl lets convert it into some ASCII form.
+    */
+   acltxtsize = sizeof_pool_memory(jcr->acl_data->content);
+   if (aclx_printStr(jcr->acl_data->content, &acltxtsize, aclbuf,
+                     aclsize, type, jcr->last_fname, 0) < 0) {
+      switch (errno) {
+      case ENOSPC:
+         /**
+          * Our buffer is not big enough, acltxtsize should be updated with the value
+          * the aclx_printStr really need. So we increase the buffer and try again.
+          */
+         jcr->acl_data->content = check_pool_memory_size(jcr->acl_data->content, acltxtsize + 1);
+         if (aclx_printStr(jcr->acl_data->content, &acltxtsize, aclbuf,
+                           aclsize, type, jcr->last_fname, 0) < 0) {
+            Mmsg1(jcr->errmsg, _("Failed to convert acl into text on file \"%s\"\n"),
+                  jcr->last_fname);
+            Dmsg2(100, "Failed to convert acl into text on file \"%s\": %ld\n",
+                  jcr->last_fname, type.u64);
+            goto bail_out;
+         }
+         break;
+      default:
+         Mmsg1(jcr->errmsg, _("Failed to convert acl into text on file \"%s\"\n"),
+               jcr->last_fname);
+         Dmsg2(100, "Failed to convert acl into text on file \"%s\": %ld\n",
+               jcr->last_fname, type.u64);
+         goto bail_out;
+      }
+   }
+
+   jcr->acl_data->content_length = strlen(jcr->acl_data->content) + 1;
+   switch (type.u64) {
+   case ACL_AIXC:
+      retval = send_acl_stream(jcr, STREAM_ACL_AIX_AIXC);
+   case ACL_NFS4:
+      retval = send_acl_stream(jcr, STREAM_ACL_AIX_NFS4);
    }
 
    }
 
-   return false;
+bail_out:
+   free_pool_memory(aclbuf);
+
+   return retval;
 }
 
 }
 
-static bool aix_parse_acl_stream(JCR *jcr, int stream)
+static bacl_exit_code aix_parse_acl_streams(JCR *jcr, int stream)
 {
 {
-   if (acl_put(jcr->last_fname, jcr->acl_data, 0) != 0) {
-      return false;
+   int cnt;
+   berrno be;
+   acl_type_t type;
+   size_t aclsize;
+   bacl_exit_code retval = bacl_exit_error;
+   POOLMEM *aclbuf = get_pool_memory(PM_MESSAGE);
+
+   switch (stream) {
+   case STREAM_ACL_AIX_TEXT:
+      /**
+       * Handle the old stream using the old system call for now.
+       */
+      if (acl_put(jcr->last_fname, jcr->acl_data->content, 0) != 0) {
+         retval = bacl_exit_error;
+         goto bail_out;
+      }
+      retval = bacl_exit_ok;
+      goto bail_out;
+   case STREAM_ACL_AIX_AIXC:
+      type.u64 = ACL_AIXC;
+      break;
+   case STREAM_ACL_AIX_NFS4:
+      type.u64 = ACL_NFS4;
+      break;
+   default:
+      goto bail_out;
+   } /* end switch (stream) */
+
+   /**
+    * Set the acl buffer to an initial size. For now we set it
+    * to the same size as the ASCII representation.
+    */
+   aclbuf = check_pool_memory_size(aclbuf, jcr->acl_data->content_length);
+   aclsize = jcr->acl_data->content_length;
+   if (aclx_scanStr(jcr->acl_data->content, aclbuf, &aclsize, type) < 0) {
+      switch (errno) {
+      case ENOSPC:
+         /**
+          * The buffer isn't big enough. The man page doesn't say that aclsize
+          * is updated to the needed size as what is done with aclx_printStr.
+          * So for now we try to increase the buffer a maximum of 3 times
+          * and retry the conversion.
+          */
+         for (cnt = 0; cnt < 3; cnt++) {
+            aclsize = 2 * aclsize;
+            aclbuf = check_pool_memory_size(aclbuf, aclsize);
+
+            if (aclx_scanStr(jcr->acl_data->content, aclbuf, &aclsize, type) == 0) {
+               break;
+            }
+
+            /**
+             * See why we failed this time, ENOSPC retry if max retries not met,
+             * otherwise abort.
+             */
+            switch (errno) {
+            case ENOSPC:
+               if (cnt < 3) {
+                  continue;
+               }
+               /* FALL THROUGH */
+            default:
+               Mmsg2(jcr->errmsg, _("aclx_scanStr error on file \"%s\": ERR=%s\n"),
+                     jcr->last_fname, be.bstrerror());
+               Dmsg2(100, "aclx_scanStr error file=%s ERR=%s\n",
+                     jcr->last_fname, be.bstrerror());
+               goto bail_out;
+            }
+         }
+         break;
+      default:
+         Mmsg2(jcr->errmsg, _("aclx_scanStr error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "aclx_scanStr error file=%s ERR=%s\n",
+               jcr->last_fname, be.bstrerror());
+      }
    }
 
    }
 
-   return true;
+   if (aclx_put(jcr->last_fname, SET_ACL, type, aclbuf, aclsize, 0) < 0) {
+      switch (errno) {
+      case ENOENT:
+         retval = bacl_exit_ok;
+         goto bail_out;
+      default:
+         Mmsg2(jcr->errmsg, _("aclx_put error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "aclx_put error file=%s ERR=%s\n",
+               jcr->last_fname, be.bstrerror());
+         goto bail_out;
+      }
+   }
+
+   retval = bacl_exit_ok;
+
+bail_out:
+   free_pool_memory(aclbuf);
+
+   return retval;
 }
 
 }
 
-#elif defined(HAVE_DARWIN_OS) \
-   || defined(HAVE_FREEBSD_OS) \
-   || defined(HAVE_IRIX_OS) \
-   || defined(HAVE_OSF1_OS) \
-   || defined(HAVE_LINUX_OS)
+#else /* HAVE_EXTENDED_ACL */
+
+#include <sys/access.h>
+
+/**
+ * Define the supported ACL streams for this OS
+ */
+static int os_access_acl_streams[1] = { STREAM_ACL_AIX_TEXT };
+static int os_default_acl_streams[1] = { -1 };
+
+static bacl_exit_code aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+{
+   char *acl_text;
+
+   if ((acl_text = acl_get(jcr->last_fname)) != NULL) {
+      jcr->acl_data->content_length = pm_strcpy(jcr->acl_data->content, acl_text);
+      actuallyfree(acl_text);
+      return send_acl_stream(jcr, STREAM_ACL_AIX_TEXT);
+   }
+   return bacl_exit_error;
+}
+
+static bacl_exit_code aix_parse_acl_streams(JCR *jcr, int stream)
+{
+   if (acl_put(jcr->last_fname, jcr->acl_data->content, 0) != 0) {
+      return bacl_exit_error;
+   }
+   return bacl_exit_ok;
+}
+#endif /* HAVE_EXTENDED_ACL */
+
+/**
+ * For this OS setup the build and parse function pointer to the OS specific functions.
+ */
+static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = aix_build_acl_streams;
+static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = aix_parse_acl_streams;
+
+#elif defined(HAVE_DARWIN_OS) || \
+      defined(HAVE_FREEBSD_OS) || \
+      defined(HAVE_IRIX_OS) || \
+      defined(HAVE_TRU64_OS) || \
+      defined(HAVE_LINUX_OS)
 
 #include <sys/types.h>
 
 
 #include <sys/types.h>
 
@@ -183,12 +418,16 @@ static bool aix_parse_acl_stream(JCR *jcr, int stream)
 #error "configure failed to detect availability of sys/acl.h"
 #endif
 
 #error "configure failed to detect availability of sys/acl.h"
 #endif
 
-/* On IRIX we can get shortened ACLs */
+/**
+ * On IRIX we can get shortened ACLs
+ */
 #if defined(HAVE_IRIX_OS) && defined(BACL_WANT_SHORT_ACLS)
 #define acl_to_text(acl,len)     acl_to_short_text((acl), (len))
 #endif
 
 #if defined(HAVE_IRIX_OS) && defined(BACL_WANT_SHORT_ACLS)
 #define acl_to_text(acl,len)     acl_to_short_text((acl), (len))
 #endif
 
-/* In Linux we can get numeric and/or shorted ACLs */
+/**
+ * In Linux we can get numeric and/or shorted ACLs
+ */
 #if defined(HAVE_LINUX_OS)
 #if defined(BACL_WANT_SHORT_ACLS) && defined(BACL_WANT_NUMERIC_IDS)
 #define BACL_ALTERNATE_TEXT            (TEXT_ABBREVIATE|TEXT_NUMERIC_IDS)
 #if defined(HAVE_LINUX_OS)
 #if defined(BACL_WANT_SHORT_ACLS) && defined(BACL_WANT_NUMERIC_IDS)
 #define BACL_ALTERNATE_TEXT            (TEXT_ABBREVIATE|TEXT_NUMERIC_IDS)
@@ -203,7 +442,7 @@ static bool aix_parse_acl_stream(JCR *jcr, int stream)
 #endif
 #endif
 
 #endif
 #endif
 
-/*
+/**
  * Some generic functions used by multiple OSes.
  */
 static acl_type_t bac_to_os_acltype(bacl_type acltype)
  * Some generic functions used by multiple OSes.
  */
 static acl_type_t bac_to_os_acltype(bacl_type acltype)
@@ -220,40 +459,39 @@ static acl_type_t bac_to_os_acltype(bacl_type acltype)
 
 #ifdef ACL_TYPE_DEFAULT_DIR
    case BACL_TYPE_DEFAULT_DIR:
 
 #ifdef ACL_TYPE_DEFAULT_DIR
    case BACL_TYPE_DEFAULT_DIR:
-      /*
-       * OSF1 has an additional acl type named ACL_TYPE_DEFAULT_DIR.
+      /**
+       * TRU64 has an additional acl type named ACL_TYPE_DEFAULT_DIR.
        */
       ostype = ACL_TYPE_DEFAULT_DIR;
       break;
 #endif
 #ifdef ACL_TYPE_EXTENDED
    case BACL_TYPE_EXTENDED:
        */
       ostype = ACL_TYPE_DEFAULT_DIR;
       break;
 #endif
 #ifdef ACL_TYPE_EXTENDED
    case BACL_TYPE_EXTENDED:
-      /*
+      /**
        * MacOSX has an additional acl type named ACL_TYPE_EXTENDED.
        */
       ostype = ACL_TYPE_EXTENDED;
       break;
 #endif
    default:
        * MacOSX has an additional acl type named ACL_TYPE_EXTENDED.
        */
       ostype = ACL_TYPE_EXTENDED;
       break;
 #endif
    default:
-      /*
-       * This should never happen, as the per os version function only tries acl
+      /**
+       * This should never happen, as the per OS version function only tries acl
        * types supported on a certain platform.
        */
       ostype = (acl_type_t)ACL_TYPE_NONE;
       break;
    }
        * types supported on a certain platform.
        */
       ostype = (acl_type_t)ACL_TYPE_NONE;
       break;
    }
-
    return ostype;
 }
 
 #if !defined(HAVE_DARWIN_OS)
    return ostype;
 }
 
 #if !defined(HAVE_DARWIN_OS)
-/*
+/**
  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
  * There is no need to store those acls as we already store the stat bits too.
  */
 static bool acl_is_trivial(acl_t acl)
 {
  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
  * There is no need to store those acls as we already store the stat bits too.
  */
 static bool acl_is_trivial(acl_t acl)
 {
-  /*
+  /**
    * acl is trivial if it has only the following entries:
    * "user::",
    * "group::",
    * acl is trivial if it has only the following entries:
    * "user::",
    * "group::",
@@ -261,29 +499,27 @@ static bool acl_is_trivial(acl_t acl)
    */
    acl_entry_t ace;
    acl_tag_t tag;
    */
    acl_entry_t ace;
    acl_tag_t tag;
-#if defined(HAVE_FREEBSD_OS) || defined(HAVE_LINUX_OS)
+#if defined(HAVE_FREEBSD_OS) || \
+    defined(HAVE_LINUX_OS)
    int entry_available;
 
    entry_available = acl_get_entry(acl, ACL_FIRST_ENTRY, &ace);
    while (entry_available == 1) {
    int entry_available;
 
    entry_available = acl_get_entry(acl, ACL_FIRST_ENTRY, &ace);
    while (entry_available == 1) {
-      /*
+      /**
        * Get the tag type of this acl entry.
        * If we fail to get the tagtype we call the acl non-trivial.
        */
       if (acl_get_tag_type(ace, &tag) < 0)
        * Get the tag type of this acl entry.
        * If we fail to get the tagtype we call the acl non-trivial.
        */
       if (acl_get_tag_type(ace, &tag) < 0)
-         return false;
-
-      /*
+         return true;
+      /**
        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
        */
       if (tag != ACL_USER_OBJ &&
           tag != ACL_GROUP_OBJ &&
           tag != ACL_OTHER)
          return false;
        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
        */
       if (tag != ACL_USER_OBJ &&
           tag != ACL_GROUP_OBJ &&
           tag != ACL_OTHER)
          return false;
-
       entry_available = acl_get_entry(acl, ACL_NEXT_ENTRY, &ace);
    }
       entry_available = acl_get_entry(acl, ACL_NEXT_ENTRY, &ace);
    }
-
    return true;
 #elif defined(HAVE_IRIX_OS)
    int n;
    return true;
 #elif defined(HAVE_IRIX_OS)
    int n;
@@ -292,17 +528,16 @@ static bool acl_is_trivial(acl_t acl)
       ace = &acl->acl_entry[n];
       tag = ace->ae_tag;
 
       ace = &acl->acl_entry[n];
       tag = ace->ae_tag;
 
-      /*
+      /**
        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
        */
       if (tag != ACL_USER_OBJ &&
           tag != ACL_GROUP_OBJ &&
        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
        */
       if (tag != ACL_USER_OBJ &&
           tag != ACL_GROUP_OBJ &&
-          tag != ACL_OTHER)
+          tag != ACL_OTHER_OBJ)
          return false;
    }
          return false;
    }
-
    return true;
    return true;
-#elif defined(HAVE_OSF1_OS)
+#elif defined(HAVE_TRU64_OS)
    int count;
 
    ace = acl->acl_first;
    int count;
 
    ace = acl->acl_first;
@@ -310,46 +545,42 @@ static bool acl_is_trivial(acl_t acl)
 
    while (count > 0) {
       tag = ace->entry->acl_type;
 
    while (count > 0) {
       tag = ace->entry->acl_type;
-
-      /*
+      /**
        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
        */
       if (tag != ACL_USER_OBJ &&
           tag != ACL_GROUP_OBJ &&
           tag != ACL_OTHER)
          return false;
        * Anything other the ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER breaks the spell.
        */
       if (tag != ACL_USER_OBJ &&
           tag != ACL_GROUP_OBJ &&
           tag != ACL_OTHER)
          return false;
-
-      /*
+      /**
        * On Tru64, perm can also contain non-standard bits such as
        * PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ...
        */
       if ((ace->entry->acl_perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)))
          return false;
        * On Tru64, perm can also contain non-standard bits such as
        * PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ...
        */
       if ((ace->entry->acl_perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)))
          return false;
-
       ace = ace->next;
       count--;
    }
       ace = ace->next;
       count--;
    }
-
    return true;
 #endif
 }
 #endif
 
    return true;
 #endif
 }
 #endif
 
-/*
+/**
  * Generic wrapper around acl_get_file call.
  */
  * Generic wrapper around acl_get_file call.
  */
-static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
+static bacl_exit_code generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
 {
    acl_t acl;
 {
    acl_t acl;
-   int len;
    acl_type_t ostype;
    char *acl_text;
    acl_type_t ostype;
    char *acl_text;
+   berrno be;
 
    ostype = bac_to_os_acltype(acltype);
    acl = acl_get_file(jcr->last_fname, ostype);
    if (acl) {
 #if defined(HAVE_IRIX_OS)
 
    ostype = bac_to_os_acltype(acltype);
    acl = acl_get_file(jcr->last_fname, ostype);
    if (acl) {
 #if defined(HAVE_IRIX_OS)
-      /* 
+      /**
        * From observation, IRIX's acl_get_file() seems to return a
        * non-NULL acl with a count field of -1 when a file has no ACL
        * defined, while IRIX's acl_to_text() returns NULL when presented
        * From observation, IRIX's acl_get_file() seems to return a
        * non-NULL acl with a count field of -1 when a file has no ACL
        * defined, while IRIX's acl_to_text() returns NULL when presented
@@ -362,153 +593,177 @@ static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
        * to acl_to_text() besides.
        */
       if (acl->acl_cnt <= 0) {
        * to acl_to_text() besides.
        */
       if (acl->acl_cnt <= 0) {
-         pm_strcpy(jcr->acl_data, "");
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
          acl_free(acl);
          acl_free(acl);
-         return 0;
+         return bacl_exit_ok;
       }
 #endif
 
 #if !defined(HAVE_DARWIN_OS)
       }
 #endif
 
 #if !defined(HAVE_DARWIN_OS)
-      /*
+      /**
        * Make sure this is not just a trivial ACL.
        */
       if (acltype == BACL_TYPE_ACCESS && acl_is_trivial(acl)) {
        * Make sure this is not just a trivial ACL.
        */
       if (acltype == BACL_TYPE_ACCESS && acl_is_trivial(acl)) {
-         /*
+         /**
           * The ACLs simply reflect the (already known) standard permissions
           * So we don't send an ACL stream to the SD.
           */
           * The ACLs simply reflect the (already known) standard permissions
           * So we don't send an ACL stream to the SD.
           */
-         pm_strcpy(jcr->acl_data, "");
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
          acl_free(acl);
          acl_free(acl);
-         return 0;
+         return bacl_exit_ok;
       }
 #endif
 
       if ((acl_text = acl_to_text(acl, NULL)) != NULL) {
       }
 #endif
 
       if ((acl_text = acl_to_text(acl, NULL)) != NULL) {
-         len = pm_strcpy(jcr->acl_data, acl_text);
+         jcr->acl_data->content_length = pm_strcpy(jcr->acl_data->content, acl_text);
          acl_free(acl);
          acl_free(acl_text);
          acl_free(acl);
          acl_free(acl_text);
-
-         return len;
+         return bacl_exit_ok;
       }
 
       }
 
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("acl_to_text error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+      Mmsg2(jcr->errmsg, _("acl_to_text error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg2(100, "acl_to_text error file=%s ERR=%s\n",  
       Dmsg2(100, "acl_to_text error file=%s ERR=%s\n",  
-         jcr->last_fname, be.bstrerror());
+            jcr->last_fname, be.bstrerror());
 
 
-      pm_strcpy(jcr->acl_data, "");
+      pm_strcpy(jcr->acl_data->content, "");
+      jcr->acl_data->content_length = 0;
       acl_free(acl);
       acl_free(acl);
-
-      return -1;
+      return bacl_exit_error;
    }
 
    }
 
-   /*
+   /**
     * Handle errors gracefully.
     */
     * Handle errors gracefully.
     */
-   switch (errno) {
+   if (acl == (acl_t)NULL) {
+      switch (errno) {
 #if defined(BACL_ENOTSUP)
 #if defined(BACL_ENOTSUP)
-   case BACL_ENOTSUP:
-      /*
-       * Not supported, just pretend there is nothing to see
-       */
-      pm_strcpy(jcr->acl_data, "");
-      return 0;
+      case BACL_ENOTSUP:
+         /**
+          * 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;
+         break;                       /* not supported */
 #endif
 #endif
-   default:
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("acl_get_file error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
-      Dmsg2(100, "acl_get_file error file=%s ERR=%s\n",  
-         jcr->last_fname, be.bstrerror());
-
-      pm_strcpy(jcr->acl_data, "");
-      return -1;
+      case ENOENT:
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
+         return bacl_exit_ok;
+      default:
+         /* Some real error */
+         Mmsg2(jcr->errmsg, _("acl_get_file error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "acl_get_file error file=%s ERR=%s\n",  
+               jcr->last_fname, be.bstrerror());
+
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
+         return bacl_exit_error;
+      }
    }
    }
+
+   /**
+    * Not supported, just pretend there is nothing to see
+    */
+   pm_strcpy(jcr->acl_data->content, "");
+   jcr->acl_data->content_length = 0;
+   return bacl_exit_ok;
 }
 
 }
 
-/*
+/**
  * Generic wrapper around acl_set_file call.
  */
  * Generic wrapper around acl_set_file call.
  */
-static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype)
+static bacl_exit_code generic_set_acl_on_os(JCR *jcr, bacl_type acltype)
 {
    acl_t acl;
    acl_type_t ostype;
 {
    acl_t acl;
    acl_type_t ostype;
+   berrno be;
 
 
-   /*
+   /**
     * If we get empty default ACLs, clear ACLs now
     */
    ostype = bac_to_os_acltype(acltype);
     * If we get empty default ACLs, clear ACLs now
     */
    ostype = bac_to_os_acltype(acltype);
-   if (ostype == ACL_TYPE_DEFAULT && strlen(jcr->acl_data) == 0) {
+   if (ostype == ACL_TYPE_DEFAULT && strlen(jcr->acl_data->content) == 0) {
       if (acl_delete_def_file(jcr->last_fname) == 0) {
       if (acl_delete_def_file(jcr->last_fname) == 0) {
-         return true;
+         return bacl_exit_ok;
+      }
+      switch (errno) {
+      case ENOENT:
+         return bacl_exit_ok;
+      default:
+         Mmsg2(jcr->errmsg, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         return bacl_exit_error;
       }
       }
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
-
-      return false;
    }
 
    }
 
-   acl = acl_from_text(jcr->acl_data);
+   acl = acl_from_text(jcr->acl_data->content);
    if (acl == NULL) {
    if (acl == NULL) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("acl_from_text error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+      Mmsg2(jcr->errmsg, _("acl_from_text error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n",  
       Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
-
-      return false;
+         jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+      return bacl_exit_error;
    }
 
    }
 
-   /*
+#ifndef HAVE_FREEBSD_OS
+   /**
     * FreeBSD always fails acl_valid() - at least on valid input...
     * As it does the right thing, given valid input, just ignore acl_valid().
     */
     * FreeBSD always fails acl_valid() - at least on valid input...
     * As it does the right thing, given valid input, just ignore acl_valid().
     */
-#ifndef HAVE_FREEBSD_OS
    if (acl_valid(acl) != 0) {
    if (acl_valid(acl) != 0) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("ac_valid error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+      Mmsg2(jcr->errmsg, _("acl_valid error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg3(100, "acl_valid error acl=%s file=%s ERR=%s\n",  
       Dmsg3(100, "acl_valid error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
+         jcr->acl_data->content, jcr->last_fname, be.bstrerror());
       acl_free(acl);
       acl_free(acl);
-
-      return false;
+      return bacl_exit_error;
    }
 #endif
 
    }
 #endif
 
-   /*
+   /**
     * Restore the ACLs, but don't complain about links which really should
     * not have attributes, and the file it is linked to may not yet be restored.
     * 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 (acl_set_file(jcr->last_fname, ostype, acl) != 0 && jcr->last_type != FT_LNK) {
     * Restore the ACLs, but don't complain about links which really should
     * not have attributes, and the file it is linked to may not yet be restored.
     * 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 (acl_set_file(jcr->last_fname, ostype, acl) != 0 && jcr->last_type != FT_LNK) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("acl_set_file error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
-      Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
-      acl_free(acl);
-
-      return false;
+      switch (errno) {
+      case ENOENT:
+         acl_free(acl);
+         return bacl_exit_ok;
+      default:
+         Mmsg2(jcr->errmsg, _("acl_set_file error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n",
+               jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+         acl_free(acl);
+         return bacl_exit_error;
+      }
    }
    acl_free(acl);
    }
    acl_free(acl);
-
-   return true;
+   return bacl_exit_ok;
 }
 
 }
 
-/*
+/**
  * OS specific functions for handling different types of acl streams.
  */
 #if defined(HAVE_DARWIN_OS)
  * OS specific functions for handling different types of acl streams.
  */
 #if defined(HAVE_DARWIN_OS)
-static bool darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
-{
-   int len;
+/**
+ * Define the supported ACL streams for this OS
+ */
+static int os_access_acl_streams[1] = { STREAM_ACL_DARWIN_ACCESS_ACL };
+static int os_default_acl_streams[1] = { -1 };
 
 
+static bacl_exit_code darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+{
 #if defined(ACL_TYPE_EXTENDED)
 #if defined(ACL_TYPE_EXTENDED)
-   /*
+   /**
     * On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
     * and acl_get_file (name, ACL_TYPE_DEFAULT)
     * always return NULL / EINVAL.  There is no point in making
     * On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
     * and acl_get_file (name, ACL_TYPE_DEFAULT)
     * always return NULL / EINVAL.  There is no point in making
@@ -517,216 +772,162 @@ static bool darwin_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
     *
     * Read access ACLs for files, dirs and links
     */
     *
     * Read access ACLs for files, dirs and links
     */
-   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED)) < 0)
-      return false;
+   if (generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED) == bacl_exit_fatal)
+      return bacl_exit_fatal;
 #else
 #else
-   /*
+   /**
     * Read access ACLs for files, dirs and links
     */
     * Read access ACLs for files, dirs and links
     */
-   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
-      return false;
-
-   if (len > 0) {
-      if (!send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL, len))
-         return false;
-   }
+   if (generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS) == bacl_exit_fatal)
+      return bacl_exit_fatal;
 #endif
 
 #endif
 
-   return true;
+   if (jcr->acl_data->content_length > 0) {
+      return send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL);
+   }
+   return bacl_exit_ok;
 }
 
 }
 
-static bool darwin_parse_acl_stream(JCR *jcr, int stream)
+static bacl_exit_code darwin_parse_acl_streams(JCR *jcr, int stream)
 {
 {
-   switch (stream) {
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_ACL_DARWIN_ACCESS_ACL:
+#if defined(ACL_TYPE_EXTENDED)
+      return generic_set_acl_on_os(jcr, BACL_TYPE_EXTENDED);
+#else
       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
-   }
-
-   return false;
+#endif
 }
 }
-#elif defined(HAVE_FREEBSD_OS)
-static bool freebsd_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
-{
-   int len;
-
-   /*
-    * Read access ACLs for files, dirs and links
-    */
-   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
-      return false;
 
 
-   if (len > 0) {
-      if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_ACCESS_ACL, len))
-         return false;
-   }
-
-   /*
-    * Directories can have default ACLs too
-    */
-   if (ff_pkt->type == FT_DIREND) {
-      if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
-         return false;
-
-      if (len > 0) {
-         if (!send_acl_stream(jcr, STREAM_ACL_FREEBSD_DEFAULT_ACL, len))
-            return false;
-      }
-   }
+/**
+ * For this OS setup the build and parse function pointer to the OS specific functions.
+ */
+static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = darwin_build_acl_streams;
+static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = darwin_parse_acl_streams;
 
 
-   return true;
-}
+#elif defined(HAVE_FREEBSD_OS) || \
+      defined(HAVE_IRIX_OS) || \
+      defined(HAVE_LINUX_OS)
 
 
-static bool freebsd_parse_acl_stream(JCR *jcr, int stream)
-{
-   switch (stream) {
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_ACL_FREEBSD_ACCESS_ACL:
-      return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
-   case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_FREEBSD_DEFAULT_ACL:
-      return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
-   }
-
-   return false;
-}
+/**
+ * Define the supported ACL streams for these OSes
+ */
+#if defined(HAVE_FREEBSD_OS)
+static int os_access_acl_streams[1] = { STREAM_ACL_FREEBSD_ACCESS_ACL };
+static int os_default_acl_streams[1] = { STREAM_ACL_FREEBSD_DEFAULT_ACL };
 #elif defined(HAVE_IRIX_OS)
 #elif defined(HAVE_IRIX_OS)
-static bool irix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
-{
-   int len;
+static int os_access_acl_streams[1] = { STREAM_ACL_IRIX_ACCESS_ACL };
+static int os_default_acl_streams[1] = { STREAM_ACL_IRIX_DEFAULT_ACL };
+#elif defined(HAVE_LINUX_OS)
+static int os_access_acl_streams[1] = { STREAM_ACL_LINUX_ACCESS_ACL };
+static int os_default_acl_streams[1] = { STREAM_ACL_LINUX_DEFAULT_ACL };
+#endif
 
 
-   /*
+static bacl_exit_code generic_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+{
+   /**
     * Read access ACLs for files, dirs and links
     */
     * Read access ACLs for files, dirs and links
     */
-   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
-      return false;
+   if (generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS) == bacl_exit_fatal)
+      return bacl_exit_fatal;
 
 
-   if (len > 0) {
-      if (!send_acl_stream(jcr, STREAM_ACL_IRIX_ACCESS_ACL, len))
-         return false;
+   if (jcr->acl_data->content_length > 0) {
+      if (send_acl_stream(jcr, os_access_acl_streams[0]) == bacl_exit_fatal)
+         return bacl_exit_fatal;
    }
 
    }
 
-   /*
+   /**
     * Directories can have default ACLs too
     */
    if (ff_pkt->type == FT_DIREND) {
     * Directories can have default ACLs too
     */
    if (ff_pkt->type == FT_DIREND) {
-      if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
-         return false;
-
-      if (len > 0) {
-         if (!send_acl_stream(jcr, STREAM_ACL_IRIX_DEFAULT_ACL, len))
-            return false;
+      if (generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT) == bacl_exit_fatal)
+         return bacl_exit_fatal;
+      if (jcr->acl_data->content_length > 0) {
+         if (send_acl_stream(jcr, os_default_acl_streams[0]) == bacl_exit_fatal)
+            return bacl_exit_fatal;
       }
    }
       }
    }
-
-   return true;
+   return bacl_exit_ok;
 }
 
 }
 
-static bool irix_parse_acl_stream(JCR *jcr, int stream)
+static bacl_exit_code generic_parse_acl_streams(JCR *jcr, int stream)
 {
 {
+   unsigned int cnt;
+
    switch (stream) {
    case STREAM_UNIX_ACCESS_ACL:
    switch (stream) {
    case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_ACL_IRIX_ACCESS_ACL:
       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
    case STREAM_UNIX_DEFAULT_ACL:
       return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
    case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_IRIX_DEFAULT_ACL:
       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
+   default:
+      /**
+       * See what type of acl it is.
+       */
+      for (cnt = 0; cnt < sizeof(os_access_acl_streams) / sizeof(int); cnt++) {
+         if (os_access_acl_streams[cnt] == stream) {
+            return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
+         }
+      }
+      for (cnt = 0; cnt < sizeof(os_default_acl_streams) / sizeof(int); cnt++) {
+         if (os_default_acl_streams[cnt] == stream) {
+            return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
+         }
+      }
+      break;
    }
    }
-
-   return false;
+   return bacl_exit_error;
 }
 }
-#elif defined(HAVE_LINUX_OS)
-static bool linux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
-{
-   int len;
-
-   /*
-    * Read access ACLs for files, dirs and links
-    */
-   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
-      return false;
-
-   if (len > 0) {
-      if (!send_acl_stream(jcr, STREAM_ACL_LINUX_ACCESS_ACL, len))
-         return false;
-   }
-
-   /*
-    * Directories can have default ACLs too
-    */
-   if (ff_pkt->type == FT_DIREND) {
-      if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
-         return false;
 
 
-      if (len > 0) {
-         if (!send_acl_stream(jcr, STREAM_ACL_LINUX_DEFAULT_ACL, len))
-            return false;
-      }
-   }
+/**
+ * For this OSes setup the build and parse function pointer to the OS specific functions.
+ */
+static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = generic_build_acl_streams;
+static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = generic_parse_acl_streams;
 
 
-   return true;
-}
+#elif defined(HAVE_TRU64_OS)
 
 
-static bool linux_parse_acl_stream(JCR *jcr, int stream)
-{
-   switch (stream) {
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_ACL_LINUX_ACCESS_ACL:
-      return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
-   case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_LINUX_DEFAULT_ACL:
-      return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
-   }
+/**
+ * Define the supported ACL streams for this OS
+ */
+static int os_access_acl_streams[1] = { STREAM_ACL_TRU64_ACCESS_ACL };
+static int os_default_acl_streams[2] = { STREAM_ACL_TRU64_DEFAULT_ACL, STREAM_ACL_TRU64_DEFAULT_DIR_ACL };
 
 
-   return false;
-}
-#elif defined(HAVE_OSF1_OS)
-static bool tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+static bacl_exit_code tru64_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
 {
-   int len;
-
-   /*
+   /**
     * Read access ACLs for files, dirs and links
     */
     * Read access ACLs for files, dirs and links
     */
-   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
-      return false;
-
-   if (len > 0) {
-      if (!send_acl_stream(jcr, STREAM_ACL_TRU64_ACCESS_ACL, len))
-         return false;
+   if ((jcr->acl_data->content_length = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
+      return bacl_exit_error;
+   if (jcr->acl_data->content_length > 0) {
+      if (!send_acl_stream(jcr, STREAM_ACL_TRU64_ACCESS_ACL))
+         return bacl_exit_error;
    }
    }
-
-   /*
+   /**
     * Directories can have default ACLs too
     */
    if (ff_pkt->type == FT_DIREND) {
     * Directories can have default ACLs too
     */
    if (ff_pkt->type == FT_DIREND) {
-      if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
-         return false;
-
-      if (len > 0) {
-         if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_ACL, len))
-            return false;
+      if ((jcr->acl_data->content_length = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT)) < 0)
+         return bacl_exit_error;
+      if (jcr->acl_data->content_length > 0) {
+         if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_ACL))
+            return bacl_exit_error;
       }
       }
-
-      /*
+      /**
        * Tru64 has next to BACL_TYPE_DEFAULT also BACL_TYPE_DEFAULT_DIR acls.
        * This is an inherited acl for all subdirs.
        * See http://www.helsinki.fi/atk/unix/dec_manuals/DOC_40D/AQ0R2DTE/DOCU_018.HTM
        * Section 21.5 Default ACLs 
        */
        * Tru64 has next to BACL_TYPE_DEFAULT also BACL_TYPE_DEFAULT_DIR acls.
        * This is an inherited acl for all subdirs.
        * See http://www.helsinki.fi/atk/unix/dec_manuals/DOC_40D/AQ0R2DTE/DOCU_018.HTM
        * Section 21.5 Default ACLs 
        */
-      if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT_DIR)) < 0)
-         return false;
-
-      if (len > 0) {
-         if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_DIR_ACL, len))
-            return false;
+      if ((jcr->acl_data->content_length = generic_get_acl_from_os(jcr, BACL_TYPE_DEFAULT_DIR)) < 0)
+         return bacl_exit_error;
+      if (jcr->acl_data->content_length > 0) {
+         if (!send_acl_stream(jcr, STREAM_ACL_TRU64_DEFAULT_DIR_ACL))
+            return bacl_exit_error;
       }
    }
       }
    }
-
-   return true;
+   return bacl_exit_ok;
 }
 
 }
 
-static bool tru64_parse_acl_stream(JCR *jcr, int stream)
+static bacl_exit_code tru64_parse_acl_streams(JCR *jcr, int stream)
 {
    switch (stream) {
    case STREAM_UNIX_ACCESS_ACL:
 {
    switch (stream) {
    case STREAM_UNIX_ACCESS_ACL:
@@ -738,6 +939,13 @@ static bool tru64_parse_acl_stream(JCR *jcr, int stream)
    case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT_DIR);
 }
    case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
       return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT_DIR);
 }
+
+/**
+ * For this OS setup the build and parse function pointer to the OS specific functions.
+ */
+static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = tru64_build_acl_streams;
+static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = tru64_parse_acl_streams;
+
 #endif
 
 #elif defined(HAVE_HPUX_OS)
 #endif
 
 #elif defined(HAVE_HPUX_OS)
@@ -749,7 +957,13 @@ static bool tru64_parse_acl_stream(JCR *jcr, int stream)
 
 #include <acllib.h>
 
 
 #include <acllib.h>
 
-/*
+/**
+ * Define the supported ACL streams for this OS
+ */
+static int os_access_acl_streams[1] = { STREAM_ACL_HPUX_ACL_ENTRY };
+static int os_default_acl_streams[1] = { -1 };
+
+/**
  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
  * There is no need to store those acls as we already store the stat bits too.
  */
  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
  * There is no need to store those acls as we already store the stat bits too.
  */
@@ -760,8 +974,7 @@ static bool acl_is_trivial(int count, struct acl_entry *entries, struct stat sb)
 
    for (n = 0; n < count; n++) {
       ace = entries[n];
 
    for (n = 0; n < count; n++) {
       ace = entries[n];
-
-      /*
+      /**
        * See if this acl just is the stat mode in acl form.
        */
       if (!((ace.uid == sb.st_uid && ace.gid == ACL_NSGROUP) ||
        * See if this acl just is the stat mode in acl form.
        */
       if (!((ace.uid == sb.st_uid && ace.gid == ACL_NSGROUP) ||
@@ -769,118 +982,130 @@ static bool acl_is_trivial(int count, struct acl_entry *entries, struct stat sb)
             (ace.uid == ACL_NSUSER && ace.gid == ACL_NSGROUP)))
          return false;
    }
             (ace.uid == ACL_NSUSER && ace.gid == ACL_NSGROUP)))
          return false;
    }
-
    return true;
 }
 
    return true;
 }
 
-/*
+/**
  * OS specific functions for handling different types of acl streams.
  */
  * OS specific functions for handling different types of acl streams.
  */
-static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+static bacl_exit_code hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
 {
-   int n, len;
+   int n;
    struct acl_entry acls[NACLENTRIES];
    char *acl_text;
    struct acl_entry acls[NACLENTRIES];
    char *acl_text;
+   berrno be;
 
    if ((n = getacl(jcr->last_fname, 0, acls)) < 0) {
 
    if ((n = getacl(jcr->last_fname, 0, acls)) < 0) {
-      switch(errno) {
+      switch (errno) {
 #if defined(BACL_ENOTSUP)
       case BACL_ENOTSUP:
 #if defined(BACL_ENOTSUP)
       case BACL_ENOTSUP:
-         /*
+         /**
           * Not supported, just pretend there is nothing to see
           * Not supported, just pretend there is nothing to see
+          *
+          * 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.
           */
           */
-         pm_strcpy(jcr->acl_data, "");
-         return true;
+         jcr->acl_data->flags &= ~BACL_FLAG_SAVE_NATIVE;
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
+         return bacl_exit_ok;
 #endif
 #endif
+      case ENOENT:
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
+         return bacl_exit_ok;
       default:
       default:
-         berrno be;
-         Jmsg2(jcr, M_ERROR, 0, _("getacl error on file \"%s\": ERR=%s\n"),
-            jcr->last_fname, be.bstrerror());
+         Mmsg2(jcr->errmsg, _("getacl error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
          Dmsg2(100, "getacl error file=%s ERR=%s\n",  
          Dmsg2(100, "getacl error file=%s ERR=%s\n",  
-            jcr->last_fname, be.bstrerror());
+               jcr->last_fname, be.bstrerror());
 
 
-         pm_strcpy(jcr->acl_data, "");
-         return false;
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
+         return bacl_exit_error;
       }
    }
       }
    }
-
    if (n == 0) {
    if (n == 0) {
-      pm_strcpy(jcr->acl_data, "");
-      return true;
+      pm_strcpy(jcr->acl_data->content, "");
+      jcr->acl_data->content_length = 0;
+      return bacl_exit_ok;
    }
    }
-
    if ((n = getacl(jcr->last_fname, n, acls)) > 0) {
       if (acl_is_trivial(n, acls, ff_pkt->statp)) {
    if ((n = getacl(jcr->last_fname, n, acls)) > 0) {
       if (acl_is_trivial(n, acls, ff_pkt->statp)) {
-         /*
+         /**
           * The ACLs simply reflect the (already known) standard permissions
           * So we don't send an ACL stream to the SD.
           */
           * The ACLs simply reflect the (already known) standard permissions
           * So we don't send an ACL stream to the SD.
           */
-         pm_strcpy(jcr->acl_data, "");
-         return true;
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
+         return bacl_exit_ok;
       }
       }
-
       if ((acl_text = acltostr(n, acls, FORM_SHORT)) != NULL) {
       if ((acl_text = acltostr(n, acls, FORM_SHORT)) != NULL) {
-         len = pm_strcpy(jcr->acl_data, acl_text);
+         jcr->acl_data->content_length = pm_strcpy(jcr->acl_data->content, acl_text);
          actuallyfree(acl_text);
 
          actuallyfree(acl_text);
 
-         return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY, len);
+         return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY);
       }
       }
-
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("acltostr error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+      Mmsg2(jcr->errmsg, _("acltostr error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg3(100, "acltostr error acl=%s file=%s ERR=%s\n",  
       Dmsg3(100, "acltostr error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
-
-      return false;
+            jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+      return bacl_exit_error;
    }
    }
-
-   return false;
+   return bacl_exit_error;
 }
 
 }
 
-static bool hpux_parse_acl_stream(JCR *jcr, int stream)
+static bacl_exit_code hpux_parse_acl_streams(JCR *jcr, int stream)
 {
    int n, stat;
    struct acl_entry acls[NACLENTRIES];
 {
    int n, stat;
    struct acl_entry acls[NACLENTRIES];
+   berrno be;
 
 
-   n = strtoacl(jcr->acl_data, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
+   n = strtoacl(jcr->acl_data->content, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
    if (n <= 0) {
    if (n <= 0) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("strtoacl error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+      Mmsg2(jcr->errmsg, _("strtoacl error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
-
-      return false;
+            jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+      return bacl_exit_error;
    }
    }
-   if (strtoacl(jcr->acl_data, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("strtoacl error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+   if (strtoacl(jcr->acl_data->content, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) {
+      Mmsg2(jcr->errmsg, _("strtoacl error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
+            jcr->acl_data->content, jcr->last_fname, be.bstrerror());
 
 
-      return false;
+      return bacl_exit_error;
    }
    }
-   /*
+   /**
     * Restore the ACLs, but don't complain about links which really should
     * not have attributes, and the file it is linked to may not yet be restored.
     * 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) {
     * Restore the ACLs, but don't complain about links which really should
     * not have attributes, and the file it is linked to may not yet be restored.
     * 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) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("setacl error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
-      Dmsg3(100, "setacl error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
-
-      return false;
+      switch (errno) {
+      case ENOENT:
+         return bacl_exit_ok;
+      default:
+         Mmsg2(jcr->errmsg, _("setacl error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg3(100, "setacl error acl=%s file=%s ERR=%s\n",
+               jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+         return bacl_exit_error;
+      }
    }
    }
-
-   return true;
+   return bacl_exit_ok;
 }
 
 }
 
+/**
+ * For this OS setup the build and parse function pointer to the OS specific functions.
+ */
+static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = hpux_build_acl_streams;
+static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = hpux_parse_acl_streams;
+
 #elif defined(HAVE_SUN_OS)
 #ifdef HAVE_SYS_ACL_H
 #include <sys/acl.h>
 #elif defined(HAVE_SUN_OS)
 #ifdef HAVE_SYS_ACL_H
 #include <sys/acl.h>
@@ -889,14 +1114,14 @@ static bool hpux_parse_acl_stream(JCR *jcr, int stream)
 #endif
 
 #if defined(HAVE_EXTENDED_ACL)
 #endif
 
 #if defined(HAVE_EXTENDED_ACL)
-/*
+/**
  * We define some internals of the Solaris acl libs here as those
  * are not exposed yet. Probably because they want us to see the
  * acls as opague data. But as we need to support different platforms
  * and versions of Solaris we need to expose some data to be able
  * to determine the type of acl used to stuff it into the correct
  * data stream. I know this is far from portable, but maybe the
  * We define some internals of the Solaris acl libs here as those
  * are not exposed yet. Probably because they want us to see the
  * acls as opague data. But as we need to support different platforms
  * and versions of Solaris we need to expose some data to be able
  * to determine the type of acl used to stuff it into the correct
  * data stream. I know this is far from portable, but maybe the
- * propper interface is exposed later on and we can get ride of
+ * proper interface is exposed later on and we can get ride of
  * this kludge. Newer versions of Solaris include sys/acl_impl.h
  * which has implementation details of acls, if thats included we
  * don't have to define it ourself.
  * this kludge. Newer versions of Solaris include sys/acl_impl.h
  * which has implementation details of acls, if thats included we
  * don't have to define it ourself.
@@ -908,7 +1133,7 @@ typedef enum acl_type {
 } acl_type_t;
 #endif
 
 } acl_type_t;
 #endif
 
-/*
+/**
  * Two external references to functions in the libsec library function not in current include files.
  */
 extern "C" {
  * Two external references to functions in the libsec library function not in current include files.
  */
 extern "C" {
@@ -916,53 +1141,85 @@ int acl_type(acl_t *);
 char *acl_strerror(int);
 }
 
 char *acl_strerror(int);
 }
 
-/*
+/**
+ * Define the supported ACL streams for this OS
+ */
+static int os_access_acl_streams[2] = { STREAM_ACL_SOLARIS_ACLENT, STREAM_ACL_SOLARIS_ACE };
+static int os_default_acl_streams[1] = { -1 };
+
+/**
  * As the new libsec interface with acl_totext and acl_fromtext also handles
  * the old format from acltotext we can use the new functions even
  * for acls retrieved and stored in the database with older fd versions. If the
  * new interface is not defined (Solaris 9 and older we fall back to the old code)
  */
  * As the new libsec interface with acl_totext and acl_fromtext also handles
  * the old format from acltotext we can use the new functions even
  * for acls retrieved and stored in the database with older fd versions. If the
  * new interface is not defined (Solaris 9 and older we fall back to the old code)
  */
-static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
 {
-   int len, flags;
+   int acl_enabled, flags;
    acl_t *aclp;
    char *acl_text;
    acl_t *aclp;
    char *acl_text;
-   bool stream_status = false;
+   bacl_exit_code stream_status = bacl_exit_error;
+   berrno be;
+
+   /**
+    * See if filesystem supports acls.
+    */
+   acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
+   switch (acl_enabled) {
+   case 0:
+      /**
+       * 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;
+      pm_strcpy(jcr->acl_data->content, "");
+      jcr->acl_data->content_length = 0;
+      return bacl_exit_ok;
+   case -1:
+      switch (errno) {
+      case ENOENT:
+         return bacl_exit_ok;
+      default:
+         Mmsg2(jcr->errmsg, _("pathconf error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "pathconf error file=%s ERR=%s\n",  
+               jcr->last_fname, be.bstrerror());
+         return bacl_exit_error;
+      }
+   default:
+      break;
+   }
 
 
-   /*
+   /**
     * 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) {
       switch (errno) {
     * 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) {
       switch (errno) {
-#if defined(BACL_ENOTSUP)
-      case BACL_ENOTSUP:
-         /*
-          * Not supported, just pretend there is nothing to see
-          */
-         pm_strcpy(jcr->acl_data, "");
-         return true;
-#endif
+      case ENOENT:
+         return bacl_exit_ok;
       default:
       default:
-         Jmsg2(jcr, M_ERROR, 0, _("acl_get error on file \"%s\": ERR=%s\n"),
-            jcr->last_fname, acl_strerror(errno));
+         Mmsg2(jcr->errmsg, _("acl_get error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, acl_strerror(errno));
          Dmsg2(100, "acl_get error file=%s ERR=%s\n",  
          Dmsg2(100, "acl_get error file=%s ERR=%s\n",  
-            jcr->last_fname, acl_strerror(errno));
-
-         return false;
+               jcr->last_fname, acl_strerror(errno));
+         return bacl_exit_error;
       }
    }
 
       }
    }
 
-   if (aclp == NULL) {
-      /*
+   if (!aclp) {
+      /**
        * The ACLs simply reflect the (already known) standard permissions
        * So we don't send an ACL stream to the SD.
        */
        * The ACLs simply reflect the (already known) standard permissions
        * So we don't send an ACL stream to the SD.
        */
-      pm_strcpy(jcr->acl_data, "");
-      return true;
+      pm_strcpy(jcr->acl_data->content, "");
+      jcr->acl_data->content_length = 0;
+      return bacl_exit_ok;
    }
 
 #if defined(ACL_SID_FMT)
    }
 
 #if defined(ACL_SID_FMT)
-   /*
+   /**
     * New format flag added in newer Solaris versions.
     */
    flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
     * New format flag added in newer Solaris versions.
     */
    flags = ACL_APPEND_ID | ACL_COMPACT_FMT | ACL_SID_FMT;
@@ -971,15 +1228,15 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 #endif /* ACL_SID_FMT */
 
    if ((acl_text = acl_totext(aclp, flags)) != NULL) {
 #endif /* ACL_SID_FMT */
 
    if ((acl_text = acl_totext(aclp, flags)) != NULL) {
-      len = pm_strcpy(jcr->acl_data, acl_text);
+      jcr->acl_data->content_length = pm_strcpy(jcr->acl_data->content, acl_text);
       actuallyfree(acl_text);
 
       switch (acl_type(aclp)) {
       case ACLENT_T:
       actuallyfree(acl_text);
 
       switch (acl_type(aclp)) {
       case ACLENT_T:
-         stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT, len);
+         stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT);
          break;
       case ACE_T:
          break;
       case ACE_T:
-         stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACE, len);
+         stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACE);
          break;
       default:
          break;
          break;
       default:
          break;
@@ -987,76 +1244,143 @@ static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 
       acl_free(aclp);
    }
 
       acl_free(aclp);
    }
-
    return stream_status;
 }
 
    return stream_status;
 }
 
-static bool solaris_parse_acl_stream(JCR *jcr, int stream)
+static bacl_exit_code solaris_parse_acl_streams(JCR *jcr, int stream)
 {
    acl_t *aclp;
 {
    acl_t *aclp;
-   int error;
+   int acl_enabled, error;
+   berrno be;
 
    switch (stream) {
    case STREAM_UNIX_ACCESS_ACL:
    case STREAM_ACL_SOLARIS_ACLENT:
    case STREAM_ACL_SOLARIS_ACE:
 
    switch (stream) {
    case STREAM_UNIX_ACCESS_ACL:
    case STREAM_ACL_SOLARIS_ACLENT:
    case STREAM_ACL_SOLARIS_ACE:
-      if ((error = acl_fromtext(jcr->acl_data, &aclp)) != 0) {
-         Jmsg2(jcr, M_ERROR, 0, _("acl_fromtext error on file \"%s\": ERR=%s\n"),
-            jcr->last_fname, acl_strerror(error));
+      /**
+       * First make sure the filesystem supports acls.
+       */
+      acl_enabled = pathconf(jcr->last_fname, _PC_ACL_ENABLED);
+      switch (acl_enabled) {
+      case 0:
+         Mmsg1(jcr->errmsg, _("Trying to restore acl on file \"%s\" on filesystem without acl support\n"),
+               jcr->last_fname);
+         return bacl_exit_error;
+      case -1:
+         switch (errno) {
+         case ENOENT:
+            return bacl_exit_ok;
+         default:
+            Mmsg2(jcr->errmsg, _("pathconf error on file \"%s\": ERR=%s\n"),
+                  jcr->last_fname, be.bstrerror());
+            Dmsg3(100, "pathconf error acl=%s file=%s ERR=%s\n",  
+                  jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+            return bacl_exit_error;
+         }
+      default:
+         /**
+          * On a filesystem with ACL support make sure this particilar ACL type can be restored.
+          */
+         switch (stream) {
+         case STREAM_ACL_SOLARIS_ACLENT:
+            /**
+             * An aclent can be restored on filesystems with _ACL_ACLENT_ENABLED or _ACL_ACE_ENABLED support.
+             */
+            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"),
+                     jcr->last_fname);
+               return bacl_exit_error;
+            }
+            break;
+         case STREAM_ACL_SOLARIS_ACE:
+            /**
+             * An ace can only be restored on a filesystem with _ACL_ACE_ENABLED support.
+             */
+            if ((acl_enabled & _ACL_ACE_ENABLED) == 0) {
+               Mmsg1(jcr->errmsg, _("Trying to restore acl on file \"%s\" on filesystem without ace acl support\n"),
+                     jcr->last_fname);
+               return bacl_exit_error;
+            }
+            break;
+         default:
+            /**
+             * Stream id which doesn't describe the type of acl which is encoded.
+             */
+            break;
+         }
+         break;
+      }
+
+      if ((error = acl_fromtext(jcr->acl_data->content, &aclp)) != 0) {
+         Mmsg2(jcr->errmsg, _("acl_fromtext error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, acl_strerror(error));
          Dmsg3(100, "acl_fromtext error acl=%s file=%s ERR=%s\n",  
          Dmsg3(100, "acl_fromtext error acl=%s file=%s ERR=%s\n",  
-            jcr->acl_data, jcr->last_fname, acl_strerror(error));
-         return false;
+               jcr->acl_data->content, jcr->last_fname, acl_strerror(error));
+         return bacl_exit_error;
       }
 
       }
 
-      /*
+      /**
        * Validate that the conversion gave us the correct acl type.
        */
       switch (stream) {
       case STREAM_ACL_SOLARIS_ACLENT:
          if (acl_type(aclp) != ACLENT_T) {
        * Validate that the conversion gave us the correct acl type.
        */
       switch (stream) {
       case STREAM_ACL_SOLARIS_ACLENT:
          if (acl_type(aclp) != ACLENT_T) {
-            Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
-               jcr->last_fname);
-            return false;
+            Mmsg1(jcr->errmsg, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
+                  jcr->last_fname);
+            return bacl_exit_error;
          }
          }
+         break;
       case STREAM_ACL_SOLARIS_ACE:
          if (acl_type(aclp) != ACE_T) {
       case STREAM_ACL_SOLARIS_ACE:
          if (acl_type(aclp) != ACE_T) {
-            Jmsg1(jcr, M_ERROR, 0, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
-               jcr->last_fname);
-            return false;
+            Mmsg1(jcr->errmsg, _("wrong encoding of acl type in acl stream on file \"%s\"\n"),
+                  jcr->last_fname);
+            return bacl_exit_error;
          }
          }
+         break;
       default:
       default:
-         /*
+         /**
           * Stream id which doesn't describe the type of acl which is encoded.
           */
          break;
       }
 
           * Stream id which doesn't describe the type of acl which is encoded.
           */
          break;
       }
 
-      /*
+      /**
        * Restore the ACLs, but don't complain about links which really should
        * not have attributes, and the file it is linked to may not yet be restored.
        * 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 ((error = acl_set(jcr->last_fname, aclp)) == -1 && jcr->last_type != FT_LNK) {
        * Restore the ACLs, but don't complain about links which really should
        * not have attributes, and the file it is linked to may not yet be restored.
        * 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 ((error = acl_set(jcr->last_fname, aclp)) == -1 && jcr->last_type != FT_LNK) {
-         Jmsg2(jcr, M_ERROR, 0, _("acl_set error on file \"%s\": ERR=%s\n"),
-            jcr->last_fname, acl_strerror(error));
-         Dmsg3(100, "acl_set error acl=%s file=%s ERR=%s\n",  
-            jcr->acl_data, jcr->last_fname, acl_strerror(error));
-
-         acl_free(aclp);
-         return false;
+         switch (errno) {
+         case ENOENT:
+            acl_free(aclp);
+            return bacl_exit_ok;
+         default:
+            Mmsg2(jcr->errmsg, _("acl_set error on file \"%s\": ERR=%s\n"),
+                  jcr->last_fname, acl_strerror(error));
+            Dmsg3(100, "acl_set error acl=%s file=%s ERR=%s\n",  
+                  jcr->acl_data->content, jcr->last_fname, acl_strerror(error));
+            acl_free(aclp);
+            return bacl_exit_error;
+         }
       }
 
       acl_free(aclp);
       }
 
       acl_free(aclp);
-      return true;
+      return bacl_exit_ok;
    default:
    default:
-      return false;
+      return bacl_exit_error;
    } /* end switch (stream) */
 }
 
 #else /* HAVE_EXTENDED_ACL */
 
    } /* end switch (stream) */
 }
 
 #else /* HAVE_EXTENDED_ACL */
 
-/*
+/**
+ * Define the supported ACL streams for this OS
+ */
+static int os_access_acl_streams[2] = { STREAM_ACL_SOLARIS_ACLENT };
+static int os_default_acl_streams[1] = { -1 };
+
+/**
  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
  * There is no need to store those acls as we already store the stat bits too.
  */
  * See if an acl is a trivial one (e.g. just the stat bits encoded as acl.)
  * There is no need to store those acls as we already store the stat bits too.
  */
@@ -1074,189 +1398,191 @@ static bool acl_is_trivial(int count, aclent_t *entries)
             ace->a_type == CLASS_OBJ))
         return false;
    }
             ace->a_type == CLASS_OBJ))
         return false;
    }
-
    return true;
 }
 
    return true;
 }
 
-/*
+/**
  * OS specific functions for handling different types of acl streams.
  */
  * OS specific functions for handling different types of acl streams.
  */
-static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt);
+static bacl_exit_code solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
 {
-   int n, len;
+   int n;
    aclent_t *acls;
    char *acl_text;
    aclent_t *acls;
    char *acl_text;
+   berrno be;
 
    n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
 
    n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
-   if (n < MIN_ACL_ENTRIES) {
-      return false;
+   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) {
       if (acl_is_trivial(n, acls)) {
 
    acls = (aclent_t *)malloc(n * sizeof(aclent_t));
    if (acl(jcr->last_fname, GETACL, n, acls) == n) {
       if (acl_is_trivial(n, acls)) {
-         /*
+         /**
           * The ACLs simply reflect the (already known) standard permissions
           * So we don't send an ACL stream to the SD.
           */
          free(acls);
           * The ACLs simply reflect the (already known) standard permissions
           * So we don't send an ACL stream to the SD.
           */
          free(acls);
-         pm_strcpy(jcr->acl_data, "");
-         return true;
+         pm_strcpy(jcr->acl_data->content, "");
+         jcr->acl_data->content_length = 0;
+         return bacl_exit_ok;
       }
 
       if ((acl_text = acltotext(acls, n)) != NULL) {
       }
 
       if ((acl_text = acltotext(acls, n)) != NULL) {
-         len = pm_strcpy(jcr->acl_data, acl_text);
+         jcr->acl_data->content_length = pm_strcpy(jcr->acl_data->content, acl_text);
          actuallyfree(acl_text);
          free(acls);
          actuallyfree(acl_text);
          free(acls);
-
-         return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT, len);
+         return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT);
       }
 
       }
 
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("acltotext error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+      Mmsg2(jcr->errmsg, _("acltotext error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg3(100, "acltotext error acl=%s file=%s ERR=%s\n",  
       Dmsg3(100, "acltotext error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
+            jcr->acl_data->content, jcr->last_fname, be.bstrerror());
    }
 
    free(acls);
    }
 
    free(acls);
-   return false;
+   return bacl_exit_error;
 }
 
 }
 
-static bool solaris_parse_acl_stream(JCR *jcr, int stream)
+static bacl_exit_code solaris_parse_acl_streams(JCR *jcr, int stream)
 {
    int n;
    aclent_t *acls;
 {
    int n;
    aclent_t *acls;
+   berrno be;
 
 
-   acls = aclfromtext(jcr->acl_data, &n);
+   acls = aclfromtext(jcr->acl_data->content, &n);
    if (!acls) {
    if (!acls) {
-      berrno be;
-      Jmsg2(jcr, M_ERROR, 0, _("aclfromtext error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
+      Mmsg2(jcr->errmsg, _("aclfromtext error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
       Dmsg3(100, "aclfromtext error acl=%s file=%s ERR=%s\n",  
       Dmsg3(100, "aclfromtext error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
-
-      return false;
+            jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+      return bacl_exit_error;
    }
 
    }
 
-   /*
+   /**
     * Restore the ACLs, but don't complain about links which really should
     * 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) {
     * Restore the ACLs, but don't complain about links which really should
     * 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;
-      Jmsg2(jcr, M_ERROR, 0, _("acl(SETACL) error on file \"%s\": ERR=%s\n"),
-         jcr->last_fname, be.bstrerror());
-      Dmsg3(100, "acl(SETACL) error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_data, jcr->last_fname, be.bstrerror());
-      actuallyfree(acls);
-
-      return false;
+      switch (errno) {
+      case ENOENT:
+         actuallyfree(acls);
+         return bacl_exit_ok;
+      default:
+         Mmsg2(jcr->errmsg, _("acl(SETACL) error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg3(100, "acl(SETACL) error acl=%s file=%s ERR=%s\n",
+               jcr->acl_data->content, jcr->last_fname, be.bstrerror());
+         actuallyfree(acls);
+         return bacl_exit_error;
+      }
    }
    }
-
    actuallyfree(acls);
    actuallyfree(acls);
-   return true;
+   return bacl_exit_ok;
 }
 }
-
 #endif /* HAVE_EXTENDED_ACL */
 #endif /* HAVE_EXTENDED_ACL */
+
+/**
+ * For this OS setup the build and parse function pointer to the OS specific functions.
+ */
+static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = solaris_build_acl_streams;
+static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = solaris_parse_acl_streams;
+
 #endif /* HAVE_SUN_OS */
 #endif /* HAVE_SUN_OS */
+#endif /* HAVE_ACL */
 
 /*
  * Entry points when compiled with support for ACLs on a supported platform.
  */
 
 
 /*
  * Entry points when compiled with support for ACLs on a supported platform.
  */
 
-/*
+/**
  * Read and send an ACL for the last encountered file.
  */
  * Read and send an ACL for the last encountered file.
  */
-bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
+bacl_exit_code build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
 {
-   /*
-    * Call the appropriate function, the ifdefs make sure the proper code is compiled.
+   /**
+    * See if we are changing from one device to an other.
+    * 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.
     */
     */
-#if defined(HAVE_AIX_OS)
-   return aix_build_acl_streams(jcr, ff_pkt);
-#elif defined(HAVE_DARWIN_OS)
-   return darwin_build_acl_streams(jcr, ff_pkt);
-#elif defined(HAVE_FREEBSD_OS)
-   return freebsd_build_acl_streams(jcr, ff_pkt);
-#elif defined(HAVE_HPUX_OS)
-   return hpux_build_acl_streams(jcr, ff_pkt);
-#elif defined(HAVE_IRIX_OS)
-   return irix_build_acl_streams(jcr, ff_pkt);
-#elif defined(HAVE_LINUX_OS)
-   return linux_build_acl_streams(jcr, ff_pkt);
-#elif defined(HAVE_OSF1_OS)
-   return tru64_build_acl_streams(jcr, ff_pkt);
-#elif defined(HAVE_SUN_OS)
-   return solaris_build_acl_streams(jcr, ff_pkt);
+   if (jcr->acl_data->current_dev != ff_pkt->statp.st_dev) {
+      /**
+       * Reset the acl save flags.
+       */
+      jcr->acl_data->flags = 0;
+
+      jcr->acl_data->flags |= BACL_FLAG_SAVE_NATIVE;
+
+      /**
+       * Save that we started scanning a new filesystem.
+       */
+      jcr->acl_data->current_dev = ff_pkt->statp.st_dev;
+   }
+
+#if defined(HAVE_ACL)
+   /**
+    * See if the BACL_FLAG_SAVE_NATIVE flag is set which lets us know if we should
+    * save native ACLs.
+    */
+   if (jcr->acl_data->flags & BACL_FLAG_SAVE_NATIVE) {
+      /**
+       * Call the appropriate function.
+       */
+      if (os_build_acl_streams) {
+         return (*os_build_acl_streams)(jcr, ff_pkt);
+      }
+   } else {
+      return bacl_exit_ok;
+   }
 #endif
 #endif
+   return bacl_exit_error;
 }
 
 }
 
-bool parse_acl_stream(JCR *jcr, int stream)
+bacl_exit_code parse_acl_streams(JCR *jcr, int stream)
 {
 {
-   /*
-    * Based on the stream being passed in dispatch to the right function
-    * for parsing and restoring a specific acl. The platform determines
-    * which streams are recognized and parsed and which are handled by
-    * the default case and ignored. The old STREAM_UNIX_ACCESS_ACL and
-    * STREAM_UNIX_DEFAULT_ACL is handled as a legacy stream by each function.
-    * As only one of the platform defines is true per compile we never end
-    * up with duplicate switch values.
-    */
+   unsigned int cnt;
+
    switch (stream) {
    switch (stream) {
-#if defined(HAVE_AIX_OS)
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_AIX_TEXT:
-      return aix_parse_acl_stream(jcr, stream);
-#elif defined(HAVE_DARWIN_OS)
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_ACL_DARWIN_ACCESS_ACL:
-      return darwin_parse_acl_stream(jcr, stream);
-#elif defined(HAVE_FREEBSD_OS)
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_FREEBSD_DEFAULT_ACL:
-   case STREAM_ACL_FREEBSD_ACCESS_ACL:
-      return freebsd_parse_acl_stream(jcr, stream);
-#elif defined(HAVE_HPUX_OS)
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_ACL_HPUX_ACL_ENTRY:
-      return hpux_parse_acl_stream(jcr, stream);
-#elif defined(HAVE_IRIX_OS)
+#if defined(HAVE_ACL)
    case STREAM_UNIX_ACCESS_ACL:
    case STREAM_UNIX_DEFAULT_ACL:
    case STREAM_UNIX_ACCESS_ACL:
    case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_IRIX_DEFAULT_ACL:
-   case STREAM_ACL_IRIX_ACCESS_ACL:
-      return irix_parse_acl_stream(jcr, stream);
-#elif defined(HAVE_LINUX_OS)
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_LINUX_DEFAULT_ACL:
-   case STREAM_ACL_LINUX_ACCESS_ACL:
-      return linux_parse_acl_stream(jcr, stream);
-#elif defined(HAVE_OSF1_OS)
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_UNIX_DEFAULT_ACL:
-   case STREAM_ACL_TRU64_DEFAULT_ACL:
-   case STREAM_ACL_TRU64_ACCESS_ACL:
-   case STREAM_ACL_TRU64_DEFAULT_DIR_ACL:
-      return tru64_parse_acl_stream(jcr, stream);
-#elif defined(HAVE_SUN_OS)
-   case STREAM_UNIX_ACCESS_ACL:
-   case STREAM_ACL_SOLARIS_ACLENT:
-#if defined(HAVE_EXTENDED_ACL)
-   case STREAM_ACL_SOLARIS_ACE:
-#endif
-      return solaris_parse_acl_stream(jcr, stream);
-#endif
-   default:
-      /*
-       * Issue a warning and discard the message. But pretend the restore was ok.
+      /**
+       * Handle legacy ACL streams.
        */
        */
-      Qmsg2(jcr, M_WARNING, 0,
-         _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"),
-         jcr->last_fname, stream);
-      return true;
-   } /* end switch (stream) */
+      if (os_parse_acl_streams) {
+         return (*os_parse_acl_streams)(jcr, stream);
+      }
+      break;
+   default:
+      if (os_parse_acl_streams) {
+         /**
+          * Walk the os_access_acl_streams array with the supported Access ACL streams for this OS.
+          */
+         for (cnt = 0; cnt < sizeof(os_access_acl_streams) / sizeof(int); cnt++) {
+            if (os_access_acl_streams[cnt] == stream) {
+               return (*os_parse_acl_streams)(jcr, stream);
+            }
+         }
+         /**
+          * Walk the os_default_acl_streams array with the supported Default ACL streams for this OS.
+          */
+         for (cnt = 0; cnt < sizeof(os_default_acl_streams) / sizeof(int); cnt++) {
+            if (os_default_acl_streams[cnt] == stream) {
+               return (*os_parse_acl_streams)(jcr, stream);
+            }
+         }
+      }
+      break;
+#else
+   default:
+      break;
+#endif
+   }
+   Qmsg2(jcr, M_WARNING, 0,
+      _("Can't restore ACLs of %s - incompatible acl stream encountered - %d\n"),
+      jcr->last_fname, stream);
+   return bacl_exit_error;
 }
 #endif
 }
 #endif