]> git.sur5r.net Git - bacula/bacula/commitdiff
kes Apply Marco's Extended attribute support patch.
authorKern Sibbald <kern@sibbald.com>
Wed, 26 Nov 2008 12:58:18 +0000 (12:58 +0000)
committerKern Sibbald <kern@sibbald.com>
Wed, 26 Nov 2008 12:58:18 +0000 (12:58 +0000)
kes  Update projects file

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@8084 91ce42f0-d328-0410-95d8-f526ca767f89

24 files changed:
bacula/autoconf/config.h.in
bacula/autoconf/config.h.in.save
bacula/autoconf/configure.in
bacula/projects
bacula/src/baconfig.h
bacula/src/dird/inc_conf.c
bacula/src/filed/Makefile.in
bacula/src/filed/acl.c
bacula/src/filed/acl.h
bacula/src/filed/backup.c
bacula/src/filed/job.c
bacula/src/filed/protos.h
bacula/src/filed/restore.c
bacula/src/filed/status.c
bacula/src/findlib/bfile.c
bacula/src/findlib/find.h
bacula/src/findlib/match.c
bacula/src/jcr.h
bacula/src/lib/mem_pool.c
bacula/src/lib/mem_pool.h
bacula/src/stored/bscan.c
bacula/src/tools/testfind.c
bacula/src/version.h
bacula/technotes-2.5

index d015a65f059c9588acbb2519c9c3f0b3fb08a830..e0f50d210be2f43619b58745ae1419b8a47eedf0 100644 (file)
 /* Define if you have zlib */
 #undef HAVE_LIBZ
 
+/* Defines if your system have the sys/acl.h header file */
+#undef HAVE_SYS_ACL_H
+
 /* Define if you have libacl */
 #undef HAVE_ACL
 
 /* Define if you have extended acls */
 #undef HAVE_EXTENDED_ACL
 
+/* Defines if your system have the sys/xattr.h header file */
+#undef HAVE_SYS_XATTR_H
+
+/* Define if you have extended attributes */
+#undef HAVE_XATTR
+
+/* Define when you have extended attributes functions starting with l (like lstat) */
+#undef HAVE_LLISTXATTR
+#undef HAVE_LGETXATTR
+#undef HAVE_LSETXATTR
+
+/* Define when you have extended attributes functions not starting with l (like stat) */
+#undef HAVE_LISTXATTR
+#undef HAVE_GETXATTR
+#undef HAVE_SETXATTR
+
 /* General libs */
 #undef LIBS
 
index d015a65f059c9588acbb2519c9c3f0b3fb08a830..e0f50d210be2f43619b58745ae1419b8a47eedf0 100644 (file)
 /* Define if you have zlib */
 #undef HAVE_LIBZ
 
+/* Defines if your system have the sys/acl.h header file */
+#undef HAVE_SYS_ACL_H
+
 /* Define if you have libacl */
 #undef HAVE_ACL
 
 /* Define if you have extended acls */
 #undef HAVE_EXTENDED_ACL
 
+/* Defines if your system have the sys/xattr.h header file */
+#undef HAVE_SYS_XATTR_H
+
+/* Define if you have extended attributes */
+#undef HAVE_XATTR
+
+/* Define when you have extended attributes functions starting with l (like lstat) */
+#undef HAVE_LLISTXATTR
+#undef HAVE_LGETXATTR
+#undef HAVE_LSETXATTR
+
+/* Define when you have extended attributes functions not starting with l (like stat) */
+#undef HAVE_LISTXATTR
+#undef HAVE_GETXATTR
+#undef HAVE_SETXATTR
+
 /* General libs */
 #undef LIBS
 
index de0de1d711d2badf3f18996d0326b642683343c8..6e413a01f0cc3bdc8847e7760cededd0b6820eb3 100644 (file)
@@ -124,7 +124,7 @@ dnl --------------------------------------------------
 dnl Libtool config
 dnl --------------------------------------------------
 AC_ARG_ENABLE(libtool,
-   AC_HELP_STRING([--enable-libtool], [enable building using GNU libtool @<:@default=yes@:>@]),
+   AC_HELP_STRING([--disable-libtool], [disable building using GNU libtool @<:@default=no@:>@]),
    [
        if test x$enableval = xno; then
          use_libtool=no
@@ -227,7 +227,24 @@ if test x${prefix} = xNONE ; then
    fi
 
    if test `eval echo ${libdir}` = NONE/lib ; then
-      libdir=/usr/lib
+      #
+      # Some platforms have other defaults (for 64 bits libs)
+      #
+      case `uname -s` in
+         Linux)
+            case `uname -m` in
+               x86_64)
+                  libdir=/usr/lib64
+                  ;;
+               *)
+                  libdir=/usr/lib
+                  ;;
+            esac
+            ;;
+         *)
+            libdir=/usr/lib
+            ;;
+      esac
    fi
 
    if test `eval echo ${includedir}` = NONE/include ; then
