]> git.sur5r.net Git - bacula/bacula/commitdiff
Strip pathname portion off all message routines that print filename:line.
authorRobert Nelson <robertn@the-nelsons.org>
Wed, 26 Jul 2006 01:36:23 +0000 (01:36 +0000)
committerRobert Nelson <robertn@the-nelsons.org>
Wed, 26 Jul 2006 01:36:23 +0000 (01:36 +0000)
Print additional messages show the elapsed time and transfer rate for the spool portion of a spooled backup job and also for the tape write portion.

Add DriveType directive to the Director's Include Option FileSet resource.  Allowed values are: fixed, removable, cdrom, and remote.  There is only an implementation for Windows because it is the only platform that has the concept of drives.

Adds EnhancedWild directive to the Director's Include Option FileSet resource.  Allowed values are: yes and no.

When EnhancedWild is enabled then the processing of the Wild, WildDir and WildFile is changed in the following ways.

Patterns conform to Posix
\ is not a special character in character classification []
To match a - it must be the first or last character
To match a ] it must be the first character

fnmatch option FNM_FILE_NAME is specified
* doesn't match a / so it won't match multiple directory levels in a path

Relative WildFile patterns (ones without a leading /) match against the filename portion
This in combination with the FNM_FILE_NAME fnmatch() flag makes directives such as WildFile = abc*.def work as expected.

Adds support for the shell's feature of brace expansion.

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

16 files changed:
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/filed/backup.c
bacula/src/filed/job.c
bacula/src/findlib/Makefile.in
bacula/src/findlib/find.c
bacula/src/findlib/find.h
bacula/src/findlib/find_one.c
bacula/src/findlib/protos.h
bacula/src/lib/Makefile.in
bacula/src/lib/message.c
bacula/src/stored/append.c
bacula/src/stored/spool.c
bacula/src/tools/Makefile.in

index e7ba378dd404625dec84e46d943eb374e1d70bb1..59cb3873c3926b1af0c719ae2ff77d092912b305 100644 (file)
@@ -663,6 +663,15 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
          for (j=0; j<incexe->num_opts; j++) {
             FOPTS *fo = incexe->opts_list[j];
             sendit(sock, "      O %s\n", fo->opts);
+
+            bool enhanced_wild = false;
+            for (k=0; fo->opts[k]!='\0'; k++) {
+               if (fo->opts[k]=='W') {
+                  enhanced_wild = true;
+                  break;
+               }
+            }
+
             for (k=0; k<fo->regex.size(); k++) {
                sendit(sock, "      R %s\n", fo->regex.get(k));
             }
@@ -681,12 +690,18 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
             for (k=0; k<fo->wildfile.size(); k++) {
                sendit(sock, "      WF %s\n", fo->wildfile.get(k));
             }
+            for (k=0; k<fo->wildbase.size(); k++) {
+               sendit(sock, "      W%c %s\n", enhanced_wild ? 'B' : 'F', fo->wildbase.get(k));
+            }
             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));
             }
+            for (k=0; k<fo->drivetype.size(); k++) {
+               sendit(sock, "      XD %s\n", fo->drivetype.get(k));
+            }
             if (fo->reader) {
                sendit(sock, "      D %s\n", fo->reader);
             }
@@ -866,8 +881,10 @@ static void free_incexe(INCEXE *incexe)
       fopt->wild.destroy();
       fopt->wilddir.destroy();
       fopt->wildfile.destroy();
+      fopt->wildbase.destroy();
       fopt->base.destroy();
       fopt->fstype.destroy();
+      fopt->drivetype.destroy();
       if (fopt->reader) {
          free(fopt->reader);
       }
index f4387202c372cdfa6170c0dcf10402345b2704a5..6695df9085a96444f4df08454f38f1c3abb0cc83 100644 (file)
@@ -372,8 +372,10 @@ struct FOPTS {
    alist wild;                        /* wild card strings */
    alist wilddir;                     /* wild card strings for directories */
    alist wildfile;                    /* wild card strings for files */
+   alist wildbase;                    /* wild card strings for files without '/' */
    alist base;                        /* list of base names */
    alist fstype;                      /* file system type limitation */
+   alist drivetype;                   /* drive type limitation */
    char *reader;                      /* reader program */
    char *writer;                      /* writer program */
 };
