]> git.sur5r.net Git - bacula/bacula/commitdiff
Added support for TRU64 Extended Attributes interface.
authorMarco van Wieringen <mvw@planets.elm.net>
Fri, 24 Sep 2010 19:09:56 +0000 (21:09 +0200)
committerEric Bollengier <eric@eb.homelinux.org>
Wed, 6 Oct 2010 09:15:19 +0000 (11:15 +0200)
bacula/src/baconfig.h
bacula/src/filed/acl.c
bacula/src/filed/restore.c
bacula/src/filed/xattr.c
bacula/src/findlib/bfile.c
bacula/src/findlib/fstype.c
bacula/src/lib/mntent_cache.c
bacula/src/stored/bscan.c
bacula/src/stored/dev.c

index 7cea63d1550c70cc1cd95c3c7d8ea40ded312f2f..b4f62ff649514ab6be50625e93a3214db4806c4d 100644 (file)
@@ -306,6 +306,7 @@ void InitWinAPIWrapper();
 #define STREAM_ACL_AIX_NFS4              1016    /* AIX specific string representation from
                                                   * aclx_printStr (NFSv4 acl)
                                                   */
+#define STREAM_XATTR_TRU64               1991    /* TRU64 specific extended attributes */
 #define STREAM_XATTR_AIX                 1992    /* AIX specific extended attributes */
 #define STREAM_XATTR_OPENBSD             1993    /* OpenBSD specific extended attributes */
 #define STREAM_XATTR_SOLARIS_SYS         1994    /* Solaris specific extensible attributes or
@@ -698,7 +699,7 @@ extern int thr_setconcurrency(int);
 
 #endif
 
-#if defined(HAVE_DARWIN_OS) || defined(HAVE_OSF1_OS)
+#if defined(HAVE_DARWIN_OS) || defined(HAVE_TRU64_OS)
 /* Apparently someone forgot to wrap getdomainname as a C function */
 extern "C" int getdomainname(char *name, int len);
 #endif
@@ -745,7 +746,7 @@ extern "C" int setdomainname(char *name, int namelen);
 #endif /* HAVE_HPUX_OS */
 
 
-#ifdef HAVE_OSF1_OS
+#ifdef HAVE_TRU64_OS
 extern "C" int fchdir(int filedes);
 extern "C" long gethostid(void);
 extern "C" int mknod(const char *path, int mode, dev_t device );
index e3be782f3a328a1b22180128bfa5088090f1804d..d3a4d2dcda10874ad70ec089e0dfba3411a5af36 100644 (file)
@@ -404,7 +404,7 @@ static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = aix_parse_
 #elif defined(HAVE_DARWIN_OS) || \
       defined(HAVE_FREEBSD_OS) || \
       defined(HAVE_IRIX_OS) || \
-      defined(HAVE_OSF1_OS) || \
+      defined(HAVE_TRU64_OS) || \
       defined(HAVE_LINUX_OS)
 
 #include <sys/types.h>
@@ -457,7 +457,7 @@ static acl_type_t bac_to_os_acltype(bacl_type acltype)
 #ifdef ACL_TYPE_DEFAULT_DIR
    case BACL_TYPE_DEFAULT_DIR:
       /**
-       * OSF1 has an additional acl type named ACL_TYPE_DEFAULT_DIR.
+       * TRU64 has an additional acl type named ACL_TYPE_DEFAULT_DIR.
        */
       ostype = ACL_TYPE_DEFAULT_DIR;
       break;
@@ -534,7 +534,7 @@ static bool acl_is_trivial(acl_t acl)
          return false;
    }
    return true;
-#elif defined(HAVE_OSF1_OS)
+#elif defined(HAVE_TRU64_OS)
    int count;
 
    ace = acl->acl_first;
@@ -879,7 +879,7 @@ static bacl_exit_code generic_parse_acl_streams(JCR *jcr, int stream)
 static bacl_exit_code (*os_build_acl_streams)(JCR *jcr, FF_PKT *ff_pkt) = generic_build_acl_streams;
 static bacl_exit_code (*os_parse_acl_streams)(JCR *jcr, int stream) = generic_parse_acl_streams;
 