@@ -1149,7 +1166,7 @@ AC_ARG_WITH(scriptdir,
 AC_SUBST(scriptdir)
 
 # ------------------------------------------
-# Where to place plugindir (script files)
+# Where to place plugindir (plugin files)
 # ------------------------------------------
 plugindir=`eval echo ${sysconfdir}`
 AC_ARG_WITH(plugindir,
@@ -2204,43 +2221,105 @@ if test x$FDLIBS = x-lz; then
 fi
 
 dnl
-dnl Check for ACL libraries
+dnl Check for ACL support and libraries
 dnl
+support_acl=yes
+AC_ARG_ENABLE(acl,
+   AC_HELP_STRING([--disable-acl], [disable acl support @<:@default=auto@:>@]),
+   [
+       if test x$enableval = xno; then
+         support_acl=no
+       fi
+   ]
+)
+
 have_acl=no
 have_extended_acl=no
-AC_CHECK_HEADER(sys/acl.h)
-AC_CHECK_FUNC(acl_get_file, [have_acl=yes],
+if test x$support_acl = xyes; then
+   AC_CHECK_HEADER(sys/acl.h, [ AC_DEFINE(HAVE_SYS_ACL_H,1,[Defines if your system have the sys/acl.h header file])] , )
+   AC_CHECK_FUNC(acl_get_file,
+      [
+          have_acl=yes
+      ], [
+          AC_CHECK_LIB(acl, acl_get_file,
+            [
+                have_acl=yes;
+                FDLIBS="-lacl $FDLIBS"
+            ], [
+                AC_CHECK_LIB(pacl, acl_get_file,
+                    [
+                       have_acl=yes;
+                       FDLIBS="-lpacl $FDLIBS"
+                    ], [
+                       AC_CHECK_LIB(sec, acltotext,
+                          [
+                              have_acl=yes;
+                              FDLIBS="-lsec $FDLIBS"
+
+                              AC_CHECK_LIB(sec, acl_totext,
+                                 [
+                                     have_extended_acl=yes
+                                 ]
+                              )
+                          ]
+                       )
+                    ]
+                 )
+             ]
+          )
+      ]
+   )
+   if test $have_acl = yes; then
+      AC_DEFINE(HAVE_ACL)
+   fi
+
+   if test $have_extended_acl = yes; then
+      AC_DEFINE(HAVE_EXTENDED_ACL)
+   fi
+fi
+
+dnl
+dnl Check for XATTR support
+dnl
+support_xattr=yes
+AC_ARG_ENABLE(xattr,
+   AC_HELP_STRING([--disable-xattr], [disable xattr support @<:@default=auto@:>@]),
    [
-       AC_CHECK_LIB(acl, acl_get_file,
-         [
-             have_acl=yes;
-             FDLIBS="-lacl $FDLIBS"
-         ], [
-             AC_CHECK_LIB(sec, acltotext,
-                [
-                    have_acl=yes;
-                    FDLIBS="-lsec $FDLIBS"
-
-                    AC_CHECK_LIB(sec, acl_totext,
-                       [
-                           have_extended_acl=yes
-                       ]
-                    )
-                ]
-             )
-         ]
-       )
+       if test x$enableval = xno; then
+         support_acl=no
+       fi
    ]
 )
-if test $have_acl = yes; then
-   AC_DEFINE(HAVE_ACL)
-fi
 
-if test $have_extended_acl = yes; then
-   AC_DEFINE(HAVE_EXTENDED_ACL)
+have_xattr=no
+if test x$support_xattr = xyes; then
+   AC_CHECK_HEADER(sys/xattr.h, [ AC_DEFINE(HAVE_SYS_XATTR_H,1,[Defines if your system have the sys/xattr.h header file])] , )
+   AC_CHECK_FUNCS(llistxattr lgetxattr lsetxattr,
+      [
+          have_xattr=yes
+          AC_DEFINE(HAVE_LLISTXATTR)
+          AC_DEFINE(HAVE_LGETXATTR)
+          AC_DEFINE(HAVE_LSETXATTR)
+      ], [
+          AC_CHECK_FUNCS(listxattr getxattr setxattr,
+              [
+                  have_xattr=yes
+                  AC_DEFINE(HAVE_LISTXATTR)
+                  AC_DEFINE(HAVE_GETXATTR)
+                  AC_DEFINE(HAVE_SETXATTR)
+              ]
+          )
+      ]
+   )
+
+   if test $have_xattr = yes; then
+      AC_DEFINE(HAVE_XATTR)
+   fi
 fi
 
+dnl
 dnl Check for pthread libraries
+dnl
 PTHREAD_LIB=""
 AC_CHECK_LIB(pthread, pthread_create, PTHREAD_LIB="-lpthread",
    [
@@ -2861,6 +2940,7 @@ Configuration on `date`:
    Subsys directory:       ${subsysdir}
    Man directory:          ${mandir}
    Data directory:         ${datarootdir}
+   Plugin directory:        ${plugindir}
    C Compiler:             ${CC} ${CCVERSION}
    C++ Compiler:           ${CXX} ${CXXVERSION}
    Compiler flags:         ${WCFLAGS} ${CFLAGS} 
@@ -2910,6 +2990,7 @@ Configuration on `date`:
    build-dird:             ${build_dird}
    build-stored:           ${build_stored}
    ACL support:            ${have_acl}
+   XATTR support:          ${have_xattr}
    Python support:         ${support_python} ${PYTHON_LIBS}
    Batch insert enabled:    ${support_batch_insert}
 
index b41e63e3151f1759ec4ee0fcd8390a66b23eee76..7da1727b7b81ec3ba84117460cc5abcf969b3f3c 100644 (file)
@@ -1,29 +1,32 @@
                 
 Projects:
                      Bacula Projects Roadmap 
-                    Status updated 26 August 2008
+                    Status updated 26 November 2008
 
 Items Completed:
-
-Summary:
 Item  1:  Accurate restoration of renamed/deleted files
-Item  2:  Allow FD to initiate a backup
 Item  3:  Merge multiple backups (Synthetic Backup or Consolidation)
 Item  4:  Implement Catalog directive for Pool resource in Director
 Item  5:  Add an item to the restore option where you can select a Pool
+Item  8:  Implement Copy pools
+Item 12:  Add Plug-ins to the FileSet Include statements.
+Item 13:  Restore only file attributes (permissions, ACL, owner, group...)
+Item 18:  Better control over Job execution
+Item 26: Store and restore extended attributes, especially selinux file contexts
+Item 27:  make changing "spooldata=yes|no" possible for
+Item 28:  Implement an option to modify the last written date for volumes
+
+Summary:
+Item  2:  Allow FD to initiate a backup
 Item  6:  Deletion of disk Volumes when pruned
 Item  7:  Implement Base jobs
-Item  8:  Implement Copy pools
 Item  9:  Scheduling syntax that permits more flexibility and options
 Item 10:  Message mailing based on backup types
 Item 11:  Cause daemons to use a specific IP address to source communications
-Item 12:  Add Plug-ins to the FileSet Include statements.
-Item 13:  Restore only file attributes (permissions, ACL, owner, group...)
 Item 14:  Add an override in Schedule for Pools based on backup types
-Item 15:  Implement more Python events and functions
+Item 15:  Implement more Python events and functions  --- Abandoned for plugins
 Item 16:  Allow inclusion/exclusion of files in a fileset by creation/mod times
 Item 17:  Automatic promotion of backup levels based on backup size
-Item 18:  Better control over Job execution
 Item 19:  Automatic disabling of devices
 Item 20:  An option to operate on all pools with update vol parameters
 Item 21:  Include timestamp of job launch in "stat clients" output
@@ -36,7 +39,7 @@ Item 25:  Archival (removal) of User Files to Tape
 Item  1:  Accurate restoration of renamed/deleted files
   Date:   28 November 2005
   Origin: Martin Simmons (martin at lispworks dot com)
-  Status: 
+  Status: Done
 
   What:   When restoring a fileset for a specified date (including "most
           recent"), Bacula should give you exactly the files and directories
@@ -81,7 +84,7 @@ Item  2:  Allow FD to initiate a backup
 Item  3:  Merge multiple backups (Synthetic Backup or Consolidation) 
   Origin: Marc Cousin and Eric Bollengier 
   Date:   15 November 2005
-  Status: 
+  Status: Done
 
   What:   A merged backup is a backup made without connecting to the Client.
           It would be a Merge of existing backups into a single backup.
@@ -116,7 +119,7 @@ Item  3:  Merge multiple backups (Synthetic Backup or Consolidation)
 Item  4:  Implement Catalog directive for Pool resource in Director
   Origin: Alan Davis adavis@ruckus.com
   Date:   6 March 2007
-  Status: Submitted
+  Status: Done, but not tested, and possibly not fully implemented.
  
   What:   The current behavior is for the director to create all pools
           found in the configuration file in all catalogs.  Add a
@@ -134,7 +137,7 @@ Item  4:  Implement Catalog directive for Pool resource in Director
 Item  5:  Add an item to the restore option where you can select a Pool
   Origin: kshatriyak at gmail dot com
     Date: 1/1/2006
-  Status:
+  Status: Done at least via command line
 
     What: In the restore option (Select the most recent backup for a
           client) it would be useful to add an option where you can limit
@@ -219,7 +222,7 @@ Item  7:  Implement Base jobs
 Item  8:  Implement Copy pools
   Date:   27 November 2005
   Origin: David Boyes (dboyes at sinenomine dot net)
-  Status:
+  Status: A trivial version of this is done.
 
   What:   I would like Bacula to have the capability to write copies
           of backed-up data on multiple physical volumes selected
@@ -540,7 +543,7 @@ Status:
 Item 15:  Implement more Python events and functions
   Date:   28 October 2005
   Origin: Kern
-  Status: 
+  Status: Project abandoned in favor of plugins.
 
   What:   Allow Python scripts to be called at more places 
           within Bacula and provide additional access to Bacula
@@ -852,7 +855,73 @@ Item 25:  Archival (removal) of User Files to Tape
           storage pool gets full) data is migrated to Tape.
 
 
+Item 26: Store and restore extended attributes, especially selinux file contexts
+   Date: 28 December 2007
+   Origin: Frank Sweetser <fs@wpi.edu>
+   Status: Done
+   What: The ability to store and restore extended attributes on
+         filesystems that support them, such as ext3.
 
+   Why: Security Enhanced Linux (SELinux) enabled systems make extensive
+        use of extended attributes.  In addition to the standard user,
+        group, and permission, each file has an associated SELinux context
+        stored as an extended attribute.  This context is used to define
+        which operations a given program is permitted to perform on that
+        file.  Storing contexts on an SELinux system is as critical as
+        storing ownership and permissions.  In the case of a full system
+        restore, the system will not even be able to boot until all
+        critical system files have been properly relabeled.
+
+ Notes: Fedora ships with a version of tar that has been patched to handle
+        extended attributes.  The patch has not been integrated upstream
+        yet, so could serve as a good starting point.
+
+        http://linux.die.net/man/2/getxattr
+        http://linux.die.net/man/2/setxattr
+        http://linux.die.net/man/2/listxattr
+        ===
+        http://linux.die.net/man/3/getfilecon
+        http://linux.die.net/man/3/setfilecon
+
+Item 27:  make changing "spooldata=yes|no" possible for
+          manual/interactive jobs
+  Origin: Marc Schiffbauer <marc@schiffbauer.net>
+  Date:   12 April 2007)
+  Status: Done
+
+  What:   Make it possible to modify the spooldata option
+          for a job when being run from within the console.
+          Currently it is possible to modify the backup level
+          and the spooldata setting in a Schedule resource.
+          It is also possible to modify the backup level when using
+          the "run" command in the console. 
+          But it is currently not possible to to the same 
+          with "spooldata=yes|no" like:
+
+          run job=MyJob level=incremental spooldata=yes
+
+  Why:    In some situations it would be handy to be able to switch
+          spooldata on or off for interactive/manual jobs based on
+          which data the admin expects or how fast the LAN/WAN
+          connection currently is.
+
+  Notes:  ./.
+
+Item 28:  Implement an option to modify the last written date for volumes
+Date:     16 September 2008
+Origin:   Franck (xeoslaenor at gmail dot com)
+Status:   Done
+What:     The ability to modify the last written date for a volume
+Why:      It's sometime necessary to jump a volume when you have a pool of volume
+          which recycles the oldest volume at each backup.
+          Sometime, it needs to cancel a set of backup (one day
+          backup, completely) and we want to avoid that bacula
+          choose the volume (which is not written at all) from
+          the cancelled backup (It has to jump to next volume).
+          in this case, we just need to update the written date
+          manually to avoir the "oldest volume" purge.
+Notes:    An option can be add to "update volume" command (like 'written date'
+          choice for example)
 
 
 ========= New Items since the last vote =================
@@ -933,32 +1002,6 @@ Item 1:   Implement an interface between Bacula and Amazon's S3.
           locally and syncing them to S3, and manually fetching them
           again when they're needed. This is very cumbersome.
 
-Item: Store and restore extended attributes, especially selinux file contexts
-   Date: 28 December 2007
-   Origin: Frank Sweetser <fs@wpi.edu>
-   What: The ability to store and restore extended attributes on
-         filesystems that support them, such as ext3.
-
-   Why: Security Enhanced Linux (SELinux) enabled systems make extensive
-        use of extended attributes.  In addition to the standard user,
-        group, and permission, each file has an associated SELinux context
-        stored as an extended attribute.  This context is used to define
-        which operations a given program is permitted to perform on that
-        file.  Storing contexts on an SELinux system is as critical as
-        storing ownership and permissions.  In the case of a full system
-        restore, the system will not even be able to boot until all
-        critical system files have been properly relabeled.
-
- Notes: Fedora ships with a version of tar that has been patched to handle
-        extended attributes.  The patch has not been integrated upstream
-        yet, so could serve as a good starting point.
-
-        http://linux.die.net/man/2/getxattr
-        http://linux.die.net/man/2/setxattr
-        http://linux.die.net/man/2/listxattr
-        ===
-        http://linux.die.net/man/3/getfilecon
-        http://linux.die.net/man/3/setfilecon
 
 Item 1:   enable/disable compression depending on storage device (disk/tape)
   Origin: Ralf Gross ralf-lists@ralfgross.de
@@ -1147,45 +1190,6 @@ Item X:   Add EFS support on Windows
                                                                                                                                                                                               encrypted-file-related callback functions.
 ========== Already implemented ================================
 
-Item  n:  make changing "spooldata=yes|no" possible for
-          manual/interactive jobs
-  Origin: Marc Schiffbauer <marc@schiffbauer.net>
-  Date:   12 April 2007)
-  Status: 
-
-  What:   Make it possible to modify the spooldata option
-          for a job when being run from within the console.
-          Currently it is possible to modify the backup level
-          and the spooldata setting in a Schedule resource.
-          It is also possible to modify the backup level when using
-          the "run" command in the console. 
-          But it is currently not possible to to the same 
-          with "spooldata=yes|no" like:
-
-          run job=MyJob level=incremental spooldata=yes
-
-  Why:    In some situations it would be handy to be able to switch
-          spooldata on or off for interactive/manual jobs based on
-          which data the admin expects or how fast the LAN/WAN
-          connection currently is.
-
-  Notes:  ./.
-
-Item 1:   Implement an option to modify the last written date for volumes
-Date:     16 September 2008
-Origin:   Franck (xeoslaenor at gmail dot com)
-Status:   Proposing
-What:     The ability to modify the last written date for a volume
-Why:      It's sometime necessary to jump a volume when you have a pool of volume
-          which recycles the oldest volume at each backup.
-          Sometime, it needs to cancel a set of backup (one day
-          backup, completely) and we want to avoid that bacula
-          choose the volume (which is not written at all) from
-          the cancelled backup (It has to jump to next volume).
-          in this case, we just need to update the written date
-          manually to avoir the "oldest volume" purge.
-Notes:    An option can be add to "update volume" command (like 'written date'
-          choice for example)
 
 ============= Empty Feature Request form ===========
 Item  n:  One line summary ...
index ea975865016cdd6e29f961fe8d921c1370de13b8..16d6832e103ec0c0be669b94978ea68c539024ed 100644 (file)
@@ -199,7 +199,7 @@ void InitWinAPIWrapper();
 #define DEFAULT_NETWORK_BUFFER_SIZE (64 * 1024)
 
 /*
- * Stream definitions.  Once defined these must NEVER
+ * Stream definitions. Once defined these must NEVER
  *   change as they go on the storage media.
  * Note, the following streams are passed from the SD to the DIR
  *   so that they may be put into the catalog (actually only the
@@ -218,10 +218,9 @@ void InitWinAPIWrapper();
 #define STREAM_MD5_SIGNATURE               3    /* deprecated */
 #define STREAM_MD5_DIGEST                  3    /* MD5 digest for the file */
 #define STREAM_GZIP_DATA                   4    /* GZip compressed file data */
-/* Extended Unix attributes with Win32 Extended data.  Deprecated. */
-#define STREAM_UNIX_ATTRIBUTES_EX          5    /* Extended Unix attr for Win32 EX */
+#define STREAM_UNIX_ATTRIBUTES_EX          5    /* Extended Unix attr for Win32 EX - Deprecated */
 #define STREAM_SPARSE_DATA                 6    /* Sparse data stream */
-#define STREAM_SPARSE_GZIP_DATA            7
+#define STREAM_SPARSE_GZIP_DATA            7    /* Sparse gzipped data stream */
 #define STREAM_PROGRAM_NAMES               8    /* program names for program data */
 #define STREAM_PROGRAM_DATA                9    /* Data needing program */
 #define STREAM_SHA1_SIGNATURE             10    /* deprecated */
@@ -230,22 +229,75 @@ void InitWinAPIWrapper();
 #define STREAM_WIN32_GZIP_DATA            12    /* Gzipped Win32 BackupRead data */
 #define STREAM_MACOS_FORK_DATA            13    /* Mac resource fork */
 #define STREAM_HFSPLUS_ATTRIBUTES         14    /* Mac OS extra attributes */
-/*** FIXME ***/
-#define STREAM_UNIX_ACCESS_ACL            15   /* Standard ACL attributes on UNIX */
-#define STREAM_UNIX_DEFAULT_ACL           16   /* Default ACL attributes on UNIX */
-/*** FIXME ***/
-#define STREAM_SHA256_DIGEST              17   /* SHA-256 digest for the file */
-#define STREAM_SHA512_DIGEST              18   /* SHA-512 digest for the file */
-#define STREAM_SIGNED_DIGEST              19   /* Signed File Digest, ASN.1, DER Encoded */
-#define STREAM_ENCRYPTED_FILE_DATA        20   /* Encrypted, uncompressed data */
-#define STREAM_ENCRYPTED_WIN32_DATA       21   /* Encrypted, uncompressed Win32 BackupRead data */
-#define STREAM_ENCRYPTED_SESSION_DATA     22   /* Encrypted Session Data, ASN.1, DER Encoded */
-#define STREAM_ENCRYPTED_FILE_GZIP_DATA   23   /* Encrypted, compressed data */
-#define STREAM_ENCRYPTED_WIN32_GZIP_DATA  24   /* Encrypted, compressed Win32 BackupRead data */
-#define STREAM_ENCRYPTED_MACOS_FORK_DATA  25   /* Encrypted, uncompressed Mac resource fork */
-#define STREAM_PLUGIN_NAME                26   /* Plugin "file" string */
-#define STREAM_PLUGIN_DATA                27   /* Plugin specific data */
+#define STREAM_UNIX_ACCESS_ACL            15    /* Standard ACL attributes on UNIX - Deprecated */
+#define STREAM_UNIX_DEFAULT_ACL           16    /* Default ACL attributes on UNIX - Deprecated */
+#define STREAM_SHA256_DIGEST              17    /* SHA-256 digest for the file */
+#define STREAM_SHA512_DIGEST              18    /* SHA-512 digest for the file */
+#define STREAM_SIGNED_DIGEST              19    /* Signed File Digest, ASN.1, DER Encoded */
+#define STREAM_ENCRYPTED_FILE_DATA        20    /* Encrypted, uncompressed data */
+#define STREAM_ENCRYPTED_WIN32_DATA       21    /* Encrypted, uncompressed Win32 BackupRead data */
+#define STREAM_ENCRYPTED_SESSION_DATA     22    /* Encrypted Session Data, ASN.1, DER Encoded */
+#define STREAM_ENCRYPTED_FILE_GZIP_DATA   23    /* Encrypted, compressed data */
+#define STREAM_ENCRYPTED_WIN32_GZIP_DATA  24    /* Encrypted, compressed Win32 BackupRead data */
+#define STREAM_ENCRYPTED_MACOS_FORK_DATA  25    /* Encrypted, uncompressed Mac resource fork */
+#define STREAM_PLUGIN_NAME                26    /* Plugin "file" string */
+#define STREAM_PLUGIN_DATA                27    /* Plugin specific data */
 
+/*
+ * Additional Stream definitions. Once defined these must NEVER
+ *   change as they go on the storage media.
+ *
+ * The Stream numbers from 1000-1999 are reserved for ACL and extended attribute streams.
+ * Each different platform has its own stream id(s), if a platform supports multiple stream types
+ * it should supply different handlers for each type it supports and this should be called
+ * from the stream dispatch function. Currently in this reserved space we allocate the
+ * different acl streams from 1000 on and the different extended attributes streams from
+ * 1999 down. So the two naming spaces grows towards each other.
+ */
+#define STREAM_ACL_AIX_TEXT                1000    /* AIX specific string representation from acl_get */
+#define STREAM_ACL_DARWIN_ACCESS_ACL_T     1001    /* Darwin (OSX) specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl)
+                                                    */
+#define STREAM_ACL_FREEBSD_DEFAULT_ACL_T   1002    /* FreeBSD specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for default acls.
+                                                    */
+#define STREAM_ACL_FREEBSD_ACCESS_ACL_T    1003    /* FreeBSD specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for access acls.
+                                                    */
+#define STREAM_ACL_HPUX_ACL_ENTRY          1004    /* HPUX specific acl_entry string representation
+                                                    * from acltostr (POSIX acl)
+                                                    */
+#define STREAM_ACL_IRIX_DEFAULT_ACL_T      1005    /* IRIX specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for default acls.
+                                                    */
+#define STREAM_ACL_IRIX_ACCESS_ACL_T       1006    /* IRIX specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for access acls.
+                                                    */
+#define STREAM_ACL_LINUX_DEFAULT_ACL_T     1007    /* Linux specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for default acls.
+                                                    */
+#define STREAM_ACL_LINUX_ACCESS_ACL_T      1008    /* Linux specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for access acls.
+                                                    */
+#define STREAM_ACL_TRU64_DEFAULT_ACL_T     1009    /* Tru64 specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for default acls.
+                                                    */
+#define STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T 1010    /* Tru64 specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for default acls.
+                                                    */
+#define STREAM_ACL_TRU64_ACCESS_ACL_T      1011    /* Tru64 specific acl_t string representation
+                                                    * from acl_to_text (POSIX acl) for access acls.
+                                                    */
+#define STREAM_ACL_SOLARIS_ACLENT_T        1012    /* Solaris specific aclent_t string representation
+                                                    * from acltotext or acl_totext (POSIX acl)
+                                                    */
+#define STREAM_ACL_SOLARIS_ACE_T           1013    /* Solaris specific ace_t string representation from
+                                                    * from acl_totext (NFSv4 or ZFS acl)
+                                                    */
+#define STREAM_XATTR_DARWIN                1996    /* Darwin (OSX) specific extended attributes */
+#define STREAM_XATTR_FREEBSD               1997    /* FreeBSD specific extended attributes */
+#define STREAM_XATTR_LINUX                 1998    /* Linux specific extended attributes */
+#define STREAM_XATTR_NETBSD                1999    /* NetBSD specific extended attributes */
 
 /*
  *  File type (Bacula defined).
index c8a7dfa2a4d994afa274914a2b00c4551b92fed8..5df66b1ac029cbc66ae314275b8c7ad5acf6eb06 100644 (file)
@@ -128,6 +128,7 @@ static RES_ITEM options_items[] = {
    {"checkfilechanges",store_opts,    {0},     0, 0, 1},
    {"strippath",       store_opts,    {0},     0, 0, 0},
    {"honornodumpflag", store_opts,    {0},     0, 0, 0},
+   {"xattrsupport",    store_opts,    {0},     0, 0, 0},
    {NULL, NULL, {0}, 0, 0, 0}
 };
 
@@ -157,7 +158,8 @@ enum {
    INC_KW_ENHANCEDWILD,
    INC_KW_CHKCHANGES,
    INC_KW_STRIPPATH,
-   INC_KW_HONOR_NODUMP
+   INC_KW_HONOR_NODUMP,
+   INC_KW_XATTR
 };
 
 /*
@@ -188,8 +190,9 @@ static struct s_kw FS_option_kw[] = {
    {"noatime",     INC_KW_NOATIME},
    {"enhancedwild", INC_KW_ENHANCEDWILD},
    {"checkfilechanges", INC_KW_CHKCHANGES},
-   {"strippath",    INC_KW_STRIPPATH},
-   {"honornodumpflag",    INC_KW_HONOR_NODUMP},
+   {"strippath",   INC_KW_STRIPPATH},
+   {"honornodumpflag", INC_KW_HONOR_NODUMP},
+   {"xattrsupport", INC_KW_XATTR},
    {NULL,          0}
 };
 
@@ -259,6 +262,8 @@ static struct s_fs_opt FS_options[] = {
    {"no",       INC_KW_CHKCHANGES,    "0"},
    {"yes",      INC_KW_HONOR_NODUMP,  "N"},
    {"no",       INC_KW_HONOR_NODUMP,  "0"},
+   {"yes",      INC_KW_XATTR,         "X"},
+   {"no",       INC_KW_XATTR,         "0"},
    {NULL,       0,                      0}
 };
 
index 00340456354fe8f3e18ce940f01f9d6d2796a2dc..a69df1f016f62bdd0ca05ad998d790f465e15d3a 100644 (file)
@@ -31,7 +31,7 @@ dummy:
 SVRSRCS = filed.c authenticate.c acl.c backup.c estimate.c \
          fd_plugins.c accurate.c \
          filed_conf.c heartbeat.c job.c pythonfd.c \
-         restore.c status.c verify.c verify_vol.c
+         restore.c status.c verify.c verify_vol.c xattr.c
 SVROBJS = $(SVRSRCS:.c=.o)
 
 # these are the objects that are changed by the .configure process
index a9a61449d17aaff93ac535f32b65d574012484c5..3f2303f6df851f11c31cfd2a816427a8436be86d 100644 (file)
  */
 #if !defined(HAVE_ACL)              /* ACL support is required, of course */ \
    || !( defined(HAVE_AIX_OS)       /* man page -- may need flags         */ \
-      || defined(HAVE_FREEBSD_OS)   /* tested   -- compile without 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_OSF1_OS)      /* man page -- may need -lpacl        */ \
       || defined(HAVE_LINUX_OS)     /* tested   -- compile with -lacl     */ \
-      || defined(HAVE_HPUX_OS)      /* man page -- may need flags         */ \
+      || defined(HAVE_OSF1_OS)      /* man page -- may need -lpacl        */ \
       || defined(HAVE_SUN_OS)       /* tested   -- compile with -lsec     */ \
        )
+
 /*
- * ***FIXME***
- * For now we abandon this test and only test for Linux:
- * 1. This is backwards compatible.
- * 2. If we allow any of the other now, we may have to provide conversion
- *    routines if we ever want to distinguish them. Or just do our best
- *    with what we have and give all ACL streams a new number/type.
+ * Entry points when compiled without support for ACLs or on an unsupported platform.
  */
-#endif
-
-#if !defined(HAVE_ACL) \
-   || !( defined(HAVE_LINUX_OS) \
-      || defined(HAVE_FREEBSD_OS) \
-      || defined(HAVE_DARWIN_OS) \
-      || defined(HAVE_IRIX_OS) \
-      || defined(HAVE_OSF1_OS) \
-      || defined(HAVE_SUN_OS) \
-       )
-
-/* bacl_get() returns the lenght of the string, or -1 on error. */
-int bacl_get(JCR *jcr, int acltype)
+bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
    Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
-   return -1;
+   return false;
 }
 
-int bacl_set(JCR *jcr, int acltype)
+bool parse_acl_stream(JCR *jcr, int stream)
 {
    Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
-   return -1;
+   return false;
+}
+
+#else
+
+/*
+ * Send an ACL stream to the SD.
+ */
+static bool send_acl_stream(JCR *jcr, int stream, int len)
+{
+   BSOCK *sd = jcr->store_bsock;
+   POOLMEM *msgsave;
+#ifdef FD_NO_SEND_TEST
+   return true;
+#endif
+
+   /*
+    * 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;
+   }
+
+   /*
+    * Send the buffer to the storage deamon
+    */
+   Dmsg1(400, "Backing up ACL <%s>\n", jcr->acl_data);
+   msgsave = sd->msg;
+   sd->msg = jcr->acl_data;
+   sd->msglen = len + 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());
+
+      return false;
+   }
+
+   jcr->JobBytes += sd->msglen;
+   sd->msg = msgsave;
+   if (!sd->signal(BNET_EOD)) {
+      Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+            sd->bstrerror());
+
+      return false;
+   }
+
+   Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
+
+   return true;
 }
 