index 6615a39d07f74a4f87b04dcdafcfe23f2d093b0f..566428ee680b516d28ef50b57a7866d29302bcbd 100644 (file)
@@ -274,6 +274,15 @@ static bool send_fileset(JCR *jcr)
          for (j=0; j<ie->num_opts; j++) {
             FOPTS *fo = ie->opts_list[j];
             bnet_fsend(fd, "O %s\n", fo->opts);
+
+            bool enhanced_wild = false;
+            for (k=0; fo->opts[k]!='\0'; k++) {
+               if (fo->opts[k]=='W') {
+                  enhanced_wild = true;
+                  break;
+               }
+            }
+
             for (k=0; k<fo->regex.size(); k++) {
                bnet_fsend(fd, "R %s\n", fo->regex.get(k));
             }
@@ -292,12 +301,18 @@ static bool send_fileset(JCR *jcr)
             for (k=0; k<fo->wildfile.size(); k++) {
                bnet_fsend(fd, "WF %s\n", fo->wildfile.get(k));
             }
+            for (k=0; k<fo->wildbase.size(); k++) {
+               bnet_fsend(fd, "W%c %s\n", enhanced_wild ? 'B' : 'F', fo->wildbase.get(k));
+            }
             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));
             }
+            for (k=0; k<fo->drivetype.size(); k++) {
+               bnet_fsend(fd, "XD %s\n", fo->drivetype.get(k));
+            }
             if (fo->reader) {
                bnet_fsend(fd, "D %s\n", fo->reader);
             }
index 3b5e0d8d52d6dda23eb358734b78e47c75a3c381..f0b9c144b12791c8fed4f171b3015ca2fe7d97a9 100644 (file)
@@ -37,6 +37,7 @@ 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_drivetype(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);
@@ -104,6 +105,8 @@ static RES_ITEM options_items[] = {
    {"fstype",          store_fstype,  {0},     0, 0, 0},
    {"hfsplussupport",  store_opts,    {0},     0, 0, 0},
    {"noatime",         store_opts,    {0},     0, 0, 0},
+   {"enhancedwild",    store_opts,    {0},     0, 0, 0},
+   {"drivetype",       store_drivetype, {0},     0, 0, 0},
    {NULL, NULL, {0}, 0, 0, 0}
 };
 
@@ -128,7 +131,8 @@ enum {
    INC_KW_ACL,
    INC_KW_IGNORECASE,
    INC_KW_HFSPLUS,
-   INC_KW_NOATIME
+   INC_KW_NOATIME,
+   INC_KW_ENHANCEDWILD
 };
 
 /*
@@ -156,6 +160,7 @@ static struct s_kw FS_option_kw[] = {
    {"ignorecase",  INC_KW_IGNORECASE},
    {"hfsplussupport", INC_KW_HFSPLUS},
    {"noatime",     INC_KW_NOATIME},
+   {"enhancedwild", INC_KW_ENHANCEDWILD},
    {NULL,          0}
 };
 
@@ -219,6 +224,8 @@ static struct s_fs_opt FS_options[] = {
    {"no",       INC_KW_HFSPLUS,       "0"},
    {"yes",      INC_KW_NOATIME,       "K"},
    {"no",       INC_KW_NOATIME,       "0"},
+   {"yes",      INC_KW_ENHANCEDWILD,  "K"},
+   {"no",       INC_KW_ENHANCEDWILD,  "0"},
    {NULL,       0,                      0}
 };
 
@@ -488,9 +495,15 @@ static void store_wild(LEX *lc, RES_ITEM *item, int index, int pass)
             res_incexe.current_opts->wilddir.append(bstrdup(lc->str));
             newsize = res_incexe.current_opts->wilddir.size();
          } else if (item->code == 2) {
-            type = "wildfile";
-            res_incexe.current_opts->wildfile.append(bstrdup(lc->str));
-            newsize = res_incexe.current_opts->wildfile.size();
+            if (strchr(lc->str, '/') != NULL) {
+               type = "wildfile";
+               res_incexe.current_opts->wildfile.append(bstrdup(lc->str));
+               newsize = res_incexe.current_opts->wildfile.size();
+            } else {
+               type = "wildbase";
+               res_incexe.current_opts->wildbase.append(bstrdup(lc->str));
+               newsize = res_incexe.current_opts->wildbase.size();
+            }
          } else {
             type = "wild";
             res_incexe.current_opts->wild.append(bstrdup(lc->str));
@@ -529,6 +542,29 @@ static void store_fstype(LEX *lc, RES_ITEM *item, int index, int pass)
    scan_to_eol(lc);
 }
 
+/* Store drivetype info */
+static void store_drivetype(LEX *lc, RES_ITEM *item, int index, int pass)
+{
+   int token;
+
+   token = lex_get_token(lc, T_SKIP_EOL);
+   if (pass == 1) {
+      /* Pickup drivetype string */
+      switch (token) {
+      case T_IDENTIFIER:
+      case T_UNQUOTED_STRING:
+      case T_QUOTED_STRING:
+         res_incexe.current_opts->drivetype.append(bstrdup(lc->str));
+         Dmsg3(900, "set drivetype %p size=%d %s\n",
+            res_incexe.current_opts, res_incexe.current_opts->drivetype.size(), lc->str);
+         break;
+      default:
+         scan_err1(lc, _("Expected an drivetype string, got: %s\n"), lc->str);
+      }
+   }
+   scan_to_eol(lc);
+}
+
 /*
  * Store Filename info. Note, for minor efficiency reasons, we
  * always increase the name buffer by 10 items because we expect
@@ -657,8 +693,10 @@ static void setup_current_opts(void)
    fo->wild.init(1, true);
    fo->wilddir.init(1, true);
    fo->wildfile.init(1, true);
+   fo->wildbase.init(1, true);
    fo->base.init(1, true);
    fo->fstype.init(1, true);
+   fo->drivetype.init(1, true);
    res_incexe.current_opts = fo;
    if (res_incexe.num_opts == 0) {
       res_incexe.opts_list = (FOPTS **)malloc(sizeof(FOPTS *));
index 450a65578a6b0b77816e7c5da3fba02b37ebfb31..ad0843ceb12cbfe595a19d933e130305026535fb 100644 (file)
@@ -250,6 +250,10 @@ static int save_file(FF_PKT *ff_pkt, void *vjcr, bool top_level)
            ff_pkt->fname);
       ff_pkt->type = FT_DIREND;       /* Backup only the directory entry */
       break;
