]> git.sur5r.net Git - bacula/bacula/commitdiff
- Integrated Preben 'Peppe' Guldberg <peppe@wielders.org>
authorKern Sibbald <kern@sibbald.com>
Thu, 9 Dec 2004 21:47:28 +0000 (21:47 +0000)
committerKern Sibbald <kern@sibbald.com>
Thu, 9 Dec 2004 21:47:28 +0000 (21:47 +0000)
  patch to avoid doing MTIOCGET on OSes that do not support
  it such as OpenBSD.
- Integrated Preben 'Peppe' Guldberg <peppe@wielders.org>
  patch to add filesystem type matching to FileSets in the
  Options resource.
- Integrated Preben 'Peppe' Guldberg <peppe@wielders.org>
  patch to add Mac OSX resource fork support (save/restore)
  to Bacula -- HFS Plus support.

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

31 files changed:
bacula/VERIFYING
bacula/src/baconfig.h
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/fd_cmds.c
bacula/src/dird/inc_conf.c
bacula/src/dird/query.sql
bacula/src/filed/backup.c
bacula/src/filed/estimate.c
bacula/src/filed/job.c
bacula/src/filed/restore.c
bacula/src/filed/verify.c
bacula/src/findlib/Makefile.in
bacula/src/findlib/Makefile.mingw
bacula/src/findlib/attribs.c
bacula/src/findlib/bfile.c
bacula/src/findlib/bfile.h
bacula/src/findlib/find.c
bacula/src/findlib/find.h
bacula/src/findlib/find_one.c
bacula/src/findlib/fstype.c [new file with mode: 0644]
bacula/src/findlib/protos.h
bacula/src/stored/btape.c
bacula/src/stored/dev.c
bacula/src/stored/dev.h
bacula/src/stored/record.c
bacula/src/stored/stored_conf.c
bacula/src/tools/Makefile.in
bacula/src/tools/fstype.c [new file with mode: 0644]
bacula/src/tools/testfind.c
bacula/src/version.h

index 8f549c4d30a887cea90d33bcc13aa0ef6efbfb53..2c7babd9ab7d1de19ca7b1ef283087f65a1c4b52 100644 (file)
@@ -12,7 +12,7 @@ Putting the Bacula Key in your Keyring:
 Once you download the Bacula public key, you must insert it in
 your keyring.  The procedure will differ depending on whether you
 are using PGP or GPG.  For GPG, assuming you have put the key
-in bacula.k, the procedure is:
+in bacula.key, the procedure is:
 
   gpg --import bacula.key
 
@@ -36,4 +36,3 @@ for GPG, you use the following command to do the verification:
 
   gpg --verify xxxx.tar.gz.sig
 
-
index db85a20c197e9a70a160353f9210e163f03c1ed2..90033c84c690ddc3e7e21e85d49f979bd07cd91f 100644 (file)
  * that it can filter packets, but otherwise, it is not used
  * or saved */
 #define FT_DIRBEGIN  18               /* Directory at beginning (not saved) */
+#define FT_INVALIDFS 19                      /* File system not allowed for */
 
 /* Definitions for upper part of type word (see above). */
 #define AR_DATA_STREAM (1<<16)        /* Data stream id present */
index ef72bee1ad7a745844fb0e95e0768d4475e4c492..433945d9bd98d4ca6dbc8144554500311ca00168 100644 (file)
@@ -587,6 +587,9 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
            for (k=0; k<fo->base.size(); k++) {
                sendit(sock, "      B %s\n", fo->base.get(k));
            }
+           for (k=0; k<fo->fstype.size(); k++) {
+               sendit(sock, "      X %s\n", fo->fstype.get(k));
+           }
            if (fo->reader) {
                sendit(sock, "      D %s\n", fo->reader);
            }
@@ -748,6 +751,7 @@ static void free_incexe(INCEXE *incexe)
       fopt->regex.destroy();
       fopt->wild.destroy();
       fopt->base.destroy();
+      fopt->fstype.destroy();
       if (fopt->reader) {
         free(fopt->reader);
       }
index c33913d24d138cedfd9457969b8579ce26a81e1f..d008a969f7a045993a7e3acecefedf17855e0028 100644 (file)
@@ -244,7 +244,7 @@ struct JOB {
 };
 
 #undef  MAX_FOPTS
-#define MAX_FOPTS 32
+#define MAX_FOPTS 34
 
 /* File options structure */
 struct FOPTS {
@@ -252,6 +252,7 @@ struct FOPTS {
    alist regex;                       /* regex string(s) */
    alist wild;                        /* wild card strings */
    alist base;                        /* list of base names */
+   alist fstype;                      /* file system type limitation */
    char *reader;                      /* reader program */
    char *writer;                      /* writer program */
 };
index 46131fc04bdd5d859ebb39637a35f8b6f1b93c9c..77ae25fdbf4a0a3234b733eca162e24972c83c14 100644 (file)
@@ -406,6 +406,9 @@ static int send_fileset(JCR *jcr)
            for (k=0; k<fo->base.size(); k++) {
                bnet_fsend(fd, "B %s\n", fo->base.get(k));
            }
+           for (k=0; k<fo->fstype.size(); k++) {
+               bnet_fsend(fd, "X %s\n", fo->fstype.get(k));
+           }
            if (fo->reader) {
                bnet_fsend(fd, "D %s\n", fo->reader);
            }
index 23c514e32c4b78e92c75978899486e7faf805643..079904c94c186ffea41b9a3dcec7a3a0791f4886 100644 (file)
@@ -39,6 +39,7 @@ void store_inc(LEX *lc, RES_ITEM *item, int index, int pass);
 static void store_newinc(LEX *lc, RES_ITEM *item, int index, int pass);
 static void store_regex(LEX *lc, RES_ITEM *item, int index, int pass);
 static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass);
+static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass);
 static void store_opts(LEX *lc, RES_ITEM *item, int index, int pass);
 static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass);
 static void options_res(LEX *lc, RES_ITEM *item, int index, int pass);
@@ -93,6 +94,8 @@ static RES_ITEM options_items[] = {
    {"reader",          store_reader,  NULL,     0, 0, 0},
    {"writer",          store_writer,  NULL,     0, 0, 0},
    {"ignorecase",      store_opts,    NULL,     0, 0, 0},
+   {"fstype",          store_fstype,  NULL,     0, 0, 0},
+   {"hfsplussupport",  store_opts,    NULL,     0, 0, 0},
    {NULL, NULL, NULL, 0, 0, 0} 
 };
 
@@ -116,7 +119,8 @@ enum {
    INC_KW_KEEPATIME,
    INC_KW_EXCLUDE,
    INC_KW_ACL,
-   INC_KW_IGNORECASE
+   INC_KW_IGNORECASE,
+   INC_KW_HFSPLUS
 };
 
 /*
@@ -140,6 +144,7 @@ static struct s_kw FS_option_kw[] = {
    {"exclude",     INC_KW_EXCLUDE},
    {"aclsupport",  INC_KW_ACL},
    {"ignorecase",  INC_KW_IGNORECASE},
+   {"hfsplussupport", INC_KW_HFSPLUS},
    {NULL,         0}
 };
 
@@ -197,6 +202,8 @@ static struct s_fs_opt FS_options[] = {
    {"no",       INC_KW_ACL,           "0"},
    {"yes",      INC_KW_IGNORECASE,    "i"},
    {"no",       INC_KW_IGNORECASE,    "0"},
+   {"yes",      INC_KW_HFSPLUS,       "R"},   /* "R" for resource fork */
+   {"no",       INC_KW_HFSPLUS,       "0"},
    {NULL,      0,                      0}
 };
 
@@ -563,6 +570,28 @@ static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass)
    scan_to_eol(lc);
 }
 
+/* Store fstype info */
+static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+   int token;
+
+   token = lex_get_token(lc, T_SKIP_EOL);           
+   if (pass == 1) {
+      /* Pickup fstype string */
+      switch (token) {
+      case T_IDENTIFIER:
+      case T_UNQUOTED_STRING:
+      case T_QUOTED_STRING:
+        res_incexe.current_opts->fstype.append(bstrdup(lc->str));
+         Dmsg3(900, "set fstype %p size=%d %s\n", 
+           res_incexe.current_opts, res_incexe.current_opts->fstype.size(), lc->str);
+        break;
+      default:
+         scan_err1(lc, _("Expected an fstype string, got: %s\n"), lc->str);
+      }                                
+   }
+   scan_to_eol(lc);
+}
 
 /*
  * Store Filename info. Note, for minor efficiency reasons, we
@@ -599,6 +628,7 @@ static void store_fname(LEX *lc, RES_ITEM *item, int index, int pass)
    scan_to_eol(lc);
 }
 
+
 /*
  * Come here when Options seen in Include/Exclude
  */
@@ -684,6 +714,7 @@ static void setup_current_opts(void)
    fo->regex.init(1, true);
    fo->wild.init(1, true);
    fo->base.init(1, true);
+   fo->fstype.init(1, true);
    res_incexe.current_opts = fo;
    if (res_incexe.num_opts == 0) {
       res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
index 443cf8f8676afc1d39d8e75048ee81ebe5444956..55101486c9dd3ebaa9f91ad8a86910a2aaa395f3 100644 (file)
@@ -58,12 +58,13 @@ SELECT DISTINCT Job.JobId,Client.Name as Client,Level,StartTime,JobFiles,JobByte
 # 6
 :List all backups for a Client
 *Enter Client Name:
-SELECT DISTINCT Job.JobId as JobId,Client.Name as Client,Level,StartTime,
+SELECT DISTINCT Job.JobId as JobId,Client.Name as Client,
+   FileSet.FileSet AS FileSet,Level,StartTime,
    JobFiles,JobBytes,VolumeName
- FROM Client,Job,JobMedia,Media
+ FROM Client,Job,JobMedia,Media,FileSet
  WHERE Client.Name='%1'
  AND Client.ClientId=Job.ClientId
- AND JobStatus='T'
+ AND JobStatus='T' AND Job.FileSetId=FileSet.FileSetId
  AND JobMedia.JobId=Job.JobId AND JobMedia.MediaId=Media.MediaId
  ORDER BY Job.StartTime;
 # 7
index 81021f694639985711065bcc7009e8519d67c59a..9fbe3f7c9b2bf89cf6a2f0d5950ca505b8d6bd08 100644 (file)
 #include <acl/libacl.h>
 #endif
 
+#ifdef HAVE_DARWIN_OS
+#include <sys/paths.h>
+#endif
+
 static int save_file(FF_PKT *ff_pkt, void *pkt);
 
 /* 
@@ -130,6 +134,7 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
    char attribs[MAXSTRING];
    char attribsEx[MAXSTRING];
    int stat, attr_stream, data_stream;
+   bool hfsplus = false;
    struct MD5Context md5c;
    struct SHA1Context sha1c;
    int gotMD5 = 0;
@@ -163,15 +168,19 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
       return 1;                      /* not used */
    case FT_NORECURSE:
    case FT_NOFSCHG:
+   case FT_INVALIDFS:
    case FT_DIREND:
       if (ff_pkt->type == FT_NORECURSE) {
-         Jmsg(jcr, M_INFO, 1, _("     Recursion turned off. Will not descend into %s\n"), 
+        Jmsg(jcr, M_INFO, 1, _("     Recursion turned off. Will not descend into %s\n"), 
            ff_pkt->fname);
       } else if (ff_pkt->type == FT_NOFSCHG) {
-         Jmsg(jcr, M_INFO, 1, _("     File system change prohibited. Will not descend into %s\n"), 
+        Jmsg(jcr, M_INFO, 1, _("     File system change prohibited. Will not descend into %s\n"), 
+           ff_pkt->fname);
+      } else if (ff_pkt->type == FT_INVALIDFS) {
+        Jmsg(jcr, M_INFO, 1, _("     Disallowed filesystem. Will not descend into %s\n"), 
            ff_pkt->fname);
       }
-      ff_pkt->type = FT_DIREND;       /* value is used below */
+      ff_pkt->type = FT_DIREND;              /* value is used below */
       Dmsg1(130, "FT_DIR saving: %s\n", ff_pkt->link);
       break;
    case FT_SPEC:
@@ -269,6 +278,29 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
       }
    }
 
+   binit(&ff_pkt->rsrc_bfd);
+#ifdef HAVE_DARWIN_OS
+   /* Open resource fork if necessary */
+   if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
+            ff_pkt->flags & FO_HFSPLUS)) {
+      /* Remember Finder Info, whether we have data or fork, or not */
+      hfsplus = true;
+      if (ff_pkt->hfsinfo.rsrclength > 0) {
+        if (!bopen_rsrc(&ff_pkt->rsrc_bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
+           ff_pkt->ff_errno = errno;
+           berrno be;
+            Jmsg(jcr, M_NOTSAVED, -1, _("     Cannot open resource fork for %s: ERR=%s.\n"), ff_pkt->fname, 
+                  be.strerror());
+            jcr->Errors++;
+            if (is_bopen(&ff_pkt->bfd)) {
+               bclose(&ff_pkt->bfd);
+            }
+            return 1;
+         }
+      }
+   }
+#endif
+
    Dmsg1(130, "bfiled: sending %s to stored\n", ff_pkt->fname);
 
    /* Find what data stream we will use, then encode the attributes */
@@ -295,6 +327,9 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
       if (is_bopen(&ff_pkt->bfd)) {
         bclose(&ff_pkt->bfd);
       }
+      if (is_bopen(&ff_pkt->rsrc_bfd)) {
+        bclose(&ff_pkt->rsrc_bfd);
+      }
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
            bnet_strerror(sd));
       return 0;
