]> git.sur5r.net Git - bacula/bacula/commitdiff
Constrain BSR indexes, fix bscan, add some new alist code
authorKern Sibbald <kern@sibbald.com>
Sat, 5 Jul 2003 12:07:08 +0000 (12:07 +0000)
committerKern Sibbald <kern@sibbald.com>
Sat, 5 Jul 2003 12:07:08 +0000 (12:07 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@617 91ce42f0-d328-0410-95d8-f526ca767f89

33 files changed:
bacula/ReleaseNotes
bacula/kernstodo
bacula/src/baconfig.h
bacula/src/bc_types.h
bacula/src/console/console.c
bacula/src/dird/bsr.c
bacula/src/dird/catreq.c
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/restore.c
bacula/src/dird/ua_cmds.c
bacula/src/dird/ua_input.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_select.c
bacula/src/dird/ua_server.c
bacula/src/filed/job.c
bacula/src/findlib/find.h
bacula/src/findlib/match.c
bacula/src/lib/mem_pool.h
bacula/src/lib/protos.h
bacula/src/lib/scan.c
bacula/src/stored/append.c
bacula/src/stored/bextract.c
bacula/src/stored/block.c
bacula/src/stored/block.h
bacula/src/stored/bscan.c
bacula/src/stored/label.c
bacula/src/stored/mount.c
bacula/src/stored/record.c
bacula/src/version.h

index 135c2042608b87ba8d1bbdb235365e08d51d6cfb..7abe9651f8e538b9723775d901bb10820c684b4b 100644 (file)
@@ -63,6 +63,8 @@ Other Changes this Release:
 
 
 Items to note:  !!!!!
+- Recycle Oldest Volume has changed to be Purge Oldest Volume
+  Please change your Director's .conf file.
 - The default time interval is now days instead of seconds. Please
   check your .conf files!
 - For MySQL users, you must have the thread safe client libraries 
index 532387eaaf933d6124f98a8647e95f2e6a6d7346..4b560ba98ba84e4d54cae22de392fd023bc81a4f 100644 (file)
@@ -18,6 +18,9 @@ Documentation to do: (any release a little bit at a time)
   (./create_mys... ./make_my...).
 - Document c:/working directory better than /working directory.
 - Document all the status codes JobLevel, JobType, JobStatus.
+- Document update volume: jobid, current, before, all
+- Document run "yes".
+- Document that bscan does not work with multiple simultaneous jobs.
 
           
 Testing to do: (painful)
@@ -33,7 +36,6 @@ Testing to do: (painful)
 - Figure out how to use ssh or stunnel to protect Bacula communications.
 
 For 1.31 release:
-- Non-fatal errors are not correct counting attribs.c:277
 - In Win portable restore the directory is not create    
    27-Jun-2003 16:52 tibs-fd: kernsrestore.2003-06-27_16.52.20 Error:
    create_file.c:175 Could not create
@@ -1013,4 +1015,5 @@ Done: (see kernsdone for more)
 - Make Restore report an error if FD or SD term codes are not OK.
 - To link with mysqlclient_r may require -lssl -lcrypto
 - Document Heart beat code 
+- Non-fatal errors are not correct counting attribs.c:277
  
index f334453666d00e63061844dddbbed88f78fd3286..2ffaa3c8ec4a9cbf43fb395250c756aae0660c77 100644 (file)
 #define _(s) gettext((s))
 #define N_(s) (s)
 #else
+#undef _
 #define _(s) (s)
+#undef N_
 #define N_(s) (s)
+#undef textdomain
 #define textdomain(d)
-#define bindtextdomain(p, d)
+/* #define bindtextdomain(p, d) */
 #endif
 
 
index e0916b2ecec811fdcafe61cfc24e0289a7f91775..e55b377bb23d07457463a06dcc87f75b0d4b313c 100644 (file)
@@ -8,7 +8,6 @@
 
     int8_t,  int16_t,  int32_t,  int64_t
     uint8_t, uint16_t, uint32_t, uint64_t
-    float32_t, float64_t
 
     Also, we define types such as file address lengths.
 
@@ -43,9 +42,13 @@ typedef char POOLMEM;
 #define mp_chr(x) x
 #ifdef xxxxx
 #define mp_chr(x) ((char*)(x))
-struct POOLMEM { };
+struct POOLMEM { 
+   POOLMEM() {}
+   operator const char*() const { return (char *)this; }
+};
 #endif
 
+
 /* Types */
 
 /* If sys/types.h does not supply intXX_t, supply them ourselves */
index a05ee37f0f0e5e0eed323f321bf8dade1fb5dc39..b036edc30d70a62ae76b2eafc270dee8b0acd797 100644 (file)
@@ -196,7 +196,7 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
         at_prompt = FALSE;
         /* @ => internal command for us */
          if (UA_sock->msg[0] == '@') {
-           parse_args(UA_sock->msg, args, &argc, argk, argv, MAX_CMD_ARGS);
+           parse_args(UA_sock->msg, &args, &argc, argk, argv, MAX_CMD_ARGS);
            if (!do_a_command(input, UA_sock)) {
               break;
            }
index e8e3508be5060263693fdee7098b7665c9c84916..e2bc4e0115fdc182f2ec7b807c5c364a03d7d665 100644 (file)
@@ -34,7 +34,6 @@
 #include "dird.h"
 
 /* Forward referenced functions */
-static RBSR *sort_bsr(RBSR *bsr);
 static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd);
 
 
@@ -57,18 +56,43 @@ static void free_findex(RBSR_FINDEX *fi)
    }
 }
 
-static void write_findex(UAContext *ua, RBSR_FINDEX *fi, FILE *fd) 
+/*
+ * Our data structures were not designed completely
+ *  correctly, so the file indexes cover the full
+ *  range regardless of volume. The FirstIndex and LastIndex
+ *  passed in here are for the current volume, so when 
+ *  writing out the fi, constrain them to those values.
+ */
+static void write_findex(UAContext *ua, RBSR_FINDEX *fi, 
+             int32_t FirstIndex, int32_t LastIndex, FILE *fd) 
 {
    if (fi) {
-      if (fi->findex == fi->findex2) {
-         fprintf(fd, "FileIndex=%d\n", fi->findex);
+      int32_t findex, findex2;
+      findex = fi->findex < FirstIndex ? FirstIndex : fi->findex;
+      findex2 = fi->findex2 > LastIndex ? LastIndex : fi->findex2;
+      if (findex == findex2) {
+         fprintf(fd, "FileIndex=%d\n", findex);
       } else {
-         fprintf(fd, "FileIndex=%d-%d\n", fi->findex, fi->findex2);
+         fprintf(fd, "FileIndex=%d-%d\n", findex, findex2);
       }
-      write_findex(ua, fi->next, fd);
+      write_findex(ua, fi->next, FirstIndex, LastIndex, fd);
    }
 }
 
+static bool is_volume_selected(RBSR_FINDEX *fi, 
+             int32_t FirstIndex, int32_t LastIndex) 
+{
+   if (fi) {
+      if ((fi->findex >= FirstIndex && fi->findex <= LastIndex) ||
+         (fi->findex2 >= FirstIndex && fi->findex2 <= LastIndex)) {
+        return true;
+      }
+      return is_volume_selected(fi->next, FirstIndex, LastIndex);
+   }
+   return false;
+}
+
+
 
 static void print_findex(UAContext *ua, RBSR_FINDEX *fi)
 {
@@ -109,9 +133,8 @@ void free_bsr(RBSR *bsr)
  */
 int complete_bsr(UAContext *ua, RBSR *bsr)
 {
-   JOB_DBR jr;
-
    if (bsr) {
+      JOB_DBR jr;
       memset(&jr, 0, sizeof(jr));
       jr.JobId = bsr->JobId;
       if (!db_get_job_record(ua->jcr, ua->db, &jr)) {
@@ -151,8 +174,6 @@ int write_bsr_file(UAContext *ua, RBSR *bsr)
       free_pool_memory(fname);
       return 0;
    }
-   /* Sort the bsr chain */
-   bsr = sort_bsr(bsr);
    /* Write them to file */
    write_bsr(ua, bsr, fd);
    stat = !ferror(fd);
@@ -179,24 +200,14 @@ int write_bsr_file(UAContext *ua, RBSR *bsr)
    return stat;
 }
 
-/*
- * First sort the bsr chain, then sort the VolParams   
- */
-static RBSR *sort_bsr(RBSR *bsr)
-{
-   if (!bsr) {
-      return bsr;
-   }
-   /* ****FIXME**** sort the bsr chain */
-   for (RBSR *nbsr=bsr; nbsr; nbsr=nbsr->next) {
-   }
-   return bsr;
-}
-
 static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd)
 {
    if (bsr) {
       for (int i=0; i < bsr->VolCount; i++) {
+        if (!is_volume_selected(bsr->fi, bsr->VolParams[i].FirstIndex,
+             bsr->VolParams[i].LastIndex)) {
+           continue;
+        }
          fprintf(fd, "Volume=\"%s\"\n", bsr->VolParams[i].VolumeName);
          fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
          fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
@@ -204,7 +215,11 @@ static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd)
                 bsr->VolParams[i].EndFile);
          fprintf(fd, "VolBlock=%u-%u\n", bsr->VolParams[i].StartBlock,
                 bsr->VolParams[i].EndBlock);
-        write_findex(ua, bsr->fi, fd);
+
+//       Dmsg2(000, "bsr VolParam FI=%u LI=%u\n",
+//         bsr->VolParams[i].FirstIndex, bsr->VolParams[i].LastIndex);
+        write_findex(ua, bsr->fi, bsr->VolParams[i].FirstIndex,
+           bsr->VolParams[i].LastIndex, fd);
       }
       write_bsr(ua, bsr->next, fd);
    }
index e2083a30ae481e58bc408008b375dd5134313d9f..2ffc82b5f71bd477037c533f700bbb4564a7907e 100644 (file)
@@ -107,9 +107,9 @@ next_volume:
            }
         }
 
