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 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;
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 bnet_sig(jcr->store_bsock, 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 bnet_sig(jcr->store_bsock, 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, _("Bacula %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 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");