]> git.sur5r.net Git - bacula/bacula/commitdiff
Merge Preben's patch for ACLs and for Mac OS X resource forks.
authorKern Sibbald <kern@sibbald.com>
Tue, 1 Feb 2005 10:01:30 +0000 (10:01 +0000)
committerKern Sibbald <kern@sibbald.com>
Tue, 1 Feb 2005 10:01:30 +0000 (10:01 +0000)
- Some doc updates.

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

bacula/src/filed/acl.c
bacula/src/filed/acl.h
bacula/src/filed/backup.c
bacula/src/findlib/find.h
bacula/src/findlib/find_one.c

index e9e093f286d174f283d8c2c613b6d569584233fa..d16f5795b7507771e24f61b0a7a4ee474aa8a08a 100644 (file)
@@ -51,6 +51,7 @@
  *
  * For a list of compiler flags, see the list preceding the big #if below.
  */
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -175,9 +176,16 @@ int bacl_get(JCR *jcr, int acltype)
    if (acl) {
       if ((acl_text = acl_to_text(acl, NULL)) != NULL) {
         len = pm_strcpy(jcr->acl_text, acl_text);
+        acl_free(acl);
         acl_free(acl_text);
         return len;
       }
+      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, "");
+#endif
    }
    /***** Do we really want to silently ignore errors from acl_get_file
      and acl_to_text?  *****/