@@ -333,12 +368,23 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
       if (is_bopen(&ff_pkt->bfd)) {
         bclose(&ff_pkt->bfd);
       }
+      if (is_bopen(&ff_pkt->rsrc_bfd)) {
+        bclose(&ff_pkt->rsrc_bfd);
+      }
       Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
            bnet_strerror(sd));
       return 0;
    }
    bnet_sig(sd, BNET_EOD);           /* indicate end of attributes data */
 
+   if (is_bopen(&ff_pkt->bfd) || hfsplus) {
+      if (ff_pkt->flags & FO_MD5) {
+        MD5Init(&md5c);
+      } else if (ff_pkt->flags & FO_SHA1) {
+        SHA1Init(&sha1c);
+      }
+   }
+
    /* 
     * If the file has data, read it and send to the Storage daemon
     *
@@ -379,18 +425,15 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
       if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, data_stream)) {
         berrno be;
         bclose(&ff_pkt->bfd);
+        if (is_bopen(&ff_pkt->rsrc_bfd)) {
+           bclose(&ff_pkt->rsrc_bfd);
+        }
          Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
               bnet_strerror(sd));
         return 0;
       }
       Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
 
-      if (ff_pkt->flags & FO_MD5) {
-        MD5Init(&md5c);
-      } else if (ff_pkt->flags & FO_SHA1) {
-        SHA1Init(&sha1c);
-      }
-
       /*
        * Make space at beginning of buffer for fileAddr because this
        *   same buffer will be used for writing if compression if off. 
@@ -452,6 +495,9 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
               sd->msg = msgsave;
               sd->msglen = 0;
               bclose(&ff_pkt->bfd);
+              if (is_bopen(&ff_pkt->rsrc_bfd)) {
+                 bclose(&ff_pkt->rsrc_bfd);
+              }
               set_jcr_job_status(jcr, JS_ErrorTerminated);
               return 0;
            }
@@ -475,6 +521,9 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
               sd->msg = msgsave;     /* restore bnet buffer */
               sd->msglen = 0;
               bclose(&ff_pkt->bfd);
+              if (is_bopen(&ff_pkt->rsrc_bfd)) {
+                 bclose(&ff_pkt->rsrc_bfd);
+              }
               return 0;
            }
         }
@@ -495,12 +544,108 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
 
       bclose(&ff_pkt->bfd);             /* close file */
       if (!bnet_sig(sd, BNET_EOD)) {    /* indicate end of file data */
+        berrno be;
+         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+              bnet_strerror(sd));
+        if (is_bopen(&ff_pkt->rsrc_bfd)) {
+           bclose(&ff_pkt->rsrc_bfd);
+        }
+        return 0;
+      }
+   }
+
+#ifdef HAVE_DARWIN_OS
+   /* 
+    * If resource fork has data, read it and send to the Storage daemon
+    *
+    */
+   if (is_bopen(&ff_pkt->rsrc_bfd)) {
+      uint64_t fileAddr = 0;         /* file address */
+      int rsize = jcr->buf_size;      /* read buffer size */
+
+      Dmsg1(300, "Saving resource fork for \"%s\"", ff_pkt->fname);
+
+      /*
+       * Send Data header to Storage daemon
+       *    <file-index> <stream> <info>
+       */
+      if (!bnet_fsend(sd, "%ld %d 0", jcr->JobFiles, STREAM_MACOS_FORK_DATA)) {
+        berrno be;
+        bclose(&ff_pkt->rsrc_bfd);
+         Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
+              bnet_strerror(sd));
+        return 0;
+      }
+      Dmsg1(300, ">stored: datahdr %s\n", sd->msg);
+
+      /* 
+       * Read the resource fork
+       */
+      while ((sd->msglen=(uint32_t)bread(&ff_pkt->rsrc_bfd, sd->msg, rsize)) > 0) {
+        jcr->ReadBytes += sd->msglen;      /* count bytes read */
+        fileAddr += sd->msglen;
+
+        /* Update MD5 if requested */
+        if (ff_pkt->flags & FO_MD5) {
+           MD5Update(&md5c, (unsigned char *)sd->msg, sd->msglen);
+           gotMD5 = 1;
+        } else if (ff_pkt->flags & FO_SHA1) {
+           SHA1Update(&sha1c, (unsigned char *)sd->msg, sd->msglen);
+           gotSHA1 = 1;
+        }
+
+        /* Send the buffer to the Storage daemon */
+        if (!bnet_send(sd)) {
+           berrno be;
+           Jmsg2(jcr, M_FATAL, 0, _("Network send error %d to SD. ERR=%s\n"),
+                 sd->msglen, bnet_strerror(sd));
+           sd->msglen = 0;
+           bclose(&ff_pkt->rsrc_bfd);
+           return 0;
+        }
+         Dmsg1(130, "Send data to SD len=%d\n", sd->msglen);
+        /*       #endif */
+        jcr->JobBytes += sd->msglen;   /* count bytes saved possibly compressed */
+      } /* end while read file data */
+
+      if (sd->msglen < 0) {
+        berrno be;
+        be.set_errno(ff_pkt->rsrc_bfd.berrno);
+         Jmsg(jcr, M_ERROR, 0, _("Read error on resource fork of %s. ERR=%s\n"),
+           ff_pkt->fname, be.strerror());
+      }
+
+      bclose(&ff_pkt->rsrc_bfd);                /* close resource fork */
+      if (!bnet_sig(sd, BNET_EOD)) {    /* indicate end of resource fork */
         berrno be;
          Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
               bnet_strerror(sd));
         return 0;
       }
    }
+#endif
+
+#ifdef HAVE_DARWIN_OS
+   /* Handle Finder Info */
+   if (S_ISREG(ff_pkt->statp.st_mode) && ff_pkt->flags & FO_HFSPLUS) {
+      Dmsg1(300, "Saving Finder Info for \"%s\"", ff_pkt->fname);
+      bnet_fsend(sd, "%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);
+      sd->msglen = 32;
+      /* Update MD5 if requested */
+      if (ff_pkt->flags & FO_MD5) {
+         MD5Update(&md5c, (unsigned char *)sd->msg, sd->msglen);
+         gotMD5 = 1;
+      } else if (ff_pkt->flags & FO_SHA1) {
+         SHA1Update(&sha1c, (unsigned char *)sd->msg, sd->msglen);
+         gotSHA1 = 1;
+      }
+      bnet_send(sd);
+      bnet_sig(sd, BNET_EOD);
+   }
+#endif
+
    
 #ifdef HAVE_ACL
    /* ACL stream */
@@ -556,13 +701,11 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr)
            berrno be;
            sd->msg = msgsave;
            sd->msglen = 0;
-           bclose(&ff_pkt->bfd);
             Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
                  bnet_strerror(sd));
         } else {
            jcr->JobBytes += sd->msglen;
            sd->msg = msgsave;
-           bclose(&ff_pkt->bfd);
            if (!bnet_sig(sd, BNET_EOD)) {
               berrno be;
                Jmsg1(jcr, M_FATAL, 0, _("Network send error to SD. ERR=%s\n"),
index bee59417eadb08a03ce44ec0e9109cc443bae540..eaa181a6b2a1809ae9f74542a562ec373fe7dc68 100644 (file)
@@ -64,6 +64,9 @@ static int tally_file(FF_PKT *ff_pkt, void *ijcr)
    case FT_REGE:
    case FT_REG:
    case FT_LNK:
+   case FT_NORECURSE:
+   case FT_NOFSCHG:
+   case FT_INVALIDFS:
    case FT_DIREND:
    case FT_SPEC:
    case FT_RAW:
@@ -76,16 +79,23 @@ static int tally_file(FF_PKT *ff_pkt, void *ijcr)
    case FT_DIRNOCHG:
    case FT_NOCHG:
    case FT_ISARCH:
-   case FT_NORECURSE:
-   case FT_NOFSCHG:
    case FT_NOOPEN:
    default:
       return 1;
    }
 
-   if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode) && 
-        ff_pkt->statp.st_size > 0) {
-      jcr->JobBytes += ff_pkt->statp.st_size;
+   if (ff_pkt->type != FT_LNKSAVED && S_ISREG(ff_pkt->statp.st_mode)) {
+      if (ff_pkt->statp.st_size > 0) {
+         jcr->JobBytes += ff_pkt->statp.st_size;
+      }
+#ifdef HAVE_DARWIN_OS
+      if (ff_pkt->flags & FO_HFSPLUS) {
+         if (ff_pkt->hfsinfo.rsrclength > 0) {
+            jcr->JobBytes += ff_pkt->hfsinfo.rsrclength;
+         }
+         jcr->JobBytes += 32;    /* Finder info */
+      }
+#endif
    }
    jcr->num_files_examined++;
    jcr->JobFiles++;                 /* increment number of files seen */
index 623f665bf5527a5e5e3d323141a755eaa142087c..1cbb589aa00494bd4f8e9a9ef765579e3be4e422 100644 (file)
@@ -250,6 +250,7 @@ void *handle_client_request(void *dirp)
            fo->regex.destroy();
            fo->wild.destroy();
            fo->base.destroy();
+           fo->fstype.destroy();
            if (fo->reader) {
               free(fo->reader);
            }
@@ -270,6 +271,7 @@ void *handle_client_request(void *dirp)
            fo->regex.destroy();
            fo->wild.destroy();
            fo->base.destroy();
+           fo->fstype.destroy();
         }
         incexe->opts_list.destroy();
         incexe->name_list.destroy();
