2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
5 Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
7 The original author of Bacula is Kern Sibbald, with contributions
8 from many others, a complete list can be found in the file AUTHORS.
10 You may use this file and others of this release according to the
11 license defined in the LICENSE file, which includes the Affero General
12 Public License, v3.0 ("AGPLv3") and some additional permissions and
13 terms pursuant to its AGPLv3 Section 7.
15 This notice must be preserved when any source code is
16 conveyed and/or propagated.
18 Bacula(R) is a registered trademark of Kern Sibbald.
21 * Bacula File Daemon Job processing
23 * Written by Kern Sibbald, October MM
32 bool win32decomp = false;
33 bool no_win32_write_errors = false;
35 /* Static variables */
36 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
39 const bool have_win32 = false;
42 const bool have_acl = true;
44 const bool have_acl = false;
48 const bool have_xattr = true;
50 const bool have_xattr = false;
53 extern CLIENT *me; /* our client resource */
55 /* Imported functions */
56 extern int status_cmd(JCR *jcr);
57 extern int qstatus_cmd(JCR *jcr);
58 extern int accurate_cmd(JCR *jcr);
60 /* Forward referenced functions */
61 static int backup_cmd(JCR *jcr);
62 static int component_cmd(JCR *jcr);
63 static int cancel_cmd(JCR *jcr);
64 static int setdebug_cmd(JCR *jcr);
65 static int setbandwidth_cmd(JCR *jcr);
66 static int estimate_cmd(JCR *jcr);
67 static int hello_cmd(JCR *jcr);
68 static int job_cmd(JCR *jcr);
69 static int fileset_cmd(JCR *jcr);
70 static int level_cmd(JCR *jcr);
71 static int verify_cmd(JCR *jcr);
72 static int restore_cmd(JCR *jcr);
73 static int end_restore_cmd(JCR *jcr);
74 static int storage_cmd(JCR *jcr);
75 static int session_cmd(JCR *jcr);
76 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
77 static void filed_free_jcr(JCR *jcr);
78 static int open_sd_read_session(JCR *jcr);
79 static int runscript_cmd(JCR *jcr);
80 static int runbefore_cmd(JCR *jcr);
81 static int runafter_cmd(JCR *jcr);
82 static int runbeforenow_cmd(JCR *jcr);
83 static int restore_object_cmd(JCR *jcr);
84 static int set_options(findFOPTS *fo, const char *opts);
85 static void set_storage_auth_key(JCR *jcr, char *key);
86 static int sm_dump_cmd(JCR *jcr);
88 static int exit_cmd(JCR *jcr);
91 /* Exported functions */
95 * The following are the recognized commands from the Director.
97 struct s_cmds cmds[] = {
98 {"backup", backup_cmd, 0},
99 {"cancel", cancel_cmd, 0},
100 {"setdebug=", setdebug_cmd, 0},
101 {"setbandwidth=",setbandwidth_cmd, 0},
102 {"snapshot", snapshot_cmd, 0},
103 {"estimate", estimate_cmd, 0},
104 {"Hello", hello_cmd, 1},
105 {"fileset", fileset_cmd, 0},
106 {"JobId=", job_cmd, 0},
107 {"level = ", level_cmd, 0},
108 {"restore ", restore_cmd, 0},
109 {"endrestore", end_restore_cmd, 0},
110 {"session", session_cmd, 0},
111 {"status", status_cmd, 1},
112 {".status", qstatus_cmd, 1},
113 {"storage ", storage_cmd, 0},
114 {"verify", verify_cmd, 0},
115 {"component", component_cmd, 0},
116 {"RunBeforeNow", runbeforenow_cmd, 0},
117 {"RunBeforeJob", runbefore_cmd, 0},
118 {"RunAfterJob", runafter_cmd, 0},
119 {"Run", runscript_cmd, 0},
120 {"accurate", accurate_cmd, 0},
121 {"restoreobject", restore_object_cmd, 0},
122 {"sm_dump", sm_dump_cmd, 0},
123 {"stop", cancel_cmd, 0},
125 {"exit", exit_cmd, 0},
127 {NULL, NULL} /* list terminator */
130 /* Commands received from director that need scanning */
131 static char jobcmd[] = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
132 static char storaddr[] = "storage address=%s port=%d ssl=%d Authorization=%100s";
133 static char storaddr_v1[] = "storage address=%s port=%d ssl=%d";
134 static char sessioncmd[] = "session %127s %ld %ld %ld %ld %ld %ld\n";
136 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
137 static char restorefcmd1[] = "restore files=%d replace=%c prelinks=%d where=\n";
139 /* The following restore commands may have a big where=/regexwhere= parameter
140 * the bsscanf is limiting the default %s to 1000c. To allow more than 1000 bytes,
141 * we can specify %xxxxs where xxxx is the size expected in bytes.
143 * So, the code will add %s\n to the end of the following restore commands
145 static char restorecmd[] = "restore replace=%c prelinks=%d where=";
146 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=";
147 static char restorefcmd[] = "restore files=%d replace=%c prelinks=%d where=";
148 static char restorefcmdR[] = "restore files=%d replace=%c prelinks=%d regexwhere=";
150 static char restoreobjcmd[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d,%s";
151 static char restoreobjcmd1[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
152 static char endrestoreobjectcmd[] = "restoreobject end\n";
153 static char verifycmd[] = "verify level=%30s";
154 static char estimatecmd[] = "estimate listing=%d";
155 static char runbefore[] = "RunBeforeJob %s";
156 static char runafter[] = "RunAfterJob %s";
157 static char runscript[] = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
158 static char setbandwidth[]= "setbandwidth=%lld Job=%127s";
160 /* Responses sent to Director */
161 static char errmsg[] = "2999 Invalid command\n";
162 static char no_auth[] = "2998 No Authorization\n";
163 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
164 static char OKBandwidth[] = "2000 OK Bandwidth\n";
165 static char OKinc[] = "2000 OK include\n";
166 static char OKest[] = "2000 OK estimate files=%s bytes=%s\n";
167 static char OKlevel[] = "2000 OK level\n";
168 static char OKbackup[] = "2000 OK backup\n";
169 static char OKverify[] = "2000 OK verify\n";
170 static char OKrestore[] = "2000 OK restore\n";
171 static char OKsession[] = "2000 OK session\n";
172 static char OKstore[] = "2000 OK storage\n";
173 static char OKstoreend[] = "2000 OK storage end\n";
174 static char OKjob[] = "2000 OK Job %s (%s) %s,%s,%s";
175 static char OKsetdebug[] = "2000 OK setdebug=%ld trace=%ld hangup=%ld"
176 " blowup=%ld options=%s tags=%s\n";
177 static char BADjob[] = "2901 Bad Job\n";
178 static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%d ReadBytes=%lld"
179 " JobBytes=%lld Errors=%d VSS=%d Encrypt=%d"
180 " CommBytes=0 CompressCommBytes=0\n";
181 static char OKRunBefore[] = "2000 OK RunBefore\n";
182 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
183 static char OKRunAfter[] = "2000 OK RunAfter\n";
184 static char OKRunScript[] = "2000 OK RunScript\n";
185 static char BADcmd[] = "2902 Bad %s\n";
186 static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
187 static char OKComponentInfo[] = "2000 OK ComponentInfo\n";
190 /* Responses received from Storage Daemon */
191 static char OK_end[] = "3000 OK end\n";
192 static char OK_close[] = "3000 OK close Status = %d\n";
193 static char OK_open[] = "3000 OK open ticket = %d\n";
194 static char OK_data[] = "3000 OK data\n";
195 static char OK_append[] = "3000 OK append data\n";
198 /* Commands sent to Storage Daemon */
199 static char append_open[] = "append open session\n";
200 static char append_data[] = "append data %d\n";
201 static char append_end[] = "append end session %d\n";
202 static char append_close[] = "append close session %d\n";
203 static char read_open[] = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
204 static char read_data[] = "read data %d\n";
205 static char read_close[] = "read close session %d\n";
206 static char read_ctrl[] = "read control %d\n";
209 * Accept requests from a Director
211 * NOTE! We are running as a separate thread
213 * Send output one line
214 * at a time followed by a zero length transmission.
216 * Return when the connection is terminated or there
219 * Basic task here is:
220 * Authenticate Director (during Hello command).
221 * Accept commands one at a time from the Director
224 * Concerning ClientRunBefore/After, the sequence of events
225 * is rather critical. If they are not done in the right
226 * order one can easily get FD->SD timeouts if the script
229 * The current sequence of events is:
230 * 1. Dir starts job with FD
231 * 2. Dir connects to SD
232 * 3. Dir connects to FD
233 * 4. FD connects to SD
234 * 5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
235 * 6. Dir sends include/exclude
236 * 7. FD sends the file data to SD
237 * 8. SD/FD disconnects while the SD despools data and attributes (optional)
238 * 9. FD runs ClientRunAfterJob
241 static void *handle_director_request(BSOCK *dir)
247 const char jobname[12] = "*Director*";
249 prevent_os_suspensions(); /* do not suspend during backup/restore */
250 jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
251 jcr->sd_calls_client_bsock = NULL;
252 jcr->sd_calls_client = false;
253 jcr->dir_bsock = dir;
254 jcr->ff = init_find_files();
255 jcr->start_time = time(NULL);
256 jcr->RunScripts = New(alist(10, not_owned_by_alist));
257 jcr->last_fname = get_pool_memory(PM_FNAME);
258 jcr->last_fname[0] = 0;
259 jcr->client_name = get_memory(strlen(my_name) + 1);
260 pm_strcpy(jcr->client_name, my_name);
261 bstrncpy(jcr->Job, jobname, sizeof(jobname)); /* dummy */
262 jcr->crypto.pki_sign = me->pki_sign;
263 jcr->crypto.pki_encrypt = me->pki_encrypt;
264 jcr->crypto.pki_keypair = me->pki_keypair;
265 jcr->crypto.pki_signers = me->pki_signers;
266 jcr->crypto.pki_recipients = me->pki_recipients;
269 /* Initialize SD start condition variable */
270 int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
273 Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat));
276 enable_backup_privileges(NULL, 1 /* ignore_errors */);
278 for (quit=false; !quit;) {
279 if (!first) { /* first call the read is done */
281 if (dir->recv() < 0) {
282 break; /* connection terminated */
285 if (dir->msglen == 0) { /* Bad connection */
289 dir->msg[dir->msglen] = 0;
290 Dmsg1(100, "<dird: %s", dir->msg);
292 for (i=0; cmds[i].cmd; i++) {
293 if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
294 found = true; /* indicate command found */
295 if (!jcr->authenticated && cmds[i].func != hello_cmd) {
297 dir->signal(BNET_EOD);
300 if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) {
301 Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
302 dir->fsend(invalid_cmd);
303 dir->signal(BNET_EOD);
306 if ((me->disabled_cmds_array && me->disabled_cmds_array[i]) ||
307 (jcr->director && jcr->director->disabled_cmds_array &&
308 jcr->director->disabled_cmds_array[i])) {
309 Jmsg(jcr, M_FATAL, 0, _("Command: \"%s\" is disabled.\n"), cmds[i].cmd);
313 Dmsg1(100, "Executing Dir %s command.\n", dir->msg);
314 if (!cmds[i].func(jcr)) { /* do command */
315 quit = true; /* error or fully terminated, get out */
316 Dmsg1(100, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
321 if (!found) { /* command not found */
328 /* Inform Storage daemon that we are done */
329 if (jcr->store_bsock) {
330 jcr->store_bsock->signal(BNET_TERMINATE);
333 /* Run the after job */
334 run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
336 if (jcr->JobId) { /* send EndJob if running a job */
337 uint32_t vss, encrypt;
338 /* Send termination status back to Dir */
339 encrypt = jcr->crypto.pki_encrypt;
341 dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles,
342 jcr->ReadBytes, jcr->JobBytes, jcr->JobErrors, vss,
344 //Dmsg0(0/*110*/, dir->msg);
347 generate_daemon_event(jcr, "JobEnd");
348 generate_plugin_event(jcr, bEventJobEnd);
351 dequeue_messages(jcr); /* send any queued messages */
353 /* Inform Director that we are done */
354 dir->signal(BNET_TERMINATE);
356 free_and_null_pool_memory(jcr->job_metadata);
358 /* Clean up fileset */
359 FF_PKT *ff = jcr->ff;
360 findFILESET *fileset = ff->fileset;
363 /* Delete FileSet Include lists */
364 for (i=0; i<fileset->include_list.size(); i++) {
365 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
366 for (j=0; j<incexe->opts_list.size(); j++) {
367 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
371 for (k=0; k<fo->regex.size(); k++) {
372 regfree((regex_t *)fo->regex.get(k));
374 for (k=0; k<fo->regexdir.size(); k++) {
375 regfree((regex_t *)fo->regexdir.get(k));
377 for (k=0; k<fo->regexfile.size(); k++) {
378 regfree((regex_t *)fo->regexfile.get(k));
381 fo->regexdir.destroy();
382 fo->regexfile.destroy();
384 fo->wilddir.destroy();
385 fo->wildfile.destroy();
386 fo->wildbase.destroy();
388 fo->fstype.destroy();
389 fo->drivetype.destroy();
391 incexe->opts_list.destroy();
392 incexe->name_list.destroy();
393 incexe->plugin_list.destroy();
394 if (incexe->ignoredir) {
395 free(incexe->ignoredir);
398 fileset->include_list.destroy();
400 /* Delete FileSet Exclude lists */
401 for (i=0; i<fileset->exclude_list.size(); i++) {
402 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
403 for (j=0; j<incexe->opts_list.size(); j++) {
404 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
406 fo->regexdir.destroy();
407 fo->regexfile.destroy();
409 fo->wilddir.destroy();
410 fo->wildfile.destroy();
411 fo->wildbase.destroy();
413 fo->fstype.destroy();
414 fo->drivetype.destroy();
416 incexe->opts_list.destroy();
417 incexe->name_list.destroy();
418 incexe->plugin_list.destroy();
419 if (incexe->ignoredir) {
420 free(incexe->ignoredir);
423 fileset->exclude_list.destroy();
427 ff->mount_points.destroy();
428 Dmsg0(100, "Calling term_find_files\n");
429 term_find_files(jcr->ff);
431 Dmsg0(100, "Done with term_find_files\n");
432 pthread_cond_destroy(&jcr->job_start_wait);
433 free_jcr(jcr); /* destroy JCR record */
434 Dmsg0(100, "Done with free_jcr\n");
435 allow_os_suspensions(); /* FD can now be suspended */
437 garbage_collect_memory_pool();
443 * Accept requests from a Director or a Storage daemon
445 void *handle_connection_request(void *caller)
447 BSOCK *bs = (BSOCK *)caller;
449 if (bs->recv() > 0) {
450 if (strncmp(bs->msg, "Ping", 4) == 0) {
451 bs->fsend("2000 Ping OK\n");
455 if (bs->msglen < 25 || bs->msglen > 500) {
458 Dmsg1(100, "Got: %s", bs->msg);
459 if (strncmp(bs->msg, "Hello Director", 14) == 0) {
460 return handle_director_request(bs);
462 if (strncmp(bs->msg, "Hello FD: Bacula Storage", 20) ==0) {
463 return handle_storage_connection(bs);
467 Dmsg2(100, "Bad command from %s. Len=%d.\n", bs->who(), bs->msglen);
469 char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
470 Jmsg2(NULL, M_FATAL, 0, _("Bad command from %s. Len=%d.\n"), who, bs->msglen);
475 static int sm_dump_cmd(JCR *jcr)
478 sm_dump(false, true);
479 jcr->dir_bsock->fsend("2000 sm_dump OK\n");
484 static int exit_cmd(JCR *jcr)
486 jcr->dir_bsock->fsend("2000 exit OK\n");
494 * Hello from Director he must identify himself and provide his
497 static int hello_cmd(JCR *jcr)
499 Dmsg0(120, "Calling Authenticate\n");
500 if (!validate_dir_hello(jcr)) {
503 if (!authenticate_director(jcr)) {
506 Dmsg0(120, "OK Authenticate\n");
507 jcr->authenticated = true;
515 static int cancel_cmd(JCR *jcr)
517 BSOCK *dir = jcr->dir_bsock;
518 char Job[MAX_NAME_LENGTH];
523 if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
524 status = JS_Canceled;
526 } else if (sscanf(dir->msg, "stop Job=%127s", Job) == 1) {
527 status = JS_Incomplete;
530 dir->fsend(_("2902 Error scanning cancel command.\n"));
533 if (!(cjcr=get_jcr_by_full_name(Job))) {
534 dir->fsend(_("2901 Job %s not found.\n"), Job);
536 generate_plugin_event(cjcr, bEventCancelCommand, NULL);
537 cjcr->setJobStatus(status);
538 if (cjcr->store_bsock) {
539 cjcr->store_bsock->set_timed_out();
540 cjcr->store_bsock->set_terminated();
542 cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
544 dir->fsend(_("2001 Job \"%s\" marked to be %s.\n"),
549 dir->signal(BNET_EOD);
554 * Set bandwidth limit as requested by the Director
557 static int setbandwidth_cmd(JCR *jcr)
559 BSOCK *dir = jcr->dir_bsock;
562 char Job[MAX_NAME_LENGTH];
565 if (sscanf(dir->msg, setbandwidth, &bw, Job) != 2 || bw < 0) {
566 pm_strcpy(jcr->errmsg, dir->msg);
567 dir->fsend(_("2991 Bad setbandwidth command: %s\n"), jcr->errmsg);
572 if(!(cjcr=get_jcr_by_full_name(Job))) {
573 dir->fsend(_("2901 Job %s not found.\n"), Job);
575 cjcr->max_bandwidth = bw;
576 if (cjcr->store_bsock) {
577 cjcr->store_bsock->set_bwlimit(bw);
582 } else { /* No job requested, apply globally */
583 me->max_bandwidth_per_job = bw; /* Overwrite directive */
585 cjcr->max_bandwidth = bw;
586 if (cjcr->store_bsock) {
587 cjcr->store_bsock->set_bwlimit(bw);
593 return dir->fsend(OKBandwidth);
597 * Set debug level as requested by the Director
600 static int setdebug_cmd(JCR *jcr)
602 BSOCK *dir = jcr->dir_bsock;
606 int64_t level, level_tags = 0;
611 Dmsg1(50, "setdebug_cmd: %s", dir->msg);
612 tags[0] = options[0] = 0;
613 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld blowup=%ld"
614 " options=%55s tags=%511s",
615 &lvl, &trace, &hangup, &blowup, options, tags);
617 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld",
618 &lvl, &trace, &hangup);
620 Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
621 if (sscanf(dir->msg, "setdebug=%ld trace=%ld", &lvl, &trace) != 2) {
622 pm_strcpy(jcr->errmsg, dir->msg);
623 dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
634 if (!debug_parse_tags(tags, &level_tags)) {
640 debug_level_tags = level_tags;
642 /* handle other options */
643 set_debug_flags(options);
645 Dmsg6(150, "level=%ld trace=%ld hangup=%ld blowup=%d options=%s tags=%s\n",
646 lvl, get_trace(), get_hangup(), get_blowup(), options, tags);
647 return dir->fsend(OKsetdebug, lvl, get_trace(), get_hangup(),
648 get_blowup(), options, tags);
652 static int estimate_cmd(JCR *jcr)
654 BSOCK *dir = jcr->dir_bsock;
655 char ed1[50], ed2[50];
657 if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
658 pm_strcpy(jcr->errmsg, dir->msg);
659 Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
660 dir->fsend(_("2992 Bad estimate command.\n"));
664 dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
665 edit_uint64_with_commas(jcr->JobBytes, ed2));
666 dir->signal(BNET_EOD);
671 * Get JobId and Storage Daemon Authorization key from Director
673 static int job_cmd(JCR *jcr)
675 BSOCK *dir = jcr->dir_bsock;
676 POOL_MEM sd_auth_key(PM_MESSAGE);
677 sd_auth_key.check_size(dir->msglen);
679 if (sscanf(dir->msg, jobcmd, &jcr->JobId, jcr->Job,
680 &jcr->VolSessionId, &jcr->VolSessionTime,
681 sd_auth_key.c_str()) != 5) {
682 pm_strcpy(jcr->errmsg, dir->msg);
683 Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
688 set_storage_auth_key(jcr, sd_auth_key.c_str());
689 Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
690 Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
691 new_plugins(jcr); /* instantiate plugins for this jcr */
692 generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
693 return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
696 extern "C" char *job_code_callback_filed(JCR *jcr, const char* param)
701 return jcr->director->hdr.name;
709 static int runbefore_cmd(JCR *jcr)
712 BSOCK *dir = jcr->dir_bsock;
713 POOLMEM *cmd = get_memory(dir->msglen+1);
716 Dmsg1(100, "runbefore_cmd: %s", dir->msg);
717 if (sscanf(dir->msg, runbefore, cmd) != 1) {
718 pm_strcpy(jcr->errmsg, dir->msg);
719 Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
720 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
726 /* Run the command now */
727 script = new_runscript();
728 script->set_job_code_callback(job_code_callback_filed);
729 script->set_command(cmd);
730 script->when = SCRIPT_Before;
731 ok = script->run(jcr, "ClientRunBeforeJob");
732 free_runscript(script);
736 dir->fsend(OKRunBefore);
739 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
744 static int runbeforenow_cmd(JCR *jcr)
746 BSOCK *dir = jcr->dir_bsock;
748 run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
749 if (job_canceled(jcr)) {
750 dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
751 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
754 dir->fsend(OKRunBeforeNow);
755 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
760 static int runafter_cmd(JCR *jcr)
762 BSOCK *dir = jcr->dir_bsock;
763 POOLMEM *msg = get_memory(dir->msglen+1);
766 Dmsg1(100, "runafter_cmd: %s", dir->msg);
767 if (sscanf(dir->msg, runafter, msg) != 1) {
768 pm_strcpy(jcr->errmsg, dir->msg);
769 Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
770 dir->fsend(_("2905 Bad RunAfterJob command.\n"));
776 cmd = new_runscript();
777 cmd->set_job_code_callback(job_code_callback_filed);
778 cmd->set_command(msg);
779 cmd->on_success = true;
780 cmd->on_failure = false;
781 cmd->when = SCRIPT_After;
783 jcr->RunScripts->append(cmd);
785 free_pool_memory(msg);
786 return dir->fsend(OKRunAfter);
789 static int runscript_cmd(JCR *jcr)
791 BSOCK *dir = jcr->dir_bsock;
792 POOLMEM *msg = get_memory(dir->msglen+1);
793 int on_success, on_failure, fail_on_error;
795 RUNSCRIPT *cmd = new_runscript() ;
796 cmd->set_job_code_callback(job_code_callback_filed);
798 Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
799 /* Note, we cannot sscanf into bools */
800 if (sscanf(dir->msg, runscript, &on_success,
805 pm_strcpy(jcr->errmsg, dir->msg);
806 Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
807 dir->fsend(_("2905 Bad RunScript command.\n"));
812 cmd->on_success = on_success;
813 cmd->on_failure = on_failure;
814 cmd->fail_on_error = fail_on_error;
817 cmd->set_command(msg);
819 jcr->RunScripts->append(cmd);
821 free_pool_memory(msg);
822 return dir->fsend(OKRunScript);
826 * This reads data sent from the Director from the
827 * RestoreObject table that allows us to get objects
828 * that were backed up (VSS .xml data) and are needed
829 * before starting the restore.
831 static int restore_object_cmd(JCR *jcr)
833 BSOCK *dir = jcr->dir_bsock;
835 restore_object_pkt rop;
837 memset(&rop, 0, sizeof(rop));
838 rop.pkt_size = sizeof(rop);
839 rop.pkt_end = sizeof(rop);
841 Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
842 if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
843 Dmsg0(20, "Got endrestoreobject\n");
844 generate_plugin_event(jcr, bEventRestoreObject, NULL);
845 return dir->fsend(OKRestoreObject);
848 rop.plugin_name = (char *)malloc(dir->msglen);
849 *rop.plugin_name = 0;
851 if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len,
852 &rop.object_full_len, &rop.object_index,
853 &rop.object_type, &rop.object_compression, &FileIndex,
854 rop.plugin_name) != 8) {
856 /* Old version, no plugin_name */
857 if (sscanf(dir->msg, restoreobjcmd1, &rop.JobId, &rop.object_len,
858 &rop.object_full_len, &rop.object_index,
859 &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
860 Dmsg0(5, "Bad restore object command\n");
861 pm_strcpy(jcr->errmsg, dir->msg);
862 Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
867 unbash_spaces(rop.plugin_name);
869 Dmsg7(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d "
870 "FI=%d plugin_name=%s\n",
871 rop.JobId, rop.object_len, rop.object_full_len,
872 rop.object_index, rop.object_type, FileIndex, rop.plugin_name);
873 /* Read Object name */
874 if (dir->recv() < 0) {
877 Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
878 rop.object_name = bstrdup(dir->msg);
881 if (dir->recv() < 0) {
884 /* Transfer object from message buffer, and get new message buffer */
885 rop.object = dir->msg;
886 dir->msg = get_pool_memory(PM_MESSAGE);
888 /* If object is compressed, uncompress it */
889 if (rop.object_compression == 1) { /* zlib level 9 */
891 int out_len = rop.object_full_len + 100;
892 POOLMEM *obj = get_memory(out_len);
893 Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
894 stat = Zinflate(rop.object, rop.object_len, obj, out_len);
895 Dmsg1(100, "Zinflate stat=%d\n", stat);
896 if (out_len != rop.object_full_len) {
897 Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
898 rop.object_full_len, out_len, rop.object_name);
900 free_pool_memory(rop.object); /* release compressed object */
901 rop.object = obj; /* new uncompressed object */
902 rop.object_len = out_len;
904 Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
905 /* we still need to do this to detect a vss restore */
906 if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
907 Dmsg0(100, "got job metadata\n");
908 jcr->got_metadata = true;
911 generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
913 if (rop.object_name) {
914 free(rop.object_name);
917 free_pool_memory(rop.object);
919 if (rop.plugin_name) {
920 free(rop.plugin_name);
923 Dmsg1(100, "Send: %s", OKRestoreObject);
927 dir->fsend(_("2909 Bad RestoreObject command.\n"));
933 static bool init_fileset(JCR *jcr)
936 findFILESET *fileset;
945 fileset = (findFILESET *)malloc(sizeof(findFILESET));
946 memset(fileset, 0, sizeof(findFILESET));
947 ff->fileset = fileset;
948 fileset->state = state_none;
949 fileset->include_list.init(1, true);
950 fileset->exclude_list.init(1, true);
955 static void append_file(JCR *jcr, findINCEXE *incexe,
956 const char *buf, bool is_file)
959 incexe->name_list.append(new_dlistString(buf));
961 } else if (me->plugin_directory) {
962 generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
963 incexe->plugin_list.append(new_dlistString(buf));
966 Jmsg(jcr, M_FATAL, 0,
967 _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
973 * Add fname to include/exclude fileset list. First check for
974 * | and < and if necessary perform command.
976 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
978 findFILESET *fileset = jcr->ff->fileset;
991 p++; /* skip over | */
992 fn = get_pool_memory(PM_FNAME);
993 fn = edit_job_codes(jcr, fn, p, "", job_code_callback_filed);
994 bpipe = open_bpipe(fn, 0, "r");
997 Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
999 free_pool_memory(fn);
1002 free_pool_memory(fn);
1003 while (fgets(buf, sizeof(buf), bpipe->rfd)) {
1004 strip_trailing_junk(buf);
1005 append_file(jcr, fileset->incexe, buf, is_file);
1007 if ((stat=close_bpipe(bpipe)) != 0) {
1009 Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
1010 p, be.code(stat), be.bstrerror(stat));
1015 Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
1016 p++; /* skip over < */
1017 if ((ffd = fopen(p, "rb")) == NULL) {
1019 Jmsg(jcr, M_FATAL, 0,
1020 _("Cannot open FileSet input file: %s. ERR=%s\n"),
1024 while (fgets(buf, sizeof(buf), ffd)) {
1025 strip_trailing_junk(buf);
1026 append_file(jcr, fileset->incexe, buf, is_file);
1031 append_file(jcr, fileset->incexe, fname, is_file);
1036 findINCEXE *get_incexe(JCR *jcr)
1038 if (jcr->ff && jcr->ff->fileset) {
1039 return jcr->ff->fileset->incexe;
1044 void set_incexe(JCR *jcr, findINCEXE *incexe)
1046 findFILESET *fileset = jcr->ff->fileset;
1047 fileset->incexe = incexe;
1052 * Define a new Exclude block in the FileSet
1054 findINCEXE *new_exclude(JCR *jcr)
1056 findFILESET *fileset = jcr->ff->fileset;
1059 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1060 memset(fileset->incexe, 0, sizeof(findINCEXE));
1061 fileset->incexe->opts_list.init(1, true);
1062 fileset->incexe->name_list.init();
1063 fileset->incexe->plugin_list.init();
1064 fileset->exclude_list.append(fileset->incexe);
1065 return fileset->incexe;
1069 * Define a new Include block in the FileSet
1071 findINCEXE *new_include(JCR *jcr)
1073 findFILESET *fileset = jcr->ff->fileset;
1076 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1077 memset(fileset->incexe, 0, sizeof(findINCEXE));
1078 fileset->incexe->opts_list.init(1, true);
1079 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1080 fileset->incexe->plugin_list.init();
1081 fileset->include_list.append(fileset->incexe);
1082 return fileset->incexe;
1086 * Define a new preInclude block in the FileSet
1087 * That is the include is prepended to the other
1088 * Includes. This is used for plugin exclusions.
1090 findINCEXE *new_preinclude(JCR *jcr)
1092 findFILESET *fileset = jcr->ff->fileset;
1094 /* New pre-include */
1095 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1096 memset(fileset->incexe, 0, sizeof(findINCEXE));
1097 fileset->incexe->opts_list.init(1, true);
1098 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1099 fileset->incexe->plugin_list.init();
1100 fileset->include_list.prepend(fileset->incexe);
1101 return fileset->incexe;
1104 static findFOPTS *start_options(FF_PKT *ff)
1106 int state = ff->fileset->state;
1107 findINCEXE *incexe = ff->fileset->incexe;
1109 if (state != state_options) {
1110 ff->fileset->state = state_options;
1111 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1112 memset(fo, 0, sizeof(findFOPTS));
1113 fo->regex.init(1, true);
1114 fo->regexdir.init(1, true);
1115 fo->regexfile.init(1, true);
1116 fo->wild.init(1, true);
1117 fo->wilddir.init(1, true);
1118 fo->wildfile.init(1, true);
1119 fo->wildbase.init(1, true);
1120 fo->base.init(1, true);
1121 fo->fstype.init(1, true);
1122 fo->drivetype.init(1, true);
1123 incexe->current_opts = fo;
1124 incexe->opts_list.append(fo);
1126 return incexe->current_opts;
1130 * Used by plugins to define a new options block
1132 void new_options(JCR *jcr, findINCEXE *incexe)
1135 incexe = jcr->ff->fileset->incexe;
1137 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1138 memset(fo, 0, sizeof(findFOPTS));
1139 fo->regex.init(1, true);
1140 fo->regexdir.init(1, true);
1141 fo->regexfile.init(1, true);
1142 fo->wild.init(1, true);
1143 fo->wilddir.init(1, true);
1144 fo->wildfile.init(1, true);
1145 fo->wildbase.init(1, true);
1146 fo->base.init(1, true);
1147 fo->fstype.init(1, true);
1148 fo->drivetype.init(1, true);
1149 incexe->current_opts = fo;
1150 incexe->opts_list.prepend(fo);
1151 jcr->ff->fileset->state = state_options;
1155 * Add a regex to the current fileset
1157 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
1159 findFOPTS *current_opts = start_options(jcr->ff);
1164 preg = (regex_t *)malloc(sizeof(regex_t));
1165 if (current_opts->flags & FO_IGNORECASE) {
1166 rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1168 rc = regcomp(preg, item, REG_EXTENDED);
1171 regerror(rc, preg, prbuf, sizeof(prbuf));
1174 Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1178 current_opts->regex.append(preg);
1179 } else if (type == 'D') {
1180 current_opts->regexdir.append(preg);
1181 } else if (type == 'F') {
1182 current_opts->regexfile.append(preg);
1186 return state_options;
1190 * Add a wild card to the current fileset
1192 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1194 findFOPTS *current_opts = start_options(jcr->ff);
1197 current_opts->wild.append(bstrdup(item));
1198 } else if (type == 'D') {
1199 current_opts->wilddir.append(bstrdup(item));
1200 } else if (type == 'F') {
1201 current_opts->wildfile.append(bstrdup(item));
1202 } else if (type == 'B') {
1203 current_opts->wildbase.append(bstrdup(item));
1207 return state_options;
1212 * Add options to the current fileset
1214 int add_options_to_fileset(JCR *jcr, const char *item)
1216 findFOPTS *current_opts = start_options(jcr->ff);
1218 set_options(current_opts, item);
1219 return state_options;
1222 static void add_fileset(JCR *jcr, const char *item)
1224 FF_PKT *ff = jcr->ff;
1225 findFILESET *fileset = ff->fileset;
1226 int state = fileset->state;
1227 findFOPTS *current_opts;
1229 /* Get code, optional subcode, and position item past the dividing space */
1230 Dmsg1(100, "%s\n", item);
1235 int subcode = ' '; /* A space is always a valid subcode */
1236 if (item[0] != '\0' && item[0] != ' ') {
1244 /* Skip all lines we receive after an error */
1245 if (state == state_error) {
1246 Dmsg0(100, "State=error return\n");
1251 * The switch tests the code for validity.
1252 * The subcode is always good if it is a space, otherwise we must confirm.
1253 * We set state to state_error first assuming the subcode is invalid,
1254 * requiring state to be set in cases below that handle subcodes.
1256 if (subcode != ' ') {
1257 state = state_error;
1258 Dmsg0(100, "Set state=error or double code.\n");
1262 (void)new_include(jcr);
1265 (void)new_exclude(jcr);
1267 case 'N': /* null */
1270 case 'F': /* file = */
1271 /* File item to include or exclude list */
1272 state = state_include;
1273 add_file_to_fileset(jcr, item, true);
1275 case 'P': /* plugin */
1276 /* Plugin item to include list */
1277 state = state_include;
1278 add_file_to_fileset(jcr, item, false);
1280 case 'R': /* regex */
1281 state = add_regex_to_fileset(jcr, item, subcode);
1284 current_opts = start_options(ff);
1285 current_opts->base.append(bstrdup(item));
1286 state = state_options;
1288 case 'X': /* Filetype or Drive type */
1289 current_opts = start_options(ff);
1290 state = state_options;
1291 if (subcode == ' ') {
1292 current_opts->fstype.append(bstrdup(item));
1293 } else if (subcode == 'D') {
1294 current_opts->drivetype.append(bstrdup(item));
1296 state = state_error;
1299 case 'W': /* wild cards */
1300 state = add_wild_to_fileset(jcr, item, subcode);
1302 case 'O': /* Options */
1303 state = add_options_to_fileset(jcr, item);
1305 case 'Z': /* ignore dir */
1306 state = state_include;
1307 fileset->incexe->ignoredir = bstrdup(item);
1310 current_opts = start_options(ff);
1311 // current_opts->reader = bstrdup(item); /* deprecated */
1312 state = state_options;
1315 current_opts = start_options(ff);
1316 // current_opts->writer = bstrdup(item); /* deprecated */
1317 state = state_options;
1319 case 'G': /* Plugin command for this Option block */
1320 current_opts = start_options(ff);
1321 current_opts->plugin = bstrdup(item);
1322 state = state_options;
1325 Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1326 state = state_error;
1329 ff->fileset->state = state;
1332 static bool term_fileset(JCR *jcr)
1334 FF_PKT *ff = jcr->ff;
1336 #ifdef xxx_DEBUG_CODE
1337 findFILESET *fileset = ff->fileset;
1340 for (i=0; i<fileset->include_list.size(); i++) {
1341 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1343 for (j=0; j<incexe->opts_list.size(); j++) {
1344 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1345 for (k=0; k<fo->regex.size(); k++) {
1346 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1348 for (k=0; k<fo->regexdir.size(); k++) {
1349 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1351 for (k=0; k<fo->regexfile.size(); k++) {
1352 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1354 for (k=0; k<fo->wild.size(); k++) {
1355 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1357 for (k=0; k<fo->wilddir.size(); k++) {
1358 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1360 for (k=0; k<fo->wildfile.size(); k++) {
1361 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1363 for (k=0; k<fo->wildbase.size(); k++) {
1364 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1366 for (k=0; k<fo->base.size(); k++) {
1367 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1369 for (k=0; k<fo->fstype.size(); k++) {
1370 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1372 for (k=0; k<fo->drivetype.size(); k++) {
1373 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1376 if (incexe->ignoredir) {
1377 Dmsg1(400, "Z %s\n", incexe->ignoredir);
1380 foreach_dlist(node, &incexe->name_list) {
1381 Dmsg1(400, "F %s\n", node->c_str());
1383 foreach_dlist(node, &incexe->plugin_list) {
1384 Dmsg1(400, "P %s\n", node->c_str());
1387 for (i=0; i<fileset->exclude_list.size(); i++) {
1388 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1390 for (j=0; j<incexe->opts_list.size(); j++) {
1391 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1392 for (k=0; k<fo->regex.size(); k++) {
1393 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1395 for (k=0; k<fo->regexdir.size(); k++) {
1396 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1398 for (k=0; k<fo->regexfile.size(); k++) {
1399 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1401 for (k=0; k<fo->wild.size(); k++) {
1402 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1404 for (k=0; k<fo->wilddir.size(); k++) {
1405 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1407 for (k=0; k<fo->wildfile.size(); k++) {
1408 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1410 for (k=0; k<fo->wildbase.size(); k++) {
1411 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1413 for (k=0; k<fo->base.size(); k++) {
1414 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1416 for (k=0; k<fo->fstype.size(); k++) {
1417 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1419 for (k=0; k<fo->drivetype.size(); k++) {
1420 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1424 foreach_dlist(node, &incexe->name_list) {
1425 Dmsg1(400, "F %s\n", node->c_str());
1427 foreach_dlist(node, &incexe->plugin_list) {
1428 Dmsg1(400, "P %s\n", node->c_str());
1432 return ff->fileset->state != state_error;
1437 * As an optimization, we should do this during
1438 * "compile" time in filed/job.c, and keep only a bit mask
1439 * and the Verify options.
1441 static int set_options(findFOPTS *fo, const char *opts)
1447 // Commented out as it is not backward compatible - KES
1449 for (p=opts; *p; p++) {
1451 case 'a': /* alway replace */
1452 case '0': /* no option */
1455 fo->flags |= FO_EXCLUDE;
1458 fo->flags |= FO_MULTIFS;
1460 case 'h': /* no recursion */
1461 fo->flags |= FO_NO_RECURSION;
1463 case 'H': /* no hard link handling */
1464 fo->flags |= FO_NO_HARDLINK;
1467 fo->flags |= FO_IGNORECASE;
1470 fo->flags |= FO_MD5;
1473 fo->flags |= FO_NOREPLACE;
1475 case 'p': /* use portable data format */
1476 fo->flags |= FO_PORTABLE;
1478 case 'R': /* Resource forks and Finder Info */
1479 fo->flags |= FO_HFSPLUS;
1481 case 'r': /* read fifo */
1482 fo->flags |= FO_READFIFO;
1487 fo->flags |= FO_SHA1;
1492 fo->flags |= FO_SHA256;
1496 fo->flags |= FO_SHA512;
1502 * If 2 or 3 is seen here, SHA2 is not configured, so
1503 * eat the option, and drop back to SHA-1.
1505 if (p[1] == '2' || p[1] == '3') {
1508 fo->flags |= FO_SHA1;
1513 fo->flags |= FO_SPARSE;
1516 fo->flags |= FO_MTIMEONLY;
1519 fo->flags |= FO_KEEPATIME;
1522 fo->flags |= FO_ACL;
1524 case 'V': /* verify options */
1525 /* Copy Verify Options */
1526 for (j=0; *p && *p != ':'; p++) {
1527 fo->VerifyOpts[j] = *p;
1528 if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1532 fo->VerifyOpts[j] = 0;
1534 case 'C': /* accurate options */
1535 /* Copy Accurate Options */
1536 for (j=0; *p && *p != ':'; p++) {
1537 fo->AccurateOpts[j] = *p;
1538 if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1542 fo->AccurateOpts[j] = 0;
1544 case 'J': /* Basejob options */
1545 /* Copy BaseJob Options */
1546 for (j=0; *p && *p != ':'; p++) {
1547 fo->BaseJobOpts[j] = *p;
1548 if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1552 fo->BaseJobOpts[j] = 0;
1554 case 'P': /* strip path */
1557 for (j=0; *p && *p != ':'; p++) {
1559 if (j < (int)sizeof(strip) - 1) {
1564 fo->strip_path = atoi(strip);
1565 fo->flags |= FO_STRIPPATH;
1566 Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1569 fo->flags |= FO_IF_NEWER;
1572 fo->flags |= FO_ENHANCEDWILD;
1574 case 'Z': /* compression */
1576 if (*p >= '0' && *p <= '9') {
1577 fo->flags |= FO_COMPRESS;
1578 fo->Compress_algo = COMPRESS_GZIP;
1579 fo->Compress_level = *p - '0';
1581 else if (*p == 'o') {
1582 fo->flags |= FO_COMPRESS;
1583 fo->Compress_algo = COMPRESS_LZO1X;
1584 fo->Compress_level = 1; /* not used with LZO */
1588 fo->flags |= FO_NOATIME;
1591 fo->flags |= FO_CHKCHANGES;
1594 fo->flags |= FO_HONOR_NODUMP;
1597 fo->flags |= FO_XATTR;
1600 Jmsg1(NULL, M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1604 return state_options;
1609 * Director is passing his Fileset
1611 static int fileset_cmd(JCR *jcr)
1613 POOL_MEM buf(PM_MESSAGE);
1614 BSOCK *dir = jcr->dir_bsock;
1617 jcr->Snapshot = (strstr(dir->msg, "snap=1") != NULL);
1618 if (!init_fileset(jcr)) {
1621 while (dir->recv() >= 0) {
1622 strip_trailing_junk(dir->msg);
1623 Dmsg1(500, "Fileset: %s\n", dir->msg);
1624 pm_strcpy(buf, dir->msg);
1625 add_fileset(jcr, buf.c_str());
1627 if (!term_fileset(jcr)) {
1630 rtnstat = dir->fsend(OKinc);
1631 generate_plugin_event(jcr, bEventEndFileSet);
1637 * The Director sends us the component info file, which
1638 * we will in turn pass to the VSS plugin.
1640 static int component_cmd(JCR *jcr)
1642 BSOCK *dir = jcr->dir_bsock;
1644 while (dir->recv() >= 0) {
1645 Dmsg1(200, "filed<dird: component: %s", dir->msg);
1646 generate_plugin_event(jcr, bEventComponentInfo, (void *)dir->msg);
1648 return dir->fsend(OKComponentInfo);
1653 * Get backup level from Director
1655 * Note: there are odd things such as accurate_differential,
1656 * and accurate_incremental that are passed in level, thus
1657 * the calls to strstr() below.
1660 static int level_cmd(JCR *jcr)
1662 BSOCK *dir = jcr->dir_bsock;
1663 POOLMEM *level, *buf = NULL;
1666 level = get_memory(dir->msglen+1);
1667 Dmsg1(10, "level_cmd: %s", dir->msg);
1669 /* keep compatibility with older directors */
1670 if (strstr(dir->msg, "accurate")) {
1671 jcr->accurate = true;
1673 if (strstr(dir->msg, "rerunning")) {
1674 jcr->rerunning = true;
1676 if (sscanf(dir->msg, "level = %s ", level) != 1) {
1679 /* Base backup requested? */
1680 if (strcasecmp(level, "base") == 0) {
1681 jcr->setJobLevel(L_BASE);
1682 /* Full backup requested? */
1683 } else if (strcasecmp(level, "full") == 0) {
1684 jcr->setJobLevel(L_FULL);
1685 } else if (strstr(level, "differential")) {
1686 jcr->setJobLevel(L_DIFFERENTIAL);
1689 } else if (strstr(level, "incremental")) {
1690 jcr->setJobLevel(L_INCREMENTAL);
1694 * We get his UTC since time, then sync the clocks and correct it
1695 * to agree with our clock.
1697 } else if (strcasecmp(level, "since_utime") == 0) {
1698 buf = get_memory(dir->msglen+1);
1699 utime_t since_time, adj;
1700 btime_t his_time, bt_start, rt=0, bt_adj=0, his_time_prev=0, n=0;
1701 if (jcr->getJobLevel() == L_NONE) {
1702 jcr->setJobLevel(L_SINCE); /* if no other job level set, do it now */
1704 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d prev_job=%127s",
1705 buf, &mtime_only, jcr->PrevJob) != 3) {
1706 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1707 buf, &mtime_only) != 2) {
1711 since_time = str_to_uint64(buf); /* this is the since time */
1712 Dmsg2(100, "since_time=%lld prev_job=%s\n", since_time, jcr->PrevJob);
1713 char ed1[50], ed2[50];
1715 * Sync clocks by polling him for the time. We take
1716 * 10 samples of his time throwing out the first two.
1718 for (int i=0; i<10; i++) {
1719 bt_start = get_current_btime();
1720 dir->signal(BNET_BTIME); /* poll for time */
1721 if (dir->recv() <= 0) { /* get response */
1724 if (sscanf(dir->msg, "btime %s", buf) != 1) {
1727 his_time = str_to_uint64(buf);
1728 rt = get_current_btime() - bt_start; /* compute round trip time */
1729 /* skip first two results and check for leap second */
1730 /* if any of the FD or DIR went back in time, skip this iteration */
1731 if (i < 2 || (his_time_prev > 0 && his_time < his_time_prev) || rt<0) {
1732 his_time_prev = his_time;
1735 his_time_prev = his_time;
1737 Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1738 edit_uint64(bt_start, ed2));
1739 bt_adj += bt_start - his_time - rt/2;
1740 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1743 if (n > 0) { /* Should be 1 in the worst case */
1744 bt_adj = bt_adj / n; /* compute average time */
1745 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1746 adj = btime_to_utime(bt_adj);
1747 since_time += adj; /* adjust for clock difference */
1749 /* Don't notify if time within 3 seconds */
1750 if (adj > 3 || adj < -3) {
1752 if (adj > 600 || adj < -600) {
1757 Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1759 dir->signal(BNET_EOD);
1761 Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1762 jcr->incremental = 1; /* set incremental or decremental backup */
1763 jcr->mtime = since_time; /* set since time */
1764 generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1766 Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1774 generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1775 return dir->fsend(OKlevel);
1778 pm_strcpy(jcr->errmsg, dir->msg);
1779 Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1788 * Get session parameters from Director -- this is for a Restore command
1789 * This is deprecated. It is now passed via the bsr.
1791 static int session_cmd(JCR *jcr)
1793 BSOCK *dir = jcr->dir_bsock;
1795 Dmsg1(100, "SessionCmd: %s", dir->msg);
1796 if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1797 &jcr->VolSessionId, &jcr->VolSessionTime,
1798 &jcr->StartFile, &jcr->EndFile,
1799 &jcr->StartBlock, &jcr->EndBlock) != 7) {
1800 pm_strcpy(jcr->errmsg, dir->msg);
1801 Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1805 return dir->fsend(OKsession);
1808 static void set_storage_auth_key(JCR *jcr, char *key)
1810 /* if no key don't update anything */
1816 * We can be contacting multiple storage daemons.
1817 * So, make sure that any old jcr->store_bsock is cleaned up.
1819 free_bsock(jcr->store_bsock);
1822 * We can be contacting multiple storage daemons.
1823 * So, make sure that any old jcr->sd_auth_key is cleaned up.
1825 if (jcr->sd_auth_key) {
1827 * If we already have a Authorization key, director can do multi
1830 Dmsg0(5, "set multi_restore=true\n");
1831 jcr->multi_restore = true;
1832 bfree(jcr->sd_auth_key);
1835 jcr->sd_auth_key = bstrdup(key);
1836 Dmsg1(5, "set sd auth key %s\n", jcr->sd_auth_key);
1840 * Get address of storage daemon from Director
1843 static int storage_cmd(JCR *jcr)
1845 int stored_port = 0; /* storage daemon port */
1846 int enable_ssl; /* enable ssl to sd */
1847 POOL_MEM sd_auth_key(PM_MESSAGE);
1848 BSOCK *dir = jcr->dir_bsock;
1851 Dmsg1(100, "StorageCmd: %s", dir->msg);
1852 sd_auth_key.check_size(dir->msglen);
1853 if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port,
1854 &enable_ssl, sd_auth_key.c_str()) == 4) {
1855 Dmsg1(100, "Set auth key %s\n", sd_auth_key.c_str());
1856 set_storage_auth_key(jcr, sd_auth_key.c_str());
1857 } else if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
1858 &stored_port, &enable_ssl) != 3) {
1859 pm_strcpy(jcr->errmsg, dir->msg);
1860 Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1861 Pmsg1(010, "Bad storage command: %s", jcr->errmsg);
1866 /* TODO: see if we put limit on restore and backup... */
1867 if (!jcr->max_bandwidth) {
1868 if (jcr->director->max_bandwidth_per_job) {
1869 jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
1871 } else if (me->max_bandwidth_per_job) {
1872 jcr->max_bandwidth = me->max_bandwidth_per_job;
1876 if (stored_port != 0) { /* We are doing the connecting */
1877 Dmsg3(110, "Connect to storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port,
1879 jcr->sd_calls_client = false;
1881 /* Open command communications with Storage daemon */
1882 /* Try to connect for 1 hour at 10 second intervals */
1883 sd->set_source_address(me->FDsrc_addr);
1884 if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1885 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1886 /* destroy() OK because sd is local */
1888 Jmsg2(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1889 jcr->stored_addr, stored_port);
1890 Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1891 jcr->stored_addr, stored_port);
1895 Dmsg0(110, "Connection OK to SD.\n");
1896 jcr->store_bsock = sd;
1897 } else { /* The storage daemon called us */
1900 struct timespec timeout;
1903 free_bsock(jcr->store_bsock);
1904 jcr->sd_calls_client = true;
1907 * Wait for the Storage daemon to contact us to start the Job,
1908 * when he does, we will be released, unless the 30 minutes
1911 gettimeofday(&tv, &tz);
1912 timeout.tv_nsec = tv.tv_usec * 1000;
1913 timeout.tv_sec = tv.tv_sec + 30 * 60; /* wait 30 minutes */
1915 while (jcr->sd_calls_client_bsock == NULL && !jcr->is_job_canceled()) {
1916 errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
1917 if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
1920 Dmsg1(800, "=== Auth cond errstat=%d\n", errstat);
1923 Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr);
1925 /* We should already have a storage connection! */
1926 if (jcr->sd_calls_client_bsock == NULL) {
1927 Pmsg0(000, "Failed connect from Storage daemon. SD bsock=NULL.\n");
1928 Pmsg1(000, "Storagecmd: %s", dir->msg);
1929 Jmsg0(jcr, M_FATAL, 0, _("Failed connect from Storage daemon. SD bsock=NULL.\n"));
1932 if (jcr->is_job_canceled()) {
1935 /* Assign the new socket to the main one */
1937 jcr->store_bsock = jcr->sd_calls_client_bsock;
1938 jcr->sd_calls_client_bsock = NULL;
1941 jcr->store_bsock->set_bwlimit(jcr->max_bandwidth);
1943 if (!send_hello_sd(jcr, jcr->Job)) {
1947 if (!authenticate_storagedaemon(jcr)) {
1950 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
1951 Dmsg0(110, "Authenticated with SD.\n");
1953 /* Send OK to Director */
1954 return dir->fsend(OKstore);
1957 dir->fsend(BADcmd, "storage");
1965 static int backup_cmd(JCR *jcr)
1967 BSOCK *dir = jcr->dir_bsock;
1968 BSOCK *sd = jcr->store_bsock;
1973 if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1974 jcr->JobFiles = FileIndex;
1975 Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1979 * If explicitly requesting FO_ACL or FO_XATTR, fail job if it
1980 * is not available on Client machine
1982 if (jcr->ff->flags & FO_ACL && !(have_acl||have_win32)) {
1983 Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for Client.\n"));
1986 if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1987 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for Client.\n"));
1990 jcr->setJobStatus(JS_Blocked);
1991 jcr->setJobType(JT_BACKUP);
1992 Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1994 Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1995 dir->fsend(BADcmd, "backup");
1999 dir->fsend(OKbackup);
2000 Dmsg1(110, "filed>dird: %s", dir->msg);
2003 * Send Append Open Session to Storage daemon
2005 sd->fsend(append_open);
2006 Dmsg1(110, ">stored: %s", sd->msg);
2008 * Expect to receive back the Ticket number
2010 if (bget_msg(sd) >= 0) {
2011 Dmsg1(110, "<stored: %s", sd->msg);
2012 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2013 Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
2016 Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
2018 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
2023 * Send Append data command to Storage daemon
2025 sd->fsend(append_data, jcr->Ticket);
2026 Dmsg1(110, ">stored: %s", sd->msg);
2029 * Expect to get OK data
2031 Dmsg1(110, "<stored: %s", sd->msg);
2032 if (!response(jcr, sd, OK_data, "Append Data")) {
2036 generate_daemon_event(jcr, "JobStart");
2037 generate_plugin_event(jcr, bEventStartBackupJob);
2039 if (jcr->Snapshot) {
2040 Dmsg0(10, "Open a snapshot session\n");
2041 /* TODO: See if we abort the job */
2042 jcr->Snapshot = open_snapshot_backup_session(jcr);
2044 /* Call RunScript just after the Snapshot creation, usually, we restart services */
2045 run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2049 * Send Files to Storage daemon
2051 Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
2052 if (!blast_data_to_storage_daemon(jcr, NULL)) {
2053 jcr->setJobStatus(JS_ErrorTerminated);
2054 sd->suppress_error_messages(true);
2055 Dmsg0(110, "Error in blast_data.\n");
2057 jcr->setJobStatus(JS_Terminated);
2058 /* Note, the above set status will not override an error */
2059 if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
2060 sd->suppress_error_messages(true);
2061 goto cleanup; /* bail out now */
2064 * Expect to get response to append_data from Storage daemon
2066 if (!response(jcr, sd, OK_append, "Append Data")) {
2067 jcr->setJobStatus(JS_ErrorTerminated);
2072 * Send Append End Data to Storage daemon
2074 sd->fsend(append_end, jcr->Ticket);
2076 if (!response(jcr, sd, OK_end, "Append End")) {
2077 jcr->setJobStatus(JS_ErrorTerminated);
2082 * Send Append Close to Storage daemon
2084 sd->fsend(append_close, jcr->Ticket);
2086 while (bget_msg(sd) >= 0) { /* stop on signal or error */
2087 if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
2089 Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
2091 Dmsg1(100, "append_close: scan fail from %s\n", sd->msg);
2095 Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
2096 Dmsg1(100, "append_close: scan fail from %s\n", sd->msg);
2099 if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings ||
2100 SDJobStatus == JS_Incomplete)) {
2101 Jmsg(jcr, M_FATAL, 0, _("Bad status %d %c returned from Storage Daemon.\n"),
2102 SDJobStatus, (char)SDJobStatus);
2108 generate_plugin_event(jcr, bEventEndBackupJob);
2109 return 0; /* return and stop command loop */
2113 * Do a Verify for Director
2116 static int verify_cmd(JCR *jcr)
2118 BSOCK *dir = jcr->dir_bsock;
2119 BSOCK *sd = jcr->store_bsock;
2122 jcr->setJobType(JT_VERIFY);
2123 if (sscanf(dir->msg, verifycmd, level) != 1) {
2124 dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2128 if (strcasecmp(level, "init") == 0) {
2129 jcr->setJobLevel(L_VERIFY_INIT);
2130 } else if (strcasecmp(level, "catalog") == 0){
2131 jcr->setJobLevel(L_VERIFY_CATALOG);
2132 } else if (strcasecmp(level, "volume") == 0){
2133 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
2134 } else if (strcasecmp(level, "data") == 0){
2135 jcr->setJobLevel(L_VERIFY_DATA);
2136 } else if (strcasecmp(level, "disk_to_catalog") == 0) {
2137 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2139 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2143 dir->fsend(OKverify);
2145 generate_daemon_event(jcr, "JobStart");
2146 generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2147 generate_plugin_event(jcr, bEventStartVerifyJob);
2149 Dmsg1(110, "filed>dird: %s", dir->msg);
2151 switch (jcr->getJobLevel()) {
2153 case L_VERIFY_CATALOG:
2156 case L_VERIFY_VOLUME_TO_CATALOG:
2157 if (!open_sd_read_session(jcr)) {
2160 start_dir_heartbeat(jcr);
2161 do_verify_volume(jcr);
2162 stop_dir_heartbeat(jcr);
2164 * Send Close session command to Storage daemon
2166 sd->fsend(read_close, jcr->Ticket);
2167 Dmsg1(130, "filed>stored: %s", sd->msg);
2169 /* ****FIXME**** check response */
2170 bget_msg(sd); /* get OK */
2172 /* Inform Storage daemon that we are done */
2173 sd->signal(BNET_TERMINATE);
2176 case L_VERIFY_DISK_TO_CATALOG:
2180 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2184 dir->signal(BNET_EOD);
2185 generate_plugin_event(jcr, bEventEndVerifyJob);
2186 return 0; /* return and terminate command loop */
2190 * Do a Restore for Director
2193 static int restore_cmd(JCR *jcr)
2195 BSOCK *dir = jcr->dir_bsock;
2196 BSOCK *sd = jcr->store_bsock;
2197 POOLMEM *args=NULL, *restore_where=NULL, *restore_rwhere=NULL;
2198 bool use_regexwhere=false;
2201 bool scan_ok = true;
2206 * Scan WHERE (base directory for restore) from command
2208 Dmsg0(100, "restore command\n");
2210 /* Pickup where string */
2211 args = get_memory(dir->msglen+1);
2214 restore_where = get_pool_memory(PM_FNAME);
2215 restore_rwhere = get_pool_memory(PM_FNAME);
2217 /* We don't know the size of where/rwhere in advance,
2218 * where= -> where=%202s\n
2220 Mmsg(restore_where, "%s%%%ds\n", restorefcmd, dir->msglen);
2221 Mmsg(restore_rwhere, "%s%%%ds\n", restorefcmdR, dir->msglen);
2223 Dmsg2(200, "where=%srwhere=%s", restore_where, restore_rwhere);
2225 /* Scan for new form with number of files to restore */
2226 if (sscanf(dir->msg, restore_where, &files, &replace, &prefix_links, args) != 4) {
2227 if (sscanf(dir->msg, restore_rwhere, &files, &replace, &prefix_links, args) != 4) {
2228 if (sscanf(dir->msg, restorefcmd1, &files, &replace, &prefix_links) != 3) {
2231 *args = 0; /* No where argument */
2233 use_regexwhere = true;
2238 jcr->ExpectedFiles = files;
2240 /* Scan for old form without number of files */
2241 jcr->ExpectedFiles = 0;
2243 /* where= -> where=%202s\n */
2244 Mmsg(restore_where, "%s%%%ds\n", restorecmd, dir->msglen);
2245 Mmsg(restore_rwhere, "%s%%%ds\n", restorecmdR, dir->msglen);
2247 if (sscanf(dir->msg, restore_where, &replace, &prefix_links, args) != 3) {
2248 if (sscanf(dir->msg, restore_rwhere, &replace, &prefix_links, args) != 3){
2249 if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2250 pm_strcpy(jcr->errmsg, dir->msg);
2251 Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2254 *args = 0; /* No where argument */
2256 use_regexwhere = true;
2261 /* Turn / into nothing */
2262 if (IsPathSeparator(args[0]) && args[1] == '\0') {
2266 Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2267 unbash_spaces(args);
2269 /* Keep track of newly created directories to apply them correct attributes */
2270 if (replace == REPLACE_NEVER || replace == REPLACE_IFNEWER) {
2271 jcr->keep_path_list = true;
2274 if (use_regexwhere) {
2275 jcr->where_bregexp = get_bregexps(args);
2276 if (!jcr->where_bregexp) {
2277 Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2281 jcr->where = bstrdup(args);
2284 jcr->replace = replace;
2285 jcr->prefix_links = prefix_links;
2287 dir->fsend(OKrestore);
2288 Dmsg1(110, "filed>dird: %s", dir->msg);
2290 jcr->setJobType(JT_RESTORE);
2292 jcr->setJobStatus(JS_Blocked);
2294 if (!open_sd_read_session(jcr)) {
2295 jcr->setJobStatus(JS_ErrorTerminated);
2299 jcr->setJobStatus(JS_Running);
2302 * Do restore of files and data
2304 start_dir_heartbeat(jcr);
2305 generate_daemon_event(jcr, "JobStart");
2306 generate_plugin_event(jcr, bEventStartRestoreJob);
2309 stop_dir_heartbeat(jcr);
2311 jcr->setJobStatus(JS_Terminated);
2312 if (jcr->JobStatus != JS_Terminated) {
2313 sd->suppress_error_messages(true);
2317 * Send Close session command to Storage daemon
2319 sd->fsend(read_close, jcr->Ticket);
2320 Dmsg1(100, "filed>stored: %s", sd->msg);
2322 bget_msg(sd); /* get OK */
2324 /* Inform Storage daemon that we are done */
2325 sd->signal(BNET_TERMINATE);
2328 bfree_and_null(jcr->where);
2330 if (jcr->JobErrors) {
2331 jcr->setJobStatus(JS_ErrorTerminated);
2334 Dmsg0(100, "Done in job.c\n");
2336 if (jcr->multi_restore) {
2337 Dmsg0(100, OKstoreend);
2338 dir->fsend(OKstoreend);
2339 ret = 1; /* we continue the loop, waiting for next part */
2341 ret = 0; /* we stop here */
2344 if (job_canceled(jcr)) {
2345 ret = 0; /* we stop here */
2349 end_restore_cmd(jcr); /* stopping so send bEventEndRestoreJob */
2353 free_and_null_pool_memory(args);
2354 free_and_null_pool_memory(restore_where);
2355 free_and_null_pool_memory(restore_rwhere);
2360 static int end_restore_cmd(JCR *jcr)
2362 Dmsg0(5, "end_restore_cmd\n");
2363 generate_plugin_event(jcr, bEventEndRestoreJob);
2364 return 0; /* return and terminate command loop */
2367 static int open_sd_read_session(JCR *jcr)
2369 BSOCK *sd = jcr->store_bsock;
2372 Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2375 Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2376 jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2377 Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2379 * Open Read Session with Storage daemon
2381 sd->fsend(read_open, "DummyVolume",
2382 jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2383 jcr->StartBlock, jcr->EndBlock);
2384 Dmsg1(110, ">stored: %s", sd->msg);
2389 if (bget_msg(sd) >= 0) {
2390 Dmsg1(110, "filed<stored: %s", sd->msg);
2391 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2392 Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2395 Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2397 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2402 * Use interactive session for the current restore
2404 if (jcr->interactive_session) {
2405 sd->fsend(read_ctrl, jcr->Ticket);
2406 Dmsg1(110, ">stored: %s", sd->msg);
2410 * Start read of data with Storage daemon
2412 sd->fsend(read_data, jcr->Ticket);
2413 Dmsg1(110, ">stored: %s", sd->msg);
2418 if (!response(jcr, sd, OK_data, "Read Data")) {
2425 * Destroy the Job Control Record and associated
2426 * resources (sockets).
2428 static void filed_free_jcr(JCR *jcr)
2430 if (jcr->dir_bsock) {
2431 free_bsock(jcr->dir_bsock);
2432 jcr->dir_bsock = NULL;
2434 if (jcr->sd_calls_client_bsock) {
2435 free_bsock(jcr->sd_calls_client_bsock);
2436 jcr->sd_calls_client_bsock = NULL;
2438 if (jcr->store_bsock) {
2439 free_bsock(jcr->store_bsock);
2440 jcr->store_bsock = NULL;
2442 if (jcr->last_fname) {
2443 free_pool_memory(jcr->last_fname);
2445 free_plugins(jcr); /* release instantiated plugins */
2446 free_runscripts(jcr->RunScripts);
2447 delete jcr->RunScripts;
2448 free_path_list(jcr);
2450 if (jcr->JobId != 0)
2451 write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2457 * Get response from Storage daemon to a command we
2458 * sent. Check that the response is OK.
2460 * Returns: 0 on failure
2463 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2470 if ((ret = bget_msg(sd)) > 0) {
2471 Dmsg0(110, sd->msg);
2472 if (strcmp(sd->msg, resp) == 0) {
2476 if (job_canceled(jcr)) {
2477 return 0; /* if canceled avoid useless error messages */
2479 if (sd->is_error()) {
2480 Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2481 cmd, sd->bstrerror());
2485 Jmsg4(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got len=%ld msg=\"%s\"\n"),
2486 cmd, resp, sd->msglen, smartdump(sd->msg, sd->msglen, buf, sizeof(buf)));
2488 Jmsg3(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got SIGNAL %s\n"),
2489 cmd, resp, bnet_sig_to_ascii(ret));