-        if (!ok && jcr->pool->recycle_oldest_volume) {
-            Dmsg1(200, "No next volume found. RecycleOldest=%d\n",
-               jcr->pool->recycle_oldest_volume);
+        if (!ok && jcr->pool->purge_oldest_volume) {
+            Dmsg1(200, "No next volume found. PurgeOldest=%d\n",
+               jcr->pool->purge_oldest_volume);
            /* Find oldest volume to recycle */
            ok = db_find_next_volume(jcr, jcr->db, -1, &mr);
             Dmsg1(400, "Find oldest=%d\n", ok);
@@ -118,7 +118,7 @@ next_volume:
                Dmsg0(400, "Try purge.\n");
               /* Try to purge oldest volume */
               ua = new_ua_context(jcr);
-               Jmsg(jcr, M_INFO, 0, _("Recycling oldest volume \"%s\"\n"), mr.VolumeName);
+               Jmsg(jcr, M_INFO, 0, _("Purging oldest volume \"%s\"\n"), mr.VolumeName);
               ok = purge_jobs_from_volume(ua, &mr);
               free_ua_context(ua);
               if (ok) {
index fd34100dbb0c475b8606a8f1dd2749a66e421776..7b8b14aece4089f9375abd80b4c279b699dd7f90 100644 (file)
@@ -8,14 +8,14 @@
  *   1. The generic lexical scanner in lib/lex.c and lib/lex.h
  *
  *   2. The generic config  scanner in lib/parse_config.c and 
- *      lib/parse_config.h.
- *      These files contain the parser code, some utility
- *      routines, and the common store routines (name, int,
- *      string).
+ *     lib/parse_config.h.
+ *     These files contain the parser code, some utility
+ *     routines, and the common store routines (name, int,
+ *     string).
  *
  *   3. The daemon specific file, which contains the Resource
- *      definitions as well as any specific store routines
- *      for the resource records.
+ *     definitions as well as any specific store routines
+ *     for the resource records.
  *
  *     Kern Sibbald, January MM
  *
@@ -83,7 +83,7 @@ int  res_all_size = sizeof(res_all);
 /* 
  *    Director Resource
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items dir_items[] = {
    {"name",        store_name,     ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0},
@@ -107,7 +107,7 @@ static struct res_items dir_items[] = {
 /* 
  *    Console Resource
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items con_items[] = {
    {"name",        store_name,     ITEM(res_con.hdr.name), 0, ITEM_REQUIRED, 0},
@@ -121,7 +121,7 @@ static struct res_items con_items[] = {
 /* 
  *    Client or File daemon resource
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 
 static struct res_items cli_items[] = {
@@ -141,7 +141,7 @@ static struct res_items cli_items[] = {
 
 /* Storage daemon resource
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items store_items[] = {
    {"name",      store_name,     ITEM(res_store.hdr.name),   0, ITEM_REQUIRED, 0},
@@ -161,7 +161,7 @@ static struct res_items store_items[] = {
 /* 
  *    Catalog Resource Directives
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items cat_items[] = {
    {"name",     store_name,     ITEM(res_cat.hdr.name),    0, ITEM_REQUIRED, 0},
@@ -180,7 +180,7 @@ static struct res_items cat_items[] = {
 /* 
  *    Job Resource Directives
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items job_items[] = {
    {"name",     store_name,    ITEM(res_job.hdr.name), 0, ITEM_REQUIRED, 0},
@@ -218,7 +218,7 @@ static struct res_items job_items[] = {
 
 /* FileSet resource
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items fs_items[] = {
    {"name",        store_name, ITEM(res_fs.hdr.name), 0, ITEM_REQUIRED, 0},
@@ -227,13 +227,13 @@ static struct res_items fs_items[] = {
    {"finclude",    store_finc, NULL,                  0, ITEM_NO_EQUALS, 0},
    {"exclude",     store_inc,  NULL,                  1, 0, 0},
    {"fexclude",    store_finc, NULL,                  1, ITEM_NO_EQUALS, 0},
-   {NULL,          NULL,       NULL,                  0, 0, 0} 
+   {NULL,         NULL,       NULL,                  0, 0, 0} 
 };
 
 /* Schedule -- see run_conf.c */
 /* Schedule
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items sch_items[] = {
    {"name",     store_name,  ITEM(res_sch.hdr.name), 0, ITEM_REQUIRED, 0},
@@ -244,7 +244,7 @@ static struct res_items sch_items[] = {
 
 /* Group resource -- not implemented
  *
- *   name          handler     value                 code flags    default_value
+ *   name         handler     value                 code flags    default_value
  */
 static struct res_items group_items[] = {
    {"name",        store_name, ITEM(res_group.hdr.name), 0, ITEM_REQUIRED, 0},
@@ -254,7 +254,7 @@ static struct res_items group_items[] = {
 
 /* Pool resource
  *
- *   name             handler     value                        code flags default_value
+ *   name            handler     value                        code flags default_value
  */
 static struct res_items pool_items[] = {
    {"name",            store_name,    ITEM(res_pool.hdr.name),      0, ITEM_REQUIRED, 0},
@@ -264,7 +264,7 @@ static struct res_items pool_items[] = {
    {"cleaningprefix",  store_strname, ITEM(res_pool.cleaning_prefix),  0, 0,     0},
    {"usecatalog",      store_yesno, ITEM(res_pool.use_catalog),     1, ITEM_DEFAULT,  1},
    {"usevolumeonce",   store_yesno, ITEM(res_pool.use_volume_once), 1, 0,        0},
-   {"recycleoldestvolume", store_yesno, ITEM(res_pool.recycle_oldest_volume), 1, 0, 0},
+   {"purgeoldestvolume", store_yesno, ITEM(res_pool.purge_oldest_volume), 1, 0, 0},
    {"maximumvolumes",  store_pint,  ITEM(res_pool.max_volumes),     0, 0,        0},
    {"maximumvolumejobs", store_pint,  ITEM(res_pool.MaxVolJobs),    0, 0,       0},
    {"maximumvolumefiles", store_pint, ITEM(res_pool.MaxVolFiles),   0, 0,       0},
@@ -280,7 +280,7 @@ static struct res_items pool_items[] = {
 
 /* 
  * Counter Resource
- *   name             handler     value                        code flags default_value
+ *   name            handler     value                        code flags default_value
  */
 static struct res_items counter_items[] = {
    {"name",            store_name,    ITEM(res_counter.hdr.name),        0, ITEM_REQUIRED, 0},
@@ -300,7 +300,7 @@ extern struct res_items msgs_items[];
  * This is the master resource definition.  
  * It must have one item for each of the resources.
  *
- *  name             items        rcode        res_head
+ *  name            items        rcode        res_head
  */
 struct s_res resources[] = {
    {"director",      dir_items,   R_DIRECTOR,  NULL},
@@ -315,13 +315,13 @@ struct s_res resources[] = {
    {"pool",          pool_items,  R_POOL,      NULL},
    {"messages",      msgs_items,  R_MSGS,      NULL},
    {"counter",       counter_items, R_COUNTER, NULL},
-   {NULL,            NULL,        0,           NULL}
+   {NULL,           NULL,        0,           NULL}
 };
 
 
 /* Keywords (RHS) permitted in Job Level records   
  *
- *   level_name      level              job_type
+ *   level_name      level             job_type
  */
 struct s_jl joblevels[] = {
    {"Full",          L_FULL,            JT_BACKUP},
@@ -333,19 +333,19 @@ struct s_jl joblevels[] = {
    {"Initcatalog",   L_VERIFY_INIT,     JT_VERIFY},
    {"VolumeToCatalog", L_VERIFY_VOLUME_TO_CATALOG,   JT_VERIFY},
    {"Data",          L_VERIFY_DATA,     JT_VERIFY},
-   {NULL,            0}
+   {NULL,           0}
 };
 
 /* Keywords (RHS) permitted in Job type records   
  *
- *   type_name       job_type
+ *   type_name      job_type
  */
 struct s_jt jobtypes[] = {
    {"backup",        JT_BACKUP},
    {"admin",         JT_ADMIN},
    {"verify",        JT_VERIFY},
    {"restore",       JT_RESTORE},
-   {NULL,            0}
+   {NULL,           0}
 };
 
 
@@ -354,7 +354,7 @@ static struct s_kw BakVerFields[] = {
    {"client",        'C'},
    {"fileset",       'F'},
    {"level",         'L'}, 
-   {NULL,            0}
+   {NULL,           0}
 };
 
 /* Keywords (RHS) permitted in Restore records */
@@ -365,7 +365,7 @@ static struct s_kw RestoreFields[] = {
    {"where",         'W'},            /* root of restore */
    {"replace",       'R'},            /* replacement options */
    {"bootstrap",     'B'},            /* bootstrap file */
-   {NULL,              0}
+   {NULL,             0}
 };
 
 /* Options permitted in Restore replace= */
@@ -374,7 +374,7 @@ struct s_kw ReplaceOptions[] = {
    {"ifnewer",        REPLACE_IFNEWER},
    {"ifolder",        REPLACE_IFOLDER},
    {"never",          REPLACE_NEVER},
-   {NULL,               0}
+   {NULL,              0}
 };
 
 char *level_to_str(int level)
@@ -386,8 +386,8 @@ char *level_to_str(int level)
    sprintf(level_no, "%d", level);    /* default if not found */
    for (i=0; joblevels[i].level_name; i++) {
       if (level == joblevels[i].level) {
-         str = joblevels[i].level_name;
-         break;
+        str = joblevels[i].level_name;
+        break;
       }
    }
    return str;
@@ -404,87 +404,87 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...
       sendit(sock, "No %s resource defined\n", res_to_str(type));
       return;
    }
-   if (type < 0) {                    /* no recursion */
+   if (type < 0) {                   /* no recursion */
       type = - type;
       recurse = 0;
    }
    switch (type) {
    case R_DIRECTOR:
       sendit(sock, "Director: name=%s MaxJobs=%d FDtimeout=%s SDtimeout=%s\n", 
-         reshdr->name, res->res_dir.MaxConcurrentJobs, 
-         edit_uint64(res->res_dir.FDConnectTimeout, ed1),
-         edit_uint64(res->res_dir.SDConnectTimeout, ed2));
+        reshdr->name, res->res_dir.MaxConcurrentJobs, 
+        edit_uint64(res->res_dir.FDConnectTimeout, ed1),
+        edit_uint64(res->res_dir.SDConnectTimeout, ed2));
       if (res->res_dir.query_file) {
          sendit(sock, "   query_file=%s\n", res->res_dir.query_file);
       }
       if (res->res_dir.messages) {
          sendit(sock, "  --> ");
-         dump_resource(-R_MSGS, (RES *)res->res_dir.messages, sendit, sock);
+        dump_resource(-R_MSGS, (RES *)res->res_dir.messages, sendit, sock);
       }
       break;
    case R_CONSOLE:
       sendit(sock, "Console: name=%s SSL=%d\n", 
-         res->res_con.hdr.name, res->res_con.enable_ssl);
+        res->res_con.hdr.name, res->res_con.enable_ssl);
       break;
    case R_COUNTER:
       sendit(sock, "Counter: name=%s min=%d max=%d\n",
-         res->res_counter.hdr.name, res->res_counter.MinValue, 
-         res->res_counter.MaxValue);
+        res->res_counter.hdr.name, res->res_counter.MinValue, 
+        res->res_counter.MaxValue);
       if (res->res_counter.Catalog) {
          sendit(sock, "  --> ");
-         dump_resource(-R_CATALOG, (RES *)res->res_counter.Catalog, sendit, sock);
+        dump_resource(-R_CATALOG, (RES *)res->res_counter.Catalog, sendit, sock);
       }
       if (res->res_counter.WrapCounter) {
          sendit(sock, "  --> ");
-         dump_resource(-R_COUNTER, (RES *)res->res_counter.WrapCounter, sendit, sock);
+        dump_resource(-R_COUNTER, (RES *)res->res_counter.WrapCounter, sendit, sock);
       }
 
 
 
-         break;
+        break;
    case R_CLIENT:
       sendit(sock, "Client: name=%s address=%s FDport=%d MaxJobs=%u\n",
-         res->res_client.hdr.name, res->res_client.address, res->res_client.FDport,
-         res->res_client.MaxConcurrentJobs);
+        res->res_client.hdr.name, res->res_client.address, res->res_client.FDport,
+        res->res_client.MaxConcurrentJobs);
       sendit(sock, "      JobRetention=%" lld " FileRetention=%" lld " AutoPrune=%d\n",
-         res->res_client.JobRetention, res->res_client.FileRetention,
-         res->res_client.AutoPrune);
+        res->res_client.JobRetention, res->res_client.FileRetention,
+        res->res_client.AutoPrune);
       if (res->res_client.catalog) {
          sendit(sock, "  --> ");
-         dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock);
+        dump_resource(-R_CATALOG, (RES *)res->res_client.catalog, sendit, sock);
       }
       break;
    case R_STORAGE:
       sendit(sock, "Storage: name=%s address=%s SDport=%d MaxJobs=%u\n\
       DeviceName=%s MediaType=%s\n",
-         res->res_store.hdr.name, res->res_store.address, res->res_store.SDport,
-         res->res_store.MaxConcurrentJobs,
-         res->res_store.dev_name, res->res_store.media_type);
+        res->res_store.hdr.name, res->res_store.address, res->res_store.SDport,
+        res->res_store.MaxConcurrentJobs,
+        res->res_store.dev_name, res->res_store.media_type);
       break;
    case R_CATALOG:
       sendit(sock, "Catalog: name=%s address=%s DBport=%d db_name=%s\n\
       db_user=%s\n",
-         res->res_cat.hdr.name, NPRT(res->res_cat.db_address),
-         res->res_cat.db_port, res->res_cat.db_name, NPRT(res->res_cat.db_user));
+        res->res_cat.hdr.name, NPRT(res->res_cat.db_address),
+        res->res_cat.db_port, res->res_cat.db_name, NPRT(res->res_cat.db_user));
       break;
    case R_JOB:
       sendit(sock, "Job: name=%s JobType=%d level=%s MaxJobs=%u\n", 
-         res->res_job.hdr.name, res->res_job.JobType, 
-         level_to_str(res->res_job.level), res->res_job.MaxConcurrentJobs);
+        res->res_job.hdr.name, res->res_job.JobType, 
+        level_to_str(res->res_job.level), res->res_job.MaxConcurrentJobs);
       sendit(sock, "     Resched=%d Times=%d Interval=%s\n",
-          res->res_job.RescheduleOnError, res->res_job.RescheduleTimes,
-          edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1));
+         res->res_job.RescheduleOnError, res->res_job.RescheduleTimes,
+         edit_uint64_with_commas(res->res_job.RescheduleInterval, ed1));
       if (res->res_job.client) {
          sendit(sock, "  --> ");
-         dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock);
+        dump_resource(-R_CLIENT, (RES *)res->res_job.client, sendit, sock);
       }
       if (res->res_job.fileset) {
          sendit(sock, "  --> ");
-         dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock);
+        dump_resource(-R_FILESET, (RES *)res->res_job.fileset, sendit, sock);
       }
       if (res->res_job.schedule) {
          sendit(sock, "  --> ");
-         dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock);
+        dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock);
       }
       if (res->res_job.RestoreWhere) {
          sendit(sock, "  --> Where=%s\n", NPRT(res->res_job.RestoreWhere));
@@ -503,108 +503,108 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...
       }
       if (res->res_job.storage) {
          sendit(sock, "  --> ");
-         dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock);
+        dump_resource(-R_STORAGE, (RES *)res->res_job.storage, sendit, sock);
       }
       if (res->res_job.pool) {
          sendit(sock, "  --> ");
-         dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock);
+        dump_resource(-R_POOL, (RES *)res->res_job.pool, sendit, sock);
       } else {
          sendit(sock, "!!! No Pool resource\n");
       }
       if (res->res_job.messages) {
          sendit(sock, "  --> ");
-         dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock);
+        dump_resource(-R_MSGS, (RES *)res->res_job.messages, sendit, sock);
       }
       break;
    case R_FILESET:
       sendit(sock, "FileSet: name=%s\n", res->res_fs.hdr.name);
       for (int i=0; i<res->res_fs.num_includes; i++) {
-         INCEXE *incexe = res->res_fs.include_items[i];
-         for (int j=0; j<incexe->num_names; j++) {
+        INCEXE *incexe = res->res_fs.include_items[i];
+        for (int j=0; j<incexe->num_names; j++) {
             sendit(sock, "      Inc: %s\n", incexe->name_list[j]);
-         }
+        }
       }
       for (int i=0; i<res->res_fs.num_excludes; i++) {
-         INCEXE *incexe = res->res_fs.exclude_items[i];
-         for (int j=0; j<incexe->num_names; j++) {
+        INCEXE *incexe = res->res_fs.exclude_items[i];
+        for (int j=0; j<incexe->num_names; j++) {
             sendit(sock, "      Exc: %s\n", incexe->name_list[j]);
-         }
+        }
       }
       break;
    case R_SCHEDULE:
       if (res->res_sch.run) {
-         int i;
-         RUN *run = res->res_sch.run;
-         char buf[1000], num[10];
+        int i;
+        RUN *run = res->res_sch.run;
+        char buf[1000], num[10];
          sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
-         if (!run) {
-            break;
-         }
+        if (!run) {
+           break;
+        }
 next_run:
          sendit(sock, "  --> Run Level=%s\n", level_to_str(run->level));
          strcpy(buf, "      hour=");
-         for (i=0; i<24; i++) {
-            if (bit_is_set(i, run->hour)) {
+        for (i=0; i<24; i++) {
+           if (bit_is_set(i, run->hour)) {
                sprintf(num, "%d ", i);
-               strcat(buf, num);
-            }
-         }
+              strcat(buf, num);
+           }
+        }
          strcat(buf, "\n");
-         sendit(sock, buf);
+        sendit(sock, buf);
          strcpy(buf, "      mday=");
-         for (i=0; i<31; i++) {
-            if (bit_is_set(i, run->mday)) {
+        for (i=0; i<31; i++) {
+           if (bit_is_set(i, run->mday)) {
                sprintf(num, "%d ", i+1);
-               strcat(buf, num);
-            }
-         }
+              strcat(buf, num);
+           }
+        }
          strcat(buf, "\n");
-         sendit(sock, buf);
+        sendit(sock, buf);
          strcpy(buf, "      month=");
-         for (i=0; i<12; i++) {
-            if (bit_is_set(i, run->month)) {
+        for (i=0; i<12; i++) {
+           if (bit_is_set(i, run->month)) {
                sprintf(num, "%d ", i+1);
-               strcat(buf, num);
-            }
-         }
+              strcat(buf, num);
+           }
+        }
          strcat(buf, "\n");
-         sendit(sock, buf);
+        sendit(sock, buf);
          strcpy(buf, "      wday=");
-         for (i=0; i<7; i++) {
-            if (bit_is_set(i, run->wday)) {
+        for (i=0; i<7; i++) {
+           if (bit_is_set(i, run->wday)) {
                sprintf(num, "%d ", i+1);
-               strcat(buf, num);
-            }
-         }
+              strcat(buf, num);
+           }
+        }
          strcat(buf, "\n");
-         sendit(sock, buf);
+        sendit(sock, buf);
          strcpy(buf, "      wpos=");
-         for (i=0; i<5; i++) {
-            if (bit_is_set(i, run->wpos)) {
+        for (i=0; i<5; i++) {
+           if (bit_is_set(i, run->wpos)) {
                sprintf(num, "%d ", i+1);
-               strcat(buf, num);
-            }
-         }
+              strcat(buf, num);
+           }
+        }
          strcat(buf, "\n");
-         sendit(sock, buf);
+        sendit(sock, buf);
          sendit(sock, "      mins=%d\n", run->minute);
-         if (run->pool) {
+        if (run->pool) {
             sendit(sock, "     --> ");
-            dump_resource(-R_POOL, (RES *)run->pool, sendit, sock);
-         }
-         if (run->storage) {
+           dump_resource(-R_POOL, (RES *)run->pool, sendit, sock);
+        }
+        if (run->storage) {
             sendit(sock, "     --> ");
-            dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock);
-         }
-         if (run->msgs) {
+           dump_resource(-R_STORAGE, (RES *)run->storage, sendit, sock);
+        }
+        if (run->msgs) {
             sendit(sock, "     --> ");
-            dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock);
-         }
-         /* If another Run record is chained in, go print it */
-         if (run->next) {
-            run = run->next;
-            goto next_run;
-         }
+           dump_resource(-R_MSGS, (RES *)run->msgs, sendit, sock);
+        }
+        /* If another Run record is chained in, go print it */
+        if (run->next) {
+           run = run->next;
+           goto next_run;
+        }
       } else {
          sendit(sock, "Schedule: name=%s\n", res->res_sch.hdr.name);
       }
@@ -614,20 +614,20 @@ next_run:
       break;
    case R_POOL:
       sendit(sock, "Pool: name=%s PoolType=%s\n", res->res_pool.hdr.name,
-              res->res_pool.pool_type);
+             res->res_pool.pool_type);
       sendit(sock, "      use_cat=%d use_once=%d acpt_any=%d cat_files=%d\n",
-              res->res_pool.use_catalog, res->res_pool.use_volume_once,
-              res->res_pool.accept_any_volume, res->res_pool.catalog_files);
+             res->res_pool.use_catalog, res->res_pool.use_volume_once,
+             res->res_pool.accept_any_volume, res->res_pool.catalog_files);
       sendit(sock, "      max_vols=%d auto_prune=%d VolRetention=%" lld "\n",
-              res->res_pool.max_volumes, res->res_pool.AutoPrune,
-              res->res_pool.VolRetention);
+             res->res_pool.max_volumes, res->res_pool.AutoPrune,
+             res->res_pool.VolRetention);
       sendit(sock, "      recycle=%d LabelFormat=%s\n", res->res_pool.Recycle,
-              NPRT(res->res_pool.label_format));
+             NPRT(res->res_pool.label_format));
       sendit(sock, "      CleaningPrefix=%s\n",
-              NPRT(res->res_pool.cleaning_prefix));
+             NPRT(res->res_pool.cleaning_prefix));
       sendit(sock, "      recyleOldest=%d MaxVolJobs=%d MaxVolFiles=%d\n",
-              res->res_pool.recycle_oldest_volume, 
-              res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles);
+             res->res_pool.purge_oldest_volume, 
+             res->res_pool.MaxVolJobs, res->res_pool.MaxVolFiles);
       break;
    case R_MSGS:
       sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name);