@@ -627,6 +629,7 @@ static findFOPTS *start_options(FF_PKT *ff)
       fo->regex.init(1, true);
       fo->wild.init(1, true);
       fo->base.init(1, true);
+      fo->fstype.init(1, true);
       incexe->current_opts = fo;
       incexe->opts_list.append(fo);
    }
@@ -759,6 +762,11 @@ static void add_fileset(JCR *jcr, const char *item)
       current_opts->base.append(bstrdup(item));
       state = state_options;
       break;
+   case 'X':
+      current_opts = start_options(ff);
+      current_opts->fstype.append(bstrdup(item));
+      state = state_options;
+      break;
    case 'W':
       current_opts = start_options(ff);
       current_opts->wild.append(bstrdup(item));
@@ -807,6 +815,9 @@ static bool term_fileset(JCR *jcr)
         for (k=0; k<fo->base.size(); k++) {
             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
         }
+        for (k=0; k<fo->fstype.size(); k++) {
+            Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
+        }
         if (fo->reader) {
             Dmsg1(400, "D %s\n", fo->reader);
         }
@@ -832,6 +843,9 @@ static bool term_fileset(JCR *jcr)
         for (k=0; k<fo->base.size(); k++) {
             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
         }
+        for (k=0; k<fo->fstype.size(); k++) {
+            Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
+        }
       }
       for (j=0; j<incexe->name_list.size(); j++) {
          Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
@@ -880,6 +894,8 @@ static void set_options(findFOPTS *fo, const char *opts)
       case 'p':                 /* use portable data format */
         fo->flags |= FO_PORTABLE;
         break;
+      case 'R':                        /* Resource forks and Finder Info */
+        fo->flags |= FO_HFSPLUS;
       case 'r':                 /* read fifo */
         fo->flags |= FO_READFIFO;
         break;
index 3ad0006cf8922ed92d8234d001e2e85897c62fff..7c4d7173aec4663bbb1718b9ac03f109f926198c 100644 (file)
 #include <acl/libacl.h>
 #endif
 
+#ifdef HAVE_DARWIN_OS
+#include <sys/attr.h>
+#include <sys/paths.h>
+#endif
+
 /* Data received from Storage Daemon */
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
 
@@ -44,6 +49,25 @@ static const char *zlib_strerror(int stat);
 
 #define RETRY 10                     /* retry wait time */
 
+#ifdef HAVE_DARWIN_OS
+/* helper routine for closing resource forks */
+int bclose_chksize(JCR *jcr, BFILE *bfd, off_t osize)
+{
+   char ec1[50], ec2[50];
+   off_t fsize;
+
+   fsize = blseek(bfd, 0, SEEK_CUR);
+   bclose(bfd);                              /* first close file */
+   if (fsize > 0 && fsize != osize) {
+      Jmsg3(jcr, M_ERROR, 0, _("File size of resource fork for restored file %s not correct. Original %s, restored %s.\n"),
+            jcr->last_fname, edit_uint64(osize, ec1),
+            edit_uint64(fsize, ec2));
+      return -1;
+   }
+   return 0;
+}
+#endif
+
 /* 
  * Restore the requested files.
  * 
@@ -64,12 +88,26 @@ void do_restore(JCR *jcr)
    uint64_t fileAddr = 0;            /* file write address */
    int non_support_data = 0;
    int non_support_attr = 0;
+   int non_support_rsrc = 0;
+   int non_support_finfo = 0;
    int non_support_acl = 0;
    int prog_name_msg = 0;
    ATTR *attr;
 #ifdef HAVE_ACL
    acl_t acl;
 #endif
+   BFILE rsrc_bfd;                   /* we often check if it is open */
+#ifdef HAVE_DARWIN_OS
+   off_t rsrcAddr = 0;
+   off_t rsrc_len;                    /* original length of resource fork */
+
+   /* TODO: initialise attrList once elsewhere? */
+   struct attrlist attrList;
+   memset(&attrList, 0, sizeof(attrList));
+   attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+   attrList.commonattr = ATTR_CMN_FNDRINFO;
+#endif
+   binit(&rsrc_bfd);
 
    binit(&bfd);
    sd = jcr->store_bsock;
@@ -104,7 +142,10 @@ void do_restore(JCR *jcr)
     *  2. Stream data
     *       a. Attributes (Unix or Win32)
     *   or  b. File data for the file
-    *   or  c. Possibly MD5 or SHA1 record
+    *   or  c. Resource fork
+    *   or  d. Finder info
+    *   or  e. ACLs
+    *   or  f. Possibly MD5 or SHA1 record
     *  3. Repeat step 1
     */
    while (bget_msg(sd) >= 0 && !job_canceled(jcr)) {
@@ -140,14 +181,26 @@ void do_restore(JCR *jcr)
          * close the output file.
          */
         if (extract) {
-           if (!is_bopen(&bfd)) {
+           if (!is_bopen(&bfd)
+#ifdef HAVE_DARWIN_OS
+                  && !is_bopen(&rsrc_bfd)
+#endif
+                  ) {
                Jmsg0(jcr, M_ERROR, 0, _("Logic error output file should be open\n"));
            }
-           set_attributes(jcr, attr, &bfd);
+#ifdef HAVE_DARWIN_OS
+            if (is_bopen(&rsrc_bfd)) {
+               bclose_chksize(jcr, &rsrc_bfd, rsrc_len);
+            }
+#endif
+            if (is_bopen(&bfd)) {
+               set_attributes(jcr, attr, &bfd);
+            }
            extract = false;
             Dmsg0(30, "Stop extracting.\n");
         }
 
+
         if (!unpack_attributes_record(jcr, stream, sd->msg, attr)) {
            goto bail_out;
         }
@@ -173,6 +226,10 @@ void do_restore(JCR *jcr)
 
         build_attr_output_fnames(jcr, attr);
 
+#ifdef HAVE_DARWIN_OS
+         from_base64(&rsrc_len, attr->attrEx);
+#endif
+
         jcr->num_files_examined++;
 
          Dmsg1(30, "Outfile=%s\n", attr->ofname);
@@ -184,14 +241,7 @@ void do_restore(JCR *jcr)
            break;
         case CF_EXTRACT:
            extract = true;
-           P(jcr->mutex);
-           pm_strcpy(jcr->last_fname, attr->ofname);
-           V(jcr->mutex);
-           jcr->JobFiles++;
-           fileAddr = 0;
-           print_ls_output(jcr, attr);
-           /* Set attributes after file extracted */
-           break;
+           /* FALLTHROUGH */
         case CF_CREATED:
            P(jcr->mutex);
            pm_strcpy(jcr->last_fname, attr->ofname);
@@ -199,8 +249,21 @@ void do_restore(JCR *jcr)
            jcr->JobFiles++;
            fileAddr = 0;
            print_ls_output(jcr, attr);
-           /* set attributes now because file will not be extracted */
-           set_attributes(jcr, attr, &bfd);
+            if (!extract) {
+               /* set attributes now because file will not be extracted */
+               set_attributes(jcr, attr, &bfd);
+            }
+#ifdef HAVE_DARWIN_OS
+            if (rsrc_len > 0) {
+              rsrcAddr = 0;
+              if (bopen_rsrc(&rsrc_bfd, jcr->last_fname, O_WRONLY | O_TRUNC | O_BINARY, 0) < 0) {
+                 Jmsg(jcr, M_ERROR, 0, _("     Cannot open resource fork for %s"), jcr->last_fname);
+              } else {
+                 Dmsg0(30, "Restoring resource fork");
+                 extract = true;
+              }
+           }
+#endif
            break;
         }  
         break;
@@ -228,6 +291,9 @@ void do_restore(JCR *jcr)
                         edit_uint64(fileAddr, ec1), attr->ofname, be.strerror());
                     extract = false;
                     bclose(&bfd);
+                    if (is_bopen(&rsrc_bfd)) {
+                       bclose(&rsrc_bfd);
+                    }
                     continue;
                  }
               }
@@ -244,6 +310,9 @@ void do_restore(JCR *jcr)
                     be.strerror());
               extract = false;
               bclose(&bfd);
+              if (is_bopen(&rsrc_bfd)) {
+                 bclose(&rsrc_bfd);
+              }
               continue;
            } 
            total += wsize;
@@ -279,6 +348,9 @@ void do_restore(JCR *jcr)
                         edit_uint64(fileAddr, ec1), attr->ofname, be.strerror());
                     extract = false;
                     bclose(&bfd);
+                    if (is_bopen(&rsrc_bfd)) {
+                       bclose(&rsrc_bfd);
+                    }
                     continue;
                  }
               }
@@ -294,6 +366,9 @@ void do_restore(JCR *jcr)
                  attr->ofname, zlib_strerror(stat));
               extract = false;
               bclose(&bfd);
+              if (is_bopen(&rsrc_bfd)) {
+                 bclose(&rsrc_bfd);
+              }
               continue;
            }
 
@@ -305,6 +380,9 @@ void do_restore(JCR *jcr)
                Jmsg2(jcr, M_ERROR, 0, _("Write error on %s: %s\n"), attr->ofname, be.strerror());
               extract = false;
               bclose(&bfd);
+              if (is_bopen(&rsrc_bfd)) {
+                 bclose(&rsrc_bfd);
+              }
               continue;
            }
            total += compress_len;
@@ -317,11 +395,59 @@ void do_restore(JCR *jcr)
             Jmsg(jcr, M_ERROR, 0, _("GZIP data stream found, but GZIP not configured!\n"));
            extract = false;
            bclose(&bfd);
+           if (is_bopen(&rsrc_bfd)) {
+              bclose(&rsrc_bfd);
+           }
            continue;
         }
 #endif
         break;
 
+      /* Resource fork stream - only recorded after a file to be restored */
+      /* Silently ignore if we cannot write - we already reported that */
+      case STREAM_MACOS_FORK_DATA:
+#ifdef HAVE_DARWIN_OS
+         if (is_bopen(&rsrc_bfd) && sd->msglen) {
+            Dmsg2(30, "Write %u bytes, total before write=%u\n", sd->msglen, total);
+            if (bwrite(&rsrc_bfd, sd->msg, sd->msglen) != sd->msglen) {
+               Dmsg0(0, "===Write error===\n");
+               berrno be;
+               be.set_errno(rsrc_bfd.berrno);
+               Jmsg2(jcr, M_ERROR, 0, _("Write error on resource fork of %s: ERR=%s\n"), jcr->last_fname,
+                     be.strerror());
+               extract = false;
+              if (is_bopen(&bfd)) {
+                 bclose(&bfd);
+              }
+               bclose(&rsrc_bfd);
+               continue;
+            } 
+            total += sd->msglen;
+            jcr->JobBytes += sd->msglen;
+            jcr->ReadBytes += sd->msglen;
+            rsrcAddr += sd->msglen;
+         }
+        break;
+#else
+         non_support_rsrc++;
+#endif
+
+      case STREAM_HFSPLUS_ATTRIBUTES:
+#ifdef HAVE_DARWIN_OS
+         Dmsg0(30, "Restoring Finder Info");
+         if (sd->msglen != 32) {
+            Jmsg(jcr, M_ERROR, 0, _("     Invalid length of Finder Info (got %d, not 32)"), sd->msglen);
+            continue;
+         }
+         if (setattrlist(jcr->last_fname, &attrList, sd->msg, sd->msglen, 0) != 0) {
+            Jmsg(jcr, M_ERROR, 0, _("     Could not set Finder Info on %s"), jcr->last_fname);
+            continue;
+         }
+         break;
+#else
+         non_support_finfo++;
+#endif
+
       case STREAM_UNIX_ATTRIBUTES_ACL:  
 #ifdef HAVE_ACL
         /* Recover ACL from stream and check it */
