]> git.sur5r.net Git - bacula/bacula/commitdiff
restore cmd + misc -- see kes04Aug02
authorKern Sibbald <kern@sibbald.com>
Sun, 4 Aug 2002 17:12:56 +0000 (17:12 +0000)
committerKern Sibbald <kern@sibbald.com>
Sun, 4 Aug 2002 17:12:56 +0000 (17:12 +0000)
git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@75 91ce42f0-d328-0410-95d8-f526ca767f89

30 files changed:
bacula/ChangeLog
bacula/kernstodo
bacula/src/baconfig.h
bacula/src/cats/protos.h
bacula/src/cats/sql.c
bacula/src/cats/sql_create.c
bacula/src/cats/sql_update.c
bacula/src/console/console.c
bacula/src/dird/catreq.c
bacula/src/dird/fd_cmds.c
bacula/src/dird/getmsg.c
bacula/src/dird/job.c
bacula/src/dird/msgchan.c
bacula/src/dird/restore.c
bacula/src/dird/ua_input.c
bacula/src/dird/ua_prune.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_server.c
bacula/src/filed/backup.c
bacula/src/filed/job.c
bacula/src/filed/status.c
bacula/src/lib/bnet.c
bacula/src/lib/bsock.h
bacula/src/lib/message.c
bacula/src/lib/protos.h
bacula/src/lib/util.c
bacula/src/stored/dircmd.c
bacula/src/stored/fd_cmds.c
bacula/src/stored/read.c
bacula/src/version.h

index ebfe6c04064b966445c78c908050bc3bfde938bd..98adef6ffff395672060d067d6d9667f25f3397a 100644 (file)
@@ -1,6 +1,6 @@
 2002-07-26 Release 1.23a
 - Fix segmentation fault is FD status.
-- Turn off TRANACTIONs for SQLite.                        
+- Turn off TRANSACTIONs for SQLite.                        
 
 2002-07-23 Release 1.23
   From kes22Jul02
index 65ada9928f5361c25d48382005fdc1eb978ba1f9..e00fe785af6633841279d8b6b08a7e155f5cad4c 100644 (file)
@@ -1,6 +1,9 @@
                  Kern's ToDo List
-                  25 July 2002
+                  3 August 2002
 
+Irix conversion notes:
+- no uuencode
+- no hostname
 To do:    
 - Document passwords.
 - Document running multiple Jobs
index 0b9213125aacf9c77210f72928e44cf5e83cfe11..dfd21d6b49fdf728f0c5a2b7f91efbebdd9064c8 100644 (file)
@@ -75,7 +75,9 @@
 #define TAPE_BSIZE 1024
 #if !defined(DEV_BSIZE) && defined(BSIZE)
 #define DEV_BSIZE BSIZE
-#else 
+#endif
+
+#ifndef DEV_BSIZE
 #define DEV_BSIZE 512
 #endif
 
index c3ca48c5a33478d04ad4f068965a6273ab632ff8..a38e5ce936bede54cc80cdde3b8942929bfce6cf 100644 (file)
@@ -41,6 +41,8 @@ int db_sql_query(B_DB *mdb, char *cmd, DB_RESULT_HANDLER *result_handler, void *
 int check_tables_version(B_DB *mdb);
 void _db_unlock(char *file, int line, B_DB *mdb);
 void _db_lock(char *file, int line, B_DB *mdb);
+void db_start_transaction(B_DB *mdb);
+void db_end_transaction(B_DB *mdb);
 
 /* create.c */
 int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar);
@@ -88,7 +90,7 @@ int  db_update_job_start_record(B_DB *db, JOB_DBR *jr);
 int  db_update_job_end_record(B_DB *db, JOB_DBR *jr);
 int  db_update_pool_record(B_DB *db, POOL_DBR *pr);
 int  db_update_media_record(B_DB *db, MEDIA_DBR *mr);
-int  db_add_MD5_to_file_record(B_DB *mdb, FileId_t FileId, char *MD5);  
+int  db_add_MD5_to_file_record(B_DB *mdb, FileId_t FileId, char *MD5); 
 int  db_mark_file_record(B_DB *mdb, FileId_t FileId, JobId_t JobId);
 
 #endif /* __SQL_PROTOS_H */
index ece888e7d6259846b53a928f1943298b18a14788..c16f59e6cccee3cf7c96ffd5b18eebd2a088e543 100644 (file)
@@ -219,5 +219,42 @@ void _db_unlock(char *file, int line, B_DB *mdb)
    }
 }    
 
+/*
+ * Start a transaction. This groups inserts and makes things
+ *  much more efficient. Usually started when inserting 
+ *  file attributes.
+ */
+void db_start_transaction(B_DB *mdb)
+{
+#ifdef HAVE_SQLITE
+   db_lock(mdb);
+   /* Allow only 10,000 changes per transaction */
+   if (mdb->transaction && mdb->changes > 10000) {
+      db_end_transaction(mdb);
+   }
+   if (!mdb->transaction) {   
+      my_sqlite_query(mdb, "BEGIN");  /* begin transaction */
+      Dmsg0(000, "Start SQLite transaction\n");
+      mdb->transaction = 1;
+   }
+   db_unlock(mdb);
+#endif
+
+}
+
+void db_end_transaction(B_DB *mdb)
+{
+#ifdef HAVE_SQLITE
+   db_lock(mdb);
+   if (mdb->transaction) {
+      my_sqlite_query(mdb, "COMMIT"); /* end transaction */
+      mdb->transaction = 0;
+      Dmsg1(000, "End SQLite transaction changes=%d\n", mdb->changes);
+   }
+   mdb->changes = 0;
+   db_unlock(mdb);
+#endif
+}
+
 
 #endif /* HAVE_MYSQL | HAVE_SQLITE */