+   case FT_INVALIDDT:
+      Jmsg(jcr, M_INFO, 1, _("     Disallowed drive type. Will not descend into %s\n"),
+           ff_pkt->fname);
+      break;
    case FT_DIREND:
       Dmsg1(130, "FT_DIREND: %s\n", ff_pkt->link);
       break;
index 9142c8e818379c468a187535d7a4c106513cf2de..ee00e1e31e6d31bd58e6c8a264bb91cb1acae56f 100644 (file)
@@ -260,8 +260,10 @@ void *handle_client_request(void *dirp)
             fo->wild.destroy();
             fo->wilddir.destroy();
             fo->wildfile.destroy();
+            fo->wildbase.destroy();
             fo->base.destroy();
             fo->fstype.destroy();
+            fo->drivetype.destroy();
             if (fo->reader) {
                free(fo->reader);
             }
@@ -285,8 +287,10 @@ void *handle_client_request(void *dirp)
             fo->wild.destroy();
             fo->wilddir.destroy();
             fo->wildfile.destroy();
+            fo->wildbase.destroy();
             fo->base.destroy();
             fo->fstype.destroy();
+            fo->drivetype.destroy();
          }
          incexe->opts_list.destroy();
          incexe->name_list.destroy();
@@ -549,8 +553,10 @@ static findFOPTS *start_options(FF_PKT *ff)
       fo->wild.init(1, true);
       fo->wilddir.init(1, true);
       fo->wildfile.init(1, true);
+      fo->wildbase.init(1, true);
       fo->base.init(1, true);
       fo->fstype.init(1, true);
+      fo->drivetype.init(1, true);
       incexe->current_opts = fo;
       incexe->opts_list.append(fo);
    }
@@ -717,8 +723,14 @@ static void add_fileset(JCR *jcr, const char *item)
       break;
    case 'X':
       current_opts = start_options(ff);
-      current_opts->fstype.append(bstrdup(item));
       state = state_options;
+      if (subcode == ' ') {
+         current_opts->fstype.append(bstrdup(item));
+      } else if (subcode == 'D') {
+         current_opts->drivetype.append(bstrdup(item));
+      } else {
+         state = state_error;
+      }
       break;
    case 'W':
       current_opts = start_options(ff);
@@ -729,6 +741,8 @@ static void add_fileset(JCR *jcr, const char *item)
          current_opts->wilddir.append(bstrdup(item));
       } else if (subcode == 'F') {
          current_opts->wildfile.append(bstrdup(item));
+      } else if (subcode == 'B') {
+         current_opts->wildbase.append(bstrdup(item));
       } else {
          state = state_error;
       }
@@ -787,12 +801,18 @@ static bool term_fileset(JCR *jcr)
          for (k=0; k<fo->wildfile.size(); k++) {
             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
          }
+         for (k=0; k<fo->wildbase.size(); k++) {
+            Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
+         }
          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 (k=0; k<fo->drivetype.size(); k++) {
+            Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
+         }
          if (fo->reader) {
             Dmsg1(400, "D %s\n", fo->reader);
          }
@@ -827,12 +847,18 @@ static bool term_fileset(JCR *jcr)
          for (k=0; k<fo->wildfile.size(); k++) {
             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
          }