@@ -658,15 +658,8 @@ static void free_incexe(INCEXE *incexe)
    }
    for (int i=0; i<incexe->num_opts; i++) {
       FOPTS *fopt = incexe->opts_list[i];
-      if (fopt->match) {
-         free(fopt->match);
-      }
-      for (int j=0; j<fopt->num_base; j++) {
-         free(fopt->base_list[j]);
-      }
-      if (fopt->base_list) {
-         free(fopt->base_list);
-      }
+      fopt->match.destroy();
+      fopt->base_list.destroy();
       free(fopt);
    }
    if (incexe->opts_list) {
@@ -706,130 +699,130 @@ void free_resource(int type)
    switch (type) {
    case R_DIRECTOR:
       if (res->res_dir.working_directory) {
-         free(res->res_dir.working_directory);
+        free(res->res_dir.working_directory);
       }
       if (res->res_dir.pid_directory) {
-         free(res->res_dir.pid_directory);
+        free(res->res_dir.pid_directory);
       }
       if (res->res_dir.subsys_directory) {
-         free(res->res_dir.subsys_directory);
+        free(res->res_dir.subsys_directory);
       }
       if (res->res_dir.password) {
-         free(res->res_dir.password);
+        free(res->res_dir.password);
       }
       if (res->res_dir.query_file) {
-         free(res->res_dir.query_file);
+        free(res->res_dir.query_file);
       }
       if (res->res_dir.DIRaddr) {
-         free(res->res_dir.DIRaddr);
+        free(res->res_dir.DIRaddr);
       }
       break;
    case R_COUNTER:
        break;
    case R_CONSOLE:
       if (res->res_con.password) {
-         free(res->res_con.password);
+        free(res->res_con.password);
       }
       break;
    case R_CLIENT:
       if (res->res_client.address) {
-         free(res->res_client.address);
+        free(res->res_client.address);
       }
       if (res->res_client.password) {
-         free(res->res_client.password);
+        free(res->res_client.password);
       }
       break;
    case R_STORAGE:
       if (res->res_store.address) {
-         free(res->res_store.address);
+        free(res->res_store.address);
       }
       if (res->res_store.password) {
-         free(res->res_store.password);
+        free(res->res_store.password);
       }
       if (res->res_store.media_type) {
-         free(res->res_store.media_type);
+        free(res->res_store.media_type);
       }
       if (res->res_store.dev_name) {
-         free(res->res_store.dev_name);
+        free(res->res_store.dev_name);
       }
       break;
    case R_CATALOG:
       if (res->res_cat.db_address) {
-         free(res->res_cat.db_address);
+        free(res->res_cat.db_address);
       }
       if (res->res_cat.db_socket) {
-         free(res->res_cat.db_socket);
+        free(res->res_cat.db_socket);
       }
       if (res->res_cat.db_user) {
-         free(res->res_cat.db_user);
+        free(res->res_cat.db_user);
       }
       if (res->res_cat.db_name) {
-         free(res->res_cat.db_name);
+        free(res->res_cat.db_name);
       }
       if (res->res_cat.db_password) {
-         free(res->res_cat.db_password);
+        free(res->res_cat.db_password);
       }
       break;
    case R_FILESET:
       if ((num=res->res_fs.num_includes)) {
-         while (--num >= 0) {   
-            free_incexe(res->res_fs.include_items[num]);
-         }
-         free(res->res_fs.include_items);
+        while (--num >= 0) {   
+           free_incexe(res->res_fs.include_items[num]);
+        }
+        free(res->res_fs.include_items);
       }
       res->res_fs.num_includes = 0;
       if ((num=res->res_fs.num_excludes)) {
-         while (--num >= 0) {   
-            free_incexe(res->res_fs.exclude_items[num]);
-         }
-         free(res->res_fs.exclude_items);
+        while (--num >= 0) {   
+           free_incexe(res->res_fs.exclude_items[num]);
+        }
+        free(res->res_fs.exclude_items);
       }
       res->res_fs.num_excludes = 0;
       break;
    case R_POOL:
       if (res->res_pool.pool_type) {
-         free(res->res_pool.pool_type);
+        free(res->res_pool.pool_type);
       }
       if (res->res_pool.label_format) {
-         free(res->res_pool.label_format);
+        free(res->res_pool.label_format);
       }
       if (res->res_pool.cleaning_prefix) {
-         free(res->res_pool.cleaning_prefix);
+        free(res->res_pool.cleaning_prefix);
       }
       break;
    case R_SCHEDULE:
       if (res->res_sch.run) {
-         RUN *nrun, *next;
-         nrun = res->res_sch.run;
-         while (nrun) {
-            next = nrun->next;
-            free(nrun);
-            nrun = next;
-         }
+        RUN *nrun, *next;
+        nrun = res->res_sch.run;
+        while (nrun) {
+           next = nrun->next;
+           free(nrun);
+           nrun = next;
+        }
       }
       break;
    case R_JOB:
       if (res->res_job.RestoreWhere) {
-         free(res->res_job.RestoreWhere);
+        free(res->res_job.RestoreWhere);
       }
       if (res->res_job.RestoreBootstrap) {
-         free(res->res_job.RestoreBootstrap);
+        free(res->res_job.RestoreBootstrap);
       }
       if (res->res_job.WriteBootstrap) {
-         free(res->res_job.WriteBootstrap);
+        free(res->res_job.WriteBootstrap);
       }
       if (res->res_job.RunBeforeJob) {
-         free(res->res_job.RunBeforeJob);
+        free(res->res_job.RunBeforeJob);
       }
       if (res->res_job.RunAfterJob) {
-         free(res->res_job.RunAfterJob);
+        free(res->res_job.RunAfterJob);
       }
       break;
    case R_MSGS:
       if (res->res_msgs.mail_cmd)
-         free(res->res_msgs.mail_cmd);
+        free(res->res_msgs.mail_cmd);
       if (res->res_msgs.operator_cmd)
-         free(res->res_msgs.operator_cmd);
+        free(res->res_msgs.operator_cmd);
       free_msgs_res((MSGS *)res);  /* free message resource */
       res = NULL;
       break;
@@ -866,10 +859,10 @@ void save_resource(int type, struct res_items *items, int pass)
     */
    for (i=0; items[i].name; i++) {
       if (items[i].flags & ITEM_REQUIRED) {
-            if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {  
+           if (!bit_is_set(i, res_all.res_dir.hdr.item_present)) {  
                Emsg2(M_ERROR_TERM, 0, "%s item is required in %s resource, but not found.\n",
-                 items[i].name, resources[rindex]);
-             }
+                items[i].name, resources[rindex]);
+            }
       }
       /* If this triggers, take a look at lib/parse_conf.h */
       if (i >= MAX_RES_ITEMS) {
@@ -892,83 +885,83 @@ void save_resource(int type, struct res_items *items, int pass)
       case R_POOL:
       case R_MSGS:
       case R_FILESET:
-         break;
+        break;
 
       /* Resources containing another resource */
       case R_DIRECTOR:
-         if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
+        if ((res = (URES *)GetResWithName(R_DIRECTOR, res_all.res_dir.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find Director resource %s\n", res_all.res_dir.hdr.name);
-         }
-         res->res_dir.messages = res_all.res_dir.messages;
-         break;
+        }
+        res->res_dir.messages = res_all.res_dir.messages;
+        break;
       case R_JOB:
-         if ((res = (URES *)GetResWithName(R_JOB, res_all.res_dir.hdr.name)) == NULL) {
+        if ((res = (URES *)GetResWithName(R_JOB, res_all.res_dir.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find Job resource %s\n", res_all.res_dir.hdr.name);
-         }
-         res->res_job.messages = res_all.res_job.messages;
-         res->res_job.schedule = res_all.res_job.schedule;
-         res->res_job.client   = res_all.res_job.client;
-         res->res_job.fileset  = res_all.res_job.fileset;
-         res->res_job.storage  = res_all.res_job.storage;
-         res->res_job.pool     = res_all.res_job.pool;
-         if (res->res_job.JobType == 0) {
+        }
+        res->res_job.messages = res_all.res_job.messages;
+        res->res_job.schedule = res_all.res_job.schedule;
+        res->res_job.client   = res_all.res_job.client;
+        res->res_job.fileset  = res_all.res_job.fileset;
+        res->res_job.storage  = res_all.res_job.storage;
+        res->res_job.pool     = res_all.res_job.pool;
+        if (res->res_job.JobType == 0) {
             Emsg1(M_ERROR_TERM, 0, "Job Type not defined for Job resource %s\n", res_all.res_dir.hdr.name);
-         }
-         if (res->res_job.level != 0) {
-            int i;
-            for (i=0; joblevels[i].level_name; i++) {
-               if (joblevels[i].level == res->res_job.level &&
-                   joblevels[i].job_type == res->res_job.JobType) {
-                  i = 0;
-                  break;
-               }
-            }
-            if (i != 0) {
+        }
+        if (res->res_job.level != 0) {
+           int i;
+           for (i=0; joblevels[i].level_name; i++) {
+              if (joblevels[i].level == res->res_job.level &&
+                  joblevels[i].job_type == res->res_job.JobType) {
+                 i = 0;
+                 break;
+              }
+           }
+           if (i != 0) {
                Emsg1(M_ERROR_TERM, 0, "Inappropriate level specified in Job resource %s\n", 
-                  res_all.res_dir.hdr.name);
-            }
-         }
-         break;
+                 res_all.res_dir.hdr.name);
+           }
+        }
+        break;
       case R_COUNTER:
-         if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
+        if ((res = (URES *)GetResWithName(R_COUNTER, res_all.res_counter.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find Counter resource %s\n", res_all.res_counter.hdr.name);
-         }
-         res->res_counter.Catalog = res_all.res_counter.Catalog;
-         res->res_counter.WrapCounter = res_all.res_counter.WrapCounter;
-         break;
+        }
+        res->res_counter.Catalog = res_all.res_counter.Catalog;
+        res->res_counter.WrapCounter = res_all.res_counter.WrapCounter;
+        break;
 
       case R_CLIENT:
-         if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.hdr.name)) == NULL) {
+        if ((res = (URES *)GetResWithName(R_CLIENT, res_all.res_client.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find Client resource %s\n", res_all.res_client.hdr.name);
-         }
-         res->res_client.catalog = res_all.res_client.catalog;
-         break;
+        }
+        res->res_client.catalog = res_all.res_client.catalog;
+        break;
       case R_SCHEDULE:
-         /* Schedule is a bit different in that it contains a RUN record
+        /* Schedule is a bit different in that it contains a RUN record
           * chain which isn't a "named" resource. This chain was linked
-          * in by run_conf.c during pass 2, so here we jam the pointer 
-          * into the Schedule resource.                         
-          */
-         if ((res = (URES *)GetResWithName(R_SCHEDULE, res_all.res_client.hdr.name)) == NULL) {
+         * in by run_conf.c during pass 2, so here we jam the pointer 
+         * into the Schedule resource.                         
+         */
+        if ((res = (URES *)GetResWithName(R_SCHEDULE, res_all.res_client.hdr.name)) == NULL) {
             Emsg1(M_ERROR_TERM, 0, "Cannot find Schedule resource %s\n", res_all.res_client.hdr.name);
-         }
-         res->res_sch.run = res_all.res_sch.run;
-         break;
+        }
+        res->res_sch.run = res_all.res_sch.run;
+        break;
       default:
          Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type);
-         error = 1;
-         break;
+        error = 1;
+        break;
       }
       /* Note, the resource name was already saved during pass 1,
        * so here, we can just release it.
        */
       if (res_all.res_dir.hdr.name) {
-         free(res_all.res_dir.hdr.name);
-         res_all.res_dir.hdr.name = NULL;
+        free(res_all.res_dir.hdr.name);
+        res_all.res_dir.hdr.name = NULL;
       }
       if (res_all.res_dir.hdr.desc) {
-         free(res_all.res_dir.hdr.desc);
-         res_all.res_dir.hdr.desc = NULL;
+        free(res_all.res_dir.hdr.desc);
+        res_all.res_dir.hdr.desc = NULL;
       }
       return;
    }
@@ -1022,17 +1015,17 @@ void save_resource(int type, struct res_items *items, int pass)
       res = (URES *)malloc(size);
       memcpy(res, &res_all, size);
       if (!resources[rindex].res_head) {
-         resources[rindex].res_head = (RES *)res; /* store first entry */
+        resources[rindex].res_head = (RES *)res; /* store first entry */
          Dmsg3(200, "Inserting first %s res: %s index=%d\n", res_to_str(type),
-               res->res_dir.hdr.name, rindex);
+              res->res_dir.hdr.name, rindex);
       } else {
-         RES *next;
-         /* Add new res to end of chain */
-         for (next=resources[rindex].res_head; next->next; next=next->next)
-            { }
-         next->next = (RES *)res;
+        RES *next;
+        /* Add new res to end of chain */
+        for (next=resources[rindex].res_head; next->next; next=next->next)
+           { }
+        next->next = (RES *)res;
          Dmsg3(200, "Inserting %s res: %s index=%d\n", res_to_str(type),
-               res->res_dir.hdr.name, rindex);
+              res->res_dir.hdr.name, rindex);
       }
    }
 }
