]> git.sur5r.net Git - bacula/bacula/commitdiff
Restore command fires off a Run command
authorKern Sibbald <kern@sibbald.com>
Fri, 9 Aug 2002 09:09:36 +0000 (09:09 +0000)
committerKern Sibbald <kern@sibbald.com>
Fri, 9 Aug 2002 09:09:36 +0000 (09:09 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@82 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/kernstodo
bacula/src/dird/Makefile.in
bacula/src/dird/query.sql
bacula/src/dird/sql_cmds.c
bacula/src/dird/ua.h
bacula/src/dird/ua_input.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_run.c
bacula/src/dird/ua_select.c
bacula/src/dird/ua_server.c
bacula/src/version.h

index e00fe785af6633841279d8b6b08a7e155f5cad4c..23d5076b2c116a91d2e1c834fe142099ee48d827 100644 (file)
@@ -13,7 +13,9 @@ To do:
 - Document better includes (does it cross file systems ?).
 - Document specifically how to add new File daemon to config files.
 - Document forcing a new tape to be used.
+- Document "Error in message.c:500 Mail program terminated in error.
 
+- Report volume write rate.
 - Fix db_get_job_volume_names() to return array of strings.
 - Report compression % and other compression statistics if turned on.
 - Add JobLevel in FD status (but make sure it is defined).
index 26d8308eb9ec0dcbf38d02f8ca77dad7691a9259..8dcae47617d0a910aa6e1931c859b04641668851 100644 (file)
@@ -93,20 +93,13 @@ install: all
        fi; \
        echo "${INSTALL_DATA} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf"; \
        ${INSTALL_DATA} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf
-       @srcconf=query.sql; \
-       if  test -f ${DESTDIR}${sysconfdir}/$$srcconf; then \
-          destconf=$$srcconf.new; \
-          echo "  ==> Found existing $$srcconf, installing new conf file as $$destconf"; \
-       else \
-          destconf=$$srcconf; \
-       fi; \
-       echo "${INSTALL_DATA} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf"; \
-       ${INSTALL_DATA} $$srcconf ${DESTDIR}${sysconfdir}/$$destconf
+       ${INSTALL_DATA} query.sql ${DESTDIR}${sysconfdir}/query.sql
 
 
 uninstall:
        (cd $(DESTDIR)$(sbindir); $(RMF) bacula-dir)
        (cd $(DESTDIR)$(sysconfdir); $(RMF) bacula-dir.conf)
+       (cd $(DESTDIR)$(sysconfdir); $(RMF) query.sql)
 
 
 
index 053ef77a78f2ce32fd9e67066cd284cbf48a2c1b..1bb698c00d02a4e5385605b1a7c92183eed8b265 100644 (file)
@@ -121,7 +121,7 @@ SELECT * from temp2;
 :List where a File is saved:
 *Enter Filename (no path):
 SELECT Job.JobId as JobId, Client.Name as Client,
- Path.Path||Filename.Name as Name,
+ Path.Path,Filename.Name,
  StartTime,Level,JobFiles,JobBytes
  FROM Client,Job,File,Filename,Path WHERE Client.ClientId=Job.ClientId
  AND JobStatus='T' AND Job.JobId=File.JobId
index 090229ab88dc09ecde4fe6411b15412e9107fa4c..05bcef6eb16e0155ed0a874ad888b7b6608604f7 100644 (file)
@@ -189,4 +189,6 @@ char *uar_list_temp =
    "SELECT JobId,Level,JobFiles,StartTime,VolumeName,StartFile,"
    "VolSessionId,VolSessionTime FROM temp";
 
-char *uar_sel_jobid_temp = "SELECT JobId from temp";
+char *uar_sel_jobid_temp = "SELECT JobId FROM temp";
+
+char *uar_sel_all_temp1 = "SELECT * FROM temp1";
index 8abee797a89443dc17c24d5ae8e5a7901e4e74ae..b5e28774e062857d5cb7ea1c61d6d18f8dae4a4a 100644 (file)
@@ -33,19 +33,19 @@ typedef struct s_ua_context {
    JCR *jcr;
    B_DB *db;
    CAT *catalog;
-   POOLMEM *cmd;                      /* return command/name buffer */
-   POOLMEM *args;                     /* command line arguments */
-   char *argk[MAX_ARGS];              /* argument keywords */
-   char *argv[MAX_ARGS];              /* argument values */
-   int argc;                          /* number of arguments */
-   char **prompt;                     /* list of prompts */
-   int max_prompts;                   /* max size of list */
-   int num_prompts;                   /* current number in list */
-   int auto_display_messages;         /* if set, display messages */
+   POOLMEM *cmd;                     /* return command/name buffer */
+   POOLMEM *args;                    /* command line arguments */
+   char *argk[MAX_ARGS];             /* argument keywords */
+   char *argv[MAX_ARGS];             /* argument values */
+   int argc;                         /* number of arguments */
+   char **prompt;                    /* list of prompts */
+   int max_prompts;                  /* max size of list */
+   int num_prompts;                  /* current number in list */
+   int auto_display_messages;        /* if set, display messages */
    int user_notified_msg_pending;     /* set when user notified */
-   int automount;                     /* if set, mount after label */
-   int quit;                          /* if set, quit */
-   int verbose;                       /* set for normal UA verbosity */
+   int automount;                    /* if set, mount after label */
+   int quit;                         /* if set, quit */
+   int verbose;                      /* set for normal UA verbosity */
 } UAContext;
 
 /* ua_cmds.c */
@@ -67,23 +67,24 @@ void prtit(void *ctx, char *msg);
 void bsendmsg(void *sock, char *fmt, ...);
 
 /* ua_select.c */
-STORE *select_storage_resource(UAContext *ua);
-JOB   *select_job_resource(UAContext *ua);
-int    select_pool_dbr(UAContext *ua, POOL_DBR *pr);
-CLIENT *select_client_resource(UAContext *ua);
+STORE  *select_storage_resource(UAContext *ua);
+JOB    *select_job_resource(UAContext *ua);
+JOB    *select_restore_job_resource(UAContext *ua);
+CLIENT *select_client_resource(UAContext *ua);
 FILESET *select_fs_resource(UAContext *ua);
-int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int    select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr);
+int    select_pool_dbr(UAContext *ua, POOL_DBR *pr);
 