@@ -395,6 +521,11 @@ ok_out:
       free(jcr->compress_buf);
       jcr->compress_buf = NULL;
    }
+#ifdef HAVE_DARWIN_OS
+   if (is_bopen(&rsrc_bfd)) {
+      bclose_chksize(jcr, &rsrc_bfd, rsrc_len);
+   }
+#endif
    bclose(&bfd);
    free_attr(attr);
    Dmsg2(10, "End Do Restore. Files=%d Bytes=%" lld "\n", jcr->JobFiles,
@@ -403,6 +534,12 @@ ok_out:
       Jmsg(jcr, M_ERROR, 0, _("%d non-supported data streams and %d non-supported attrib streams ignored.\n"),
         non_support_data, non_support_attr);
    }
+   if (non_support_rsrc) {
+      Jmsg(jcr, M_INFO, 0, _("%d non-supported resource fork streams ignored.\n"), non_support_rsrc);
+   }
+   if (non_support_finfo) {
+      Jmsg(jcr, M_INFO, 0, _("%d non-supported Finder Info streams ignored.\n"), non_support_rsrc);
+   }
    if (non_support_acl) {
       Jmsg(jcr, M_INFO, 0, _("%d non-supported acl streams ignored.\n"), non_support_acl);
    }
index ced83987720c3f12410461f638273963b7144b76..7deceb5f492150a4fbe6036268f481223dc9aca9 100644 (file)
 #include "bacula.h"
 #include "filed.h"
 
+#ifdef HAVE_DARWIN_OS
+#include <sys/paths.h>
+#endif
+
 static int verify_file(FF_PKT *ff_pkt, void *my_pkt);
 
 /* 
@@ -65,9 +69,12 @@ void do_verify(JCR *jcr)
 static int verify_file(FF_PKT *ff_pkt, void *pkt) 
 {
    char attribs[MAXSTRING];
+   char attribsEx[MAXSTRING];
    int64_t n;
    int stat;
    BFILE bfd;
+   BFILE rsrc_bfd;
+   bool hfsplus = false;
    struct MD5Context md5c;
    struct SHA1Context sha1c;
    unsigned char signature[25];       /* large enough for either */
@@ -171,97 +178,171 @@ static int verify_file(FF_PKT *ff_pkt, void *pkt)
       }
    }
 
-   encode_stat(attribs, ff_pkt, 0);
-     
-   P(jcr->mutex);
-   jcr->JobFiles++;                 /* increment number of files sent */
-   pm_strcpy(jcr->last_fname, ff_pkt->fname);
-   V(jcr->mutex);
-
-   /* 
-    * Send file attributes to Director
-    *  File_index
-    *  Stream
-    *  Verify Options
-    *  Filename (full path)
-    *  Encoded attributes
-    *  Link name (if type==FT_LNK)
-    * For a directory, link is the same as fname, but with trailing
-    * slash. For a linked file, link is the link.
-    */
-   /* Send file attributes to Director (note different format than for Storage) */
-   Dmsg2(400, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, ff_pkt->fname);
-   if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) {
-      stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
-                   STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 
-                   0, attribs, 0, ff_pkt->link, 0);
-   } else if (ff_pkt->type == FT_DIREND) {
-      /* Here link is the canonical filename (i.e. with trailing slash) */
-      stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
-                   STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->link, 
-                   0, attribs, 0, 0);
-   } else {
-      stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
-                   STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 
-                   0, attribs, 0, 0);
-   }
-   Dmsg2(20, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
-   if (!stat) {
-      Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
-      if (is_bopen(&bfd)) {
-        bclose(&bfd);
+   binit(&rsrc_bfd);         /* we check if this is open below */
+#ifdef HAVE_DARWIN_OS
+   /* Open resource fork if necessary */
+   if (ff_pkt->type != FT_LNKSAVED && (S_ISREG(ff_pkt->statp.st_mode) &&
+            ff_pkt->flags & FO_HFSPLUS)) {
+      /* Remember Finder Info, whether we have data or fork, or not */
+      hfsplus = true;
+      if (ff_pkt->hfsinfo.rsrclength > 0) {
+         if (bopen_rsrc(&rsrc_bfd, ff_pkt->fname, O_RDONLY | O_BINARY, 0) < 0) {
+            ff_pkt->ff_errno = errno;
+            berrno be;
+            Jmsg(jcr, M_NOTSAVED, -1, _("     Cannot open resource fork for %s: ERR=%s\n"),
+                 ff_pkt->fname, be.strerror());
+            jcr->Errors++;
+            if (is_bopen(&ff_pkt->bfd)) {
+               bclose(&ff_pkt->bfd);
+            }
+            return 1;
+         }
       }
-      return 0;
    }
+#endif
+
+      encode_stat(attribs, ff_pkt, 0);
 
-   /* If file opened, compute MD5 or SHA1 hash */
-   if (is_bopen(&bfd)  && ff_pkt->flags & FO_MD5) {
-      char MD5buf[40];               /* 24 should do */
-      MD5Init(&md5c);
-      while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) {
-        MD5Update(&md5c, ((unsigned char *)jcr->big_buf), (int)n);
-        jcr->JobBytes += n;
-        jcr->ReadBytes += n;
+      /* Now possibly extend the attributes */
+      encode_attribsEx(jcr, attribsEx, ff_pkt);
+
+      P(jcr->mutex);
+      jcr->JobFiles++;              /* increment number of files sent */
+      pm_strcpy(jcr->last_fname, ff_pkt->fname);
+      V(jcr->mutex);
+
+      /* 
+       * Send file attributes to Director
+       *       File_index
+       *       Stream
+       *       Verify Options
+       *       Filename (full path)
+       *       Encoded attributes
+       *       Link name (if type==FT_LNK)
+       * For a directory, link is the same as fname, but with trailing
+       * slash. For a linked file, link is the link.
+       */
+      /* Send file attributes to Director (note different format than for Storage) */
+      Dmsg2(400, "send ATTR inx=%d fname=%s\n", jcr->JobFiles, ff_pkt->fname);
+      if (ff_pkt->type == FT_LNK || ff_pkt->type == FT_LNKSAVED) {
+         stat = bnet_fsend(dir, "%d %d %s %s%c%s%c%s%c", jcr->JobFiles,
+               STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 
+               0, attribs, 0, ff_pkt->link, 0);
+      } else if (ff_pkt->type == FT_DIREND) {
+         /* Here link is the canonical filename (i.e. with trailing slash) */
+         stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
+               STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->link, 
+               0, attribs, 0, 0);
+      } else {
+         stat = bnet_fsend(dir,"%d %d %s %s%c%s%c%c", jcr->JobFiles,
+               STREAM_UNIX_ATTRIBUTES, ff_pkt->VerifyOpts, ff_pkt->fname, 
+               0, attribs, 0, 0);
       }
-      if (n < 0) {
-        berrno be;
-        be.set_errno(bfd.berrno);
-         Jmsg(jcr, M_ERROR, 1, _("Error reading file %s: ERR=%s\n"), 
-             ff_pkt->fname, be.strerror());
-        jcr->Errors++;
+      Dmsg2(20, "bfiled>bdird: attribs len=%d: msg=%s\n", dir->msglen, dir->msg);
+      if (!stat) {
+         Jmsg(jcr, M_FATAL, 0, _("Network error in send to Director: ERR=%s\n"), bnet_strerror(dir));
+         if (is_bopen(&bfd)) {
+            bclose(&bfd);
+         }
+         if (is_bopen(&rsrc_bfd)) {
+            bclose(&rsrc_bfd);
+         }
+         return 0;
       }
-      MD5Final(signature, &md5c);
 
-      bin_to_base64(MD5buf, (char *)signature, 16); /* encode 16 bytes */
-      Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, MD5buf);
-      bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_SIGNATURE, MD5buf,
-        jcr->JobFiles);
-      Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
-   } else if (is_bopen(&bfd) && ff_pkt->flags & FO_SHA1) {
-      char SHA1buf[40];              /* 24 should do */
-      SHA1Init(&sha1c);
-      while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) {
-        SHA1Update(&sha1c, ((unsigned char *)jcr->big_buf), (int)n);
-        jcr->JobBytes += n;
-        jcr->ReadBytes += n;
+      /* compute MD5 or SHA1 hash */
+      if ((is_bopen(&bfd) || hfsplus) && ff_pkt->flags & FO_MD5) {
+         char MD5buf[40];                    /* 24 should do */
+         MD5Init(&md5c);
+         if (is_bopen(&bfd)) {
+            while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) {
+               MD5Update(&md5c, ((unsigned char *)jcr->big_buf), (int)n);
+               jcr->JobBytes += n;
+               jcr->ReadBytes += n;
+            }
+            if (n < 0) {
+               berrno be;
+               be.set_errno(bfd.berrno);
+               Jmsg(jcr, M_ERROR, 1, _("Error reading file %s: ERR=%s\n"), 
+                     ff_pkt->fname, be.strerror());
+               jcr->Errors++;
+            }
+         }
+#ifdef HAVE_DARWIN_OS
+         if (is_bopen(&rsrc_bfd)) {
+            while ((n=bread(&rsrc_bfd, jcr->big_buf, jcr->buf_size)) > 0) {
+               MD5Update(&md5c, ((unsigned char *)jcr->big_buf), (int)n);
+               jcr->JobBytes += n;
+               jcr->ReadBytes += n;
+            }
+            if (n < 0) {
+               berrno be;
+               be.set_errno(rsrc_bfd.berrno);
+               Jmsg(jcr, M_ERROR, 1, _("Error reading file %s: ERR=%s\n"), 
+                     ff_pkt->fname, be.strerror());
+               jcr->Errors++;
+            }
+         }
+         if (ff_pkt->flags & FO_HFSPLUS) {
+            MD5Update(&md5c, ((unsigned char *)ff_pkt->hfsinfo.fndrinfo), 32);
+         }
+#endif
+         MD5Final(signature, &md5c);
+
+         bin_to_base64(MD5buf, (char *)signature, 16); /* encode 16 bytes */
+         Dmsg2(400, "send inx=%d MD5=%s\n", jcr->JobFiles, MD5buf);
+         bnet_fsend(dir, "%d %d %s *MD5-%d*", jcr->JobFiles, STREAM_MD5_SIGNATURE, MD5buf,
+               jcr->JobFiles);
+         Dmsg2(20, "bfiled>bdird: MD5 len=%d: msg=%s\n", dir->msglen, dir->msg);
+      } else if ((is_bopen(&bfd) || hfsplus) && ff_pkt->flags & FO_SHA1) {
+         char SHA1buf[40];           /* 24 should do */
+         SHA1Init(&sha1c);
+         if (is_bopen(&bfd)) {
+            while ((n=bread(&bfd, jcr->big_buf, jcr->buf_size)) > 0) {
+               SHA1Update(&sha1c, ((unsigned char *)jcr->big_buf), (int)n);
+               jcr->JobBytes += n;
+               jcr->ReadBytes += n;
+            }
+            if (n < 0) {
+               berrno be;
+               be.set_errno(bfd.berrno);
+               Jmsg(jcr, M_ERROR, 1, _("Error reading file %s: ERR=%s\n"), 
+                     ff_pkt->fname, be.strerror());
+               jcr->Errors++;
+            }
+         }
+#ifdef HAVE_DARWIN_OS
+         if (is_bopen(&rsrc_bfd)) {
+            while ((n=bread(&rsrc_bfd, jcr->big_buf, jcr->buf_size)) > 0) {
+               SHA1Update(&sha1c, ((unsigned char *)jcr->big_buf), (int)n);
+               jcr->JobBytes += n;
+               jcr->ReadBytes += n;
+            }
+            if (n < 0) {
+               berrno be;
+               be.set_errno(rsrc_bfd.berrno);
+               Jmsg(jcr, M_ERROR, 1, _("Error reading file %s: ERR=%s\n"), 
+                     ff_pkt->fname, be.strerror());
+               jcr->Errors++;
+            }
+         }
+         if (ff_pkt->flags & FO_HFSPLUS) {
+            SHA1Update(&sha1c, ((unsigned char *)ff_pkt->hfsinfo.fndrinfo), 32);
+         }
+#endif
+         SHA1Final(&sha1c, signature);
+
+         bin_to_base64(SHA1buf, (char *)signature, 20); /* encode 20 bytes */
+         Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, SHA1buf);
+         bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_SIGNATURE, 
+               SHA1buf, jcr->JobFiles);
+         Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
       }