@@ -1049,9 +1042,9 @@ static void store_jobtype(LEX *lc, struct res_items *item, int index, int pass)
    /* Store the type both pass 1 and pass 2 */
    for (i=0; jobtypes[i].type_name; i++) {
       if (strcasecmp(lc->str, jobtypes[i].type_name) == 0) {
-         ((JOB *)(item->value))->JobType = jobtypes[i].job_type;
-         i = 0;
-         break;
+        ((JOB *)(item->value))->JobType = jobtypes[i].job_type;
+        i = 0;
+        break;
       }
    }
    if (i != 0) {
@@ -1073,9 +1066,9 @@ static void store_level(LEX *lc, struct res_items *item, int index, int pass)
    /* Store the level pass 2 so that type is defined */
    for (i=0; joblevels[i].level_name; i++) {
       if (strcasecmp(lc->str, joblevels[i].level_name) == 0) {
-         ((JOB *)(item->value))->level = joblevels[i].level;
-         i = 0;
-         break;
+        ((JOB *)(item->value))->level = joblevels[i].level;
+        i = 0;
+        break;
       }
    }
    if (i != 0) {
@@ -1092,9 +1085,9 @@ static void store_replace(LEX *lc, struct res_items *item, int index, int pass)
    /* Scan Replacement options */
    for (i=0; ReplaceOptions[i].name; i++) {
       if (strcasecmp(lc->str, ReplaceOptions[i].name) == 0) {
-         *(int *)(item->value) = ReplaceOptions[i].token;
-         i = 0;
-         break;
+        *(int *)(item->value) = ReplaceOptions[i].token;
+        i = 0;
+        break;
       }
    }
    if (i != 0) {
@@ -1132,59 +1125,59 @@ static void store_backup(LEX *lc, struct res_items *item, int index, int pass)
       Dmsg1(190, "Got keyword: %s\n", lc->str);
       found = FALSE;
       for (i=0; BakVerFields[i].name; i++) {
-         if (strcasecmp(lc->str, BakVerFields[i].name) == 0) {
-            found = TRUE;
-            if (lex_get_token(lc, T_ALL) != T_EQUALS) {
+        if (strcasecmp(lc->str, BakVerFields[i].name) == 0) {
+           found = TRUE;
+           if (lex_get_token(lc, T_ALL) != T_EQUALS) {
                scan_err1(lc, "Expected an equals, got: %s", lc->str);
-            }
-            token = lex_get_token(lc, T_NAME);
+           }
+           token = lex_get_token(lc, T_NAME);
             Dmsg1(190, "Got value: %s\n", lc->str);
-            switch (BakVerFields[i].token) {
+           switch (BakVerFields[i].token) {
                case 'C':
-                  /* Find Client Resource */
-                  if (pass == 2) {
-                     res = GetResWithName(R_CLIENT, lc->str);
-                     if (res == NULL) {
+                 /* Find Client Resource */
+                 if (pass == 2) {
+                    res = GetResWithName(R_CLIENT, lc->str);
+                    if (res == NULL) {
                         scan_err1(lc, "Could not find specified Client Resource: %s",
-                                   lc->str);
-                     }
-                     res_all.res_job.client = (CLIENT *)res;
-                  }
-                  break;
+                                  lc->str);
+                    }
+                    res_all.res_job.client = (CLIENT *)res;
+                 }
+                 break;
                case 'F':
-                  /* Find FileSet Resource */
-                  if (pass == 2) {
-                     res = GetResWithName(R_FILESET, lc->str);
-                     if (res == NULL) {
+                 /* Find FileSet Resource */
+                 if (pass == 2) {
+                    res = GetResWithName(R_FILESET, lc->str);
+                    if (res == NULL) {
                         scan_err1(lc, "Could not find specified FileSet Resource: %s\n",
-                                    lc->str);
-                     }
-                     res_all.res_job.fileset = (FILESET *)res;
-                  }
-                  break;
+                                   lc->str);
+                    }
+                    res_all.res_job.fileset = (FILESET *)res;
+                 }
+                 break;
                case 'L':
-                  /* Get level */
-                  for (i=0; joblevels[i].level_name; i++) {
-                     if (joblevels[i].job_type == item->code && 
-                          strcasecmp(lc->str, joblevels[i].level_name) == 0) {
-                        ((JOB *)(item->value))->level = joblevels[i].level;
-                        i = 0;
-                        break;
-                     }
-                  }
-                  if (i != 0) {
+                 /* Get level */
+                 for (i=0; joblevels[i].level_name; i++) {
+                    if (joblevels[i].job_type == item->code && 
+                         strcasecmp(lc->str, joblevels[i].level_name) == 0) {
+                       ((JOB *)(item->value))->level = joblevels[i].level;
+                       i = 0;
+                       break;
+                    }
+                 }
+                 if (i != 0) {
                      scan_err1(lc, "Expected a Job Level keyword, got: %s", lc->str);
-                  }
-                  break;
-            } /* end switch */
-            break;
-         } /* end if strcmp() */
+                 }
+                 break;
+           } /* end switch */
+           break;
+        } /* end if strcmp() */
       } /* end for */
       if (!found) {
          scan_err1(lc, "%s not a valid Backup/verify keyword", lc->str);
       }
    } /* end while */
-   lc->options = options;             /* reset original options */
+   lc->options = options;            /* reset original options */
    set_bit(index, res_all.hdr.item_present);
 }
 
@@ -1214,91 +1207,91 @@ static void store_restore(LEX *lc, struct res_items *item, int index, int pass)
       found = FALSE;
       for (i=0; RestoreFields[i].name; i++) {
          Dmsg1(190, "Restore kw=%s\n", lc->str);
-         if (strcasecmp(lc->str, RestoreFields[i].name) == 0) {
-            found = TRUE;
-            if (lex_get_token(lc, T_ALL) != T_EQUALS) {
+        if (strcasecmp(lc->str, RestoreFields[i].name) == 0) {
+           found = TRUE;
+           if (lex_get_token(lc, T_ALL) != T_EQUALS) {
                scan_err1(lc, "Expected an equals, got: %s", lc->str);
-            }
-            token = lex_get_token(lc, T_ALL);
+           }
+           token = lex_get_token(lc, T_ALL);
             Dmsg1(190, "Restore value=%s\n", lc->str);
-            switch (RestoreFields[i].token) {
+           switch (RestoreFields[i].token) {
                case 'B':
-                  /* Bootstrap */
-                  if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
+                 /* Bootstrap */
+                 if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
                      scan_err1(lc, "Expected a Restore bootstrap file, got: %s", lc->str);
-                  }
-                  if (pass == 1) {
-                     res_all.res_job.RestoreBootstrap = bstrdup(lc->str);
-                  }
-                  break;
+                 }
+                 if (pass == 1) {
+                    res_all.res_job.RestoreBootstrap = bstrdup(lc->str);
+                 }
+                 break;
                case 'C':
-                  /* Find Client Resource */
-                  if (pass == 2) {
-                     res = GetResWithName(R_CLIENT, lc->str);
-                     if (res == NULL) {
+                 /* Find Client Resource */
+                 if (pass == 2) {
+                    res = GetResWithName(R_CLIENT, lc->str);
+                    if (res == NULL) {
                         scan_err1(lc, "Could not find specified Client Resource: %s",
-                                   lc->str);
-                     }
-                     res_all.res_job.client = (CLIENT *)res;
-                  }
-                  break;
+                                  lc->str);
+                    }
+                    res_all.res_job.client = (CLIENT *)res;
+                 }
+                 break;
                case 'F':
-                  /* Find FileSet Resource */
-                  if (pass == 2) {
-                     res = GetResWithName(R_FILESET, lc->str);
-                     if (res == NULL) {
+                 /* Find FileSet Resource */
+                 if (pass == 2) {
+                    res = GetResWithName(R_FILESET, lc->str);
+                    if (res == NULL) {
                         scan_err1(lc, "Could not find specified FileSet Resource: %s\n",
-                                    lc->str);
-                     }
-                     res_all.res_job.fileset = (FILESET *)res;
-                  }
-                  break;
+                                   lc->str);
+                    }
+                    res_all.res_job.fileset = (FILESET *)res;
+                 }
+                 break;
                case 'J':
-                  /* JobId */
-                  if (token != T_NUMBER) {
+                 /* JobId */
+                 if (token != T_NUMBER) {
                      scan_err1(lc, "expected an integer number, got: %s", lc->str);
-                  }
-                  errno = 0;
-                  res_all.res_job.RestoreJobId = strtol(lc->str, NULL, 0);
+                 }
+                 errno = 0;
+                 res_all.res_job.RestoreJobId = strtol(lc->str, NULL, 0);
                   Dmsg1(190, "RestorJobId=%d\n", res_all.res_job.RestoreJobId);
-                  if (errno != 0) {
+                 if (errno != 0) {
                      scan_err1(lc, "expected an integer number, got: %s", lc->str);
-                  }
-                  break;
+                 }
+                 break;
                case 'W':
-                  /* Where */
-                  if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
+                 /* Where */
+                 if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
                      scan_err1(lc, "Expected a Restore root directory, got: %s", lc->str);
-                  }
-                  if (pass == 1) {
-                     res_all.res_job.RestoreWhere = bstrdup(lc->str);
-                  }
-                  break;
+                 }
+                 if (pass == 1) {
+                    res_all.res_job.RestoreWhere = bstrdup(lc->str);
+                 }
+                 break;
                case 'R':
-                  /* Replacement options */
-                  if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
+                 /* Replacement options */
+                 if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
                      scan_err1(lc, "Expected a keyword name, got: %s", lc->str);
-                  }
-                  /* Fix to scan Replacement options */
-                  for (i=0; ReplaceOptions[i].name; i++) {
-                     if (strcasecmp(lc->str, ReplaceOptions[i].name) == 0) {
-                         ((JOB *)(item->value))->replace = ReplaceOptions[i].token;
-                        i = 0;
-                        break;
-                     }
-                  }
-                  if (i != 0) {
+                 }
+                 /* Fix to scan Replacement options */
+                 for (i=0; ReplaceOptions[i].name; i++) {
+                    if (strcasecmp(lc->str, ReplaceOptions[i].name) == 0) {
+                        ((JOB *)(item->value))->replace = ReplaceOptions[i].token;
+                       i = 0;
+                       break;
+                    }
+                 }
+                 if (i != 0) {
                      scan_err1(lc, "Expected a Restore replacement option, got: %s", lc->str);
-                  }
-                  break;
-            } /* end switch */
-            break;
-         } /* end if strcmp() */
+                 }
+                 break;
+           } /* end switch */
+           break;
+        } /* end if strcmp() */
       } /* end for */
       if (!found) {
          scan_err1(lc, "%s not a valid Restore keyword", lc->str);
       }
    } /* end while */
-   lc->options = options;             /* reset original options */
+   lc->options = options;            /* reset original options */
    set_bit(index, res_all.hdr.item_present);
 }