index e5502af60866641fe332751a71286c1af79f02c6..7674ec14a3ca643dedb59111130a2950af6daa32 100644 (file)
@@ -505,13 +505,6 @@ int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar)
    Dmsg0(50, "db_create_file_record\n");
 
    Dmsg3(100, "Path=%s File=%s FilenameId=%d\n", spath, file, ar->FilenameId);
-#ifdef HAVE_SQLITE
-   if (mdb->transaction && mdb->changes > 10000) {
-      my_sqlite_query(mdb, "COMMIT");    /* end transaction */
-      my_sqlite_query(mdb, "BEGIN");     /* start new transaction */
-      mdb->changes = 0;
-   }
-#endif
    return 1;
 }
 
index 1d778acbc3641843de74ad06f4c68bf6ef28dace..834e6e017fd86e5928de71091da6cbe1956780a8 100644 (file)
@@ -107,11 +107,6 @@ ClientId=%d, JobTDate=%s WHERE JobId=%d",
       (char)(jr->Level), dt, jr->ClientId, edit_uint64(JobTDate, ed1), jr->JobId);
    stat = UPDATE_DB(mdb, mdb->cmd);
    db_unlock(mdb);
-#ifdef HAVE_SQLITE
-   /******FIXME***** do this machine independently */
-// my_sqlite_query(mdb, "BEGIN");     /* begin transaction */
-// mdb->transaction = 1;
-#endif
    mdb->changes = 0;
    return stat;
 }
@@ -149,10 +144,6 @@ VolSessionTime=%d, PoolId=%d, FileSetId=%d, JobTDate=%s WHERE JobId=%d",
       jr->PoolId, jr->FileSetId, edit_uint64(JobTDate, ed2), jr->JobId);
 
    stat = UPDATE_DB(mdb, mdb->cmd);
-#ifdef HAVE_SQLITE
-   my_sqlite_query(mdb, "COMMIT");    /* end transaction */
-   mdb->transaction = 0;
-#endif
    db_unlock(mdb);
    return stat;
 }
index fe0aac5b2f1212668d8ab0e6ce24c085a829e2ff..616cbaf980a124c7104162157446d0472a8796cb 100644 (file)
@@ -130,7 +130,7 @@ static void read_and_process_input(FILE *input, BSOCK *UA_sock)
            break;                    /* error */
         }
       }
-      if (strcmp(UA_sock->msg, "quit") == 0 || strcmp(UA_sock->msg, "exit") == 0) {
+      if (strcmp(UA_sock->msg, ".quit") == 0 || strcmp(UA_sock->msg, ".exit") == 0) {
         break;
       }
       while ((stat = bnet_recv(UA_sock)) > 0) {
index 7d7b21b599fbb134f2f4b0e01b649aab72e4d41b..f9b7960f718e9f88181538bf229d6807e109ae17 100644 (file)
@@ -235,6 +235,7 @@ void catalog_update(JCR *jcr, BSOCK *bs, char *msg)
    if (!jcr->pool->catalog_files) {
       return;
    }
+   db_start_transaction(jcr->db);     /* start transaction if not already open */
    skip_nonspaces(&p);               /* UpdCat */
    skip_spaces(&p);
    skip_nonspaces(&p);               /* Job=nnn */
index 85f990c2afcb0ca326e16e06a2e83ae2accb5114..fb5f8a953efe3254f201c28ee3792dd2d4d369c3 100644 (file)
@@ -131,7 +131,7 @@ int send_include_list(JCR *jcr)
         return 0;
       }
    }
-   bnet_sig(fd, BNET_EOF);
+   bnet_sig(fd, BNET_EOD);           /* end of data */
    fd->msg = msgsave;
    if (!response(fd, OKinc, "Include")) {
       jcr->JobStatus = JS_ErrorTerminated;
@@ -166,7 +166,7 @@ int send_exclude_list(JCR *jcr)
         return 0;
       }
    }