+         for (k=0; k<fo->wildbase.size(); k++) {
+            Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
+         }
          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 (k=0; k<fo->drivetype.size(); k++) {
+            Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
+         }
       }
       for (j=0; j<incexe->name_list.size(); j++) {
          Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
@@ -940,6 +966,9 @@ static void set_options(findFOPTS *fo, const char *opts)
       case 'w':
          fo->flags |= FO_IF_NEWER;
          break;
+      case 'W':
+         fo->flags |= FO_ENHANCEDWILD;
+         break;
       case 'Z':                 /* gzip compression */
          fo->flags |= FO_GZIP;
          fo->GZIP_level = *++p - '0';
index a9e4a4ff764904da3094dbf32de89412f936a585..2a84fc9253abc79c3b8a3a88383baefeebd8087f 100644 (file)
@@ -23,9 +23,9 @@ dummy:
 
 #
 LIBSRCS = find.c match.c find_one.c attibs.c create_file.c \
-         bfile.c enable_priv.c fstype.c makepath.c save-cwd.c
+         bfile.c drivetype.c enable_priv.c fstype.c makepath.c save-cwd.c
 LIBOBJS = find.o match.o find_one.o attribs.o create_file.o \
-         bfile.o enable_priv.o fstype.o makepath.o save-cwd.o
+         bfile.o drivetype.o enable_priv.o fstype.o makepath.o save-cwd.o
 
 .SUFFIXES:     .c .o
 .PHONY:
index 8fde075a359c32585844774bcac12319d3a9628f..c8e4e9aeede1c69da0b3a2f957aa3eddfdcd7fec 100644 (file)
@@ -174,6 +174,7 @@ find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt, bool t
             ff->flags |= fo->flags;
             ff->GZIP_level = fo->GZIP_level;
             ff->fstypes = fo->fstype;
+            ff->drivetypes = fo->drivetype;
             bstrncat(ff->VerifyOpts, fo->VerifyOpts, sizeof(ff->VerifyOpts));
          }
          for (j=0; j<incexe->name_list.size(); j++) {
@@ -191,9 +192,22 @@ find_files(JCR *jcr, FF_PKT *ff, int callback(FF_PKT *ff_pkt, void *hpkt, bool t
 static bool accept_file(FF_PKT *ff)
 {
    int i, j, k;
-   int ic;
+   int fnm_flags;
    findFILESET *fileset = ff->fileset;
    findINCEXE *incexe = fileset->incexe;
+   const char *basename;
+   int (*match_func)(const char *pattern, const char *string, int flags);
+
+   if (ff->flags & FO_ENHANCEDWILD) {
+      match_func = enh_fnmatch;
+      if ((basename = strrchr(ff->fname, '/')) != NULL)
+         basename++;
+      else
+         basename = ff->fname;
+   } else {
+      match_func = fnmatch;
+      basename = ff->fname;
+   }
 
    for (j=0; j<incexe->opts_list.size(); j++) {
       findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
@@ -202,10 +216,14 @@ static bool accept_file(FF_PKT *ff)
       ff->reader = fo->reader;
       ff->writer = fo->writer;
       ff->fstypes = fo->fstype;
-      ic = (ff->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0;
+      ff->drivetypes = fo->drivetype;
+
+      fnm_flags = (ff->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0;
+      fnm_flags |= (ff->flags & FO_ENHANCEDWILD) ? FNM_PATHNAME : 0;
+
       if (S_ISDIR(ff->statp.st_mode)) {
          for (k=0; k<fo->wilddir.size(); k++) {
-            if (fnmatch((char *)fo->wilddir.get(k), ff->fname, fnmode|ic) == 0) {
+            if (match_func((char *)fo->wilddir.get(k), ff->fname, fnmode|fnm_flags) == 0) {
                if (ff->flags & FO_EXCLUDE) {
                   Dmsg2(100, "Exclude wilddir: %s file=%s\n", (char *)fo->wilddir.get(k),
                      ff->fname);
@@ -216,7 +234,7 @@ static bool accept_file(FF_PKT *ff)
          }
       } else {
          for (k=0; k<fo->wildfile.size(); k++) {
-            if (fnmatch((char *)fo->wildfile.get(k), ff->fname, fnmode|ic) == 0) {
+            if (match_func((char *)fo->wildfile.get(k), ff->fname, fnmode|fnm_flags) == 0) {
                if (ff->flags & FO_EXCLUDE) {
                   Dmsg2(100, "Exclude wildfile: %s file=%s\n", (char *)fo->wildfile.get(k),
                      ff->fname);
@@ -225,9 +243,20 @@ static bool accept_file(FF_PKT *ff)
                return true;           /* accept file */
             }
          }
+
+         for (k=0; k<fo->wildbase.size(); k++) {
+            if (match_func((char *)fo->wildbase.get(k), basename, fnmode|fnm_flags) == 0) {
+               if (ff->flags & FO_EXCLUDE) {
+                  Dmsg2(100, "Exclude wildbase: %s file=%s\n", (char *)fo->wildbase.get(k),
+                     basename);
+                  return false;       /* reject file */
+               }
+               return true;           /* accept file */
+            }
+         }
       }
       for (k=0; k<fo->wild.size(); k++) {
-         if (fnmatch((char *)fo->wild.get(k), ff->fname, fnmode|ic) == 0) {
+         if (match_func((char *)fo->wild.get(k), ff->fname, fnmode|fnm_flags) == 0) {
             if (ff->flags & FO_EXCLUDE) {
                Dmsg2(100, "Exclude wild: %s file=%s\n", (char *)fo->wild.get(k),
                   ff->fname);
@@ -276,7 +305,8 @@ static bool accept_file(FF_PKT *ff)
       if (ff->flags & FO_EXCLUDE &&
           fo->regex.size() == 0     && fo->wild.size() == 0 &&
           fo->regexdir.size() == 0  && fo->wilddir.size() == 0 &&
-          fo->regexfile.size() == 0 && fo->wildfile.size() == 0) {
+          fo->regexfile.size() == 0 && fo->wildfile.size() == 0 &&
+          fo->wildbase.size() == 0) {
          return false;              /* reject file */
       }
    }
@@ -286,18 +316,18 @@ static bool accept_file(FF_PKT *ff)
       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
       for (j=0; j<incexe->opts_list.size(); j++) {
          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
-         ic = (fo->flags & FO_IGNORECASE) ? FNM_CASEFOLD : 0;
+         fnm_flags = (fo->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) {
+            if (fnmatch((char *)fo->wild.get(k), ff->fname, fnmode|fnm_flags) == 0) {
                Dmsg1(100, "Reject wild1: %s\n", ff->fname);
                return false;          /* reject file */
             }
          }
       }
-      ic = (incexe->current_opts != NULL && incexe->current_opts->flags & FO_IGNORECASE)
+      fnm_flags = (incexe->current_opts != NULL && incexe->current_opts->flags & FO_IGNORECASE)
              ? FNM_CASEFOLD : 0;
       for (j=0; j<incexe->name_list.size(); j++) {
-         if (fnmatch((char *)incexe->name_list.get(j), ff->fname, fnmode|ic) == 0) {
+         if (fnmatch((char *)incexe->name_list.get(j), ff->fname, fnmode|fnm_flags) == 0) {
             Dmsg1(100, "Reject wild2: %s\n", ff->fname);
             return false;          /* reject file */
          }
index 31ec519eb946d1ddeb0b1444d8c0a527d897b954..0217dfc988118faebd22864dd8e78d525d0b3d2e 100755 (executable)
@@ -42,6 +42,7 @@ struct utimbuf {
 #define MODE_RALL (S_IRUSR|S_IRGRP|S_IROTH)
 
 #include "lib/fnmatch.h"
+#include "lib/enh_fnmatch.h"
 
 #ifndef HAVE_REGEX_H
 #include "lib/bregex.h"
@@ -92,6 +93,7 @@ enum {
 #define FO_SHA512       (1<<20)       /* Do SHA512 checksum */
 #define FO_ENCRYPT      (1<<21)       /* Encrypt data stream */
 #define FO_NOATIME      (1<<22)       /* Use O_NOATIME to prevent atime change */
+#define FO_ENHANCEDWILD (1<<23)       /* Enhanced wild card processing */
 
 struct s_included_file {
    struct s_included_file *next;
@@ -135,8 +137,10 @@ struct findFOPTS {
    alist wild;                        /* wild card strings */
    alist wilddir;                     /* wild card strings for directories */
    alist wildfile;                    /* wild card strings for files */
+   alist wildbase;                    /* wild card strings for basenames */
    alist base;                        /* list of base names */
    alist fstype;                      /* file system type limitation */
+   alist drivetype;                   /* drive type limitation */
    char *reader;                      /* reader program */
    char *writer;                      /* writer program */
 };
@@ -200,6 +204,7 @@ struct FF_PKT {
    char *reader;                      /* reader program */
    char *writer;                      /* writer program */
    alist fstypes;                     /* allowed file system types */
+   alist drivetypes;                  /* allowed drive types */
 
    /* List of all hard linked files found */
    struct f_link **linkhash;          /* hard linked files */
index b4e5831f874127e0786cd2af4bb5df4b40f552db..152cda924b4d3d169916430c0a796602da49b88b 100755 (executable)
@@ -108,6 +108,34 @@ static int accept_fstype(FF_PKT *ff, void *dummy) {
    return accept;
 }
 
+/*
+ * Check to see if we allow the drive type of a file or directory.
+ * If we do not have a list of drive types, we accept anything.
+ */
+static int accept_drivetype(FF_PKT *ff, void *dummy) {
+   int i;
+   char dt[100];
+   bool accept = true;
+
+   if (ff->drivetypes.size()) {
+      accept = false;
+      if (!drivetype(ff->fname, dt, sizeof(dt))) {
+         Dmsg1(50, "Cannot determine drive type for \"%s\"\n", ff->fname);
+      } else {
+         for (i = 0; i < ff->drivetypes.size(); ++i) {
+            if (strcmp(dt, (char *)ff->drivetypes.get(i)) == 0) {
+               Dmsg2(100, "Accepting drive type %s for \"%s\"\n", dt, ff->fname);
+               accept = true;
+               break;
+            }
+            Dmsg3(200, "drive type %s for \"%s\" does not match %s\n", dt,
+                  ff->fname, ff->drivetypes.get(i));
+         }
+      }
+   }
+   return accept;
+}
+
 /*
  * This function determines whether we can use getattrlist()
  * It's odd, but we have to use the function to determine that...
@@ -176,7 +204,7 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt,
    restore_times.modtime = ff_pkt->statp.st_mtime;
 
    /*
-    * We check for allowed fstypes at top_level and fstype change (below).
+    * We check for allowed fstypes and drivetypes at top_level and fstype change (below).
     */
    if (top_level) {
       if (!accept_fstype(ff_pkt, NULL)) {
@@ -184,7 +212,29 @@ find_one_file(JCR *jcr, FF_PKT *ff_pkt,
          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);
+
+         char fs[100];
+
+         if (!fstype(ff_pkt->fname, fs, sizeof(fs))) {
+             bstrncpy(fs, "unknown", sizeof(fs));
+         }
+
+         Jmsg(jcr, M_INFO, 0, _("Top level directory \"%s\" has unlisted fstype \"%s\"\n"), fname, fs);
+         return 1;      /* Just ignore this error - or the whole backup is cancelled */
+      }
+      if (!accept_drivetype(ff_pkt, NULL)) {
+         ff_pkt->type = FT_INVALIDDT;
+         if (ff_pkt->flags & FO_KEEPATIME) {
+            utime(fname, &restore_times);
+         }
+
+         char dt[100];
+
+         if (!drivetype(ff_pkt->fname, dt, sizeof(dt))) {
+             bstrncpy(dt, "unknown", sizeof(dt));
+         }
+
+         Jmsg(jcr, M_INFO, 0, _("Top level directory \"%s\" has an unlisted drive type \"%s\"\n"), fname, dt);
          return 1;      /* Just ignore this error - or the whole backup is cancelled */
       }
       ff_pkt->volhas_attrlist = volume_has_attrlist(fname);
index 0c2837ecbe8c3ea510735f480eabe52bc797f350..ff40dfdc3a87ba5da9ff802320a4833bd28c446c 100644 (file)
@@ -70,4 +70,7 @@ int make_path(JCR *jcr, const char *argpath, int mode,
 /* from fstype.c */
 bool fstype(const char *fname, char *fs, int fslen);
 
+/* from drivetype.c */
+bool drivetype(const char *fname, char *fs, int fslen);
+
 /* from bfile.c -- see bfile.h */
index 6225e71eca4619677f388f8d02ffb981c91fccfb..827d52f5394e84154cde738f078d049f0d97ba33 100644 (file)
@@ -38,7 +38,7 @@ LIBSRCS = alloc.c attr.c base64.c berrno.c bsys.c bget_msg.c \
 LIBOBJS = alloc.o attr.o base64.o berrno.o bsys.o bget_msg.o \
          bnet.o bnet_server.o runscript.o \
          bpipe.o bsnprintf.o btime.o \
-         cram-md5.o crc32.o crypto.o daemon.o edit.o fnmatch.o \
+         cram-md5.o crc32.o crypto.o daemon.o edit.o enh_fnmatch.o fnmatch.o \
          hmac.o idcache.o jcr.o lex.o alist.o dlist.o \
          md5.o message.o mem_pool.o openssl.o parse_conf.o \
          queue.o bregex.o \
index 1bd6f8eb90e438adebcb653904a94d82a3c2e097..44070a79e5837486f0853d2b666b891ffe0ec6f4 100755 (executable)
@@ -773,9 +773,14 @@ d_msg(const char *file, int line, int level, const char *fmt,...)
           /* visual studio passes the whole path to the file as well
            * which makes for very long lines
            */
-          const char *f = strrchr(file, '\\');
-          if (f) file = f + 1;
-          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line);
+          const char *basename;
+
+          if ((basename = strrchr(file, '\\')) == NULL) {
+             basename = file;
+          } else {
+             basename++;
+          }
+          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
        } else {
           len = 0;
        }
@@ -850,7 +855,14 @@ p_msg(const char *file, int line, int level, const char *fmt,...)
 
 #ifdef FULL_LOCATION
     if (level >= 0) {
-       len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line);
+       const char *basename;
+
+       if ((basename = strrchr(file, '\\')) == NULL) {
+          basename = file;
+       } else {
+          basename++;
+       }
+       len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
     } else {
        len = 0;
     }
@@ -895,7 +907,14 @@ t_msg(const char *file, int line, int level, const char *fmt,...)
 
 #ifdef FULL_LOCATION
        if (details) {
-          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, file, line);
+          const char *basename;
+
+          if ((basename = strrchr(file, '\\')) == NULL) {
+             basename = file;
+          } else {
+             basename++;
+          }
+          len = bsnprintf(buf, sizeof(buf), "%s: %s:%d ", my_name, basename, line);
        } else {
           len = 0;
        }
@@ -926,6 +945,14 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...)
     va_list   arg_ptr;
     int len;
 
+    const char *basename;
+
+    if ((basename = strrchr(file, '\\')) == NULL) {
+       basename = file;
+    } else {
+       basename++;
+    }
+
     /*
      * Check if we have a message destination defined.
      * We always report M_ABORT and M_ERROR_TERM
@@ -937,23 +964,23 @@ e_msg(const char *file, int line, int type, int level, const char *fmt,...)
     switch (type) {
     case M_ABORT:
        len = bsnprintf(buf, sizeof(buf), _("%s: ABORTING due to ERROR in %s:%d\n"),
-               my_name, file, line);
+               my_name, basename, line);
        break;
     case M_ERROR_TERM:
        len = bsnprintf(buf, sizeof(buf), _("%s: ERROR TERMINATION at %s:%d\n"),
-               my_name, file, line);
+               my_name, basename, line);
        break;
     case M_FATAL:
        if (level == -1)            /* skip details */
           len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error because: "), my_name);
        else
-          len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, file, line);
+          len = bsnprintf(buf, sizeof(buf), _("%s: Fatal Error at %s:%d because:\n"), my_name, basename, line);
        break;
     case M_ERROR:
        if (level == -1)            /* skip details */
           len = bsnprintf(buf, sizeof(buf), _("%s: ERROR: "), my_name);
        else
-          len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, file, line);
+          len = bsnprintf(buf, sizeof(buf), _("%s: ERROR in %s:%d "), my_name, basename, line);
        break;
     case M_WARNING:
        len = bsnprintf(buf, sizeof(buf), _("%s: Warning: "), my_name);
@@ -1087,9 +1114,16 @@ void j_msg(const char *file, int line, JCR *jcr, int type, time_t mtime, const c
    va_list   arg_ptr;
    int i, len, maxlen;
    POOLMEM *pool_buf;
+   const char *basename;
+
+   if ((basename = strrchr(file, '\\')) == NULL) {
+      basename = file;
+   } else {
+      basename++;
+   }
 
    pool_buf = get_pool_memory(PM_EMSG);
-   i = Mmsg(pool_buf, "%s:%d ", file, line);
+   i = Mmsg(pool_buf, "%s:%d ", basename, line);
 
    for (;;) {
       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
@@ -1116,7 +1150,15 @@ int m_msg(const char *file, int line, POOLMEM **pool_buf, const char *fmt, ...)
    va_list   arg_ptr;
    int i, len, maxlen;
 
-   i = sprintf(*pool_buf, "%s:%d ", file, line);
+   const char *basename;
+
+   if ((basename = strrchr(file, '\\')) == NULL) {
+      basename = file;
+   } else {
+      basename++;
+   }
+
+   i = sprintf(*pool_buf, "%s:%d ", basename, line);
 
    for (;;) {
       maxlen = sizeof_pool_memory(*pool_buf) - i - 1;
@@ -1137,7 +1179,15 @@ int m_msg(const char *file, int line, POOLMEM *&pool_buf, const char *fmt, ...)
    va_list   arg_ptr;
    int i, len, maxlen;
 
-   i = sprintf(pool_buf, "%s:%d ", file, line);
+   const char *basename;
+
+   if ((basename = strrchr(file, '\\')) == NULL) {
+      basename = file;
+   } else {
+      basename++;
+   }
+
+   i = sprintf(pool_buf, "%s:%d ", basename, line);
 
    for (;;) {
       maxlen = sizeof_pool_memory(pool_buf) - i - 1;
index eeae53420bd481965aec63da5ae870ba0f4ca95a..b82d023dccf402760afcbc2ad9245a5051e9fd30 100644 (file)
@@ -43,6 +43,7 @@ bool do_append_data(JCR *jcr)
    char buf1[100], buf2[100];
    DCR *dcr = jcr->dcr;
    DEVICE *dev;
+   char ec[50];
 
 
    if (!dcr) { 
@@ -240,6 +241,7 @@ bool do_append_data(JCR *jcr)
          Dmsg0(650, "Enter bnet_get\n");
       }
       Dmsg1(650, "End read loop with FD. Stat=%d\n", n);
+
       if (is_bnet_error(ds)) {
          Dmsg1(350, "Network read error from FD. ERR=%s\n", bnet_strerror(ds));
          Jmsg1(jcr, M_FATAL, 0, _("Network error on data channel. ERR=%s\n"),
@@ -249,6 +251,15 @@ bool do_append_data(JCR *jcr)
       }
    }
 
+   time_t job_elapsed = time(NULL) - jcr->run_time;
+
+   if (job_elapsed == 0)
+      job_elapsed = 1;
+
+   Jmsg(dcr->jcr, M_INFO, 0, _("Job write elapsed time = %02d:%02d:%02d, Transfer rate = %s bytes/second\n"),
+         job_elapsed / 3600, job_elapsed % 3600 / 60, job_elapsed % 60,
+         edit_uint64_with_commas(jcr->dcr->job_spool_size / job_elapsed, ec));
+
    /* Create Job status for end of session label */
    set_jcr_job_status(jcr, ok?JS_Terminated:JS_ErrorTerminated);
 
index 62675c67c2212ce7c55d7d9ea0d6b015e017067d..5923279c02cf3437c9b4799f136b710f72825bc4 100644 (file)
@@ -237,6 +237,8 @@ static bool despool_data(DCR *dcr, bool commit)
    Dmsg1(800, "read/write block size = %d\n", block->buf_len);
    lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */
 
+   time_t despool_start = time(NULL);
+
    for ( ; ok; ) {
       if (job_canceled(jcr)) {
          ok = false;
@@ -256,6 +258,16 @@ static bool despool_data(DCR *dcr, bool commit)
       }
       Dmsg3(800, "Write block ok=%d FI=%d LI=%d\n", ok, block->FirstIndex, block->LastIndex);
    }
+
+   time_t despool_elapsed = time(NULL) - despool_start;
+
+   if (despool_elapsed == 0)
+      despool_elapsed = 1;
+
+   Jmsg(dcr->jcr, M_INFO, 0, _("Despooling elapsed time = %02d:%02d:%02d, Transfer rate = %s bytes/second\n"),
+         despool_elapsed / 3600, despool_elapsed % 3600 / 60, despool_elapsed % 60,
+         edit_uint64_with_commas(jcr->dcr->job_spool_size / despool_elapsed, ec1));
+
    dcr->block = block;                /* reset block */
 
    lseek(rdcr->spool_fd, 0, SEEK_SET); /* rewind */
index 84591abe14eed881f173d357d167e34242cd6ac0..e1677fcc7a7c0368d5731d66dfbf7c09f5ae1911 100644 (file)
@@ -38,7 +38,7 @@ EXTRAOBJS = @OBJLIST@
 DIRCONFOBJS = ../dird/dird_conf.o ../dird/run_conf.o ../dird/inc_conf.o
 
 NODIRTOOLS = bsmtp
-DIRTOOLS = bsmtp dbcheck fstype testfind testls bregex bwild
+DIRTOOLS = bsmtp dbcheck drivetype fstype testfind testls bregex bwild
 TOOLS = $(@DIR_TOOLS@)
 
 INSNODIRTOOLS = bsmtp
@@ -68,6 +68,9 @@ dbcheck: dbcheck.o ../lib/libbac.a ../cats/libsql.a $(DIRCONFOBJS)
 fstype: fstype.o ../lib/libbac.a ../findlib/libfind.a
        $(CXX) $(LDFLAGS) -L../lib -L../findlib -o $@ fstype.o -lfind -lbac -lm $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
 
+drivetype: drivetype.o ../lib/libbac.a ../findlib/libfind.a
+       $(CXX) $(LDFLAGS) -L../lib -L../findlib -o $@ drivetype.o -lfind -lbac -lm $(DLIB) $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)
+
 testfind: ../findlib/libfind.a ../lib/libbac.a $(FINDOBJS)
        $(CXX) -g $(LDFLAGS) -L. -L../lib -L../findlib -o $@ $(FINDOBJS) \
          $(DLIB) -lfind -lbac -lm $(LIBS) $(GETTEXT_LIBS) $(OPENSSL_LIBS)