-#elif defined(HAVE_AIX_OS)
+#if defined(HAVE_AIX_OS)
 
 #include <sys/access.h>
 
-int bacl_get(JCR *jcr, int acltype)
+static bool aix_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
    char *acl_text;
    int len;
 
    if ((acl_text = acl_get(jcr->last_fname)) != NULL) {
-      len = pm_strcpy(jcr->acl_text, acl_text);
+      len = pm_strcpy(jcr->acl_data, acl_text);
       actuallyfree(acl_text);
-      return len;
+
+      return send_acl_stream(jcr, STREAM_ACL_AIX_TEXT, len);
    }
-   return -1;
+
+   return false;
 }
 
-int bacl_set(JCR *jcr, int acltype)
+static bool aix_parse_acl_stream(JCR *jcr, int stream)
 {
-   if (acl_put(jcr->last_fname, jcr->acl_text, 0) != 0) {
-      return -1;
+   if (acl_put(jcr->last_fname, jcr->acl_data, 0) != 0) {
+      return false;
    }
-   return 0;
+
+   return true;
 }
 
-#elif defined(HAVE_FREEBSD_OS) \
-   || defined(HAVE_DARWIN_OS) \
+#elif defined(HAVE_DARWIN_OS) \
+   || defined(HAVE_FREEBSD_OS) \
    || defined(HAVE_IRIX_OS) \
    || defined(HAVE_OSF1_OS) \
    || defined(HAVE_LINUX_OS)
 
 #include <sys/types.h>
+
+#ifdef HAVE_SYS_ACL_H
 #include <sys/acl.h>
+#else
+#error "configure failed to detect availability of sys/acl.h"
+#endif
 
 /* On IRIX we can get shortened ACLs */
 #if defined(HAVE_IRIX_OS) && defined(BACL_WANT_SHORT_ACLS)
@@ -165,15 +210,157 @@ int bacl_set(JCR *jcr, int acltype)
 #endif
 #endif
 
-int bacl_get(JCR *jcr, int acltype)
+/*
+ * Some generic functions used by multiple OSes.
+ */
+static acl_type_t bac_to_os_acltype(bacl_type acltype)
+{
+   acl_type_t ostype;
+
+   switch (acltype) {
+   case BACL_TYPE_ACCESS:
+      ostype = ACL_TYPE_ACCESS;
+      break;
+   case BACL_TYPE_DEFAULT:
+      ostype = ACL_TYPE_DEFAULT;
+      break;
+
+#ifdef ACL_TYPE_DEFAULT_DIR
+   case BACL_TYPE_DEFAULT_DIR:
+      /*
+       * OSF1 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:
+      /*
+       * 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
+       * types supported on a certain platform.
+       */
+      ostype = ACL_TYPE_NONE;
+      break;
+   }
+
+   return ostype;
+}
+
+/*
+ * 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.
+ */
+#if defined(HAVE_DARWIN_OS)
+static bool acl_is_trivial(acl_t acl)
+{
+   /*
+    * acl is trivial if it is empty.
+    */
+   return (acl_entries(acl) == 0);
+}
+#else /* FreeBSD, IRIX, OSF1, Linux */
+static bool acl_is_trivial(acl_t acl)
+{
+  /*
+   * acl is trivial if it has only the following entries:
+   * "user::",
+   * "group::",
+   * "other::"
+   */
+   acl_entry_t ace;
+   acl_tag_t tag;
+#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) {
+      /*
+       * 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;
+
+      /*
+       * 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);
+   }
+
+   return true;
+#elif defined(HAVE_IRIX_OS)
+   int n;
+
+   for (n = 0; n < acl->acl_cnt; n++) {
+      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 &&
+          tag != ACL_OTHER)
+         return false;
+   }
+
+   return true;
+#elif defined(HAVE_OSF1_OS)
+   int count;
+
+   ace = acl->acl_first;
+   count = acl->acl_num;
+
+   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;
+
+      /*
+       * 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--;
+   }
+
+   return true;
+#endif
+}
+#endif
+
+/*
+ * Generic wrapper around acl_get_file call.
+ */
+static int generic_get_acl_from_os(JCR *jcr, bacl_type acltype)
 {
    acl_t acl;
    int len;
    acl_type_t ostype;
    char *acl_text;
 
-   ostype = (acltype & BACL_TYPE_DEFAULT) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS;
-
+   ostype = bac_to_os_acltype(acltype);
    acl = acl_get_file(jcr->last_fname, ostype);
    if (acl) {
 #if defined(HAVE_IRIX_OS)
@@ -190,59 +377,103 @@ int bacl_get(JCR *jcr, int acltype)
        * to acl_to_text() besides.
        */
       if (acl->acl_cnt <= 0) {
-        acl_free(acl);
+         pm_strcpy(jcr->acl_data, "");
+         acl_free(acl);
          return 0;
       }
 #endif
+
+      /*
+       * Make sure this is not just a trivial ACL.
+       */
+      if ((acltype == BACL_TYPE_ACCESS ||
+           acltype == BACL_TYPE_EXTENDED) &&
+           acl_is_trivial(acl)) {
+         /*
+          * 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, "");
+         acl_free(acl);
+         return 0;
+      }
+
       if ((acl_text = acl_to_text(acl, NULL)) != NULL) {
-         len = pm_strcpy(jcr->acl_text, acl_text);
+         len = pm_strcpy(jcr->acl_data, acl_text);
          acl_free(acl);
          acl_free(acl_text);
+
          return len;
       }
+
       berrno be;
       Jmsg2(jcr, M_ERROR, 0, _("acl_to_text error on file \"%s\": ERR=%s\n"),
          jcr->last_fname, be.bstrerror());
-      Dmsg3(100, "acl_to_text error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
+      Dmsg2(100, "acl_to_text error file=%s ERR=%s\n",  
+         jcr->last_fname, be.bstrerror());
+
+      pm_strcpy(jcr->acl_data, "");
       acl_free(acl);
-#ifndef HAVE_OSF1_OS          /* BACL_ENOTSUP not defined for OSF1 */
-   } else if (errno == BACL_ENOTSUP) {
-      /* Not supported, just pretend there is nothing to see */
-      return pm_strcpy(jcr->acl_text, "");
+
+      return -1;
+   }
+
+   /*
+    * Handle errors gracefully.
+    */
+   switch (errno) {
+#if defined(BACL_ENOTSUP)
+   case BACL_ENOTSUP:
+      /*
+       * Not supported, just pretend there is nothing to see
+       */
+      pm_strcpy(jcr->acl_data, "");
+      return 0;
 #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;
    }
-   /***** Do we really want to silently ignore errors from acl_get_file
-     and acl_to_text?  *****/
-   return 0;
 }
 
-int bacl_set(JCR *jcr, int acltype)
+/*
+ * Generic wrapper around acl_set_file call.
+ */
+static bool generic_set_acl_on_os(JCR *jcr, bacl_type acltype)
 {
    acl_t acl;
    acl_type_t ostype;
 
-   ostype = (acltype & BACL_TYPE_DEFAULT) ? ACL_TYPE_DEFAULT : ACL_TYPE_ACCESS;
-
-   /* If we get empty default ACLs, clear ACLs now */
-   if (ostype == ACL_TYPE_DEFAULT && strlen(jcr->acl_text) == 0) {
+   /*
+    * 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 (acl_delete_def_file(jcr->last_fname) == 0) {
-         return 0;
+         return true;
       }
       berrno be;
       Jmsg2(jcr, M_ERROR, 0, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"),
          jcr->last_fname, be.bstrerror());
-      return -1;
+
+      return false;
    }
 
-   acl = acl_from_text(jcr->acl_text);
+   acl = acl_from_text(jcr->acl_data);
    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());
       Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
-      return -1;
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
+
+      return false;
    }
 
    /*
@@ -255,100 +486,450 @@ int bacl_set(JCR *jcr, int acltype)
       Jmsg2(jcr, M_ERROR, 0, _("ac_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",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
       acl_free(acl);
-      return -1;
+
+      return false;
    }
 #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) {
       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_text, jcr->last_fname, be.bstrerror());
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
       acl_free(acl);
-      return -1;
+
+      return false;
    }
    acl_free(acl);
-   return 0;
+
+   return true;
+}
+
+/*
+ * 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;
+
+#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
+    * these two useless calls.  The real ACL is retrieved through
+    * acl_get_file (name, ACL_TYPE_EXTENDED).
+    *
+    * Read access ACLs for files, dirs and links
+    */
+   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_EXTENDED)) < 0)
+      return false;
+#else
+   /*
+    * Read access ACLs for files, dirs and links
+    */
+   if ((len = generic_get_acl_from_os(jcr, BACL_TYPE_ACCESS)) < 0)
+      return false;
+#endif
+
+   if (len > 0) {
+      if (!send_acl_stream(jcr, STREAM_ACL_DARWIN_ACCESS_ACL_T, len))
+         return false;
+   }
+
+   return true;
+}
+
+static bool darwin_parse_acl_stream(JCR *jcr, int stream)
+{
+   switch (stream) {
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_ACL_DARWIN_ACCESS_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
+   }
+
+   return false;
+}
+#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_T, 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_T, len))
+            return false;
+      }
+   }
+
+   return true;
+}
+
+static bool freebsd_parse_acl_stream(JCR *jcr, int stream)
+{
+   switch (stream) {
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_ACL_FREEBSD_ACCESS_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
+   case STREAM_UNIX_DEFAULT_ACL:
+   case STREAM_ACL_FREEBSD_DEFAULT_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
+   }
+
+   return false;
+}
+#elif defined(HAVE_IRIX_OS)
+static bool irix_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_IRIX_ACCESS_ACL_T, 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_IRIX_DEFAULT_ACL_T, len))
+            return false;
+      }
+   }
+
+   return true;
+}
+
+static bool irix_parse_acl_stream(JCR *jcr, int stream)
+{
+   switch (stream) {
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_ACL_IRIX_ACCESS_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
+   case STREAM_UNIX_DEFAULT_ACL:
+   case STREAM_ACL_IRIX_DEFAULT_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
+   }
+
+   return false;
+}
+#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_T, 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_T, len))
+            return false;
+      }
+   }
+
+   return true;
+}
+
+static bool linux_parse_acl_stream(JCR *jcr, int stream)
+{
+   switch (stream) {
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_ACL_LINUX_ACCESS_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
+   case STREAM_UNIX_DEFAULT_ACL:
+   case STREAM_ACL_LINUX_DEFAULT_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
+   }
+
+   return false;
+}
+#elif defined(HAVE_OSF1_OS)
+static bool tru64_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_TRU64_ACCESS_ACL_T, 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_TRU64_DEFAULT_ACL_T, len))
+            return false;
+      }
+
+      /*
+       * 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_T, len))
+            return false;
+      }
+   }
+
+   return true;
 }
 
+static bool tru64_parse_acl_stream(JCR *jcr, int stream)
+{
+   switch (stream) {
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_ACL_TRU64_ACCESS_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_ACCESS);
+   case STREAM_UNIX_DEFAULT_ACL:
+   case STREAM_ACL_TRU64_DEFAULT_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT);
+   case STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T:
+      return generic_set_acl_on_os(jcr, BACL_TYPE_DEFAULT_DIR);
+}
+#endif
+
 #elif defined(HAVE_HPUX_OS)
+#ifdef HAVE_SYS_ACL_H
 #include <sys/acl.h>
+#else
+#error "configure failed to detect availability of sys/acl.h"
+#endif
+
 #include <acllib.h>
 
-int bacl_get(JCR *jcr, int acltype)
+/*
+ * 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(int count, struct acl_entry *entries, struct stat sb)
+{
+   int n;
+   struct acl_entry ace
+
+   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) ||
+            (ace.uid == ACL_NSUSER && ace.gid == sb.st_gid) ||
+            (ace.uid == ACL_NSUSER && ace.gid == ACL_NSGROUP)))
+         return false;
+   }
+
+   return true;
+}
+
+/*
+ * OS specific functions for handling different types of acl streams.
+ */
+static bool hpux_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
    int n, len;
    struct acl_entry acls[NACLENTRIES];
    char *acl_text;
 