-      if (n < 0) {
-        berrno be;
-        be.set_errno(bfd.berrno);
-         Jmsg(jcr, M_ERROR, 1, _("Error reading file %s: ERR=%s\n"), 
-             ff_pkt->fname, be.strerror());
-        jcr->Errors++;
+      if (is_bopen(&bfd)) {
+         bclose(&bfd);
       }
-      SHA1Final(&sha1c, signature);
-
-      bin_to_base64(SHA1buf, (char *)signature, 20); /* encode 20 bytes */
-      Dmsg2(400, "send inx=%d SHA1=%s\n", jcr->JobFiles, SHA1buf);
-      bnet_fsend(dir, "%d %d %s *SHA1-%d*", jcr->JobFiles, STREAM_SHA1_SIGNATURE, 
-        SHA1buf, jcr->JobFiles);
-      Dmsg2(20, "bfiled>bdird: SHA1 len=%d: msg=%s\n", dir->msglen, dir->msg);
-   }
-   if (is_bopen(&bfd)) {
-      bclose(&bfd);
+      if (is_bopen(&rsrc_bfd)) {
+         bclose(&rsrc_bfd);
+      }
+      return 1;
    }
-   return 1;
-}
index 7d2c71b5d1fd7e0aaaf4db815c7efae209e56884..2bbdacc573ad6b9cf3ba4177be6642844bf0329b 100644 (file)
@@ -21,9 +21,9 @@ dummy:
 
 #
 LIBSRCS = find.c match.c find_one.c attibs.c create_file.c \
-         bfile.c enable_priv.c makepath.c save-cwd.c winapi.c
+         bfile.c enable_priv.c fstype.c makepath.c save-cwd.c winapi.c
 LIBOBJS = find.o match.o find_one.o attribs.o create_file.o \
-         bfile.o enable_priv.o makepath.o save-cwd.o winapi.o
+         bfile.o enable_priv.o fstype.o makepath.o save-cwd.o winapi.o
 
 .SUFFIXES:     .c .o
 .PHONY:
index 5cc0fdd2c086813ba6847acdbb3288615911cd04..46fdb6d3c916a432865c762dd398643f4d3e04fa 100644 (file)
@@ -94,9 +94,9 @@ dummy:
 
 #
 LIBSRCS = find.c match.c find_one.c attibs.c create_file.c \
-         bfile.c enable_priv.c makepath.c save-cwd.c winapi.c
+         bfile.c enable_priv.c fstype.c makepath.c save-cwd.c winapi.c
 LIBOBJS = find.o match.o find_one.o attribs.o create_file.o \
-         bfile.o enable_priv.o makepath.o save-cwd.o winapi.o
+         bfile.o enable_priv.o fstype.o makepath.o save-cwd.o winapi.o
 
 .SUFFIXES:     .c .o
 .PHONY:
index 32a839bf3e9a0bb9bc127492a408f412ee37c5a2..ec9ecd6c9112974a0e2e1ed7dcf6c86635362542 100755 (executable)
@@ -420,7 +420,16 @@ bool set_attributes(JCR *jcr, ATTR *attr, BFILE *ofd)
  */
 int encode_attribsEx(JCR *jcr, char *attribsEx, FF_PKT *ff_pkt)
 {
+#ifdef HAVE_DARWIN_OS
+   char *p;
+   p = attribsEx;
+   if (ff_pkt->flags & FO_HFSPLUS) {
+      p += to_base64((uint64_t)(ff_pkt->hfsinfo.rsrclength), p);
+   }
+   *p = 0;
+#else
    *attribsEx = 0;                   /* no extended attributes */
+#endif
    return STREAM_UNIX_ATTRIBUTES;
 }
 
index bd5fefbb1ca7efa17022cd21f7a518429411e992..dc72bbc7bc7464ec7022b35ea2c2781505b030d8 100644 (file)
 #include "bacula.h"
 #include "find.h"
 
+#ifdef HAVE_DARWIN_OS
+#include <sys/paths.h>
+#endif
+
 /* ===============================================================
  * 
  *           U N I X   AND   W I N D O W S
@@ -77,6 +81,10 @@ const char *stream_to_ascii(int stream)
       return "Program data";
    case STREAM_SHA1_SIGNATURE:
       return "SHA1 signature";
+   case STREAM_MACOS_FORK_DATA:
+      return "HFS+ resource fork";
+   case STREAM_HFSPLUS_ATTRIBUTES:
+      return "HFS+ Finder Info";
    default:
       sprintf(buf, "%d", stream);
       return (const char *)buf;
@@ -178,6 +186,10 @@ int is_stream_supported(int stream)
    case STREAM_PROGRAM_NAMES:
    case STREAM_PROGRAM_DATA:
    case STREAM_SHA1_SIGNATURE:
+#ifdef HAVE_DARWIN_OS
+   case STREAM_MACOS_FORK_DATA:
+   case STREAM_HFSPLUS_ATTRIBUTES:
+#endif
    case 0:                           /* compatibility with old tapes */
       return 1;
    }
@@ -469,6 +481,10 @@ int is_stream_supported(int stream)
    case STREAM_PROGRAM_NAMES:
    case STREAM_PROGRAM_DATA:
    case STREAM_SHA1_SIGNATURE:
+#ifdef HAVE_DARWIN_OS
+   case STREAM_MACOS_FORK_DATA:
+   case STREAM_HFSPLUS_ATTRIBUTES:
+#endif
    case 0:                           /* compatibility with old tapes */
       return 1;
 
@@ -513,6 +529,24 @@ int bopen(BFILE *bfd, const char *fname, int flags, mode_t mode)
    return bfd->fid;
 }
 
+#ifdef HAVE_DARWIN_OS
+/* Open the resource fork of a file. */
+int bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode)
+{
+   POOLMEM *rsrc_fname;
+   size_t fname_len;
+
+   fname_len = strlen(fname);
+   rsrc_fname = get_pool_memory(PM_FNAME);
+   bstrncpy(rsrc_fname, fname, fname_len + 1);
+   bstrncpy(rsrc_fname + fname_len, _PATH_RSRCFORKSPEC,
+      strlen(_PATH_RSRCFORKSPEC) + 1);
+   bopen(bfd, rsrc_fname, flags, mode);
+   free_pool_memory(rsrc_fname);
+   return bfd->fid;
+}
+#endif
+
 int bclose(BFILE *bfd)
 { 
    int stat;  
index 91beed66a7b4c3a90d389b76c8c0b58fc6cb880d..21a25c0cabfd600416c7eb329617a3084fa25288 100644 (file)
@@ -96,6 +96,9 @@ int     is_stream_supported(int stream);
 int     is_win32_stream(int stream);
 char   *xberror(BFILE *bfd);          /* DO NOT USE  -- use berrno class */
 int     bopen(BFILE *bfd, const char *fname, int flags, mode_t mode);
+#ifdef HAVE_DARWIN_OS
+int     bopen_rsrc(BFILE *bfd, const char *fname, int flags, mode_t mode);
+#endif
 int     bclose(BFILE *bfd);
 ssize_t bread(BFILE *bfd, void *buf, size_t count);
 ssize_t bwrite(BFILE *bfd, void *buf, size_t count);
index 2a1d7029a582a9eb4a3831b942b8b18a5512921c..03cd5c5078016a9019f31294ed2afc4eeb29b280 100644 (file)
@@ -6,6 +6,8 @@
  *    routines for the new syntax Options resource.
  *
  *  Kern E. Sibbald, MM
+ *
+ *   Version $Id$
  */
 /*
    Copyright (C) 2000-2004 Kern Sibbald and John Walker
@@ -175,6 +177,7 @@ static bool accept_file(FF_PKT *ff)
       ff->GZIP_level = fo->GZIP_level;
       ff->reader = fo->reader;
       ff->writer = fo->writer;
+      ff->fstypes = &(fo->fstype);
       ic = (ff->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0;
       for (k=0; k<fo->wild.size(); k++) {
         if (fnmatch((char *)fo->wild.get(k), ff->fname, fnmode|ic) == 0) {
@@ -239,6 +242,7 @@ static int our_callback(FF_PKT *ff, void *hpkt)
    case FT_ISARCH:
    case FT_NORECURSE:
    case FT_NOFSCHG:
+   case FT_INVALIDFS:
    case FT_NOOPEN:
 //    return ff->callback(ff, hpkt);
 
index 4a3cf4fd754d63bbf619cc6366f997a4510eebad..ba2980965473de3854f77579c3450d1f226b7493 100755 (executable)
@@ -93,7 +93,7 @@ enum {
 #define FO_ACL          (1<<14)       /* Backup ACLs */
 #define FO_NO_HARDLINK  (1<<15)       /* don't handle hard links */
 #define FO_IGNORECASE   (1<<16)       /* Ignore file name case */
-
+#define FO_HFSPLUS      (1<<17)       /* Resource forks and Finder Info */
 
 struct s_included_file {
    struct s_included_file *next;
@@ -134,6 +134,7 @@ struct findFOPTS {
    alist regex;                       /* regex string(s) */
    alist wild;                        /* wild card strings */
    alist base;                        /* list of base names */
+   alist fstype;                      /* file system type limitation */
    char *reader;                      /* reader program */
    char *writer;                      /* writer program */
 };
@@ -157,6 +158,13 @@ struct findFILESET {
    alist exclude_list;
 };
 
+#ifdef HAVE_DARWIN_OS
+struct HFSPLUS_INFO {
+   unsigned long length;              /* Mandatory field */
+   char fndrinfo[32];                 /* Finder Info */
+   off_t rsrclength;                  /* Size of resource fork */
+};
+#endif
 
 /*
  * Definition of the find_files packet passed as the
@@ -189,9 +197,17 @@ struct FF_PKT {
    int GZIP_level;                    /* compression level */
    char *reader;                      /* reader program */
    char *writer;                      /* writer program */
+   alist *fstypes;                   /* allowed file system types */
 
    /* 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 */
+   BFILE rsrc_bfd;                    /* fd for resource forks */
+#ifdef HAVE_DARWIN_OS
+   struct HFSPLUS_INFO hfsinfo;       /* Finder Info and resource fork size */
+#endif
 };
 
 
index d9f6d4d44ff36b67590d44c1194b372abe9a6135..e4b1bcfead593dfdc5043301909de1994e8ab9ab 100755 (executable)
 
    Thanks to the TAR programmers.
 
+     Version $Id$
+
  */
 
 #include "bacula.h"
 #include "find.h"
+#ifdef HAVE_DARWIN_OS
+#include <sys/attr.h>
+#endif
 
 extern int32_t name_max;             /* filename max length */
 extern int32_t path_max;             /* path name max length */
@@ -55,6 +60,36 @@ static void free_dir_ff_pkt(FF_PKT *dir_ff_pkt)
    free(dir_ff_pkt);
 }
 