-void   start_prompt(UAContext *ua, char *msg);
-void   add_prompt(UAContext *ua, char *prompt);
-int    do_prompt(UAContext *ua, char *msg, char *prompt);
-CAT   *get_catalog_resource(UAContext *ua);           
-STORE *get_storage_resource(UAContext *ua, char *cmd);
-int    get_media_type(UAContext *ua, char *MediaType);
-int    get_pool_dbr(UAContext *ua, POOL_DBR *pr);
-POOL  *get_pool_resource(UAContext *ua);
+void   start_prompt(UAContext *ua, char *msg);
+void   add_prompt(UAContext *ua, char *prompt);
+int    do_prompt(UAContext *ua, char *msg, char *prompt);
+CAT    *get_catalog_resource(UAContext *ua);          
+STORE  *get_storage_resource(UAContext *ua, char *cmd);
+int    get_media_type(UAContext *ua, char *MediaType);
+int    get_pool_dbr(UAContext *ua, POOL_DBR *pr);
+POOL   *get_pool_resource(UAContext *ua);
 CLIENT *get_client_resource(UAContext *ua);
-int get_job_dbr(UAContext *ua, JOB_DBR *jr);
+int    get_job_dbr(UAContext *ua, JOB_DBR *jr);
 
 int find_arg_keyword(UAContext *ua, char **list);
 int do_keyword_prompt(UAContext *ua, char *msg, char **list);
index 7aa673016045b70da17eb45b5c0d2cc0633af224..9a9382d3d03b542823d2703861faedec876f3f06 100644 (file)
@@ -51,7 +51,7 @@ int get_cmd(UAContext *ua, char *prompt)
       if (bnet_recv(sock) < 0) {
         return 0;
       }
