]> git.sur5r.net Git - bacula/bacula/commitdiff
Extract restore object and send to FD first cut
authorKern Sibbald <kern@sibbald.com>
Sat, 10 Apr 2010 20:45:39 +0000 (22:45 +0200)
committerEric Bollengier <eric@eb.homelinux.org>
Mon, 2 Aug 2010 14:50:31 +0000 (16:50 +0200)
21 files changed:
bacula/src/cats/create_bdb_database.in [deleted file]
bacula/src/cats/drop_bdb_database.in [deleted file]
bacula/src/cats/drop_bdb_tables.in [deleted file]
bacula/src/cats/drop_mysql_tables.in
bacula/src/cats/drop_postgresql_tables.in
bacula/src/cats/grant_bdb_privileges.in [deleted file]
bacula/src/cats/make_bdb_tables.in [deleted file]
bacula/src/cats/make_mysql_tables.in
bacula/src/cats/make_postgresql_tables.in
bacula/src/cats/make_sqlite3_tables.in
bacula/src/cats/sql_create.c
bacula/src/cats/update_bdb_tables.in [deleted file]
bacula/src/dird/fd_cmds.c
bacula/src/dird/job.c
bacula/src/dird/protos.h
bacula/src/dird/restore.c
bacula/src/dird/ua_restore.c
bacula/src/dird/ua_run.c
bacula/src/filed/backup.c
bacula/src/filed/job.c
bacula/src/jcr.h

diff --git a/bacula/src/cats/create_bdb_database.in b/bacula/src/cats/create_bdb_database.in
deleted file mode 100644 (file)
index 4313515..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-#
-# shell script to create Bacula database(s)
-#
-#  Nothing to do 
diff --git a/bacula/src/cats/drop_bdb_database.in b/bacula/src/cats/drop_bdb_database.in
deleted file mode 100644 (file)
index f526590..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/sh
-#
-# shell script to drop Bacula database(s)
-#
-#  Nothing to do 
diff --git a/bacula/src/cats/drop_bdb_tables.in b/bacula/src/cats/drop_bdb_tables.in
deleted file mode 100644 (file)
index 9c27241..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/sh
-#
-# shell script to Delete the Bacula database (same as deleting 
-#  the tables)
-#
-
-rm -f @working_dir@/control.db
-rm -f @working_dir@/jobs.db
-rm -f @working_dir@/pools.db
-rm -f @working_dir@/media.db
-rm -f @working_dir@/jobmedia.db
-rm -f @working_dir@/client.db
-rm -f @working_dir@/fileset.db
index a66aa421d59c7f4ed415eff44550ba606fd3b5f9..18f401f63b1311a5604bb25ba138a90af1a32194 100644 (file)
@@ -35,6 +35,7 @@ DROP TABLE IF EXISTS Location;
 DROP TABLE IF EXISTS LocationLog;
 DROP TABLE IF EXISTS PathVisibility;
 DROP TABLE IF EXISTS PathHierarchy;
+DROP TABLE IF EXISTS RestoreObject;
 END-OF-DATA
 then
    echo "Deletion of ${db_name} MySQL tables succeeded."
index 05355ddbe07d527eee4e58d1f41ce2ff2c11db6d..9f4e312e1c9628724674726fcba0be099905498e 100644 (file)
@@ -31,6 +31,7 @@ drop table Location;
 drop table locationlog;
 drop table PathVisibility;
 drop table PathHierarchy;
+drop table RestoreObject;
 END-OF-DATA
 pstat=$?
 if test $pstat = 0; 
