2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2015 Kern Sibbald
6 The original author of Bacula is Kern Sibbald, with contributions
7 from many others, a complete list can be found in the file AUTHORS.
9 You may use this file and others of this release according to the
10 license defined in the LICENSE file, which includes the Affero General
11 Public License, v3.0 ("AGPLv3") and some additional permissions and
12 terms pursuant to its AGPLv3 Section 7.
14 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Bacula File Daemon Job processing
22 * Written by Kern Sibbald, October MM
31 bool win32decomp = false;
32 bool no_win32_write_errors = false;
34 /* Static variables */
35 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
37 const bool have_win32 = false;
40 const bool have_acl = true;
42 const bool have_acl = false;
46 const bool have_xattr = true;
48 const bool have_xattr = false;
51 extern CLIENT *me; /* our client resource */
53 /* Imported functions */
54 extern int status_cmd(JCR *jcr);
55 extern int qstatus_cmd(JCR *jcr);
56 extern int accurate_cmd(JCR *jcr);
58 /* Forward referenced functions */
59 static int backup_cmd(JCR *jcr);
60 static int component_cmd(JCR *jcr);
61 static int cancel_cmd(JCR *jcr);
62 static int setdebug_cmd(JCR *jcr);
63 static int setbandwidth_cmd(JCR *jcr);
64 static int estimate_cmd(JCR *jcr);
65 static int hello_cmd(JCR *jcr);
66 static int job_cmd(JCR *jcr);
67 static int fileset_cmd(JCR *jcr);
68 static int level_cmd(JCR *jcr);
69 static int verify_cmd(JCR *jcr);
70 static int restore_cmd(JCR *jcr);
71 static int end_restore_cmd(JCR *jcr);
72 static int storage_cmd(JCR *jcr);
73 static int session_cmd(JCR *jcr);
74 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
75 static void filed_free_jcr(JCR *jcr);
76 static int open_sd_read_session(JCR *jcr);
77 static int runscript_cmd(JCR *jcr);
78 static int runbefore_cmd(JCR *jcr);
79 static int runafter_cmd(JCR *jcr);
80 static int runbeforenow_cmd(JCR *jcr);
81 static int restore_object_cmd(JCR *jcr);
82 static int set_options(findFOPTS *fo, const char *opts);
83 static void set_storage_auth_key(JCR *jcr, char *key);
84 static int sm_dump_cmd(JCR *jcr);
86 static int exit_cmd(JCR *jcr);
89 /* Exported functions */
93 * The following are the recognized commands from the Director.
95 struct s_cmds cmds[] = {
96 {"backup", backup_cmd, 0},
97 {"cancel", cancel_cmd, 0},
98 {"setdebug=", setdebug_cmd, 0},
99 {"setbandwidth=",setbandwidth_cmd, 0},
100 {"snapshot", snapshot_cmd, 0},
101 {"estimate", estimate_cmd, 0},
102 {"Hello", hello_cmd, 1},
103 {"fileset", fileset_cmd, 0},
104 {"JobId=", job_cmd, 0},
105 {"level = ", level_cmd, 0},
106 {"restore ", restore_cmd, 0},
107 {"endrestore", end_restore_cmd, 0},
108 {"session", session_cmd, 0},
109 {"status", status_cmd, 1},
110 {".status", qstatus_cmd, 1},
111 {"storage ", storage_cmd, 0},
112 {"verify", verify_cmd, 0},
113 {"component", component_cmd, 0},
114 {"RunBeforeNow", runbeforenow_cmd, 0},
115 {"RunBeforeJob", runbefore_cmd, 0},
116 {"RunAfterJob", runafter_cmd, 0},
117 {"Run", runscript_cmd, 0},
118 {"accurate", accurate_cmd, 0},
119 {"restoreobject", restore_object_cmd, 0},
120 {"sm_dump", sm_dump_cmd, 0},
121 {"stop", cancel_cmd, 0},
123 {"exit", exit_cmd, 0},
125 {NULL, NULL} /* list terminator */
128 /* Commands received from director that need scanning */
129 static char jobcmd[] = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
130 static char storaddr[] = "storage address=%s port=%d ssl=%d Authorization=%100s";
131 static char storaddr_v1[] = "storage address=%s port=%d ssl=%d";
132 static char sessioncmd[] = "session %127s %ld %ld %ld %ld %ld %ld\n";
134 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
135 static char restorefcmd1[] = "restore files=%d replace=%c prelinks=%d where=\n";
137 /* The following restore commands may have a big where=/regexwhere= parameter
138 * the bsscanf is limiting the default %s to 1000c. To allow more than 1000 bytes,
139 * we can specify %xxxxs where xxxx is the size expected in bytes.
141 * So, the code will add %s\n to the end of the following restore commands
143 static char restorecmd[] = "restore replace=%c prelinks=%d where=";
144 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=";
145 static char restorefcmd[] = "restore files=%d replace=%c prelinks=%d where=";
146 static char restorefcmdR[] = "restore files=%d replace=%c prelinks=%d regexwhere=";
148 static char restoreobjcmd[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d,%s";
149 static char restoreobjcmd1[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
150 static char endrestoreobjectcmd[] = "restoreobject end\n";
151 static char verifycmd[] = "verify level=%30s";
152 static char estimatecmd[] = "estimate listing=%d";
153 static char runbefore[] = "RunBeforeJob %s";
154 static char runafter[] = "RunAfterJob %s";
155 static char runscript[] = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
156 static char setbandwidth[]= "setbandwidth=%lld Job=%127s";
158 /* Responses sent to Director */
159 static char errmsg[] = "2999 Invalid command\n";
160 static char no_auth[] = "2998 No Authorization\n";
161 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
162 static char OKBandwidth[] = "2000 OK Bandwidth\n";
163 static char OKinc[] = "2000 OK include\n";
164 static char OKest[] = "2000 OK estimate files=%s bytes=%s\n";
165 static char OKlevel[] = "2000 OK level\n";
166 static char OKbackup[] = "2000 OK backup\n";
167 static char OKverify[] = "2000 OK verify\n";
168 static char OKrestore[] = "2000 OK restore\n";
169 static char OKsession[] = "2000 OK session\n";
170 static char OKstore[] = "2000 OK storage\n";
171 static char OKstoreend[] = "2000 OK storage end\n";
172 static char OKjob[] = "2000 OK Job %s (%s) %s,%s,%s";
173 static char OKsetdebug[] = "2000 OK setdebug=%ld trace=%ld hangup=%ld"
174 " blowup=%ld options=%s tags=%s\n";
175 static char BADjob[] = "2901 Bad Job\n";
176 static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%d ReadBytes=%lld"
177 " JobBytes=%lld Errors=%d VSS=%d Encrypt=%d"
178 " CommBytes=0 CompressCommBytes=0\n";
179 static char OKRunBefore[] = "2000 OK RunBefore\n";
180 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
181 static char OKRunAfter[] = "2000 OK RunAfter\n";
182 static char OKRunScript[] = "2000 OK RunScript\n";
183 static char BADcmd[] = "2902 Bad %s\n";
184 static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
185 static char OKComponentInfo[] = "2000 OK ComponentInfo\n";
188 /* Responses received from Storage Daemon */
189 static char OK_end[] = "3000 OK end\n";
190 static char OK_close[] = "3000 OK close Status = %d\n";
191 static char OK_open[] = "3000 OK open ticket = %d\n";
192 static char OK_data[] = "3000 OK data\n";
193 static char OK_append[] = "3000 OK append data\n";
196 /* Commands sent to Storage Daemon */
197 static char append_open[] = "append open session\n";
198 static char append_data[] = "append data %d\n";
199 static char append_end[] = "append end session %d\n";
200 static char append_close[] = "append close session %d\n";
201 static char read_open[] = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
202 static char read_data[] = "read data %d\n";
203 static char read_close[] = "read close session %d\n";
204 static char read_ctrl[] = "read control %d\n";
207 * Accept requests from a Director
209 * NOTE! We are running as a separate thread
211 * Send output one line
212 * at a time followed by a zero length transmission.
214 * Return when the connection is terminated or there
217 * Basic task here is:
218 * Authenticate Director (during Hello command).
219 * Accept commands one at a time from the Director
222 * Concerning ClientRunBefore/After, the sequence of events
223 * is rather critical. If they are not done in the right
224 * order one can easily get FD->SD timeouts if the script
227 * The current sequence of events is:
228 * 1. Dir starts job with FD
229 * 2. Dir connects to SD
230 * 3. Dir connects to FD
231 * 4. FD connects to SD
232 * 5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
233 * 6. Dir sends include/exclude
234 * 7. FD sends the file data to SD
235 * 8. SD/FD disconnects while the SD despools data and attributes (optional)
236 * 9. FD runs ClientRunAfterJob
239 static void *handle_director_request(BSOCK *dir)
245 const char jobname[12] = "*Director*";
247 prevent_os_suspensions(); /* do not suspend during backup/restore */
248 jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
249 jcr->sd_calls_client_bsock = NULL;
250 jcr->sd_calls_client = false;
251 jcr->dir_bsock = dir;
252 jcr->ff = init_find_files();
253 jcr->start_time = time(NULL);
254 jcr->RunScripts = New(alist(10, not_owned_by_alist));
255 jcr->last_fname = get_pool_memory(PM_FNAME);
256 jcr->last_fname[0] = 0;
257 jcr->client_name = get_memory(strlen(my_name) + 1);
258 pm_strcpy(jcr->client_name, my_name);
259 bstrncpy(jcr->Job, jobname, sizeof(jobname)); /* dummy */
260 jcr->crypto.pki_sign = me->pki_sign;
261 jcr->crypto.pki_encrypt = me->pki_encrypt;
262 jcr->crypto.pki_keypair = me->pki_keypair;
263 jcr->crypto.pki_signers = me->pki_signers;
264 jcr->crypto.pki_recipients = me->pki_recipients;
267 /* Initialize SD start condition variable */
268 int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
271 Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat));
274 enable_backup_privileges(NULL, 1 /* ignore_errors */);
276 for (quit=false; !quit;) {
277 if (!first) { /* first call the read is done */
279 if (dir->recv() < 0) {
280 break; /* connection terminated */
283 if (dir->msglen == 0) { /* Bad connection */
287 dir->msg[dir->msglen] = 0;
288 Dmsg1(100, "<dird: %s", dir->msg);
290 for (i=0; cmds[i].cmd; i++) {
291 if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
292 found = true; /* indicate command found */
293 if (!jcr->authenticated && cmds[i].func != hello_cmd) {
295 dir->signal(BNET_EOD);
298 if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) {
299 Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
300 dir->fsend(invalid_cmd);
301 dir->signal(BNET_EOD);
304 if ((me->disabled_cmds_array && me->disabled_cmds_array[i]) ||
305 (jcr->director && jcr->director->disabled_cmds_array &&
306 jcr->director->disabled_cmds_array[i])) {
307 Jmsg(jcr, M_FATAL, 0, _("Command: \"%s\" is disabled.\n"), cmds[i].cmd);
311 Dmsg1(100, "Executing Dir %s command.\n", dir->msg);
312 if (!cmds[i].func(jcr)) { /* do command */
313 quit = true; /* error or fully terminated, get out */
314 Dmsg1(100, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
319 if (!found) { /* command not found */
326 /* Inform Storage daemon that we are done */
327 if (jcr->store_bsock) {
328 jcr->store_bsock->signal(BNET_TERMINATE);
331 /* Run the after job */
332 run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
334 if (jcr->JobId) { /* send EndJob if running a job */
335 uint32_t vss, encrypt;
336 /* Send termination status back to Dir */
337 encrypt = jcr->crypto.pki_encrypt;
339 dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles,
340 jcr->ReadBytes, jcr->JobBytes, jcr->JobErrors, vss,
344 generate_daemon_event(jcr, "JobEnd");
345 generate_plugin_event(jcr, bEventJobEnd);
348 dequeue_messages(jcr); /* send any queued messages */
350 /* Inform Director that we are done */
351 dir->signal(BNET_TERMINATE);
353 free_and_null_pool_memory(jcr->job_metadata);
355 /* Clean up fileset */
356 FF_PKT *ff = jcr->ff;
357 findFILESET *fileset = ff->fileset;
360 /* Delete FileSet Include lists */
361 for (i=0; i<fileset->include_list.size(); i++) {
362 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
363 for (j=0; j<incexe->opts_list.size(); j++) {
364 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
368 for (k=0; k<fo->regex.size(); k++) {
369 regfree((regex_t *)fo->regex.get(k));
371 for (k=0; k<fo->regexdir.size(); k++) {
372 regfree((regex_t *)fo->regexdir.get(k));
374 for (k=0; k<fo->regexfile.size(); k++) {
375 regfree((regex_t *)fo->regexfile.get(k));
378 fo->regexdir.destroy();
379 fo->regexfile.destroy();
381 fo->wilddir.destroy();
382 fo->wildfile.destroy();
383 fo->wildbase.destroy();
385 fo->fstype.destroy();
386 fo->drivetype.destroy();
388 incexe->opts_list.destroy();
389 incexe->name_list.destroy();
390 incexe->plugin_list.destroy();
391 if (incexe->ignoredir) {
392 free(incexe->ignoredir);
395 fileset->include_list.destroy();
397 /* Delete FileSet Exclude lists */
398 for (i=0; i<fileset->exclude_list.size(); i++) {
399 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
400 for (j=0; j<incexe->opts_list.size(); j++) {
401 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
403 fo->regexdir.destroy();
404 fo->regexfile.destroy();
406 fo->wilddir.destroy();
407 fo->wildfile.destroy();
408 fo->wildbase.destroy();
410 fo->fstype.destroy();
411 fo->drivetype.destroy();
413 incexe->opts_list.destroy();
414 incexe->name_list.destroy();
415 incexe->plugin_list.destroy();
416 if (incexe->ignoredir) {
417 free(incexe->ignoredir);
420 fileset->exclude_list.destroy();
424 ff->mount_points.destroy();
425 Dmsg0(100, "Calling term_find_files\n");
426 term_find_files(jcr->ff);
428 Dmsg0(100, "Done with term_find_files\n");
429 pthread_cond_destroy(&jcr->job_start_wait);
430 free_jcr(jcr); /* destroy JCR record */
431 Dmsg0(100, "Done with free_jcr\n");
432 allow_os_suspensions(); /* FD can now be suspended */
434 garbage_collect_memory_pool();
440 * Accept requests from a Director or a Storage daemon
442 void *handle_connection_request(void *caller)
444 BSOCK *bs = (BSOCK *)caller;
446 if (bs->recv() > 0) {
447 if (strncmp(bs->msg, "Ping", 4) == 0) {
448 bs->fsend("2000 Ping OK\n");
452 if (bs->msglen < 25 || bs->msglen > 500) {
455 Dmsg1(100, "Got: %s", bs->msg);
456 if (strncmp(bs->msg, "Hello Director", 14) == 0) {
457 return handle_director_request(bs);
459 if (strncmp(bs->msg, "Hello FD: Bacula Storage", 20) ==0) {
460 return handle_storage_connection(bs);
464 Dmsg2(100, "Bad command from %s. Len=%d.\n", bs->who(), bs->msglen);
466 char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
467 Jmsg2(NULL, M_FATAL, 0, _("Bad command from %s. Len=%d.\n"), who, bs->msglen);
472 static int sm_dump_cmd(JCR *jcr)
475 sm_dump(false, true);
476 jcr->dir_bsock->fsend("2000 sm_dump OK\n");
481 static int exit_cmd(JCR *jcr)
483 jcr->dir_bsock->fsend("2000 exit OK\n");
491 * Hello from Director he must identify himself and provide his
494 static int hello_cmd(JCR *jcr)
496 Dmsg0(120, "Calling Authenticate\n");
497 if (!validate_dir_hello(jcr)) {
500 if (!authenticate_director(jcr)) {
503 Dmsg0(120, "OK Authenticate\n");
504 jcr->authenticated = true;
512 static int cancel_cmd(JCR *jcr)
514 BSOCK *dir = jcr->dir_bsock;
515 char Job[MAX_NAME_LENGTH];
520 if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
521 status = JS_Canceled;
523 } else if (sscanf(dir->msg, "stop Job=%127s", Job) == 1) {
524 status = JS_Incomplete;
527 dir->fsend(_("2902 Error scanning cancel command.\n"));
530 if (!(cjcr=get_jcr_by_full_name(Job))) {
531 dir->fsend(_("2901 Job %s not found.\n"), Job);
533 generate_plugin_event(cjcr, bEventCancelCommand, NULL);
534 cjcr->setJobStatus(status);
535 if (cjcr->store_bsock) {
536 cjcr->store_bsock->set_timed_out();
537 cjcr->store_bsock->set_terminated();
539 cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
541 dir->fsend(_("2001 Job \"%s\" marked to be %s.\n"),
546 dir->signal(BNET_EOD);
551 * Set bandwidth limit as requested by the Director
554 static int setbandwidth_cmd(JCR *jcr)
556 BSOCK *dir = jcr->dir_bsock;
559 char Job[MAX_NAME_LENGTH];
562 if (sscanf(dir->msg, setbandwidth, &bw, Job) != 2 || bw < 0) {
563 pm_strcpy(jcr->errmsg, dir->msg);
564 dir->fsend(_("2991 Bad setbandwidth command: %s\n"), jcr->errmsg);
569 if(!(cjcr=get_jcr_by_full_name(Job))) {
570 dir->fsend(_("2901 Job %s not found.\n"), Job);
572 cjcr->max_bandwidth = bw;
573 if (cjcr->store_bsock) {
574 cjcr->store_bsock->set_bwlimit(bw);
579 } else { /* No job requested, apply globally */
580 me->max_bandwidth_per_job = bw; /* Overwrite directive */
582 cjcr->max_bandwidth = bw;
583 if (cjcr->store_bsock) {
584 cjcr->store_bsock->set_bwlimit(bw);
590 return dir->fsend(OKBandwidth);
594 * Set debug level as requested by the Director
597 static int setdebug_cmd(JCR *jcr)
599 BSOCK *dir = jcr->dir_bsock;
603 int64_t level, level_tags = 0;
608 Dmsg1(50, "setdebug_cmd: %s", dir->msg);
609 tags[0] = options[0] = 0;
610 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld blowup=%ld"
611 " options=%55s tags=%511s",
612 &lvl, &trace, &hangup, &blowup, options, tags);
614 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld",
615 &lvl, &trace, &hangup);
617 Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
618 if (sscanf(dir->msg, "setdebug=%ld trace=%ld", &lvl, &trace) != 2) {
619 pm_strcpy(jcr->errmsg, dir->msg);
620 dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
631 if (!debug_parse_tags(tags, &level_tags)) {
637 debug_level_tags = level_tags;
639 /* handle other options */
640 set_debug_flags(options);
642 Dmsg6(150, "level=%ld trace=%ld hangup=%ld blowup=%d options=%s tags=%s\n",
643 lvl, get_trace(), get_hangup(), get_blowup(), options, tags);
644 return dir->fsend(OKsetdebug, lvl, get_trace(), get_hangup(),
645 get_blowup(), options, tags);
649 static int estimate_cmd(JCR *jcr)
651 BSOCK *dir = jcr->dir_bsock;
652 char ed1[50], ed2[50];
654 if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
655 pm_strcpy(jcr->errmsg, dir->msg);
656 Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
657 dir->fsend(_("2992 Bad estimate command.\n"));
661 dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
662 edit_uint64_with_commas(jcr->JobBytes, ed2));
663 dir->signal(BNET_EOD);
668 * Get JobId and Storage Daemon Authorization key from Director
670 static int job_cmd(JCR *jcr)
672 BSOCK *dir = jcr->dir_bsock;
673 POOL_MEM sd_auth_key(PM_MESSAGE);
674 sd_auth_key.check_size(dir->msglen);
676 if (sscanf(dir->msg, jobcmd, &jcr->JobId, jcr->Job,
677 &jcr->VolSessionId, &jcr->VolSessionTime,
678 sd_auth_key.c_str()) != 5) {
679 pm_strcpy(jcr->errmsg, dir->msg);
680 Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
685 set_storage_auth_key(jcr, sd_auth_key.c_str());
686 Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
687 Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
688 new_plugins(jcr); /* instantiate plugins for this jcr */
689 generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
690 return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
693 extern "C" char *job_code_callback_filed(JCR *jcr, const char* param)
698 return jcr->director->hdr.name;
706 static int runbefore_cmd(JCR *jcr)
709 BSOCK *dir = jcr->dir_bsock;
710 POOLMEM *cmd = get_memory(dir->msglen+1);
713 Dmsg1(100, "runbefore_cmd: %s", dir->msg);
714 if (sscanf(dir->msg, runbefore, cmd) != 1) {
715 pm_strcpy(jcr->errmsg, dir->msg);
716 Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
717 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
723 /* Run the command now */
724 script = new_runscript();
725 script->set_job_code_callback(job_code_callback_filed);
726 script->set_command(cmd);
727 script->when = SCRIPT_Before;
728 ok = script->run(jcr, "ClientRunBeforeJob");
729 free_runscript(script);
733 dir->fsend(OKRunBefore);
736 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
741 static int runbeforenow_cmd(JCR *jcr)
743 BSOCK *dir = jcr->dir_bsock;
745 run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
746 if (job_canceled(jcr)) {
747 dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
748 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
751 dir->fsend(OKRunBeforeNow);
752 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
757 static int runafter_cmd(JCR *jcr)
759 BSOCK *dir = jcr->dir_bsock;
760 POOLMEM *msg = get_memory(dir->msglen+1);
763 Dmsg1(100, "runafter_cmd: %s", dir->msg);
764 if (sscanf(dir->msg, runafter, msg) != 1) {
765 pm_strcpy(jcr->errmsg, dir->msg);
766 Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
767 dir->fsend(_("2905 Bad RunAfterJob command.\n"));
773 cmd = new_runscript();
774 cmd->set_job_code_callback(job_code_callback_filed);
775 cmd->set_command(msg);
776 cmd->on_success = true;
777 cmd->on_failure = false;
778 cmd->when = SCRIPT_After;
780 jcr->RunScripts->append(cmd);
782 free_pool_memory(msg);
783 return dir->fsend(OKRunAfter);
786 static int runscript_cmd(JCR *jcr)
788 BSOCK *dir = jcr->dir_bsock;
789 POOLMEM *msg = get_memory(dir->msglen+1);
790 int on_success, on_failure, fail_on_error;
792 RUNSCRIPT *cmd = new_runscript() ;
793 cmd->set_job_code_callback(job_code_callback_filed);
795 Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
796 /* Note, we cannot sscanf into bools */
797 if (sscanf(dir->msg, runscript, &on_success,
802 pm_strcpy(jcr->errmsg, dir->msg);
803 Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
804 dir->fsend(_("2905 Bad RunScript command.\n"));
809 cmd->on_success = on_success;
810 cmd->on_failure = on_failure;
811 cmd->fail_on_error = fail_on_error;
814 cmd->set_command(msg);
816 jcr->RunScripts->append(cmd);
818 free_pool_memory(msg);
819 return dir->fsend(OKRunScript);
823 * This reads data sent from the Director from the
824 * RestoreObject table that allows us to get objects
825 * that were backed up (VSS .xml data) and are needed
826 * before starting the restore.
828 static int restore_object_cmd(JCR *jcr)
830 BSOCK *dir = jcr->dir_bsock;
832 restore_object_pkt rop;
834 memset(&rop, 0, sizeof(rop));
835 rop.pkt_size = sizeof(rop);
836 rop.pkt_end = sizeof(rop);
838 Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
839 if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
840 Dmsg0(20, "Got endrestoreobject\n");
841 generate_plugin_event(jcr, bEventRestoreObject, NULL);
842 return dir->fsend(OKRestoreObject);
845 rop.plugin_name = (char *)malloc(dir->msglen);
846 *rop.plugin_name = 0;
848 if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len,
849 &rop.object_full_len, &rop.object_index,
850 &rop.object_type, &rop.object_compression, &FileIndex,
851 rop.plugin_name) != 8) {
853 /* Old version, no plugin_name */
854 if (sscanf(dir->msg, restoreobjcmd1, &rop.JobId, &rop.object_len,
855 &rop.object_full_len, &rop.object_index,
856 &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
857 Dmsg0(5, "Bad restore object command\n");
858 pm_strcpy(jcr->errmsg, dir->msg);
859 Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
864 unbash_spaces(rop.plugin_name);
866 Dmsg7(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d "
867 "FI=%d plugin_name=%s\n",
868 rop.JobId, rop.object_len, rop.object_full_len,
869 rop.object_index, rop.object_type, FileIndex, rop.plugin_name);
870 /* Read Object name */
871 if (dir->recv() < 0) {
874 Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
875 rop.object_name = bstrdup(dir->msg);
878 if (dir->recv() < 0) {
881 /* Transfer object from message buffer, and get new message buffer */
882 rop.object = dir->msg;
883 dir->msg = get_pool_memory(PM_MESSAGE);
885 /* If object is compressed, uncompress it */
886 if (rop.object_compression == 1) { /* zlib level 9 */
888 int out_len = rop.object_full_len + 100;
889 POOLMEM *obj = get_memory(out_len);
890 Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
891 stat = Zinflate(rop.object, rop.object_len, obj, out_len);
892 Dmsg1(100, "Zinflate stat=%d\n", stat);
893 if (out_len != rop.object_full_len) {
894 Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
895 rop.object_full_len, out_len, rop.object_name);
897 free_pool_memory(rop.object); /* release compressed object */
898 rop.object = obj; /* new uncompressed object */
899 rop.object_len = out_len;
901 Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
902 /* we still need to do this to detect a vss restore */
903 if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
904 Dmsg0(100, "got job metadata\n");
905 jcr->got_metadata = true;
908 generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
910 if (rop.object_name) {
911 free(rop.object_name);
914 free_pool_memory(rop.object);
916 if (rop.plugin_name) {
917 free(rop.plugin_name);
920 Dmsg1(100, "Send: %s", OKRestoreObject);
924 dir->fsend(_("2909 Bad RestoreObject command.\n"));
930 static bool init_fileset(JCR *jcr)
933 findFILESET *fileset;
942 fileset = (findFILESET *)malloc(sizeof(findFILESET));
943 memset(fileset, 0, sizeof(findFILESET));
944 ff->fileset = fileset;
945 fileset->state = state_none;
946 fileset->include_list.init(1, true);
947 fileset->exclude_list.init(1, true);
952 static void append_file(JCR *jcr, findINCEXE *incexe,
953 const char *buf, bool is_file)
956 incexe->name_list.append(new_dlistString(buf));
958 } else if (me->plugin_directory) {
959 generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
960 incexe->plugin_list.append(new_dlistString(buf));
963 Jmsg(jcr, M_FATAL, 0,
964 _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
970 * Add fname to include/exclude fileset list. First check for
971 * | and < and if necessary perform command.
973 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
975 findFILESET *fileset = jcr->ff->fileset;
988 p++; /* skip over | */
989 fn = get_pool_memory(PM_FNAME);
990 fn = edit_job_codes(jcr, fn, p, "", job_code_callback_filed);
991 bpipe = open_bpipe(fn, 0, "r");
994 Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
996 free_pool_memory(fn);
999 free_pool_memory(fn);
1000 while (fgets(buf, sizeof(buf), bpipe->rfd)) {
1001 strip_trailing_junk(buf);
1002 append_file(jcr, fileset->incexe, buf, is_file);
1004 if ((stat=close_bpipe(bpipe)) != 0) {
1006 Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
1007 p, be.code(stat), be.bstrerror(stat));
1012 Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
1013 p++; /* skip over < */
1014 if ((ffd = fopen(p, "rb")) == NULL) {
1016 Jmsg(jcr, M_FATAL, 0,
1017 _("Cannot open FileSet input file: %s. ERR=%s\n"),
1021 while (fgets(buf, sizeof(buf), ffd)) {
1022 strip_trailing_junk(buf);
1023 append_file(jcr, fileset->incexe, buf, is_file);
1028 append_file(jcr, fileset->incexe, fname, is_file);
1033 findINCEXE *get_incexe(JCR *jcr)
1035 if (jcr->ff && jcr->ff->fileset) {
1036 return jcr->ff->fileset->incexe;
1041 void set_incexe(JCR *jcr, findINCEXE *incexe)
1043 findFILESET *fileset = jcr->ff->fileset;
1044 fileset->incexe = incexe;
1049 * Define a new Exclude block in the FileSet
1051 findINCEXE *new_exclude(JCR *jcr)
1053 findFILESET *fileset = jcr->ff->fileset;
1056 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1057 memset(fileset->incexe, 0, sizeof(findINCEXE));
1058 fileset->incexe->opts_list.init(1, true);
1059 fileset->incexe->name_list.init();
1060 fileset->incexe->plugin_list.init();
1061 fileset->exclude_list.append(fileset->incexe);
1062 return fileset->incexe;
1066 * Define a new Include block in the FileSet
1068 findINCEXE *new_include(JCR *jcr)
1070 findFILESET *fileset = jcr->ff->fileset;
1073 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1074 memset(fileset->incexe, 0, sizeof(findINCEXE));
1075 fileset->incexe->opts_list.init(1, true);
1076 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1077 fileset->incexe->plugin_list.init();
1078 fileset->include_list.append(fileset->incexe);
1079 return fileset->incexe;
1083 * Define a new preInclude block in the FileSet
1084 * That is the include is prepended to the other
1085 * Includes. This is used for plugin exclusions.
1087 findINCEXE *new_preinclude(JCR *jcr)
1089 findFILESET *fileset = jcr->ff->fileset;
1091 /* New pre-include */
1092 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1093 memset(fileset->incexe, 0, sizeof(findINCEXE));
1094 fileset->incexe->opts_list.init(1, true);
1095 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1096 fileset->incexe->plugin_list.init();
1097 fileset->include_list.prepend(fileset->incexe);
1098 return fileset->incexe;
1101 static findFOPTS *start_options(FF_PKT *ff)
1103 int state = ff->fileset->state;
1104 findINCEXE *incexe = ff->fileset->incexe;
1106 if (state != state_options) {
1107 ff->fileset->state = state_options;
1108 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1109 memset(fo, 0, sizeof(findFOPTS));
1110 fo->regex.init(1, true);
1111 fo->regexdir.init(1, true);
1112 fo->regexfile.init(1, true);
1113 fo->wild.init(1, true);
1114 fo->wilddir.init(1, true);
1115 fo->wildfile.init(1, true);
1116 fo->wildbase.init(1, true);
1117 fo->base.init(1, true);
1118 fo->fstype.init(1, true);
1119 fo->drivetype.init(1, true);
1120 incexe->current_opts = fo;
1121 incexe->opts_list.append(fo);
1123 return incexe->current_opts;
1127 * Used by plugins to define a new options block
1129 void new_options(JCR *jcr, findINCEXE *incexe)
1132 incexe = jcr->ff->fileset->incexe;
1134 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1135 memset(fo, 0, sizeof(findFOPTS));
1136 fo->regex.init(1, true);
1137 fo->regexdir.init(1, true);
1138 fo->regexfile.init(1, true);
1139 fo->wild.init(1, true);
1140 fo->wilddir.init(1, true);
1141 fo->wildfile.init(1, true);
1142 fo->wildbase.init(1, true);
1143 fo->base.init(1, true);
1144 fo->fstype.init(1, true);
1145 fo->drivetype.init(1, true);
1146 incexe->current_opts = fo;
1147 incexe->opts_list.prepend(fo);
1148 jcr->ff->fileset->state = state_options;
1152 * Add a regex to the current fileset
1154 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
1156 findFOPTS *current_opts = start_options(jcr->ff);
1161 preg = (regex_t *)malloc(sizeof(regex_t));
1162 if (current_opts->flags & FO_IGNORECASE) {
1163 rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1165 rc = regcomp(preg, item, REG_EXTENDED);
1168 regerror(rc, preg, prbuf, sizeof(prbuf));
1171 Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1175 current_opts->regex.append(preg);
1176 } else if (type == 'D') {
1177 current_opts->regexdir.append(preg);
1178 } else if (type == 'F') {
1179 current_opts->regexfile.append(preg);
1183 return state_options;
1187 * Add a wild card to the current fileset
1189 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1191 findFOPTS *current_opts = start_options(jcr->ff);
1194 current_opts->wild.append(bstrdup(item));
1195 } else if (type == 'D') {
1196 current_opts->wilddir.append(bstrdup(item));
1197 } else if (type == 'F') {
1198 current_opts->wildfile.append(bstrdup(item));
1199 } else if (type == 'B') {
1200 current_opts->wildbase.append(bstrdup(item));
1204 return state_options;
1209 * Add options to the current fileset
1211 int add_options_to_fileset(JCR *jcr, const char *item)
1213 findFOPTS *current_opts = start_options(jcr->ff);
1215 set_options(current_opts, item);
1216 return state_options;
1219 static void add_fileset(JCR *jcr, const char *item)
1221 FF_PKT *ff = jcr->ff;
1222 findFILESET *fileset = ff->fileset;
1223 int state = fileset->state;
1224 findFOPTS *current_opts;
1226 /* Get code, optional subcode, and position item past the dividing space */
1227 Dmsg1(100, "%s\n", item);
1232 int subcode = ' '; /* A space is always a valid subcode */
1233 if (item[0] != '\0' && item[0] != ' ') {
1241 /* Skip all lines we receive after an error */
1242 if (state == state_error) {
1243 Dmsg0(100, "State=error return\n");
1248 * The switch tests the code for validity.
1249 * The subcode is always good if it is a space, otherwise we must confirm.
1250 * We set state to state_error first assuming the subcode is invalid,
1251 * requiring state to be set in cases below that handle subcodes.
1253 if (subcode != ' ') {
1254 state = state_error;
1255 Dmsg0(100, "Set state=error or double code.\n");
1259 (void)new_include(jcr);
1262 (void)new_exclude(jcr);
1264 case 'N': /* null */
1267 case 'F': /* file = */
1268 /* File item to include or exclude list */
1269 state = state_include;
1270 add_file_to_fileset(jcr, item, true);
1272 case 'P': /* plugin */
1273 /* Plugin item to include list */
1274 state = state_include;
1275 add_file_to_fileset(jcr, item, false);
1277 case 'R': /* regex */
1278 state = add_regex_to_fileset(jcr, item, subcode);
1281 current_opts = start_options(ff);
1282 current_opts->base.append(bstrdup(item));
1283 state = state_options;
1285 case 'X': /* Filetype or Drive type */
1286 current_opts = start_options(ff);
1287 state = state_options;
1288 if (subcode == ' ') {
1289 current_opts->fstype.append(bstrdup(item));
1290 } else if (subcode == 'D') {
1291 current_opts->drivetype.append(bstrdup(item));
1293 state = state_error;
1296 case 'W': /* wild cards */
1297 state = add_wild_to_fileset(jcr, item, subcode);
1299 case 'O': /* Options */
1300 state = add_options_to_fileset(jcr, item);
1302 case 'Z': /* ignore dir */
1303 state = state_include;
1304 fileset->incexe->ignoredir = bstrdup(item);
1307 current_opts = start_options(ff);
1308 // current_opts->reader = bstrdup(item); /* deprecated */
1309 state = state_options;
1312 current_opts = start_options(ff);
1313 // current_opts->writer = bstrdup(item); /* deprecated */
1314 state = state_options;
1316 case 'G': /* Plugin command for this Option block */
1317 current_opts = start_options(ff);
1318 current_opts->plugin = bstrdup(item);
1319 state = state_options;
1322 Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1323 state = state_error;
1326 ff->fileset->state = state;
1329 static bool term_fileset(JCR *jcr)
1331 FF_PKT *ff = jcr->ff;
1333 #ifdef xxx_DEBUG_CODE
1334 findFILESET *fileset = ff->fileset;
1337 for (i=0; i<fileset->include_list.size(); i++) {
1338 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1340 for (j=0; j<incexe->opts_list.size(); j++) {
1341 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1342 for (k=0; k<fo->regex.size(); k++) {
1343 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1345 for (k=0; k<fo->regexdir.size(); k++) {
1346 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1348 for (k=0; k<fo->regexfile.size(); k++) {
1349 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1351 for (k=0; k<fo->wild.size(); k++) {
1352 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1354 for (k=0; k<fo->wilddir.size(); k++) {
1355 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1357 for (k=0; k<fo->wildfile.size(); k++) {
1358 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1360 for (k=0; k<fo->wildbase.size(); k++) {
1361 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1363 for (k=0; k<fo->base.size(); k++) {
1364 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1366 for (k=0; k<fo->fstype.size(); k++) {
1367 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1369 for (k=0; k<fo->drivetype.size(); k++) {
1370 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1373 if (incexe->ignoredir) {
1374 Dmsg1(400, "Z %s\n", incexe->ignoredir);
1377 foreach_dlist(node, &incexe->name_list) {
1378 Dmsg1(400, "F %s\n", node->c_str());
1380 foreach_dlist(node, &incexe->plugin_list) {
1381 Dmsg1(400, "P %s\n", node->c_str());
1384 for (i=0; i<fileset->exclude_list.size(); i++) {
1385 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1387 for (j=0; j<incexe->opts_list.size(); j++) {
1388 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1389 for (k=0; k<fo->regex.size(); k++) {
1390 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1392 for (k=0; k<fo->regexdir.size(); k++) {
1393 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1395 for (k=0; k<fo->regexfile.size(); k++) {
1396 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1398 for (k=0; k<fo->wild.size(); k++) {
1399 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1401 for (k=0; k<fo->wilddir.size(); k++) {
1402 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1404 for (k=0; k<fo->wildfile.size(); k++) {
1405 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1407 for (k=0; k<fo->wildbase.size(); k++) {
1408 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1410 for (k=0; k<fo->base.size(); k++) {
1411 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1413 for (k=0; k<fo->fstype.size(); k++) {
1414 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1416 for (k=0; k<fo->drivetype.size(); k++) {
1417 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1421 foreach_dlist(node, &incexe->name_list) {
1422 Dmsg1(400, "F %s\n", node->c_str());
1424 foreach_dlist(node, &incexe->plugin_list) {
1425 Dmsg1(400, "P %s\n", node->c_str());
1429 return ff->fileset->state != state_error;
1434 * As an optimization, we should do this during
1435 * "compile" time in filed/job.c, and keep only a bit mask
1436 * and the Verify options.
1438 static int set_options(findFOPTS *fo, const char *opts)
1444 // Commented out as it is not backward compatible - KES
1446 for (p=opts; *p; p++) {
1448 case 'a': /* alway replace */
1449 case '0': /* no option */
1452 fo->flags |= FO_EXCLUDE;
1455 fo->flags |= FO_MULTIFS;
1457 case 'h': /* no recursion */
1458 fo->flags |= FO_NO_RECURSION;
1460 case 'H': /* no hard link handling */
1461 fo->flags |= FO_NO_HARDLINK;
1464 fo->flags |= FO_IGNORECASE;
1467 fo->flags |= FO_MD5;
1470 fo->flags |= FO_NOREPLACE;
1472 case 'p': /* use portable data format */
1473 fo->flags |= FO_PORTABLE;
1475 case 'R': /* Resource forks and Finder Info */
1476 fo->flags |= FO_HFSPLUS;
1478 case 'r': /* read fifo */
1479 fo->flags |= FO_READFIFO;
1484 fo->flags |= FO_SHA1;
1489 fo->flags |= FO_SHA256;
1493 fo->flags |= FO_SHA512;
1499 * If 2 or 3 is seen here, SHA2 is not configured, so
1500 * eat the option, and drop back to SHA-1.
1502 if (p[1] == '2' || p[1] == '3') {
1505 fo->flags |= FO_SHA1;
1510 fo->flags |= FO_SPARSE;
1513 fo->flags |= FO_MTIMEONLY;
1516 fo->flags |= FO_KEEPATIME;
1519 fo->flags |= FO_ACL;
1521 case 'V': /* verify options */
1522 /* Copy Verify Options */
1523 for (j=0; *p && *p != ':'; p++) {
1524 fo->VerifyOpts[j] = *p;
1525 if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1529 fo->VerifyOpts[j] = 0;
1531 case 'C': /* accurate options */
1532 /* Copy Accurate Options */
1533 for (j=0; *p && *p != ':'; p++) {
1534 fo->AccurateOpts[j] = *p;
1535 if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1539 fo->AccurateOpts[j] = 0;
1541 case 'J': /* Basejob options */
1542 /* Copy BaseJob Options */
1543 for (j=0; *p && *p != ':'; p++) {
1544 fo->BaseJobOpts[j] = *p;
1545 if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1549 fo->BaseJobOpts[j] = 0;
1551 case 'P': /* strip path */
1554 for (j=0; *p && *p != ':'; p++) {
1556 if (j < (int)sizeof(strip) - 1) {
1561 fo->strip_path = atoi(strip);
1562 fo->flags |= FO_STRIPPATH;
1563 Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1566 fo->flags |= FO_IF_NEWER;
1569 fo->flags |= FO_ENHANCEDWILD;
1571 case 'Z': /* compression */
1573 if (*p >= '0' && *p <= '9') {
1574 fo->flags |= FO_COMPRESS;
1575 fo->Compress_algo = COMPRESS_GZIP;
1576 fo->Compress_level = *p - '0';
1578 else if (*p == 'o') {
1579 fo->flags |= FO_COMPRESS;
1580 fo->Compress_algo = COMPRESS_LZO1X;
1581 fo->Compress_level = 1; /* not used with LZO */
1585 fo->flags |= FO_NOATIME;
1588 fo->flags |= FO_CHKCHANGES;
1591 fo->flags |= FO_HONOR_NODUMP;
1594 fo->flags |= FO_XATTR;
1597 Jmsg1(NULL, M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1601 return state_options;
1606 * Director is passing his Fileset
1608 static int fileset_cmd(JCR *jcr)
1610 POOL_MEM buf(PM_MESSAGE);
1611 BSOCK *dir = jcr->dir_bsock;
1614 jcr->Snapshot = (strstr(dir->msg, "snap=1") != NULL);
1615 if (!init_fileset(jcr)) {
1618 while (dir->recv() >= 0) {
1619 strip_trailing_junk(dir->msg);
1620 Dmsg1(500, "Fileset: %s\n", dir->msg);
1621 pm_strcpy(buf, dir->msg);
1622 add_fileset(jcr, buf.c_str());
1624 if (!term_fileset(jcr)) {
1627 rtnstat = dir->fsend(OKinc);
1628 generate_plugin_event(jcr, bEventEndFileSet);
1634 * The Director sends us the component info file, which
1635 * we will in turn pass to the VSS plugin.
1637 static int component_cmd(JCR *jcr)
1639 BSOCK *dir = jcr->dir_bsock;
1641 while (dir->recv() >= 0) {
1642 Dmsg1(200, "filed<dird: component: %s", dir->msg);
1643 generate_plugin_event(jcr, bEventComponentInfo, (void *)dir->msg);
1645 return dir->fsend(OKComponentInfo);
1650 * Get backup level from Director
1652 * Note: there are odd things such as accurate_differential,
1653 * and accurate_incremental that are passed in level, thus
1654 * the calls to strstr() below.
1657 static int level_cmd(JCR *jcr)
1659 BSOCK *dir = jcr->dir_bsock;
1660 POOLMEM *level, *buf = NULL;
1663 level = get_memory(dir->msglen+1);
1664 Dmsg1(10, "level_cmd: %s", dir->msg);
1666 /* keep compatibility with older directors */
1667 if (strstr(dir->msg, "accurate")) {
1668 jcr->accurate = true;
1670 if (strstr(dir->msg, "rerunning")) {
1671 jcr->rerunning = true;
1673 if (sscanf(dir->msg, "level = %s ", level) != 1) {
1676 /* Base backup requested? */
1677 if (strcasecmp(level, "base") == 0) {
1678 jcr->setJobLevel(L_BASE);
1679 /* Full backup requested? */
1680 } else if (strcasecmp(level, "full") == 0) {
1681 jcr->setJobLevel(L_FULL);
1682 } else if (strstr(level, "differential")) {
1683 jcr->setJobLevel(L_DIFFERENTIAL);
1686 } else if (strstr(level, "incremental")) {
1687 jcr->setJobLevel(L_INCREMENTAL);
1691 * We get his UTC since time, then sync the clocks and correct it
1692 * to agree with our clock.
1694 } else if (strcasecmp(level, "since_utime") == 0) {
1695 buf = get_memory(dir->msglen+1);
1696 utime_t since_time, adj;
1697 btime_t his_time, bt_start, rt=0, bt_adj=0, his_time_prev=0, n=0;
1698 if (jcr->getJobLevel() == L_NONE) {
1699 jcr->setJobLevel(L_SINCE); /* if no other job level set, do it now */
1701 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d prev_job=%127s",
1702 buf, &mtime_only, jcr->PrevJob) != 3) {
1703 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1704 buf, &mtime_only) != 2) {
1708 since_time = str_to_uint64(buf); /* this is the since time */
1709 Dmsg2(100, "since_time=%lld prev_job=%s\n", since_time, jcr->PrevJob);
1710 char ed1[50], ed2[50];
1712 * Sync clocks by polling him for the time. We take
1713 * 10 samples of his time throwing out the first two.
1715 for (int i=0; i<10; i++) {
1716 bt_start = get_current_btime();
1717 dir->signal(BNET_BTIME); /* poll for time */
1718 if (dir->recv() <= 0) { /* get response */
1721 if (sscanf(dir->msg, "btime %s", buf) != 1) {
1724 his_time = str_to_uint64(buf);
1725 rt = get_current_btime() - bt_start; /* compute round trip time */
1726 /* skip first two results and check for leap second */
1727 /* if any of the FD or DIR went back in time, skip this iteration */
1728 if (i < 2 || (his_time_prev > 0 && his_time < his_time_prev) || rt<0) {
1729 his_time_prev = his_time;
1732 his_time_prev = his_time;
1734 Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1735 edit_uint64(bt_start, ed2));
1736 bt_adj += bt_start - his_time - rt/2;
1737 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1740 if (n > 0) { /* Should be 1 in the worst case */
1741 bt_adj = bt_adj / n; /* compute average time */
1742 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1743 adj = btime_to_utime(bt_adj);
1744 since_time += adj; /* adjust for clock difference */
1746 /* Don't notify if time within 3 seconds */
1747 if (adj > 3 || adj < -3) {
1749 if (adj > 600 || adj < -600) {
1754 Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1756 dir->signal(BNET_EOD);
1758 Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1759 jcr->incremental = 1; /* set incremental or decremental backup */
1760 jcr->mtime = since_time; /* set since time */
1761 generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1763 Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1771 generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1772 return dir->fsend(OKlevel);
1775 pm_strcpy(jcr->errmsg, dir->msg);
1776 Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1785 * Get session parameters from Director -- this is for a Restore command
1786 * This is deprecated. It is now passed via the bsr.
1788 static int session_cmd(JCR *jcr)
1790 BSOCK *dir = jcr->dir_bsock;
1792 Dmsg1(100, "SessionCmd: %s", dir->msg);
1793 if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1794 &jcr->VolSessionId, &jcr->VolSessionTime,
1795 &jcr->StartFile, &jcr->EndFile,
1796 &jcr->StartBlock, &jcr->EndBlock) != 7) {
1797 pm_strcpy(jcr->errmsg, dir->msg);
1798 Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1802 return dir->fsend(OKsession);
1805 static void set_storage_auth_key(JCR *jcr, char *key)
1807 /* if no key don't update anything */
1813 * We can be contacting multiple storage daemons.
1814 * So, make sure that any old jcr->store_bsock is cleaned up.
1816 free_bsock(jcr->store_bsock);
1819 * We can be contacting multiple storage daemons.
1820 * So, make sure that any old jcr->sd_auth_key is cleaned up.
1822 if (jcr->sd_auth_key) {
1824 * If we already have a Authorization key, director can do multi
1827 Dmsg0(5, "set multi_restore=true\n");
1828 jcr->multi_restore = true;
1829 bfree(jcr->sd_auth_key);
1832 jcr->sd_auth_key = bstrdup(key);
1833 Dmsg1(5, "set sd auth key %s\n", jcr->sd_auth_key);
1837 * Get address of storage daemon from Director
1840 static int storage_cmd(JCR *jcr)
1842 int stored_port = 0; /* storage daemon port */
1843 int enable_ssl; /* enable ssl to sd */
1844 POOL_MEM sd_auth_key(PM_MESSAGE);
1845 BSOCK *dir = jcr->dir_bsock;
1848 Dmsg1(100, "StorageCmd: %s", dir->msg);
1849 sd_auth_key.check_size(dir->msglen);
1850 if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port,
1851 &enable_ssl, sd_auth_key.c_str()) == 4) {
1852 Dmsg1(100, "Set auth key %s\n", sd_auth_key.c_str());
1853 set_storage_auth_key(jcr, sd_auth_key.c_str());
1854 } else if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
1855 &stored_port, &enable_ssl) != 3) {
1856 pm_strcpy(jcr->errmsg, dir->msg);
1857 Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1858 Pmsg1(010, "Bad storage command: %s", jcr->errmsg);
1863 /* TODO: see if we put limit on restore and backup... */
1864 if (!jcr->max_bandwidth) {
1865 if (jcr->director->max_bandwidth_per_job) {
1866 jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
1868 } else if (me->max_bandwidth_per_job) {
1869 jcr->max_bandwidth = me->max_bandwidth_per_job;
1873 if (stored_port != 0) { /* We are doing the connecting */
1874 Dmsg3(110, "Connect to storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port,
1876 jcr->sd_calls_client = false;
1878 /* Open command communications with Storage daemon */
1879 /* Try to connect for 1 hour at 10 second intervals */
1880 sd->set_source_address(me->FDsrc_addr);
1881 if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1882 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1883 /* destroy() OK because sd is local */
1885 Jmsg2(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1886 jcr->stored_addr, stored_port);
1887 Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1888 jcr->stored_addr, stored_port);
1892 Dmsg0(110, "Connection OK to SD.\n");
1893 jcr->store_bsock = sd;
1894 } else { /* The storage daemon called us */
1897 struct timespec timeout;
1900 free_bsock(jcr->store_bsock);
1901 jcr->sd_calls_client = true;
1904 * Wait for the Storage daemon to contact us to start the Job,
1905 * when he does, we will be released, unless the 30 minutes
1908 gettimeofday(&tv, &tz);
1909 timeout.tv_nsec = tv.tv_usec * 1000;
1910 timeout.tv_sec = tv.tv_sec + 30 * 60; /* wait 30 minutes */
1912 while (jcr->sd_calls_client_bsock == NULL && !jcr->is_job_canceled()) {
1913 errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
1914 if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
1917 Dmsg1(800, "=== Auth cond errstat=%d\n", errstat);
1920 Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr);
1922 /* We should already have a storage connection! */
1923 if (jcr->sd_calls_client_bsock == NULL) {
1924 Pmsg0(000, "Failed connect from Storage daemon. SD bsock=NULL.\n");
1925 Pmsg1(000, "Storagecmd: %s", dir->msg);
1926 Jmsg0(jcr, M_FATAL, 0, _("Failed connect from Storage daemon. SD bsock=NULL.\n"));
1929 if (jcr->is_job_canceled()) {
1932 /* Assign the new socket to the main one */
1934 jcr->store_bsock = jcr->sd_calls_client_bsock;
1935 jcr->sd_calls_client_bsock = NULL;
1938 jcr->store_bsock->set_bwlimit(jcr->max_bandwidth);
1940 if (!send_hello_sd(jcr, jcr->Job)) {
1944 if (!authenticate_storagedaemon(jcr)) {
1947 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
1948 Dmsg0(110, "Authenticated with SD.\n");
1950 /* Send OK to Director */
1951 return dir->fsend(OKstore);
1954 dir->fsend(BADcmd, "storage");
1962 static int backup_cmd(JCR *jcr)
1964 BSOCK *dir = jcr->dir_bsock;
1965 BSOCK *sd = jcr->store_bsock;
1970 if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1971 jcr->JobFiles = FileIndex;
1972 Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1976 * If explicitly requesting FO_ACL or FO_XATTR, fail job if it
1977 * is not available on Client machine
1979 if (jcr->ff->flags & FO_ACL && !(have_acl||have_win32)) {
1980 Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for Client.\n"));
1983 if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1984 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for Client.\n"));
1987 jcr->setJobStatus(JS_Blocked);
1988 jcr->setJobType(JT_BACKUP);
1989 Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1991 Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1992 dir->fsend(BADcmd, "backup");
1996 dir->fsend(OKbackup);
1997 Dmsg1(110, "filed>dird: %s", dir->msg);
2000 * Send Append Open Session to Storage daemon
2002 sd->fsend(append_open);
2003 Dmsg1(110, ">stored: %s", sd->msg);
2005 * Expect to receive back the Ticket number
2007 if (bget_msg(sd) >= 0) {
2008 Dmsg1(110, "<stored: %s", sd->msg);
2009 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2010 Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
2013 Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
2015 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
2020 * Send Append data command to Storage daemon
2022 sd->fsend(append_data, jcr->Ticket);
2023 Dmsg1(110, ">stored: %s", sd->msg);
2026 * Expect to get OK data
2028 Dmsg1(110, "<stored: %s", sd->msg);
2029 if (!response(jcr, sd, OK_data, "Append Data")) {
2033 generate_daemon_event(jcr, "JobStart");
2034 generate_plugin_event(jcr, bEventStartBackupJob);
2036 if (jcr->Snapshot) {
2037 Dmsg0(10, "Open a snapshot session\n");
2038 /* TODO: See if we abort the job */
2039 jcr->Snapshot = open_snapshot_backup_session(jcr);
2041 /* Call RunScript just after the Snapshot creation, usually, we restart services */
2042 run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2046 * Send Files to Storage daemon
2048 Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
2049 if (!blast_data_to_storage_daemon(jcr, NULL)) {
2050 jcr->setJobStatus(JS_ErrorTerminated);
2051 sd->suppress_error_messages(true);
2052 Dmsg0(110, "Error in blast_data.\n");
2054 jcr->setJobStatus(JS_Terminated);
2055 /* Note, the above set status will not override an error */
2056 if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
2057 sd->suppress_error_messages(true);
2058 goto cleanup; /* bail out now */
2061 * Expect to get response to append_data from Storage daemon
2063 if (!response(jcr, sd, OK_append, "Append Data")) {
2064 jcr->setJobStatus(JS_ErrorTerminated);
2069 * Send Append End Data to Storage daemon
2071 sd->fsend(append_end, jcr->Ticket);
2073 if (!response(jcr, sd, OK_end, "Append End")) {
2074 jcr->setJobStatus(JS_ErrorTerminated);
2079 * Send Append Close to Storage daemon
2081 sd->fsend(append_close, jcr->Ticket);
2083 while (bget_msg(sd) >= 0) { /* stop on signal or error */
2084 if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
2086 Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
2088 Dmsg1(100, "append_close: scan fail from %s\n", sd->msg);
2092 Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
2093 Dmsg1(100, "append_close: scan fail from %s\n", sd->msg);
2096 if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings ||
2097 SDJobStatus == JS_Incomplete)) {
2098 Jmsg(jcr, M_FATAL, 0, _("Bad status %d %c returned from Storage Daemon.\n"),
2099 SDJobStatus, (char)SDJobStatus);
2105 generate_plugin_event(jcr, bEventEndBackupJob);
2106 return 0; /* return and stop command loop */
2110 * Do a Verify for Director
2113 static int verify_cmd(JCR *jcr)
2115 BSOCK *dir = jcr->dir_bsock;
2116 BSOCK *sd = jcr->store_bsock;
2119 jcr->setJobType(JT_VERIFY);
2120 if (sscanf(dir->msg, verifycmd, level) != 1) {
2121 dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2125 if (strcasecmp(level, "init") == 0) {
2126 jcr->setJobLevel(L_VERIFY_INIT);
2127 } else if (strcasecmp(level, "catalog") == 0){
2128 jcr->setJobLevel(L_VERIFY_CATALOG);
2129 } else if (strcasecmp(level, "volume") == 0){
2130 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
2131 } else if (strcasecmp(level, "data") == 0){
2132 jcr->setJobLevel(L_VERIFY_DATA);
2133 } else if (strcasecmp(level, "disk_to_catalog") == 0) {
2134 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2136 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2140 dir->fsend(OKverify);
2142 generate_daemon_event(jcr, "JobStart");
2143 generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2144 generate_plugin_event(jcr, bEventStartVerifyJob);
2146 Dmsg1(110, "filed>dird: %s", dir->msg);
2148 switch (jcr->getJobLevel()) {
2150 case L_VERIFY_CATALOG:
2154 case L_VERIFY_VOLUME_TO_CATALOG:
2155 if (!open_sd_read_session(jcr)) {
2158 start_dir_heartbeat(jcr);
2159 do_verify_volume(jcr);
2160 stop_dir_heartbeat(jcr);
2162 * Send Close session command to Storage daemon
2164 sd->fsend(read_close, jcr->Ticket);
2165 Dmsg1(130, "filed>stored: %s", sd->msg);
2167 /* ****FIXME**** check response */
2168 bget_msg(sd); /* get OK */
2170 /* Inform Storage daemon that we are done */
2171 sd->signal(BNET_TERMINATE);
2174 case L_VERIFY_DISK_TO_CATALOG:
2178 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2182 dir->signal(BNET_EOD);
2183 generate_plugin_event(jcr, bEventEndVerifyJob);
2184 return 0; /* return and terminate command loop */
2188 * Do a Restore for Director
2191 static int restore_cmd(JCR *jcr)
2193 BSOCK *dir = jcr->dir_bsock;
2194 BSOCK *sd = jcr->store_bsock;
2195 POOLMEM *args=NULL, *restore_where=NULL, *restore_rwhere=NULL;
2196 bool use_regexwhere=false;
2199 bool scan_ok = true;
2204 * Scan WHERE (base directory for restore) from command
2206 Dmsg0(100, "restore command\n");
2208 /* Pickup where string */
2209 args = get_memory(dir->msglen+1);
2212 restore_where = get_pool_memory(PM_FNAME);
2213 restore_rwhere = get_pool_memory(PM_FNAME);
2215 /* We don't know the size of where/rwhere in advance,
2216 * where= -> where=%202s\n
2218 Mmsg(restore_where, "%s%%%ds\n", restorefcmd, dir->msglen);
2219 Mmsg(restore_rwhere, "%s%%%ds\n", restorefcmdR, dir->msglen);
2221 Dmsg2(200, "where=%srwhere=%s", restore_where, restore_rwhere);
2223 /* Scan for new form with number of files to restore */
2224 if (sscanf(dir->msg, restore_where, &files, &replace, &prefix_links, args) != 4) {
2225 if (sscanf(dir->msg, restore_rwhere, &files, &replace, &prefix_links, args) != 4) {
2226 if (sscanf(dir->msg, restorefcmd1, &files, &replace, &prefix_links) != 3) {
2229 *args = 0; /* No where argument */
2231 use_regexwhere = true;
2236 jcr->ExpectedFiles = files;
2238 /* Scan for old form without number of files */
2239 jcr->ExpectedFiles = 0;
2241 /* where= -> where=%202s\n */
2242 Mmsg(restore_where, "%s%%%ds\n", restorecmd, dir->msglen);
2243 Mmsg(restore_rwhere, "%s%%%ds\n", restorecmdR, dir->msglen);
2245 if (sscanf(dir->msg, restore_where, &replace, &prefix_links, args) != 3) {
2246 if (sscanf(dir->msg, restore_rwhere, &replace, &prefix_links, args) != 3){
2247 if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2248 pm_strcpy(jcr->errmsg, dir->msg);
2249 Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2252 *args = 0; /* No where argument */
2254 use_regexwhere = true;
2259 /* Turn / into nothing */
2260 if (IsPathSeparator(args[0]) && args[1] == '\0') {
2264 Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2265 unbash_spaces(args);
2267 /* Keep track of newly created directories to apply them correct attributes */
2268 if (replace == REPLACE_NEVER || replace == REPLACE_IFNEWER) {
2269 jcr->keep_path_list = true;
2272 if (use_regexwhere) {
2273 jcr->where_bregexp = get_bregexps(args);
2274 if (!jcr->where_bregexp) {
2275 Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2279 jcr->where = bstrdup(args);
2282 jcr->replace = replace;
2283 jcr->prefix_links = prefix_links;
2285 dir->fsend(OKrestore);
2286 Dmsg1(110, "filed>dird: %s", dir->msg);
2288 jcr->setJobType(JT_RESTORE);
2290 jcr->setJobStatus(JS_Blocked);
2292 if (!open_sd_read_session(jcr)) {
2293 jcr->setJobStatus(JS_ErrorTerminated);
2297 jcr->setJobStatus(JS_Running);
2300 * Do restore of files and data
2302 start_dir_heartbeat(jcr);
2303 generate_daemon_event(jcr, "JobStart");
2304 generate_plugin_event(jcr, bEventStartRestoreJob);
2307 stop_dir_heartbeat(jcr);
2309 jcr->setJobStatus(JS_Terminated);
2310 if (jcr->JobStatus != JS_Terminated) {
2311 sd->suppress_error_messages(true);
2315 * Send Close session command to Storage daemon
2317 sd->fsend(read_close, jcr->Ticket);
2318 Dmsg1(100, "filed>stored: %s", sd->msg);
2320 bget_msg(sd); /* get OK */
2322 /* Inform Storage daemon that we are done */
2323 sd->signal(BNET_TERMINATE);
2326 bfree_and_null(jcr->where);
2328 if (jcr->JobErrors) {
2329 jcr->setJobStatus(JS_ErrorTerminated);
2332 Dmsg0(100, "Done in job.c\n");
2334 if (jcr->multi_restore) {
2335 Dmsg0(100, OKstoreend);
2336 dir->fsend(OKstoreend);
2337 ret = 1; /* we continue the loop, waiting for next part */
2339 ret = 0; /* we stop here */
2342 if (job_canceled(jcr)) {
2343 ret = 0; /* we stop here */
2347 end_restore_cmd(jcr); /* stopping so send bEventEndRestoreJob */
2351 free_and_null_pool_memory(args);
2352 free_and_null_pool_memory(restore_where);
2353 free_and_null_pool_memory(restore_rwhere);
2358 static int end_restore_cmd(JCR *jcr)
2360 Dmsg0(5, "end_restore_cmd\n");
2361 generate_plugin_event(jcr, bEventEndRestoreJob);
2362 return 0; /* return and terminate command loop */
2365 static int open_sd_read_session(JCR *jcr)
2367 BSOCK *sd = jcr->store_bsock;
2370 Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2373 Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2374 jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2375 Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2377 * Open Read Session with Storage daemon
2379 sd->fsend(read_open, "DummyVolume",
2380 jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2381 jcr->StartBlock, jcr->EndBlock);
2382 Dmsg1(110, ">stored: %s", sd->msg);
2387 if (bget_msg(sd) >= 0) {
2388 Dmsg1(110, "filed<stored: %s", sd->msg);
2389 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2390 Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2393 Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2395 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2400 * Use interactive session for the current restore
2402 if (jcr->interactive_session) {
2403 sd->fsend(read_ctrl, jcr->Ticket);
2404 Dmsg1(110, ">stored: %s", sd->msg);
2408 * Start read of data with Storage daemon
2410 sd->fsend(read_data, jcr->Ticket);
2411 Dmsg1(110, ">stored: %s", sd->msg);
2416 if (!response(jcr, sd, OK_data, "Read Data")) {
2423 * Destroy the Job Control Record and associated
2424 * resources (sockets).
2426 static void filed_free_jcr(JCR *jcr)
2428 if (jcr->dir_bsock) {
2429 free_bsock(jcr->dir_bsock);
2430 jcr->dir_bsock = NULL;
2432 if (jcr->sd_calls_client_bsock) {
2433 free_bsock(jcr->sd_calls_client_bsock);
2434 jcr->sd_calls_client_bsock = NULL;
2436 if (jcr->store_bsock) {
2437 free_bsock(jcr->store_bsock);
2438 jcr->store_bsock = NULL;
2440 if (jcr->last_fname) {
2441 free_pool_memory(jcr->last_fname);
2443 free_plugins(jcr); /* release instantiated plugins */
2444 free_runscripts(jcr->RunScripts);
2445 delete jcr->RunScripts;
2446 free_path_list(jcr);
2448 if (jcr->JobId != 0)
2449 write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2455 * Get response from Storage daemon to a command we
2456 * sent. Check that the response is OK.
2458 * Returns: 0 on failure
2461 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2468 if ((ret = bget_msg(sd)) > 0) {
2469 Dmsg0(110, sd->msg);
2470 if (strcmp(sd->msg, resp) == 0) {
2474 if (job_canceled(jcr)) {
2475 return 0; /* if canceled avoid useless error messages */
2477 if (sd->is_error()) {
2478 Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2479 cmd, sd->bstrerror());
2483 Jmsg4(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got len=%ld msg=\"%s\"\n"),
2484 cmd, resp, sd->msglen, smartdump(sd->msg, sd->msglen, buf, sizeof(buf)));
2486 Jmsg3(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got SIGNAL %s\n"),
2487 cmd, resp, bnet_sig_to_ascii(ret));