-      ua->cmd = (char *) check_pool_memory_size(ua->cmd, sock->msglen+1);
+      ua->cmd = check_pool_memory_size(ua->cmd, sock->msglen+1);
       bstrncpy(ua->cmd, sock->msg, sock->msglen+1);
       strip_trailing_junk(ua->cmd);
       if (strcmp(ua->cmd, ".messages") == 0) {
@@ -131,12 +131,12 @@ char *next_arg(char **s)
 
 void parse_command_args(UAContext *ua)
 {
-   BSOCK *sock = ua->UA_sock;
    char *p, *n;
-   int i;
+   int i, len;
 
-   ua->args = (char *) check_pool_memory_size(ua->args, sock->msglen+1);
-   bstrncpy(ua->args, sock->msg, sock->msglen+1);
+   len = strlen(ua->cmd) + 1;
+   ua->args = check_pool_memory_size(ua->args, len);
+   bstrncpy(ua->args, ua->cmd, len);
    strip_trailing_junk(ua->args);
    ua->argc = 0;
    p = ua->args;
index 905c7b8955215e59cc5c1bec81130151d2c24441..252688bf83d3a87a40fc69ddb18e22b2a59bb56f 100644 (file)
@@ -36,6 +36,9 @@
 
 
 /* Imported functions */
+extern int runcmd(UAContext *ua, char *cmd);
+
+/* Imported variables */
 extern char *uar_list_jobs;
 extern char *uar_file;
 extern char *uar_sel_files;
@@ -48,6 +51,7 @@ extern char *uar_full;
 extern char *uar_inc;
 extern char *uar_list_temp;
 extern char *uar_sel_jobid_temp;
+extern char *uar_sel_all_temp1;
 
 /* Context for insert_tree_handler() */
 typedef struct s_tree_ctx {
@@ -58,12 +62,13 @@ typedef struct s_tree_ctx {
    UAContext *ua;
 } TREE_CTX;
 
-struct s_full_ctx {
+typedef struct s_jobids {
    btime_t JobTDate;
    uint32_t ClientId;
    uint32_t TotalFiles;
    char JobIds[200];
-};
+   CLIENT *client;
+} JobIds;
 
 
 /* FileIndex entry in bootstrap record */
@@ -86,6 +91,8 @@ typedef struct s_rbsr {
 /* Forward referenced functions */
 static RBSR *new_bsr();
 static void free_bsr(RBSR *bsr);
+static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd);
+static int  write_bsr_file(UAContext *ua, RBSR *bsr);
 static void print_bsr(UAContext *ua, RBSR *bsr);
 static int  complete_bsr(UAContext *ua, RBSR *bsr);
 static int insert_tree_handler(void *ctx, int num_fields, char **row);
@@ -93,7 +100,7 @@ static void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex);
 static int last_full_handler(void *ctx, int num_fields, char **row);
 static int jobid_handler(void *ctx, int num_fields, char **row);
 static int next_jobid_from_list(char **p, uint32_t *JobId);
-static int user_select_jobids(UAContext *ua, struct s_full_ctx *full);
+static int user_select_jobids(UAContext *ua, JobIds *ji);
 static void user_select_files(TREE_CTX *tree);
 
 
@@ -105,31 +112,62 @@ int restorecmd(UAContext *ua, char *cmd)
 {
    POOLMEM *query;
    TREE_CTX tree;
-   JobId_t JobId;
+   JobId_t JobId, last_JobId;
    char *p;
    RBSR *bsr;
    char *nofname = "";
-   struct s_full_ctx full;
+   JobIds ji;
+   JOB *job = NULL;
+   JOB *restore_job = NULL;
+   int restore_jobs = 0;
 
    if (!open_db(ua)) {
       return 0;
    }
 
    memset(&tree, 0, sizeof(TREE_CTX));
-   memset(&full, 0, sizeof(full));
+   memset(&ji, 0, sizeof(ji));
+
+   /* Ensure there is at least one Restore Job */
+   LockRes();
+   while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
+      if (job->JobType == JT_RESTORE) {
+        if (!restore_job) {
+           restore_job = job;
+        }
+        restore_jobs++;
+      }
+   }
+   UnlockRes();
+   if (!restore_jobs) {
+      bsendmsg(ua, _(
+         "No Restore Job Resource found. You must create at least\n"
+         "one before running this command.\n"));
+      return 0;
+   }
 
-   if (!user_select_jobids(ua, &full)) {
+
+   if (!user_select_jobids(ua, &ji)) {
       return 0;
    }
 
    /* 
     * Build the directory tree 
     */
-   tree.root = new_tree(full.TotalFiles);
+   tree.root = new_tree(ji.TotalFiles);
    tree.root->fname = nofname;
    tree.ua = ua;
    query = get_pool_memory(PM_MESSAGE);
-   for (p=full.JobIds; next_jobid_from_list(&p, &JobId) > 0; ) {
+   last_JobId = 0;
+   /*
+    * For display purposes, the same JobId, with different volumes may
+    * appear more than once, however, we only insert it once.
+    */
+   for (p=ji.JobIds; next_jobid_from_list(&p, &JobId) > 0; ) {
+      if (JobId == last_JobId) {            
+        continue;                    /* eliminate duplicate JobIds */
+      }
+      last_JobId = JobId;
       bsendmsg(ua, _("Building directory tree for JobId %u ...\n"), JobId);
       Mmsg(&query, uar_sel_files, JobId);
       if (!db_sql_query(ua->db, query, insert_tree_handler, (void *)&tree)) {
@@ -160,11 +198,35 @@ int restorecmd(UAContext *ua, char *cmd)
    if (bsr->JobId) {
       complete_bsr(ua, bsr);         /* find Vol, SessId, SessTime from JobIds */
       print_bsr(ua, bsr);
+      write_bsr_file(ua, bsr);
    } else {
       bsendmsg(ua, _("No files selected to restore.\n"));
    }
    free_bsr(bsr);
 
+   if (restore_jobs == 1) {
+      job = restore_job;
+   } else {
+      job = select_restore_job_resource(ua);
+   }
+   if (!job) {
+      bsendmsg(ua, _("No Restore Job resource found!\n"));
+      return 0;
+   }
+
+   if (ji.client) {
+      Mmsg(&ua->cmd, "run job=%s client=%s bootstrap=%s/restore.bsr",
+        job->hdr.name, ji.client->hdr.name, working_directory);
+   } else {
+      Mmsg(&ua->cmd, "run job=%s bootstrap=%s/restore.bsr",
+        job->hdr.name, working_directory);
+   }
+
+   Dmsg1(400, "Submitting: %s\n", ua->cmd);
+   
+   parse_command_args(ua);
+   runcmd(ua, ua->cmd);
+
    bsendmsg(ua, _("Restore command done.\n"));
    return 1;
 }
@@ -174,7 +236,7 @@ int restorecmd(UAContext *ua, char *cmd)
  *  select a list of JobIds from which he will subsequently
  *  select which files are to be restored.
  */
-static int user_select_jobids(UAContext *ua, struct s_full_ctx *full)
+static int user_select_jobids(UAContext *ua, JobIds *ji)
 {
    char *p;
    JobId_t JobId;
@@ -222,7 +284,7 @@ static int user_select_jobids(UAContext *ua, struct s_full_ctx *full)
          if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) {
            return 0;
         }
-        bstrncpy(full->JobIds, ua->cmd, sizeof(full->JobIds));
+        bstrncpy(ji->JobIds, ua->cmd, sizeof(ji->JobIds));
         break;
       case 3:                        /* Enter an SQL list command */
          if (!get_cmd(ua, _("Enter SQL list command: "))) {
@@ -240,11 +302,11 @@ static int user_select_jobids(UAContext *ua, struct s_full_ctx *full)
         if (!db_sql_query(ua->db, uar_create_temp1, NULL, NULL)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
-         if (!get_cmd(ua, _("Enter Client name: "))) {
+        if (!(ji->client = get_client_resource(ua))) {
            return 0;
         }
         query = get_pool_memory(PM_MESSAGE);
-        Mmsg(&query, uar_last_full, ua->cmd);
+        Mmsg(&query, uar_last_full, ji->client->hdr.name);
         /* Find JobId of full Backup of system */
         if (!db_sql_query(ua->db, query, NULL, NULL)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
@@ -256,18 +318,18 @@ static int user_select_jobids(UAContext *ua, struct s_full_ctx *full)
          /* Note, this is needed as I don't seem to get the callback
          * from the call just above.
          */
-         if (!db_sql_query(ua->db, "SELECT * from temp1", last_full_handler, (void *)full)) {
+        if (!db_sql_query(ua->db, uar_sel_all_temp1, last_full_handler, (void *)ji)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
         /* Now find all Incremental Jobs */
-        Mmsg(&query, uar_inc, (uint32_t)full->JobTDate, full->ClientId);
+        Mmsg(&query, uar_inc, (uint32_t)ji->JobTDate, ji->ClientId);
         if (!db_sql_query(ua->db, query, NULL, NULL)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
         free_pool_memory(query);
         db_list_sql_query(ua->db, uar_list_temp, prtit, ua, 1);
 
-        if (!db_sql_query(ua->db, uar_sel_jobid_temp, jobid_handler, (void *)full)) {
+        if (!db_sql_query(ua->db, uar_sel_jobid_temp, jobid_handler, (void *)ji)) {
             bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
         db_sql_query(ua->db, uar_del_temp, NULL, NULL);
@@ -278,16 +340,16 @@ static int user_select_jobids(UAContext *ua, struct s_full_ctx *full)
       }
    }
 
-   if (*full->JobIds == 0) {
+   if (*ji->JobIds == 0) {
       bsendmsg(ua, _("No Jobs selected.\n"));
       return 0;
    }
-   bsendmsg(ua, _("You have selected the following JobId: %s\n"), full->JobIds);
+   bsendmsg(ua, _("You have selected the following JobId: %s\n"), ji->JobIds);
 
    memset(&jr, 0, sizeof(JOB_DBR));
 
-   full->TotalFiles = 0;
-   for (p=full->JobIds; ; ) {
+   ji->TotalFiles = 0;
+   for (p=ji->JobIds; ; ) {
       int stat = next_jobid_from_list(&p, &JobId);
       if (stat < 0) {
          bsendmsg(ua, _("Invalid JobId in list.\n"));
@@ -301,7 +363,7 @@ static int user_select_jobids(UAContext *ua, struct s_full_ctx *full)
          bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db));
         return 0;
       }
-      full->TotalFiles += jr.JobFiles;
+      ji->TotalFiles += jr.JobFiles;
    }
    return 1;
 }
@@ -314,7 +376,7 @@ static int next_jobid_from_list(char **p, uint32_t *JobId)
 
    jobid[0] = 0;
    for (i=0; i<(int)sizeof(jobid); i++) {
-      if (*q == ',') {
+      if (*q == ',' || *q == 0) {
         q++;
         break;
       }
@@ -326,9 +388,6 @@ static int next_jobid_from_list(char **p, uint32_t *JobId)
    }
    *p = q;
    *JobId = strtoul(jobid, NULL, 10);
-   if (errno) {
-      return 0;
-   }
    return 1;
 }
 
@@ -337,13 +396,13 @@ static int next_jobid_from_list(char **p, uint32_t *JobId)
  */
 static int jobid_handler(void *ctx, int num_fields, char **row)
 {
-   struct s_full_ctx *full = (struct s_full_ctx *)ctx;
+   JobIds *ji = (JobIds *)ctx;
 
-   if (strlen(full->JobIds)+strlen(row[0])+2 < sizeof(full->JobIds)) {
-      if (full->JobIds[0] != 0) {
-         strcat(full->JobIds, ",");
+   if (strlen(ji->JobIds)+strlen(row[0])+2 < sizeof(ji->JobIds)) {
+      if (ji->JobIds[0] != 0) {
+         strcat(ji->JobIds, ",");
       }
-      strcat(full->JobIds, row[0]);
+      strcat(ji->JobIds, row[0]);
    }
 
    return 0;
@@ -355,10 +414,10 @@ static int jobid_handler(void *ctx, int num_fields, char **row)
  */
 static int last_full_handler(void *ctx, int num_fields, char **row)
 {
-   struct s_full_ctx *full = (struct s_full_ctx *)ctx;
+   JobIds *ji = (JobIds *)ctx;
 
-   full->JobTDate = atoi(row[1]);
-   full->ClientId = atoi(row[2]);
+   ji->JobTDate = atoi(row[1]);
+   ji->ClientId = atoi(row[2]);
 
    return 0;
 }
@@ -391,8 +450,8 @@ static struct cmdstruct commands[] = {
  { N_("pwd"),        pwdcmd,       _("print directory")},
  { N_("rm"),         rmcmd,        _("remove a file")},
  { N_("remove"),     rmcmd,        _("remove a file")},
- { N_("done"),       quitcmd,      _("quit")},
- { N_("exit"),       quitcmd,      _("exit = quit")},
+ { N_("done"),       quitcmd,      _("leave file selection mode")},
+ { N_("exit"),       quitcmd,      _("exit = done")},
  { N_("?"),          helpcmd,      _("print help")},    
             };
 #define comsize (sizeof(commands)/sizeof(struct cmdstruct))
@@ -406,6 +465,11 @@ static struct cmdstruct commands[] = {
 static void user_select_files(TREE_CTX *tree)
 {
    char cwd[2000];
+
+   bsendmsg(tree->ua, _( 
+      "You are now entering file selection mode where you add and\n"
+      "remove files to be restored. All files are initially added.\n"
+      "Enter done to leave this mode.\n\n"));
    /*
     * Enter interactive command handler allowing selection
     *  of individual files.
@@ -432,7 +496,7 @@ static void user_select_files(TREE_CTX *tree)
            break;
         }
       if (!found) {
-         bsendmsg(tree->ua, _("Illegal command. Enter \"done\" to end.\n"));
+         bsendmsg(tree->ua, _("Illegal command. Enter \"done\" to exit.\n"));
       }
       if (!stat) {
         break;
@@ -440,7 +504,9 @@ static void user_select_files(TREE_CTX *tree)
    }
 }
 
-
+/*
+ * Create new FileIndex entry for BSR 
+ */
 static RBSR_FINDEX *new_findex() 
 {
    RBSR_FINDEX *fi = (RBSR_FINDEX *)malloc(sizeof(RBSR_FINDEX));
@@ -448,6 +514,7 @@ static RBSR_FINDEX *new_findex()
    return fi;
 }
 
+/* Free all BSR FileIndex entries */
 static void free_findex(RBSR_FINDEX *fi)
 {
    if (fi) {
@@ -456,6 +523,19 @@ static void free_findex(RBSR_FINDEX *fi)
    }
 }
 
+static void write_findex(UAContext *ua, RBSR_FINDEX *fi, FILE *fd) 
+{
+   if (fi) {
+      if (fi->findex == fi->findex2) {
+         fprintf(fd, "FileIndex=%d\n", fi->findex);
+      } else {
+         fprintf(fd, "FileIndex=%d-%d\n", fi->findex, fi->findex2);
+      }
+      write_findex(ua, fi->next, fd);
+   }
+}
+
+
 static void print_findex(UAContext *ua, RBSR_FINDEX *fi)
 {
    if (fi) {
@@ -468,6 +548,7 @@ static void print_findex(UAContext *ua, RBSR_FINDEX *fi)
    }
 }
 
+/* Create a new bootstrap record */
 static RBSR *new_bsr()
 {
    RBSR *bsr = (RBSR *)malloc(sizeof(RBSR));
@@ -475,6 +556,7 @@ static RBSR *new_bsr()
    return bsr;
 }
 
+/* Free the entire BSR */
 static void free_bsr(RBSR *bsr)
 {
    if (bsr) {
@@ -489,13 +571,12 @@ static void free_bsr(RBSR *bsr)
 
 /*
  * Complete the BSR by filling in the VolumeName and
- *  VolSessionId and VolSessionTime
+ *  VolSessionId and VolSessionTime using the JobId
  */
 static int complete_bsr(UAContext *ua, RBSR *bsr)
 {
    JOB_DBR jr;
    char VolumeNames[1000];           /* ****FIXME**** */
-   char *p;
 
    if (bsr) {
       memset(&jr, 0, sizeof(jr));
@@ -510,15 +591,49 @@ static int complete_bsr(UAContext *ua, RBSR *bsr)
          bsendmsg(ua, _("Unable to get Job Volumes. ERR=%s\n"), db_strerror(ua->db));
         return 0;
       }
-      if ((p = strchr(VolumeNames, '|'))) {
-        *p = 0;                      /* take first volume */
-      }
       bsr->VolumeName = bstrdup(VolumeNames);
       return complete_bsr(ua, bsr->next);
    }
    return 1;
 }
 
+/*
+ * Write the bootstrap record to file
+ */
+static int write_bsr_file(UAContext *ua, RBSR *bsr)
+{
+   FILE *fd;
+   POOLMEM *fname = get_pool_memory(PM_MESSAGE);
+   int stat;
+
+   Mmsg(&fname, "%s/restore.bsr", working_directory);
+   fd = fopen(fname, "w+");
+   if (!fd) {
+      bsendmsg(ua, _("Unable to create bootstrap file %s. ERR=%s\n"), 
+        fname, strerror(errno));
+      free_pool_memory(fname);
+      return 0;
+   }
+   write_bsr(ua, bsr, fd);
+   stat = !ferror(fd);
+   fclose(fd);
+   bsendmsg(ua, _("Bootstrap records written to %s\n"), fname);
+   free_pool_memory(fname);
+   return stat;
+}
+
+static void write_bsr(UAContext *ua, RBSR *bsr, FILE *fd)
+{
+   if (bsr) {
+      if (bsr->VolumeName) {
+         fprintf(fd, "VolumeName=%s\n", bsr->VolumeName);
+      }
+      fprintf(fd, "VolSessionId=%u\n", bsr->VolSessionId);
+      fprintf(fd, "VolSessionTime=%u\n", bsr->VolSessionTime);
+      write_findex(ua, bsr->fi, fd);
+      write_bsr(ua, bsr->next, fd);
+   }
+}
 
 static void print_bsr(UAContext *ua, RBSR *bsr)
 {
@@ -526,7 +641,6 @@ static void print_bsr(UAContext *ua, RBSR *bsr)
       if (bsr->VolumeName) {
          bsendmsg(ua, "VolumeName=%s\n", bsr->VolumeName);
       }
-//    bsendmsg(ua, "JobId=%u\n", bsr->JobId);
       bsendmsg(ua, "VolSessionId=%u\n", bsr->VolSessionId);
       bsendmsg(ua, "VolSessionTime=%u\n", bsr->VolSessionTime);
       print_findex(ua, bsr->fi);
@@ -548,7 +662,7 @@ static void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex)
    if (findex == 0) {
       return;                        /* probably a dummy directory */
    }
-
+   
    if (!bsr->fi) {                   /* if no FI add one */
       /* This is the first FileIndex item in the chain */
       bsr->fi = new_findex();
@@ -603,7 +717,6 @@ static void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex)
         RBSR_FINDEX *nfi;     
         fi->findex2 = findex;
         if (fi->next && ((findex+1) == fi->next->findex)) { 
-            Dmsg1(400, "Coallase %d\n", findex);
            nfi = fi->next;
            fi->findex2 = nfi->findex2;
            fi->next = nfi->next;
@@ -629,6 +742,13 @@ static void add_findex(RBSR *bsr, uint32_t JobId, int32_t findex)
    return;
 }
 
+/*
+ * This callback routine is responsible for inserting the
+ *  items it gets into the directory tree. For each JobId selected
+ *  this routine is called once for each file. We do not allow
+ *  duplicate filenames, but instead keep the info from the most
+ *  recent file entered (i.e. the JobIds are assumed to be sorted)
+ */
 static int insert_tree_handler(void *ctx, int num_fields, char **row)
 {
    TREE_CTX *tree = (TREE_CTX *)ctx;
@@ -660,11 +780,7 @@ static int insert_tree_handler(void *ctx, int num_fields, char **row)
    new_node->FileIndex = atoi(row[2]);
    new_node->JobId = atoi(row[3]);
    new_node->type = type;
-#ifdef xxxxxxx
-   if (((tree->cnt) % 10000) == 0) {
-      bsendmsg(tree->ua, "%d ", tree->cnt);
-   }
-#endif
+   new_node->extract = 1;            /* extract all by default */
    tree->cnt++;
    return 0;
 }
@@ -672,7 +788,8 @@ static int insert_tree_handler(void *ctx, int num_fields, char **row)
 
 /*
  * Set extract to value passed. We recursively walk
- *  down the tree setting all children.
+ *  down the tree setting all children if the 
+ *  node is a directory.
  */
 static void set_extract(TREE_NODE *node, int value)
 {
@@ -733,7 +850,7 @@ static int findcmd(UAContext *ua, TREE_CTX *tree)
       for (TREE_NODE *node=first_tree_node(tree->root); node; node=next_tree_node(node)) {
         if (fnmatch(ua->argk[i], node->fname, 0) == 0) {
            tree_getpath(node, cwd, sizeof(cwd));
-            bsendmsg(ua, "%s\n", cwd);
+            bsendmsg(ua, "%s%s\n", node->extract?"*":"", cwd);
         }
       }
    }
index 594f9f079393f14bbfa51aa75b49c10964fc80ec..c304d8ca94d83e0e9a97a18d64e8c9dec93663cc 100644 (file)
@@ -77,13 +77,14 @@ int runcmd(UAContext *ua, char *cmd)
    where = NULL;
    client_name = NULL;
    fileset_name = NULL;
+   bootstrap = NULL;
 
    Dmsg1(20, "run: %s\n", ua->UA_sock->msg);
 
    for (i=1; i<ua->argc; i++) {
       found = False;
       Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
-      for (j=0; kw[j]; j++) {
+      for (j=0; !found && kw[j]; j++) {
         if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
            if (!ua->argv[i]) {
                bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
@@ -145,20 +146,20 @@ int runcmd(UAContext *ua, char *cmd)
                     return 1;
                  }
                  where = ua->argv[i];
-                 break;
                  found = True;
+                 break;
               case 7: /* bootstrap */
                  if (bootstrap) {
                      bsendmsg(ua, _("Bootstrap specified twice.\n"));
                     return 1;
                  }
                  bootstrap = ua->argv[i];
-                 break;
                  found = True;
+                 break;
               default:
                  break;
            }
-        }
+        } /* end strcase compare */
       } /* end keyword loop */
       if (!found) {
          Dmsg1(200, "%s not found\n", ua->argk[i]);
@@ -170,7 +171,7 @@ int runcmd(UAContext *ua, char *cmd)
            job_name = ua->argk[i];   /* use keyword as job name */
             Dmsg1(200, "Set jobname=%s\n", job_name);
         } else {
-            bsendmsg(ua, _("Invalid keyword %s\n"), ua->argk[i]);
+            bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
            return 1;
         }
       }
@@ -278,7 +279,6 @@ Storage:  %s\n"),
 JobName:    %s\n\
 Bootstrap:  %s\n\
 Where:      %s\n\
-Level:      %s\n\
 FileSet:    %s\n\
 Client:     %s\n\
 Storage:    %s\n\
@@ -286,7 +286,6 @@ JobId:      %s\n"),
                 job->hdr.name,
                 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, 
@@ -371,6 +370,8 @@ JobId:      %s\n"),
               break;
            }
            goto try_again;
+        } else {
+            bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
         }
         goto try_again;
       case 1:
index 7948f143b3a9f31f4089ffa3348cb18417063416..ce5fb94d4662ece5786e88a91724cce6ee511725 100644 (file)
@@ -197,6 +197,28 @@ JOB *select_job_resource(UAContext *ua)
    return job;
 }
 
+/* 
+ * Select a Restore Job resource from prompt list
+ */
+JOB *select_restore_job_resource(UAContext *ua)
+{
+   char name[MAX_NAME_LENGTH];   
+   JOB *job = NULL;
+
+   start_prompt(ua, _("The defined Restore Job resources are:\n"));
+   LockRes();
+   while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
+      if (job->JobType == JT_RESTORE) {
+        add_prompt(ua, job->hdr.name);
+      }
+   }
+   UnlockRes();
+   do_prompt(ua, _("Select Restore Job"), name);
+   job = (JOB *)GetResWithName(R_JOB, name);
+   return job;
+}
+
+
 
 /* 
  * Select a client resource from prompt list
index 6884ae4ff55eaa12294840de7f293258413fda64..a5aa83324028a6151f13535719a201c99af4ce08 100644 (file)
@@ -91,7 +91,6 @@ static void *connect_thread(void *arg)
 static void handle_UA_client_request(void *arg)
 {
    int stat;
-   static char cmd[1000];
    UAContext ua;
    BSOCK *UA_sock = (BSOCK *) arg;
 
@@ -118,17 +117,18 @@ static void handle_UA_client_request(void *arg)
    while (!ua.quit) {
       stat = bnet_recv(ua.UA_sock);
       if (stat > 0) {
-        bstrncpy(cmd, ua.UA_sock->msg, sizeof(cmd));
+        ua.cmd = check_pool_memory_size(ua.cmd, ua.UA_sock->msglen+1);
+        bstrncpy(ua.cmd, ua.UA_sock->msg, ua.UA_sock->msglen+1);
         parse_command_args(&ua);
          if (ua.argc > 0 && ua.argk[0][0] == '.') {
-           do_a_dot_command(&ua, cmd);
+           do_a_dot_command(&ua, ua.cmd);
         } else {
-           do_a_command(&ua, cmd);
+           do_a_command(&ua, ua.cmd);
         }
         if (!ua.quit) {
            if (ua.auto_display_messages) {
-               strcpy(cmd, "messages");
-              qmessagescmd(&ua, cmd);
+               strcpy(ua.cmd, "messages");
+              qmessagescmd(&ua, ua.cmd);
               ua.user_notified_msg_pending = FALSE;
            } else if (!ua.user_notified_msg_pending && console_msg_pending) {
                bsendmsg(&ua, _("You have messages.\n"));
index 1c587928b59e1cd7224a8ad87a01f7a216d987a0..fba7113f220ede659b214218099d122be5d82b55 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.24"
 #define VSTRING "1"
-#define DATE    "07 August 2002"
-#define LSMDATE "07Aug02"
+#define DATE    "08 August 2002"
+#define LSMDATE "08Aug02"
 
 /* Debug flags */
 #define DEBUG 1