+/*
+ * Check to see if we allow the file system type of a file or directory.
+ * If we do not have a list of file system types, we accept anything.
+ */
+static int accept_fstype(FF_PKT *ff, void *dummy) {
+   int i;
+   char *fs;
+   bool accept = true;
+
+   if (ff->fstypes->size()) {
+      accept = false;
+      fs = fstype(ff->fname);
+      if (fs == NULL) {
+         Dmsg1(50, "Cannot determine file system type for \"%s\"\n", ff->fname);
+      } else {
+        for (i = 0; i <ff->fstypes->size(); ++i) {
+           if (strcmp(fs, (char *)ff->fstypes->get(i)) == 0) {
+               Dmsg2(100, "Accepting fstype %s for \"%s\"\n", fs, ff->fname);
+              accept = true;
+              break;
+           }
+            Dmsg3(200, "fstype %s for \"%s\" does not match %s\n", fs,
+                 ff->fname, ff->fstypes->get(i));
+        }
+        free(fs);
+      }
+   }
+   return accept;
+}
+
 /*
  * Find a single file.                       
  * handle_file is the callback for handling the file.
@@ -79,6 +114,23 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
        return handle_file(ff_pkt, pkt);
    }
 
+#ifdef HAVE_DARWIN_OS
+   if (S_ISREG(ff_pkt->statp.st_mode) && ff_pkt->flags & FO_HFSPLUS) {
+       /* TODO: initialise attrList once elsewhere? */
+       struct attrlist attrList;
+       memset(&attrList, 0, sizeof(attrList));
+       attrList.bitmapcount = ATTR_BIT_MAP_COUNT;
+       attrList.commonattr = ATTR_CMN_FNDRINFO;
+       attrList.fileattr = ATTR_FILE_RSRCLENGTH;
+       if (getattrlist(fname, &attrList, &ff_pkt->hfsinfo,
+               sizeof(ff_pkt->hfsinfo), 0) != 0) {
+         ff_pkt->type = FT_NOSTAT;
+         ff_pkt->ff_errno = errno;
+         return handle_file(ff_pkt, pkt);
+       }
+   }
+#endif
+
    Dmsg1(300, "File ----: %s\n", fname);
 
    /* Save current times of this directory in case we need to
@@ -87,6 +139,27 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
    restore_times.actime = ff_pkt->statp.st_atime;
    restore_times.modtime = ff_pkt->statp.st_mtime;
 
+   if (top_level) {
+      /*
+       * Check if we start with an allowed file system.
+       *
+       * handle_file() calls accept_file() which fills in ff_pkt->fstypes
+       * Temporarily use our own handler with a fake, but probable, type.
+       */
+      int (*callback)(FF_PKT *, void *) = ff_pkt->callback;
+      ff_pkt->callback = accept_fstype;
+      ff_pkt->type = FT_DIRBEGIN;
+      rtn_stat = handle_file(ff_pkt, pkt);
+      ff_pkt->callback = callback;
+      if (!rtn_stat) {
+        ff_pkt->type = FT_INVALIDFS;
+        if (ff_pkt->flags & FO_KEEPATIME) {
+           utime(fname, &restore_times);
+        }
+         Jmsg1(jcr, M_ERROR, 0, _("Top level entry \"%s\" has an unlisted fstype\n"), fname);
+        return rtn_stat;
+      }
+   }
 
    /* 
     * If this is an Incremental backup, see if file was modified
@@ -292,16 +365,22 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
       /* 
        * Do not descend into subdirectories (recurse) if the
        * user has turned it off for this directory.
-       * Or if we are crossing file systems, 
-       * avoid doing so if the user only wants to dump one file system.
+       *
+       * If we are crossing file systems, we are either not allowed
+       * to cross, or we may be restricted by a list of permitted
+       * file systems.
        */
       if (ff_pkt->flags & FO_NO_RECURSION) {
         ff_pkt->type = FT_NORECURSE;
         recurse = false;
-      } else if (!top_level && !(ff_pkt->flags & FO_MULTIFS) &&
-          parent_device != ff_pkt->statp.st_dev) {
-        ff_pkt->type = FT_NOFSCHG;
-        recurse = false;
+      } else if (!top_level && parent_device != ff_pkt->statp.st_dev) {
+        if(!(ff_pkt->flags & FO_MULTIFS)) {
+           ff_pkt->type = FT_NOFSCHG;
+           recurse = false;
+        } else if (!accept_fstype(ff_pkt, NULL)) {
+           ff_pkt->type = FT_INVALIDFS;
+           recurse = false;
+        }
       }
       if (!recurse) {
         rtn_stat = handle_file(ff_pkt, pkt);
@@ -310,7 +389,10 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt, int handle_file(FF_PKT *ff, void *hpkt),
         }
         free(link);
         free_dir_ff_pkt(dir_ff_pkt);
-        ff_pkt->link = ff_pkt->fname;     /* reset "link" */
+         ff_pkt->link = ff_pkt->fname;     /* reset "link" */
+        if (ff_pkt->flags & FO_KEEPATIME) {
+           utime(fname, &restore_times);
+        }
         return rtn_stat;
       }
 