index 817183b1b3ddce0cd89f52922b35531c480b1ef8..146fb29a0da77936fdfd8a5df3efc3c33b057ff4 100644 (file)
@@ -210,17 +210,16 @@ struct JOB {
 
 #define MAX_FOPTS 30
 
-struct s_fopts_item {
+/* File options structure */
+struct FOPTS {
    char opts[MAX_FOPTS];              /* options string */
-   char *match;                       /* match string */
-   char **base_list;                  /* list of base job names */
-   int  num_base;                     /* number of bases in list */
+   alist match;                       /* match string(s) */
+   alist base_list;                   /* list of base names */
 };
-typedef struct s_fopts_item FOPTS;
 
 
 /* This is either an include item or an exclude item */
-struct s_incexc_item {
+struct INCEXE {
    FOPTS *current_opts;               /* points to current options structure */
    FOPTS **opts_list;                 /* options list */
    int num_opts;                      /* number of options items */
@@ -228,7 +227,6 @@ struct s_incexc_item {
    int max_names;                     /* malloc'ed size of name list */
    int num_names;                     /* number of names in the list */
 };
-typedef struct s_incexc_item INCEXE;
 
 /* 
  *   FileSet Resource
@@ -294,7 +292,7 @@ struct POOL {
    int   catalog_files;               /* maintain file entries in catalog */
    int   use_volume_once;             /* write on volume only once */
    int   accept_any_volume;           /* accept any volume */
-   int   recycle_oldest_volume;       /* recycle oldest volume */
+   int   purge_oldest_volume;        /* purge oldest volume */
    uint32_t max_volumes;              /* max number of volumes */
    utime_t VolRetention;              /* volume retention period in seconds */
    utime_t VolUseDuration;            /* duration volume can be used */
index 8323a21a88c39d60ccd6962b562760a21b6ebd9b..450e005d807cfad4a9cb87e44afbdf738eaa193e 100644 (file)
@@ -167,21 +167,21 @@ int send_level_command(JCR *jcr)
     * Send Level command to File daemon
     */
    switch (jcr->JobLevel) {
-      case L_BASE:
-         bnet_fsend(fd, levelcmd, "base", " ", 0);
-        break;
-      case L_FULL:
-         bnet_fsend(fd, levelcmd, "full", " ", 0);
-        break;
-      case L_DIFFERENTIAL:
-      case L_INCREMENTAL:
-         bnet_fsend(fd, levelcmd, "since ", jcr->stime, 0);
-        break;
-      case L_SINCE:
-      default:
-         Jmsg2(jcr, M_FATAL, 0, _("Unimplemented backup level %d %c\n"), 
-           jcr->JobLevel, jcr->JobLevel);
-        return 0;
+   case L_BASE:
+      bnet_fsend(fd, levelcmd, "base", " ", 0);
+      break;
+   case L_FULL:
+      bnet_fsend(fd, levelcmd, "full", " ", 0);
+      break;
+   case L_DIFFERENTIAL:
+   case L_INCREMENTAL:
+      bnet_fsend(fd, levelcmd, "since ", jcr->stime, 0);
+      break;
+   case L_SINCE:
+   default:
+      Jmsg2(jcr, M_FATAL, 0, _("Unimplemented backup level %d %c\n"), 
+        jcr->JobLevel, jcr->JobLevel);
+      return 0;
    }
    Dmsg1(120, ">filed: %s", fd->msg);
    if (!response(jcr, fd, OKlevel, "Level", DISPLAY_ERROR)) {
@@ -216,12 +216,18 @@ static int send_list(JCR *jcr, int list)
       char *p;
       int optlen, stat;
       INCEXE *ie;
+      FOPTS  *fo;
+
 
       if (list == INC_LIST) {
         ie = fileset->include_items[i];
       } else {
         ie = fileset->exclude_items[i];
       }
+      fo = ie->opts_list[0];
+      for (int j=0; j<fo->match.size(); j++) {
+         Dmsg1(000, "Match=%s\n", fo->match.get(j));
+      }
       for (int j=0; j<ie->num_names; j++) {
         p = ie->name_list[j];
         switch (*p) {
index c5caf6235ebadd7bf58e6e4f199a990b52e289b3..2b2629090f9990054dc8309101be20e4aa2a27de 100644 (file)
@@ -398,17 +398,14 @@ static void store_match(LEX *lc, struct res_items *item, int index, int pass)
        */
       token = lex_get_token(lc, T_ALL);           
       switch (token) {
-        case T_IDENTIFIER:
-        case T_UNQUOTED_STRING:
-        case T_QUOTED_STRING:
-           setup_current_opts();
-           if (res_incexe.current_opts->match) {
-               scan_err0(lc, _("More than one match specified.\n")); 
-           }
-           res_incexe.current_opts->match = bstrdup(lc->str);
-           break;
-        default:
-            scan_err1(lc, _("Expected a filename, got: %s\n"), lc->str);
+      case T_IDENTIFIER:
+      case T_UNQUOTED_STRING:
+      case T_QUOTED_STRING:
+        setup_current_opts();
+        res_incexe.current_opts->match.append(bstrdup(lc->str));
+        break;
+      default:
+         scan_err1(lc, _("Expected a filename, got: %s\n"), lc->str);
       }                                
    } else { /* pass 2 */
       lex_get_token(lc, T_ALL);         
@@ -420,7 +417,6 @@ static void store_match(LEX *lc, struct res_items *item, int index, int pass)
 static void store_base(LEX *lc, struct res_items *item, int index, int pass)
 {
    int token;
-   FOPTS *copt;
 
    if (pass == 1) {
       setup_current_opts();
@@ -428,14 +424,7 @@ static void store_base(LEX *lc, struct res_items *item, int index, int pass)
        * Pickup Base Job Name
        */
       token = lex_get_token(lc, T_NAME);          
-      copt = res_incexe.current_opts;
-      if (copt->base_list == NULL) {
-        copt->base_list = (char **)malloc(sizeof(char *));                     
-      } else {
-        copt->base_list = (char **)realloc(copt->base_list,
-           sizeof(char *) * (copt->num_base+1));
-      }
-      copt->base_list[copt->num_base++] = bstrdup(lc->str);
+      res_incexe.current_opts->base_list.append(bstrdup(lc->str));
    } else { /* pass 2 */
       lex_get_token(lc, T_ALL);         
    }
@@ -507,7 +496,6 @@ static void store_opts(LEX *lc, struct res_items *item, int index, int pass)
 
    if (pass == 1) {
       setup_current_opts();
-
       bstrncat(res_incexe.current_opts->opts, inc_opts, MAX_FOPTS);
    }
 
index 52c1b66f88c9964d4734d791228d21de259a3758..d8b1b72088af86e04609b3c54539bd8e4969064c 100644 (file)
@@ -42,7 +42,7 @@
 #include "dird.h"
 
 /* Commands sent to File daemon */
-static char restorecmd[]   = "restore replace=%c where=%s\n";
+static char restorecmd[]   = "restore replace=%c prelinks=%d where=%s\n";
 static char storaddr[]     = "storage address=%s port=%d ssl=0\n";
 static char sessioncmd[]   = "session %s %ld %ld %ld %ld %ld %ld\n";  
 
@@ -237,7 +237,7 @@ int do_restore(JCR *jcr)
       where = "";                     /* None */
    }
    bash_spaces(where);
-   bnet_fsend(fd, restorecmd, replace, where);
+   bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
    unbash_spaces(where);
 
    if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
index 2e05678084b3203e1d86f3739bc2f306079a461c..ccf346e8621bc5b1d4b82b4157f072fd588dbed3 100644 (file)
@@ -617,18 +617,18 @@ static int update_cmd(UAContext *ua, char *cmd)
    }
 
    switch (find_arg_keyword(ua, kw)) {
-      case 0:
-      case 1:
-        update_volume(ua);
-        return 1;
-      case 2:
-        update_pool(ua);
-        return 1;
-      case 3:
-        update_slots(ua);
-        return 1;
-      default:
-        break;
+   case 0:
+   case 1:
+      update_volume(ua);
+      return 1;
+   case 2:
+      update_pool(ua);
+      return 1;
+   case 3:
+      update_slots(ua);
+      return 1;
+   default:
+      break;
    }
     
    start_prompt(ua, _("Update choice:\n"));
@@ -636,21 +636,142 @@ static int update_cmd(UAContext *ua, char *cmd)
    add_prompt(ua, _("Pool from resource"));
    add_prompt(ua, _("Slots from autochanger"));
    switch (do_prompt(ua, _("item"), _("Choose catalog item to update"), NULL, 0)) {
-      case 0:
-        update_volume(ua);
-        break;
-      case 1:
-        update_pool(ua);
-        break;
-      case 2:
-        update_slots(ua);
-        break;
-      default:
-        break;
+   case 0:
+      update_volume(ua);
+      break;
+   case 1:
+      update_pool(ua);
+      break;
+   case 2:
+      update_slots(ua);
+      break;
+   default:
+      break;
    }
    return 1;
 }
 
+static void update_volstatus(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   bstrncpy(mr->VolStatus, val, sizeof(mr->VolStatus));
+   Mmsg(&query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%u",
+      mr->VolStatus, mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New Volume status is: %s\n"), mr->VolStatus);
+   }
+   free_pool_memory(query);
+}
+
+static void update_volretention(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   char ed1[50];
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   if (!duration_to_utime(val, &mr->VolRetention)) {
+      bsendmsg(ua, _("Invalid retention period specified.\n"));
+      return;
+   }
+   Mmsg(&query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%u",
+      edit_uint64(mr->VolRetention, ed1), mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New retention seconds is: %s\n"),
+        edit_utime(mr->VolRetention, ed1));
+   }
+   free_pool_memory(query);
+}
+
+static void update_voluseduration(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   char ed1[50];
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   if (!duration_to_utime(val, &mr->VolUseDuration)) {
+      bsendmsg(ua, _("Invalid use duration specified.\n"));
+      return;
+   }
+   query = get_pool_memory(PM_MESSAGE);
+   Mmsg(&query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%u",
+      edit_uint64(mr->VolUseDuration, ed1), mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New use duration is: %s\n"),
+        edit_utime(mr->VolUseDuration, ed1));
+   }
+   free_pool_memory(query);
+}
+
+static void update_volmaxjobs(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   Mmsg(&query, "UPDATE Media SET MaxVolJobs=%s WHERE MediaId=%u",
+      val, mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New max jobs is: %s\n"), val);
+   }
+   free_pool_memory(query);
+}
+
+static void update_volmaxfiles(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   Mmsg(&query, "UPDATE Media SET MaxVolFiles=%s WHERE MediaId=%u",
+      val, mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New max files is: %s\n"), val);
+   }
+   free_pool_memory(query);
+}
+
+static void update_volmaxbytes(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   uint64_t maxbytes;
+   char ed1[50];
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   if (!size_to_uint64(val, strlen(val), &maxbytes)) {
+      bsendmsg(ua, _("Invalid byte size specification.\n"));
+      return;
+   } 
+   Mmsg(&query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%u",
+      edit_uint64(maxbytes, ed1), mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {
+      bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
+   }
+   free_pool_memory(query);
+}
+
+static void update_volrecycle(UAContext *ua, char *val, MEDIA_DBR *mr)
+{
+   int recycle;
+   POOLMEM *query = get_pool_memory(PM_MESSAGE);
+   if (strcasecmp(val, _("yes")) == 0) {
+      recycle = 1;
+   } else if (strcasecmp(val, _("no")) == 0) {
+      recycle = 0;
+   } else {
+      bsendmsg(ua, _("Invalid value. It must by yes or no.\n"));
+      return;
+   }
+   Mmsg(&query, "UPDATE Media SET Recycle=%d WHERE MediaId=%u",
+      recycle, mr->MediaId);
+   if (!db_sql_query(ua->db, query, NULL, NULL)) {  
+      bsendmsg(ua, "%s", db_strerror(ua->db));
+   } else {      
+      bsendmsg(ua, _("New recycle flag is: %s\n"),
+         mr->Recycle==1?_("yes"):_("no"));
+   }
+   free_pool_memory(query);
+}
+
 /*
  * Update a media record -- allows you to change the
  *  Volume status. E.g. if you want Bacula to stop
@@ -662,9 +783,31 @@ static int update_volume(UAContext *ua)
    MEDIA_DBR mr;
    POOLMEM *query;
    char ed1[30];
+   bool done = false;
+   char *kw[] = {
+      N_("VolStatus"),
+      N_("VolRetention"),
+      N_("VolUse"),
+      N_("MaxVolJobs"),
+      N_("MaxVolFiles"),
+      N_("Recycle"),
+      NULL };
 
+   if (!select_media_dbr(ua, &mr)) {
+      return 0;
+   }
+   for (int i=0; kw[i]; i++) {
+      if (find_arg_with_value(ua, kw[i]) > 0) {
+        switch (i) {
+        case 0:
+           update_volstatus(ua, ua->argv[i], &mr);
+           break;
+        }
+        done = true;
+      }
+   }
 
-   for (int done=0; !done; ) {
+   for ( ; !done; ) {
       if (!select_media_dbr(ua, &mr)) {
         return 0;
       }
@@ -698,16 +841,7 @@ static int update_volume(UAContext *ua)
          if (do_prompt(ua, "", _("Choose new Volume Status"), ua->cmd, sizeof(mr.VolStatus)) < 0) {
            return 1;
         }
-        bstrncpy(mr.VolStatus, ua->cmd, sizeof(mr.VolStatus));
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET VolStatus='%s' WHERE MediaId=%u",
-           mr.VolStatus, mr.MediaId);
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {  
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New Volume status is: %s\n"), mr.VolStatus);
-        }
-        free_pool_memory(query);
+        update_volstatus(ua, ua->cmd, &mr);
         break;
       case 1:                        /* Retention */
          bsendmsg(ua, _("Current retention seconds is: %s\n"),
@@ -715,20 +849,7 @@ static int update_volume(UAContext *ua)
          if (!get_cmd(ua, _("Enter Volume Retention period: "))) {
            return 0;
         }
-        if (!duration_to_utime(ua->cmd, &mr.VolRetention)) {
-            bsendmsg(ua, _("Invalid retention period specified.\n"));
-           break;
-        }
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET VolRetention=%s WHERE MediaId=%u",
-           edit_uint64(mr.VolRetention, ed1), mr.MediaId);
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {  
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New retention seconds is: %s\n"),
-              edit_utime(mr.VolRetention, ed1));
-        }
-        free_pool_memory(query);
+        update_volretention(ua, ua->cmd, &mr);
         break;
 
       case 2:                        /* Use Duration */
@@ -737,98 +858,41 @@ static int update_volume(UAContext *ua)
          if (!get_cmd(ua, _("Enter Volume Use Duration: "))) {
            return 0;
         }
-        if (!duration_to_utime(ua->cmd, &mr.VolUseDuration)) {
-            bsendmsg(ua, _("Invalid use duration specified.\n"));
-           break;
-        }
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET VolUseDuration=%s WHERE MediaId=%u",
-           edit_uint64(mr.VolUseDuration, ed1), mr.MediaId);
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {  
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New use duration is: %s\n"),
-              edit_utime(mr.VolUseDuration, ed1));
-        }
-        free_pool_memory(query);
+        update_voluseduration(ua, ua->cmd, &mr);
         break;
 
       case 3:                        /* Max Jobs */
-        int32_t maxjobs;
          bsendmsg(ua, _("Current max jobs is: %u\n"), mr.MaxVolJobs);
          if (!get_pint(ua, _("Enter new Maximum Jobs: "))) {
            return 0;
         }
-        maxjobs = ua->pint32_val;
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET MaxVolJobs=%u WHERE MediaId=%u",
-           maxjobs, mr.MediaId);
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {  
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New max jobs is: %u\n"), maxjobs);
-        }
-        free_pool_memory(query);
+        update_volmaxjobs(ua, ua->cmd, &mr);
         break;
 
       case 4:                        /* Max Files */
-        int32_t maxfiles;
          bsendmsg(ua, _("Current max files is: %u\n"), mr.MaxVolFiles);
          if (!get_pint(ua, _("Enter new Maximum Files: "))) {
            return 0;
         }
-        maxfiles = ua->pint32_val;
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET MaxVolFiles=%u WHERE MediaId=%u",
-           maxfiles, mr.MediaId);
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {  
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New max files is: %u\n"), maxfiles);
-        }
-        free_pool_memory(query);
+        update_volmaxfiles(ua, ua->cmd, &mr);
         break;
 
       case 5:                        /* Max Bytes */
-        uint64_t maxbytes;
          bsendmsg(ua, _("Current value is: %s\n"), edit_uint64(mr.MaxVolBytes, ed1));
          if (!get_cmd(ua, _("Enter new Maximum Bytes: "))) {
            return 0;
         }
-        if (!size_to_uint64(ua->cmd, strlen(ua->cmd), &maxbytes)) {
-            bsendmsg(ua, _("Invalid byte size specification.\n"));
-           break;
-        } 
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET MaxVolBytes=%s WHERE MediaId=%u",
-           edit_uint64(maxbytes, ed1), mr.MediaId);
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {  
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {
-            bsendmsg(ua, _("New Max bytes is: %s\n"), edit_uint64(maxbytes, ed1));
-        }
-        free_pool_memory(query);
+        update_volmaxbytes(ua, ua->cmd, &mr);
         break;
 
 
       case 6:                        /* Recycle */
-        int recycle;
          bsendmsg(ua, _("Current recycle flag is: %s\n"),
             mr.Recycle==1?_("yes"):_("no"));
          if (!get_yesno(ua, _("Enter new Recycle status: "))) {
            return 0;
         }
-        recycle = ua->pint32_val;
-        query = get_pool_memory(PM_MESSAGE);
-         Mmsg(&query, "UPDATE Media SET Recycle=%d WHERE MediaId=%u",
-           recycle, mr.MediaId);
-        if (!db_sql_query(ua->db, query, NULL, NULL)) {  
-            bsendmsg(ua, "%s", db_strerror(ua->db));
-        } else {       
-            bsendmsg(ua, _("New recycle flag is: %s\n"),
-               mr.Recycle==1?_("yes"):_("no"));
-        }
-        free_pool_memory(query);
+        update_volrecycle(ua, ua->cmd, &mr);
         break;
 
       case 7:                        /* Slot */
@@ -906,7 +970,6 @@ static int update_pool(UAContext *ua)
    POOL *pool;
    POOLMEM *query;      
    
-   
    pool = get_pool_resource(ua);
    if (!pool) {
       return 0;
@@ -981,7 +1044,6 @@ static void do_client_setdebug(UAContext *ua, CLIENT *client, int level)
    bnet_sig(fd, BNET_TERMINATE);
    bnet_close(fd);
    ua->jcr->file_bsock = NULL;
-
    return;  
 }
 
@@ -1141,26 +1203,26 @@ static int setdebug_cmd(UAContext *ua, char *cmd)
    add_prompt(ua, _("Client"));
    add_prompt(ua, _("All"));
    switch(do_prompt(ua, "", _("Select daemon type to set debug level"), NULL, 0)) {
-      case 0:                        /* Director */
-        debug_level = level;
-        break;
-      case 1:
-        store = get_storage_resource(ua, 0);
-        if (store) {
-           do_storage_setdebug(ua, store, level);
-        }
-        break;
-      case 2:
-        client = select_client_resource(ua);
-        if (client) {
-           do_client_setdebug(ua, client, level);
-        }
-        break;
-      case 3:
-        do_all_setdebug(ua, level);
-        break;
-      default:
-        break;
+   case 0:                        /* Director */
+      debug_level = level;
+      break;
+   case 1:
+      store = get_storage_resource(ua, 0);
+      if (store) {
+        do_storage_setdebug(ua, store, level);
+      }
+      break;
+   case 2:
+      client = select_client_resource(ua);
+      if (client) {
+        do_client_setdebug(ua, client, level);
+      }
+      break;
+   case 3:
+      do_all_setdebug(ua, level);
+      break;
+   default:
+      break;
    }
    return 1;
 }
@@ -1307,25 +1369,25 @@ static int delete_cmd(UAContext *ua, char *cmd)
 "Pool or a Volume since they may contain data.\n\n"));
      
    switch (find_arg_keyword(ua, keywords)) {
-      case 0:
-        delete_volume(ua);     
-        return 1;
-      case 1:
-        delete_pool(ua);
-        return 1;
-      default:
-        break;
+   case 0:
+      delete_volume(ua);     
+      return 1;
+   case 1:
+      delete_pool(ua);
+      return 1;
+   default:
+      break;
    }
    switch (do_keyword_prompt(ua, _("Choose catalog item to delete"), keywords)) {
-      case 0:
-        delete_volume(ua);
-        break;
-      case 1:
-        delete_pool(ua);
-        break;
-      default:
-         bsendmsg(ua, _("Nothing done.\n"));
-        break;
+   case 0:
+      delete_volume(ua);
+      break;
+   case 1:
+      delete_pool(ua);
+      break;
+   default:
+      bsendmsg(ua, _("Nothing done.\n"));
+      break;
    }
    return 1;
 }
index 65505a716ce8084ca9dd31cc16428a6668e65867..c0f3ea74ed55aff70bacc4e911a8bb09f8e0ad48 100644 (file)
@@ -131,5 +131,5 @@ int get_yesno(UAContext *ua, char *prompt)
 
 void parse_ua_args(UAContext *ua)
 {
-   parse_args(ua->cmd, ua->args, &ua->argc, ua->argk, ua->argv, MAX_CMD_ARGS);
+   parse_args(ua->cmd, &ua->args, &ua->argc, ua->argk, ua->argv, MAX_CMD_ARGS);
 }
index e169cfdf3bfb34f61dc9b0e9e2590473d99f74cc..02853da6f07de1970b3342cedfd3e50f7e89ed49 100644 (file)
@@ -80,7 +80,6 @@ static void free_name_list(NAME_LIST *name_list);
 static void get_storage_from_mediatype(UAContext *ua, NAME_LIST *name_list, JOBIDS *ji);
 static int select_backups_before_date(UAContext *ua, JOBIDS *ji, char *date);
 