@@ -234,6 +242,9 @@ int bacl_get(JCR *jcr, int acltype)
    char *acl_text;
 
    if ((n = getacl(jcr->last_fname, 0, acls)) <= 0) {
+      if (errno == BACL_ENOTSUP) {
+        return pm_strcpy(jcr->acl_text, "");
+      }
       return -1;
    }
    if ((n = getacl(jcr->last_fname, n, acls)) > 0) {
@@ -274,15 +285,18 @@ int bacl_get(JCR *jcr, int acltype)
    char *acl_text;
 
    n = acl(jcr->last_fname, GETACLCNT, 0, NULL);
-   if (n <= 0) {
+   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;
    }
    if (acl(jcr->last_fname, GETACL, n, acls) == n) {
       if ((acl_text = acltotext(acls, n)) != NULL) {
-        pm_strcpy(jcr->acl_text, acl_text);
+        len = pm_strcpy(jcr->acl_text, acl_text);
         free(acl_text);
         free(acls);
         return len;
@@ -436,6 +450,7 @@ int aclcp(char *src, char *dst)
 int aclls(char *fname)
 {
    struct stat st;
+   int len;
 
    if (lstat(fname, &st) != 0) {
       Dmsg0(200, "acl: source does not exist\n");
@@ -448,18 +463,26 @@ int aclls(char *fname)
 
    jcr.last_fname = fname;
 
-   if (bacl_get(&jcr, BACL_TYPE_ACCESS) < 0) {
+   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);
    }
-   printf("#file: %s\n%s\n", jcr.last_fname, jcr.acl_text);
 
    if (S_ISDIR(st.st_mode) && (BACL_CAP & BACL_CAP_DEFAULTS_DIR)) {
-      if (bacl_get(&jcr, BACL_TYPE_DEFAULT) < 0) {
+      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);
       }
-      printf("#file: %s [default]\n%s\n", jcr.last_fname, jcr.acl_text);
    }
 
    return 0;
index 44b46c0c0a7cb1fc042fde9d238313c28afa0505..2d5676f24d3af7f885e12268254d4610f9ec93b0 100644 (file)
@@ -5,10 +5,10 @@
 #ifndef _BACULA_ACL_
 #define _BACULA_ACL_
 
-/* If you want shorter ACL strings when possible, uncomment this */
-#define BACL_WANT_SHORT_ACLS
+/* For shorter ACL strings when possible, define BACL_WANT_SHORT_ACLS */
+/* #define BACL_WANT_SHORT_ACLS */
 
-/* If you want numeric user/group ids when possible, uncomment this */
+/* 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_CAP_DEFAULTS     0x001    /* Has default ACLs for directories */
 #define BACL_CAP_DEFAULTS_DIR 0x002    /* Default ACLs must be read separately */
 
-/* Set capabilities for various OS */
-#if defined(HAVE_SUN_OS)
-#define BACL_CAP             BACL_CAP_DEFAULTS
-#elif defined(HAVE_FREEBSD_OS) \
-   || defined(HAVE_IRIX_OS) \
-   || defined(HAVE_OSF1_OS) \
-   || defined(HAVE_LINUX_OS)
+/* 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)
-#else
+#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 */
 #endif
 
 #endif
index 1508cf86870e948d56c0570c5e22a4c2417a73ae..de5de2e02ec457197ed0c617b69ee4f80fc03184 100644 (file)
@@ -341,7 +341,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
    }
 
 #ifdef HAVE_DARWIN_OS
-   /* Open resource fork if necessary and save content */
+   /* Regular files can have resource forks and Finder Info */
    if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
            ff_pkt->flags & FO_HFSPLUS)) {
       if (ff_pkt->hfsinfo.rsrclength > 0) {
@@ -379,15 +379,17 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
 #endif
 
 #ifdef HAVE_ACL
-   /* Read access ACLs for files, dirs and links */
-   if (!read_and_send_acl(jcr, BACL_TYPE_ACCESS, STREAM_UNIX_ATTRIBUTES_ACCESS_ACL)) {
-      return 0;
-   }
-   /* 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_ATTRIBUTES_DEFAULT_ACL)) {
+   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_ATTRIBUTES_ACCESS_ACL)) {
         return 0;
       }
+      /* 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_ATTRIBUTES_DEFAULT_ACL)) {
+           return 0;
+        }
+      }
    }
 #endif
 
index cf35bd589a8f576d7cbf54dcd51457bcdad44338..24107519be203a4c528a8602b84cafecd1c2d2de 100755 (executable)
@@ -202,9 +202,10 @@ struct FF_PKT {
    /* List of all hard linked files found */
    struct f_link *linklist;          /* hard linked files */
 
-   /* Darwin specific things. So as not to clutter every bclose()
-    * with an #ifdef, we always include rsrc_bfd */
+   /* Darwin specific things.
+    * To avoid clutter, we always include rsrc_bfd and volhas_attrlist */
    BFILE rsrc_bfd;                   /* fd for resource forks */
+   bool volhas_attrlist;             /* Volume supports getattrlist() */
 #ifdef HAVE_DARWIN_OS
    struct HFSPLUS_INFO hfsinfo;       /* Finder Info and resource fork size */
 #endif
index d3516d37fe3984eb2abf4f2f2d5d7d04d936ac10..90709c47eed3056b65d284d89227c8601e9b868f 100755 (executable)
@@ -88,6 +88,39 @@ static int accept_fstype(FF_PKT *ff, void *dummy) {
    return accept;
 }
 
+/*
+ * This function determines whether we can use getattrlist()
+ * It's odd, but we have to use the function to determine that...
+ * Also, the man pages talk about things as if they were implemented.
+ *
+ * On Mac OS X, this succesfully differentiates between HFS+ and UFS
+ * volumes, which makes me trust it is OK for others, too.
+ */
+static bool volume_has_attrlist(const char *fname)
+{
+#ifdef HAVE_DARWIN_OS
+   struct statfs st;
+   struct volinfo_struct {
+      unsigned long length;              /* Mandatory field */
+      vol_capabilities_attr_t info;      /* Volume capabilities */
+   } vol;
+   struct attrlist attrList;
+
+   memset(&attrList, 0, sizeof(attrList));
+   attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+   attrList.volattr = ATTR_VOL_INFO | ATTR_VOL_CAPABILITIES;
+   if (statfs(fname, &st) == 0) {
+      /* We need to check on the mount point */
+      if (getattrlist(st.f_mntonname, &attrList, &vol, sizeof(vol), FSOPT_NOFOLLOW) == 0
+           && (vol.info.capabilities[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_ATTRLIST)
+           && (vol.info.valid[VOL_CAPABILITIES_INTERFACES] & VOL_CAP_INT_ATTRLIST)) {
+        return true;
+      }
+   }
+#endif
+   return false;
+}
+
 /*
  * Find a single file.
  * handle_file is the callback for handling the file.
@@ -124,13 +157,16 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
    /*
     * We check for allowed fstypes at top_level and fstype change (below).
     */
-   if (top_level && !accept_fstype(ff_pkt, NULL)) {
-      ff_pkt->type = FT_INVALIDFS;
-      if (ff_pkt->flags & FO_KEEPATIME) {
-        utime(fname, &restore_times);
+   if (top_level) {
+      if (!accept_fstype(ff_pkt, NULL)) {
+        ff_pkt->type = FT_INVALIDFS;
+        if (ff_pkt->flags & FO_KEEPATIME) {
+           utime(fname, &restore_times);
+        }
+        Jmsg1(jcr, M_ERROR, 0, _("Top level directory \"%s\" has an unlisted fstype\n"), fname);
+        return 1;      /* Just ignore this error - or the whole backup is cancelled */
       }
-      Jmsg1(jcr, M_ERROR, 0, _("Top level directory \"%s\" has an unlisted fstype\n"), fname);
-      return 1;      /* Just ignore this error - or the whole backup is cancelled */
+      ff_pkt->volhas_attrlist = volume_has_attrlist(fname);
    }
 
    /*
@@ -151,7 +187,8 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
    }
 
 #ifdef HAVE_DARWIN_OS
-   if (S_ISREG(ff_pkt->statp.st_mode) && ff_pkt->flags & FO_HFSPLUS) {
+   if (ff_pkt->flags & FO_HFSPLUS && ff_pkt->volhas_attrlist
+        && S_ISREG(ff_pkt->statp.st_mode)) {
        /* TODO: initialise attrList once elsewhere? */
        struct attrlist attrList;
        memset(&attrList, 0, sizeof(attrList));
@@ -159,7 +196,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        attrList.commonattr = ATTR_CMN_FNDRINFO;
        attrList.fileattr = ATTR_FILE_RSRCLENGTH;
        if (getattrlist(fname, &attrList, &ff_pkt->hfsinfo,
-               sizeof(ff_pkt->hfsinfo), 0) != 0) {
+               sizeof(ff_pkt->hfsinfo), FSOPT_NOFOLLOW) != 0) {
          ff_pkt->type = FT_NOSTAT;
          ff_pkt->ff_errno = errno;
          return handle_file(ff_pkt, pkt);
@@ -276,6 +313,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       int status;
       dev_t our_device = ff_pkt->statp.st_dev;
       bool recurse = true;
+      bool volhas_attrlist = ff_pkt->volhas_attrlist;   /* Remember this if we recurse */
 
       /*
        * If we are using Win32 (non-portable) backup API, don't check
@@ -370,8 +408,11 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
         } else if (!accept_fstype(ff_pkt, NULL)) {
            ff_pkt->type = FT_INVALIDFS;
            recurse = false;
+        } else {
+           ff_pkt->volhas_attrlist = volume_has_attrlist(fname);
         }
       }
+      /* If not recursing, just backup dir and return */
       if (!recurse) {
         rtn_stat = handle_file(ff_pkt, pkt);
         if (ff_pkt->linked) {
@@ -466,6 +507,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       if (ff_pkt->flags & FO_KEEPATIME) {
         utime(fname, &restore_times);
       }
+      ff_pkt->volhas_attrlist = volhas_attrlist;      /* Restore value in case it changed. */
       return rtn_stat;
    } /* end check for directory */