-/*
- * Bacula Director -- restore.c -- responsible for restoring files
- *
- * Kern Sibbald, November MM
- *
- * This routine is run as a separate thread.
- *
- * Current implementation is Catalog verification only (i.e. no
- * verification versus tape).
- *
- * Basic tasks done here:
- * Open DB
- * Open Message Channel with Storage daemon to tell him a job will be starting.
- * Open connection with File daemon and pass him commands
- * to do the restore.
- * Update the DB according to what files where restored????
- *
- * Version $Id$
- */
/*
Bacula® - The Network Backup Solution
- Copyright (C) 2000-2006 Free Software Foundation Europe e.V.
+ Copyright (C) 2000-2009 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.
This program is Free Software; you can redistribute it and/or
modify it under the terms of version two of the GNU General Public
- License as published by the Free Software Foundation plus additions
- that are listed in the file LICENSE.
+ License as published by the Free Software Foundation and included
+ in the file LICENSE.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
- Bacula® is a registered trademark of John Walker.
+ Bacula® is a registered trademark of Kern Sibbald.
The licensor of Bacula is the Free Software Foundation Europe
(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
+ *
+ * This routine is run as a separate thread.
+ *
+ * Current implementation is Catalog verification only (i.e. no
+ * verification versus tape).
+ *
+ * Basic tasks done here:
+ * Open DB
+ * Open Message Channel with Storage daemon to tell him a job will be starting.
+ * Open connection with File daemon and pass him commands
+ * to do the restore.
+ * Update the DB according to what files where restored????
+ *
+ * Version $Id$
+ */
#include "bacula.h"
#include "dird.h"
/* Commands sent to File daemon */
-static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
-static char storaddr[] = "storage address=%s port=%d ssl=0\n";
+static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
+static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
+static char storaddr[] = "storage address=%s port=%d ssl=0\n";
/* Responses received from File daemon */
static char OKrestore[] = "2000 OK restore\n";
{
BSOCK *fd;
JOB_DBR rjr; /* restore job record */
+ char replace, *where, *cmd;
+ char empty = '\0';
+ int stat;
free_wstorage(jcr); /* we don't write */
+ if (!allow_duplicate_job(jcr)) {
+ goto bail_out;
+ }
+
memset(&rjr, 0, sizeof(rjr));
jcr->jr.JobLevel = L_FULL; /* Full restore */
if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
Dmsg0(20, "Updated job start record\n");
Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
"You probably ran a restore job directly. All restore jobs must\n"
"be run using the restore command.\n"));
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
* Start conversation with Storage daemon
*/
if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
/*
* Now start a job with the Storage daemon
*/
if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
- if (!bnet_fsend(jcr->store_bsock, "run")) {
- return false;
+ if (!jcr->store_bsock->fsend("run")) {
+ goto bail_out;
}
/*
* Now start a Storage daemon message thread
*/
if (!start_storage_daemon_message_thread(jcr)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
Dmsg0(50, "Storage daemon connection OK\n");
*/
set_jcr_job_status(jcr, JS_WaitFD);
if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
fd = jcr->file_bsock;
if (jcr->rstore->SDDport == 0) {
jcr->rstore->SDDport = jcr->rstore->SDport;
}
- bnet_fsend(fd, storaddr, jcr->rstore->address, jcr->rstore->SDDport);
+ fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport);
Dmsg1(6, "dird>filed: %s\n", fd->msg);
if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
/*
*/
if (!send_bootstrap_file(jcr, fd) ||
!response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
if (!send_runscripts_commands(jcr)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
/* Send restore command */
- char replace, *where;
- char empty = '\0';
if (jcr->replace != 0) {
replace = jcr->replace;
} else {
replace = REPLACE_ALWAYS; /* always replace */
}
- if (jcr->where) {
+
+ if (jcr->RegexWhere) {
+ where = jcr->RegexWhere; /* override */
+ cmd = restorecmdR;
+ } else if (jcr->job->RegexWhere) {
+ where = jcr->job->RegexWhere; /* no override take from job */
+ cmd = restorecmdR;
+
+ } else if (jcr->where) {
where = jcr->where; /* override */
+ cmd = restorecmd;
} else if (jcr->job->RestoreWhere) {
where = jcr->job->RestoreWhere; /* no override take from job */
- } else {
- where = ∅ /* None */
+ cmd = restorecmd;
+
+ } else { /* nothing was specified */
+ where = ∅ /* use default */
+ cmd = restorecmd;
}
+
jcr->prefix_links = jcr->job->PrefixLinks;
+
bash_spaces(where);
- bnet_fsend(fd, restorecmd, replace, jcr->prefix_links, where);
+ fd->fsend(cmd, replace, jcr->prefix_links, where);
unbash_spaces(where);
if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
- restore_cleanup(jcr, JS_ErrorTerminated);
- return false;
+ goto bail_out;
}
/* Wait for Job Termination */
- int stat = wait_for_job_termination(jcr);
+ stat = wait_for_job_termination(jcr);
restore_cleanup(jcr, stat);
-
return true;
+
+bail_out:
+ restore_cleanup(jcr, JS_ErrorTerminated);
+ return false;
}
bool do_restore_init(JCR *jcr)
jcr->unlink_bsr = false;
}
+ if (job_canceled(jcr)) {
+ cancel_storage_daemon_job(jcr);
+ }
+
switch (TermCode) {
case JS_Terminated:
if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
term_msg = _("Restore OK");
}
break;
+ case JS_Warnings:
+ term_msg = _("Restore OK -- with warnings");
+ break;
case JS_FatalError:
case JS_ErrorTerminated:
term_msg = _("*** Restore Error ***");
msg_type = M_ERROR; /* Generate error message */
if (jcr->store_bsock) {
- bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+ jcr->store_bsock->signal(BNET_TERMINATE);
if (jcr->SD_msg_chan) {
pthread_cancel(jcr->SD_msg_chan);
}
case JS_Canceled:
term_msg = _("Restore Canceled");
if (jcr->store_bsock) {
- bnet_sig(jcr->store_bsock, BNET_TERMINATE);
+ jcr->store_bsock->signal(BNET_TERMINATE);
if (jcr->SD_msg_chan) {
pthread_cancel(jcr->SD_msg_chan);
}
jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
- Jmsg(jcr, msg_type, 0, _("Bacula %s (%s): %s\n"
+ Jmsg(jcr, msg_type, 0, _("%s %s %s (%s): %s\n"
+" Build OS: %s %s %s\n"
" JobId: %d\n"
" Job: %s\n"
-" Client: %s\n"
+" Restore Client: %s\n"
" Start time: %s\n"
" End time: %s\n"
" Files Expected: %s\n"
" FD termination status: %s\n"
" SD termination status: %s\n"
" Termination: %s\n\n"),
- VERSION,
- LSMDATE,
- edt,
+ BACULA, my_name, VERSION, LSMDATE, edt,
+ HOST_OS, DISTNAME, DISTVER,
jcr->jr.JobId,
jcr->jr.Job,
- jcr->client->hdr.name,
+ jcr->client->name(),
sdt,
edt,
edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
(float)kbps,
- jcr->Errors,
+ jcr->JobErrors,
fd_term_msg,
sd_term_msg,
term_msg);