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 plus additions
11 that are listed in the file LICENSE.
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 restore_cleanup(jcr, JS_ErrorTerminated);
142 fd = jcr->file_bsock;
143 set_jcr_job_status(jcr, JS_Running);
146 * send Storage daemon address to the File daemon,
147 * then wait for File daemon to make connection
148 * with Storage daemon.
150 if (jcr->rstore->SDDport == 0) {
151 jcr->rstore->SDDport = jcr->rstore->SDport;
153 bnet_fsend(fd, storaddr, jcr->rstore->address, jcr->rstore->SDDport);
154 Dmsg1(6, "dird>filed: %s\n", fd->msg);
155 if (!response(jcr, fd, OKstore, "Storage", DISPLAY_ERROR)) {
156 restore_cleanup(jcr, JS_ErrorTerminated);
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)) {
165 restore_cleanup(jcr, JS_ErrorTerminated);
170 if (!send_runscripts_commands(jcr)) {
171 restore_cleanup(jcr, JS_ErrorTerminated);
175 /* Send restore command */
176 char replace, *where, *cmd=NULL;
179 if (jcr->replace != 0) {
180 replace = jcr->replace;
181 } else if (jcr->job->replace != 0) {
182 replace = jcr->job->replace;
184 replace = REPLACE_ALWAYS; /* always replace */
187 where = ∅ /* default */
189 if (jcr->RegexWhere) {
190 where = jcr->RegexWhere; /* override */
192 } else if (jcr->job->RegexWhere) {
193 where = jcr->job->RegexWhere; /* no override take from job */
196 } else if (jcr->where) {
197 where = jcr->where; /* override */
199 } else if (jcr->job->RestoreWhere) {
200 where = jcr->job->RestoreWhere; /* no override take from job */
204 jcr->prefix_links = jcr->job->PrefixLinks;
207 bnet_fsend(fd, cmd, replace, jcr->prefix_links, where);
208 unbash_spaces(where);
210 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
211 restore_cleanup(jcr, JS_ErrorTerminated);
215 /* Wait for Job Termination */
216 int stat = wait_for_job_termination(jcr);
217 restore_cleanup(jcr, stat);
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;
251 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
252 term_msg = _("Restore OK -- warning file count mismatch");
254 term_msg = _("Restore OK");
258 case JS_ErrorTerminated:
259 term_msg = _("*** Restore Error ***");
260 msg_type = M_ERROR; /* Generate error message */
261 if (jcr->store_bsock) {
262 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
263 if (jcr->SD_msg_chan) {
264 pthread_cancel(jcr->SD_msg_chan);
269 term_msg = _("Restore Canceled");
270 if (jcr->store_bsock) {
271 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
272 if (jcr->SD_msg_chan) {
273 pthread_cancel(jcr->SD_msg_chan);
278 term_msg = term_code;
279 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
282 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
283 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
284 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
285 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
293 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
294 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
296 Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
297 " Build OS: %s %s %s\n"
300 " Restore Client: %s\n"
303 " Files Expected: %s\n"
304 " Files Restored: %s\n"
305 " Bytes Restored: %s\n"
308 " FD termination status: %s\n"
309 " SD termination status: %s\n"
310 " Termination: %s\n\n"),
311 my_name, VERSION, LSMDATE, edt,
312 HOST_OS, DISTNAME, DISTVER,
318 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
319 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
320 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
327 Dmsg0(20, "Leaving restore_cleanup\n");