2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2009 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 Authorization=%s\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 OKstoreend[] = "2000 OK storage end\n";
62 /* Responses received from the Storage daemon */
63 static char OKbootstrap[] = "3000 OK bootstrap\n";
65 static void build_restore_command(JCR *jcr, POOL_MEM &ret)
67 char replace, *where, *cmd;
70 /* Build the restore command */
72 if (jcr->replace != 0) {
73 replace = jcr->replace;
74 } else if (jcr->job->replace != 0) {
75 replace = jcr->job->replace;
77 replace = REPLACE_ALWAYS; /* always replace */
80 if (jcr->RegexWhere) {
81 where = jcr->RegexWhere; /* override */
83 } else if (jcr->job->RegexWhere) {
84 where = jcr->job->RegexWhere; /* no override take from job */
87 } else if (jcr->where) {
88 where = jcr->where; /* override */
90 } else if (jcr->job->RestoreWhere) {
91 where = jcr->job->RestoreWhere; /* no override take from job */
94 } else { /* nothing was specified */
95 where = ∅ /* use default */
99 jcr->prefix_links = jcr->job->PrefixLinks;
102 Mmsg(ret, cmd, replace, jcr->prefix_links, where);
103 unbash_spaces(where);
106 struct bootstrap_info
110 char storage[MAX_NAME_LENGTH+1];
113 #define UA_CMD_SIZE 1000
115 /* Open the bootstrap file and find the first Storage=
116 * Returns ok if able to open
117 * It fills the storage name (should be the first line)
118 * and the file descriptor to the bootstrap file,
119 * it should be used for next operations, and need to be closed
122 static bool open_bootstrap_file(JCR *jcr, struct bootstrap_info &info)
129 if (!jcr->RestoreBootstrap) {
132 strncpy(info.storage, jcr->rstore->name(), MAX_NAME_LENGTH);
134 bs = fopen(jcr->RestoreBootstrap, "rb");
137 Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
138 jcr->RestoreBootstrap, be.bstrerror());
139 set_jcr_job_status(jcr, JS_ErrorTerminated);
143 ua = new_ua_context(jcr);
144 ua->cmd = check_pool_memory_size(ua->cmd, UA_CMD_SIZE+1);
145 while (!fgets(ua->cmd, UA_CMD_SIZE, bs)) {
150 if (!strcasecmp(ua->argk[0], "Storage")) {
151 strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
157 fseek(bs, 0, SEEK_SET); /* return to the top of the file */
162 * This function compare the given storage name with the
163 * the current one. We compare the name and the address:port.
164 * Returns true if we use the same storage.
166 static bool is_on_same_storage(JCR *jcr, char *new_one)
170 /* with old FD, we send the whole bootstrap to the storage */
171 if (jcr->FDVersion < 2) {
174 /* we are in init loop ? shoudn't fall here */
179 if (!strcmp(new_one, jcr->rstore->name())) {
182 new_store = (STORE *)GetResWithName(R_STORAGE, new_one);
184 Jmsg(jcr, M_FATAL, 0,
185 _("Could not get storage resource '%s'.\n"), new_one);
186 set_jcr_job_status(jcr, JS_ErrorTerminated);
189 /* if Port and Hostname/IP are same, we are talking to the same
192 if (jcr->rstore->SDport != new_store->SDport ||
193 strcmp(jcr->rstore->address, new_store->address))
201 * Check if the current line contains Storage="xxx", and compare the
202 * result to the current storage. We use UAContext to analyse the bsr
205 * Returns true if we need to change the storage, and it set the new
206 * Storage resource name in "storage" arg.
208 static bool check_for_new_storage(JCR *jcr, struct bootstrap_info &info)
210 UAContext *ua = info.ua;
215 if (!strcasecmp(ua->argk[0], "Storage")) {
216 /* Continue if this is a volume from the same storage. */
217 if (is_on_same_storage(jcr, ua->argv[0])) {
220 /* note the next storage name */
221 strncpy(info.storage, ua->argv[0], MAX_NAME_LENGTH);
222 Dmsg1(5, "Change storage to %s\n", info.storage);
229 * Send bootstrap file to Storage daemon section by section.
231 static bool send_bootstrap_file(JCR *jcr, BSOCK *sock,
232 struct bootstrap_info &info)
235 const char *bootstrap = "bootstrap\n";
236 UAContext *ua = info.ua;
239 Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
240 if (!jcr->RestoreBootstrap) {
243 sock->fsend(bootstrap);
245 while(fgets(ua->cmd, UA_CMD_SIZE, bs)) {
246 if (check_for_new_storage(jcr, info)) {
247 /* Otherwise, we need to contact another storage daemon.
248 * Reset bs to the beginning of the current segment.
250 fseeko(bs, pos, SEEK_SET);
253 sock->fsend("%s", ua->cmd);
256 sock->signal(BNET_EOD);
261 * Change the read storage resource for the current job.
263 static void select_rstore(JCR *jcr, struct bootstrap_info &info)
266 if (!strcmp(jcr->rstore->name(), info.storage)) {
270 if (!(ustore.store = (STORE *)GetResWithName(R_STORAGE,info.storage))) {
271 Jmsg(jcr, M_FATAL, 0,
272 _("Could not get storage resource '%s'.\n"), info.storage);
273 set_jcr_job_status(jcr, JS_ErrorTerminated);
277 if (jcr->store_bsock) {
278 jcr->store_bsock->destroy();
279 jcr->store_bsock = NULL;
283 set_rstorage(jcr, &ustore);
287 * Clean the struct bootstrap_info struct
289 static void close_bootstrap_file(struct bootstrap_info &info)
295 free_ua_context(info.ua);
300 * Take a bootstrap and for each different storage, we change the storage
301 * resource and start a new restore session between the client and the storage
304 bool restore_bootstrap(JCR *jcr)
308 bool first_time=true;
309 struct bootstrap_info info;
310 POOL_MEM restore_cmd(PM_MESSAGE);
313 /* this command is used for each part */
314 build_restore_command(jcr, restore_cmd);
316 if (!open_bootstrap_file(jcr, info)) {
319 while (!end_loop && !feof(info.bs)) {
321 select_rstore(jcr, info);
324 * Open a message channel connection with the Storage
325 * daemon. This is to let him know that our client
326 * will be contacting him for a backup session.
329 Dmsg0(10, "Open connection with storage daemon\n");
330 set_jcr_job_status(jcr, JS_WaitSD);
332 * Start conversation with Storage daemon
334 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
337 sd = jcr->store_bsock;
339 * Now start a job with the Storage daemon
341 if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
347 * Start conversation with File daemon
349 set_jcr_job_status(jcr, JS_WaitFD);
350 jcr->keep_sd_auth_key = true; /* don't clear the sd_auth_key now */
351 if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
355 fd = jcr->file_bsock;
358 set_jcr_job_status(jcr, JS_WaitSD);
361 * Send the bootstrap file -- what Volumes/files to restore
363 if (!send_bootstrap_file(jcr, sd, info) ||
364 !response(jcr, sd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
368 if (!sd->fsend("run")) {
372 * Now start a Storage daemon message thread
374 if (!start_storage_daemon_message_thread(jcr)) {
377 Dmsg0(50, "Storage daemon connection OK\n");
380 * send Storage daemon address to the File daemon,
381 * then wait for File daemon to make connection
382 * with Storage daemon.
384 if (jcr->rstore->SDDport == 0) {
385 jcr->rstore->SDDport = jcr->rstore->SDport;
387 fd->fsend(storaddr, jcr->rstore->address, jcr->rstore->SDDport,
389 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
391 Dmsg1(6, "dird>filed: %s\n", fd->msg);
392 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
397 if (!send_runscripts_commands(jcr)) {
403 fd->fsend("%s", restore_cmd.c_str());
405 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
409 if (jcr->FDVersion < 2) { /* Old FD */
410 end_loop=true; /* we do only one loop */
413 if (!response(jcr, fd, OKstoreend, "Store end", DISPLAY_ERROR)) {
416 wait_for_storage_daemon_termination(jcr);
418 } /* the whole boostrap has been send */
420 if (fd && jcr->FDVersion >= 2) {
421 fd->fsend("endrestore");
427 close_bootstrap_file(info);
432 * Do a restore of the specified files
434 * Returns: 0 on failure
437 bool do_restore(JCR *jcr)
439 JOB_DBR rjr; /* restore job record */
442 free_wstorage(jcr); /* we don't write */
444 if (!allow_duplicate_job(jcr)) {
448 memset(&rjr, 0, sizeof(rjr));
449 jcr->jr.JobLevel = L_FULL; /* Full restore */
450 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
451 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
454 Dmsg0(20, "Updated job start record\n");
456 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
458 if (!jcr->RestoreBootstrap) {
459 Jmsg(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
460 "You probably ran a restore job directly. All restore jobs must\n"
461 "be run using the restore command.\n"));
466 /* Print Job Start message */
467 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
469 if (!restore_bootstrap(jcr)) {
473 /* Wait for Job Termination */
474 stat = wait_for_job_termination(jcr);
475 restore_cleanup(jcr, stat);
479 restore_cleanup(jcr, JS_ErrorTerminated);
483 bool do_restore_init(JCR *jcr)
490 * Release resources allocated during restore.
493 void restore_cleanup(JCR *jcr, int TermCode)
495 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
496 char ec1[30], ec2[30], ec3[30];
497 char term_code[100], fd_term_msg[100], sd_term_msg[100];
498 const char *term_msg;
499 int msg_type = M_INFO;
502 Dmsg0(20, "In restore_cleanup\n");
503 update_job_end(jcr, TermCode);
505 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
506 unlink(jcr->RestoreBootstrap);
507 jcr->unlink_bsr = false;
510 if (job_canceled(jcr)) {
511 cancel_storage_daemon_job(jcr);
516 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
517 term_msg = _("Restore OK -- warning file count mismatch");
519 term_msg = _("Restore OK");
523 term_msg = _("Restore OK -- with warnings");
526 case JS_ErrorTerminated:
527 term_msg = _("*** Restore Error ***");
528 msg_type = M_ERROR; /* Generate error message */
529 if (jcr->store_bsock) {
530 jcr->store_bsock->signal(BNET_TERMINATE);
531 if (jcr->SD_msg_chan) {
532 pthread_cancel(jcr->SD_msg_chan);
537 term_msg = _("Restore Canceled");
538 if (jcr->store_bsock) {
539 jcr->store_bsock->signal(BNET_TERMINATE);
540 if (jcr->SD_msg_chan) {
541 pthread_cancel(jcr->SD_msg_chan);
546 term_msg = term_code;
547 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
550 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
551 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
552 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
553 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
561 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
562 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
564 Jmsg(jcr, msg_type, 0, _("%s %s %s (%s): %s\n"
565 " Build OS: %s %s %s\n"
568 " Restore Client: %s\n"
571 " Files Expected: %s\n"
572 " Files Restored: %s\n"
573 " Bytes Restored: %s\n"
576 " FD termination status: %s\n"
577 " SD termination status: %s\n"
578 " Termination: %s\n\n"),
579 BACULA, my_name, VERSION, LSMDATE, edt,
580 HOST_OS, DISTNAME, DISTVER,
586 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
587 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
588 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
595 Dmsg0(20, "Leaving restore_cleanup\n");