]> git.sur5r.net Git - bacula/bacula/commitdiff
Basic Restore bootstrap implemented -- kes25Jun02
authorKern Sibbald <kern@sibbald.com>
Tue, 25 Jun 2002 10:00:12 +0000 (10:00 +0000)
committerKern Sibbald <kern@sibbald.com>
Tue, 25 Jun 2002 10:00:12 +0000 (10:00 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@49 91ce42f0-d328-0410-95d8-f526ca767f89

31 files changed:
bacula/src/baconfig.h
bacula/src/console/console_conf.c
bacula/src/dird/dird_conf.c
bacula/src/dird/dird_conf.h
bacula/src/dird/fd_cmds.c
bacula/src/dird/job.c
bacula/src/dird/restore.c
bacula/src/dird/ua_output.c
bacula/src/dird/ua_run.c
bacula/src/filed/filed.c
bacula/src/filed/filed_conf.c
bacula/src/filed/job.c
bacula/src/jcr.h
bacula/src/lib/lex.c
bacula/src/lib/lex.h
bacula/src/lib/parse_conf.c
bacula/src/lib/parse_conf.h
bacula/src/lib/protos.h
bacula/src/stored/Makefile.in
bacula/src/stored/bextract.c
bacula/src/stored/bls.c
bacula/src/stored/bsr.h
bacula/src/stored/fd_cmds.c
bacula/src/stored/job.c
bacula/src/stored/match_bsr.c
bacula/src/stored/parse_bsr.c
bacula/src/stored/protos.h
bacula/src/stored/read.c
bacula/src/stored/stored.c
bacula/src/stored/stored_conf.c
bacula/src/version.h

index 11261ed7f70b4e72e494f85a465400cea4a05daa..4262b4a050b06bfc5230d971e32efdb3787c4d57 100644 (file)
@@ -30,8 +30,6 @@
 
 /* Bacula common configuration defines */
 
-#define DEBUG 1                       /* turn on debug code */
-
 #define TRUE  1
 #define FALSE 0
 
@@ -48,7 +46,7 @@
    jcr[0] = 0; }
 
 /* Allow printing of NULL pointers */
-#define NPRT(x) (x)?(x):"(NULL)
+#define NPRT(x) (x)?(x):"*None*
 
 #ifdef ENABLE_NLS
 #include <libintl.h>
index 202d750ae34db3d8596951527fe63ab046a9a894..f0d30810f1747d0b26978abed510c25355cd00fc 100644 (file)
@@ -243,11 +243,18 @@ void save_resource(int type, struct res_items *items, int pass)
    }
    /* Common */
    if (!error) {
-      res = (URES *) malloc(size);
+      res = (URES *)malloc(size);
       memcpy(res, &res_all, size);
-      res->res_dir.hdr.next = resources[rindex].res_head;
-      resources[rindex].res_head = (RES *)res;
-      Dmsg1(90, "dir_conf: inserting res: %s\n", res->res_dir.hdr.name);
+      if (!resources[rindex].res_head) {
+        resources[rindex].res_head = (RES *)res; /* store first entry */
+      } 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;
+         Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
+              res->res_dir.hdr.name);
+      }
    }
-
 }
index a8087e9a3568c8d6c956fa76b8018bbcc4e6b0a9..153533132771244832e24f03981268606d7db0e2 100644 (file)
@@ -170,6 +170,8 @@ static struct res_items job_items[] = {
    {"pool",     store_res,     ITEM(res_job.pool),     R_POOL, 0, 0},
    {"client",   store_res,     ITEM(res_job.client),   R_CLIENT, 0, 0},
    {"fileset",  store_res,     ITEM(res_job.fs),       R_FILESET, 0, 0},
+   {"where",    store_dir,     ITEM(res_job.RestoreWhere), 0, 0, 0},
+   {"bootstrap",store_dir,     ITEM(res_job.RestoreBootstrap), 0, 0, 0},
    {"maxruntime", store_time,  ITEM(res_job.MaxRunTime), 0, 0, 0},
    {"maxstartdelay", store_time,ITEM(res_job.MaxStartDelay), 0, 0, 0},
    {"prunejobs",   store_yesno, ITEM(res_job.PruneJobs), 1, ITEM_DEFAULT, 0},
@@ -301,6 +303,7 @@ static struct s_kw RestoreFields[] = {
    {"jobid",         'J'},            /* JobId to restore */
    {"where",         'W'},            /* root of restore */
    {"replace",       'R'},            /* replacement options */
+   {"bootstrap",     'B'},            /* bootstrap file */
    {NULL,             0}
 };
 
@@ -444,7 +447,10 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, char *fmt, ...
            dump_resource(-R_SCHEDULE, (RES *)res->res_job.schedule, sendit, sock);
         }
         if (res->res_job.RestoreWhere) {
-            sendit(sock, "  --> Where=%s\n", res->res_job.RestoreWhere);
+            sendit(sock, "  --> Where=%s\n", NPRT(res->res_job.RestoreWhere));
+        }
+        if (res->res_job.RestoreBootstrap) {
+            sendit(sock, "  --> Bootstrap=%s\n", NPRT(res->res_job.RestoreBootstrap));
         }
         if (res->res_job.storage) {
             sendit(sock, "  --> ");
@@ -670,6 +676,9 @@ void free_resource(int type)
         if (res->res_job.RestoreWhere) {
            free(res->res_job.RestoreWhere);
         }
+        if (res->res_job.RestoreBootstrap) {
+           free(res->res_job.RestoreBootstrap);
+        }
         break;
       case R_MSGS:
         if (res->res_msgs.mail_cmd)
@@ -851,12 +860,18 @@ void save_resource(int type, struct res_items *items, int pass)
    if (!error) {
       res = (URES *)malloc(size);
       memcpy(res, &res_all, size);
-      res->res_dir.hdr.next = resources[rindex].res_head;
-      resources[rindex].res_head = (RES *)res;
-      Dmsg2(90, "dir_conf: inserting %s res: %s\n", res_to_str(type),
-        res->res_dir.hdr.name);
+      if (!resources[rindex].res_head) {
+        resources[rindex].res_head = (RES *)res; /* store first entry */
+      } 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;
+         Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
+              res->res_dir.hdr.name);
+      }
    }
-
 }
 
 /* 
@@ -996,7 +1011,7 @@ static void store_backup(LEX *lc, struct res_items *item, int index, int pass)
 /* 
  * Store restore info for Job record 
  *
- *    Restore = JobId=<job-id> Where=<root-directory> Replace=<options>
+ *    Restore = JobId=<job-id> Where=<root-directory> Replace=<options> Bootstrap=<file>
  *
  */
 static void store_restore(LEX *lc, struct res_items *item, int index, int pass)