-
 /*
  *   Restore files
  *
@@ -176,7 +175,6 @@ int restorecmd(UAContext *ua, char *cmd)
       if (!db_sql_query(ua->db, query, unique_name_list_handler, (void *)&name_list)) {
          bsendmsg(ua, "%s", db_strerror(ua->db));
       }
-
    }
    bsendmsg(ua, "%d item%s inserted into the tree and marked for extraction.\n", 
       items, items==1?"":"s");
@@ -186,8 +184,10 @@ int restorecmd(UAContext *ua, char *cmd)
    get_storage_from_mediatype(ua, &name_list, &ji);
    free_name_list(&name_list);
 
-   /* Let the user select which files to restore */
-   user_select_files_from_tree(&tree);
+   if (find_arg(ua, _("all")) < 0) {
+      /* Let the user select which files to restore */
+      user_select_files_from_tree(&tree);
+   }
 
    /*
     * Walk down through the tree finding all files marked to be 
@@ -273,7 +273,8 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
    JobId_t JobId;
    JOB_DBR jr;
    POOLMEM *query;
-   int done = 0;
+   bool done = false;
+   int i;
    char *list[] = { 
       "List last 20 Jobs run",
       "List Jobs where a given File is saved",
@@ -284,23 +285,68 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
       "Cancel",
       NULL };
 
-   bsendmsg(ua, _("\nFirst you select one or more JobIds that contain files\n"
+   char *kw[] = {
+      "jobid",     /* 0 */
+      "current",   /* 1 */
+      "before",    /* 2 */
+      NULL
+   };
+
+   switch (find_arg_keyword(ua, kw)) {
+   case 0:                           /* jobid */
+      i = find_arg_with_value(ua, _("jobid"));
+      if (i < 0) {
+        return 0;
+      }
+      bstrncpy(ji->JobIds, ua->argv[i], sizeof(ji->JobIds));
+      done = true;
+      break;
+   case 1:                           /* current */
+      bstrutime(date, sizeof(date), time(NULL));
+      if (!select_backups_before_date(ua, ji, date)) {
+        return 0;
+      }
+      done = true;
+      break;
+   case 2:                           /* before */
+      i = find_arg_with_value(ua, _("before"));
+      if (i < 0) {
+        return 0;
+      }
+      if (str_to_utime(ua->argv[i]) == 0) {
+         bsendmsg(ua, _("Improper date format: %s\n"), ua->argv[i]);
+        return 0;
+      }
+      bstrncpy(date, ua->argv[i], sizeof(date));
+      if (!select_backups_before_date(ua, ji, date)) {
+        return 0;
+      }
+      done = true;
+      break;
+   default:
+      break;
+   }
+       
+   if (!done) {
+      bsendmsg(ua, _("\nFirst you select one or more JobIds that contain files\n"
                   "to be restored. You will be presented several methods\n"
                   "of specifying the JobIds. Then you will be allowed to\n"
                   "select which files from those JobIds are to be restored.\n\n"));
+   }
 
+   /* If choice not already made above, prompt */
    for ( ; !done; ) {
       start_prompt(ua, _("To select the JobIds, you have the following choices:\n"));
       for (int i=0; list[i]; i++) {
         add_prompt(ua, list[i]);
       }
-      done = 1;
+      done = true;
       switch (do_prompt(ua, "", _("Select item: "), NULL, 0)) {
       case -1:                       /* error */
         return 0;
       case 0:                        /* list last 20 Jobs run */
         db_list_sql_query(ua->jcr, ua->db, uar_list_jobs, prtit, ua, 1, HORZ_LIST);
-        done = 0;
+        done = false;
         break;
       case 1:                        /* list where a file is saved */
         char *fname;
@@ -316,7 +362,7 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
         free(fname);
         db_list_sql_query(ua->jcr, ua->db, query, prtit, ua, 1, HORZ_LIST);
         free_pool_memory(query);
-        done = 0;
+        done = false;
         break;
       case 2:                        /* enter a list of JobIds */
          if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) {
@@ -329,7 +375,7 @@ static int user_select_jobids(UAContext *ua, JOBIDS *ji)
            return 0;
         }
         db_list_sql_query(ua->jcr, ua->db, ua->cmd, prtit, ua, 1, HORZ_LIST);
-        done = 0;
+        done = false;
         break;
       case 4:                        /* Select the most recent backups */
         bstrutime(date, sizeof(date), time(NULL));
@@ -493,15 +539,14 @@ bail_out:
    return stat;
 }
 