-   bnet_sig(fd, BNET_EOF);
+   bnet_sig(fd, BNET_EOD);
    fd->msg = msgsave;
    if (!response(fd, OKexc, "Exclude")) {
       jcr->JobStatus = JS_ErrorTerminated;
index ca6273cc02aa0697aaf84ebb54712e067627e5e4..7c1caf51185270c871ce72469a1cff2e20097221 100644 (file)
@@ -80,7 +80,6 @@ int32_t bget_msg(BSOCK *bs, int rtn)
       if (n == 0) {                  /* handle signal */
         /* 0 return from bnet_recv() => network signal */
         switch (bs->msglen) {
-           case BNET_EOF:               /* deprecated */
            case BNET_EOD:               /* end of data */
               return 0;
            case BNET_EOD_POLL:
index ec96726857cc13016f7820fda2d3882558debfd4..7c9678f60e6c2d88043b6c602033ed9ff4473634 100644 (file)
@@ -183,6 +183,7 @@ static void job_thread(void *arg)
         case JT_ADMIN:
            /* No actual job */
            do_autoprune(jcr);
+           jcr->JobStatus = JS_Terminated;
            break;
         default:
             Dmsg1(0, "Unimplemented job type: %d\n", jcr->JobType);
index 324e0d4389780b99cdb83d57b034b7f1eff81d32..82919650a9d7f566214007a6e2677fdcef2de852 100644 (file)
@@ -183,6 +183,7 @@ static void msg_thread_cleanup(void *arg)
 {
    JCR *jcr = (JCR *)arg;
    Dmsg0(200, "End msg_thread\n");
+   db_end_transaction(jcr->db);       /* terminate any open transaction */
    P(jcr->mutex);
    jcr->msg_thread_done = TRUE;
    pthread_cond_broadcast(&jcr->term_wait); /* wakeup any waiting threads */
index bd510d8e0eedf53819de4bcc1340885d2dc6236d..5f3a49dea2b8193af34b85985548c6e8bb1db9a8 100644 (file)
@@ -298,7 +298,7 @@ static int send_bootstrap_file(JCR *jcr)
       fd->msglen = Mmsg(&fd->msg, "%s", buf);
       bnet_send(fd);      
    }
-   bnet_sig(fd, BNET_EOF);
+   bnet_sig(fd, BNET_EOD);
    fclose(bs);
    if (!response(fd, OKbootstrap, "Bootstrap")) {
       jcr->JobStatus = JS_ErrorTerminated;
index 85d7feefdd49fa0608da896b2820202441de017a..7aa673016045b70da17eb45b5c0d2cc0633af224 100644 (file)
@@ -52,8 +52,7 @@ int get_cmd(UAContext *ua, char *prompt)
         return 0;
       }
       ua->cmd = (char *) check_pool_memory_size(ua->cmd, sock->msglen+1);
-      strcpy(ua->cmd, sock->msg);
-      ua->cmd[sock->msglen] = 0;
+      bstrncpy(ua->cmd, sock->msg, sock->msglen+1);
       strip_trailing_junk(ua->cmd);
       if (strcmp(ua->cmd, ".messages") == 0) {
         qmessagescmd(ua, ua->cmd);
@@ -74,31 +73,39 @@ int get_cmd(UAContext *ua, char *prompt)
  */
 char *next_arg(char **s)
 {
-   char *p, *n;
+   char *p, *q, *n;
 
+   Dmsg1(400, "Next arg=%s\n", *s);
    /* skip past spaces to next arg */
-   for (p=*s; *p && *p == ' '; p++)
-      {}
+   for (p=*s; *p && *p == ' '; ) {
+      p++;
+   }   
    /* Determine start of argument */
    if (*p == '"') {
-      n = p+1;                       /* skip leading quote */
+      Dmsg0(400, "Start with quote.\n");
+      for (n = q = ++p; *p && *p != '"'; ) {
+         if (*p == '\\') {
+           p++;
+        }
+        *q++ = *p++;
+      }
+      p++;                           /* skip terminating quote */
+      for ( ; *p && *p != ' '; ) {
+        *q++ = *p++;
+      }
+      *q = 0;
    } else {
+      /* Scan argment and terminate it */
       n = p;
-   }
-   /* Scan argment and terminate it */
-   for ( ; *p && *p != ' '; p++) {
-      if (*p == '"') {
-         for (p++; *p && *p != '"'; p++) {
-           *(p-1) = *p;
-           *p = 0;
-        }
-        break;
+      for ( ; *p && *p != ' '; ) {
+        p++;
+      }
+      if (*p == ' ') {
+        *p++ = 0;
       }
-   }
-   if (*p) {                         /* if more arguments */
-      *p++ = 0;                      /* terminate this one */
    }
    *s = p;
+   Dmsg2(400, "End arg=%s next=%s\n", n, p);
    return n;
 }   
 
@@ -129,8 +136,7 @@ void parse_command_args(UAContext *ua)
    int i;
 
    ua->args = (char *) check_pool_memory_size(ua->args, sock->msglen+1);
-   strcpy(ua->args, sock->msg);
-   ua->args[sock->msglen] = 0;
+   bstrncpy(ua->args, sock->msg, sock->msglen+1);
    strip_trailing_junk(ua->args);
    ua->argc = 0;
    p = ua->args;
@@ -154,7 +160,7 @@ void parse_command_args(UAContext *ua)
       }
       ua->argv[i] = p;               /* save ptr to value or NULL */
    }
-#ifdef xxxxxxxxx
+#ifdef xxxx
    for (i=0; i<ua->argc; i++) {
       Dmsg3(000, "Arg %d: kw=%s val=%s\n", i, 
          ua->argk[i], ua->argv[i]?ua->argv[i]:"NULL");
index fd972682ee00cde60edda915146dd6e821d432d8..0d7c2edf46b1f357e787b37cfa6a6a6af3fa901f 100644 (file)
@@ -311,8 +311,8 @@ int prune_files(UAContext *ua, CLIENT *client)
    }
    edit_uint64_with_commas(del.tot_ids, ed1);
    edit_uint64_with_commas(del.num_ids, ed2);
-   bsendmsg(ua, _("Pruned %s Files from %s Jobs for client %s from %s catalog.\n"), 
-      ed1, ed2, client->hdr.name, client->catalog->hdr.name);
+   bsendmsg(ua, _("Pruned %s Files from %s Jobs for client %s from catalog.\n"), 
+      ed1, ed2, client->hdr.name);
    
 bail_out:
    db_unlock(ua->db);
@@ -465,8 +465,8 @@ int prune_jobs(UAContext *ua, CLIENT *client, int JobType)
       db_sql_query(ua->db, query, NULL, (void *)NULL);
       Dmsg1(050, "Del sql=%s\n", query);
    }
-   bsendmsg(ua, _("Pruned %d %s for client %s from %s catalog.\n"), del.num_ids,
-      del.num_ids==1?_("Job"):_("Jobs"), client->hdr.name, client->catalog->hdr.name);
+   bsendmsg(ua, _("Pruned %d %s for client %s from catalog.\n"), del.num_ids,
+      del.num_ids==1?_("Job"):_("Jobs"), client->hdr.name);
    
 bail_out:
    drop_temp_tables(ua);
index f45832be4fdbcb4fe6a1767ceed8b789fb047d88..85a70e963df738a3eb70c066d289d78b23295584 100644 (file)
 extern char *uar_list_jobs;
 extern char *uar_file;
 extern char *uar_sel_files;
+extern char *uar_del_temp;
+extern char *uar_del_temp1;
+extern char *uar_create_temp;
+extern char *uar_create_temp1;
+extern char *uar_last_full;
+extern char *uar_full;
+extern char *uar_inc;
+extern char *uar_list_temp;
+extern char *uar_sel_jobid_temp;
 
 /* Context for insert_tree_handler() */
 typedef struct s_tree_ctx {
@@ -49,6 +58,13 @@ typedef struct s_tree_ctx {
    UAContext *ua;
 } TREE_CTX;
 
+struct s_full_ctx {
+   btime_t JobTDate;
+   uint32_t ClientId;
+   uint32_t TotalFiles;
+   char JobIds[200];
+};
+
 
 /* FileIndex entry in bootstrap record */
 typedef struct s_rbsr_findex {
@@ -74,10 +90,13 @@ 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);
 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 void user_select_files(TREE_CTX *tree);
 
 
-
 /*
  *   Restore files
  *
@@ -85,138 +104,273 @@ static void user_select_files(TREE_CTX *tree);
 int restorecmd(UAContext *ua, char *cmd)
 {
    POOLMEM *query;
-   int JobId, done = 0;
    TREE_CTX tree;
+   JobId_t JobId;
+   char *p;
    RBSR *bsr;
    char *nofname = "";
-   JOB_DBR jr;
-   char *list[] = { 
-      "List last Jobs run",
-      "Enter list of JobIds",
-      "Enter SQL list command", 
-      "Select a File",
-      "Cancel",
-      NULL };
+   struct s_full_ctx full;
 
    if (!open_db(ua)) {
       return 0;
    }
 
    memset(&tree, 0, sizeof(TREE_CTX));
+   memset(&full, 0, sizeof(full));
+
+   if (!user_select_jobids(ua, &full)) {
+      return 0;
+   }
+
+
+   /* 
+    * Build the directory tree 
+    */
+   tree.root = new_tree(full.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; ) {
+      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)) {
+         bsendmsg(ua, "%s", db_strerror(ua->db));
+      }
+   }
+   bsendmsg(ua, "\n");
+   free_pool_memory(query);
+
+   /* Let the user select which files to restore */
+   user_select_files(&tree);
+
+   /*
+    * Walk down through the tree finding all files marked to be 
+    *  extracted making a bootstrap file.
+    */
+   bsr = new_bsr();
+   for (TREE_NODE *node=first_tree_node(tree.root); node; node=next_tree_node(node)) {
+      Dmsg2(400, "FI=%d node=0x%x\n", node->FileIndex, node);
+      if (node->extract) {
+         Dmsg2(400, "type=%d FI=%d\n", node->type, node->FileIndex);
+        add_findex(bsr, node->JobId, node->FileIndex);
+      }
+   }
+
+   free_tree(tree.root);             /* free the directory tree */
+
+   if (bsr->JobId) {
+      complete_bsr(ua, bsr);         /* find Vol, SessId, SessTime from JobIds */
+      print_bsr(ua, bsr);
+   } else {
+      bsendmsg(ua, _("No files selected to restore.\n"));
+   }
+   free_bsr(bsr);
+
+   bsendmsg(ua, _("Restore command done.\n"));
+   return 1;
+}
+
+/*
+ * The first step in the restore process is for the user to 
+ *  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)
+{
+   char *p;
+   JobId_t JobId;
+   JOB_DBR jr;
+   POOLMEM *query;
+   int done = 0;
+   char *list[] = { 
+      "List last 20 Jobs run",
+      "List Jobs where a given File is saved",
+      "Enter list of JobIds to select",
+      "Enter SQL list command", 
+      "Select the most recent backup for a client"
+      "Cancel",
+      NULL };
+
+   bsendmsg(ua, _("\nFirst you select one or more JobIds that contain files\n"
+                  "to be restored. You will be presented several methods\n"
+                  "of specifying the JobIds. Then you will be allowed to\n"
+                  "select which files from those JobIds are to be restored.\n\n"));
 
    for ( ; !done; ) {
-      start_prompt(ua, _("To narrow down the restore, you have the following choices:\n"));
+      start_prompt(ua, _("To select the JobIds, you have the following choices:\n"));
       for (int i=0; list[i]; i++) {
         add_prompt(ua, list[i]);
       }
       done = 1;
       switch (do_prompt(ua, "Select item: ", NULL)) {
-      case -1:
+      case -1:                       /* error */
         return 0;