-   if ((n = getacl(jcr->last_fname, 0, acls)) <= 0) {
-      if (errno == BACL_ENOTSUP) {
-         return pm_strcpy(jcr->acl_text, "");
+   if ((n = getacl(jcr->last_fname, 0, acls)) < 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
+      default:
+         berrno be;
+         Jmsg2(jcr, M_ERROR, 0, _("getacl error on file \"%s\": ERR=%s\n"),
+            jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "getacl error file=%s ERR=%s\n",  
+            jcr->last_fname, be.bstrerror());
+
+         pm_strcpy(jcr->acl_data, "");
+         return false;
       }
-      return -1;
    }
+
+   if (n == 0) {
+      pm_strcpy(jcr->acl_data, "");
+      return true;
+   }
+
    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.
+          */
+         pm_strcpy(jcr->acl_data, "");
+         return true;
+      }
+
       if ((acl_text = acltostr(n, acls, FORM_SHORT)) != NULL) {
-         len = pm_strcpy(jcr->acl_text, acl_text);
+         len = pm_strcpy(jcr->acl_data, acl_text);
          actuallyfree(acl_text);
-         return len;
+
+         return send_acl_stream(jcr, STREAM_ACL_HPUX_ACL_ENTRY, len);
       }
+
       berrno be;
       Jmsg2(jcr, M_ERROR, 0, _("acltostr error on file \"%s\": ERR=%s\n"),
          jcr->last_fname, be.bstrerror());
       Dmsg3(100, "acltostr error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
-      return -1;
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
+
+      return false;
    }