-
+/* Return next JobId from comma separated list */
 static int next_jobid_from_list(char **p, uint32_t *JobId)
 {
    char jobid[30];
-   int i;
    char *q = *p;
 
    jobid[0] = 0;
-   for (i=0; i<(int)sizeof(jobid); i++) {
+   for (int i=0; i<(int)sizeof(jobid); i++) {
       if (*q == ',' || *q == 0) {
         q++;
         break;
@@ -524,13 +569,13 @@ static int jobid_handler(void *ctx, int num_fields, char **row)
 {
    JOBIDS *ji = (JOBIDS *)ctx;
 
+   /* Concatenate a JobId if it does not exceed array size */
    if (strlen(ji->JobIds)+strlen(row[0])+2 < sizeof(ji->JobIds)) {
       if (ji->JobIds[0] != 0) {
          strcat(ji->JobIds, ",");
       }
       strcat(ji->JobIds, row[0]);
    }
-
    return 0;
 }
 
@@ -597,9 +642,7 @@ static int unique_name_list_handler(void *ctx, int num_fields, char **row)
  */
 static void print_name_list(UAContext *ua, NAME_LIST *name_list)
 { 
-   int i;
-
-   for (i=0; i < name_list->num_ids; i++) {
+   for (int i=0; i < name_list->num_ids; i++) {
       bsendmsg(ua, "%s\n", name_list->name[i]);
    }
 }
@@ -610,9 +653,7 @@ static void print_name_list(UAContext *ua, NAME_LIST *name_list)
  */
 static void free_name_list(NAME_LIST *name_list)
 { 
-   int i;
-
-   for (i=0; i < name_list->num_ids; i++) {
+   for (int i=0; i < name_list->num_ids; i++) {
       free(name_list->name[i]);
    }
    if (name_list->name) {
index 8275e19834ae8c5b487314d560a84eab65d4a9b7..6dadd3dfffe72aa4a3e7cbcbd74977f5db7bebec 100644 (file)
@@ -447,6 +447,15 @@ When:       %s\n"),
         free_jcr(jcr);
         return 0;
    }
+
+   /* Run without prompting? */
+   if (find_arg(ua, _("yes")) > 0) {
+      Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
+      run_job(jcr);
+      bsendmsg(ua, _("Run command submitted.\n"));
+      return 1;
+   }
+
    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
       free_jcr(jcr);
       return 0;                      /* do not run */
@@ -655,6 +664,7 @@ When:       %s\n"),
       free_jcr(jcr);
       return 0;                      /* error do no run Job */
    }
+
    if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
       Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
       run_job(jcr);
index 39cf261c8ca8ea410b7ba7164ad5655d5c5f83e1..f3afec0d056e8f8e5e52c4aa40c3bd20b6e2b3ed 100644 (file)
@@ -74,9 +74,8 @@ int confirm_retention(UAContext *ua, utime_t *ret, char *msg)
  */
 int find_arg_keyword(UAContext *ua, char **list)
 {
-   int i, j;
-   for (i=1; i<ua->argc; i++) {
-      for(j=0; list[j]; j++) {
+   for (int i=1; i<ua->argc; i++) {
+      for(int j=0; list[j]; j++) {
         if (strcasecmp(_(list[j]), ua->argk[i]) == 0) {
            return j;
         }
@@ -85,11 +84,6 @@ int find_arg_keyword(UAContext *ua, char **list)
    return -1;
 }
 
-/* 
- * Given a single keyword, find it in the argument list.
- * Returns: -1 if not found
- *          list index (base 0) on success
- */
 int find_arg(UAContext *ua, char *keyword)
 {
    for (int i=1; i<ua->argc; i++) {
@@ -100,6 +94,12 @@ int find_arg(UAContext *ua, char *keyword)
    return -1;
 }
 
+/* 
+ * Given a single keyword, find it in the argument list, but
+ *   it must have a value
+ * Returns: -1 if not found or no value
+ *          list index (base 0) on success
+ */
 int find_arg_with_value(UAContext *ua, char *keyword)
 {
    for (int i=1; i<ua->argc; i++) {
@@ -114,8 +114,6 @@ int find_arg_with_value(UAContext *ua, char *keyword)
    return -1;
 }
 
-
-
 /* 
  * Given a list of keywords, prompt the user 
  * to choose one.
index eb5470c0f13768b76cd05ef1c838a82b33888aee..ef0832930dd07b3a8e633ac41efea983f2026d7a 100644 (file)
@@ -147,8 +147,7 @@ static void *handle_UA_client_request(void *arg)
    while (!ua->quit) {
       stat = bnet_recv(ua->UA_sock);
       if (stat >= 0) {
-        ua->cmd = check_pool_memory_size(ua->cmd, ua->UA_sock->msglen+1);
-        bstrncpy(ua->cmd, ua->UA_sock->msg, ua->UA_sock->msglen+1);
+        pm_strcpy(&ua->cmd, ua->UA_sock->msg);
         parse_ua_args(ua);
          if (ua->argc > 0 && ua->argk[0][0] == '.') {
            do_a_dot_command(ua, ua->cmd);
index da51fed3b9266702eac7d69e65d0c49591011e0b..8c6652c4410b45b08e9de5bcdefc13dd063da597 100644 (file)
@@ -90,8 +90,8 @@ static struct s_cmds cmds[] = {
 static char jobcmd[]      = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
 static char storaddr[]    = "storage address=%s port=%d ssl=%d\n";
 static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
-static char restorecmd[]  = "restore replace=%c where=%s\n";
-static char restorecmd1[] = "restore replace=%c where=\n";
+static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
+static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
 static char verifycmd[]   = "verify level=%30s\n";
 static char estimatecmd[] = "estimate listing=%d\n";
 
@@ -741,6 +741,7 @@ static int restore_cmd(JCR *jcr)
    BSOCK *dir = jcr->dir_bsock;
    BSOCK *sd = jcr->store_bsock;
    POOLMEM *where;
+   int prefix_links;
    char replace;
    char ed1[50], ed2[50];
 
@@ -752,8 +753,8 @@ static int restore_cmd(JCR *jcr)
    where = get_memory(dir->msglen+1);
    *where = 0;
 
-   if (sscanf(dir->msg, restorecmd, &replace, where) != 2) {
-      if (sscanf(dir->msg, restorecmd1, &replace) != 1) {
+   if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) {
+      if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
         pm_strcpy(&jcr->errmsg, dir->msg);
          Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
         return 0;
@@ -770,6 +771,7 @@ static int restore_cmd(JCR *jcr)
    jcr->where = bstrdup(where);
    free_pool_memory(where);
    jcr->replace = replace;
+   jcr->prefix_links = prefix_links;
 
    bnet_fsend(dir, OKrestore);
    Dmsg1(110, "bfiled>dird: %s", dir->msg);
index 0cca05390e3a22eff5c8a9cafb3eee2674738de0..7251b7f03eef1f1e34597cc4543e3a8ac17cf22c 100755 (executable)
@@ -105,14 +105,14 @@ struct s_excluded_file {
  * Definition of the find_files packet passed as the
  * first argument to the find_files callback subroutine.
  */
-typedef struct s_ff {
+struct FF_PKT {
    char *fname;                       /* filename */
    char *link;                        /* link if file linked */
    POOLMEM *sys_fname;                /* system filename */
    struct stat statp;                 /* stat packet */
-   uint32_t FileIndex;                /* FileIndex of this file */
-   uint32_t LinkFI;                   /* FileIndex of main hard linked file */
-   struct f_link *linked;             /* Set if we are hard linked */
+   int32_t FileIndex;                 /* FileIndex of this file */
+   int32_t LinkFI;                    /* FileIndex of main hard linked file */
+   struct f_link *linked;             /* Set if this file is hard linked */
    int type;                          /* FT_ type from above */
    uint32_t flags;                    /* control flags */
    int ff_errno;                      /* errno */
@@ -129,8 +129,9 @@ typedef struct s_ff {
    struct s_excluded_file *excluded_files_list;
    struct s_excluded_file *excluded_paths_list;
 
+   /* List of all hard linked files found */
    struct f_link *linklist;           /* hard linked files */
-} FF_PKT;
+};
 
 
 #include "protos.h"
index 4a66dab5c2acf17702fd90e93a89617290636b50..823e3b5a1065902927877260fd50a0d56fd1b2b3 100644 (file)
@@ -103,54 +103,54 @@ void add_fname_to_include_list(FF_PKT *ff, int prefixed, char *fname)
    if (prefixed) {
       for (p=fname; *p && *p != ' '; p++) {
         switch (*p) {
-            case 'a':                 /* alway replace */
-            case '0':                 /* no option */
-              break;
-            case 'f':
-              inc->options |= FO_MULTIFS;
-              break;
-            case 'h':                 /* no recursion */
-              inc->options |= FO_NO_RECURSION;
-              break;
-            case 'M':                 /* MD5 */
-              inc->options |= FO_MD5;
-              break;
-            case 'n':
-              inc->options |= FO_NOREPLACE;
-              break;
-            case 'p':                 /* use portable data format */
-              inc->options |= FO_PORTABLE;
-              break;
-            case 'r':                 /* read fifo */
-              inc->options |= FO_READFIFO;
-              break;
-            case 'S':
-              inc->options |= FO_SHA1;
-              break;
-            case 's':
-              inc->options |= FO_SPARSE;
-              break;
-            case 'V':                  /* verify options */
-              /* Copy Verify Options */
-               for (j=0; *p && *p != ':'; p++) {
-                 inc->VerifyOpts[j] = *p;
-                 if (j < (int)sizeof(inc->VerifyOpts) - 1) {
-                    j++;
-                 }
+         case 'a':                 /* alway replace */
+         case '0':                 /* no option */
+           break;
+         case 'f':
+           inc->options |= FO_MULTIFS;
+           break;
+         case 'h':                 /* no recursion */
+           inc->options |= FO_NO_RECURSION;
+           break;
+         case 'M':                 /* MD5 */
+           inc->options |= FO_MD5;
+           break;
+         case 'n':
+           inc->options |= FO_NOREPLACE;
+           break;
+         case 'p':                 /* use portable data format */
+           inc->options |= FO_PORTABLE;
+           break;
+         case 'r':                 /* read fifo */
+           inc->options |= FO_READFIFO;
+           break;
+         case 'S':
+           inc->options |= FO_SHA1;
+           break;
+         case 's':
+           inc->options |= FO_SPARSE;
+           break;
+         case 'V':                  /* verify options */
+           /* Copy Verify Options */
+            for (j=0; *p && *p != ':'; p++) {
+              inc->VerifyOpts[j] = *p;
+              if (j < (int)sizeof(inc->VerifyOpts) - 1) {
+                 j++;
               }
-              inc->VerifyOpts[j] = 0;
-              break;
-            case 'w':
-              inc->options |= FO_IF_NEWER;
-              break;
-            case 'Z':                 /* gzip compression */
-              inc->options |= FO_GZIP;
-               inc->level = *++p - '0';
-               Dmsg1(200, "Compression level=%d\n", inc->level);
-              break;
-           default:
-               Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *p);
-              break;
+           }
+           inc->VerifyOpts[j] = 0;
+           break;
+         case 'w':
+           inc->options |= FO_IF_NEWER;
+           break;
+         case 'Z':                 /* gzip compression */
+           inc->options |= FO_GZIP;
+            inc->level = *++p - '0';
+            Dmsg1(200, "Compression level=%d\n", inc->level);
+           break;
+        default:
+            Emsg1(M_ERROR, 0, "Unknown include/exclude option: %c\n", *p);
+           break;
         }
       }
       /* Skip past space(s) */
index 6c7c928bda3714c371b0816300bcac54d770376a..96fa5a7de8aaea215eceab016c4d363c89a31654 100644 (file)
 
  */
 
+#ifndef __MEM_POOL_H_
+#define __MEM_POOL_H_
+
+
 #ifdef SMARTALLOC
 
 #define get_pool_memory(pool) sm_get_pool_memory(__FILE__, __LINE__, pool)
@@ -68,3 +72,5 @@ extern void  print_memory_pool_stats();
 #define PM_MESSAGE 3                  /* daemon message */
 #define PM_EMSG    4                  /* error message */
 #define PM_MAX     PM_EMSG            /* Number of types */
+
+#endif
index 9b3516831eab15cdda04fad745694a18057ab605..130656d3d1601b2ad2aa5be8ddb830bac04d9778 100644 (file)
 struct JCR;
 
 /* attr.c */
-ATTR    *new_attr();
-void     free_attr(ATTR *attr);
-int      unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
-void     build_attr_output_fnames(JCR *jcr, ATTR *attr);
-void     print_ls_output(JCR *jcr, ATTR *attr);
+ATTR     *new_attr();
+void      free_attr(ATTR *attr);
+int       unpack_attributes_record(JCR *jcr, int32_t stream, char *rec, ATTR *attr);
+void      build_attr_output_fnames(JCR *jcr, ATTR *attr);
+void      print_ls_output(JCR *jcr, ATTR *attr);
 
 /* base64.c */
-void     base64_init            (void);
-int      to_base64              (intmax_t value, char *where);
-int      from_base64            (intmax_t *value, char *where);
-int      bin_to_base64          (char *buf, char *bin, int len);
+void      base64_init            (void);
+int       to_base64              (intmax_t value, char *where);
+int       from_base64            (intmax_t *value, char *where);
+int       bin_to_base64          (char *buf, char *bin, int len);
 
 /* bsys.c */
-char    *bstrncpy               (char *dest, const char *src, int maxlen);
-char    *bstrncat               (char *dest, const char *src, int maxlen);
-void    *b_malloc               (char *file, int line, size_t size);
+char     *bstrncpy               (char *dest, const char *src, int maxlen);
+char     *bstrncat               (char *dest, const char *src, int maxlen);
+void     *b_malloc               (char *file, int line, size_t size);
 #ifndef DEBUG
-void    *bmalloc                (size_t size);
+void     *bmalloc                (size_t size);
 #endif
-void    *brealloc               (void *buf, size_t size);
-void    *bcalloc                (size_t size1, size_t size2);
-int      bsnprintf              (char *str, size_t size, const  char  *format, ...);
-int      bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
-int      pool_sprintf           (char *pool_buf, char *fmt, ...);
-void     create_pid_file        (char *dir, char *progname, int port);
-int      delete_pid_file        (char *dir, char *progname, int port);
-void     drop                   (char *uid, char *gid);
-int      bmicrosleep            (time_t sec, long msec);
-char    *bfgets                 (char *s, int size, FILE *fd);
+void     *brealloc               (void *buf, size_t size);
+void     *bcalloc                (size_t size1, size_t size2);
+int       bsnprintf              (char *str, size_t size, const  char  *format, ...);
+int       bvsnprintf             (char *str, size_t size, const char  *format, va_list ap);
+int       pool_sprintf           (char *pool_buf, char *fmt, ...);
+void      create_pid_file        (char *dir, char *progname, int port);
+int       delete_pid_file        (char *dir, char *progname, int port);
+void      drop                   (char *uid, char *gid);
+int       bmicrosleep            (time_t sec, long msec);
+char     *bfgets                 (char *s, int size, FILE *fd);
 #ifndef HAVE_STRTOLL
-long long int strtoll           (const char *ptr, char **endptr, int base);
+long long int strtoll            (const char *ptr, char **endptr, int base);
 #endif
 
 /* bnet.c */
-int32_t    bnet_recv            (BSOCK *bsock);
-int       bnet_send             (BSOCK *bsock);
-int       bnet_fsend            (BSOCK *bs, char *fmt, ...);
-int       bnet_set_buffer_size  (BSOCK *bs, uint32_t size, int rw);
-int       bnet_sig              (BSOCK *bs, int sig);
-int       bnet_ssl_server       (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
-int       bnet_ssl_client       (BSOCK *bsock, char *password, int ssl_need);
-BSOCK *    bnet_connect           (JCR *jcr, int retry_interval,
-              int max_retry_time, char *name, char *host, char *service, 
-              int port, int verbose);
-void      bnet_close            (BSOCK *bsock);
-BSOCK *    init_bsock           (JCR *jcr, int sockfd, char *who, char *ip, int port);
-BSOCK *    dup_bsock            (BSOCK *bsock);
-void      term_bsock            (BSOCK *bsock);
-char *    bnet_strerror         (BSOCK *bsock);
-char *    bnet_sig_to_ascii     (BSOCK *bsock);
-int       bnet_wait_data        (BSOCK *bsock, int sec);
-int       bnet_wait_data_intr   (BSOCK *bsock, int sec);
-int       bnet_despool          (BSOCK *bsock);
-int       is_bnet_stop          (BSOCK *bsock);
-int       is_bnet_error         (BSOCK *bsock);
-void      bnet_suppress_error_messages(BSOCK *bsock, int flag);
+int32_t    bnet_recv             (BSOCK *bsock);
+int        bnet_send             (BSOCK *bsock);
+int        bnet_fsend            (BSOCK *bs, char *fmt, ...);
+int        bnet_set_buffer_size  (BSOCK *bs, uint32_t size, int rw);
+int        bnet_sig              (BSOCK *bs, int sig);
+int        bnet_ssl_server       (BSOCK *bsock, char *password, int ssl_need, int ssl_has);
+int        bnet_ssl_client       (BSOCK *bsock, char *password, int ssl_need);
+BSOCK *    bnet_connect            (JCR *jcr, int retry_interval,
+               int max_retry_time, char *name, char *host, char *service, 
+               int port, int verbose);
+void       bnet_close            (BSOCK *bsock);
+BSOCK *    init_bsock            (JCR *jcr, int sockfd, char *who, char *ip, int port);
+BSOCK *    dup_bsock             (BSOCK *bsock);
+void       term_bsock            (BSOCK *bsock);
+char *     bnet_strerror         (BSOCK *bsock);
+char *     bnet_sig_to_ascii     (BSOCK *bsock);
+int        bnet_wait_data        (BSOCK *bsock, int sec);
+int        bnet_wait_data_intr   (BSOCK *bsock, int sec);
+int        bnet_despool          (BSOCK *bsock);
+int        is_bnet_stop          (BSOCK *bsock);
+int        is_bnet_error         (BSOCK *bsock);
+void       bnet_suppress_error_messages(BSOCK *bsock, int flag);
 
 /* bget_msg.c */
-int     bget_msg(BSOCK *sock);
+int      bget_msg(BSOCK *sock);
 
 /* bpipe.c */
-BPIPE *         open_bpipe(char *prog, int wait, char *mode);
-int             close_wpipe(BPIPE *bpipe);
-int             close_bpipe(BPIPE *bpipe);
+BPIPE *          open_bpipe(char *prog, int wait, char *mode);
+int              close_wpipe(BPIPE *bpipe);
+int              close_bpipe(BPIPE *bpipe);
 
 /* cram-md5.c */
 int cram_md5_get_auth(BSOCK *bs, char *password, int ssl_need);
 int cram_md5_auth(BSOCK *bs, char *password, int ssl_need);
 void hmac_md5(uint8_t* text, int text_len, uint8_t*  key,
-             int key_len, uint8_t *hmac);
+              int key_len, uint8_t *hmac);
 
 /* crc32.c */
 
 uint32_t bcrc32(uint8_t *buf, int len);
 
 /* daemon.c */
-void    daemon_start            ();
+void     daemon_start            ();
 
 /* edit.c */
-uint64_t        str_to_uint64(char *str);
-int64_t         str_to_int64(char *str);
-char *          edit_uint64_with_commas   (uint64_t val, char *buf);
-char *          add_commas              (char *val, char *buf);
-char *          edit_uint64             (uint64_t val, char *buf);
-int             duration_to_utime       (char *str, utime_t *value);
-int             size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
-char            *edit_utime             (utime_t val, char *buf);
-int             is_a_number             (const char *num);
-int             is_an_integer           (const char *n);
+uint64_t         str_to_uint64(char *str);
+int64_t          str_to_int64(char *str);
+char *           edit_uint64_with_commas   (uint64_t val, char *buf);
+char *           add_commas              (char *val, char *buf);
+char *           edit_uint64             (uint64_t val, char *buf);
+int              duration_to_utime       (char *str, utime_t *value);
+int              size_to_uint64(char *str, int str_len, uint64_t *rtn_value);
+char             *edit_utime             (utime_t val, char *buf);
+int              is_a_number             (const char *num);
+int              is_an_integer           (const char *n);
 
 /* lex.c */
-LEX *    lex_close_file         (LEX *lf);
-LEX *    lex_open_file          (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
-int      lex_get_char           (LEX *lf);
-void     lex_unget_char         (LEX *lf);
-char *   lex_tok_to_str         (int token);
-int      lex_get_token          (LEX *lf, int expect);
+LEX *     lex_close_file         (LEX *lf);
+LEX *     lex_open_file          (LEX *lf, char *fname, LEX_ERROR_HANDLER *scan_error);
+int       lex_get_char           (LEX *lf);
+void      lex_unget_char         (LEX *lf);
+char *    lex_tok_to_str         (int token);
+int       lex_get_token          (LEX *lf, int expect);
 
 /* message.c */
-void      my_name_is            (int argc, char *argv[], char *name);
-void      init_msg              (JCR *jcr, MSGS *msg);
-void      term_msg              (void);
-void      close_msg             (JCR *jcr);
-void      add_msg_dest          (MSGS *msg, int dest, int type, char *where, char *dest_code);
-void      rem_msg_dest          (MSGS *msg, int dest, int type, char *where);
-void      Jmsg                  (JCR *jcr, int type, int level, char *fmt, ...);
-void      dispatch_message      (JCR *jcr, int type, int level, char *buf);
-void      init_console_msg      (char *wd);
-void      free_msgs_res         (MSGS *msgs);
-int       open_spool_file       (JCR *jcr, BSOCK *bs);
-int       close_spool_file      (JCR *jcr, BSOCK *bs);
+void       my_name_is            (int argc, char *argv[], char *name);
+void       init_msg              (JCR *jcr, MSGS *msg);
+void       term_msg              (void);
+void       close_msg             (JCR *jcr);
+void       add_msg_dest          (MSGS *msg, int dest, int type, char *where, char *dest_code);
+void       rem_msg_dest          (MSGS *msg, int dest, int type, char *where);
+void       Jmsg                  (JCR *jcr, int type, int level, char *fmt, ...);
+void       dispatch_message      (JCR *jcr, int type, int level, char *buf);
+void       init_console_msg      (char *wd);
+void       free_msgs_res         (MSGS *msgs);
+int        open_spool_file       (JCR *jcr, BSOCK *bs);
+int        close_spool_file      (JCR *jcr, BSOCK *bs);
 
 
 /* bnet_server.c */
-void      bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, 
-                  void *handle_client_request(void *bsock));
-void            bnet_server             (int port, void handle_client_request(BSOCK *bsock));
-int             net_connect             (int port);
-BSOCK *         bnet_bind               (int port);
-BSOCK *         bnet_accept             (BSOCK *bsock, char *who);
+void       bnet_thread_server(char *bind_addr, int port, int max_clients, workq_t *client_wq, 
+                   void *handle_client_request(void *bsock));
+void             bnet_server             (int port, void handle_client_request(BSOCK *bsock));
+int              net_connect             (int port);
+BSOCK *          bnet_bind               (int port);
+BSOCK *          bnet_accept             (BSOCK *bsock, char *who);
 
 /* signal.c */
-void            init_signals             (void terminate(int sig));
-void            init_stack_dump          (void);
+void             init_signals             (void terminate(int sig));
+void             init_stack_dump          (void);
 
 /* scan.c */
-void            strip_trailing_junk     (char *str);
-void            strip_trailing_slashes  (char *dir);
-int             skip_spaces             (char **msg);
-int             skip_nonspaces          (char **msg);
-int             fstrsch                 (char *a, char *b);
-int             parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
-                       char **argk, char **argv, int max_args);
-char           *next_arg(char **s);
+void             strip_trailing_junk     (char *str);
+void             strip_trailing_slashes  (char *dir);
+int              skip_spaces             (char **msg);
+int              skip_nonspaces          (char **msg);
+int              fstrsch                 (char *a, char *b);
+int              parse_args(POOLMEM *cmd, POOLMEM **args, int *argc, 
+                        char **argk, char **argv, int max_args);
+char            *next_arg(char **s);
 
 /* util.c */
-int             is_buf_zero             (char *buf, int len);
-void            lcase                   (char *str);
-void            bash_spaces             (char *str);
-void            unbash_spaces           (char *str);
-char *          encode_time             (time_t time, char *buf);
-char *          encode_mode             (mode_t mode, char *buf);
-int             do_shell_expansion      (char *name, int name_len);
-void            jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
-void            pm_strcat               (POOLMEM **pm, char *str);
-void            pm_strcpy               (POOLMEM **pm, char *str);
-int             run_program             (char *prog, int wait, POOLMEM *results);
-char *          job_type_to_str         (int type);
-char *          job_status_to_str       (int stat);
-char *          job_level_to_str        (int level);
-void            make_session_key        (char *key, char *seed, int mode);
-POOLMEM        *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to);  
-void            set_working_directory(char *wd);
+int              is_buf_zero             (char *buf, int len);
+void             lcase                   (char *str);
+void             bash_spaces             (char *str);
+void             unbash_spaces           (char *str);
+char *           encode_time             (time_t time, char *buf);
+char *           encode_mode             (mode_t mode, char *buf);
+int              do_shell_expansion      (char *name, int name_len);
+void             jobstatus_to_ascii      (int JobStatus, char *msg, int maxlen);
+void             pm_strcat               (POOLMEM **pm, char *str);
+void             pm_strcpy               (POOLMEM **pm, char *str);
+int              run_program             (char *prog, int wait, POOLMEM *results);
+char *           job_type_to_str         (int type);
+char *           job_status_to_str       (int stat);
+char *           job_level_to_str        (int level);
+void             make_session_key        (char *key, char *seed, int mode);
+POOLMEM         *edit_job_codes(JCR *jcr, char *omsg, char *imsg, char *to);  
+void             set_working_directory(char *wd);
 
 
 /* watchdog.c */
index 376e3fd3930cd749c8ad63af8743f2a8d795f93a..2a80ad2b181dc590922edae5b836d9b4384af752 100644 (file)
@@ -188,18 +188,15 @@ char *next_arg(char **s)
  *  argv[2] = 
  */
 
-int parse_args(POOLMEM *cmd, POOLMEM *args, int *argc, 
+int parse_args(POOLMEM *cmd, POOLMEM **args, int *argc, 
               char **argk, char **argv, int max_args) 
 {
    char *p, *q, *n;
-   int len;
 
-   len = strlen(cmd) + 1;
-   args = check_pool_memory_size(args, len);
-   bstrncpy(args, cmd, len);
-   strip_trailing_junk(args);
+   pm_strcpy(args, cmd);
+   strip_trailing_junk(*args);
+   p = *args;
    *argc = 0;
-   p = args;
    /* Pick up all arguments */
    while (*argc < max_args) {
       n = next_arg(&p);   
@@ -232,10 +229,10 @@ int parse_args(POOLMEM *cmd, POOLMEM *args, int *argc,
       }
       argv[i] = p;                   /* save ptr to value or NULL */
    }
-   return 1;
 #ifdef xxxx
-   for (i=0; i<argc; i++) {
+   for (int i=0; i < *argc; i++) {
       Dmsg3(000, "Arg %d: kw=%s val=%s\n", i, argk[i], argv[i]?argv[i]:"NULL");
    }
 #endif
+   return 1;
 }
index 9b2730f8e1fc19ea8bc8ac7b610842b27f83fc08..8195769e85dce7279594fcef4be18d4202af60ce 100644 (file)
@@ -108,7 +108,7 @@ int do_append_data(JCR *jcr)
     *  file. 1. for the Attributes, 2. for the file data if any, 
     *  and 3. for the MD5 if any.
     */
-   jcr->VolFirstIndex = 0;
+   jcr->VolFirstIndex = jcr->VolLastIndex = 0;
    jcr->run_time = time(NULL);             /* start counting time for rates */
    for (last_file_index = 0; ok && !job_canceled(jcr); ) {
 
@@ -161,10 +161,6 @@ int do_append_data(JCR *jcr)
       }
       if (file_index != last_file_index) {
         jcr->JobFiles = file_index;
-        if (jcr->VolFirstIndex == 0) {
-           jcr->VolFirstIndex = file_index;
-        }
-        jcr->VolLastIndex = file_index;
         last_file_index = file_index;
       }
       
index 8d063902ea4297ab44481f6bc871a08d4b5b9bbe..f8d5175a3279f8ea3adc39ffb2b3cf4e2e06ee3c 100644 (file)
@@ -49,7 +49,6 @@ static FF_PKT *ff = &my_ff;
 static BSR *bsr = NULL;
 static int extract = FALSE;
 static int non_support_data = 0;
-static int non_support_attr = 0;
 static long total = 0;
 static ATTR *attr;
 static char *where;
index acbb5d5e6024b436c3856f009c379f736fd7189c..9cf920f0c75fdc96b7e10a7423b7b54a7b516cf5 100644 (file)
@@ -146,6 +146,7 @@ void empty_block(DEV_BLOCK *block)
    block->read_len = 0;
    block->write_failed = false;
    block->block_read = false;
+   block->FirstIndex = block->LastIndex = 0;
 }
 
 /*
@@ -475,7 +476,7 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       return 0;
    }
 
-   /* Do housekeeping */
+   /* We successfully wrote the block, now do housekeeping */
 
    dev->VolCatInfo.VolCatBytes += block->binbuf;
    dev->VolCatInfo.VolCatBlocks++;   
@@ -493,6 +494,12 @@ int write_block_to_dev(JCR *jcr, DEVICE *dev, DEV_BLOCK *block)
       jcr->EndBlock = (uint32_t)dev->file_addr;
       jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
    }
+   if (jcr->VolFirstIndex == 0 && block->FirstIndex > 0) {
+      jcr->VolFirstIndex = block->FirstIndex;
+   }
+   if (block->LastIndex > 0) {
+      jcr->VolLastIndex = block->LastIndex;
+   }
    jcr->WroteVol = true;
 
    Dmsg2(190, "write_block: wrote block %d bytes=%d\n", dev->block_num,
@@ -635,10 +642,26 @@ reread:
    }  
 
    dev->state &= ~(ST_EOF|ST_SHORT); /* clear EOF and short block */
-   dev->block_num++;
    dev->VolCatInfo.VolCatReads++;   
    dev->VolCatInfo.VolCatRBytes += block->read_len;
 
+   dev->VolCatInfo.VolCatBytes += block->block_len;
+   dev->VolCatInfo.VolCatBlocks++;   
+   dev->file_addr += block->block_len;
+   dev->EndBlock = dev->block_num;
+   dev->EndFile  = dev->file;
+   dev->block_num++;
+   block->BlockNumber++;
+
+   /* Update jcr values */
+   if (dev->state & ST_TAPE) {
+      jcr->EndBlock = dev->EndBlock;
+      jcr->EndFile  = dev->EndFile;
+   } else {
+      jcr->EndBlock = (uint32_t)dev->file_addr;
+      jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+   }
+
    /*
     * If we read a short block on disk,
     * seek to beginning of next block. This saves us
index 1f762415249f3311bd23732316703b7dcb668bc4..2972bded93d8ebed176adffaf44ba7ec4629a963 100644 (file)
@@ -99,6 +99,8 @@ struct DEV_BLOCK {
    int      BlockVer;                 /* block version 1 or 2 */
    bool     write_failed;             /* set if write failed */
    bool     block_read;               /* set when block read */
+   int32_t  FirstIndex;               /* first index this block */
+   int32_t  LastIndex;                /* last index this block */
    char    *bufp;                     /* pointer into buffer */
    POOLMEM *buf;                      /* actual data buffer */
 };
index 5197c4538c2558f666deba7d8ca77a34e5a782be..fac6ec09200d895c9044852265c05ae948a116d5 100644 (file)
@@ -337,8 +337,8 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       case VOL_LABEL:
         unser_volume_label(dev, rec);
         /* Check Pool info */
-        strcpy(pr.Name, dev->VolHdr.PoolName);
-        strcpy(pr.PoolType, dev->VolHdr.PoolType);
+        bstrncpy(pr.Name, dev->VolHdr.PoolName, sizeof(pr.Name));
+        bstrncpy(pr.PoolType, dev->VolHdr.PoolType, sizeof(pr.PoolType));
         if (db_get_pool_record(bjcr, db, &pr)) {
            if (verbose) {
                Pmsg1(000, _("Pool record for %s found in DB.\n"), pr.Name);
@@ -360,7 +360,7 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
 
         /* Check Media Info */
         memset(&mr, 0, sizeof(mr));
-        strcpy(mr.VolumeName, dev->VolHdr.VolName);
+        bstrncpy(mr.VolumeName, dev->VolHdr.VolName, sizeof(mr.VolumeName));
         mr.PoolId = pr.PoolId;
         if (db_get_media_record(bjcr, db, &mr)) {
            if (verbose) {
@@ -374,7 +374,7 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
                Pmsg1(000, _("VOL_LABEL: Media record not found for Volume: %s\n"),
                  mr.VolumeName);
            }
-           strcpy(mr.MediaType, dev->VolHdr.MediaType);
+           bstrncpy(mr.MediaType, dev->VolHdr.MediaType, sizeof(mr.MediaType));
            create_media_record(db, &mr, &dev->VolHdr);
         }
         if (strcmp(mr.MediaType, dev->VolHdr.MediaType) != 0) {
@@ -534,6 +534,19 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       return;
    }
 
+   mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
+   if (!mjcr) {
+      if (mr.VolJobs > 0) {
+         Pmsg2(000, _("Could not find Job for SessId=%d SessTime=%d record.\n"),
+                     rec->VolSessionId, rec->VolSessionTime);
+      } else {
+        ignored_msgs++;
+      }
+      return;
+   }
+   if (mjcr->VolFirstIndex == 0) {
+      mjcr->VolFirstIndex = block->FirstIndex;
+   }
 
    /* File Attributes stream */
    switch (rec->Stream) {
@@ -554,16 +567,6 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
         build_attr_output_fnames(bjcr, attr);
         print_ls_output(bjcr, attr);
       }
-      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-      if (!mjcr) {
-        if (mr.VolJobs > 0) {
-            Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Attributes record.\n"),
-                        rec->VolSessionId, rec->VolSessionTime);
-        } else {
-           ignored_msgs++;
-        }
-        return;
-      }
       fr.JobId = mjcr->JobId;
       fr.FileId = 0;
       if (db_get_file_attributes_record(bjcr, db, attr->fname, &fr)) {
@@ -581,16 +584,6 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
    case STREAM_WIN32_DATA:
    case STREAM_FILE_DATA:
    case STREAM_SPARSE_DATA:
-      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-      if (!mjcr) {
-        if (mr.VolJobs > 0) {
-            Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for File Data record.\n"),
-                        rec->VolSessionId, rec->VolSessionTime);
-        } else {
-           ignored_msgs++;
-        }
-        return;
-      }
       mjcr->JobBytes += rec->data_len;
       if (rec->Stream == STREAM_SPARSE_DATA) {
         mjcr->JobBytes -= sizeof(uint64_t);
@@ -600,47 +593,17 @@ static void record_cb(JCR *bjcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *rec)
       break;
 
    case STREAM_GZIP_DATA:
-      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-      if (!mjcr) {
-        if (mr.VolJobs > 0) {
-            Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for GZIP Data record.\n"),
-                        rec->VolSessionId, rec->VolSessionTime);
-        } else {
-           ignored_msgs++;
-        }
-        return;
-      }
       mjcr->JobBytes += rec->data_len; /* No correct, we should expand it */
       free_jcr(mjcr);                /* done using JCR */
       break;
 
    case STREAM_SPARSE_GZIP_DATA:
-      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-      if (!mjcr) {
-        if (mr.VolJobs > 0) {
-            Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Sparse GZIP Data record.\n"),
-                        rec->VolSessionId, rec->VolSessionTime);
-        } else {
-           ignored_msgs++;
-        }
-        return;
-      }
       mjcr->JobBytes += rec->data_len - sizeof(uint64_t); /* No correct, we should expand it */
       free_jcr(mjcr);                /* done using JCR */
       break;
 
    /* Win32 GZIP stream */
    case STREAM_WIN32_GZIP_DATA:
-      mjcr = get_jcr_by_session(rec->VolSessionId, rec->VolSessionTime);
-      if (!mjcr) {
-        if (mr.VolJobs > 0) {
-            Pmsg2(000, _("Could not find Job SessId=%d SessTime=%d for Win32 GZIP Data record.\n"),
-                        rec->VolSessionId, rec->VolSessionTime);
-        } else {
-           ignored_msgs++;
-        }
-        return;
-      }
       mjcr->JobBytes += rec->data_len;
       free_jcr(mjcr);                /* done using JCR */
       break;
index 739e8d8447223831bf53f11f36f11db2c35cd66c..1912d1571e0d22567df59229032f3b263f882513 100644 (file)
@@ -441,7 +441,6 @@ int write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *Poo
 void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
 {
    ser_declare;
-   struct date_time dt;
 
    rec->sync          = 1;         /* wait for completion */
    rec->VolSessionId   = jcr->VolSessionId;
@@ -455,15 +454,9 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
 
    ser_uint32(jcr->JobId);
 
-   if (BaculaTapeVersion >= 11) {
-      ser_btime(get_current_btime());
-      ser_float64(0);
-   } else {
-      /* OLD WAY DEPRECATED */
-      get_current_time(&dt);
-      ser_float64(dt.julian_day_number);
-      ser_float64(dt.julian_day_fraction);
-   }
+   /* Changed in VerNum 11 */
+   ser_btime(get_current_btime());
+   ser_float64(0);
 
    ser_string(jcr->pool_name);
    ser_string(jcr->pool_type);
@@ -475,9 +468,8 @@ void create_session_label(JCR *jcr, DEV_RECORD *rec, int label)
    ser_string(jcr->fileset_name);
    ser_uint32(jcr->JobType);
    ser_uint32(jcr->JobLevel);
-   if (BaculaTapeVersion >= 11) {
-      ser_string(jcr->fileset_md5);
-   }
+   /* Added in VerNum 11 */
+   ser_string(jcr->fileset_md5);
 
    if (label == EOS_LABEL) {
       ser_uint32(jcr->JobFiles);
@@ -507,27 +499,27 @@ int write_session_label(JCR *jcr, DEV_BLOCK *block, int label)
    rec = new_record();
    Dmsg1(90, "session_label record=%x\n", rec);
    switch (label) {
-      case SOS_LABEL:
-        if (dev->state & ST_TAPE) {
-           jcr->StartBlock = dev->block_num;
-           jcr->StartFile  = dev->file;
-        } else {
-           jcr->StartBlock = (uint32_t)dev->file_addr;
-           jcr->StartFile = (uint32_t)(dev->file_addr >> 32);
-        }
-        break;
-      case EOS_LABEL:
-        if (dev->state & ST_TAPE) {
-           jcr->EndBlock = dev->EndBlock;
-           jcr->EndFile  = dev->EndFile;
-        } else {
-           jcr->EndBlock = (uint32_t)dev->file_addr;
-           jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
-        }
-        break;
-      default:
-         Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label);
-        break;
+   case SOS_LABEL:
+      if (dev->state & ST_TAPE) {
+        jcr->StartBlock = dev->block_num;
+        jcr->StartFile  = dev->file;
+      } else {
+        jcr->StartBlock = (uint32_t)dev->file_addr;
+        jcr->StartFile = (uint32_t)(dev->file_addr >> 32);
+      }
+      break;
+   case EOS_LABEL:
+      if (dev->state & ST_TAPE) {
+        jcr->EndBlock = dev->EndBlock;
+        jcr->EndFile  = dev->EndFile;
+      } else {
+        jcr->EndBlock = (uint32_t)dev->file_addr;
+        jcr->EndFile = (uint32_t)(dev->file_addr >> 32);
+      }
+      break;
+   default:
+      Jmsg1(jcr, M_ABORT, 0, _("Bad session label = %d\n"), label);
+      break;
    }
    create_session_label(jcr, rec, label);
    rec->FileIndex = label;
index c747ef5fc55163edcc5d6433c39c648b38186f85..816c830e45110cb03c06be31caa53866563b1545 100644 (file)
@@ -95,7 +95,6 @@ mount_next_vol:
 
    dev->state &= ~(ST_APPEND|ST_READ|ST_EOT|ST_WEOT|ST_EOF);
 
-   jcr->VolFirstIndex = jcr->JobFiles; /* first update of Vol FileIndex */
    for ( ;; ) {
       int vol_label_status;
       autochanger = autoload_device(jcr, dev, 1, NULL);
index e560ad03853439a4e4b3439dc16529439c7a6cbf..efe66fa51a4ef9a0c5a9510f69a67afc1550b99b 100644 (file)
@@ -211,8 +211,8 @@ rem=%d remainder=%d\n",
       if (remlen >= WRITE_RECHDR_LENGTH) {
         ser_begin(block->bufp, WRITE_RECHDR_LENGTH);
         if (BLOCK_VER == 1) {
-        ser_uint32(rec->VolSessionId);
-        ser_uint32(rec->VolSessionTime);
+           ser_uint32(rec->VolSessionId);
+           ser_uint32(rec->VolSessionTime);
         } else {
            block->VolSessionId = rec->VolSessionId;
            block->VolSessionTime = rec->VolSessionTime;
@@ -225,6 +225,13 @@ rem=%d remainder=%d\n",
         block->binbuf += WRITE_RECHDR_LENGTH;
         remlen -= WRITE_RECHDR_LENGTH;
         rec->remainder = rec->data_len;
+        if (rec->FileIndex > 0) {
+           /* If data record, update what we have in this block */
+           if (block->FirstIndex == 0) {
+              block->FirstIndex = rec->FileIndex;
+           }
+           block->LastIndex = rec->FileIndex;
+        }
       } else {
         rec->remainder = rec->data_len + WRITE_RECHDR_LENGTH;
         return 0;
@@ -247,8 +254,8 @@ rem=%d remainder=%d\n",
        */
       ser_begin(block->bufp, WRITE_RECHDR_LENGTH);
       if (BLOCK_VER == 1) {
-      ser_uint32(rec->VolSessionId);
-      ser_uint32(rec->VolSessionTime);
+        ser_uint32(rec->VolSessionId);
+        ser_uint32(rec->VolSessionTime);
       } else {
         block->VolSessionId = rec->VolSessionId;
         block->VolSessionTime = rec->VolSessionTime;
@@ -269,6 +276,13 @@ rem=%d remainder=%d\n",
       block->bufp += WRITE_RECHDR_LENGTH;
       block->binbuf += WRITE_RECHDR_LENGTH;
       remlen -= WRITE_RECHDR_LENGTH;
+      if (rec->FileIndex > 0) {
+        /* If data record, update what we have in this block */
+        if (block->FirstIndex == 0) {
+           block->FirstIndex = rec->FileIndex;
+        }
+        block->LastIndex = rec->FileIndex;
+      }
    }
    if (remlen == 0) {
       return 0;                      /* partial transfer */
@@ -393,8 +407,8 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
 
       unser_begin(block->bufp, WRITE_RECHDR_LENGTH);
       if (block->BlockVer == 1) {
-      unser_uint32(VolSessionId);
-      unser_uint32(VolSessionTime);
+        unser_uint32(VolSessionId);
+        unser_uint32(VolSessionTime);
       } else {
         VolSessionId = block->VolSessionId;
         VolSessionTime = block->VolSessionTime;
@@ -437,9 +451,15 @@ int read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec)
       rec->VolSessionId = VolSessionId;
       rec->VolSessionTime = VolSessionTime;
       rec->FileIndex = FileIndex;
+      if (FileIndex > 0) {
+        if (block->FirstIndex == 0) {
+           block->FirstIndex = FileIndex;
+        }
+        block->LastIndex = FileIndex;
+      }
 
-      Dmsg6(100, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n\
-remlen=%d data_len=%d\n",
+      Dmsg6(100, "rd_rec_blk() got FI=%s SessId=%d Strm=%s len=%u\n"
+                 "remlen=%d data_len=%d\n",
         FI_to_ascii(rec->FileIndex), rec->VolSessionId, 
         stream_to_ascii(rec->Stream, rec->FileIndex), data_bytes, remlen, 
         rec->data_len);
index 5022f86d8518e62e2ed20090bcb23f03d1942d58..d0a1f839ff497ed6cdf19cf62afbff73db0227af 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.31"
 #define VSTRING "1"
-#define BDATE   "26 Jun 2003"
-#define LSMDATE "26Jun03"
+#define BDATE   "02 Jul 2003"
+#define LSMDATE "02Jul03"
 
 /* Debug flags */
 #define DEBUG 1