-      case 0:
+      case 0:                        /* list last 20 Jobs run */
         db_list_sql_query(ua->db, uar_list_jobs, prtit, ua, 1);
-         if (!get_cmd(ua, _("Enter JobId to select files for restore: "))) {
+        done = 0;
+        break;
+      case 1:                        /* list where a file is saved */
+         if (!get_cmd(ua, _("Enter Filename: "))) {
            return 0;
         }
-        if (!is_a_number(ua->cmd)) {
-           bsendmsg(ua, _("Bad JobId entered.\n"));
-          return 0;
-        }
-        JobId = atoi(ua->cmd);
+        query = get_pool_memory(PM_MESSAGE);
+        Mmsg(&query, uar_file, ua->cmd);
+        db_list_sql_query(ua->db, query, prtit, ua, 1);
+        free_pool_memory(query);
+        done = 0;
         break;
-
-      case 1:
-         if (!get_cmd(ua, _("Enter JobIds: "))) {
+      case 2:                        /* enter a list of JobIds */
+         if (!get_cmd(ua, _("Enter JobId(s), comma separated, to restore: "))) {
            return 0;
         }
-        JobId = atoi(ua->cmd);
+        bstrncpy(full->JobIds, ua->cmd, sizeof(full->JobIds));
         break;
-      case 2:
+      case 3:                        /* Enter an SQL list command */
          if (!get_cmd(ua, _("Enter SQL list command: "))) {
            return 0;
         }
         db_list_sql_query(ua->db, ua->cmd, prtit, ua, 1);
         done = 0;
         break;
-      case 3:
-         if (!get_cmd(ua, _("Enter Filename: "))) {
+      case 4:                        /* Select the most recent backups */
+        db_sql_query(ua->db, uar_del_temp, NULL, NULL);
+        db_sql_query(ua->db, uar_del_temp1, NULL, NULL);
+        if (!db_sql_query(ua->db, uar_create_temp, NULL, NULL)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
+        }
+        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: "))) {
            return 0;
         }
         query = get_pool_memory(PM_MESSAGE);
-        Mmsg(&query, uar_file, ua->cmd);
-        db_list_sql_query(ua->db, query, prtit, ua, 1);
-        free_pool_memory(query);
-         if (!get_cmd(ua, _("Enter JobId to select files for restore: "))) {
-           return 0;
+        Mmsg(&query, uar_last_full, ua->cmd);
+        /* Find JobId of full Backup of system */
+        if (!db_sql_query(ua->db, query, NULL, NULL)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
+        }
+        /* Find all Volumes used by that JobId */
+        if (!db_sql_query(ua->db, uar_full, NULL,NULL)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
+        }
+         /* 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)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
-        if (!is_a_number(ua->cmd)) {
-           bsendmsg(ua, _("Bad JobId entered.\n"));
-          return 0;
+        /* Now find all Incremental Jobs */
+        Mmsg(&query, uar_inc, (uint32_t)full->JobTDate, full->ClientId);
+        if (!db_sql_query(ua->db, query, NULL, NULL)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
         }
-        JobId = atoi(ua->cmd);
+        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)) {
+            bsendmsg(ua, "%s\n", db_strerror(ua->db));
+        }
+        db_sql_query(ua->db, uar_del_temp, NULL, NULL);
+        db_sql_query(ua->db, uar_del_temp1, NULL, NULL);
         break;
-      case 4:
+      case 5:
         return 0;
       }
    }
 