@@ -1027,6 +1042,15 @@ static void store_restore(LEX *lc, struct res_items *item, int index, int pass)
            token = lex_get_token(lc, T_ALL);
             Dmsg1(190, "Restore value=%s\n", lc->str);
            switch (RestoreFields[i].token) {
+               case 'B':
+                 /* 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;
                case 'C':
                  /* Find Client Resource */
                  if (pass == 2) {
index 94a1e05038915c46125f5cc2ff8e6bf7bba944ce..862e7c35793712ac027d53af951f1500079a8c71 100644 (file)
@@ -154,6 +154,7 @@ struct s_res_job {
    int  level;                       /* default backup/verify level */
    int  RestoreJobId;                /* What -- JobId to restore */
    char *RestoreWhere;               /* Where on disk to restore -- directory */
+   char *RestoreBootstrap;           /* Bootstrap file */
    int  RestoreOptions;              /* How (overwrite, ..) */
    btime_t MaxRunTime;               /* max run time in seconds */
    btime_t MaxStartDelay;            /* max start delay in seconds */
index 08e4f1147b41c5153d780b11b6e86d21700b7fff..85f990c2afcb0ca326e16e06a2e83ae2accb5114 100644 (file)
@@ -125,6 +125,7 @@ int send_include_list(JCR *jcr)
       Dmsg1(20, "dird>filed: include file: %s\n", fileset->include_array[i]);
       fd->msg = fileset->include_array[i];
       if (!bnet_send(fd)) {
+        fd->msg = msgsave;
          Emsg0(M_FATAL, 0, _(">filed: write error on socket\n"));
         jcr->JobStatus = JS_ErrorTerminated;
         return 0;
index fbb76047e92aed6e2a3fcfed81323d45cf0a20e0..e2ce5d29068b491ff2a97eadc119073ff253e085 100644 (file)
@@ -307,6 +307,9 @@ void dird_free_jcr(JCR *jcr)
    if (jcr->RestoreWhere) {
       free(jcr->RestoreWhere);
    }
+   if (jcr->RestoreBootstrap) {
+      free(jcr->RestoreBootstrap);
+   }
    Dmsg0(200, "End dird free_jcr\n");
 }
 
@@ -333,6 +336,13 @@ void set_jcr_defaults(JCR *jcr, JOB *job)
    jcr->catalog = job->client->catalog;
    jcr->fileset = job->fs;
    jcr->msgs = job->messages; 
+   if (jcr->RestoreBootstrap) {
+      free(jcr->RestoreBootstrap);
+   }
+   /* This can be overridden by Console program */
+   if (job->RestoreBootstrap) {
+      jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
+   }
    /* If no default level given, set one */
    if (jcr->JobLevel == 0) {
       switch (jcr->JobType) {
index f92efb0e2da0f0155c33f046ef7ecaa25ce6d4f9..bd510d8e0eedf53819de4bcc1340885d2dc6236d 100644 (file)
@@ -52,9 +52,11 @@ static char sessioncmd[]   = "session %s %ld %ld %ld %ld %ld %ld\n";
 static char OKrestore[]   = "2000 OK restore\n";
 static char OKstore[]     = "2000 OK storage\n";
 static char OKsession[]   = "2000 OK session\n";
+static char OKbootstrap[] = "2000 OK bootstrap\n";
 
 /* Forward referenced functions */
 static void restore_cleanup(JCR *jcr, int status);
+static int send_bootstrap_file(JCR *jcr);
 
 /* External functions */
 
@@ -89,37 +91,39 @@ int do_restore(JCR *jcr)
 
    Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
 
-   /*
-    * Find Job Record for Files to be restored
-    */
-   if (jcr->RestoreJobId != 0) {
-      rjr.JobId = jcr->RestoreJobId;    /* specified by UA */
-   } else {
-      rjr.JobId = jcr->job->RestoreJobId; /* specified by Job Resource */
-   }
-   if (!db_get_job_record(jcr->db, &rjr)) {
-      Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId,
-        db_strerror(jcr->db));
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return 0;
-   }
-   Dmsg3(20, "Got JobId=%d VolSessId=%ld, VolSesTime=%ld\n", 
-            rjr.JobId, rjr.VolSessionId, rjr.VolSessionTime);
-   Dmsg4(20, "StartFile=%ld, EndFile=%ld StartBlock=%ld EndBlock=%ld\n", 
-            rjr.StartFile, rjr.EndFile, rjr.StartBlock, rjr.EndBlock);
-
-   /*
-    * Now find the Volumes we will need for the Restore
+   /* 
+    * The following code is kept temporarily for compatibility.
+    * It is the predecessor to the Bootstrap file.
     */
-   jcr->VolumeName[0] = 0;
-   if (!db_get_job_volume_names(jcr->db, rjr.JobId, jcr->VolumeName) ||
-       jcr->VolumeName[0] == 0) {
-      Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume Name for restore Job %d. %s"), 
-        rjr.JobId, db_strerror(jcr->db));
-      restore_cleanup(jcr, JS_ErrorTerminated);
-      return 0;
+   if (!jcr->RestoreBootstrap) {
+      /*
+       * Find Job Record for Files to be restored
+       */
+      if (jcr->RestoreJobId != 0) {
+        rjr.JobId = jcr->RestoreJobId;     /* specified by UA */
+      } else {
+        rjr.JobId = jcr->job->RestoreJobId; /* specified by Job Resource */
+      }
+      if (!db_get_job_record(jcr->db, &rjr)) {
+         Jmsg2(jcr, M_FATAL, 0, _("Cannot get job record id=%d %s"), rjr.JobId,
+           db_strerror(jcr->db));
+        restore_cleanup(jcr, JS_ErrorTerminated);
+        return 0;
+      }
+
+      /*
+       * Now find the Volumes we will need for the Restore
+       */
+      jcr->VolumeName[0] = 0;
+      if (!db_get_job_volume_names(jcr->db, rjr.JobId, jcr->VolumeName) ||
+          jcr->VolumeName[0] == 0) {
+         Jmsg(jcr, M_FATAL, 0, _("Cannot find Volume Name for restore Job %d. %s"), 
+           rjr.JobId, db_strerror(jcr->db));
+        restore_cleanup(jcr, JS_ErrorTerminated);
+        return 0;
+      }
+      Dmsg1(20, "Got job Volume Names: %s\n", jcr->VolumeName);
    }
-   Dmsg1(20, "Got job Volume Names: %s\n", jcr->VolumeName);
       
 
    /* Print Job Start message */
@@ -180,6 +184,7 @@ int do_restore(JCR *jcr)
       return 0;
    }
 
+
    /* 
     * send Storage daemon address to the File daemon,
     *  then wait for File daemon to make connection
@@ -197,26 +202,39 @@ int do_restore(JCR *jcr)
    }
    jcr->JobStatus = JS_Running;
 
-   /*
-    * Pass the VolSessionId, VolSessionTime, Start and
-    * end File and Blocks on the session command.
+   /* 
+    * Send the bootstrap file -- what Volumes/files to restore
     */
-   bnet_fsend(fd, sessioncmd, 
-            jcr->VolumeName,
-            rjr.VolSessionId, rjr.VolSessionTime, 
-            rjr.StartFile, rjr.EndFile, rjr.StartBlock, 
-            rjr.EndBlock);
-   if (!response(fd, OKsession, "Session")) {
+   if (!send_bootstrap_file(jcr)) {
       restore_cleanup(jcr, JS_ErrorTerminated);
       return 0;
    }
 
+   /* 
+    * The following code is deprecated  
+    */
+   if (!jcr->RestoreBootstrap) {
+      /*
+       * Pass the VolSessionId, VolSessionTime, Start and
+       * end File and Blocks on the session command.
+       */
+      bnet_fsend(fd, sessioncmd, 
+               jcr->VolumeName,
+               rjr.VolSessionId, rjr.VolSessionTime, 
+               rjr.StartFile, rjr.EndFile, rjr.StartBlock, 
+               rjr.EndBlock);
+      if (!response(fd, OKsession, "Session")) {
+        restore_cleanup(jcr, JS_ErrorTerminated);
+        return 0;
+      }
+   }
+
    /* Send restore command */
    if (jcr->RestoreWhere) {
       bnet_fsend(fd, restorecmd, jcr->RestoreWhere);
    } else {
-      bnet_fsend(fd, restorecmd,                              
-         jcr->job->RestoreWhere==NULL ? "" : jcr->job->RestoreWhere);
+      bnet_fsend(fd, restorecmd, 
+                 jcr->job->RestoreWhere ? jcr->job->RestoreWhere : "");
    }
    if (!response(fd, OKrestore, "Restore")) {
       restore_cleanup(jcr, JS_ErrorTerminated);
@@ -224,7 +242,7 @@ int do_restore(JCR *jcr)
    }
 
    /* Wait for Job Termination */
-   /*** ****FIXME**** get job termination data */
+   /*** ****FIXME**** get job termination status */
    Dmsg0(20, "wait for job termination\n");
    while (bget_msg(fd, 0) >  0) {
       Dmsg1(0, "dird<filed: %s\n", fd->msg);
@@ -254,3 +272,37 @@ static void restore_cleanup(JCR *jcr, int status)
 
    Dmsg0(20, "Leaving restore_cleanup\n");
 }
+
+static int send_bootstrap_file(JCR *jcr)
+{
+   FILE *bs;
+   char buf[1000];
+   BSOCK *fd = jcr->file_bsock;
+   char *bootstrap = "bootstrap\n";
+
+   Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
+   if (!jcr->RestoreBootstrap) {
+      return 1;
+   }
+   bs = fopen(jcr->RestoreBootstrap, "r");
+   if (!bs) {
+      Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), 
+        jcr->RestoreBootstrap, strerror(errno));
+      jcr->JobStatus = JS_ErrorTerminated;
+      return 0;
+   }
+   strcpy(fd->msg, bootstrap); 
+   fd->msglen = strlen(fd->msg);
+   bnet_send(fd);
+   while (fgets(buf, sizeof(buf), bs)) {
+      fd->msglen = Mmsg(&fd->msg, "%s", buf);
+      bnet_send(fd);      
+   }
+   bnet_sig(fd, BNET_EOF);
+   fclose(bs);
+   if (!response(fd, OKbootstrap, "Bootstrap")) {
+      jcr->JobStatus = JS_ErrorTerminated;
+      return 0;
+   }
+   return 1;
+}
index 1da05280c99ef0180ab8caaa8221b6bf960fded7..494120d07a130351936fcbe91948ae19712370dc 100644 (file)
@@ -242,7 +242,7 @@ int listcmd(UAContext *ua, char *cmd)
 
         for (j=i+1; j<ua->argc; j++) {
             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
-              strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
+              strncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH);
               jr.Job[MAX_NAME_LENGTH-1] = 0;
               jr.JobId = 0;
               db_get_job_record(ua->db, &jr);
@@ -262,7 +262,7 @@ int listcmd(UAContext *ua, char *cmd)
         int done = FALSE;
         for (j=i+1; j<ua->argc; j++) {
             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
-              strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
+              strncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH);
               jr.Job[MAX_NAME_LENGTH-1] = 0;
               jr.JobId = 0;
               db_get_job_record(ua->db, &jr);
@@ -290,7 +290,7 @@ int listcmd(UAContext *ua, char *cmd)
         int done = FALSE;
         for (j=i+1; j<ua->argc; j++) {
             if (strcasecmp(ua->argk[j], _("job")) == 0 && ua->argv[j]) {
-              strncpy(jr.Job, ua->argv[i], MAX_NAME_LENGTH);
+              strncpy(jr.Job, ua->argv[j], MAX_NAME_LENGTH);
               jr.Job[MAX_NAME_LENGTH-1] = 0;
               jr.JobId = 0;
               db_get_job_record(ua->db, &jr);
@@ -315,7 +315,7 @@ int listcmd(UAContext *ua, char *cmd)
            db_list_media_records(ua->db, &mr, prtit, ua);
         }
       } else {
-         bsendmsg(ua, _("Unknown list keyword: %s\n"), ua->argk[i]);
+         bsendmsg(ua, _("Unknown list keyword: %s\n"), NPRT(ua->argk[i]));
       }
    }
    return 1;
index 913743d543f7d33db1cef2888d07847a08f22d77..be8dfc46598cfda492eb749d1c1a6eb1318b6f84 100644 (file)
@@ -50,7 +50,7 @@ int runcmd(UAContext *ua, char *cmd)
    JOB *job;
    JCR *jcr;
    char *job_name, *level_name, *jid, *store_name;
-   char *where, *fileset_name, *client_name;
+   char *where, *fileset_name, *client_name, *bootstrap;
    int i, j, found;
    STORE *store;
    CLIENT *client;
@@ -63,6 +63,7 @@ int runcmd(UAContext *ua, char *cmd)
       N_("level"),
       N_("storage"),
       N_("where"),
+      N_("bootstrap"),
       NULL};
 
    if (!open_db(ua)) {
@@ -146,6 +147,14 @@ int runcmd(UAContext *ua, char *cmd)
                  where = ua->argv[i];
                  break;
                  found = True;
+              case 7: /* bootstrap */
+                 if (bootstrap) {
+                     bsendmsg(ua, _("Bootstrap specified twice.\n"));
+                    return 1;
+                 }
+                 bootstrap = ua->argv[i];
+                 break;
+                 found = True;
               default:
                  break;
            }
@@ -205,6 +214,7 @@ int runcmd(UAContext *ua, char *cmd)
 try_again:
    Dmsg1(20, "JobType=%c\n", jcr->JobType);
    switch (jcr->JobType) {
+      char ec1[30];
       case JT_BACKUP:
       case JT_VERIFY:
         if (level_name) {
@@ -239,7 +249,7 @@ Storage:  %s\n"),
                 jcr->store->hdr.name);
         break;
       case JT_RESTORE:
-        if (jcr->RestoreJobId == 0) {
+        if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
            if (jid) {
               jcr->RestoreJobId = atoi(jid);
            } else {
@@ -250,23 +260,25 @@ Storage:  %s\n"),
               jcr->RestoreJobId = atoi(ua->cmd);
            }
         }
-         jcr->JobLevel = 'F';            /* ***FIXME*** */
+         jcr->JobLevel = 'F';         /* default level */
          Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
          bsendmsg(ua, _("Run Restore job\n\
 JobName:    %s\n\
+Bootstrap:  %s\n\
 Where:      %s\n\
-RestoreId:  %d\n\
 Level:      %s\n\
 FileSet:    %s\n\
 Client:     %s\n\
-Storage:    %s\n"),
+Storage:    %s\n\
+JobId:      %s\n"),
                 job->hdr.name,
-                jcr->RestoreWhere?jcr->RestoreWhere:job->RestoreWhere,
-                jcr->RestoreJobId,
+                NPRT(jcr->RestoreBootstrap),
+                jcr->RestoreWhere?jcr->RestoreWhere:NPRT(job->RestoreWhere),
                 level_to_str(jcr->JobLevel),
                 jcr->fileset->hdr.name,
                 jcr->client->hdr.name,
-                jcr->store->hdr.name);
+                jcr->store->hdr.name, 
+                 jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1));
         break;
       default:
          bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
@@ -278,15 +290,18 @@ Storage:    %s\n"),
       return 1;
    }
    if (strcasecmp(ua->cmd, _("mod")) == 0) {
+      FILE *fd;
+
       start_prompt(ua, _("Parameters to modify:\n"));
-      add_prompt(ua, _("Job"));
-      add_prompt(ua, _("Level"));
-      add_prompt(ua, _("FileSet"));
-      add_prompt(ua, _("Client"));
-      add_prompt(ua, _("Storage"));
+      add_prompt(ua, _("Job"));              /* 0 */
+      add_prompt(ua, _("Level"));            /* 1 */
+      add_prompt(ua, _("FileSet"));          /* 2 */
+      add_prompt(ua, _("Client"));           /* 3 */
+      add_prompt(ua, _("Storage"));          /* 4 */
       if (jcr->JobType == JT_RESTORE) {
-         add_prompt(ua, _("Where"));
-         add_prompt(ua, _("JobId"));
+         add_prompt(ua, _("Bootstrap"));     /* 5 */
+         add_prompt(ua, _("Where"));         /* 6 */
+         add_prompt(ua, _("JobId"));         /* 7 */
       }
       switch (do_prompt(ua, _("Select parameter to modify"), NULL)) {
       case 0:
@@ -375,10 +390,33 @@ Storage:    %s\n"),
         }
         break;
       case 5:
+        /* Bootstrap */
+         if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
+           break;
+        }
+        if (jcr->RestoreBootstrap) {
+           free(jcr->RestoreBootstrap);
+           jcr->RestoreBootstrap = NULL;
+        }
+        if (ua->cmd[0] != 0) {
+           jcr->RestoreBootstrap = bstrdup(ua->cmd);
+            fd = fopen(jcr->RestoreBootstrap, "r");
+           if (!fd) {
+               bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
+                 jcr->RestoreBootstrap, strerror(errno));
+              free(jcr->RestoreBootstrap);
+              jcr->RestoreBootstrap = NULL;
+           } else {
+              fclose(fd);
+           }
+        }
+        goto try_again;
+      case 6:
         /* Where */
          if (!get_cmd(ua, _("Please enter path prefix (where) for restore: "))) {
            break;
         }
+        /* ***FIXME*** allow drive:/ for Windows */
          if (ua->cmd[0] != '/') {
             bsendmsg(ua, _("Prefix must begin with a /\n"));
         } else {
@@ -388,10 +426,13 @@ Storage:    %s\n"),
            jcr->RestoreWhere = bstrdup(ua->cmd);
         }  
         goto try_again;
-      case 6:
+      case 7:
         /* JobId */
         jid = NULL;                  /* force reprompt */
         jcr->RestoreJobId = 0;
+        if (jcr->RestoreBootstrap) {
+            bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
+        }
         goto try_again;
       default: 
         goto try_again;
index 4124f8c4be01c169c1753b9781593fa59aa96ac7..bbd95ba5c8938ca6277c26df09ad7caf890bbfc7 100644 (file)
@@ -50,7 +50,8 @@ int win32_client = 0;
 static char *configfile = NULL;
 static int foreground = 0;
 static workq_t dir_workq;            /* queue of work from Director */
-static CLIENT *me;                   /* my resource */
+
+CLIENT *me;                          /* my resource */
 
 static void usage()
 {
index 315163e706016b23ad97b1f5d3996ef634707ec4..1c9c2da75990a658a03752f7d40159357fedaab5 100644 (file)
@@ -286,9 +286,16 @@ void save_resource(int type, struct res_items *items, int pass)
    if (!error) {
       res = (URES *)malloc(size);
       memcpy(res, &res_all, size);
-      res->res_dir.hdr.next = resources[rindex].res_head;
-      resources[rindex].res_head = (RES *)res;
-      Dmsg1(90, "dir_conf: inserting res: %s\n", res->res_dir.hdr.name);
+      if (!resources[rindex].res_head) {
+        resources[rindex].res_head = (RES *)res; /* store first entry */
+      } 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;
+         Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
+              res->res_dir.hdr.name);
+      }
    }