diff --git a/bacula/src/cats/grant_bdb_privileges.in b/bacula/src/cats/grant_bdb_privileges.in
deleted file mode 100644 (file)
index 8ca8ea2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-#
-# shell script to grant privileges to the bdb database
-#
-bindir=@SQL_BINDIR@
-
-# nothing to do here
\ No newline at end of file
diff --git a/bacula/src/cats/make_bdb_tables.in b/bacula/src/cats/make_bdb_tables.in
deleted file mode 100644 (file)
index 246edb9..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/bin/sh
-#
-# shell script to create Bacula tables
-#
-# Nothing to do -- created by Bacula
-#
index 206c52f07f66f49623c7103c8cb417204dc54535..27067f0148cbcfe9560b55dd9b39702aedd1aeb8 100644 (file)
@@ -51,6 +51,7 @@ CREATE TABLE RestoreObject (
    Path BLOB NOT NULL,
    RestoreObject BLOB NOT NULL,
    PluginName TINYBLOB NOT NULL,
+   ObjectLength INTEGER DEFAULT 0,
    ObjectIndex INTEGER DEFAULT 0,
    ObjectType INTEGER DEFAULT 0,
    FileIndex INTEGER UNSIGNED DEFAULT 0,
index 34d5d612547fd3d515be285b14348ecc0f43dd06..4339a28ebd0b86eb0ad40326ad600cccef39084b 100644 (file)
@@ -66,6 +66,7 @@ CREATE TABLE RestoreObject (
    Path TEXT NOT NULL,
    RestoreObject TEXT NOT NULL,
    PluginName TEXT NOT NULL,
+   ObjectLength INTEGER DEFAULT 0,
    ObjectIndex INTEGER DEFAULT 0,
    ObjectType INTEGER DEFAULT 0,
    FileIndex INTEGER UNSIGNED DEFAULT 0,
index 40a17e9c4f413d4e8c6a5c42bccf460884831393..1cf00f1d7edc588d88a11ac23a48bb4e74b4565c 100644 (file)
@@ -55,6 +55,7 @@ CREATE TABLE RestoreObject (
    Path TEXT DEFAULT '',
    RestoreObject TEXT DEFAULT '',
    PluginName TEXT DEFAULT '',
+   ObjectLength INTEGER DEFAULT 0,
    ObjectIndex INTEGER DEFAULT 0,
    ObjectType INTEGER DEFAULT 0,
    FileIndex INTEGER UNSIGNED DEFAULT 0,
index 44d1c2c5520871e04b6080d02a7d2104d298c20c..d892faabeacd92de3f38accb6ff25042d8f0746f 100644 (file)
@@ -1287,8 +1287,8 @@ bool db_create_restore_object_record(JCR *jcr, B_DB *mdb, ROBJECT_DBR *ro)
 
    Mmsg(mdb->cmd,
         "INSERT INTO RestoreObject (Fname,Path,PluginName,RestoreObject,"
-        "ObjectIndex,ObjectType,FileIndex,JobId) VALUES"
-        "('%s','%s','%s','%s',%d,%d,%d,%u)", 
+        "ObjectLength,ObjectIndex,ObjectType,FileIndex,JobId) VALUES"
+        "('%s','%s','%s','%s',%d,%d,%d,%d,%u)", 
         mdb->esc_name, mdb->esc_path, mdb->esc_path, esc_obj, ro->object_len,
         ro->ObjectIndex, FT_RESTORE_FIRST, ro->FileIndex, ro->JobId);
 
diff --git a/bacula/src/cats/update_bdb_tables.in b/bacula/src/cats/update_bdb_tables.in
deleted file mode 100755 (executable)
index d8e3df3..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/sh
-#
-# Shell script to update bdb tables
-# Nothing to do here.
-#
-echo " "
-bindir=@SQL_BINDIR@
-
-exit 0
index 6b99d9992c016f5a0a94882bfbeeb583d9982a32..340ff606ffc393977d440ab2ba08da51cb3c2382 100644 (file)
@@ -323,9 +323,9 @@ bool send_level_command(JCR *jcr)
    }
    Dmsg1(120, ">filed: %s", fd->msg);
    if (!response(jcr, fd, OKlevel, "Level", DISPLAY_ERROR)) {
-      return 0;
+      return false;
    }
-   return 1;
+   return true;
 }
 
 /*
@@ -667,6 +667,41 @@ bail_out:
    return 0;
 }
 
+static int restore_object_handler(void *ctx, int num_fields, char **row)
+{
+   JCR *jcr = (JCR *)ctx;
+   BSOCK *fd;
+
+   fd = jcr->file_bsock;
+   if (jcr->is_job_canceled()) {
+      return 1;
+   }
+   bash_spaces(row[2]);
+   bash_spaces(row[3]);
+   bash_spaces(row[6]);
+   fd->fsend("RestoreObject JobId=%s ObjLen=%s ObjInx=%s ObjType=%s FI=%s",
+      row[0], row[3], row[6], row[7], row[8]);
+   Dmsg1(000, ">fd: %s\n", fd->msg);
+   return 0;
+}
+
+bool send_restore_objects(JCR *jcr)
+{
+//   BSOCK *fd = jcr->file_bsock;
+   POOL_MEM query(PM_MESSAGE);
+
+   if (!jcr->JobIds || !jcr->JobIds[0]) {
+      return true;
+   }
+   Mmsg(query, "SELECT JobId,Fname,Path,ObjectLength,RestoreObject,"
+        "PluginName,ObjectIndex,ObjectType,FileIndex "
+        "FROM RestoreObject WHERE JobId IN (%s)", jcr->JobIds);
+   
+   /* missing_handler is called for each file found */
+   db_sql_query(jcr->db, query.c_str(), restore_object_handler, (void *)jcr);
+   return true;
+}
+
 
 
 /*
index 23b5022dbef83dfae144741a0ae8c4fc806fbbc3..48556976e74f34e007532d6dbb409f4838ac3274 100644 (file)
@@ -1012,14 +1012,6 @@ void create_unique_job_name(JCR *jcr, const char *base_name)
 /* Called directly from job rescheduling */
 void dird_free_jcr_pointers(JCR *jcr)
 {
-   if (jcr->sd_auth_key) {
-      free(jcr->sd_auth_key);
-      jcr->sd_auth_key = NULL;
-   }
-   if (jcr->where) {
-      free(jcr->where);
-      jcr->where = NULL;
-   }
    if (jcr->file_bsock) {
       Dmsg0(200, "Close File bsock\n");
       bnet_close(jcr->file_bsock);
@@ -1030,27 +1022,16 @@ void dird_free_jcr_pointers(JCR *jcr)
       bnet_close(jcr->store_bsock);
       jcr->store_bsock = NULL;
    }
-   if (jcr->fname) {
-      Dmsg0(200, "Free JCR fname\n");
-      free_pool_memory(jcr->fname);
-      jcr->fname = NULL;
-   }
-   if (jcr->RestoreBootstrap) {
-      free(jcr->RestoreBootstrap);
-      jcr->RestoreBootstrap = NULL;
-   }
-   if (jcr->client_uname) {
-      free_pool_memory(jcr->client_uname);
-      jcr->client_uname = NULL;
-   }
-   if (jcr->attr) {
-      free_pool_memory(jcr->attr);
-      jcr->attr = NULL;
-   }
-   if (jcr->ar) {
-      free(jcr->ar);
-      jcr->ar = NULL;
-   }
+
+   bfree_and_null(jcr->sd_auth_key);
+   bfree_and_null(jcr->where);
+   bfree_and_null(jcr->RestoreBootstrap);
+   bfree_and_null(jcr->ar);
+
+   free_and_null_pool_memory(jcr->JobIds);
+   free_and_null_pool_memory(jcr->client_uname);
+   free_and_null_pool_memory(jcr->attr);
+   free_and_null_pool_memory(jcr->fname);
 }
 
 /*
@@ -1076,36 +1057,14 @@ void dird_free_jcr(JCR *jcr)
       db_close_database(jcr, jcr->db);
       jcr->db = NULL;
    }
-   if (jcr->stime) {
-      Dmsg0(200, "Free JCR stime\n");
-      free_pool_memory(jcr->stime);
-      jcr->stime = NULL;
-   }
-   if (jcr->fname) {
-      Dmsg0(200, "Free JCR fname\n");
-      free_pool_memory(jcr->fname);
-      jcr->fname = NULL;
-   }
-   if (jcr->pool_source) {
-      free_pool_memory(jcr->pool_source);
-      jcr->pool_source = NULL;
-   }
-   if (jcr->catalog_source) {
-      free_pool_memory(jcr->catalog_source);
-      jcr->catalog_source = NULL;
-   }
-   if (jcr->rpool_source) {
-      free_pool_memory(jcr->rpool_source);
-      jcr->rpool_source = NULL;
-   }
-   if (jcr->wstore_source) {
-      free_pool_memory(jcr->wstore_source);
-      jcr->wstore_source = NULL;
-   }
-   if (jcr->rstore_source) {
-      free_pool_memory(jcr->rstore_source);
-      jcr->rstore_source = NULL;
-   }
+
+   free_and_null_pool_memory(jcr->stime);
+   free_and_null_pool_memory(jcr->fname);
+   free_and_null_pool_memory(jcr->pool_source);
+   free_and_null_pool_memory(jcr->catalog_source);
+   free_and_null_pool_memory(jcr->rpool_source);
+   free_and_null_pool_memory(jcr->wstore_source);
+   free_and_null_pool_memory(jcr->rstore_source);
 
    /* Delete lists setup to hold storage pointers */
    free_rwstorage(jcr);