-   return -1;
+
+   return false;
 }
 
-int bacl_set(JCR *jcr, int acltype)
+static bool hpux_parse_acl_stream(JCR *jcr, int stream)
 {
    int n, stat;
    struct acl_entry acls[NACLENTRIES];
 
-   n = strtoacl(jcr->acl_text, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
+   n = strtoacl(jcr->acl_data, 0, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP);
    if (n <= 0) {
       berrno be;
       Jmsg2(jcr, M_ERROR, 0, _("strtoacl error on file \"%s\": ERR=%s\n"),
          jcr->last_fname, be.bstrerror());
       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
-      return -1;
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
+
+      return false;
    }
-   if (strtoacl(jcr->acl_text, n, NACLENTRIES, acls, ACL_FILEOWNER, ACL_FILEGROUP) != n) {
+   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());
       Dmsg3(100, "strtoacl error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
-      return -1;
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
+
+      return false;
    }
    /*
     * 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_text, jcr->last_fname, be.bstrerror());
-      return -1;
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
+
+      return false;
    }
-   return 0;
+
+   return true;
 }
 
 #elif defined(HAVE_SUN_OS)
+#ifdef HAVE_SYS_ACL_H
 #include <sys/acl.h>
+#else
+#error "configure failed to detect availability of sys/acl.h"
+#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
+ * propper 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.
+ */
+#if !defined(_SYS_ACL_IMPL_H)
+typedef enum acl_type {
+   ACLENT_T = 0,
+   ACE_T = 1
+} acl_type_t;
+#endif
+
+/*
+ * Two external references to functions in the libsec library function not in current include files.
+ */
+extern "C" {
+int acl_type(acl_t *);
+char *acl_strerror(int);
+}
 
 /*
  * As the new libsec interface with acl_totext and acl_fromtext also handles
@@ -356,22 +937,43 @@ int bacl_set(JCR *jcr, int acltype)
  * 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)
  */
-#if defined(HAVE_EXTENDED_ACL)
-int bacl_get(JCR *jcr, int acltype)
+static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
    int len, flags;
    acl_t *aclp;
    char *acl_text;
+   bool stream_status = false;
 
    /*
     * 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)
-      return -1;
+   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
+      default:
+         Jmsg2(jcr, M_ERROR, 0, _("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",  
+            jcr->last_fname, acl_strerror(errno));
+
+         return false;
+      }
+   }
 
    if (aclp == NULL) {
-      /* The ACLs simply reflect the (already known) standard permissions */
-      return pm_strcpy(jcr->acl_text, "");
+      /*
+       * 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;
    }
 
 #if defined(ACL_SID_FMT)
@@ -384,60 +986,117 @@ int bacl_get(JCR *jcr, int acltype)
 #endif /* ACL_SID_FMT */
 
    if ((acl_text = acl_totext(aclp, flags)) != NULL) {
-      len = pm_strcpy(jcr->acl_text, acl_text);
+      len = pm_strcpy(jcr->acl_data, acl_text);
       actuallyfree(acl_text);
 
-      acl_free(aclp);
+      switch (acl_type(aclp)) {
+      case ACLENT_T:
+         stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT_T, len);
+         break;
+      case ACE_T:
+         stream_status = send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACE_T, len);
+         break;
+      default:
+         break;
+      }
 
-      return len;
+      acl_free(aclp);
    }
 
-   acl_free(aclp);
-
-   return -1;
-}
-
-/*
- * As the header acl.h doesn't seem to define this one we need to.
- */
-extern "C" {
-char *acl_strerror(int);
+   return stream_status;
 }
 
-int bacl_set(JCR *jcr, int acltype)
+static bool solaris_parse_acl_stream(JCR *jcr, int stream)
 {
    acl_t *aclp;
    int error;
 
-   if ((error = acl_fromtext(jcr->acl_text, &aclp)) != 0) {
-      Jmsg2(jcr, M_ERROR, 0, _("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",  
-         jcr->acl_text, jcr->last_fname, acl_strerror(error));
-      return -1;
-   }
+   switch (stream) {
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_ACL_SOLARIS_ACLENT_T:
+   case STREAM_ACL_SOLARIS_ACE_T:
+      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));
+         Dmsg3(100, "acl_fromtext error acl=%s file=%s ERR=%s\n",  
+            jcr->acl_data, jcr->last_fname, acl_strerror(error));
+         return false;
+      }
 
-   /*
-    * 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 ((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_text, jcr->last_fname, acl_strerror(error));
+      /*
+       * Validate that the conversion gave us the correct acl type.
+       */
+      switch (stream) {
+      case STREAM_ACL_SOLARIS_ACLENT_T:
+         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;
+         }
+      case STREAM_ACL_SOLARIS_ACE_T:
+         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;
+         }
+      default:
+         /*
+          * Stream id which doesn't describe the type of acl which is encoded.
+          */
+         break;
+      }
 
-      acl_free(aclp);
-      return -1;
-   }
+      /*
+       * 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;
+      }
 
-   acl_free(aclp);
-   return 0;
+      acl_free(aclp);
+      return true;
+   default:
+      return false;
+   } /* end switch (stream) */
 }
 
 #else /* HAVE_EXTENDED_ACL */
 
-int bacl_get(JCR *jcr, int acltype)
+/*
+ * 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(int count, aclent_t *entries)
+{
+   int n;
+   aclent_t *ace;
+
+   for (n = 0; n < count; n++) {
+      ace = &entries[n];
+
+      if (!(ace->a_type == USER_OBJ ||
+            ace->a_type == GROUP_OBJ ||
+            ace->a_type == OTHER_OBJ ||
+            ace->a_type == CLASS_OBJ))
+        return false;
+   }
+
+   return true;
+}
+
+/*
+ * OS specific functions for handling different types of acl streams.
+ */
+static bool solaris_build_acl_streams(JCR *jcr, FF_PKT *ff_pkt);
 {
    int n, len;
    aclent_t *acls;
@@ -445,45 +1104,55 @@ int bacl_get(JCR *jcr, int acltype)
 
    n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
    if (n < MIN_ACL_ENTRIES) {
-      return -1;
-   } else if (n == MIN_ACL_ENTRIES) {
-      /* The ACLs simply reflect the (already known) standard permissions */
-      return pm_strcpy(jcr->acl_text, "");
-   }
-   if ((acls = (aclent_t *)malloc(n * sizeof(aclent_t))) == NULL) {
-      return -1;
-   }
+      return false;
+
+   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);
+         pm_strcpy(jcr->acl_data, "");
+         return true;
+      }
+
       if ((acl_text = acltotext(acls, n)) != NULL) {
-         len = pm_strcpy(jcr->acl_text, acl_text);
+         len = pm_strcpy(jcr->acl_data, acl_text);
          actuallyfree(acl_text);
          free(acls);
-         return len;
+
+         return send_acl_stream(jcr, STREAM_ACL_SOLARIS_ACLENT_T, len);
       }
+
       berrno be;
       Jmsg2(jcr, M_ERROR, 0, _("acltotext error on file \"%s\": ERR=%s\n"),
          jcr->last_fname, be.bstrerror());
       Dmsg3(100, "acltotext error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
    }
+
    free(acls);
-   return -1;
+   return false;
 }
 
-int bacl_set(JCR *jcr, int acltype)
+static bool solaris_parse_acl_stream(JCR *jcr, int stream)
 {
    int n;
    aclent_t *acls;
 
-   acls = aclfromtext(jcr->acl_text, &n);
+   acls = aclfromtext(jcr->acl_data, &n);
    if (!acls) {
       berrno be;
       Jmsg2(jcr, M_ERROR, 0, _("aclfromtext error on file \"%s\": ERR=%s\n"),
          jcr->last_fname, be.bstrerror());
       Dmsg3(100, "aclfromtext error acl=%s file=%s ERR=%s\n",  
-         jcr->acl_text, jcr->last_fname, be.bstrerror());
-      return -1;
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
+
+      return false;
    }
+
    /*
     * 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.
@@ -493,213 +1162,116 @@ int bacl_set(JCR *jcr, int acltype)
       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_text, jcr->last_fname, be.bstrerror());
+         jcr->acl_data, jcr->last_fname, be.bstrerror());
       actuallyfree(acls);
-      return -1;
+
+      return false;
    }
+
    actuallyfree(acls);
-   return 0;
+   return true;
 }
 
 #endif /* HAVE_EXTENDED_ACL */
 #endif /* HAVE_SUN_OS */
 
-
-#ifdef TEST_PROGRAM
-
 /*
- * Test program setup 
- *
- * Compile and set up with eg. with eg.
- *
- *    $ cc -DTEST_PROGRAM -DHAVE_SUN_OS -lsec -o acl acl.c
- *    $ ln -s acl aclcp
- *
- * You can then list ACLs with acl and copy them with aclcp.
- *
- * For a list of compiler flags, see the list preceding the big #if below.
+ * Entry points when compiled with support for ACLs on a supported platform.
  */
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include "acl.h"
-
-#define BACLLEN 65535
-#define pm_strcpy(d,s)     (strncpy(d, s, BACLLEN - 1) == NULL ? -1 : (int)strlen(d))
-#define Dmsg0(n,s)         fprintf(stderr, s)
-#define Dmsg1(n,s,a1)      fprintf(stderr, s, a1)
-#define Dmsg2(n,s,a1,a2)   fprintf(stderr, s, a1, a2)
-
-int aclls(char *fname);
-int aclcp(char *src, char *dst);
-
-struct JCRstruct {
-   char *last_fname;
-   char acl_text[BACLLEN];
-};
-typedef struct JCRstruct JCR;
-JCR jcr;
-
-int main(int argc, char **argv)
-{
-   char *prgname;
-   int status = 0;
 
-   if (argc < 1) {
-      Dmsg0(200, "Cannot determine my own name\n");
-      return EXIT_FAILURE;
-   }
-
-   prgname = last_path_separator(argv[0]);
-   if (prgname == NULL || *++prgname == '\0') {
-      prgname = argv[0];
-   }
-   --argc;
-   ++argv;
-
-   /* aclcp "copies" ACLs - set ACLs on destination equal to ACLs on source */
-   if (strcmp(prgname, "aclcp") == 0) {
-      int verbose = 0;
-      if (strcmp(*argv, "-v") == 0) {
-         ++verbose;
-         --argc;
-         ++argv;
-      }
-      if (argc != 2) {
-         Dmsg2(200, "%s: wrong number of arguments\n"
-               "usage:\t%s [-v] source destination\n"
-               "\tCopies ACLs from source to destination.\n"
-               "\tSpecify -v to show ACLs after copy for verification.\n",
-               prgname, prgname);
-         return EXIT_FAILURE;
-      }
-      if (strcmp(argv[0], argv[1]) == 0) {
-         Dmsg2(200, "%s: identical source and destination.\n"
-               "usage:\t%s [-v] source destination\n"
-               "\tCopies ACLs from source to destination.\n"
-               "\tSpecify -v to show ACLs after copy for verification.\n",
-               prgname, prgname);
-         return EXIT_FAILURE;
-      }
-      if (verbose) {
-         aclls(argv[0]);
-      }
-      status = aclcp(argv[0], argv[1]);
-      if (verbose && status == 0) {
-         aclls(argv[1]);
-      }
-      return status;
-   }
-
-   /* Default: just list ACLs */
-   if (argc < 1) {
-      Dmsg2(200, "%s: missing arguments\n"
-            "usage:\t%s file ...\n"
-            "\tLists ACLs of specified files or directories.\n",
-            prgname, prgname);
-      return EXIT_FAILURE;
-   }
-   while (argc--) {
-      if (!aclls(*argv++)) {
-         status = EXIT_FAILURE;
-      }
-   }
-
-   return status;
-}
-
-/**** Test program *****/
-int aclcp(char *src, char *dst)
+/*
+ * Read and send an ACL for the last encountered file.
+ */
+bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt)
 {
-   struct stat st;
-
-   if (lstat(dst, &st) != 0) {
-      Dmsg0(200, "aclcp: destination does not exist\n");
-      return EXIT_FAILURE;
-   }
-   if (S_ISLNK(st.st_mode)) {
-      Dmsg0(200, "aclcp: cannot set ACL on symlinks\n");
-      return EXIT_FAILURE;
-   }
-   if (lstat(src, &st) != 0) {
-      Dmsg0(200, "aclcp: source does not exist\n");
-      return EXIT_FAILURE;
-   }
-   if (S_ISLNK(st.st_mode)) {
-      Dmsg0(200, "aclcp: will not read ACL from symlinks\n");
-      return EXIT_FAILURE;
-   }
-
-   jcr.last_fname = src;
-   if (bacl_get(&jcr, BACL_TYPE_ACCESS) < 0) {
-      Dmsg1(200, "aclcp: could not read ACLs for %s\n", jcr.last_fname);
-      return EXIT_FAILURE;
-   } else {
-      jcr.last_fname = dst;
-      if (bacl_set(&jcr, BACL_TYPE_ACCESS) < 0) {
-         Dmsg1(200, "aclcp: could not set ACLs on %s\n", jcr.last_fname);
-         return EXIT_FAILURE;
-      }
-   }
-
-   if (S_ISDIR(st.st_mode) && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
-      jcr.last_fname = src;
-      if (bacl_get(&jcr, BACL_TYPE_DEFAULT) < 0) {
-         Dmsg1(200, "aclcp: could not read default ACLs for %s\n", jcr.last_fname);
-         return EXIT_FAILURE;
-      } else {
-         jcr.last_fname = dst;
-         if (bacl_set(&jcr, BACL_TYPE_DEFAULT) < 0) {
-            Dmsg1(200, "aclcp: could not set default ACLs on %s\n", jcr.last_fname);
-            return EXIT_FAILURE;
-         }
-      }
-   }
-
-   return 0;
+   /*
+    * Call the appropriate function, the ifdefs make sure the proper code is compiled.
+    */
+#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);
+#endif
 }
 