-#elif defined(HAVE_OSF1_OS)
+#elif defined(HAVE_TRU64_OS)
 
 /**
  * Define the supported ACL streams for this OS
index 0832b99be1ab67271811d06c1da730fd68cea3ff..c06d0c5e855f1b59e1406569c3afb224dc039dc1 100644 (file)
@@ -687,6 +687,7 @@ void do_restore(JCR *jcr)
          }
          break;
 
+      case STREAM_XATTR_TRU64:
       case STREAM_XATTR_AIX:
       case STREAM_XATTR_OPENBSD:
       case STREAM_XATTR_SOLARIS_SYS:
index 55b814c89f81ac3fb7467962c6f8817b4cc9c74f..49b47884106d9ce736351a08d157c779c670ba9b 100644 (file)
@@ -121,14 +121,9 @@ static bxattr_exit_code send_xattr_stream(JCR *jcr, int stream)
 
 /*
  * First some generic functions for OSes that use the same xattr encoding scheme.
+ * Currently for all OSes except for Solaris.
  */
-#if defined(HAVE_AIX_OS) || \
-    defined(HAVE_DARWIN_OS) || \
-    defined(HAVE_LINUX_OS) || \
-    defined(HAVE_NETBSD_OS) || \
-    defined(HAVE_FREEBSD_OS) || \
-    defined(HAVE_OPENBSD_OS)
-
+#if !defined(HAVE_SUN_OS)
 static void xattr_drop_internal_table(alist *xattr_value_list)
 {
    xattr_t *current_xattr;
@@ -1371,6 +1366,310 @@ bail_out:
 static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = bsd_build_xattr_streams;
 static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = bsd_parse_xattr_streams;
 
+#elif defined(HAVE_TRU64_OS)
+
+#if !defined(HAVE_GETPROPLIST) || \
+    !defined(HAVE_GET_PROPLIST_ENTRY) || \
+    !defined(HAVE_SIZEOF_PROPLIST_ENTRY) || \
+    !defined(HAVE_ADD_PROPLIST_ENTRY) || \
+    !defined(HAVE_SETPROPLIST)
+#error "Missing full support for the Extended Attributes functions."
+#endif
+
+#ifdef HAVE_SYS_PROPLIST_H
+#include <sys/proplist.h>
+#else
+#error "Missing sys/proplist.h header file"
+#endif
+
+/*
+ * Define the supported XATTR streams for this OS
+ */
+static int os_default_xattr_streams[1] = { STREAM_XATTR_TRU64 };
+static const char *xattr_acl_skiplist[1] = { NULL };
+static const char *xattr_skiplist[1] = { NULL };
+
+static bxattr_exit_code tru64_build_xattr_streams(JCR *jcr, FF_PKT *ff_pkt)
+{
+   char *bp,
+        *xattr_name,
+        *xattr_value;
+   int xattr_count = 0;
+   int32_t *flags,
+           *xattr_value_len;
+   int32_t xattr_list_len,
+           xattrbuf_size,
+           xattrbuf_min_size;
+   uint32_t expected_serialize_len = 0;
+   xattr_t *current_xattr;
+   alist *xattr_value_list = NULL;
+   struct proplistname_args prop_args;
+   bxattr_exit_code retval = bxattr_exit_error;
+   POOLMEM *xattrbuf = get_pool_memory(PM_MESSAGE);
+   berrno be;
+
+   xattrbuf_size = sizeof_pool_memory(xattrbuf);
+   xattrbuf_min_size = 0;
+   xattr_list_len = getproplist(jcr->last_fname, 1, &prop_args, xattrbuf_size,
+                                xattrbuf, &xattrbuf_min_size);
+
+   /**
+    * See what xattr are available.
+    */
+   switch (xattr_list_len) {
+   case -1:
+      switch (errno) {
+      case EOPNOTSUPP:
+         retval = bacl_exit_ok;
+         goto bail_out;
+      default:
+         Mmsg2(jcr->errmsg, _("getproplist error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "getproplist error file=%s ERR=%s\n",
+               jcr->last_fname, be.bstrerror());
+         goto bail_out;
+      }
+      break;
+   case 0:
+      if (xattrbuf_min_size) {
+         /**
+          * The buffer isn't big enough to hold the xattr data, we now have
+          * a minimum buffersize so we resize the buffer and try again.
+          */
+         xattrbuf = check_pool_memory_size(xattrbuf, xattrbuf_min_size + 1);
+         xattrbuf_size = xattrbuf_min_size + 1;
+         xattr_list_len = getproplist(jcr->last_fname, 1, &prop_args, xattrbuf_size,
+                                   xattrbuf, &xattrbuf_min_size);
+         switch (xattr_list_len) {
+         case -1:
+            switch (errno) {
+            case EOPNOTSUPP:
+               retval = bacl_exit_ok;
+               goto bail_out;
+            default:
+               Mmsg2(jcr->errmsg, _("getproplist error on file \"%s\": ERR=%s\n"),
+                     jcr->last_fname, be.bstrerror());
+               Dmsg2(100, "getproplist error file=%s ERR=%s\n",
+                     jcr->last_fname, be.bstrerror());
+               goto bail_out;
+            }
+            break;
+         case 0:
+            /**
+             * This should never happen as we sized the buffer according to the minimumsize
+             * returned by a previous getproplist call. If it does happen things are fishy and
+             * we are better of forgetting this xattr as it seems its list is changing at this
+             * exact moment so we can never make a good backup copy of it.
+             */
+            retval = bacl_exit_ok;
+            goto bail_out;
+         default:
+            break;
+         }
+      } else {
+         /**
+          * No xattr on file.
+          */
+         retval = bacl_exit_ok;
+         goto bail_out;
+      }
+      break;
+   default:
+      break;
+   }
+
+   xattr_value_list = New(alist(10, not_owned_by_alist));
+
+   /**
+    * Walk the list of extended attributes names and retrieve the data.
+    * We already count the bytes needed for serializing the stream later on.
+    */
+   bp = xattrbuf;
+   while (xattrbuf_size > 0) {
+      /*
+       * Call getproplist_entry to initialize name and value
+       * pointers to entries position within buffer.
+       */
+      xattrbuf_size -= get_proplist_entry(&xattr_name, &flags, &xattr_value_len, &xattr_value, &bp);
+
+      /*
+       * On some OSes you also get the acls in the extented attribute list.
+       * So we check if we are already backing up acls and if we do we
+       * don't store the extended attribute with the same info.
+       */
+      if (ff_pkt->flags & FO_ACL) {
+         for (cnt = 0; xattr_acl_skiplist[cnt] != NULL; cnt++) {
+            if (bstrcmp(xattr_name, xattr_acl_skiplist[cnt])) {
+               skip_xattr = true;
+               break;
+            }
+         }
+      }
+
+      /*
+       * On some OSes we want to skip certain xattrs which are in the xattr_skiplist array.
+       */
+      if (!skip_xattr) {
+         for (cnt = 0; xattr_skiplist[cnt] != NULL; cnt++) {
+            if (bstrcmp(xattr_name, xattr_skiplist[cnt])) {
+               skip_xattr = true;
+               break;
+            }
+         }
+      }
+
+      if (skip_xattr) {
+         continue;
+      }
+
+      /*
+       * Each xattr valuepair starts with a magic so we can parse it easier.
+       */
+      current_xattr = (xattr_t *)malloc(sizeof(xattr_t));
+      current_xattr->magic = XATTR_MAGIC;
+      expected_serialize_len += sizeof(current_xattr->magic);
+
+      current_xattr->name_length = strlen(xattr_name);
+      current_xattr->name = bstrdup(xattr_name);
+
+      expected_serialize_len += sizeof(current_xattr->name_length) + current_xattr->name_length;
+
+      current_xattr->value_length = *xattr_value_len;
+      current_xattr->value = (char *)malloc(current_xattr->value_length);
+      memcpy(current_xattr->value, xattr_value, current_xattr->value_length);
+
+      expected_serialize_len += sizeof(current_xattr->value_length) + current_xattr->value_length;
+
+      /*
+       * Protect ourself against things getting out of hand.
+       */
+      if (expected_serialize_len >= MAX_XATTR_STREAM) {
+         Mmsg2(jcr->errmsg, _("Xattr stream on file \"%s\" exceeds maximum size of %d bytes\n"),
+               jcr->last_fname, MAX_XATTR_STREAM);
+         free(current_xattr->value);
+         free(current_xattr->name);
+         free(current_xattr);
+         goto bail_out;
+      }
+
+      xattr_value_list->append(current_xattr);
+      xattr_count++;
+   }
+
+   /*
+    * If we found any xattr send them to the SD.
+    */
+   if (xattr_count > 0) {
+      /*
+       * Serialize the datastream.
+       */
+      if (serialize_xattr_stream(jcr, expected_serialize_len, xattr_value_list) < expected_serialize_len) {
+         Mmsg1(jcr->errmsg, _("Failed to serialize extended attributes on file \"%s\"\n"),
+               jcr->last_fname);
+         Dmsg1(100, "Failed to serialize extended attributes on file \"%s\"\n",
+               jcr->last_fname);
+         goto bail_out;
+      }
+
+      /*
+       * Send the datastream to the SD.
+       */
+      retval = send_xattr_stream(jcr, os_default_xattr_streams[0]);
+   }
+
+bail_out:
+   if (xattr_value_list != NULL) {
+      xattr_drop_internal_table(xattr_value_list);
+   }
+   free_pool_memory(xattrbuf);
+
+   return retval;
+}
+
+static bxattr_exit_code tru64_parse_xattr_streams(JCR *jcr, int stream)
+{
+   char *bp, *xattrbuf;
+   int32_t xattrbuf_size, cnt;
+   xattr_t *current_xattr;
+   alist *xattr_value_list;
+   berrno be;
+
+   xattr_value_list = New(alist(10, not_owned_by_alist));
+
+   if (unserialize_xattr_stream(jcr, xattr_value_list) != bxattr_exit_ok) {
+      xattr_drop_internal_table(xattr_value_list);
+      return bxattr_exit_error;
+   }
+
+   /**
+    * See how big the propertylist must be.
+    */
+   xattrbuf_size = 0;
+   foreach_alist(current_xattr, xattr_value_list) {
+      xattrbuf_size += sizeof_proplist_entry(current_xattr->name, current_xattr->value_length);
+   }
+
+   xattrbuf = (char *)malloc(xattrbuf_size);
+
+   cnt = 0;
+   bp = xattrbuf;
+   /**
+    * Add all value pairs to the proplist.
+    */
+   foreach_alist(current_xattr, xattr_value_list) {
+      cnt = add_proplist_entry(current_xattr->name, 0, current_xattr->value_length,
+                               current_xattr->value, &bp);
+   }
+
+   if (cnt != xattrbuf_size) {
+      Mmsg1(jcr->errmsg, _("Unable create proper proplist to restore xattrs on file \"%s\"\n"),
+            jcr->last_fname);
+      Dmsg1(100, "Unable create proper proplist to restore xattrs on file \"%s\"\n",
+            jcr->last_fname);
+      free(xattrbuf);
+      goto bail_out;
+   }
+
+   /**
+    * Restore the list of extended attributes on the file.
+    */
+   cnt = setproplist(jcr->last_fname, 1, xattrbuf_size, xattrbuf);
+   switch (cnt) {
+   case -1:
+      switch (errno) {
+      case EOPNOTSUPP:
+         retval = bacl_exit_ok;
+         free(xattrbuf);
+         goto bail_out;
+      default:
+         Mmsg2(jcr->errmsg, _("setproplist error on file \"%s\": ERR=%s\n"),
+               jcr->last_fname, be.bstrerror());
+         Dmsg2(100, "setproplist error file=%s ERR=%s\n",
+               jcr->last_fname, be.bstrerror());
+         free(xattrbuf);
+         goto bail_out;
+      }
+      break;
+   default:
+      break;
+   }
+
+   free(xattrbuf);
+
+   xattr_drop_internal_table(xattr_value_list);
+   return bxattr_exit_ok;
+
+bail_out:
+   xattr_drop_internal_table(xattr_value_list);
+   return bxattr_exit_error;
+}
+
+/*
+ * Function pointers to the build and parse function to use for these xattrs.
+ */
+static bxattr_exit_code (*os_build_xattr_streams)(JCR *jcr, FF_PKT *ff_pkt) = tru64_build_xattr_streams;
+static bxattr_exit_code (*os_parse_xattr_streams)(JCR *jcr, int stream) = tru64_parse_xattr_streams;
+
 #elif defined(HAVE_SUN_OS)
 /*
  * Solaris extended attributes were introduced in Solaris 9
index 6d2d797c6ffd625e9ac41ac0c01aad03993e06e6..584902c38058199d2fa0e341013b55b0f08936ef 100644 (file)
@@ -160,9 +160,9 @@ const char *stream_to_ascii(int stream)
    case STREAM_ACL_LINUX_ACCESS_ACL:
       return _("Linux Specific Access ACL attribs");
    case STREAM_ACL_TRU64_DEFAULT_ACL:
-      return _("OSF1 Specific Default ACL attribs");
+      return _("TRU64 Specific Default ACL attribs");
    case STREAM_ACL_TRU64_ACCESS_ACL:
-      return _("OSF1 Specific Access ACL attribs");
+      return _("TRU64 Specific Access ACL attribs");
    case STREAM_ACL_SOLARIS_ACLENT:
       return _("Solaris Specific ACL attribs");
    case STREAM_ACL_SOLARIS_ACE:
@@ -173,6 +173,8 @@ const char *stream_to_ascii(int stream)
       return _("AIX Specific ACL attribs");
    case STREAM_ACL_AIX_NFS4:
       return _("AIX Specific ACL attribs");
+   case STREAM_XATTR_TRU64:
+      return _("TRU64 Specific Extended attribs");
    case STREAM_XATTR_AIX:
       return _("AIX Specific Extended attribs");
    case STREAM_XATTR_OPENBSD:
index 4765f9415b2ceed99847bc7abd6e69bffd55dbb0..21cd969546bc8ccb5ab98c84a5c786ed8a20aaf8 100644 (file)
@@ -53,7 +53,7 @@
    "HAVE_NETBSD_OS\n" \
    "HAVE_OPENBSD_OS\n" \
    "HAVE_SUN_OS\n" \
-   "HAVE_OSF1_OS\n" \
+   "HAVE_TRU64_OS\n" \
    "HAVE_WIN32\n"
 #define false              0
 #define true               1
@@ -131,7 +131,7 @@ bool fstype(const char *fname, char *fs, int fslen)
 }
 
 #elif defined(HAVE_LINUX_OS) || \
-      defined(HAVE_OSF1_OS)
+      defined(HAVE_TRU64_OS)
 
 #include <sys/stat.h>
 #include "lib/mntent_cache.h"
index c130fa2d95d70faeab2bcde1fd4aeabca3ce7d88..998dbdb6b98b161be90ef05bb2dbae5363cc4828 100644 (file)
  * - DARWIN (OSX)
  * - IRIX
  * - AIX
- * - OSF1 (True64)
+ * - TRU64 (True64)
  * - Solaris
  *
- * Currently we only use this code for Linux and OSF1 based fstype determination.
+ * Currently we only use this code for Linux and TRU64 based fstype determination.
  * For the other OS-es we can use the fstype present in stat structure on those OS-es.
  *
  * This code replaces the big switch we used before based on SUPER_MAGIC present in
@@ -88,7 +88,7 @@
 #elif defined(HAVE_AIX_OS)
 #include <fshelp.h>
 #include <sys/vfs.h>
-#elif defined(HAVE_OSF1_OS)
+#elif defined(HAVE_TRU64_OS)
 #include <sys/mount.h>
 #endif
 
@@ -275,7 +275,7 @@ static void refresh_mount_cache(void)
       cnt++;
    }
    free(entries);
-#elif defined(HAVE_OSF1_OS)
+#elif defined(HAVE_TRU64_OS)
    struct statfs *entries, *current;
    struct stat st;
    int n_entries, cnt;
index 5c487c29ee094efea96949996ad963d66a828240..195448f73e296d3a4146ef86995a87bab7294b09 100644 (file)
@@ -812,6 +812,7 @@ static bool record_cb(DCR *dcr, DEV_RECORD *rec)
       /* Ignore Unix ACL attributes */
       break;
 
+   case STREAM_XATTR_TRU64:
    case STREAM_XATTR_AIX:
    case STREAM_XATTR_OPENBSD:
    case STREAM_XATTR_SOLARIS_SYS:
index 9fa2e31f52fbc6e6637ea8f674dff1794e8688ee..e40948d538a10cfae88c8552d31c09b562a4e876 100644 (file)
@@ -1686,7 +1686,7 @@ void DEVICE::clrerror(int func)
 }
 #endif
 
-/* Clear Subsystem Exception OSF1 */
+/* Clear Subsystem Exception TRU64 */
 #ifdef MTCSE
 {
    struct mtop mt_com;