-
 }
index b797bc348187e7f0d95a27408bcc63085cec81b9..c0c704fad510b628ff89cccda50a61dab2345c1b 100644 (file)
 #include "filed.h"
 
 extern char my_name[];
+extern CLIENT *me;                   /* our client resource */
                        
 /* Imported functions */
 extern int status_cmd(JCR *jcr);
                                   
 /* Forward referenced functions */
 static int backup_cmd(JCR *jcr);
+static int bootstrap_cmd(JCR *jcr);
 static int cancel_cmd(JCR *jcr);
 static int setdebug_cmd(JCR *jcr);
 static int estimate_cmd(JCR *jcr);
@@ -51,6 +53,7 @@ static int session_cmd(JCR *jcr);
 static int response(BSOCK *sd, char *resp, char *cmd);
 static void filed_free_jcr(JCR *jcr);
 static int open_sd_read_session(JCR *jcr);
+static int send_bootstrap_file(JCR *jcr);
 
 
 /* Exported functions */
@@ -78,6 +81,7 @@ static struct s_cmds cmds[] = {
    {"status",   status_cmd},
    {"storage ", storage_cmd},
    {"verify",   verify_cmd},
+   {"bootstrap",bootstrap_cmd},
    {NULL,      NULL}                  /* list terminator */
 };
 
@@ -96,6 +100,7 @@ static char OKest[]        = "2000 OK estimate files=%ld bytes=%ld\n";
 static char OKexc[]        = "2000 OK exclude\n";
 static char OKlevel[]      = "2000 OK level\n";
 static char OKbackup[]     = "2000 OK backup\n";
+static char OKbootstrap[]  = "2000 OK bootstrap\n";
 static char OKverify[]     = "2000 OK verify\n";
 static char OKrestore[]    = "2000 OK restore\n";
 static char OKsession[]    = "2000 OK session\n";
@@ -109,6 +114,7 @@ static char OK_end[]       = "3000 OK end\n";
 static char OK_open[]      = "3000 OK open ticket = %d\n";
 static char OK_data[]      = "3000 OK data\n";
 static char OK_append[]    = "3000 OK append data\n";
+static char OKSDbootstrap[] = "3000 OK bootstrap\n";
 
 
 /* Commands sent to Storage Daemon */
@@ -141,7 +147,7 @@ void *handle_client_request(void *dirp)
 {
    int i, found, quit;
    JCR *jcr;
-   BSOCK *dir = (BSOCK *) dirp;
+   BSOCK *dir = (BSOCK *)dirp;
 
    jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
    jcr->dir_bsock = dir;
@@ -262,9 +268,9 @@ static int estimate_cmd(JCR *jcr)
 static int job_cmd(JCR *jcr)
 {
    BSOCK *dir = jcr->dir_bsock;
-   char *sd_auth_key;
+   POOLMEM *sd_auth_key;
 
-   sd_auth_key = (char *) get_memory(dir->msglen);
+   sd_auth_key = get_memory(dir->msglen);
    if (sscanf(dir->msg, jobcmd,  &jcr->JobId, jcr->Job,  
              &jcr->VolSessionId, &jcr->VolSessionTime,
              sd_auth_key) != 5) {
@@ -323,6 +329,40 @@ static int exclude_cmd(JCR *jcr)
    return bnet_fsend(dir, OKexc);
 }
 
+
+static int bootstrap_cmd(JCR *jcr)
+{
+   BSOCK *dir = jcr->dir_bsock;
+   POOLMEM *fname = get_pool_memory(PM_FNAME);
+   FILE *bs;
+
+   if (jcr->RestoreBootstrap) {
+      unlink(jcr->RestoreBootstrap);
+      free_pool_memory(jcr->RestoreBootstrap);
+   }
+   Mmsg(&fname, "%s/%s.%s.bootstrap", me->working_directory, me->hdr.name,
+      jcr->Job);
+   Dmsg1(400, "bootstrap=%s\n", fname);
+   jcr->RestoreBootstrap = fname;
+   bs = fopen(fname, "a+");           /* create file */
+   if (!bs) {
+      Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
+        jcr->RestoreBootstrap, strerror(errno));
+      free_pool_memory(jcr->RestoreBootstrap);
+      jcr->RestoreBootstrap = NULL;
+      return 0;
+   }
+
+   while (bnet_recv(dir) > 0) {
+       Dmsg1(200, "filed<dird: bootstrap file %s\n", dir->msg);
+       fputs(dir->msg, bs);
+   }
+   fclose(bs);
+
+   return bnet_fsend(dir, OKbootstrap);
+}
+
+
 /*
  * Get backup level from Director
  *
@@ -670,6 +710,10 @@ static int open_sd_read_session(JCR *jcr)
       return 0;
    }
 
+   if (!send_bootstrap_file(jcr)) {
+      return 0;
+   }
+
    /* 
     * Start read of data with Storage daemon
     */
@@ -697,6 +741,10 @@ static void filed_free_jcr(JCR *jcr)
    if (jcr->where) {
       free_pool_memory(jcr->where);
    }
+   if (jcr->RestoreBootstrap) {
+      unlink(jcr->RestoreBootstrap);
+      free_pool_memory(jcr->RestoreBootstrap);
+   }
    if (jcr->last_fname) {
       free_pool_memory(jcr->last_fname);
    }
@@ -733,3 +781,37 @@ int response(BSOCK *sd, char *resp, char *cmd)
    }
    return 0;
 }