-/**** Test program *****/
-int aclls(char *fname)
+bool parse_acl_stream(JCR *jcr, int stream)
 {
-   struct stat st;
-   int len;
-
-   if (lstat(fname, &st) != 0) {
-      Dmsg0(200, "acl: source does not exist\n");
-      return EXIT_FAILURE;
-   }
-   if (S_ISLNK(st.st_mode)) {
-      Dmsg0(200, "acl: will not read ACL from symlinks\n");
-      return EXIT_FAILURE;
-   }
-
-   jcr.last_fname = fname;
-
-   len = bacl_get(&jcr, BACL_TYPE_ACCESS);
-   if (len < 0) {
-      Dmsg1(200, "acl: could not read ACLs for %s\n", jcr.last_fname);
-      return EXIT_FAILURE;
-   } else if (len == 0) {
-      printf("#file: %s [standard permissions - or unsupported]\n\n", jcr.last_fname);
-   } else {
-      printf("#file: %s\n%s\n", jcr.last_fname, jcr.acl_text);
-   }
-
-   if (S_ISDIR(st.st_mode) && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
-      len = bacl_get(&jcr, BACL_TYPE_DEFAULT);
-      if (len < 0) {
-         Dmsg1(200, "acl: could not read default ACLs for %s\n", jcr.last_fname);
-         return EXIT_FAILURE;
-      } else if (len == 0) {
-         printf("#file: %s [default, none - or unsupported]\n\n", jcr.last_fname);
-      } else {
-         printf("#file: %s [default]\n%s\n", jcr.last_fname, jcr.acl_text);
-      }
-   }
-
-   return 0;
+   /*
+    * 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.
+    */
+   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_T:
+      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_T:
+   case STREAM_ACL_FREEBSD_ACCESS_ACL_T:
+      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)
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_UNIX_DEFAULT_ACL:
+   case STREAM_ACL_IRIX_DEFAULT_ACL_T:
+   case STREAM_ACL_IRIX_ACCESS_ACL_T:
+      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_T:
+   case STREAM_ACL_LINUX_ACCESS_ACL_T:
+      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_T:
+   case STREAM_ACL_TRU64_ACCESS_ACL_T:
+   case STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T:
+      return tru64_parse_acl_stream(jcr, stream);
+#elif defined(HAVE_SUN_OS)
+   case STREAM_UNIX_ACCESS_ACL:
+   case STREAM_ACL_SOLARIS_ACLENT_T:
+#if defined(HAVE_EXTENDED_ACL)
+   case STREAM_ACL_SOLARIS_ACE_T:
+#endif
+      return solaris_parse_acl_stream(jcr, stream);
+#endif
+   default:
+      /*
+       * Issue a warning and discard the message. But pretend the restore was ok.
+       */
+      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) */
 }
 #endif
index f03d5c31eb0b859ba0e14003a06c8d45dd0a176d..81149cf96bcd2163f7402565fd1eba9beedd6554 100644 (file)
 /* For numeric user/group ids when possible, define BACL_WANT_NUMERIC_IDS */
 /* #define BACL_WANT_NUMERIC_IDS */
 
-/* We support the following types of ACLs */
-#define BACL_TYPE_NONE        0x000
-#define BACL_TYPE_ACCESS      0x001
-#define BACL_TYPE_DEFAULT     0x002
+/*
+ * We support the following types of ACLs
+ */
+typedef enum {
+   BACL_TYPE_NONE = 0,
+   BACL_TYPE_ACCESS = 1,
+   BACL_TYPE_DEFAULT = 2,
+   BACL_TYPE_DEFAULT_DIR = 3,
+   BACL_TYPE_EXTENDED = 4
+} bacl_type;
 
-#define BACL_CAP_NONE         0x000    /* No special capabilities */
-#define BACL_CAP_DEFAULTS     0x001    /* Has default ACLs for directories */
-#define BACL_CAP_DEFAULTS_DIR 0x002    /* Default ACLs must be read separately */
+/*
+ * This value is used as ostype when we encounter a invalid acl type.
+ * The way the code is build this should never happen.
+ */
+#if !defined(ACL_TYPE_NONE)
+#define ACL_TYPE_NONE 0x0
+#endif
 
-/* Set BACL_CAP (always) and BACL_ENOTSUP (when used) for various OS */
 #if defined(HAVE_FREEBSD_OS)
-#define BACL_CAP              (BACL_CAP_DEFAULTS|BACL_CAP_DEFAULTS_DIR)
 #define BACL_ENOTSUP          EOPNOTSUPP
 #elif defined(HAVE_DARWIN_OS)
-#define BACL_CAP              BACL_CAP_NONE
 #define BACL_ENOTSUP          EOPNOTSUPP
 #elif defined(HAVE_HPUX_OS)
-#define BACL_CAP              BACL_CAP_NONE
 #define BACL_ENOTSUP          EOPNOTSUPP
 #elif defined(HAVE_IRIX_OS)
-#define BACL_CAP              (BACL_CAP_DEFAULTS|BACL_CAP_DEFAULTS_DIR)
 #define BACL_ENOTSUP          ENOSYS
 #elif defined(HAVE_LINUX_OS) 
-#define BACL_CAP              (BACL_CAP_DEFAULTS|BACL_CAP_DEFAULTS_DIR)
 #define BACL_ENOTSUP          ENOTSUP
-#elif defined(HAVE_OSF1_OS)
-#define BACL_CAP              (BACL_CAP_DEFAULTS|BACL_CAP_DEFAULTS_DIR)
-/* #define BACL_ENOTSUP       ENOTSUP */     /* Don't know */
-#define BACL_CAP              (BACL_CAP_DEFAULTS|BACL_CAP_DEFAULTS_DIR)
-#elif defined(HAVE_SUN_OS)
-#define BACL_CAP              BACL_CAP_DEFAULTS
-#else
-#define BACL_CAP              BACL_CAP_NONE  /* nothing special */
+#elif defined(HAVE_SUN_OS) 
+#define BACL_ENOTSUP          ENOSYS
 #endif
 
 #endif
index 9525a0579cfce14c424272dbcbd68897cefdf2f5..c5d8d3e768b44ee059e3b0ac9e3f845688f84018 100644 (file)
@@ -42,7 +42,6 @@
 int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level);
 static int send_data(JCR *jcr, int stream, FF_PKT *ff_pkt, DIGEST *digest, DIGEST *signature_digest);
 bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream);
-static bool read_and_send_acl(JCR *jcr, int acltype, int stream);
 static bool crypto_session_start(JCR *jcr);
 static void crypto_session_end(JCR *jcr);
 static bool crypto_session_send(JCR *jcr, BSOCK *sd);
@@ -145,7 +144,8 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
    
    start_heartbeat_monitor(jcr);
 