index 2055b8cb724fd41cf7ba4d36077fe71b4a5d0ed8..ee7bef42deffc969d7e6d3cb9a4a01ff62ce0b0d 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -27,8 +27,6 @@
 */
 /*
  * Director external function prototypes
- *
- *   Version $Id$
  */
 
 /* admin.c */
@@ -104,6 +102,7 @@ extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname,
                           char *link, char *attr, int stream);
 extern void get_level_since_time(JCR *jcr, char *since, int since_len);
 extern int send_runscripts_commands(JCR *jcr);
+extern bool send_restore_objects(JCR *jcr);
 
 /* getmsg.c */
 enum e_prtmsg {
index e852edfe4c5b1436ce82c5b9c5d52c3897010aa3..b75b82935de1e75109a8ec7cc34b9884dc57801b 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2000-2009 Free Software Foundation Europe e.V.
+   Copyright (C) 2000-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -25,7 +25,7 @@
    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
    Switzerland, email:ftf@fsfeurope.org.
 */
-/*
+/**
  *   Bacula Director -- restore.c -- responsible for restoring files
  *
  *     Kern Sibbald, November MM
@@ -42,7 +42,6 @@
  *       to do the restore.
  *     Update the DB according to what files where restored????
  *
- *   Version $Id$
  */
 
 
@@ -112,7 +111,8 @@ struct bootstrap_info
 
 #define UA_CMD_SIZE 1000
 
-/* Open the bootstrap file and find the first Storage= 
+/*
+ * Open the bootstrap file and find the first Storage= 
  * Returns ok if able to open
  * It fills the storage name (should be the first line) 
  * and the file descriptor to the bootstrap file, 
@@ -158,7 +158,7 @@ static bool open_bootstrap_file(JCR *jcr, struct bootstrap_info &info)
    return true;
 }
 
-/* 
+/** 
  * This function compare the given storage name with the
  * the current one. We compare the name and the address:port.
  * Returns true if we use the same storage.
@@ -197,7 +197,7 @@ static bool is_on_same_storage(JCR *jcr, char *new_one)
    return true;
 }
 
-/* 
+/** 
  * Check if the current line contains Storage="xxx", and compare the
  * result to the current storage. We use UAContext to analyse the bsr 
  * string.
@@ -225,7 +225,7 @@ static bool check_for_new_storage(JCR *jcr, struct bootstrap_info &info)
    return false;
 }
 
-/*
+/**
  * Send bootstrap file to Storage daemon section by section.
  */
 static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
@@ -257,12 +257,13 @@ static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
    return true;
 }
 