-   memset(&jr, 0, sizeof(JOB_DBR));
-   jr.JobId = JobId;
-   if (!db_get_job_record(ua->db, &jr)) {
-      bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db));
+   if (*full->JobIds == 0) {
+      bsendmsg(ua, _("No Jobs selected.\n"));
       return 0;
    }
+   bsendmsg(ua, _("You have selected the following JobId: %s\n"), full->JobIds);
 
-   /* 
-    * Build the directory tree 
-    */
-   bsendmsg(ua, _("Building directory tree of backed up files ...\n"));
-   memset(&tree, 0, sizeof(tree));
-   tree.root = new_tree(jr.JobFiles);
-   tree.root->fname = nofname;
-   tree.ua = ua;
-   query = get_pool_memory(PM_MESSAGE);
-   Mmsg(&query, uar_sel_files, JobId);
-   if (!db_sql_query(ua->db, query, insert_tree_handler, (void *)&tree)) {
-      bsendmsg(ua, "%s", db_strerror(ua->db));
-   }
-   free_pool_memory(query);
+   memset(&jr, 0, sizeof(JOB_DBR));
 
-   /* Let the user select which files to restore */
-   user_select_files(&tree);
+   for (p=full->JobIds; ; ) {
+      int stat = next_jobid_from_list(&p, &JobId);
+      if (stat < 0) {
+         bsendmsg(ua, _("Invalid JobId in list.\n"));
+        return 0;
+      }
+      if (stat == 0) {
+        break;
+      }
+      jr.JobId = JobId;
+      if (!db_get_job_record(ua->db, &jr)) {
+         bsendmsg(ua, _("Unable to get Job record. ERR=%s\n"), db_strerror(ua->db));
+        return 0;
+      }
+      full->TotalFiles = jr.JobFiles;
+   }
+   return 1;
+}
 
