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;
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 = jcr->where; /* override */
188 } else if (jcr->job->RestoreWhere) {
189 where = jcr->job->RestoreWhere; /* no override take from job */
191 where = ∅ /* None */
194 jcr->prefix_links = jcr->job->PrefixLinks;
196 if (jcr->where_use_regexp) {
203 bnet_fsend(fd, cmd, replace, jcr->prefix_links, where);
204 unbash_spaces(where);
206 if (!response(jcr, fd, OKrestore, "Restore", DISPLAY_ERROR)) {
207 restore_cleanup(jcr, JS_ErrorTerminated);
211 /* Wait for Job Termination */
212 int stat = wait_for_job_termination(jcr);
213 restore_cleanup(jcr, stat);
218 bool do_restore_init(JCR *jcr)
225 * Release resources allocated during restore.
228 void restore_cleanup(JCR *jcr, int TermCode)
230 char sdt[MAX_TIME_LENGTH], edt[MAX_TIME_LENGTH];
231 char ec1[30], ec2[30], ec3[30];
232 char term_code[100], fd_term_msg[100], sd_term_msg[100];
233 const char *term_msg;
234 int msg_type = M_INFO;
237 Dmsg0(20, "In restore_cleanup\n");
238 update_job_end(jcr, TermCode);
240 if (jcr->unlink_bsr && jcr->RestoreBootstrap) {
241 unlink(jcr->RestoreBootstrap);
242 jcr->unlink_bsr = false;
247 if (jcr->ExpectedFiles > jcr->jr.JobFiles) {
248 term_msg = _("Restore OK -- warning file count mismatch");
250 term_msg = _("Restore OK");
254 case JS_ErrorTerminated:
255 term_msg = _("*** Restore Error ***");
256 msg_type = M_ERROR; /* Generate error message */
257 if (jcr->store_bsock) {
258 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
259 if (jcr->SD_msg_chan) {
260 pthread_cancel(jcr->SD_msg_chan);
265 term_msg = _("Restore Canceled");
266 if (jcr->store_bsock) {
267 bnet_sig(jcr->store_bsock, BNET_TERMINATE);
268 if (jcr->SD_msg_chan) {
269 pthread_cancel(jcr->SD_msg_chan);
274 term_msg = term_code;
275 sprintf(term_code, _("Inappropriate term code: %c\n"), TermCode);
278 bstrftimes(sdt, sizeof(sdt), jcr->jr.StartTime);
279 bstrftimes(edt, sizeof(edt), jcr->jr.EndTime);
280 if (jcr->jr.EndTime - jcr->jr.StartTime > 0) {
281 kbps = (double)jcr->jr.JobBytes / (1000 * (jcr->jr.EndTime - jcr->jr.StartTime));
289 jobstatus_to_ascii(jcr->FDJobStatus, fd_term_msg, sizeof(fd_term_msg));
290 jobstatus_to_ascii(jcr->SDJobStatus, sd_term_msg, sizeof(sd_term_msg));
292 Jmsg(jcr, msg_type, 0, _("Bacula %s %s (%s): %s\n"
293 " Build OS: %s %s %s\n"
299 " Files Expected: %s\n"
300 " Files Restored: %s\n"
301 " Bytes Restored: %s\n"
304 " FD termination status: %s\n"
305 " SD termination status: %s\n"
306 " Termination: %s\n\n"),
307 my_name, VERSION, LSMDATE, edt,
308 HOST_OS, DISTNAME, DISTVER,
311 jcr->client->hdr.name,
314 edit_uint64_with_commas((uint64_t)jcr->ExpectedFiles, ec1),
315 edit_uint64_with_commas((uint64_t)jcr->jr.JobFiles, ec2),
316 edit_uint64_with_commas(jcr->jr.JobBytes, ec3),
323 Dmsg0(20, "Leaving restore_cleanup\n");