-/* 
+/** 
  * Change the read storage resource for the current job.
  */
 static void select_rstore(JCR *jcr, struct bootstrap_info &info)
 {
    USTORE ustore;
+
    if (!strcmp(jcr->rstore->name(), info.storage)) {
       return;
    }
@@ -296,10 +297,14 @@ static void close_bootstrap_file(struct bootstrap_info &info)
    }
 }
 
-/* 
- * Take a bootstrap and for each different storage, we change the storage
- * resource and start a new restore session between the client and the storage
- *
+/** 
+ * The bootstrap is stored in a file, so open the file, and loop
+ *   through it processing each storage device in turn. If the
+ *   storage is different from the prior one, we open a new connection
+ *   to the new storage and do a restore for that part.
+ * This permits handling multiple storage daemons for a single
+ *   restore.  E.g. your Full is stored on tape, and Incrementals
+ *   on disk.
  */
 bool restore_bootstrap(JCR *jcr)
 {
@@ -313,14 +318,16 @@ bool restore_bootstrap(JCR *jcr)
    /* this command is used for each part */
    build_restore_command(jcr, restore_cmd);
    
+   /* Open the bootstrap file */
    if (!open_bootstrap_file(jcr, info)) {
       goto bail_out;
    }
+   /* Read the bootstrap file */
    while (!end_loop && !feof(info.bs)) {
       
       select_rstore(jcr, info);
 
-      /*
+      /**
        * Open a message channel connection with the Storage
        * daemon. This is to let him know that our client
        * will be contacting him for a backup  session.
@@ -351,7 +358,6 @@ bool restore_bootstrap(JCR *jcr)
          if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
             goto bail_out;
          }
-
          fd = jcr->file_bsock;
       }
 
@@ -400,6 +406,10 @@ bool restore_bootstrap(JCR *jcr)
          first_time=false;
       }
 
+      if (!send_restore_objects(jcr)) {
+         goto bail_out;
+      }
+
       fd->fsend("%s", restore_cmd.c_str());
 
       if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
@@ -428,7 +438,7 @@ bail_out:
    return ret;
 }
 
-/*
+/**
  * Do a restore of the specified files
  *
  *  Returns:  0 on failure
@@ -466,6 +476,7 @@ bool do_restore(JCR *jcr)
    /* Print Job Start message */
    Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
 
+   /* Read the bootstrap file and do the restore */
    if (!restore_bootstrap(jcr)) {
       goto bail_out;
    }
@@ -486,7 +497,7 @@ bool do_restore_init(JCR *jcr)
    return true;
 }
 
-/*
+/**
  * Release resources allocated during restore.
  *
  */
index c2348d89f924a3195d2c51105cf07a5be4a96367..43d31d278da71f4684e1249c477f7367d16a0e29 100644 (file)
@@ -1,7 +1,7 @@
 /*
    Bacula® - The Network Backup Solution
 
-   Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
+   Copyright (C) 2002-2010 Free Software Foundation Europe e.V.
 
    The main author of Bacula is Kern Sibbald, with contributions from
    many others, a complete list can be found in the file AUTHORS.
@@ -36,8 +36,6 @@
  *        bsr.c July MMIII
  *
  *     Kern Sibbald, July MMII
- *
- *   Version $Id$
  */
 
 
@@ -67,7 +65,7 @@ static bool insert_dir_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *di
 static void insert_one_file_or_dir(UAContext *ua, RESTORE_CTX *rx, char *date, bool dir);
 static int get_client_name(UAContext *ua, RESTORE_CTX *rx);
 static int get_restore_client_name(UAContext *ua, RESTORE_CTX &rx);
-static int get_date(UAContext *ua, char *date, int date_len);
+static bool get_date(UAContext *ua, char *date, int date_len);
 static int restore_count_handler(void *ctx, int num_fields, char **row);
 static bool insert_table_into_findex_list(UAContext *ua, RESTORE_CTX *rx, char *table);
 static void get_and_display_basejobs(UAContext *ua, RESTORE_CTX *rx);
@@ -92,6 +90,7 @@ int restore_cmd(UAContext *ua, const char *cmd)
    rx.path = get_pool_memory(PM_FNAME);
    rx.fname = get_pool_memory(PM_FNAME);
    rx.JobIds = get_pool_memory(PM_FNAME);
+   rx.JobIds[0] = 0;
    rx.BaseJobIds = get_pool_memory(PM_FNAME);
    rx.query = get_pool_memory(PM_FNAME);
    rx.bsr = new_bsr();
@@ -279,6 +278,9 @@ int restore_cmd(UAContext *ua, const char *cmd)
       pm_strcat(ua->cmd, " yes");    /* pass it on to the run command */
    }
    Dmsg1(200, "Submitting: %s\n", ua->cmd);