-   /*
-    * Walk down through the tree finding all files marked to be 
-    *  extracted making a bootstrap file.
-    */
-   bsr = new_bsr();
-   for (TREE_NODE *node=first_tree_node(tree.root); node; node=next_tree_node(node)) {
-      Dmsg2(400, "FI=%d node=0x%x\n", node->FileIndex, node);
-      if (node->extract) {
-         Dmsg2(400, "type=%d FI=%d\n", node->type, node->FileIndex);
-        add_findex(bsr, node->JobId, node->FileIndex);
+static int next_jobid_from_list(char **p, uint32_t *JobId)
+{
+   char jobid[30];
+   int i;
+   char *q = *p;
+
+   jobid[0] = 0;
+   for (i=0; i<(int)sizeof(jobid); i++) {
+      if (*q == ',') {
+        q++;
+        break;
       }
+      jobid[i] = *q++;
+      jobid[i+1] = 0;
    }
+   if (jobid[0] == 0 || !is_a_number(jobid)) {
+      return 0;
+   }
+   *p = q;
+   *JobId = strtoul(jobid, NULL, 10);
+   if (errno) {
+      return 0;
+   }
+   return 1;
+}
 
-   free_tree(tree.root);             /* free the directory tree */
+/*
+ * Callback handler make list of JobIds
+ */
+static int jobid_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_full_ctx *full = (struct s_full_ctx *)ctx;
 
-   if (bsr->JobId) {
-      complete_bsr(ua, bsr);
-      print_bsr(ua, bsr);
-   } else {
-      bsendmsg(ua, _("No files selected to restore.\n"));
+   if (strlen(full->JobIds)+strlen(row[0])+2 < sizeof(full->JobIds)) {
+      if (full->JobIds[0] != 0) {
+         strcat(full->JobIds, ",");
+      }
+      strcat(full->JobIds, row[0]);
    }
-   free_bsr(bsr);
 
-   bsendmsg(ua, _("Restore command done.\n"));
-   return 1;
+   return 0;
+}
+
+
+/*
+ * Callback handler to pickup last Full backup JobId and ClientId
+ */
+static int last_full_handler(void *ctx, int num_fields, char **row)
+{
+   struct s_full_ctx *full = (struct s_full_ctx *)ctx;
+
+   full->JobTDate = atoi(row[1]);
+   full->ClientId = atoi(row[2]);
+
+   return 0;
 }
 
 
 
+
 /* Forward referenced commands */
 
 static int addcmd(UAContext *ua, TREE_CTX *tree);
+static int countcmd(UAContext *ua, TREE_CTX *tree);
+static int findcmd(UAContext *ua, TREE_CTX *tree);
 static int lscmd(UAContext *ua, TREE_CTX *tree);
 static int helpcmd(UAContext *ua, TREE_CTX *tree);
 static int cdcmd(UAContext *ua, TREE_CTX *tree);
@@ -228,6 +382,8 @@ static int quitcmd(UAContext *ua, TREE_CTX *tree);
 struct cmdstruct { char *key; int (*func)(UAContext *ua, TREE_CTX *tree); char *help; }; 
 static struct cmdstruct commands[] = {
  { N_("add"),        addcmd,       _("add file")},
+ { N_("count"),      countcmd,     _("count files")},
+ { N_("find"),       findcmd,      _("find files")},
  { N_("ls"),         lscmd,        _("list current directory")},    
  { N_("dir"),        lscmd,        _("list current directory")},    
  { N_("help"),       helpcmd,      _("print help")},
@@ -276,7 +432,7 @@ static void user_select_files(TREE_CTX *tree)
            break;
         }
       if (!found) {
-         bsendmsg(tree->ua, _("Illegal command\n"));
+         bsendmsg(tree->ua, _("Illegal command. Enter \"done\" to end.\n"));
       }
       if (!stat) {
         break;
@@ -500,9 +656,11 @@ 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
    tree->cnt++;
    return 0;
 }
@@ -541,6 +699,45 @@ static int addcmd(UAContext *ua, TREE_CTX *tree)
    return 1;
 }
 
+static int countcmd(UAContext *ua, TREE_CTX *tree)
+{
+   int total, extract;
+
+   total = extract = 0;
+   for (TREE_NODE *node=first_tree_node(tree->root); node; node=next_tree_node(node)) {
+      if (node->type != TN_NEWDIR) {
+        total++;
+        if (node->extract) {
+           extract++;
+        }
+      }
+   }
+   bsendmsg(ua, "%d total files. %d marked for extraction.\n", total, extract);
+   return 1;
+}
+
+static int findcmd(UAContext *ua, TREE_CTX *tree)
+{
+   char cwd[2000];
+
+   if (ua->argc == 1) {
+      bsendmsg(ua, _("No file specification given.\n"));
+      return 0;
+   }
+   
+   for (int i=1; i < ua->argc; i++) {
+      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);
+        }
+      }
+   }
+   return 1;
+}
+
+
+
 static int lscmd(UAContext *ua, TREE_CTX *tree)
 {
    TREE_NODE *node;
@@ -572,11 +769,18 @@ static int helpcmd(UAContext *ua, TREE_CTX *tree)
 
 static int cdcmd(UAContext *ua, TREE_CTX *tree) 
 {
+   TREE_NODE *node;
    char cwd[2000];
+
    if (ua->argc != 2) {
       return 1;
    }
-   tree->node = tree_cwd(ua->argk[1], tree->root, tree->node);
+   node = tree_cwd(ua->argk[1], tree->root, tree->node);
+   if (!node) {
+      bsendmsg(ua, _("Invalid path given.\n"));
+   } else {
+      tree->node = node;
+   }
    tree_getpath(tree->node, cwd, sizeof(cwd));
    bsendmsg(ua, _("cwd is: %s\n"), cwd);
    return 1;
index 861b92024d703ba7a290e818e48fcb804b70cac8..6884ae4ff55eaa12294840de7f293258413fda64 100644 (file)
@@ -117,10 +117,8 @@ static void handle_UA_client_request(void *arg)
 
    while (!ua.quit) {
       stat = bnet_recv(ua.UA_sock);
-      Dmsg1(500, "stat=%d\n", stat);
       if (stat > 0) {
-        strncpy(cmd, ua.UA_sock->msg, sizeof(cmd));
-        cmd[sizeof(cmd)-1] = 0;       /* ensure it is terminated/trucated */
+        bstrncpy(cmd, ua.UA_sock->msg, sizeof(cmd));
         parse_command_args(&ua);
          if (ua.argc > 0 && ua.argk[0][0] == '.') {
            do_a_dot_command(&ua, cmd);
@@ -139,12 +137,10 @@ static void handle_UA_client_request(void *arg)
            bnet_sig(ua.UA_sock, BNET_EOD); /* send end of command */
         }
       } else if (stat == 0) {
-        if (ua.UA_sock->msglen == BNET_TERMINATE || 
-            ua.UA_sock->msglen == BNET_EOF) {
+        if (ua.UA_sock->msglen == BNET_TERMINATE) {
            ua.quit = TRUE;
            break;
         }
-         Dmsg1(000, "stat=0 msglen=%d\n", ua.UA_sock->msglen);
         bnet_sig(ua.UA_sock, BNET_POLL);
       } else {
         break;                    /* error, exit */
index a1cdd6e59fd1feb0a334ead272018118a4c1c8e2..a9df1b575c2c2463ad6ff0aaa64f7498dca41abb 100644 (file)
@@ -71,7 +71,7 @@ int blast_data_to_storage_daemon(JCR *jcr, char *addr, int port)
       stat = 0;                      /* error */
    }
 
-   bnet_sig(sd, BNET_EOF);           /* terminate data connection */
+   bnet_sig(sd, BNET_EOD);           /* end data connection */
 
    if (jcr->big_buf) {
       free(jcr->big_buf);
index 7e1fd7e01438fb26fcd34f139f2159b0fc18863a..a4c1474da9c3a65b2ae64d9a6be9e287831fa8c5 100644 (file)
@@ -231,7 +231,7 @@ static int cancel_cmd(JCR *jcr)
    } else {
       bnet_fsend(dir, "2902 Error scanning cancel command.\n");
    }
-   bnet_sig(dir, BNET_EOF);
+   bnet_sig(dir, BNET_EOD);
    return 1;
 }
 
@@ -577,11 +577,11 @@ cleanup:
 
    /* Inform Storage daemon that we are done */
    if (sd) {
-      bnet_sig(sd, BNET_EOF);
+      bnet_sig(sd, BNET_TERMINATE);
    }
 
    /* Inform Director that we are done */
-   bnet_sig(dir, BNET_EOF);
+   bnet_sig(dir, BNET_TERMINATE);
 
    return jcr->JobStatus == JS_Terminated;
 }
@@ -637,7 +637,7 @@ static int verify_cmd(JCR *jcr)
       bnet_recv(sd);                    /* get OK */
 
       /* Inform Storage daemon that we are done */
-      bnet_sig(sd, BNET_EOF);
+      bnet_sig(sd, BNET_TERMINATE);
 
       break;
    default:
@@ -646,7 +646,7 @@ static int verify_cmd(JCR *jcr)
    }
 
    /* Inform Director that we are done */
-   return bnet_sig(dir, BNET_EOF);
+   return bnet_sig(dir, BNET_TERMINATE);
 }
 
 /*  
@@ -695,10 +695,10 @@ static int restore_cmd(JCR *jcr)
    bnet_recv(sd);                    /* get OK */
 
    /* Inform Storage daemon that we are done */