+
+static int send_bootstrap_file(JCR *jcr)
+{
+   FILE *bs;
+   char buf[1000];
+   BSOCK *sd = jcr->store_bsock;
+   char *bootstrap = "bootstrap\n";
+
+   Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
+   if (!jcr->RestoreBootstrap) {
+      return 1;
+   }
+   bs = fopen(jcr->RestoreBootstrap, "r");
+   if (!bs) {
+      Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"), 
+        jcr->RestoreBootstrap, strerror(errno));
+      jcr->JobStatus = JS_ErrorTerminated;
+      return 0;
+   }
+   strcpy(sd->msg, bootstrap); 
+   sd->msglen = strlen(sd->msg);
+   bnet_send(sd);
+   while (fgets(buf, sizeof(buf), bs)) {
+      sd->msglen = Mmsg(&sd->msg, "%s", buf);
+      bnet_send(sd);      
+   }
+   bnet_sig(sd, BNET_EOF);
+   fclose(bs);
+   if (!response(sd, OKSDbootstrap, "Bootstrap")) {
+      jcr->JobStatus = JS_ErrorTerminated;
+      return 0;
+   }
+   return 1;
+}
index 3b7139621dc70aa5000f9742ce542e364a4f17cb..d88b54df1e80dcde98afce071b82e8fe553a3410 100644 (file)
@@ -103,6 +103,7 @@ struct s_jcr {
    time_t end_time;                   /* job end time */
    POOLMEM *VolumeName;               /* Volume name desired -- pool_memory */
    POOLMEM *client_name;              /* client name */
+   char *RestoreBootstrap;            /* Bootstrap file to restore */
    char *sd_auth_key;                 /* SD auth key */
    MSGS *msgs;                        /* Message resource */
 
@@ -151,7 +152,7 @@ struct s_jcr {
    char *big_buf;                     /* I/O buffer */
    POOLMEM *compress_buf;             /* Compression buffer */
    int32_t compress_buf_size;         /* Length of compression buffer */
-   char *where;                       /* Root where to restore */
+   POOLMEM *where;                    /* Root where to restore */
    int buf_size;                      /* length of buffer */
    FF_PKT *ff;                        /* Find Files packet */
    char stored_addr[MAX_NAME_LENGTH]; /* storage daemon address */
@@ -167,12 +168,13 @@ struct s_jcr {
    int type;
    DEVRES *device;                    /* device to use */
    VOLUME_CAT_INFO VolCatInfo;        /* Catalog info for desired volume */
-   POOLMEM *job_name;                    /* base Job name (not unique) */
-   POOLMEM *fileset_name;                /* FileSet */
-   POOLMEM *pool_name;                   /* pool to use */
-   POOLMEM *pool_type;                   /* pool type to use */
-   POOLMEM *media_type;                  /* media type */
-   POOLMEM *dev_name;                    /* device name */
+   POOLMEM *job_name;                 /* base Job name (not unique) */
+   POOLMEM *fileset_name;             /* FileSet */
+   POOLMEM *pool_name;                /* pool to use */
+   POOLMEM *pool_type;                /* pool type to use */
+   POOLMEM *media_type;               /* media type */
+   POOLMEM *dev_name;                 /* device name */
+   VOL_LIST *VolList;                 /* list to read */
    long NumVolumes;                   /* number of volumes used */
    long CurVolume;                    /* current volume number */
    int mode;                          /* manual/auto run */
index 322181ad4e34329891211b244f498322c00d7f15..ce92ce3c0c3c3451156d276aef47f1a8556ee95e 100644 (file)
@@ -47,7 +47,7 @@ void scan_to_eol(LEX *lc)
 /*
  * Format a scanner error message 
  */
-void s_err(char *file, int line, LEX *lc, char *msg, ...)
+static void s_err(char *file, int line, LEX *lc, char *msg, ...)
 {
    va_list arg_ptr;
    char buf[MAXSTRING];
@@ -103,7 +103,8 @@ lex_close_file(LEX *lf)
  *
  */
 LEX *
-lex_open_file(LEX *lf, char *filename) 
+lex_open_file(LEX *lf, char *filename, LEX_ERROR_HANDLER *scan_error) 
+             
 {
    LEX *nf;
    FILE *fd;
@@ -128,6 +129,11 @@ lex_open_file(LEX *lf, char *filename)
    lf->fname = fname;
    lf->state = lex_none;
    lf->ch = L_EOL;
+   if (scan_error) {
+      lf->scan_error = scan_error;
+   } else {
+      lf->scan_error = s_err;
+   }
    Dmsg1(29, "Return lex=%x\n", lf);
    return lf;
 }
@@ -421,7 +427,7 @@ lex_get_token(LEX *lf, int expect)
             if (ISSPACE(ch) || ch == '\n' || ch == L_EOL || ch == '}' || ch == '{' ||
                 ch == ';' || ch == ','   || ch == '"' || ch == '#') {
               lf->state = lex_none;
-              lf = lex_open_file(lf, lf->str);
+              lf = lex_open_file(lf, lf->str, NULL);
               break;
            }
            add_str(lf, ch);
@@ -453,7 +459,10 @@ lex_get_token(LEX *lf, int expect)
       } else {
          char *p = strchr(lf->str, '-');
         if (!p) {
-            scan_err1(lf, "expected an integer or a range, got: %s", lf->str);
+            scan_err2(lf, "expected an integer or a range, got %s: %s", 
+              lex_tok_to_str(token), lf->str);
+           token = T_ERROR;
+           break;
         }
         *p++ = 0;                       /* terminate first half of range */
         lf->pint32_val  = scan_pint(lf, lf->str);
@@ -464,46 +473,63 @@ lex_get_token(LEX *lf, int expect)
 
    case T_INT32:
       if (token != T_NUMBER || !is_a_number(lf->str)) {
-         scan_err1(lf, "expected an integer number, got: %s", lf->str);
+         scan_err2(lf, "expected an integer number, got %s: %s",
+              lex_tok_to_str(token), lf->str);
+        token = T_ERROR;
+        break;
+      }
+      errno = 0;
+      lf->int32_val = (int32_t)strtod(lf->str, NULL);
+      if (errno != 0) {
+         scan_err2(lf, "expected an integer number, got %s: %s",
+              lex_tok_to_str(token), lf->str);
+        token = T_ERROR;
       } else {
-        errno = 0;
-        lf->int32_val = (int32_t)strtod(lf->str, NULL);
-        if (errno != 0) {
-            scan_err1(lf, "expected an integer number, got: %s", lf->str);
-        }
+        token = T_INT32;
       }
-      token = T_INT32;
       break;
 
    case T_INT64:
       Dmsg2(400, "int64=:%s: %f\n", lf->str, strtod(lf->str, NULL)); 
       if (token != T_NUMBER || !is_a_number(lf->str)) {
-         scan_err1(lf, "expected an integer number, got: %s", lf->str);
+         scan_err2(lf, "expected an integer number, got %s: %s",
+              lex_tok_to_str(token), lf->str);
+        token = T_ERROR;
+        break;
+      }
+      errno = 0;
+      lf->int64_val = (int64_t)strtod(lf->str, NULL);
+      if (errno != 0) {
+         scan_err2(lf, "expected an integer number, got %s: %s",
+              lex_tok_to_str(token), lf->str);
+        token = T_ERROR;
       } else {
-        errno = 0;
-        lf->int64_val = (int64_t)strtod(lf->str, NULL);
-        if (errno != 0) {
-            scan_err1(lf, "expected an integer number, got: %s", lf->str);
-        }
+        token = T_INT64;
       }
-      token = T_INT64;
       break;
 
    case T_NAME:
       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
-         scan_err1(lf, "expected a name: %s", lf->str);
+         scan_err2(lf, "expected a name, got %s: %s",
+              lex_tok_to_str(token), lf->str);
+        token = T_ERROR;
       } else if (lf->str_len > MAX_RES_NAME_LENGTH) {
          scan_err3(lf, "name %s length %d too long, max is %d\n", lf->str, 
            lf->str_len, MAX_RES_NAME_LENGTH);
+        token = T_ERROR;
+      } else {
+        token = T_NAME;
       }
-      token = T_NAME;
       break;
 
    case T_STRING:
       if (token != T_IDENTIFIER && token != T_UNQUOTED_STRING && token != T_QUOTED_STRING) {
-         scan_err1(lf, "expected a name: %s", lf->str);
+         scan_err2(lf, "expected a name, got %s: %s",
+              lex_tok_to_str(token), lf->str);
+        token = T_ERROR;
+      } else {
+        token = T_STRING;
       }
-      token = T_STRING;
       break;
 
 
index 795d31cbcf573291d08662faaefc4d8860c65a98..d52542ac3c2617f7ae228e3bfccc22d0708e9e50 100644 (file)
@@ -98,6 +98,20 @@ typedef struct s_lex_context {
    uint32_t pint32_val2;
    int32_t int32_val;
    int64_t int64_val;
+   void (*scan_error)(char *file, int line, struct s_lex_context *lc, char *msg, ...);
 } LEX;
 
+typedef void (LEX_ERROR_HANDLER)(char *file, int line, LEX *lc, char *msg, ...);
+
+/* Lexical scanning errors in parsing conf files */
+#define scan_err0(lc, msg) lc->scan_error(__FILE__, __LINE__, lc, msg)
+#define scan_err1(lc, msg, a1) lc->scan_error(__FILE__, __LINE__, lc, msg, a1)
+#define scan_err2(lc, msg, a1, a2) lc->scan_error(__FILE__, __LINE__, lc, msg, a1, a2)
+#define scan_err3(lc, msg, a1, a2, a3) lc->scan_error(__FILE__, __LINE__, lc, msg, a1, a2, a3)
+#define scan_err4(lc, msg, a1, a2, a3, a4) lc->scan_error(__FILE__, __LINE__, lc, msg, a1, a2, a3, a4)
+#define scan_err5(lc, msg, a1, a2, a3, a4, a5) lc->scan_error(__FILE__, __LINE__, lc, msg, a1, a2, a3, a4, a5)
+#define scan_err6(lc, msg, a1, a2, a3, a4, a5, a6) lc->scan_error(__FILE__, __LINE__, lc, msg, a1, a2, a3, a4, a5, a6)
+
+void scan_to_eol(LEX *lc);
+
 #endif /* _LEX_H */
index 03d76235da12a7d822fceb97d618f6c8d27c598b..e4d43a9747c823d23734a1acab30702b15805ee8 100755 (executable)
@@ -669,7 +669,7 @@ parse_config(char *cf)
    Dmsg0(200, "Enter parse_config()\n");
    for (pass=1; pass <= 2; pass++) {
       Dmsg1(200, "parse_config pass %d\n", pass);
-      lc = lex_open_file(lc, cf);
+      lc = lex_open_file(lc, cf, NULL);
       while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
          Dmsg1(150, "parse got token=%s\n", lex_tok_to_str(token));
         switch (state) {
index f1503b73d914d2abf54ccdbe93f121cc027b4390..a666970af828b405cd737062266336bc8849608c 100644 (file)
@@ -21,7 +21,7 @@
 
  */
 
-struct res_items;                  /* Declare forward referenced structure */ 
+struct res_items;                   /* Declare forward referenced structure */ 
 typedef void (MSG_RES_HANDLER)(LEX *lc, struct res_items *item, int index, int pass);
 
 /* This is the structure that defines
@@ -30,30 +30,30 @@ typedef void (MSG_RES_HANDLER)(LEX *lc, struct res_items *item, int index, int p
  * tables.
  */
 struct res_items {
-   char *name;                       /* Resource name i.e. Director, ... */
-   MSG_RES_HANDLER *handler;         /* Routine storing the resource item */
-   void **value;                     /* Where to store the item */
-   int code;                         /* item code/additional info */
-   int flags;                        /* flags: default, required, ... */
-   int default_value;                /* default value */
+   char *name;                        /* Resource name i.e. Director, ... */
+   MSG_RES_HANDLER *handler;          /* Routine storing the resource item */
+   void **value;                      /* Where to store the item */
+   int  code;                         /* item code/additional info */
+   int  flags;                        /* flags: default, required, ... */
+   int  default_value;                /* default value */
 };
 
 /* For storing name_addr items in res_items table */
 #define ITEM(x) ((void **)&res_all.x)
 
-#define MAX_RES_ITEMS 32             /* maximum resource items per RES */
+#define MAX_RES_ITEMS 32              /* maximum resource items per RES */
 
 /* This is the universal header that is
  * at the beginning of every resource
  * record.
  */
 struct s_reshdr {
-   char *name;                       /* resource name */
-   char *desc;                       /* resource description */
-   int  rcode;                       /* resource id or type */
-   int  refcnt;                      /* reference count for releasing */
+   struct s_reshdr *next;             /* pointer to next resource of this type */
+   char *name;                        /* resource name */
+   char *desc;                        /* resource description */
+   int   rcode;                       /* resource id or type */
+   int   refcnt;                      /* reference count for releasing */
    char  item_present[MAX_RES_ITEMS]; /* set if item is present in conf file */
-   struct s_reshdr *next;            /* pointer to next resource of this type */
 };
 
 typedef struct s_reshdr RES;
@@ -63,26 +63,26 @@ typedef struct s_reshdr RES;
  * This is the structure that defines the
  * resources that are available to this daemon.
  */
-struct s_res {      
-   char *name;                       /* resource name */
-   struct res_items *items;          /* list of resource keywords */
-   int rcode;                        /* code if needed */
-   RES *res_head;                    /* where to store it */
+struct s_res {       
+   char *name;                        /* resource name */
+   struct res_items *items;           /* list of resource keywords */
+   int rcode;                         /* code if needed */
+   RES *res_head;                     /* where to store it */
 };
 
 /* Common Resource definitions */
 
-#define MAX_RES_NAME_LENGTH MAX_NAME_LENGTH-1      /* maximum resource name length */
+#define MAX_RES_NAME_LENGTH MAX_NAME_LENGTH-1       /* maximum resource name length */
 
-#define ITEM_REQUIRED 0x1            /* item required */
-#define ITEM_DEFAULT  0x2            /* default supplied */
+#define ITEM_REQUIRED 0x1             /* item required */
+#define ITEM_DEFAULT  0x2             /* default supplied */
 
 /* Message Resource */
 struct s_res_msgs {
-   RES  hdr;
-   char *mail_cmd;                   /* mail command */
-   char *operator_cmd;               /* Operator command */
-   DEST *dest_chain;                 /* chain of destinations */
+   RES   hdr;
+   char *mail_cmd;                    /* mail command */
+   char *operator_cmd;                /* Operator command */
+   DEST *dest_chain;                  /* chain of destinations */
    char send_msg[nbytes_for_bits(M_MAX+1)];  /* bit array of types */
 };
 typedef struct s_res_msgs MSGS;
@@ -92,7 +92,7 @@ typedef struct s_res_msgs MSGS;
  * resource structure definitions.
  */
 union cu_res {
-   struct s_res_msgs   res_msgs;
+   struct s_res_msgs    res_msgs;
    RES hdr;
 };
 
@@ -100,8 +100,8 @@ typedef union cu_res CURES;
 
 
 /* Configuration routines */
-void  parse_config           __PROTO((char *cf));
-void  free_config_resources   __PROTO(());
+void  parse_config(char *cf);
+void  free_config_resources(void);
 
 /* Resource routines */
 RES *GetResWithName(int rcode, char *name);
@@ -112,10 +112,6 @@ void dump_resource(int type, RES *res, void sendmsg(void *sock, char *fmt, ...),
 void free_resource(int type);
 void init_resource(int type, struct res_items *item);
 void save_resource(int type, struct res_items *item, int pass);
-
-
-void scan_error(LEX *lc, char *msg, ...);  /* old way, do not use */
-void scan_to_eol(LEX *lc);
 char *res_to_str(int rcode);
 
 void store_str(LEX *lc, struct res_items *item, int index, int pass);
@@ -131,14 +127,3 @@ void store_int64(LEX *lc, struct res_items *item, int index, int pass);
 void store_yesno(LEX *lc, struct res_items *item, int index, int pass);
 void store_time(LEX *lc, struct res_items *item, int index, int pass);
 void store_size(LEX *lc, struct res_items *item, int index, int pass);
-
-/* Lexical scanning errors in parsing conf files */
-#define scan_err0(lc, msg) s_err(__FILE__, __LINE__, lc, msg)
-#define scan_err1(lc, msg, a1) s_err(__FILE__, __LINE__, lc, msg, a1)
-#define scan_err2(lc, msg, a1, a2) s_err(__FILE__, __LINE__, lc, msg, a1, a2)
-#define scan_err3(lc, msg, a1, a2, a3) s_err(__FILE__, __LINE__, lc, msg, a1, a2, a3)
-#define scan_err4(lc, msg, a1, a2, a3, a4) s_err(__FILE__, __LINE__, lc, msg, a1, a2, a3, a4)
-#define scan_err5(lc, msg, a1, a2, a3, a4, a5) s_err(__FILE__, __LINE__, lc, msg, a1, a2, a3, a4, a5)
-#define scan_err6(lc, msg, a1, a2, a3, a4, a5, a6) s_err(__FILE__, __LINE__, lc, msg, a1, a2, a3, a4, a5, a6)
-
-void s_err(char *file, int line, LEX *lc, char *msg,...);
index 43926b72d5749a169b03ae2429adabf0c7eef562..37c0f188dfed15ca6727c543239f14ca0d3ab18a 100644 (file)
@@ -84,7 +84,7 @@ void     daemon_start            ();
 
 /* lex.c */
 LEX *     lex_close_file         (LEX *lf);
-LEX *     lex_open_file          (LEX *lf, char *fname);
+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);
index 35ea4a20bf5a63a5f69b964719e266640dec748f..6dac0c8b7b7cdf0cab984c12e3d3affd12a04ce4 100644 (file)
@@ -39,9 +39,9 @@ TAPESRCS = btape.c block.c dev.c device.c askdir.c label.c \
 TAPEOBJS = btape.o block.o dev.o device.o askdir.o label.o \
           record.o stored_conf.o 
 
-BLSOBJS = bls.o block.o device.o dev.o askdir.o label.o record.o
+BLSOBJS = bls.o block.o device.o dev.o label.o record.o
 
-BEXTOBJS = bextract.o block.o device.o dev.o askdir.o label.o record.o \
+BEXTOBJS = bextract.o block.o device.o dev.o label.o record.o \
           match_bsr.o parse_bsr.o
 
 SCNOBJS = bscan.o block.o device.o dev.o askdir.o label.o record.o
index d0e77f947ac51ed03bdf085aecd4190bcb1db4f4..418a6e6c230221022a180dc5415bf29396a2321e 100644 (file)
@@ -44,7 +44,6 @@ static FF_PKT my_ff;
 static FF_PKT *ff = &my_ff;
 
 static BSR *bsr = NULL;
-static SESSION_LABEL sesrec;
 
 static void usage()
 {
@@ -63,6 +62,7 @@ static void my_free_jcr(JCR *jcr)
    return;
 }
 
+
 int main (int argc, char *argv[])
 {
    int ch;   
@@ -138,7 +138,10 @@ int main (int argc, char *argv[])
    jcr = new_jcr(sizeof(JCR), my_free_jcr);
    jcr->VolSessionId = 1;
    jcr->VolSessionTime = (uint32_t)time(NULL);
-   jcr->NumVolumes = 1;
+   jcr->bsr = bsr;
+   strcpy(jcr->Job, "bextract");
+   jcr->dev_name = get_pool_memory(PM_FNAME);
+   strcpy(jcr->dev_name, argv[0]);
 
    do_extract(argv[0], argv[1]);
 
@@ -166,6 +169,7 @@ static void do_extract(char *devname, char *where)
    POOLMEM *ofile;                   /* output name with prefix */
    POOLMEM *lname;                   /* link name */
    int wherelen;                     /* prefix length */
+   SESSION_LABEL sessrec;
 
    if (strncmp(devname, "/dev/", 5) != 0) {
       /* Try stripping file part */
@@ -178,19 +182,20 @@ static void do_extract(char *devname, char *where)
         *p = 0;
       }
    }
+   strcpy(jcr->VolumeName, VolName);
 
    dev = init_dev(NULL, devname);
    if (!dev || !open_device(dev)) {
-      Emsg1(M_ABORT, 0, "Cannot open %s\n", devname);
+      Emsg1(M_ERROR_TERM, 0, "Cannot open %s\n", devname);
    }
    Dmsg0(90, "Device opened for read.\n");
 
    if (stat(where, &statp) < 0) {
-      Emsg2(M_ABORT, 0, "Cannot stat %s. It must exist. ERR=%s\n",
+      Emsg2(M_ERROR_TERM, 0, "Cannot stat %s. It must exist. ERR=%s\n",
         where, strerror(errno));
    }
    if (!S_ISDIR(statp.st_mode)) {
-      Emsg1(M_ABORT, 0, "%s must be a directory.\n", where);
+      Emsg1(M_ERROR_TERM, 0, "%s must be a directory.\n", where);
    }
 
    wherelen = strlen(where);
@@ -200,11 +205,17 @@ static void do_extract(char *devname, char *where)
 
    block = new_block(dev);
 
-   strcpy(jcr->VolumeName, VolName);
-   Dmsg1(100, "Volume=%s\n", jcr->VolumeName);
+   create_vol_list(jcr);
 
+   Dmsg1(20, "Found %d volumes names to restore.\n", jcr->NumVolumes);
+
+   /* 
+    * Ready device for reading, and read records
+    */
    if (!acquire_device_for_read(jcr, dev, block)) {
-      Emsg1(M_ABORT, 0, "Cannot open %s\n", devname);
+      free_block(block);
+      free_vol_list(jcr);
+      return;
    }
 
    memset(&rec, 0, sizeof(rec));
@@ -215,11 +226,46 @@ static void do_extract(char *devname, char *where)
 
    for ( ;; ) {
       int ok;
+      DEV_RECORD *record;            /* for reading label of multi-volumes */
 
       if (!read_record(dev, block, &rec)) {
         uint32_t status;
+         Dmsg1(500, "Main read record failed. rem=%d\n", rec.remainder);
         if (dev->state & ST_EOT) {
-           break;
+           if (rec.remainder) {
+               Dmsg0(500, "Not end of record.\n");
+           }
+            Dmsg2(90, "NumVolumes=%d CurVolume=%d\n", jcr->NumVolumes, jcr->CurVolume);
+           /*
+            * End Of Tape -- mount next Volume (if another specified)
+            */
+           if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) {
+              VOL_LIST *vol = jcr->VolList;
+              /* Find next Volume */
+              jcr->CurVolume++;
+              for (int i=1; i<jcr->CurVolume; i++) {
+                 vol = vol->next;
+              }
+              strcpy(jcr->VolumeName, vol->VolumeName);
+               Dmsg1(400, "There is another volume %s.\n", jcr->VolumeName);
+
+              close_dev(dev);
+              dev->state &= ~ST_READ; 
+              if (!acquire_device_for_read(jcr, dev, block)) {
+                  Emsg2(M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev),
+                       jcr->VolumeName);
+                 ok = FALSE;
+                 break;
+              }
+              record = new_record();
+               Dmsg1(500, "read record after new tape. rem=%d\n", record->remainder);
+              read_record(dev, block, record); /* read vol label */
+              dump_label_record(dev, record, 0);
+              free_record(record);
+              continue;
+           }
+            Dmsg0(90, "End of Device reached.\n");
+           break;                    /* End of Tape */
         }
         if (dev->state & ST_EOF) {
            continue;                 /* try again */
@@ -228,17 +274,17 @@ static void do_extract(char *devname, char *where)
         status_dev(dev, &status);
          Dmsg1(20, "Device status: %x\n", status);
         if (status & MT_EOD)
-            Emsg0(M_ABORT, 0, "Unexpected End of Data\n");
+            Emsg0(M_ERROR_TERM, 0, "Unexpected End of Data\n");
         else if (status & MT_EOT)
-            Emsg0(M_ABORT, 0, "Unexpected End of Tape\n");
+            Emsg0(M_ERROR_TERM, 0, "Unexpected End of Tape\n");
         else if (status & MT_EOF)
-            Emsg0(M_ABORT, 0, "Unexpected End of File\n");
+            Emsg0(M_ERROR_TERM, 0, "Unexpected End of File\n");
         else if (status & MT_DR_OPEN)
-            Emsg0(M_ABORT, 0, "Tape Door is Open\n");
+            Emsg0(M_ERROR_TERM, 0, "Tape Door is Open\n");
         else if (!(status & MT_ONLINE))
-            Emsg0(M_ABORT, 0, "Unexpected Tape is Off-line\n");
+            Emsg0(M_ERROR_TERM, 0, "Unexpected Tape is Off-line\n");
         else
-            Emsg3(M_ABORT, 0, "Read error %d on Record Header %s: %s\n", n, dev_name(dev), strerror(errno));
+            Emsg3(M_ERROR_TERM, 0, "Read error %d on Record Header %s: %s\n", n, dev_name(dev), strerror(errno));
       }
 
 
@@ -254,6 +300,7 @@ static void do_extract(char *devname, char *where)
        */
       if (rec.FileIndex < 0) {
         char *rtype;
+        memset(&sessrec, 0, sizeof(sessrec));
         switch (rec.FileIndex) {
            case PRE_LABEL:
                rtype = "Fresh Volume Label";   
@@ -264,7 +311,7 @@ static void do_extract(char *devname, char *where)
               break;
            case SOS_LABEL:
                rtype = "Begin Session";
-              unser_session_label(&sesrec, &rec);
+              unser_session_label(&sessrec, &rec);
               break;
            case EOS_LABEL:
                rtype = "End Session";
@@ -280,6 +327,17 @@ static void do_extract(char *devname, char *where)
             printf("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n",
               rtype, rec.VolSessionId, rec.VolSessionTime, rec.Stream, rec.data_len);
         }
+
+         Dmsg1(40, "Got label = %d\n", rec.FileIndex);
+        if (rec.FileIndex == EOM_LABEL) { /* end of tape? */
+            Dmsg0(40, "Get EOM LABEL\n");
+           break;                         /* yes, get out */
+        }
+        continue;                         /* ignore other labels */
+      } /* end if label record */
+
+      /* Is this the file we want? */
+      if (bsr && !match_bsr(bsr, &rec, &dev->VolHdr, &sessrec)) {
         continue;
       }
 
@@ -292,7 +350,7 @@ static void do_extract(char *devname, char *where)
          */
         if (extract) {
            if (ofd < 0) {
-               Emsg0(M_ABORT, 0, "Logic error output file should be open\n");
+               Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n");
            }
            close(ofd);
            ofd = -1;
@@ -323,7 +381,7 @@ static void do_extract(char *devname, char *where)
          */
          sscanf(rec.data, "%ld %d", &record_file_index, &type);
         if (record_file_index != rec.FileIndex)
-            Emsg2(M_ABORT, 0, "Record header file index %ld not equal record index %ld\n",
+            Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
               rec.FileIndex, record_file_index);
         ap = rec.data;
          while (*ap++ != ' ')         /* skip record file index */
@@ -348,14 +406,8 @@ static void do_extract(char *devname, char *where)
            *lname = 0;
         }
 
-        /* Is this the file we want? */
-        if (bsr) {
-           ok = match_bsr(bsr, &rec, &dev->VolHdr, &sesrec);
-        } else {
-           ok = TRUE;
-        }
            
-        if (ok && file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
+        if (file_is_included(ff, fname) && !file_is_excluded(ff, fname)) {
 
            decode_stat(ap, &statp);
            /*
@@ -393,7 +445,7 @@ static void do_extract(char *devname, char *where)
            total += rec.data_len;
             Dmsg2(8, "Write %ld bytes, total=%ld\n", rec.data_len, total);
            if ((uint32_t)write(ofd, rec.data, rec.data_len) != rec.data_len) {
-               Emsg1(M_ABORT, 0, "Write error: %s\n", strerror(errno));
+               Emsg1(M_ERROR_TERM, 0, "Write error: %s\n", strerror(errno));
            }
         }
  
@@ -405,13 +457,13 @@ static void do_extract(char *devname, char *where)
            compress_len = compress_buf_size;
            if (uncompress((Bytef *)compress_buf, &compress_len, 
                  (const Bytef *)rec.data, (uLong)rec.data_len) != Z_OK) {
-               Emsg0(M_ABORT, 0, _("Uncompression error.\n"));
+               Emsg0(M_ERROR_TERM, 0, _("Uncompression error.\n"));
            }
 
             Dmsg2(100, "Write uncompressed %d bytes, total before write=%d\n", compress_len, total);
            if ((uLongf)write(ofd, compress_buf, (size_t)compress_len) != compress_len) {
                Dmsg0(0, "===Write error===\n");
-               Emsg2(M_ABORT, 0, "Write error on %s: %s\n", ofile, strerror(errno));
+               Emsg2(M_ERROR_TERM, 0, "Write error on %s: %s\n", ofile, strerror(errno));
            }
            total += compress_len;
             Dmsg2(100, "Compress len=%d uncompressed=%d\n", rec.data_len,
@@ -419,7 +471,7 @@ static void do_extract(char *devname, char *where)
         }
 #else
         if (extract) {
-            Emsg0(M_ABORT, 0, "GZIP data stream found, but GZIP not configured!\n");
+            Emsg0(M_ERROR_TERM, 0, "GZIP data stream found, but GZIP not configured!\n");
         }
 #endif
 
@@ -427,7 +479,7 @@ static void do_extract(char *devname, char *where)
       /* If extracting, wierd stream (not 1 or 2), close output file anyway */
       } else if (extract) {
         if (ofd < 0) {
-            Emsg0(M_ABORT, 0, "Logic error output file should be open\n");
+            Emsg0(M_ERROR_TERM, 0, "Logic error output file should be open\n");
         }
         close(ofd);
         ofd = -1;
@@ -492,3 +544,20 @@ static void print_ls_output(char *fname, char *link, int type, struct stat *stat
    *p = 0;
    fputs(buf, stdout);
 }
+
+/* Dummies to replace askdir.c */
+int    dir_get_volume_info(JCR *jcr) { return 1;}
+int    dir_find_next_appendable_volume(JCR *jcr) { return 1;}
+int    dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
+int    dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
+int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
+int    dir_send_job_status(JCR *jcr) {return 1;}
+
+
+int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
+{
+   fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
+      jcr->VolumeName, dev_name(dev));
+   getchar();  
+   return 1;
+}
index 69aca0f40cc31f76c3c76a7e581e04456dc2b742..5224a86e9df63a103d268d402296732602f4442e 100644 (file)
@@ -202,11 +202,13 @@ static void do_setup(char *infname)
    Dmsg2(10, "Device=%s, Vol=%s.\n", infname, VolName);
    dev = init_dev(NULL, infname);
    if (!dev) {
-      Emsg1(M_ABORT, 0, "Cannot open %s\n", infname);
+      Emsg1(M_FATAL, 0, "Cannot open %s\n", infname);
+      exit(1);
    }
    /* ***FIXME**** init capabilities */
    if (!open_device(dev)) {
-      Emsg1(M_ABORT, 0, "Cannot open %s\n", infname);
+      Emsg1(M_FATAL, 0, "Cannot open %s\n", infname);
+      exit(1);
    }
    Dmsg0(90, "Device opened for read.\n");
 
@@ -252,16 +254,15 @@ static int mount_next_volume(char *infname)
       CurVolume++;
       Dmsg1(20, "There is another volume %s.\n", p);
       VolName = p;
-      close_dev(dev);
       jcr->VolumeName = check_pool_memory_size(jcr->VolumeName, 
                          strlen(VolName)+1);
       strcpy(jcr->VolumeName, VolName);
-      printf("Mount Volume %s on device %s and press return when ready.",
-        VolName, infname);
-      getchar();   
-      block->binbuf = 0;     /* consumed all bytes */
-      if (!ready_dev_for_read(jcr, dev, block)) {
-         Emsg2(M_ABORT, 0, "Cannot open Dev=%s, Vol=%s\n", infname, VolName);
+
+      close_dev(dev);
+      dev->state &= ~ST_READ; 
+      if (!acquire_device_for_read(jcr, dev, block)) {
+         Emsg2(M_FATAL, 0, "Cannot open Dev=%s, Vol=%s\n", infname, VolName);
+        exit(1);
       }
       return 1;             /* Next volume mounted */
    }
@@ -280,17 +281,17 @@ static void display_error_status()
    status_dev(dev, &status);
    Dmsg1(20, "Device status: %x\n", status);
    if (status & MT_EOD)
-      Emsg0(M_ABORT, 0, "Unexpected End of Data\n");
+      Emsg0(M_ERROR_TERM, 0, "Unexpected End of Data\n");
    else if (status & MT_EOT)
-      Emsg0(M_ABORT, 0, "Unexpected End of Tape\n");
+      Emsg0(M_ERROR_TERM, 0, "Unexpected End of Tape\n");
    else if (status & MT_EOF)
-      Emsg0(M_ABORT, 0, "Unexpected End of File\n");
+      Emsg0(M_ERROR_TERM, 0, "Unexpected End of File\n");
    else if (status & MT_DR_OPEN)
-      Emsg0(M_ABORT, 0, "Tape Door is Open\n");
+      Emsg0(M_ERROR_TERM, 0, "Tape Door is Open\n");
    else if (!(status & MT_ONLINE))
-      Emsg0(M_ABORT, 0, "Unexpected Tape is Off-line\n");
+      Emsg0(M_ERROR_TERM, 0, "Unexpected Tape is Off-line\n");
    else
-      Emsg2(M_ABORT, 0, "Read error on Record Header %s: %s\n", dev_name(dev), strerror(errno));
+      Emsg2(M_ERROR_TERM, 0, "Read error on Record Header %s: %s\n", dev_name(dev), strerror(errno));
 }
 
 
@@ -385,7 +386,7 @@ Warning, this Volume is a continuation of Volume %s\n",
        *    NOTE: this no longer exists
        */
       if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
-         Emsg0(M_ABORT, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n");
+         Emsg0(M_ERROR_TERM, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n");
       }
 
       /* 
@@ -456,7 +457,7 @@ Warning, this Volume is a continuation of Volume %s\n",
        *    NOTE: this no longer exists
        */
       if (rec->VolSessionId == 0 && rec->VolSessionTime == 0) {
-         Emsg0(M_ABORT, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n");
+         Emsg0(M_ERROR_TERM, 0, "Zero VolSessionId and VolSessionTime. This shouldn't happen\n");
       }
 
       /* 
@@ -473,7 +474,7 @@ Warning, this Volume is a continuation of Volume %s\n",
         char *ap;
          sscanf(rec->data, "%ld %d %s", &record_file_index, &type, fname);
         if (record_file_index != rec->FileIndex) {
-            Emsg2(M_ABORT, 0, "Record header file index %ld not equal record index %ld\n",
+            Emsg2(M_ERROR_TERM, 0, "Record header file index %ld not equal record index %ld\n",
               rec->FileIndex, record_file_index);
         }
         ap = rec->data;
@@ -529,3 +530,20 @@ static void print_ls_output(char *fname, char *link, int type, struct stat *stat
    *p = 0;
    fputs(buf, stdout);
 }
+
+/* Dummies to replace askdir.c */
+int    dir_get_volume_info(JCR *jcr) { return 1;}
+int    dir_find_next_appendable_volume(JCR *jcr) { return 1;}
+int    dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel) { return 1; }
+int    dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev) { return 1; }
+int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec) { return 1;}
+int    dir_send_job_status(JCR *jcr) {return 1;}
+
+
+int dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev)
+{
+   fprintf(stderr, "Mount Volume %s on device %s and press return when ready: ",
+      jcr->VolumeName, dev_name(dev));
+   getchar();  
+   return 1;
+}
index be8ef84d379dfa79851415b062f8ab3f433ab1cf..98228c906f319fff2a7366654080efa017947fa0 100644 (file)
 
 #include "findlib/find.h"
 
+/*
+ * List of Volume names to be read by Storage daemon.
+ *  Formed by Storage daemon from BSR  
+ */
+struct s_vol_list {
+   struct s_vol_list *next;
+   char VolumeName[MAX_NAME_LENGTH];
+};
+typedef struct s_vol_list VOL_LIST;
+
+
 /*
  * !!!!!!!!!!!!!!!!!! NOTE !!!!!!!!!!!!!!!!!!!!!!!!!!!!!
- * !!!                                               !!!
- * !!!   All records must have a pointer to          !!!
- * !!!   the next item as the first item defined.    !!!
- * !!!                                               !!!
+ * !!!                                              !!!
+ * !!!  All records must have a pointer to          !!!
+ * !!!  the next item as the first item defined.    !!!
+ * !!!                                              !!!
  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  */
 
 typedef struct s_bsr_client {
    struct s_bsr_client *next;
-   char *ClientName;
+   char ClientName[MAX_NAME_LENGTH];
 } BSR_CLIENT;
 
 typedef struct s_bsr_sessid {
@@ -61,15 +72,15 @@ typedef struct s_bsr_sesstime {
 
 typedef struct s_bsr_volfile {
    struct s_bsr_volfile *next;
-   uint32_t sfile;                    /* start file */
-   uint32_t efile;                    /* end file */
+   uint32_t sfile;                   /* start file */
+   uint32_t efile;                   /* end file */
    int found;
 } BSR_VOLFILE;
 
 typedef struct s_bsr_findex {
    struct s_bsr_findex *next;
-   int32_t findex;                    /* start file index */
-   int32_t findex2;                   /* end file index */
+   int32_t findex;                   /* start file index */
+   int32_t findex2;                  /* end file index */
    int found;
 } BSR_FINDEX;
 
@@ -92,25 +103,25 @@ typedef struct s_bsr_joblevel {
 
 typedef struct s_bsr_job {
    struct s_bsr_job *next;
-   char *Job;
+   char Job[MAX_NAME_LENGTH];
    int found;
 } BSR_JOB;
 
 
 typedef struct s_bsr {
-   struct s_bsr *next;                /* pointer to next one */
-   int           done;                /* set when everything found */
-   char         *VolumeName;
-   BSR_VOLFILE  *volfile;
+   struct s_bsr *next;               /* pointer to next one */
+   int          done;                /* set when everything found */
+   char        *VolumeName;
+   BSR_VOLFILE *volfile;
    BSR_SESSTIME *sesstime;
-   BSR_SESSID   *sessid;
-   BSR_JOBID    *JobId;
-   BSR_JOB      *job;
-   BSR_CLIENT   *client;
-   BSR_FINDEX   *FileIndex;
-   BSR_JOBTYPE  *JobType;
+   BSR_SESSID  *sessid;
+   BSR_JOBID   *JobId;
+   BSR_JOB     *job;
+   BSR_CLIENT  *client;
+   BSR_FINDEX  *FileIndex;
+   BSR_JOBTYPE *JobType;
    BSR_JOBLEVEL *JobLevel;
-   FF_PKT *ff;                        /* include/exclude */
+   FF_PKT *ff;                       /* include/exclude */
 } BSR;
 
 
index af1867c75ac8d78bf093241f1b0cbbff9d69e2cb..e770c719a6b7b6ce0ae7e9a64e39cfe7312934fa 100644 (file)
@@ -34,6 +34,7 @@
 #include "stored.h"
 
 /* Imported variables */
+extern STORES *me;
 
 /* Static variables */
 static char ferrmsg[]      = "3900 Invalid command\n";
@@ -53,6 +54,7 @@ static int append_end_session(JCR *jcr);
 static int read_open_session(JCR *jcr);
 static int read_data_cmd(JCR *jcr);
 static int read_close_session(JCR *jcr);
+static int bootstrap_cmd(JCR *jcr);
 
 struct s_cmds {
    char *cmd;
@@ -70,26 +72,28 @@ static struct s_cmds fd_cmds[] = {
    {"read open",    read_open_session},
    {"read data",    read_data_cmd},
    {"read close",   read_close_session},
+   {"bootstrap",    bootstrap_cmd},
    {NULL,          NULL}                  /* list terminator */
 };
 
 /* Commands from the File daemon that require additional scanning */
-/*  static char append_open[]  = "append open session\n"; */
-static char read_open[]    = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
+static char read_open[]       = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
 
 /* Responses sent to the File daemon */
-static char NO_open[]      = "3901 Error session already open\n";
-static char NOT_opened[]   = "3902 Error session not opened\n";
-static char OK_end[]       = "3000 OK end\n";
-static char OK_close[]     = "3000 OK close Volumes = %d\n";
-static char OK_open[]      = "3000 OK open ticket = %d\n";
-static char OK_append[]    = "3000 OK append data\n";
-static char ERROR_append[] = "3903 Error append data\n";
+static char NO_open[]         = "3901 Error session already open\n";
+static char NOT_opened[]      = "3902 Error session not opened\n";
+static char OK_end[]          = "3000 OK end\n";
+static char OK_close[]        = "3000 OK close Volumes = %d\n";
+static char OK_open[]         = "3000 OK open ticket = %d\n";
+static char OK_append[]       = "3000 OK append data\n";
+static char ERROR_append[]    = "3903 Error append data\n";
+static char OK_bootstrap[]    = "3000 OK bootstrap\n";
+static char ERROR_bootstrap[] = "3904 Error bootstrap\n";
 
 /* Information sent to the Director */
 static char Job_start[] = "3010 Job %s start\n";
 static char Job_end[]  = 
-   "3099 Job %s end JobStatus=%d JobFiles=%d JobBytes=%" lld "\n";
+   "3099 Job %s end JobStatus=%d JobFiles=%d JobBytes=%s\n";
 
 /*
  * Run a File daemon Job -- File daemon already authorized
@@ -104,6 +108,7 @@ void run_job(JCR *jcr)
    int i, found, quit;
    BSOCK *fd = jcr->file_bsock;
    BSOCK *dir = jcr->dir_bsock;
+   char ec1[30];
 
 
    Dmsg1(20, "Start run Job=%s\n", jcr->Job);
@@ -141,7 +146,7 @@ void run_job(JCR *jcr)
       jcr->JobStatus = JS_Terminated;
    }
    bnet_fsend(dir, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
-      jcr->JobBytes);
+      edit_uint64(jcr->JobBytes, ec1));
 
    bnet_sig(dir, BNET_EOF);          /* send EOF to Director daemon */
    return;
@@ -303,6 +308,50 @@ static int read_open_session(JCR *jcr)
    return 1;
 }
 
+static int bootstrap_cmd(JCR *jcr)
+{
+   BSOCK *fd = jcr->file_bsock;
+   POOLMEM *fname = get_pool_memory(PM_FNAME);
+   FILE *bs;
+
+   if (jcr->RestoreBootstrap) {
+      unlink(jcr->RestoreBootstrap);
+      free_pool_memory(jcr->RestoreBootstrap);
+   }
+   Mmsg(&fname, "%s/%s.%s.bootstrap", me->working_directory, me->hdr.name,
+      jcr->Job);
+   Dmsg1(400, "bootstrap=%s\n", fname);
+   jcr->RestoreBootstrap = fname;
+   bs = fopen(fname, "a+");           /* create file */
+   if (!bs) {
+      Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
+        jcr->RestoreBootstrap, strerror(errno));
+      goto bail_out;
+   }
+   while (bnet_recv(fd) > 0) {
+       Dmsg1(200, "stored<filed: bootstrap file %s\n", fd->msg);
+       fputs(fd->msg, bs);
+   }
+   fclose(bs);
+   jcr->bsr = parse_bsr(jcr->RestoreBootstrap);
+   if (!jcr->bsr) {
+      goto bail_out;
+   }
+   if (debug_level > 20) {
+      dump_bsr(jcr->bsr);
+   }
+   return bnet_fsend(fd, OK_bootstrap);
+
+bail_out:
+   unlink(jcr->RestoreBootstrap);
+   free_pool_memory(jcr->RestoreBootstrap);
+   jcr->RestoreBootstrap = NULL;
+   bnet_fsend(fd, ERROR_bootstrap);
+   return 0;
+
+}
+
+
 /*
  *   Read Close session command
  *     Close the read session
index ee5e63e588dafad913ad88793422ee6002e6ad21..c462f583485096f49a636b26b119b4f4ad326bb0 100644 (file)
@@ -327,5 +327,14 @@ void stored_free_jcr(JCR *jcr)
    if (jcr->fileset_name) {
       free_memory(jcr->fileset_name);
    }
+   if (jcr->bsr) {
+      free_bsr(jcr->bsr);
+   }
+   if (jcr->RestoreBootstrap) {
+      unlink(jcr->RestoreBootstrap);
+      free_pool_memory(jcr->RestoreBootstrap);
+      jcr->RestoreBootstrap = NULL;
+   }
+                     
    return;
 }
index 3eb5387ca7a4c0a348f124c5ce17d53d65ddfbd9..21d5a19420415b4ec4f6f1041a893b728c0626df 100755 (executable)
@@ -157,7 +157,7 @@ static int match_jobid(BSR_JOBID *jobid, SESSION_LABEL *sessrec)
    if (!jobid) {
       return 1;                      /* no specification matches all */
    }
-   if (jobid->JobId >= sessrec->JobId && jobid->JobId2 <= sessrec->JobId) {
+   if (jobid->JobId <= sessrec->JobId && jobid->JobId2 >= sessrec->JobId) {
       jobid->found++;
       return 1;
    }
@@ -173,7 +173,7 @@ static int match_volfile(BSR_VOLFILE *volfile, DEV_RECORD *rec)
    if (!volfile) {
       return 1;                      /* no specification matches all */
    }
-   if (volfile->sfile >= rec->File && volfile->efile <= rec->File) {
+   if (volfile->sfile <= rec->File && volfile->efile >= rec->File) {
       volfile->found++;
       return 1;
    }
@@ -189,7 +189,7 @@ static int match_findex(BSR_FINDEX *findex, DEV_RECORD *rec)
    if (!findex) {
       return 1;                      /* no specification matches all */
    }
-   if (findex->findex >= rec->FileIndex && findex->findex2 <= rec->FileIndex) {
+   if (findex->findex <= rec->FileIndex && findex->findex2 >= rec->FileIndex) {
       findex->found++;
       return 1;
    }
@@ -205,7 +205,7 @@ static int match_sessid(BSR_SESSID *sessid, DEV_RECORD *rec)
    if (!sessid) {
       return 1;                      /* no specification matches all */
    }
-   if (sessid->sessid >= rec->VolSessionId && sessid->sessid2 <= rec->VolSessionId) {
+   if (sessid->sessid <= rec->VolSessionId && sessid->sessid2 >= rec->VolSessionId) {
       sessid->found++;
       return 1;
    }
index 91ee185c11212564eb33e9598a20469b232c1da9..522b19b05a0907a3479dc1d3a2e724b07dd02594 100755 (executable)
@@ -73,6 +73,24 @@ static BSR *new_bsr()
    return bsr;
 }
 
+/*
+ * Format a scanner error message 
+ */
+static void s_err(char *file, int line, LEX *lc, char *msg, ...)
+{
+   va_list arg_ptr;
+   char buf[MAXSTRING];
+
+   va_start(arg_ptr, msg);
+   bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
+   va_end(arg_ptr);
+     
+   e_msg(file, line, M_FATAL, 0, "Config error: %s\n\
+            : Line %d, col %d of file %s\n%s\n",
+      buf, lc->line_no, lc->col_no, lc->fname, lc->line);
+}
+
+
 /*********************************************************************
  *
  *     Parse Bootstrap file
@@ -86,7 +104,7 @@ BSR *parse_bsr(char *cf)
    BSR *bsr = root_bsr;
 
    Dmsg0(200, "Enter parse_bsf()\n");
-   lc = lex_open_file(lc, cf);
+   lc = lex_open_file(lc, cf, s_err);
    while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
       Dmsg1(150, "parse got token=%s\n", lex_tok_to_str(token));
       if (token == T_EOL) {
@@ -98,6 +116,8 @@ BSR *parse_bsr(char *cf)
             Dmsg1 (150, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
            if (token != T_EQUALS) {
                scan_err1(lc, "expected an equals, got: %s", lc->str);
+              bsr = NULL;
+              break;
            }
             Dmsg1(100, "calling handler for %s\n", items[i].name);
            /* Call item handler */
@@ -109,11 +129,18 @@ BSR *parse_bsr(char *cf)
       if (i >= 0) {
          Dmsg1(150, "Keyword = %s\n", lc->str);
          scan_err1(lc, "Keyword %s not found", lc->str);
+        break;
+      }
+      if (!bsr) {
+        break;
       }
-
    }
    lc = lex_close_file(lc);
    Dmsg0(200, "Leave parse_bsf()\n");
+   if (!bsr) {
+      free_bsr(root_bsr);
+      root_bsr = NULL;
+   }
    return root_bsr;
 }
 
@@ -122,6 +149,9 @@ static BSR *store_vol(LEX *lc, BSR *bsr)
    int token;
     
    token = lex_get_token(lc, T_NAME);
+   if (token == T_ERROR) {
+      return NULL;
+   }
    if (bsr->VolumeName) {
       bsr->next = new_bsr();
       bsr = bsr->next;
@@ -138,9 +168,12 @@ static BSR *store_client(LEX *lc, BSR *bsr)
     
    for (;;) {
       token = lex_get_token(lc, T_NAME);
+      if (token == T_ERROR) {
+        return NULL;
+      }
       client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
       memset(client, 0, sizeof(BSR_CLIENT));
-      client->ClientName = bstrdup(lc->str);
+      strcpy(client->ClientName, lc->str);
       /* Add it to the end of the client chain */
       if (!bsr->client) {
         bsr->client = client;
@@ -165,9 +198,12 @@ static BSR *store_job(LEX *lc, BSR *bsr)
     
    for (;;) {
       token = lex_get_token(lc, T_NAME);
+      if (token == T_ERROR) {
+        return NULL;
+      }
       job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
       memset(job, 0, sizeof(BSR_JOB));
-      job->Job = bstrdup(lc->str);
+      strcpy(job->Job, lc->str);
       /* Add it to the end of the client chain */
       if (!bsr->job) {
         bsr->job = job;
@@ -193,6 +229,9 @@ static BSR *store_findex(LEX *lc, BSR *bsr)
 
    for (;;) {
       token = lex_get_token(lc, T_PINT32_RANGE);
+      if (token == T_ERROR) {
+        return NULL;
+      }
       findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
       memset(findex, 0, sizeof(BSR_FINDEX));
       findex->findex = lc->pint32_val;
@@ -223,6 +262,9 @@ static BSR *store_jobid(LEX *lc, BSR *bsr)
 
    for (;;) {
       token = lex_get_token(lc, T_PINT32_RANGE);
+      if (token == T_ERROR) {
+        return NULL;
+      }
       jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
       memset(jobid, 0, sizeof(BSR_JOBID));
       jobid->JobId = lc->pint32_val;
@@ -273,6 +315,9 @@ static BSR *store_volfile(LEX *lc, BSR *bsr)
 
    for (;;) {
       token = lex_get_token(lc, T_PINT32_RANGE);
+      if (token == T_ERROR) {
+        return NULL;
+      }
       volfile = (BSR_VOLFILE *)malloc(sizeof(BSR_VOLFILE));
       memset(volfile, 0, sizeof(BSR_VOLFILE));
       volfile->sfile = lc->pint32_val;
@@ -304,6 +349,9 @@ static BSR *store_sessid(LEX *lc, BSR *bsr)
 
    for (;;) {
       token = lex_get_token(lc, T_PINT32_RANGE);
+      if (token == T_ERROR) {
+        return NULL;
+      }
       sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
       memset(sid, 0, sizeof(BSR_SESSID));
       sid->sessid = lc->pint32_val;
@@ -333,6 +381,9 @@ static BSR *store_sesstime(LEX *lc, BSR *bsr)
 
    for (;;) {
       token = lex_get_token(lc, T_PINT32);
+      if (token == T_ERROR) {
+        return NULL;
+      }
       stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
       memset(stime, 0, sizeof(BSR_SESSTIME));
       stime->sesstime = lc->pint32_val;
@@ -498,3 +549,96 @@ void free_bsr(BSR *bsr)
    free_bsr(bsr->next);
    free(bsr);
 }
+
+/*****************************************************************
+ * Routines for handling volumes     
+ */
+VOL_LIST *new_vol()
+{
+   VOL_LIST *vol;
+   vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
+   memset(vol, 0, sizeof(VOL_LIST));
+   return vol;
+}
+
+/* 
+ * Add current volume to end of list, only if the Volume
+ * is not already in the list.
+ *
+ *   returns: 1 if volume added
+ *           0 if volume already in list
+ */
+int add_vol(JCR *jcr, VOL_LIST *vol)
+{
+   VOL_LIST *next = jcr->VolList;
+
+   if (!next) {                      /* list empty ? */
+      jcr->VolList = vol;            /* yes, add volume */
+   } else {
+      for ( ; next->next; next=next->next) {
+        if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
+           return 0;                 /* already in list */
+        }
+      }
+      if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
+        return 0;                    /* already in list */
+      }
+      next->next = vol;              /* add volume */
+   }
+   return 1;
+}
+
+void free_vol_list(JCR *jcr)
+{
+   VOL_LIST *next = jcr->VolList;
+   VOL_LIST *tmp;
+
+   for ( ; next; ) {
+      tmp = next->next;
+      free(next);
+      next = tmp;
+   }
+}
+
+void create_vol_list(JCR *jcr)
+{
+   char *p, *n;
+   VOL_LIST *vol;
+
+   /* 
+    * Build a list of volume to be processed
+    */
+   jcr->NumVolumes = 0;
+   jcr->CurVolume = 1;
+   if (jcr->bsr) {
+      BSR *bsr = jcr->bsr;
+      strcpy(jcr->VolumeName, bsr->VolumeName); /* setup first volume */
+      for ( ; bsr; bsr=bsr->next) {
+        vol = new_vol();
+        strcpy(vol->VolumeName, bsr->VolumeName);
+        if (add_vol(jcr, vol)) {
+           jcr->NumVolumes++;
+            Dmsg1(400, "Added volume %s\n", vol->VolumeName);
+        } else {
+            Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
+           free((char *)vol);
+        }
+      }
+   } else {
+      /* This is the old way -- deprecated */ 
+      for (p = jcr->VolumeName; p && *p; ) {
+         n = strchr(p, '|');             /* volume name separator */
+        if (n) {
+           *n++ = 0;                    /* Terminate name */
+        }
+        vol = new_vol();
+        strcpy(vol->VolumeName, p);
+        if (add_vol(jcr, vol)) {
+           jcr->NumVolumes++;
+        } else {
+           free((char *)vol);
+        }
+        p = n;
+      }
+   }
+}
index 38ac7c081801bfee0e6738912efed8d8da71f030..ec564adc6a933464875c366a65f88432e5e59944 100644 (file)
 uint32_t new_VolSessionId();
 
 /* From askdir.c */
-int     dir_get_volume_info(JCR *jcr);
-int     dir_find_next_appendable_volume(JCR *jcr);
-int     dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel);
-int     dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev);
-int     dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
-int     dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
-int     dir_send_job_status(JCR *jcr);
+int    dir_get_volume_info(JCR *jcr);
+int    dir_find_next_appendable_volume(JCR *jcr);
+int    dir_update_volume_info(JCR *jcr, VOLUME_CAT_INFO *vol, int relabel);
+int    dir_ask_sysop_to_mount_next_volume(JCR *jcr, DEVICE *dev);
+int    dir_ask_sysop_to_mount_volume(JCR *jcr, DEVICE *dev);
+int    dir_update_file_attributes(JCR *jcr, DEV_RECORD *rec);
+int    dir_send_job_status(JCR *jcr);
 
 /* authenticate.c */
-int     authenticate_director(JCR *jcr);
-int     authenticate_filed(JCR *jcr);
+int    authenticate_director(JCR *jcr);
+int    authenticate_filed(JCR *jcr);
 
 /* From block.c */
-void    dump_block(DEV_BLOCK *b, char *msg);
+void   dump_block(DEV_BLOCK *b, char *msg);
 DEV_BLOCK *new_block(DEVICE *dev);
-void    init_block_write(DEV_BLOCK *block);
-void    empty_block(DEV_BLOCK *block);
-void    free_block(DEV_BLOCK *block);
-int     write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int     write_block_to_dev(DEVICE *dev, DEV_BLOCK *block);
-int     read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
-int     read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
+void   init_block_write(DEV_BLOCK *block);
+void   empty_block(DEV_BLOCK *block);
+void   free_block(DEV_BLOCK *block);
+int    write_block_to_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int    write_block_to_dev(DEVICE *dev, DEV_BLOCK *block);
+int    read_block_from_device(DEVICE *dev, DEV_BLOCK *block);
+int    read_block_from_dev(DEVICE *dev, DEV_BLOCK *block);
 
 
 /* From dev.c */
-DEVICE  *init_dev(DEVICE *dev, char *device);
-int      open_dev(DEVICE *dev, char *VolName, int mode);
-void     close_dev(DEVICE *dev);
-void     force_close_dev(DEVICE *dev);
-int      truncate_dev(DEVICE *dev);
-void     term_dev(DEVICE *dev);
-char *   strerror_dev(DEVICE *dev);
-void     clrerror_dev(DEVICE *dev, int func);
-int      update_pos_dev(DEVICE *dev);
-int      rewind_dev(DEVICE *dev);
-int      load_dev(DEVICE *dev);
-int      offline_dev(DEVICE *dev);
-int      flush_dev(DEVICE *dev);
-int      weof_dev(DEVICE *dev, int num);
-int      write_block(DEVICE *dev);
-int      write_dev(DEVICE *dev, char *buf, size_t len);
-int      read_dev(DEVICE *dev, char *buf, size_t len);
-int      status_dev(DEVICE *dev, uint32_t *status);
-int      eod_dev(DEVICE *dev);
-int      fsf_dev(DEVICE *dev, int num);
-int      fsr_dev(DEVICE *dev, int num);
-int      bsf_dev(DEVICE *dev, int num);
-int      bsr_dev(DEVICE *dev, int num);
+DEVICE *init_dev(DEVICE *dev, char *device);
+int     open_dev(DEVICE *dev, char *VolName, int mode);
+void    close_dev(DEVICE *dev);
+void    force_close_dev(DEVICE *dev);
+int     truncate_dev(DEVICE *dev);
+void    term_dev(DEVICE *dev);
+char *  strerror_dev(DEVICE *dev);
+void    clrerror_dev(DEVICE *dev, int func);
+int     update_pos_dev(DEVICE *dev);
+int     rewind_dev(DEVICE *dev);
+int     load_dev(DEVICE *dev);
+int     offline_dev(DEVICE *dev);
+int     flush_dev(DEVICE *dev);
+int     weof_dev(DEVICE *dev, int num);
+int     write_block(DEVICE *dev);
+int     write_dev(DEVICE *dev, char *buf, size_t len);
+int     read_dev(DEVICE *dev, char *buf, size_t len);
+int     status_dev(DEVICE *dev, uint32_t *status);
+int     eod_dev(DEVICE *dev);
+int     fsf_dev(DEVICE *dev, int num);
+int     fsr_dev(DEVICE *dev, int num);
+int     bsf_dev(DEVICE *dev, int num);
+int     bsr_dev(DEVICE *dev, int num);
 
 /* Get info about device */
-char *   dev_name(DEVICE *dev);
-char *   dev_vol_name(DEVICE *dev);
+char *  dev_name(DEVICE *dev);
+char *  dev_vol_name(DEVICE *dev);
 uint32_t dev_block(DEVICE *dev);
 uint32_t dev_file(DEVICE *dev);
-int      dev_is_tape(DEVICE *dev);
+int     dev_is_tape(DEVICE *dev);
 
 /* From device.c */
-int      open_device(DEVICE *dev);
-int      acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int      acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int      ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-int      release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     block_device(DEVICE *dev, int state);
-void     unblock_device(DEVICE *dev);
-void     lock_device(DEVICE *dev);
-void     unlock_device(DEVICE *dev);
-int      fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int     open_device(DEVICE *dev);
+int     acquire_device_for_append(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int     acquire_device_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int     ready_dev_for_read(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+int     release_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    block_device(DEVICE *dev, int state);
+void    unblock_device(DEVICE *dev);
+void    lock_device(DEVICE *dev);
+void    unlock_device(DEVICE *dev);
+int     fixup_device_block_write_error(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
 
 /* From dircmd.c */
-void     connection_request(void *arg); 
+void    connection_request(void *arg); 
 
 
 /* From fd_cmds.c */
-void     run_job(JCR *jcr);
+void    run_job(JCR *jcr);
 
 /* From fdmsg.c */
-int      bget_msg(BSOCK *sock);
+int     bget_msg(BSOCK *sock);
 
 /* From job.c */
-void     stored_free_jcr(JCR *jcr);
-void     connection_from_filed(void *arg);     
-void     handle_filed_connection(BSOCK *fd, char *job_name);
+void    stored_free_jcr(JCR *jcr);
+void    connection_from_filed(void *arg);     
+void    handle_filed_connection(BSOCK *fd, char *job_name);
 
 /* From label.c */
-int      read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
-int      write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
-int      write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
-int      write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
-void     dump_volume_label(DEVICE *dev);
-void     dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
-int      unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
-int      unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
+int     read_dev_volume_label(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    create_session_label(JCR *jcr, DEV_RECORD *rec, int label);
+int     write_volume_label_to_dev(JCR *jcr, DEVRES *device, char *VolName, char *PoolName);
+int     write_session_label(JCR *jcr, DEV_BLOCK *block, int label);
+int     write_volume_label_to_block(JCR *jcr, DEVICE *dev, DEV_BLOCK *block);
+void    dump_volume_label(DEVICE *dev);
+void    dump_label_record(DEVICE *dev, DEV_RECORD *rec, int verbose);
+int     unser_volume_label(DEVICE *dev, DEV_RECORD *rec);
+int     unser_session_label(SESSION_LABEL *label, DEV_RECORD *rec);
 
 /* From match_bsr.c */
 int match_bsr(BSR *bsr, DEV_RECORD *rec, VOLUME_LABEL *volrec, 
-              SESSION_LABEL *sesrec);
+             SESSION_LABEL *sesrec);
 
 /* From parse_bsr.c */
 extern BSR *parse_bsr(char *lf);
 extern void dump_bsr(BSR *bsr);
 extern void free_bsr(BSR *bsr);
+extern VOL_LIST *new_vol();
+extern int add_vol(JCR *jcr, VOL_LIST *vol);
+extern void free_vol_list(JCR *jcr);
+extern void create_vol_list(JCR *jcr);
 
 /* From record.c */
 char   *FI_to_ascii(int fi);
 char   *stream_to_ascii(int stream);
-int     write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
-int     read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
+int    write_record_to_block(DEV_BLOCK *block, DEV_RECORD *rec);
+int    read_record_from_block(DEV_BLOCK *block, DEV_RECORD *rec); 
 DEV_RECORD *new_record();
-void    free_record(DEV_RECORD *rec);
-int     read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
-int     write_record_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
+void   free_record(DEV_RECORD *rec);
+int    read_record(DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
+int    write_record_device(JCR *jcr, DEVICE *dev, DEV_BLOCK *block, DEV_RECORD *record);
index d956494a103b38e51941b6fbc879b0966358bac0..baf57f549d1cc124c09ac5e27cabc53f46bc0c1c 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Read code for Storage daemon
+ *
  *     Kern Sibbald, November MM
  *
  *   Version $Id$
@@ -42,6 +43,7 @@ extern int  FiledDataChan;          /* File daemon data channel (port) */
 static char OK_data[]    = "3000 OK data\n";
 static char rec_header[] = "rechdr %ld %ld %ld %ld %ld";
 
+
 /* 
  *  Read Data and send to File Daemon
  *   Returns: 0 on failure
@@ -55,12 +57,13 @@ int do_read_data(JCR *jcr)
    DEVICE *dev;
    DEV_RECORD rec;
    DEV_BLOCK *block;
-   char *hdr, *p;
-
+   POOLMEM *hdr; 
+   SESSION_LABEL sessrec;             /* session record */
    
    Dmsg0(20, "Start read data.\n");
 
    dev = jcr->device->dev;
+   memset(&sessrec, 0, sizeof(sessrec));
 
    /* Tell File daemon we will send data */
    bnet_fsend(fd_sock, OK_data);
@@ -77,17 +80,7 @@ int do_read_data(JCR *jcr)
 
    block = new_block(dev);
 
-   /* Find out if we were passed multiple volumes */
-   jcr->NumVolumes = 1;
-   jcr->CurVolume = 1;
-   /* Scan through VolumeNames terminating them and counting them */
-   for (p = jcr->VolumeName; p && *p; ) {
-      p = strchr(p, '|');             /* volume name separator */
-      if (p) {
-        *p++ = 0;                    /* Terminate name */
-        jcr->NumVolumes++;
-      }
-   }
+   create_vol_list(jcr);
 
    Dmsg1(20, "Found %d volumes names to restore.\n", jcr->NumVolumes);
 
@@ -96,20 +89,20 @@ int do_read_data(JCR *jcr)
     */
    if (!acquire_device_for_read(jcr, dev, block)) {
       free_block(block);
+      free_vol_list(jcr);
       return 0;
    }
 
    memset(&rec, 0, sizeof(rec));
    rec.data = ds->msg;               /* use socket message buffer */
-   hdr = (char *) get_pool_memory(PM_MESSAGE);
+   hdr = get_pool_memory(PM_MESSAGE);
 
    /*
-    * ****FIXME**** enhance this to look for 
-    *              more things than just a session.
+    *  Read records, apply BSR filtering, and return any that are 
+    *   matched.
     */
    for ( ;ok; ) {
       DEV_RECORD *record;            /* for reading label of multi-volumes */
-      SESSION_LABEL sessrec;          /* session record */
 
       if (job_cancelled(jcr)) {
         ok = FALSE;
@@ -124,16 +117,21 @@ int do_read_data(JCR *jcr)
                Dmsg0(500, "Not end of record.\n");
            }
             Dmsg2(90, "NumVolumes=%d CurVolume=%d\n", jcr->NumVolumes, jcr->CurVolume);
+           /*
+            * End Of Tape -- mount next Volume (if another specified)
+            */
            if (jcr->NumVolumes > 1 && jcr->CurVolume < jcr->NumVolumes) {
+              VOL_LIST *vol = jcr->VolList;
               close_dev(dev);
-              for (p=jcr->VolumeName; *p++; ) /* skip to next volume name */
-                 { }
               jcr->CurVolume++;
-               Dmsg1(20, "There is another volume %s.\n", p);
-              strcpy(jcr->VolumeName, p);
+              for (int i=1; i<jcr->CurVolume; i++) {
+                 vol = vol->next;
+              }
+              strcpy(jcr->VolumeName, vol->VolumeName);
+               Dmsg1(000, "There is another volume %s.\n", jcr->VolumeName);
               dev->state &= ~ST_READ; 
               if (!acquire_device_for_read(jcr, dev, block)) {
-                  Emsg2(M_ERROR, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), p);
+                  Emsg2(M_ERROR, 0, "Cannot open Dev=%s, Vol=%s\n", dev_name(dev), jcr->VolumeName);
                  ok = FALSE;
                  break;
               }
@@ -152,12 +150,15 @@ int do_read_data(JCR *jcr)
            continue;                 /* End of File */
         }
 
-         Emsg2(M_ABORT, 0, "Read error on Record Header %s ERR=%s\n", dev_name(dev), strerror(errno));
+         Jmsg2(jcr, M_FATAL, 0, "Read error on Record Header %s ERR=%s\n", dev_name(dev), strerror(errno));
+        ok = FALSE;
+        break;
       }
 
       /* Some sort of label? */ 
       if (rec.FileIndex < 0) {
         char *rtype;
+        memset(&sessrec, 0, sizeof(sessrec));
         switch (rec.FileIndex) {
            case PRE_LABEL:
                rtype = "Fresh Volume Label";   
@@ -191,18 +192,21 @@ int do_read_data(JCR *jcr)
            break;                         /* yes, get out */
         }
         continue;                         /* ignore other labels */
-      }
-
-      /* ****FIXME***** make sure we REALLY have a session record */
-      if (jcr->bsr && !match_bsr(jcr->bsr, &rec, &dev->VolHdr, &sessrec)) {
-         Dmsg0(50, "BSR rejected record\n");
-        continue;
-      }
+      } /* end if label record */
 
-      if (rec.VolSessionId != jcr->read_VolSessionId ||
-         rec.VolSessionTime != jcr->read_VolSessionTime) {
-         Dmsg0(50, "Ignore record ids not equal\n");
-        continue;                    /* ignore */
+      if (jcr->bsr) {
+        /* Match BSR against current record */
+        if (!match_bsr(jcr->bsr, &rec, &dev->VolHdr, &sessrec)) {
+            Dmsg0(50, "BSR rejected record\n");
+           continue;
+        }
+      } else { 
+        /* Old way, deprecated */
+        if (rec.VolSessionId != jcr->read_VolSessionId ||
+            rec.VolSessionTime != jcr->read_VolSessionTime) {
+            Dmsg0(50, "Ignore record ids not equal\n");
+           continue;                    /* ignore */
+        }
       }
        
       /* Generate Header parameters and send to File daemon
@@ -240,6 +244,7 @@ int do_read_data(JCR *jcr)
    }
    free_pool_memory(hdr);
    free_block(block);
+   free_vol_list(jcr);
    Dmsg0(30, "Done reading.\n");
    return ok ? 1 : 0;
 }
index 9b151b0fd7ad0b5c0df0a5c7d48e7368a703c5cb..568ad16e73ffd83a9be41d0b5cac8c2cd6c131aa 100644 (file)
@@ -51,7 +51,7 @@ BSHM bshm;                          /* shared memory control packet */
 
 
 /* This is our own global resource */
-static STORES *me;
+STORES *me;
 
 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
 static uint32_t VolSessionId = 0;
index 1220202d5505514007bd115f2774debd61e8daa0..c034df374a2b9755a595d7f2841eb33d7eeb5cf9 100644 (file)
@@ -363,9 +363,18 @@ void save_resource(int type, struct res_items *items, int pass)
    }
    /* Common */
    if (!error) {
-      res = (URES *) malloc(size);
+      res = (URES *)malloc(size);
       memcpy(res, &res_all, size);
-      res->res_dir.hdr.next = resources[rindex].res_head;
-      resources[rindex].res_head = (RES *)res;
+      if (!resources[rindex].res_head) {
+        resources[rindex].res_head = (RES *)res; /* store first entry */
+      } 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;
+         Dmsg2(90, "Inserting %s res: %s\n", res_to_str(type),
+              res->res_dir.hdr.name);
+      }
    }
 }
index c6485ed68b7dec5f083e5dbb226fe3c0506b88a3..24fd1d157ed31ec819ee86e4eaba5826ed0e33c1 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.22"
 #define VSTRING "1"
-#define DATE    "22 June 2002"
-#define LSMDATE "22Jun02"
+#define DATE    "25 June 2002"
+#define LSMDATE "25Jun02"
 
 /* Debug flags */
 #define DEBUG 1