+   /* Transfer jobids to jcr to for picking up restore objects */
+   jcr->JobIds = rx.JobIds;
+   rx.JobIds = NULL;
    parse_ua_args(ua);
    run_cmd(ua, ua->cmd);
    free_rx(&rx);
@@ -721,6 +723,7 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
             pm_strcat(rx->JobIds, ua->cmd);
          }
          if (*rx->JobIds == 0 || *rx->JobIds == '.') {
+            *rx->JobIds = 0;
             return 0;                 /* nothing entered, return */
          }
          if (!have_date) {
@@ -835,13 +838,13 @@ static int user_select_jobids_or_files(UAContext *ua, RESTORE_CTX *rx)
 /*
  * Get date from user
  */
-static int get_date(UAContext *ua, char *date, int date_len)
+static bool get_date(UAContext *ua, char *date, int date_len)
 {
    ua->send_msg(_("The restored files will the most current backup\n"
                   "BEFORE the date you specify below.\n\n"));
    for ( ;; ) {
       if (!get_cmd(ua, _("Enter date as YYYY-MM-DD HH:MM:SS :"))) {
-         return 0;
+         return false;
       }
       if (str_to_utime(ua->cmd) != 0) {
          break;
@@ -849,7 +852,7 @@ static int get_date(UAContext *ua, char *date, int date_len)
       ua->error_msg(_("Improper date format.\n"));
    }
    bstrncpy(date, ua->cmd, date_len);
-   return 1;
+   return true;
 }
 
 /*
index 97874c431e877e15d80a8d0f3d5147dbc4ed97ba..13ffabddd54fe519b85fe25714f0ad83899951d9 100644 (file)
@@ -122,6 +122,11 @@ int run_cmd(UAContext *ua, const char *cmd)
       jcr->unlink_bsr = ua->jcr->unlink_bsr;    /* copy unlink flag from caller */
       ua->jcr->unlink_bsr = false;
    }
+   /* Transfer JobIds to new restore Job */
+   if (ua->jcr->JobIds) {
+      jcr->JobIds = ua->jcr->JobIds;
+      ua->jcr->JobIds = NULL;
+   }
 
 try_again:
    if (!reset_restore_context(ua, jcr, rc)) {
index bcd25c1fc3f04dfec103c8c2e84c1a057551f410..a03f040773bb4f56c8f6ad786c5e0046df58ac88 100644 (file)
@@ -299,6 +299,7 @@ static bool crypto_session_send(JCR *jcr, BSOCK *sd)
 int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
 {
    bool do_read = false;
+   bool plugin_started = false;
    int stat, data_stream; 
    int rtnstat = 0;
    DIGEST *digest = NULL;
@@ -497,12 +498,17 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
          goto bail_out;
       }
       send_plugin_name(jcr, sd, true);      /* signal start of plugin data */
+      plugin_started = true;
    }
 
    /** Send attributes -- must be done after binit() */
    if (!encode_and_send_attributes(jcr, ff_pkt, data_stream)) {
       goto bail_out;
    }
+   /** Meta data only for restore object */
+   if (ff_pkt->type == FT_RESTORE_FIRST) {
+      goto good_rtn;
+   }
 
    /** Set up the encryption context and send the session data to the SD */
    if (has_file_data && jcr->crypto.pki_encrypt) {
@@ -529,7 +535,7 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
       do_read = true;
    }
 
-   if (ff_pkt->cmd_plugin && ff_pkt->type != FT_RESTORE_FIRST) {
+   if (ff_pkt->cmd_plugin) {
       do_read = true;
    }
 
@@ -734,14 +740,14 @@ int save_file(JCR *jcr, FF_PKT *ff_pkt, bool top_level)
       sd->send();
       sd->signal(BNET_EOD);              /* end of checksum */
    }
-   if (ff_pkt->cmd_plugin) {
-      send_plugin_name(jcr, sd, false); /* signal end of plugin data */
-   }
 
 good_rtn:
    rtnstat = 1;                       /* good return */
 
 bail_out:
+   if (ff_pkt->cmd_plugin && plugin_started) {
+      send_plugin_name(jcr, sd, false); /* signal end of plugin data */
+   }
    if (digest) {
       crypto_digest_free(digest);
    }
index 19676e93f106e677bab7c3e9ad288fba80cb7423..4fca924320a9b760f3835ca366f28e93cf8e1ed3 100644 (file)
@@ -88,6 +88,7 @@ static int runscript_cmd(JCR *jcr);
 static int runbefore_cmd(JCR *jcr);
 static int runafter_cmd(JCR *jcr);
 static int runbeforenow_cmd(JCR *jcr);
+static int restoreobject_cmd(JCR *jcr);
 static void set_options(findFOPTS *fo, const char *opts);
 static void set_storage_auth_key(JCR *jcr, char *key);
 
@@ -124,6 +125,7 @@ static struct s_cmds cmds[] = {
    {"RunAfterJob",  runafter_cmd,  0},
    {"Run",          runscript_cmd, 0},
    {"accurate",     accurate_cmd,  0},
+   {"restoreobject", restoreobject_cmd, 0},
    {NULL,       NULL}                  /* list terminator */
 };
 
@@ -135,6 +137,7 @@ static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
 static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
+static char restoreobjcmd[] = "RestoreObject JobId=%u ObjLen=%d ObjInx=%d ObjType=%d FI=%d";
 static char verifycmd[]   = "verify level=%30s";
 static char estimatecmd[] = "estimate listing=%d";
 static char runbefore[]   = "RunBeforeJob %s";
@@ -615,6 +618,28 @@ static int runscript_cmd(JCR *jcr)
 }
 
 