-   bnet_sig(sd, BNET_EOF);
+   bnet_sig(sd, BNET_TERMINATE);
 
    /* Inform Director that we are done */
-   bnet_sig(dir, BNET_EOF);
+   bnet_sig(dir, BNET_TERMINATE);
 
    Dmsg0(30, "Done in job.c\n");
    return 1;
@@ -836,7 +836,7 @@ static int send_bootstrap_file(JCR *jcr)
       sd->msglen = Mmsg(&sd->msg, "%s", buf);
       bnet_send(sd);      
    }
-   bnet_sig(sd, BNET_EOF);
+   bnet_sig(sd, BNET_EOD);
    fclose(bs);
    if (!response(sd, OKSDbootstrap, "Bootstrap")) {
       jcr->JobStatus = JS_ErrorTerminated;
index 33c7cbcb9c87040997554d67da77e1701f18c361..8cf036efb2c34241c6bc982c02fbd4623c6361c9 100755 (executable)
@@ -142,7 +142,7 @@ int status_cmd(JCR *jcr)
    do_status(sendit, (void *)user);
    bnet_fsend(user, "====\n");
 
-   bnet_sig(user, BNET_EOF);
+   bnet_sig(user, BNET_EOD);
    return 1;
 }
 
index 05c5a714308722b2e0cda7c477f244f57e12a918..1bf9863c940bb496639e615be7f273c80e5d7f56 100644 (file)
@@ -116,7 +116,7 @@ bnet_recv(BSOCK *bsock)
    int32_t nbytes;
    int32_t pktsiz;
 
