From e1e7c2aaef15193daad550d12c2ca4c65e76778c Mon Sep 17 00:00:00 2001 From: Kern Sibbald Date: Sat, 10 Apr 2010 22:45:39 +0200 Subject: [PATCH] Extract restore object and send to FD first cut --- bacula/src/cats/create_bdb_database.in | 5 -- bacula/src/cats/drop_bdb_database.in | 5 -- bacula/src/cats/drop_bdb_tables.in | 13 ---- bacula/src/cats/drop_mysql_tables.in | 1 + bacula/src/cats/drop_postgresql_tables.in | 1 + bacula/src/cats/grant_bdb_privileges.in | 7 --- bacula/src/cats/make_bdb_tables.in | 6 -- bacula/src/cats/make_mysql_tables.in | 1 + bacula/src/cats/make_postgresql_tables.in | 1 + bacula/src/cats/make_sqlite3_tables.in | 1 + bacula/src/cats/sql_create.c | 4 +- bacula/src/cats/update_bdb_tables.in | 9 --- bacula/src/dird/fd_cmds.c | 39 +++++++++++- bacula/src/dird/job.c | 77 ++++++----------------- bacula/src/dird/protos.h | 5 +- bacula/src/dird/restore.c | 43 ++++++++----- bacula/src/dird/ua_restore.c | 17 ++--- bacula/src/dird/ua_run.c | 5 ++ bacula/src/filed/backup.c | 14 +++-- bacula/src/filed/job.c | 25 ++++++++ bacula/src/jcr.h | 1 + 21 files changed, 142 insertions(+), 138 deletions(-) delete mode 100644 bacula/src/cats/create_bdb_database.in delete mode 100644 bacula/src/cats/drop_bdb_database.in delete mode 100644 bacula/src/cats/drop_bdb_tables.in delete mode 100644 bacula/src/cats/grant_bdb_privileges.in delete mode 100644 bacula/src/cats/make_bdb_tables.in delete mode 100755 bacula/src/cats/update_bdb_tables.in diff --git a/bacula/src/cats/create_bdb_database.in b/bacula/src/cats/create_bdb_database.in deleted file mode 100644 index 4313515899..0000000000 --- a/bacula/src/cats/create_bdb_database.in +++ /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 index f52659024b..0000000000 --- a/bacula/src/cats/drop_bdb_database.in +++ /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 index 9c272413a5..0000000000 --- a/bacula/src/cats/drop_bdb_tables.in +++ /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 diff --git a/bacula/src/cats/drop_mysql_tables.in b/bacula/src/cats/drop_mysql_tables.in index a66aa421d5..18f401f63b 100644 --- a/bacula/src/cats/drop_mysql_tables.in +++ b/bacula/src/cats/drop_mysql_tables.in @@ -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." diff --git a/bacula/src/cats/drop_postgresql_tables.in b/bacula/src/cats/drop_postgresql_tables.in index 05355ddbe0..9f4e312e1c 100644 --- a/bacula/src/cats/drop_postgresql_tables.in +++ b/bacula/src/cats/drop_postgresql_tables.in @@ -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 index 8ca8ea24f5..0000000000 --- a/bacula/src/cats/grant_bdb_privileges.in +++ /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 index 246edb9e9c..0000000000 --- a/bacula/src/cats/make_bdb_tables.in +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh -# -# shell script to create Bacula tables -# -# Nothing to do -- created by Bacula -# diff --git a/bacula/src/cats/make_mysql_tables.in b/bacula/src/cats/make_mysql_tables.in index 206c52f07f..27067f0148 100644 --- a/bacula/src/cats/make_mysql_tables.in +++ b/bacula/src/cats/make_mysql_tables.in @@ -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, diff --git a/bacula/src/cats/make_postgresql_tables.in b/bacula/src/cats/make_postgresql_tables.in index 34d5d61254..4339a28ebd 100644 --- a/bacula/src/cats/make_postgresql_tables.in +++ b/bacula/src/cats/make_postgresql_tables.in @@ -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, diff --git a/bacula/src/cats/make_sqlite3_tables.in b/bacula/src/cats/make_sqlite3_tables.in index 40a17e9c4f..1cf00f1d7e 100644 --- a/bacula/src/cats/make_sqlite3_tables.in +++ b/bacula/src/cats/make_sqlite3_tables.in @@ -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, diff --git a/bacula/src/cats/sql_create.c b/bacula/src/cats/sql_create.c index 44d1c2c552..d892faabea 100644 --- a/bacula/src/cats/sql_create.c +++ b/bacula/src/cats/sql_create.c @@ -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 index d8e3df3bf5..0000000000 --- a/bacula/src/cats/update_bdb_tables.in +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -# -# Shell script to update bdb tables -# Nothing to do here. -# -echo " " -bindir=@SQL_BINDIR@ - -exit 0 diff --git a/bacula/src/dird/fd_cmds.c b/bacula/src/dird/fd_cmds.c index 6b99d9992c..340ff606ff 100644 --- a/bacula/src/dird/fd_cmds.c +++ b/bacula/src/dird/fd_cmds.c @@ -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; +} + /* diff --git a/bacula/src/dird/job.c b/bacula/src/dird/job.c index 23b5022dbe..48556976e7 100644 --- a/bacula/src/dird/job.c +++ b/bacula/src/dird/job.c @@ -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); diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 2055b8cb72..ee7bef42de 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -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 { diff --git a/bacula/src/dird/restore.c b/bacula/src/dird/restore.c index e852edfe4c..b75b82935d 100644 --- a/bacula/src/dird/restore.c +++ b/bacula/src/dird/restore.c @@ -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. * */ diff --git a/bacula/src/dird/ua_restore.c b/bacula/src/dird/ua_restore.c index c2348d89f9..43d31d278d 100644 --- a/bacula/src/dird/ua_restore.c +++ b/bacula/src/dird/ua_restore.c @@ -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; } /* diff --git a/bacula/src/dird/ua_run.c b/bacula/src/dird/ua_run.c index 97874c431e..13ffabddd5 100644 --- a/bacula/src/dird/ua_run.c +++ b/bacula/src/dird/ua_run.c @@ -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)) { diff --git a/bacula/src/filed/backup.c b/bacula/src/filed/backup.c index bcd25c1fc3..a03f040773 100644 --- a/bacula/src/filed/backup.c +++ b/bacula/src/filed/backup.c @@ -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); } diff --git a/bacula/src/filed/job.c b/bacula/src/filed/job.c index 19676e93f1..4fca924320 100644 --- a/bacula/src/filed/job.c +++ b/bacula/src/filed/job.c @@ -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; diff --git a/bacula/src/jcr.h b/bacula/src/jcr.h index fce17558fa..9e6c14a504 100644 --- a/bacula/src/jcr.h +++ b/bacula/src/jcr.h @@ -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 */ -- 2.39.5