+static int restoreobject_cmd(JCR *jcr)
+{
+   BSOCK *dir = jcr->dir_bsock;
+   POOLMEM *msg = get_memory(dir->msglen+1);
+   uint32_t JobId;
+   int32_t object_len, object_index, object_type, FileIndex;
+
+   Dmsg1(000, "restoreobject_cmd: %s", dir->msg);
+   if (sscanf(dir->msg, restoreobjcmd, &JobId, &object_len, &object_index, 
+              &object_type, &FileIndex) != 5) {
+      pm_strcpy(jcr->errmsg, dir->msg);
+      Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
+      dir->fsend(_("2909 Bad RestoreObject command.\n"));
+      free_memory(msg);
+      return 0;
+   }
+   Dmsg5(000, "JobId=%u objlen=%d objinx=%d objtype=%d FI=%d\n",
+         JobId, object_len, object_index, object_type, FileIndex);
+   return 1;
+}
+
+
 static bool init_fileset(JCR *jcr)
 {
    FF_PKT *ff;
index fce17558fa1f397851d217d9dafd94237881dd43..9e6c14a5047f3609d60e02669a2277cecdf5ae7d 100644 (file)
@@ -239,6 +239,7 @@ public:
    time_t wait_time_sum;              /* cumulative wait time since job start */
    time_t wait_time;                  /* timestamp when job have started to wait */
    POOLMEM *client_name;              /* client name */
+   POOLMEM *JobIds;                   /* User entered string of JobIds */
    POOLMEM *RestoreBootstrap;         /* Bootstrap file to restore */
    POOLMEM *stime;                    /* start time for incremental/differential */
    char *sd_auth_key;                 /* SD auth key */