+++ /dev/null
-#!/bin/sh
-#
-# shell script to create Bacula database(s)
-#
-# Nothing to do
+++ /dev/null
-#!/bin/sh
-#
-# shell script to drop Bacula database(s)
-#
-# Nothing to do
+++ /dev/null
-#!/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
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."
drop table locationlog;
drop table PathVisibility;
drop table PathHierarchy;
+drop table RestoreObject;
END-OF-DATA
pstat=$?
if test $pstat = 0;
+++ /dev/null
-#!/bin/sh
-#
-# shell script to grant privileges to the bdb database
-#
-bindir=@SQL_BINDIR@
-
-# nothing to do here
\ No newline at end of file
+++ /dev/null
-#!/bin/sh
-#
-# shell script to create Bacula tables
-#
-# Nothing to do -- created by Bacula
-#
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,
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,
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,
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);
+++ /dev/null
-#!/bin/sh
-#
-# Shell script to update bdb tables
-# Nothing to do here.
-#
-echo " "
-bindir=@SQL_BINDIR@
-
-exit 0
}
Dmsg1(120, ">filed: %s", fd->msg);
if (!response(jcr, fd, OKlevel, "Level", DISPLAY_ERROR)) {
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/*
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;
+}
+
/*
/* 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);
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);
}
/*
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);
/*
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.
*/
/*
* Director external function prototypes
- *
- * Version $Id$
*/
/* admin.c */
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 {
/*
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.
(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
* to do the restore.
* Update the DB according to what files where restored????
*
- * Version $Id$
*/
#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,
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.
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.
return false;
}
-/*
+/**
* Send bootstrap file to Storage daemon section by section.
*/
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;
}
}
}
-/*
- * 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)
{
/* 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.
if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
goto bail_out;
}
-
fd = jcr->file_bsock;
}
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)) {
return ret;
}
-/*
+/**
* Do a restore of the specified files
*
* Returns: 0 on failure
/* 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;
}
return true;
}
-/*
+/**
* Release resources allocated during restore.
*
*/
/*
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.
* bsr.c July MMIII
*
* Kern Sibbald, July MMII
- *
- * Version $Id$
*/
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);
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();
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);
pm_strcat(rx->JobIds, ua->cmd);
}
if (*rx->JobIds == 0 || *rx->JobIds == '.') {
+ *rx->JobIds = 0;
return 0; /* nothing entered, return */
}
if (!have_date) {
/*
* 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;
ua->error_msg(_("Improper date format.\n"));
}
bstrncpy(date, ua->cmd, date_len);
- return 1;
+ return true;
}
/*
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)) {
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;
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) {
do_read = true;
}
- if (ff_pkt->cmd_plugin && ff_pkt->type != FT_RESTORE_FIRST) {
+ if (ff_pkt->cmd_plugin) {
do_read = true;
}
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);
}
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);
{"RunAfterJob", runafter_cmd, 0},
{"Run", runscript_cmd, 0},
{"accurate", accurate_cmd, 0},
+ {"restoreobject", restoreobject_cmd, 0},
{NULL, NULL} /* list terminator */
};
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";
}
+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;
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 */