-   if (bsock->errors) {
+   if (bsock->errors || bsock->terminated) {
       return -2;
    }
 
@@ -146,13 +146,11 @@ bnet_recv(BSOCK *bsock)
 
    pktsiz = ntohl(pktsiz);           /* decode no. of bytes that follow */
 
-   if (pktsiz <= 0) {
-      bsock->b_errno = ENODATA;
-      bsock->msglen = pktsiz;        /* return size */
-      return 0;                      /* soft EOF */
-   }
-   /* For big packet size, something went wrong */
-   if (pktsiz > 10000000) {
+   /* If signal or packet size too big */
+   if (pktsiz <= 0 || pktsiz > 10000000) {
+      if (pktsiz == BNET_TERMINATE) {
+        bsock->terminated = 1;
+      }
       bsock->b_errno = ENODATA;
       bsock->msglen = pktsiz;        /* return size */
       return 0;                      /* soft EOF */
@@ -239,7 +237,7 @@ bnet_send(BSOCK *bsock)
    int32_t rc;
    int32_t pktsiz;
 
-   if (bsock->errors) {
+   if (bsock->errors || bsock->terminated) {
       return 0;
    }
    pktsiz = htonl((int32_t)bsock->msglen);
@@ -579,8 +577,6 @@ char *bnet_sig_to_ascii(BSOCK *bs)
 {
    static char buf[30];
    switch (bs->msglen) {
-      case BNET_EOF:
-         return "BNET_EOF";
       case BNET_EOD:
          return "BNET_EOD";
       case BNET_EOD_POLL:
index a0ddf0a4137fa65ee3b016f1b353fd11bf910a0f..a507ad10bcfca9afb1e5a5ef2072535acbd1870b 100644 (file)
@@ -56,7 +56,6 @@ typedef struct s_bsock {
 } BSOCK;
 
 /* Signal definitions for use in bnet_sig() */
-#define BNET_EOF          0           /* Deprecated, use BNET_EOD */
 #define BNET_EOD         -1           /* End of data stream, new data may follow */
 #define BNET_EOD_POLL    -2           /* End of data and poll all in one */
 #define BNET_STATUS      -3           /* Send full status */
index d288dcc617d5594c9af45616c7caeaab87a56f5e..cd9abfcbb7bd48f94653af714fd696bb38334e85 100755 (executable)
@@ -789,7 +789,7 @@ e_msg(char *file, int line, int type, int level, char *fmt,...)
                  my_name, file, line);
          break;
        case M_ERROR_TERM:
-          sprintf(buf, "%s ERROR TERMINATING at %s:%d\n", 
+          sprintf(buf, "%s ERROR TERMINATION at %s:%d\n", 
                  my_name, file, line);
          break;
        case M_FATAL:
@@ -874,7 +874,7 @@ Jmsg(void *vjcr, int type, int level, char *fmt,...)
           sprintf(buf, "%s ABORTING due to ERROR\n", my_name);
          break;
        case M_ERROR_TERM:
-          sprintf(buf, "%s ERROR TERMINATING\n", my_name);
+          sprintf(buf, "%s ERROR TERMINATION\n", my_name);
          break;
        case M_FATAL:
           sprintf(buf, "%s: Job %s Fatal error: ", my_name, job);
index 878469953d356eaf720cd5959133ee468f7e61fa..20f5f3095e4fab754c0684d948ab706baea43d83 100644 (file)
@@ -32,6 +32,7 @@ void    decode_stat            (char *buf, struct stat *statp);
 int      bin_to_base64          (char *buf, char *bin, int len);
 
 /* bmisc.c */
+char    *bstrncpy               (char *dest, char *src, int maxlen);
 void    *b_malloc               (char *file, int line, size_t size);
 #ifndef DEBUG
 void    *bmalloc                (size_t size);
index 5bf396db94f877c9fa247ef297353268cf1178d7..2611cda0b6ca46139427ee0f4aacfc4cd00e58ee 100644 (file)
@@ -425,6 +425,8 @@ char *job_type_to_str(int type)
    case JT_RESTORE:
       str = "Restore";
       break;
+   case JT_ADMIN:
+      str = "Admin";
    default:
       str = "Unknown Job Type";
       break;
index 95414cc1a9776da4dbd52ad99c2039fc27ca931c..1f5b4c8c5b21a7bcb01c066bf784539993d503a1 100644 (file)
@@ -216,7 +216,7 @@ static int cancel_cmd(JCR *cjcr)
    } else {
       bnet_fsend(dir, _("3993 Error scanning cancel command.\n"));
    }
-   bnet_sig(dir, BNET_EOF);
+   bnet_sig(dir, BNET_EOD);
    return 1;
 }
 
@@ -292,7 +292,7 @@ static int label_cmd(JCR *jcr)
    free_memory(volname);
    free_memory(poolname);
    free_memory(mtype);
-   bnet_sig(dir, BNET_EOF);
+   bnet_sig(dir, BNET_EOD);
    return 1;
 }
 
@@ -503,7 +503,7 @@ static int mount_cmd(JCR *jcr)
       bnet_fsend(dir, _("3906 Error scanning mount command: %s\n"), dev_name);
    }
    free_memory(dev_name);
-   bnet_sig(dir, BNET_EOF);
+   bnet_sig(dir, BNET_EOD);
    return 1;
 }
 
@@ -588,7 +588,7 @@ static int unmount_cmd(JCR *jcr)
       bnet_fsend(dir, _("3907 Error scanning unmount command: %s\n"), dname);
    }
    free_memory(dname);
-   bnet_sig(dir, BNET_EOF);
+   bnet_sig(dir, BNET_EOD);
    return 1;
 }
 
@@ -720,6 +720,6 @@ static int status_cmd(JCR *jcr)
 #endif
    bnet_fsend(user, "====\n");
 
-   bnet_sig(user, BNET_EOF);
+   bnet_sig(user, BNET_EOD);
    return 1;
 }
index e770c719a6b7b6ce0ae7e9a64e39cfe7312934fa..90cec7925c69778449a36021a0f5a75347f1dd83 100644 (file)
@@ -148,7 +148,7 @@ void run_job(JCR *jcr)
    bnet_fsend(dir, Job_end, jcr->Job, jcr->JobStatus, jcr->JobFiles,
       edit_uint64(jcr->JobBytes, ec1));
 
-   bnet_sig(dir, BNET_EOF);          /* send EOF to Director daemon */
+   bnet_sig(dir, BNET_EOD);          /* send EOD to Director daemon */
    return;
 }
 
@@ -234,7 +234,7 @@ static int append_close_session(JCR *jcr)
    bnet_fsend(fd, OK_close, jcr->NumVolumes);
    Dmsg1(60, ">filed: %s\n", fd->msg);
 
-   bnet_sig(fd, BNET_EOF);           /* send EOF to File daemon */
+   bnet_sig(fd, BNET_EOD);           /* send EOD to File daemon */
        
    Dmsg1(10, "Append close session: %s\n", dev_name(jcr->device->dev));
 
@@ -369,7 +369,7 @@ static int read_close_session(JCR *jcr)
    bnet_fsend(fd, OK_close);
    Dmsg1(60, ">filed: %s\n", fd->msg);
 
-   bnet_sig(fd, BNET_EOF);         /* send EOF to File daemon */
+   bnet_sig(fd, BNET_EOD);         /* send EOD to File daemon */
        
    jcr->session_opened = FALSE;
    return 1;
index f298a533221fd199e4e8b9bbfe7c87d80dc2a774..b39e23da15978e4aa99cd4b15218718c68bb1317 100644 (file)
@@ -237,7 +237,7 @@ int do_read_data(JCR *jcr)
       }
    }
    /* Send end of data to FD */
-   bnet_sig(ds, BNET_EOF);
+   bnet_sig(ds, BNET_EOD);
 
    if (!release_device(jcr, dev, block)) {
       ok = FALSE;
index 47140df20f066d6978cbf152cefa276744d31927..0916ff096982a0f2d37d34333ac477f39b37690a 100644 (file)
@@ -1,8 +1,8 @@
 /* */
 #define VERSION "1.24"
 #define VSTRING "1"
-#define DATE    "01 August 2002"
-#define LSMDATE "01Aug02"
+#define DATE    "04 August 2002"
+#define LSMDATE "04Aug02"
 
 /* Debug flags */
 #define DEBUG 1