diff --git a/bacula/src/findlib/fstype.c b/bacula/src/findlib/fstype.c
new file mode 100644 (file)
index 0000000..1de11ef
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *  Implement routines to determine file system types.
+ *
+ *   Written by Preben 'Peppe' Guldberg, December MMIV
+ * 
+ *   Version $Id$
+ */
+
+/*
+   Copyright (C) Kern Sibbald
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#ifndef TEST_PROGRAM
+#include "bacula.h"
+#include "find.h"
+#else /* Set up for testing a stand alone program */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define SUPPORTEDOSES      "HAVE_DARWIN_OS\n" \
+                           "HAVE_FREEBSD_OS\n" \
+                           "HAVE_HPUX_OS\n" \
+                           "HAVE_IRIX_OS\n" \
+                           "HAVE_LINUX_OS\n" \
+                           "HAVE_NETBSD_OS\n" \
+                           "HAVE_OPENBSD_OS\n" \
+                           "HAVE_SUN_OS\n"
+#define POOLMEM           char
+#define bstrdup           strdup
+#define Dmsg0(n,s)         fprintf(stderr, s "\n");
+#define Dmsg1(n,s,a1)      fprintf(stderr, s "\n", a1);
+#define Dmsg2(n,s,a1,a2)   fprintf(stderr, s "\n", a1, a2);
+#endif
+
+/*
+ * These functions should be implemented for each OS
+ *
+ *      POOLMEM *fstype(const char *fname);
+ */
+#if defined(HAVE_DARWIN_OS) \
+   || defined(HAVE_FREEBSD_OS ) \
+   || defined(HAVE_NETBSD_OS) \
+   || defined(HAVE_OPENBSD_OS)
+#include <sys/param.h>
+#include <sys/mount.h>
+POOLMEM *fstype(const char *fname)
+{
+   struct statfs st;
+   if (statfs(fname, &st) == 0) {
+      return bstrdup(st.f_fstypename);
+   }
+   Dmsg1(50, "statfs() failed for \"%s\"", fname);
+   return NULL;
+}
+
+#elif defined(HAVE_HPUX_OS) \
+   || defined(HAVE_IRIX_OS)
+#include <sys/types.h>
+#include <sys/statvfs.h>
+POOLMEM *fstype(const char *fname)
+{
+   struct statvfs st;
+   if (statvfs(fname, &st) == 0) {
+      return bstrdup(st.f_basetype);
+   }
+   Dmsg1(50, "statfs() failed for \"%s\"", fname);
+   return NULL;
+}
+
+#elif defined(HAVE_LINUX_OS)
+#include <sys/vfs.h>
+POOLMEM *fstype(const char *fname)
+{
+   struct statfs st;
+   if (statfs(fname, &st) == 0) {
+      /*
+       * Values nicked from statfs(2), testing and 
+       *
+       *    $ grep -r SUPER_MAGIC /usr/include/linux
+       *
+       * Entries are sorted on ("fsname")
+       */
+      switch (st.f_type) {
+
+#if 0      /* These need confirmation */
+      case 0xadf5:         return bstrdup("adfs");          /* ADFS_SUPER_MAGIC */
+      case 0xadff:         return bstrdup("affs");          /* AFFS_SUPER_MAGIC */
+      case 0x6B414653:     return bstrdup("afs");           /* AFS_FS_MAGIC */
+      case 0x0187:         return bstrdup("autofs");        /* AUTOFS_SUPER_MAGIC */
+      case 0x62646576:     return bstrdup("bdev");          /* ??? */
+      case 0x42465331:     return bstrdup("befs");          /* BEFS_SUPER_MAGIC */
+      case 0x1BADFACE:     return bstrdup("bfs");           /* BFS_MAGIC */
+      case 0x42494e4d:     return bstrdup("binfmt_misc");   /* ??? */
+      case (('C'<<8)|'N'): return bstrdup("capifs");        /* CAPIFS_SUPER_MAGIC */
+      case 0xFF534D42:     return bstrdup("cifs");          /* CIFS_MAGIC_NUMBER */
+      case 0x73757245:     return bstrdup("coda");          /* CODA_SUPER_MAGIC */
+      case 0x012ff7b7:     return bstrdup("coherent");      /* COH_SUPER_MAGIC */
+      case 0x28cd3d45:     return bstrdup("cramfs");        /* CRAMFS_MAGIC */
+      case 0x1373:         return bstrdup("devfs");         /* DEVFS_SUPER_MAGIC */
+      case 0x1cd1:         return bstrdup("devpts");        /* ??? */
+      case 0x414A53:       return bstrdup("efs");           /* EFS_SUPER_MAGIC */
+      case 0x03111965:     return bstrdup("eventpollfs");   /* EVENTPOLLFS_MAGIC */
+      case 0x137d:         return bstrdup("ext");           /* EXT_SUPER_MAGIC */
+      case 0xef51:         return bstrdup("ext2");          /* EXT2_OLD_SUPER_MAGIC */
+      case 0xBAD1DEA:      return bstrdup("futexfs");       /* ??? */
+      case 0xaee71ee7:     return bstrdup("gadgetfs");      /* GADGETFS_MAGIC */
+      case 0x00c0ffee:     return bstrdup("hostfs");        /* HOSTFS_SUPER_MAGIC */
+      case 0xf995e849:     return bstrdup("hpfs");          /* HPFS_SUPER_MAGIC */
+      case 0xb00000ee:     return bstrdup("hppfs");         /* HPPFS_SUPER_MAGIC */
+      case 0x958458f6:     return bstrdup("hugetlbfs");     /* HUGETLBFS_MAGIC */
+      case 0x12061983:     return bstrdup("hwgfs");         /* HWGFS_MAGIC */
+      case 0x66726f67:     return bstrdup("ibmasmfs");      /* IBMASMFS_MAGIC */
+      case 0x9660:         return bstrdup("iso9660");       /* ISOFS_SUPER_MAGIC */
+      case 0x9660:         return bstrdup("isofs");         /* ISOFS_SUPER_MAGIC */
+      case 0x07c0:         return bstrdup("jffs");          /* JFFS_MAGIC_SB_BITMASK */
+      case 0x72b6:         return bstrdup("jffs2");         /* JFFS2_SUPER_MAGIC */
+      case 0x3153464a:     return bstrdup("jfs");           /* JFS_SUPER_MAGIC */
+      case 0x2468:         return bstrdup("minix");         /* MINIX2_SUPER_MAGIC */
+      case 0x2478:         return bstrdup("minix");         /* MINIX2_SUPER_MAGIC2 */
+      case 0x137f:         return bstrdup("minix");         /* MINIX_SUPER_MAGIC */
+      case 0x138f:         return bstrdup("minix");         /* MINIX_SUPER_MAGIC2 */
+      case 0x19800202:     return bstrdup("mqueue");        /* MQUEUE_MAGIC */
+      case 0x4d44:         return bstrdup("msdos");         /* MSDOS_SUPER_MAGIC */
+      case 0x564c:         return bstrdup("ncpfs");         /* NCP_SUPER_MAGIC */
+      case 0x6969:         return bstrdup("nfs");           /* NFS_SUPER_MAGIC */
+      case 0x5346544e:     return bstrdup("ntfs");          /* NTFS_SB_MAGIC */
+      case 0x9fa1:         return bstrdup("openpromfs");    /* OPENPROM_SUPER_MAGIC */
+      case 0x6f70726f:     return bstrdup("oprofilefs");    /* OPROFILEFS_MAGIC */
+      case 0xa0b4d889:     return bstrdup("pfmfs");         /* PFMFS_MAGIC */
+      case 0x50495045:     return bstrdup("pipfs");         /* PIPEFS_MAGIC */
+      case 0x9fa0:         return bstrdup("proc");          /* PROC_SUPER_MAGIC */
+      case 0x002f:         return bstrdup("qnx4");          /* QNX4_SUPER_MAGIC */
+      case 0x858458f6:     return bstrdup("ramfs");         /* RAMFS_MAGIC */
+      case 0x52654973:     return bstrdup("reiserfs");      /* REISERFS_SUPER_MAGIC */
+      case 0x7275:         return bstrdup("romfs");         /* ROMFS_MAGIC */
+      case 0x858458f6:     return bstrdup("rootfs");        /* RAMFS_MAGIC */
+      case 0x67596969:     return bstrdup("rpc_pipefs");    /* RPCAUTH_GSSMAGIC */
+      case 0x517B:         return bstrdup("smbfs");         /* SMB_SUPER_MAGIC */
+      case 0x534F434B:     return bstrdup("sockfs");        /* SOCKFS_MAGIC */
+      case 0x62656572:     return bstrdup("sysfs");         /* SYSFS_MAGIC */
+      case 0x012ff7b6:     return bstrdup("sysv2");         /* SYSV2_SUPER_MAGIC */
+      case 0x012ff7b5:     return bstrdup("sysv4");         /* SYSV4_SUPER_MAGIC */
+      case 0x858458f6:     return bstrdup("tmpfs");         /* RAMFS_MAGIC */
+      case 0x01021994:     return bstrdup("tmpfs");         /* TMPFS_MAGIC */
+      case 0x15013346:     return bstrdup("udf");           /* UDF_SUPER_MAGIC */
+      case 0x00011954:     return bstrdup("ufs");           /* UFS_MAGIC */
+      case 0x9fa2:         return bstrdup("usbdevfs");      /* USBDEVICE_SUPER_MAGIC */
+      case 0xa501FCF5:     return bstrdup("vxfs");          /* VXFS_SUPER_MAGIC */
+      case 0x012ff7b4:     return bstrdup("xenix");         /* XENIX_SUPER_MAGIC */
+      case 0x58465342:     return bstrdup("xfs");           /* XFS_SB_MAGIC */
+      case 0x012fd16d:     return bstrdup("xiafs");         /* _XIAFS_SUPER_MAGIC */
+
+      case 0xef53:         return bstrdup("ext2");          /* EXT2_SUPER_MAGIC */
+   /* case 0xef53:        ext2 and ext3 are the same */    /* EXT3_SUPER_MAGIC */
+#else      /* Known good values */
+#endif
+
+      default:
+         Dmsg2(10, "Unknown file system type \"0x%x\" for \"%s\".", st.f_type,
+              fname);
+        return NULL;
+      }
+   }
+   Dmsg1(50, "statfs() failed for \"%s\"", fname);
+   return NULL;
+}
+
+#elif defined(HAVE_SUN_OS)
+#include <sys/types.h>
+#include <sys/stat.h>
+POOLMEM *fstype(const char *fname)
+{
+   struct stat st;
+   if (lstat(fname, &st) == 0) {
+      return bstrdup(st.st_fstype);
+   }
+   Dmsg1(50, "lstat() failed for \"%s\"", fname);
+   return NULL;
+}
+
+#else   /* No recognised OS */
+POOLMEM *fstype(const char *fname)
+{
+   Dmsg0(10, "!!! fstype() not implemented for this OS. !!!");
+#ifdef TEST_PROGRAM
+   Dmsg1(10, "Please define one of the following when compiling:\n\n%s\n",
+        SUPPORTEDOSES);
+   exit(EXIT_FAILURE);
+#endif
+   return NULL;
+}
+#endif
+
+#ifdef TEST_PROGRAM
+int main(int argc, char **argv)
+{
+   char *p;
+   int status = 0;
+
+   if (argc < 2) {
+      p = (argc < 1) ? "fstype" : argv[0];
+      printf("usage:\t%s path ...\n"
+            "\t%s prints the file system type and pathname of the paths.\n",
+           p, p);
+      return EXIT_FAILURE;
+   }
+   while (*++argv) {
+      if ((p = fstype(*argv)) == NULL) {
+        status = EXIT_FAILURE;
+      } else {
+         printf("%s\t%s\n", p, *argv);
+      }
+   }
+   return status;
+}
+#endif
index 58566d9cfd18898975190df4f6477c6faaa899fa..97dbbc8033233854608d5722e60675a20f362c8b 100644 (file)
@@ -64,4 +64,7 @@ int make_path(JCR *jcr, const char *argpath, int mode,
           int parent_mode, uid_t owner, gid_t group,
           int preserve_existing, char *verbose_fmt_string);
 
+/* from fstype.c */
+POOLMEM *fstype(const char *fname);
+
 /* from bfile.c -- see bfile.h */
index 281aba001887caff63cae3b5f213aca749f39ce1..917948292430617f4e05330432bd4275a6298b14 100644 (file)
@@ -552,6 +552,7 @@ static void capcmd()
    printf("%sLABEL ", dev->capabilities & CAP_LABEL ? "" : "!");
    printf("%sANONVOLS ", dev->capabilities & CAP_ANONVOLS ? "" : "!");
    printf("%sALWAYSOPEN ", dev->capabilities & CAP_ALWAYSOPEN ? "" : "!");
+   printf("%sMTIOCGET ", dev->capabilities & CAP_MTIOCGET ? "" : "!");
    printf("\n");
 
    printf(_("Device status:\n"));
@@ -1327,7 +1328,10 @@ bail_out:
       set_off = true;
       goto test_again;
    }
-   Pmsg0(-1, "You must correct this error or Bacula will not work.\n");
+   Pmsg0(-1, "You must correct this error or Bacula will not work.\n"
+            "Some systems, e.g. OpenBSD, require you to set\n"
+            "   File Block Bookkeeping = no\n"
+            "in your device resource. Use with caution.\n");
    return -2;
 }
 
@@ -1404,7 +1408,11 @@ failed:
             "nnn must match your tape driver's block size, which\n"
             "can be determined by reading your tape manufacturers\n"
             "information, and the information on your kernel dirver.\n"
-            "Fixed block sizes, however, are not normally an ideal solution.\n");
+            "Fixed block sizes, however, are not normally an ideal solution.\n"
+            "\n"
+            "Some systems, e.g. OpenBSD, require you to set\n"
+            "   File Block Bookkeeping = no\n"
+            "in your device resource. Use with caution.\n");
        return;
    }
 
index ac75f9732c6302805766c557005c42eba0e0df61..baf1e2085baade5d3e98bd8e88292b6dc1ae50d6 100644 (file)
@@ -460,7 +460,7 @@ eod_dev(DEVICE *dev)
    }
 #ifdef MTEOM
 
-   if (dev_cap(dev, CAP_FASTFSF) && !dev_cap(dev, CAP_EOM)) {
+   if (dev_cap(dev, CAP_MTIOCGET) && dev_cap(dev, CAP_FASTFSF) && !dev_cap(dev, CAP_EOM)) {
       struct mtget mt_stat;
       Dmsg0(100,"Using FAST FSF for EOM\n");
       if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno <= 0) {
@@ -479,12 +479,13 @@ eod_dev(DEVICE *dev)
       }
    }
 