-   jcr->acl_text = get_pool_memory(PM_MESSAGE);
+   jcr->acl_data = get_pool_memory(PM_MESSAGE);
+   jcr->xattr_data = get_pool_memory(PM_MESSAGE);
 
    /* Subroutine save_file() is called for each file */
    if (!find_files(jcr, (FF_PKT *)jcr->ff, save_file, plugin_save)) {
@@ -155,7 +155,8 @@ bool blast_data_to_storage_daemon(JCR *jcr, char *addr)
 
    accurate_send_deleted_list(jcr);              /* send deleted list to SD  */
 
-   free_pool_memory(jcr->acl_text);
+   free_pool_memory(jcr->acl_data);
+   free_pool_memory(jcr->xattr_data);
 
    stop_heartbeat_monitor(jcr);
 
@@ -582,7 +583,7 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
       Dmsg1(300, "Saving Finder Info for \"%s\"\n", ff_pkt->fname);
       sd->fsend("%ld %d 0", jcr->JobFiles, STREAM_HFSPLUS_ATTRIBUTES);
       Dmsg1(300, "bfiled>stored:header %s\n", sd->msg);
-      memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
+      pm_memcpy(sd->msg, ff_pkt->hfsinfo.fndrinfo, 32);
       sd->msglen = 32;
       if (digest) {
          crypto_digest_update(digest, (uint8_t *)sd->msg, sd->msglen);
@@ -595,17 +596,20 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
    }
 #endif
 
-   if (ff_pkt->flags & FO_ACL) {
-      /* Read access ACLs for files, dirs and links */
-      if (!read_and_send_acl(jcr, BACL_TYPE_ACCESS, STREAM_UNIX_ACCESS_ACL)) {
+   /*
+    * Save ACLs for anything not being a symlink.
+    */
+   if (ff_pkt->flags & FO_ACL && ff_pkt->type != FT_LNK) {
+      if (!build_acl_streams(jcr, ff_pkt))
+         goto bail_out;
+   }
+
+   /*
+    * Save Extended Attributes for all files.
+    */
+   if (ff_pkt->flags & FO_XATTR) {
+      if (!build_xattr_streams(jcr, ff_pkt))
          goto bail_out;
-      }
-      /* Directories can have default ACLs too */
-      if (ff_pkt->type == FT_DIREND && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
-         if (!read_and_send_acl(jcr, BACL_TYPE_DEFAULT, STREAM_UNIX_DEFAULT_ACL)) {
-            goto bail_out;
-         }
-      }
    }
 
    /* Terminate the signing digest and send it to the Storage daemon */
@@ -1021,61 +1025,6 @@ err:
    return 0;
 }
 
-/*
- * Read and send an ACL for the last encountered file.
- */
-static bool read_and_send_acl(JCR *jcr, int acltype, int stream)
-{
-#ifdef HAVE_ACL
-   BSOCK *sd = jcr->store_bsock;
-   POOLMEM *msgsave;
-   int len;
-#ifdef FD_NO_SEND_TEST
-   return true;
-#endif
-
-   len = bacl_get(jcr, acltype);
-   if (len < 0) {
-      Jmsg1(jcr, M_WARNING, 0, _("Error reading ACL of %s\n"), jcr->last_fname);
-      return true; 
-   }
-   if (len == 0) {
-      return true;                    /* no ACL */
-   }
-
-   /* 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;
-   }
-
-   /* Send the buffer to the storage deamon */
-   Dmsg2(400, "Backing up ACL type 0x%2x <%s>\n", acltype, jcr->acl_text);
-   msgsave = sd->msg;
-   sd->msg = jcr->acl_text;
-   sd->msglen = len + 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());
-      return false;
-   }
-
-   jcr->JobBytes += sd->msglen;
-   sd->msg = msgsave;
-   if (!sd->signal(BNET_EOD)) {
-      Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
-            sd->bstrerror());
-      return false;
-   }
-
-   Dmsg1(200, "ACL of file: %s successfully backed up!\n", jcr->last_fname);
-#endif
-   return true;
-}
-
 bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream) 
 {
    BSOCK *sd = jcr->store_bsock;
index 9256b4241f15198bcd3928f56d1850da94aff03d..8d0cf550e41306ef81a7f4b7858e6ee4ca6fb821 100644 (file)
@@ -1120,6 +1120,9 @@ static void set_options(findFOPTS *fo, const char *opts)
       case 'N':
          fo->flags |= FO_HONOR_NODUMP;
          break;
+      case 'X':
+         fo->flags |= FO_XATTR;
+         break;
       default:
          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
          break;
index 21794509b23d48bfd378b4f2a65a055e4497bf81..8c3dcb77fe6de662519b980bf09b4cac72c8c3ef 100644 (file)
@@ -47,8 +47,8 @@ void start_dir_heartbeat(JCR *jcr);
 void stop_dir_heartbeat(JCR *jcr);
 
 /* From acl.c */
-int bacl_get(JCR *jcr, int acltype);
-int bacl_set(JCR *jcr, int acltype);
+bool build_acl_streams(JCR *jcr, FF_PKT *ff_pkt);
+bool parse_acl_stream(JCR *jcr, int stream);
 
 /* from accurate.c */
 bool accurate_send_deleted_list(JCR *jcr);
@@ -59,3 +59,7 @@ bool encode_and_send_attributes(JCR *jcr, FF_PKT *ff_pkt, int &data_stream);
 void strip_path(FF_PKT *ff_pkt);
 void unstrip_path(FF_PKT *ff_pkt);
 
+/* from xattr.c */
+bool build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt);
+bool parse_xattr_stream(JCR *jcr, int stream);
+
index 0fc635e39fb5a2fd09d06fe80fdabcbf3cc638cc..eba51ce3fa9fd3aadf799a70bd119d24f580ea46 100644 (file)
@@ -62,6 +62,11 @@ const bool have_acl = false;
    const bool have_sha2 = false;
 #endif
 
+#if defined(HAVE_XATTR)
+const bool have_xattr = true;
+#else
+const bool have_xattr = false;
+#endif
 
 /* Data received from Storage Daemon */
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
@@ -171,6 +176,7 @@ void do_restore(JCR *jcr)
    int non_support_acl = 0;
    int non_support_progname = 0;
    int non_support_crypto = 0;
+   int non_support_xattr = 0;
 
 #ifdef HAVE_DARWIN_OS
    struct attrlist attrList;
@@ -243,9 +249,8 @@ void do_restore(JCR *jcr)
    binit(&rctx.bfd);
    binit(&rctx.forkbfd);
    attr = rctx.attr = new_attr(jcr);
-   jcr->acl_text = get_pool_memory(PM_MESSAGE);
-
-   
+   jcr->acl_data = get_pool_memory(PM_MESSAGE);
+   jcr->xattr_data = get_pool_memory(PM_MESSAGE);
 
    while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
       /* Remember previous stream type */
@@ -573,6 +578,21 @@ void do_restore(JCR *jcr)
          break;
 
       case STREAM_UNIX_ACCESS_ACL:
+      case STREAM_UNIX_DEFAULT_ACL:
+      case STREAM_ACL_AIX_TEXT:
+      case STREAM_ACL_DARWIN_ACCESS_ACL_T:
+      case STREAM_ACL_FREEBSD_DEFAULT_ACL_T:
+      case STREAM_ACL_FREEBSD_ACCESS_ACL_T:
+      case STREAM_ACL_HPUX_ACL_ENTRY:
+      case STREAM_ACL_IRIX_DEFAULT_ACL_T:
+      case STREAM_ACL_IRIX_ACCESS_ACL_T:
+      case STREAM_ACL_LINUX_DEFAULT_ACL_T:
+      case STREAM_ACL_LINUX_ACCESS_ACL_T:
+      case STREAM_ACL_TRU64_DEFAULT_ACL_T:
+      case STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T:
+      case STREAM_ACL_TRU64_ACCESS_ACL_T:
+      case STREAM_ACL_SOLARIS_ACLENT_T:
+      case STREAM_ACL_SOLARIS_ACE_T:
          /*
           * Do not restore ACLs when
           * a) The current file is not extracted
@@ -583,28 +603,36 @@ void do_restore(JCR *jcr)
             break;
          }
          if (have_acl) {
-            pm_strcpy(jcr->acl_text, sd->msg);
-            Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_ACCESS, jcr->acl_text);
-            if (bacl_set(jcr, BACL_TYPE_ACCESS) != 0) {
-               Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACL of %s\n"), jcr->last_fname);
+            pm_memcpy(jcr->acl_data, sd->msg, sd->msglen);
+            jcr->acl_data_len = sd->msglen;
+            if (!parse_acl_stream(jcr, rctx.stream)) {
+               Qmsg1(jcr, M_WARNING, 0, _("Can't restore ACLs of %s\n"), jcr->last_fname);
             }
          } else {
             non_support_acl++;
          }
          break;
 
-      case STREAM_UNIX_DEFAULT_ACL:
+      case STREAM_XATTR_DARWIN:
+      case STREAM_XATTR_FREEBSD:
+      case STREAM_XATTR_LINUX:
+         /*
+          * Do not restore Extended Attributes when
+          * a) The current file is not extracted
+          * b)     and it is not a directory (they are never "extracted")
+          * c) or the file name is empty
+          */
          if ((!rctx.extract && jcr->last_type != FT_DIREND) || (*jcr->last_fname == 0)) {
             break;
          }
