2 Bacula® - The Network Backup Solution
4 Copyright (C) 2000-2007 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 John Walker.
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 */
73 free_wstorage(jcr); /* we don't write */
75 memset(&rjr, 0, sizeof(rjr));
76 jcr->jr.JobLevel = L_FULL; /* Full restore */
77 if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
78 Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
79 restore_cleanup(jcr, JS_ErrorTerminated);
82 Dmsg0(20, "Updated job start record\n");
84 Dmsg1(20, "RestoreJobId=%d\n", jcr->job->RestoreJobId);
86 if (!jcr->RestoreBootstrap) {
87 Jmsg0(jcr, M_FATAL, 0, _("Cannot restore without a bootstrap file.\n"
88 "You probably ran a restore job directly. All restore jobs must\n"
89 "be run using the restore command.\n"));
90 restore_cleanup(jcr, JS_ErrorTerminated);
95 /* Print Job Start message */
96 Jmsg(jcr, M_INFO, 0, _("Start Restore Job %s\n"), jcr->Job);
99 * Open a message channel connection with the Storage
100 * daemon. This is to let him know that our client
101 * will be contacting him for a backup session.
104 Dmsg0(10, "Open connection with storage daemon\n");
105 set_jcr_job_status(jcr, JS_WaitSD);
107 * Start conversation with Storage daemon
109 if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
110 restore_cleanup(jcr, JS_ErrorTerminated);
114 * Now start a job with the Storage daemon
116 if (!start_storage_daemon_job(jcr, jcr->rstorage, NULL)) {
117 restore_cleanup(jcr, JS_ErrorTerminated);
120 if (!bnet_fsend(jcr->store_bsock, "run")) {
124 * Now start a Storage daemon message thread
126 if (!start_storage_daemon_message_thread(jcr)) {
127 restore_cleanup(jcr, JS_ErrorTerminated);
130 Dmsg0(50, "Storage daemon connection OK\n");
134 * Start conversation with File daemon
136 set_jcr_job_status(jcr, JS_WaitFD);
137 if (!connect_to_file_daemon(jcr, 10, FDConnectTimeout, 1)) {
138 cancel_storage_daemon_job(jcr);
139 restore_cleanup(jcr, JS_ErrorTerminated);
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 bnet_fsend(fd, 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)) {
157 restore_cleanup(jcr, JS_ErrorTerminated);
162 * Send the bootstrap file -- what Volumes/files to restore
164 if (!send_bootstrap_file(jcr, fd) ||
165 !response(jcr, fd, OKbootstrap, "Bootstrap", DISPLAY_ERROR)) {
166 restore_cleanup(jcr, JS_ErrorTerminated);
171 if (!send_runscripts_commands(jcr)) {
172 restore_cleanup(jcr, JS_ErrorTerminated);
176 /* Send restore command */
177 char replace, *where, *cmd=NULL;
180 if (jcr->replace != 0) {
181 replace = jcr->replace;
182 } else if (jcr->job->replace != 0) {
183 replace = jcr->job->replace;
185 replace = REPLACE_ALWAYS; /* always replace */
188 where = ∅ /* default */
190 if (jcr->RegexWhere) {
191 where = jcr->RegexWhere; /* override */
193 } else if (jcr->job->RegexWhere) {
194 where = jcr->job->RegexWhere; /* no override take from job */
197 } else if (jcr->where) {
198 where = jcr->where; /* override */
200 } else if (jcr->job->RestoreWhere) {
201 where = jcr->job->RestoreWhere; /* no override take from job */
205 jcr->prefix_links = jcr->job->PrefixLinks;
208 bnet_fsend(fd, cmd, replace, jcr->prefix_links, where);
209 unbash_spaces(where);
211 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
212 restore_cleanup(jcr, JS_ErrorTerminated);
216 /* Wait for Job Termination */
217 int stat = wait_for_job_termination(jcr);
218 restore_cleanup(jcr, stat);
223 bool do_restore_init(JCR *jcr)
230 * Release resources allocated during restore.
233 void restore_cleanup(JCR *jcr, int TermCode)
235 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
236 char ec1[30], ec2[30], ec3[30];
237 char term_code[100], fd_term_msg[100], sd_term_msg[100];
238 const char *term_msg;
239 int msg_type = M_INFO;
242 Dmsg0(20, "In restore_cleanup\n");
243 update_job_end(jcr, TermCode);
245 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
246 unlink(jcr->RestoreBootstrap);
247 jcr->unlink_bsr = false;
252 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
253 term_msg = _("Restore OK -- warning file count mismatch");
255 term_msg = _("Restore OK");
259 case JS_ErrorTerminated:
260 term_msg = _("*** Restore Error ***");
261 msg_type = M_ERROR; /* Generate error message */
262 if (jcr->store_bsock) {
263 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
264 if (jcr->SD_msg_chan) {
265 pthread_cancel(jcr->SD_msg_chan);
270 term_msg = _("Restore Canceled");
271 if (jcr->store_bsock) {
272 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
273 if (jcr->SD_msg_chan) {
274 pthread_cancel(jcr->SD_msg_chan);
279 term_msg = term_code;
280 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
283 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
284 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
285 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
286 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
294 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
295 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
297 Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
298 " Build OS: %s %s %s\n"
301 " Restore Client: %s\n"
304 " Files Expected: %s\n"
305 " Files Restored: %s\n"
306 " Bytes Restored: %s\n"
309 " FD termination status: %s\n"
310 " SD termination status: %s\n"
311 " Termination: %s\n\n"),
312 my_name, VERSION, LSMDATE, edt,
313 HOST_OS, DISTNAME, DISTVER,
319 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
320 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
321 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
328 Dmsg0(20, "Leaving restore_cleanup\n");