-   if (dev_cap(dev, CAP_EOM)) {
-      Dmsg0(100,"Using EOM for EOM\n");
-      mt_com.mt_op = MTEOM;
-      mt_com.mt_count = 1;
-   }
-   if (dev_cap(dev, CAP_FASTFSF) || dev_cap(dev, CAP_EOM)) {
+   if (dev_cap(dev, CAP_MTIOCGET) && (dev_cap(dev, CAP_FASTFSF) || dev_cap(dev, CAP_EOM))) {
+      if (dev_cap(dev, CAP_EOM)) {
+         Dmsg0(100,"Using EOM for EOM\n");
+        mt_com.mt_op = MTEOM;
+        mt_com.mt_count = 1;
+      }
+
       if ((stat=ioctl(dev->fd, MTIOCTOP, (char *)&mt_com)) < 0) {
         berrno be;
         clrerror_dev(dev, mt_com.mt_op);
@@ -532,13 +533,11 @@ eod_dev(DEVICE *dev)
         if (file_num == (int)dev->file) {
            struct mtget mt_stat;
             Dmsg1(100, "fsf_dev did not advance from file %d\n", file_num);
-#ifndef HAVE_OPENBSD_OS
-           if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && 
+           if (dev_cap(dev, CAP_MTIOCGET) && ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && 
                      mt_stat.mt_fileno >= 0) {
                Dmsg2(100, "Adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
               dev->file = mt_stat.mt_fileno;
            }
-#endif
            stat = 0;
            break;                    /* we are not progressing, bail out */
         }
@@ -554,7 +553,7 @@ eod_dev(DEVICE *dev)
       /* Backup over EOF */
       stat = bsf_dev(dev, 1);
       /* If BSF worked and fileno is known (not -1), set file */
-      if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) {
+      if (dev_cap(dev, CAP_MTIOCGET) && ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) {
          Dmsg2(100, "BSFATEOF adjust file from %d to %d\n", dev->file , mt_stat.mt_fileno);
         dev->file = mt_stat.mt_fileno;
       } else {
@@ -679,7 +678,11 @@ uint32_t status_dev(DEVICE *dev)
          Dmsg0(-20, " IM_REP_EN");
       }
 #endif /* !SunOS && !OSF */
-      Dmsg2(-20, " file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
+      if (dev_cap(dev, CAP_MTIOCGET)) {
+         Dmsg2(-20, " file=%d block=%d\n", mt_stat.mt_fileno, mt_stat.mt_blkno);
+      } else {
+         Dmsg2(-20, " file=%d block=%d\n", -1, -1);
+      }
    } else {
       stat |= BMT_ONLINE | BMT_BOT;
    }
@@ -833,7 +836,7 @@ fsf_dev(DEVICE *dev, int num)
     *  the SCSI driver will ensure that we do not
     *  forward space past the end of the medium.
     */
-   if (dev_cap(dev, CAP_FSF) && dev_cap(dev, CAP_FASTFSF)) {
+   if (dev_cap(dev, CAP_FSF) && dev_cap(dev, CAP_MTIOCGET) && dev_cap(dev, CAP_FASTFSF)) {
       mt_com.mt_op = MTFSF;
       mt_com.mt_count = num;
       stat = ioctl(dev->fd, MTIOCTOP, (char *)&mt_com);
@@ -1035,15 +1038,12 @@ fsr_dev(DEVICE *dev, int num)
       struct mtget mt_stat;
       clrerror_dev(dev, MTFSR);
       Dmsg1(100, "FSF fail: ERR=%s\n", be.strerror());
-#ifndef HAVE_OPENBSD_OS
-      if (ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) {
+      if (dev_cap(dev, CAP_MTIOCGET) && ioctl(dev->fd, MTIOCGET, (char *)&mt_stat) == 0 && mt_stat.mt_fileno >= 0) {
          Dmsg4(100, "Adjust from %d:%d to %d:%d\n", dev->file, 
            dev->block_num, mt_stat.mt_fileno, mt_stat.mt_blkno);
         dev->file = mt_stat.mt_fileno;
         dev->block_num = mt_stat.mt_blkno;
-      } else
-#endif
-      {
+      } else {
         if (dev->state & ST_EOF) {
            dev->state |= ST_EOT;
         } else {
index adb7674af9be0eb03a0d7a1b3a39f9d329f463a5..c6871518dc57b6925e91a494b03b0bf0bf260fca 100644 (file)
@@ -90,6 +90,7 @@ enum {
 #define CAP_TWOEOF         (1<<17)    /* Write two eofs for EOM */
 #define CAP_CLOSEONPOLL    (1<<18)    /* Close device on polling */
 #define CAP_POSITIONBLOCKS (1<<19)    /* Use block positioning */
+#define CAP_MTIOCGET       (1<<20)    /* Basic support for fileno and blkno */
 
 /* Test state */
 #define dev_state(dev, st_state) ((dev)->state & (st_state))
index 616b068abda2fdfc6f4eb088510c91cdc864eb47..3275c91452f049b3bcaeece8e1da5341c4d0f902 100644 (file)
@@ -112,6 +112,10 @@ const char *stream_to_ascii(int stream, int fi)
        return "PROG-NAMES";
     case STREAM_PROGRAM_DATA:
        return "PROG-DATA";
+    case STREAM_MACOS_FORK_DATA:
+       return "MACOS-RSRC";
+    case STREAM_HFSPLUS_ATTRIBUTES:
+       return "HFSPLUS-ATTR";
     case -STREAM_UNIX_ATTRIBUTES:
        return "contUATTR";
     case -STREAM_FILE_DATA:
@@ -136,6 +140,10 @@ const char *stream_to_ascii(int stream, int fi)
        return "contPROG-NAMES";
     case -STREAM_PROGRAM_DATA:
        return "contPROG-DATA";
+    case -STREAM_MACOS_FORK_DATA:
+       return "contMACOS-RSRC";
+    case -STREAM_HFSPLUS_ATTRIBUTES:
+       return "contHFSPLUS-ATTR";
     default:
        sprintf(buf, "%d", stream);
        return buf;     
index 8a8de08288f6630e1a2e8c84d2f659de92921cd3..22f071c22c8656ffab2594b3180319e7ad02d9fc 100644 (file)
@@ -102,6 +102,7 @@ static RES_ITEM dev_items[] = {
    {"autochanger",           store_yesno,  ITEM(res_dev.cap_bits), CAP_AUTOCHANGER, ITEM_DEFAULT, 0},
    {"closeonpoll",           store_yesno,  ITEM(res_dev.cap_bits), CAP_CLOSEONPOLL, ITEM_DEFAULT, 0},
    {"blockpositioning",      store_yesno,  ITEM(res_dev.cap_bits), CAP_POSITIONBLOCKS, ITEM_DEFAULT, 1},
+   {"usemtiocget",           store_yesno,  ITEM(res_dev.cap_bits), CAP_MTIOCGET, ITEM_DEFAULT, 1},
    {"changerdevice",         store_strname,ITEM(res_dev.changer_name), 0, 0, 0},
    {"changercommand",        store_strname,ITEM(res_dev.changer_command), 0, 0, 0},
    {"alertcommand",          store_strname,ITEM(res_dev.alert_command), 0, 0, 0},
index 64dffb6b6c42717669049d52f8034344b930fc03..7b53649f00efa19b2001cd484ffefa42bcf4fd57 100644 (file)
@@ -38,7 +38,7 @@ DIRCONFOBJS = ../dird/dird_conf.o ../dird/run_conf.o ../dird/inc_conf.o
 .c.o:
        $(CXX) $(DEFS) $(DEBUG) -c $(CPPFLAGS) -I$(srcdir) -I$(basedir) $(DINCLUDE) $(CFLAGS) $<
 #-------------------------------------------------------------------------
-all: Makefile bsmtp dbcheck testfind testls 
+all: Makefile bsmtp dbcheck fstype testfind testls 
        @echo "==== Make of tools is good ===="
        @echo " "
 
@@ -48,6 +48,9 @@ bsmtp:        bsmtp.o ../lib/libbac.a
 dbcheck: dbcheck.o ../lib/libbac.a ../cats/libsql.a $(DIRCONFOBJS)
        $(CXX) $(LDFLAGS) -L../lib -L../cats -o $@ dbcheck.o $(DIRCONFOBJS) -lsql -lbac -lm $(DB_LIBS) $(LIBS) 
 
+fstype: fstype.o ../lib/libbac.a ../findlib/libfind.a
+       $(CXX) $(LDFLAGS) -L../lib -L../findlib -o $@ fstype.o -lfind -lbac -lm $(DLIB) $(LIBS) 
+
 testfind: ../findlib/libfind.a ../lib/libbac.a $(FINDOBJS)
        $(CXX) -g $(LDFLAGS) -L. -L../lib -L../findlib -o $@ $(FINDOBJS) \
          $(DLIB) -lfind -lbac -lm $(LIBS) 
diff --git a/bacula/src/tools/fstype.c b/bacula/src/tools/fstype.c
new file mode 100644 (file)
index 0000000..c34fe51
--- /dev/null
@@ -0,0 +1,91 @@
+/*  
+ * Program for determining file system type
+ *
+ *   Written by Preben 'Peppe' Guldberg, December MMIV
+ * 
+ *   Version $Id$
+ *   
+ */
+
+/*
+   Copyright (C) 2004 Kern Sibbald               
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public
+   License along with this program; if not, write to the Free
+   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+   MA 02111-1307, USA.
+
+ */
+
+#include "bacula.h"
+#include "findlib/find.h"
+
+static void usage()
+{
+   fprintf(stderr, _(
+"\n"
+"Usage: fstype [-d debug_level] path ...\n"
+"\n"
+"       Print the file system type a given file/directory is on.\n"
+"       The following options are supported:\n"
+"\n"
+"       -v     print both path and file system type.\n"
+"       -?     print this message.\n"
+"\n"));
+
+   exit(1);
+}
+
+
+int
+main (int argc, char *const *argv)
+{
+   POOLMEM *fs;
+   int verbose = 0;
+   int status = 0;
+   int ch, i;
+
+   while ((ch = getopt(argc, argv, "v?")) != -1) {
+      switch (ch) {
+         case 'v':
+           verbose = 1;
+           break;
+         case '?':
+        default:
+           usage();
+
+      }  
+   }
+   argc -= optind;
+   argv += optind;
+
+   if (argc < 1) {
+      usage();
+   }
+
+   for (i = 0; i < argc; --argc, ++argv) {
+      if ((fs = fstype(*argv)) != NULL) {
+        if (verbose) {
+            printf("%s: %s\n", *argv, fs);
+        } else {
+           puts(fs);
+        }
+        free(fs);
+      } else {
+         fprintf(stderr, "%s: unknown\n", *argv);
+        status = 1;
+      }
+   }
+
+   exit(status);
+}
index 61e64a271780ab1a24c60f92bde3fdaa581a1f9e..3630884ead9a5b91f4caf14a3a5b1cb79d1b5b4a 100644 (file)
@@ -208,12 +208,22 @@ static int print_file(FF_PKT *ff, void *pkt)
       break;
    case FT_DIRBEGIN:
       return 1;
+   case FT_NORECURSE:
+   case FT_NOFSCHG:
+   case FT_INVALIDFS:
    case FT_DIREND:
-      if (debug_level == 1) {
-         printf("%s\n", ff->fname);
-      } else if (debug_level > 1) {
-         printf("Dir: %s\n", ff->fname);
+      if (debug_level) {
+        char errmsg[100] = "";
+        if (ff->type == FT_NORECURSE) {
+           bstrncpy(errmsg, "\t[will not descend: recursion turned off]", sizeof(errmsg));
+        } else if (ff->type == FT_NOFSCHG) {
+           bstrncpy(errmsg, "\t[will not descend: file system change not allowed]", sizeof(errmsg));
+        } else if (ff->type == FT_INVALIDFS) {
+           bstrncpy(errmsg, "\t[will not descend: disallowed file system]", sizeof(errmsg));
+        }
+        printf("%s%s%s\n", (debug_level > 1 ? "Dir: " : ""), ff->fname, errmsg);
       }
+      ff->type = FT_DIREND;
       count_files(ff);
       break;
    case FT_SPEC:
@@ -239,12 +249,6 @@ static int print_file(FF_PKT *ff, void *pkt)
    case FT_ISARCH:
       printf(_("Err: Attempt to backup archive. Not saved. %s\n"), ff->fname);
       break;
-   case FT_NORECURSE:
-      printf(_("Recursion turned off. Directory not entered. %s\n"), ff->fname);
-      break;
-   case FT_NOFSCHG:
-      printf(_("Skip: File system change prohibited. Directory not entered. %s\n"), ff->fname);
-      break;
    case FT_NOOPEN:
       printf(_("Err: Could not open directory %s: %s\n"), ff->fname, strerror(errno));
       break;
index 63200ca108f661b229632547754c971cfb4c6c64..859b77eab409846d567283b27c05820295abea13 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #undef  VERSION
 #define VERSION "1.37.1"
-#define BDATE   "06 December 2004"
-#define LSMDATE "06Dec04"
+#define BDATE   "09 December 2004"
+#define LSMDATE "09Dec04"
 
 /* Debug flags */
 #undef  DEBUG