-         if (have_acl) {
-            pm_strcpy(jcr->acl_text, sd->msg);
-            Dmsg2(400, "Restoring ACL type 0x%2x <%s>\n", BACL_TYPE_DEFAULT, jcr->acl_text);
-            if (bacl_set(jcr, BACL_TYPE_DEFAULT) != 0) {
-               Qmsg1(jcr, M_WARNING, 0, _("Can't restore default ACL of %s\n"), jcr->last_fname);
+         if (have_xattr) {
+            pm_memcpy(jcr->xattr_data, sd->msg, sd->msglen);
+            jcr->xattr_data_len = sd->msglen;
+            if (!parse_xattr_stream(jcr, rctx.stream)) {
+               Qmsg1(jcr, M_WARNING, 0, _("Can't restore Extended Attributes of %s\n"), jcr->last_fname);
             }
          } else {
-            non_support_acl++;
+            non_support_xattr++;
          }
          break;
 
@@ -703,7 +731,8 @@ ok_out:
    bclose(&rctx.forkbfd);
    bclose(&rctx.bfd);
    free_attr(rctx.attr);
-   free_pool_memory(jcr->acl_text);
+   free_pool_memory(jcr->xattr_data);
+   free_pool_memory(jcr->acl_data);
    Dmsg2(10, "End Do Restore. Files=%d Bytes=%s\n", jcr->JobFiles,
       edit_uint64(jcr->JobBytes, ec1));
    if (non_support_data > 1 || non_support_attr > 1) {
@@ -722,6 +751,9 @@ ok_out:
    if (non_support_crypto) {
       Jmsg(jcr, M_INFO, 0, _("%d non-supported crypto streams ignored.\n"), non_support_acl);
    }
+   if (non_support_xattr) {
+      Jmsg(jcr, M_INFO, 0, _("%d non-supported xattr streams ignored.\n"), non_support_xattr);
+   }
 
 }
 
index 4ee3c136851244021876c51cc95821c00e69f84a..aa55a8732327e2a01bd2d8f4adddcb84d98a83d9 100644 (file)
@@ -340,8 +340,8 @@ static void sendit(const char *msg, int len, STATUS_PKT *sp)
 {
    if (sp->bs) {
       BSOCK *user = sp->bs;
-      user->msg = check_pool_memory_size(user->msg, len+1);
-      memcpy(user->msg, msg, len+1);
+     
+      pm_memcpy(user->msg, msg, len+1);
       user->msglen = len+1;
       user->send();
    } else {
index c9dba67d09672b6381622286430f8c137d4998f2..eafaf6c17fc881776df84a73f359e86474cfc2d4 100644 (file)
@@ -143,6 +143,40 @@ const char *stream_to_ascii(int stream)
       return _("Encrypted Win32 GZIP data");
    case STREAM_ENCRYPTED_MACOS_FORK_DATA:
       return _("Encrypted MacOS fork data");
+   case STREAM_ACL_AIX_TEXT:
+      return _("AIX Specific ACL attribs");
+   case STREAM_ACL_DARWIN_ACCESS_ACL_T:
+      return _("Darwin Specific ACL attribs");
+   case STREAM_ACL_FREEBSD_DEFAULT_ACL_T:
+      return _("FreeBSD Specific Default ACL attribs");
+   case STREAM_ACL_FREEBSD_ACCESS_ACL_T:
+      return _("FreeBSD Specific Access ACL attribs");
+   case STREAM_ACL_HPUX_ACL_ENTRY:
+      return _("HPUX Specific ACL attribs");
+   case STREAM_ACL_IRIX_DEFAULT_ACL_T:
+      return _("Irix Specific Default ACL attribs");
+   case STREAM_ACL_IRIX_ACCESS_ACL_T:
+      return _("Irix Specific Access ACL attribs");
+   case STREAM_ACL_LINUX_DEFAULT_ACL_T:
+      return _("Linux Specific Default ACL attribs");
+   case STREAM_ACL_LINUX_ACCESS_ACL_T:
+      return _("Linux Specific Access ACL attribs");
+   case STREAM_ACL_TRU64_DEFAULT_ACL_T:
+      return _("OSF1 Specific Default ACL attribs");
+   case STREAM_ACL_TRU64_ACCESS_ACL_T:
+      return _("OSF1 Specific Access ACL attribs");
+   case STREAM_ACL_SOLARIS_ACLENT_T:
+      return _("Solaris Specific ACL attribs");
+   case STREAM_ACL_SOLARIS_ACE_T:
+      return _("Solaris Specific ACL attribs");
+   case STREAM_XATTR_DARWIN:
+      return _("Darwin Specific Extended attribs");
+   case STREAM_XATTR_FREEBSD:
+      return _("FreeBSD Specific Extended attribs");
+   case STREAM_XATTR_LINUX:
+      return _("Linux Specific Extended attribs");
+   case STREAM_XATTR_NETBSD:
+      return _("NetBSD Specific Extended attribs");
    default:
       sprintf(buf, "%d", stream);
       return (const char *)buf;
index 86568bda08c6251e5fd0a065a05c3c0801b57b15..035102cd17716ec9ab3530a7a1c992f776a39995 100644 (file)
@@ -101,6 +101,7 @@ int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
 #define FO_CHKCHANGES   (1<<24)       /* Check if file have been modified during backup */
 #define FO_STRIPPATH    (1<<25)       /* Check for stripping path */
 #define FO_HONOR_NODUMP (1<<26)       /* honor NODUMP flag */
+#define FO_XATTR        (1<<27)       /* Backup Extended Attributes */
 
 struct s_included_file {
    struct s_included_file *next;
index c285ce7fce1b0b1d7b99c4df5c695df55194a1a7..e4e69bdea841a2acd82337fc3ac5318e74397571 100644 (file)
@@ -195,6 +195,9 @@ void add_fname_to_include_list(FF_PKT *ff, int prefixed, const char *fname)
          case 'K':
             inc->options |= FO_NOATIME;
             break;
+         case 'X':
+            inc->options |= FO_XATTR;
+            break;
          default:
             Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *rp);
             break;
index d7dfff922f1cc7fff5c3562482e5e881456812d9..fcda30cdb71e518a3935ccc051c9f29e922aac7a 100644 (file)
@@ -331,7 +331,10 @@ public:
    /* File Daemon specific part of JCR */
    uint32_t num_files_examined;       /* files examined this job */
    POOLMEM *last_fname;               /* last file saved/verified */
-   POOLMEM *acl_text;                 /* text of ACL for backup */
+   POOLMEM *acl_data;                 /* data with ACLs for backup/restore */
+   uint32_t acl_data_len;             /* length of acl data buffer */
+   POOLMEM *xattr_data;               /* data with Extended Attributes for backup/restore */
+   uint32_t xattr_data_len;           /* length of xattr_data buffer */
    int32_t last_type;                 /* type of last file saved/verified */
    int incremental;                   /* set if incremental for SINCE */
    utime_t mtime;                     /* begin time for SINCE */
index d961c396c7aae88c35e5a0891998af05d1fb5666..e36f63df6a4b9c6e70b5043b3e5017bf2a5fb767 100644 (file)
@@ -95,7 +95,6 @@ struct abufhead {
 
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 
-
 #ifdef SMARTALLOC
 
 #define HEAD_SIZE BALIGN(sizeof(struct abufhead))
@@ -154,7 +153,6 @@ POOLMEM *sm_get_memory(const char *fname, int lineno, int32_t size)
    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
 }
 
-
 /* Return the size of a memory buffer */
 int32_t sm_sizeof_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
 {
@@ -233,7 +231,6 @@ void sm_free_pool_memory(const char *fname, int lineno, POOLMEM *obuf)
    V(mutex);
 }
 
-
 #else
 
 /* =========  NO SMARTALLOC  =========================================  */
@@ -284,7 +281,6 @@ POOLMEM *get_memory(int32_t size)
    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
 }
 
-
 /* Return the size of a memory buffer */
 int32_t sizeof_pool_memory(POOLMEM *obuf)
 {
@@ -295,8 +291,6 @@ int32_t sizeof_pool_memory(POOLMEM *obuf)
    return ((struct abufhead *)cp)->ablen;
 }
 
-
-
 /* Realloc pool memory buffer */
 POOLMEM *realloc_pool_memory(POOLMEM *obuf, int32_t size)
 {
@@ -321,7 +315,6 @@ POOLMEM *realloc_pool_memory(POOLMEM *obuf, int32_t size)
    return (POOLMEM *)(((char *)buf)+HEAD_SIZE);
 }
 
-
 POOLMEM *check_pool_memory_size(POOLMEM *obuf, int32_t size)
 {
    ASSERT(obuf);
@@ -361,10 +354,8 @@ void free_pool_memory(POOLMEM *obuf)
    Dmsg2(1800, "free_pool_memory %p pool=%d\n", buf, pool);
    V(mutex);
 }
-
 #endif /* SMARTALLOC */
 
-
 /*
  * Clean up memory pool periodically
  *
@@ -393,9 +384,6 @@ void garbage_collect_memory_pool()
    }
 }
 
-
-
-
 /* Release all pooled memory */
 void close_memory_pool()
 {
@@ -423,7 +411,6 @@ void close_memory_pool()
 }
 
 #ifdef DEBUG
-
 static const char *pool_name(int pool)
 {
    static const char *name[] = {"NoPool", "NAME  ", "FNAME ", "MSG   ", "EMSG  "};
@@ -452,7 +439,6 @@ void print_memory_pool_stats()
 void print_memory_pool_stats() {}
 #endif /* DEBUG */
 
-
 /*
  * Concatenate a string (str) onto a pool memory buffer pm
  *   Returns: length of concatenated string
@@ -483,7 +469,6 @@ int pm_strcat(POOLMEM *&pm, const char *str)
    return pmlen + len - 1;
 }
 
-
 int pm_strcat(POOLMEM *&pm, POOL_MEM &str)
 {
    int pmlen = strlen(pm);
@@ -507,7 +492,6 @@ int pm_strcat(POOL_MEM &pm, const char *str)
    return pmlen + len - 1;
 }
 
-
 /*
  * Copy a string (str) into a pool memory buffer pm
  *   Returns: length of string copied
@@ -545,7 +529,6 @@ int pm_strcpy(POOLMEM *&pm, POOL_MEM &str)
    return len - 1;
 }
 
-
 int pm_strcpy(POOL_MEM &pm, const char *str)
 {
    int len;
@@ -558,6 +541,38 @@ int pm_strcpy(POOL_MEM &pm, const char *str)
    return len - 1;
 }
 
+/*
+ * Copy data into a pool memory buffer pm
+ *   Returns: length of data copied
+ */
+int pm_memcpy(POOLMEM **pm, const void *data, size_t n)
+{
+   *pm = check_pool_memory_size(*pm, n);
+   memcpy(*pm, data, n);
+   return n;
+}
+
+int pm_memcpy(POOLMEM *&pm, const void *data, size_t n)
+{
+   pm = check_pool_memory_size(pm, n);
+   memcpy(pm, data, n);
+   return n;
+}
+
+int pm_memcpy(POOLMEM *&pm, POOL_MEM &data, size_t n)
+{
+   pm = check_pool_memory_size(pm, n);
+   memcpy(pm, data.c_str(), n);
+   return n;
+}
+
+int pm_memcpy(POOL_MEM &pm, const void *data, size_t n)
+{
+   pm.check_size(n);
+   memcpy(pm.c_str(), data, n);
+   return n;
+}
+
 /* ==============  CLASS POOL_MEM   ============== */
 
 /* Return the size of a memory buffer */
@@ -608,7 +623,6 @@ int POOL_MEM::strcat(const char *str)
    return pmlen + len - 1;
 }
 
-
 int POOL_MEM::strcpy(const char *str)
 {
    int len;
index cdf03d71bf7b6741c1f889bbecb7c86d8b0b893b..abb4daeba30e001eb7d330a863b164d1d1cde373 100644 (file)
@@ -111,6 +111,9 @@ int pm_strcpy(POOLMEM **pm, const char *str);
 int pm_strcpy(POOLMEM *&pm, const char *str);
 int pm_strcpy(POOL_MEM &pm, const char *str);
 int pm_strcpy(POOLMEM *&pm, POOL_MEM &str);
-
+int pm_memcpy(POOLMEM **pm, const void *data, size_t n);
+int pm_memcpy(POOLMEM *&pm, const void *data, size_t n);
+int pm_memcpy(POOL_MEM &pm, const void *data, size_t n);
+int pm_memcpy(POOLMEM *&pm, POOL_MEM &data, size_t n);
 
 #endif
index a4d320c7217c3ba5f571bffbb384b04438f841ae..2dd620b683534ab773ca4d27afc453b182f2ae34 100644 (file)
@@ -791,9 +791,30 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
       }
       break;
 
-   case STREAM_UNIX_ACCESS_ACL:          /* Standard ACL attributes on UNIX */
-   case STREAM_UNIX_DEFAULT_ACL:         /* Default ACL attributes on UNIX */
-      /* Ignore Unix attributes */
+   case STREAM_UNIX_ACCESS_ACL:          /* Deprecated Standard ACL attributes on UNIX */
+   case STREAM_UNIX_DEFAULT_ACL:         /* Deprecated Default ACL attributes on UNIX */
+   case STREAM_ACL_AIX_TEXT:
+   case STREAM_ACL_DARWIN_ACCESS_ACL_T:
+   case STREAM_ACL_FREEBSD_DEFAULT_ACL_T:
+   case STREAM_ACL_FREEBSD_ACCESS_ACL_T:
+   case STREAM_ACL_HPUX_ACL_ENTRY:
+   case STREAM_ACL_IRIX_DEFAULT_ACL_T:
+   case STREAM_ACL_IRIX_ACCESS_ACL_T:
+   case STREAM_ACL_LINUX_DEFAULT_ACL_T:
+   case STREAM_ACL_LINUX_ACCESS_ACL_T:
+   case STREAM_ACL_TRU64_DEFAULT_ACL_T:
+   case STREAM_ACL_TRU64_DEFAULT_DIR_ACL_T:
+   case STREAM_ACL_TRU64_ACCESS_ACL_T:
+   case STREAM_ACL_SOLARIS_ACLENT_T:
+   case STREAM_ACL_SOLARIS_ACE_T:
+      /* Ignore Unix ACL attributes */
+      break;
+
+   case STREAM_XATTR_DARWIN:
+   case STREAM_XATTR_FREEBSD:
+   case STREAM_XATTR_LINUX:
+   case STREAM_XATTR_NETBSD:
+      /* Ignore Unix Extended attributes */
       break;
 
    default:
index bacabaedf3b8c56b7cfe3a24c80aa5cb355f9269..5df537689ccad733b8aafeac3991847e836ce0bd 100644 (file)
@@ -632,6 +632,9 @@ static void set_options(findFOPTS *fo, const char *opts)
          fo->GZIP_level = *++p - '0';
          Dmsg1(200, "Compression level=%d\n", fo->GZIP_level);
          break;
+      case 'X':
+         fo->flags |= FO_XATTR;
+         break;
       default:
          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
          break;
index 41b6ccfe37564975d3ea24d05755d43a525a033b..194530f2b622906e9b9772ba62e42801cd80da19 100644 (file)
@@ -3,9 +3,9 @@
  */
 
 #undef  VERSION
-#define VERSION "2.5.20"
-#define BDATE   "25 November 2008"
-#define LSMDATE "25Nov08"
+#define VERSION "2.5.21"
+#define BDATE   "26 November 2008"
+#define LSMDATE "26Nov08"
 
 #define PROG_COPYRIGHT "Copyright (C) %d-2008 Free Software Foundation Europe e.V.\n"
 #define BYEAR "2008"       /* year for copyright messages in progs */
index cc9bd593479d75d4f2c9db39735e9311d4706d31..d2f8b33064bb1bc99a3b4bf0521d597d61dd8736 100644 (file)
@@ -10,6 +10,9 @@ filepattern (restore with regex in bsr)
 mixed priorities
 
 General:
+26Nov08
+kes  Apply Marco's Extended attribute support patch.
+kes  Update projects file
 25Nov08
 kes  More changes to ensure that during thread switches the jcr
      is removed from the TSD.