2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Bacula Director -- restore.c -- responsible for restoring files
31 * Kern Sibbald, November MM
33 * This routine is run as a separate thread.
35 * Current implementation is Catalog verification only (i.e. no
36 * verification versus tape).
38 * Basic tasks done here:
40 * Open Message Channel with Storage daemon to tell him a job will be starting.
41 * Open connection with File daemon and pass him commands
43 * Update the DB according to what files where restored????
52 /* Commands sent to File daemon */
53 static char restorecmd[] = "restore replace=%c prelinks=%d where=%s\n";
54 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
55 static char storaddr[] = "storage address=%s port=%d ssl=0\n";
57 /* Responses received from File daemon */
58 static char OKrestore[] = "2000 OK restore\n";
59 static char OKstore[] = "2000 OK storage\n";
60 static char OKbootstrap[] = "2000 OK bootstrap\n";
63 * Do a restore of the specified files
65 * Returns: 0 on failure
68 bool do_restore(JCR *jcr)
71 JOB_DBR rjr; /* restore job record */
72 char replace, *where, *cmd;
76 free_wstorage(jcr); /* we don't write */
78 if (!allow_duplicate_job(jcr)) {
82 memset(&rjr, 0, sizeof(rjr));
83 jcr->jr.JobLevel = L_FULL; /* Full restore */
84 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
85 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
88 Dmsg0(20, "Updated job start record\n");
90 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
92 if (!jcr->RestoreBootstrap) {
93 Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
94 "You probably ran a restore job directly. All restore jobs must\n"
95 "be run using the restore command.\n"));
100 /* Print Job Start message */
101 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
104 * Open a message channel connection with the Storage
105 * daemon. This is to let him know that our client
106 * will be contacting him for a backup session.
109 Dmsg0(10, "Open connection with storage daemon\n");
110 set_jcr_job_status(jcr, JS_WaitSD);
112 * Start conversation with Storage daemon
114 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
118 * Now start a job with the Storage daemon
120 if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
123 if (!jcr->store_bsock->fsend("run")) {
127 * Now start a Storage daemon message thread
129 if (!start_storage_daemon_message_thread(jcr)) {
132 Dmsg0(50, "Storage daemon connection OK\n");
136 * Start conversation with File daemon
138 set_jcr_job_status(jcr, JS_WaitFD);
139 if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
143 fd = jcr->file_bsock;
144 set_jcr_job_status(jcr, JS_Running);
147 * send Storage daemon address to the File daemon,
148 * then wait for File daemon to make connection
149 * with Storage daemon.
151 if (jcr->rstore->SDDport == 0) {
152 jcr->rstore->SDDport = jcr->rstore->SDport;
154 fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport);
155 Dmsg1(6, "dird>filed: %s\n", fd->msg);
156 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
161 * Send the bootstrap file -- what Volumes/files to restore
163 if (!send_bootstrap_file(jcr, fd) ||
164 !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
169 if (!send_runscripts_commands(jcr)) {
173 /* Send restore command */
175 if (jcr->replace != 0) {
176 replace = jcr->replace;
177 } else if (jcr->job->replace != 0) {
178 replace = jcr->job->replace;
180 replace = REPLACE_ALWAYS; /* always replace */
183 if (jcr->RegexWhere) {
184 where = jcr->RegexWhere; /* override */
186 } else if (jcr->job->RegexWhere) {
187 where = jcr->job->RegexWhere; /* no override take from job */
190 } else if (jcr->where) {
191 where = jcr->where; /* override */
193 } else if (jcr->job->RestoreWhere) {
194 where = jcr->job->RestoreWhere; /* no override take from job */
197 } else { /* nothing was specified */
198 where = ∅ /* use default */
202 jcr->prefix_links = jcr->job->PrefixLinks;
205 fd->fsend(cmd, replace, jcr->prefix_links, where);
206 unbash_spaces(where);
208 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
212 /* Wait for Job Termination */
213 stat = wait_for_job_termination(jcr);
214 restore_cleanup(jcr, stat);
218 restore_cleanup(jcr, JS_ErrorTerminated);
222 bool do_restore_init(JCR *jcr)
229 * Release resources allocated during restore.
232 void restore_cleanup(JCR *jcr, int TermCode)
234 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
235 char ec1[30], ec2[30], ec3[30];
236 char term_code[100], fd_term_msg[100], sd_term_msg[100];
237 const char *term_msg;
238 int msg_type = M_INFO;
241 Dmsg0(20, "In restore_cleanup\n");
242 update_job_end(jcr, TermCode);
244 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
245 unlink(jcr->RestoreBootstrap);
246 jcr->unlink_bsr = false;
249 if (job_canceled(jcr)) {
250 cancel_storage_daemon_job(jcr);
255 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
256 term_msg = _("Restore OK -- warning file count mismatch");
258 term_msg = _("Restore OK");
262 case JS_ErrorTerminated:
263 term_msg = _("*** Restore Error ***");
264 msg_type = M_ERROR; /* Generate error message */
265 if (jcr->store_bsock) {
266 jcr->store_bsock->signal(BNET_TERMINATE);
267 if (jcr->SD_msg_chan) {
268 pthread_cancel(jcr->SD_msg_chan);
273 term_msg = _("Restore Canceled");
274 if (jcr->store_bsock) {
275 jcr->store_bsock->signal(BNET_TERMINATE);
276 if (jcr->SD_msg_chan) {
277 pthread_cancel(jcr->SD_msg_chan);
282 term_msg = term_code;
283 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
286 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
287 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
288 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
289 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
297 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
298 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
300 Jmsg(jcr, msg_type, 0, _("%s %s %s (%s): %s\n"
301 " Build OS: %s %s %s\n"
304 " Restore Client: %s\n"
307 " Files Expected: %s\n"
308 " Files Restored: %s\n"
309 " Bytes Restored: %s\n"
312 " FD termination status: %s\n"
313 " SD termination status: %s\n"
314 " Termination: %s\n\n"),
315 BACULA, my_name, VERSION, LSMDATE, edt,
316 HOST_OS, DISTNAME, DISTVER,
322 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
323 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
324 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
331 Dmsg0(20, "Leaving restore_cleanup\n");