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,
346 generate_daemon_event(jcr, "JobEnd");
347 generate_plugin_event(jcr, bEventJobEnd);
350 dequeue_messages(jcr); /* send any queued messages */
352 /* Inform Director that we are done */
353 dir->signal(BNET_TERMINATE);
355 free_and_null_pool_memory(jcr->job_metadata);
357 /* Clean up fileset */
358 FF_PKT *ff = jcr->ff;
359 findFILESET *fileset = ff->fileset;
362 /* Delete FileSet Include lists */
363 for (i=0; i<fileset->include_list.size(); i++) {
364 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
365 for (j=0; j<incexe->opts_list.size(); j++) {
366 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
370 for (k=0; k<fo->regex.size(); k++) {
371 regfree((regex_t *)fo->regex.get(k));
373 for (k=0; k<fo->regexdir.size(); k++) {
374 regfree((regex_t *)fo->regexdir.get(k));
376 for (k=0; k<fo->regexfile.size(); k++) {
377 regfree((regex_t *)fo->regexfile.get(k));
380 fo->regexdir.destroy();
381 fo->regexfile.destroy();
383 fo->wilddir.destroy();
384 fo->wildfile.destroy();
385 fo->wildbase.destroy();
387 fo->fstype.destroy();
388 fo->drivetype.destroy();
390 incexe->opts_list.destroy();
391 incexe->name_list.destroy();
392 incexe->plugin_list.destroy();
393 if (incexe->ignoredir) {
394 free(incexe->ignoredir);
397 fileset->include_list.destroy();
399 /* Delete FileSet Exclude lists */
400 for (i=0; i<fileset->exclude_list.size(); i++) {
401 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
402 for (j=0; j<incexe->opts_list.size(); j++) {
403 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
405 fo->regexdir.destroy();
406 fo->regexfile.destroy();
408 fo->wilddir.destroy();
409 fo->wildfile.destroy();
410 fo->wildbase.destroy();
412 fo->fstype.destroy();
413 fo->drivetype.destroy();
415 incexe->opts_list.destroy();
416 incexe->name_list.destroy();
417 incexe->plugin_list.destroy();
418 if (incexe->ignoredir) {
419 free(incexe->ignoredir);
422 fileset->exclude_list.destroy();
426 ff->mount_points.destroy();
427 Dmsg0(100, "Calling term_find_files\n");
428 term_find_files(jcr->ff);
430 Dmsg0(100, "Done with term_find_files\n");
431 pthread_cond_destroy(&jcr->job_start_wait);
432 free_jcr(jcr); /* destroy JCR record */
433 Dmsg0(100, "Done with free_jcr\n");
434 allow_os_suspensions(); /* FD can now be suspended */
436 garbage_collect_memory_pool();
442 * Accept requests from a Director or a Storage daemon
444 void *handle_connection_request(void *caller)
446 BSOCK *bs = (BSOCK *)caller;
448 if (bs->recv() > 0) {
449 if (strncmp(bs->msg, "Ping", 4) == 0) {
450 bs->fsend("2000 Ping OK\n");
454 if (bs->msglen < 25 || bs->msglen > 500) {
457 Dmsg1(100, "Got: %s", bs->msg);
458 if (strncmp(bs->msg, "Hello Director", 14) == 0) {
459 return handle_director_request(bs);
461 if (strncmp(bs->msg, "Hello FD: Bacula Storage", 20) ==0) {
462 return handle_storage_connection(bs);
466 Dmsg2(100, "Bad command from %s. Len=%d.\n", bs->who(), bs->msglen);
468 char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
469 Jmsg2(NULL, M_FATAL, 0, _("Bad command from %s. Len=%d.\n"), who, bs->msglen);
474 static int sm_dump_cmd(JCR *jcr)
477 sm_dump(false, true);
478 jcr->dir_bsock->fsend("2000 sm_dump OK\n");
483 static int exit_cmd(JCR *jcr)
485 jcr->dir_bsock->fsend("2000 exit OK\n");
493 * Hello from Director he must identify himself and provide his
496 static int hello_cmd(JCR *jcr)
498 Dmsg0(120, "Calling Authenticate\n");
499 if (!validate_dir_hello(jcr)) {
502 if (!authenticate_director(jcr)) {
505 Dmsg0(120, "OK Authenticate\n");
506 jcr->authenticated = true;
514 static int cancel_cmd(JCR *jcr)
516 BSOCK *dir = jcr->dir_bsock;
517 char Job[MAX_NAME_LENGTH];
522 if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
523 status = JS_Canceled;
525 } else if (sscanf(dir->msg, "stop Job=%127s", Job) == 1) {
526 status = JS_Incomplete;
529 dir->fsend(_("2902 Error scanning cancel command.\n"));
532 if (!(cjcr=get_jcr_by_full_name(Job))) {
533 dir->fsend(_("2901 Job %s not found.\n"), Job);
535 generate_plugin_event(cjcr, bEventCancelCommand, NULL);
536 cjcr->setJobStatus(status);
537 if (cjcr->store_bsock) {
538 cjcr->store_bsock->set_timed_out();
539 cjcr->store_bsock->set_terminated();
541 cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
543 dir->fsend(_("2001 Job \"%s\" marked to be %s.\n"),
548 dir->signal(BNET_EOD);
553 * Set bandwidth limit as requested by the Director
556 static int setbandwidth_cmd(JCR *jcr)
558 BSOCK *dir = jcr->dir_bsock;
561 char Job[MAX_NAME_LENGTH];
564 if (sscanf(dir->msg, setbandwidth, &bw, Job) != 2 || bw < 0) {
565 pm_strcpy(jcr->errmsg, dir->msg);
566 dir->fsend(_("2991 Bad setbandwidth command: %s\n"), jcr->errmsg);
571 if(!(cjcr=get_jcr_by_full_name(Job))) {
572 dir->fsend(_("2901 Job %s not found.\n"), Job);
574 cjcr->max_bandwidth = bw;
575 if (cjcr->store_bsock) {
576 cjcr->store_bsock->set_bwlimit(bw);
581 } else { /* No job requested, apply globally */
582 me->max_bandwidth_per_job = bw; /* Overwrite directive */
584 cjcr->max_bandwidth = bw;
585 if (cjcr->store_bsock) {
586 cjcr->store_bsock->set_bwlimit(bw);
592 return dir->fsend(OKBandwidth);
596 * Set debug level as requested by the Director
599 static int setdebug_cmd(JCR *jcr)
601 BSOCK *dir = jcr->dir_bsock;
605 int64_t level, level_tags = 0;
610 Dmsg1(50, "setdebug_cmd: %s", dir->msg);
611 tags[0] = options[0] = 0;
612 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld blowup=%ld"
613 " options=%55s tags=%511s",
614 &lvl, &trace, &hangup, &blowup, options, tags);
616 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld",
617 &lvl, &trace, &hangup);
619 Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
620 if (sscanf(dir->msg, "setdebug=%ld trace=%ld", &lvl, &trace) != 2) {
621 pm_strcpy(jcr->errmsg, dir->msg);
622 dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
633 if (!debug_parse_tags(tags, &level_tags)) {
639 debug_level_tags = level_tags;
641 /* handle other options */
642 set_debug_flags(options);
644 Dmsg6(150, "level=%ld trace=%ld hangup=%ld blowup=%d options=%s tags=%s\n",
645 lvl, get_trace(), get_hangup(), get_blowup(), options, tags);
646 return dir->fsend(OKsetdebug, lvl, get_trace(), get_hangup(),
647 get_blowup(), options, tags);
651 static int estimate_cmd(JCR *jcr)
653 BSOCK *dir = jcr->dir_bsock;
654 char ed1[50], ed2[50];
656 if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
657 pm_strcpy(jcr->errmsg, dir->msg);
658 Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
659 dir->fsend(_("2992 Bad estimate command.\n"));
663 dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
664 edit_uint64_with_commas(jcr->JobBytes, ed2));
665 dir->signal(BNET_EOD);
670 * Get JobId and Storage Daemon Authorization key from Director
672 static int job_cmd(JCR *jcr)
674 BSOCK *dir = jcr->dir_bsock;
675 POOL_MEM sd_auth_key(PM_MESSAGE);
676 sd_auth_key.check_size(dir->msglen);
678 if (sscanf(dir->msg, jobcmd, &jcr->JobId, jcr->Job,
679 &jcr->VolSessionId, &jcr->VolSessionTime,
680 sd_auth_key.c_str()) != 5) {
681 pm_strcpy(jcr->errmsg, dir->msg);
682 Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
687 set_storage_auth_key(jcr, sd_auth_key.c_str());
688 Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
689 Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
690 new_plugins(jcr); /* instantiate plugins for this jcr */
691 generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
692 return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
695 extern "C" char *job_code_callback_filed(JCR *jcr, const char* param)
700 return jcr->director->hdr.name;
708 static int runbefore_cmd(JCR *jcr)
711 BSOCK *dir = jcr->dir_bsock;
712 POOLMEM *cmd = get_memory(dir->msglen+1);
715 Dmsg1(100, "runbefore_cmd: %s", dir->msg);
716 if (sscanf(dir->msg, runbefore, cmd) != 1) {
717 pm_strcpy(jcr->errmsg, dir->msg);
718 Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
719 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
725 /* Run the command now */
726 script = new_runscript();
727 script->set_job_code_callback(job_code_callback_filed);
728 script->set_command(cmd);
729 script->when = SCRIPT_Before;
730 ok = script->run(jcr, "ClientRunBeforeJob");
731 free_runscript(script);
735 dir->fsend(OKRunBefore);
738 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
743 static int runbeforenow_cmd(JCR *jcr)
745 BSOCK *dir = jcr->dir_bsock;
747 run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
748 if (job_canceled(jcr)) {
749 dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
750 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
753 dir->fsend(OKRunBeforeNow);
754 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
759 static int runafter_cmd(JCR *jcr)
761 BSOCK *dir = jcr->dir_bsock;
762 POOLMEM *msg = get_memory(dir->msglen+1);
765 Dmsg1(100, "runafter_cmd: %s", dir->msg);
766 if (sscanf(dir->msg, runafter, msg) != 1) {
767 pm_strcpy(jcr->errmsg, dir->msg);
768 Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
769 dir->fsend(_("2905 Bad RunAfterJob command.\n"));
775 cmd = new_runscript();
776 cmd->set_job_code_callback(job_code_callback_filed);
777 cmd->set_command(msg);
778 cmd->on_success = true;
779 cmd->on_failure = false;
780 cmd->when = SCRIPT_After;
782 jcr->RunScripts->append(cmd);
784 free_pool_memory(msg);
785 return dir->fsend(OKRunAfter);
788 static int runscript_cmd(JCR *jcr)
790 BSOCK *dir = jcr->dir_bsock;
791 POOLMEM *msg = get_memory(dir->msglen+1);
792 int on_success, on_failure, fail_on_error;
794 RUNSCRIPT *cmd = new_runscript() ;
795 cmd->set_job_code_callback(job_code_callback_filed);
797 Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
798 /* Note, we cannot sscanf into bools */
799 if (sscanf(dir->msg, runscript, &on_success,
804 pm_strcpy(jcr->errmsg, dir->msg);
805 Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
806 dir->fsend(_("2905 Bad RunScript command.\n"));
811 cmd->on_success = on_success;
812 cmd->on_failure = on_failure;
813 cmd->fail_on_error = fail_on_error;
816 cmd->set_command(msg);
818 jcr->RunScripts->append(cmd);
820 free_pool_memory(msg);
821 return dir->fsend(OKRunScript);
825 * This reads data sent from the Director from the
826 * RestoreObject table that allows us to get objects
827 * that were backed up (VSS .xml data) and are needed
828 * before starting the restore.
830 static int restore_object_cmd(JCR *jcr)
832 BSOCK *dir = jcr->dir_bsock;
834 restore_object_pkt rop;
836 memset(&rop, 0, sizeof(rop));
837 rop.pkt_size = sizeof(rop);
838 rop.pkt_end = sizeof(rop);
840 Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
841 if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
842 Dmsg0(20, "Got endrestoreobject\n");
843 generate_plugin_event(jcr, bEventRestoreObject, NULL);
844 return dir->fsend(OKRestoreObject);
847 rop.plugin_name = (char *)malloc(dir->msglen);
848 *rop.plugin_name = 0;
850 if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len,
851 &rop.object_full_len, &rop.object_index,
852 &rop.object_type, &rop.object_compression, &FileIndex,
853 rop.plugin_name) != 8) {
855 /* Old version, no plugin_name */
856 if (sscanf(dir->msg, restoreobjcmd1, &rop.JobId, &rop.object_len,
857 &rop.object_full_len, &rop.object_index,
858 &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
859 Dmsg0(5, "Bad restore object command\n");
860 pm_strcpy(jcr->errmsg, dir->msg);
861 Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
866 unbash_spaces(rop.plugin_name);
868 Dmsg7(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d "
869 "FI=%d plugin_name=%s\n",
870 rop.JobId, rop.object_len, rop.object_full_len,
871 rop.object_index, rop.object_type, FileIndex, rop.plugin_name);
872 /* Read Object name */
873 if (dir->recv() < 0) {
876 Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
877 rop.object_name = bstrdup(dir->msg);
880 if (dir->recv() < 0) {
883 /* Transfer object from message buffer, and get new message buffer */
884 rop.object = dir->msg;
885 dir->msg = get_pool_memory(PM_MESSAGE);
887 /* If object is compressed, uncompress it */
888 if (rop.object_compression == 1) { /* zlib level 9 */
890 int out_len = rop.object_full_len + 100;
891 POOLMEM *obj = get_memory(out_len);
892 Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
893 stat = Zinflate(rop.object, rop.object_len, obj, out_len);
894 Dmsg1(100, "Zinflate stat=%d\n", stat);
895 if (out_len != rop.object_full_len) {
896 Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
897 rop.object_full_len, out_len, rop.object_name);
899 free_pool_memory(rop.object); /* release compressed object */
900 rop.object = obj; /* new uncompressed object */
901 rop.object_len = out_len;
903 Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
904 /* we still need to do this to detect a vss restore */
905 if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
906 Dmsg0(100, "got job metadata\n");
907 jcr->got_metadata = true;
910 generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
912 if (rop.object_name) {
913 free(rop.object_name);
916 free_pool_memory(rop.object);
918 if (rop.plugin_name) {
919 free(rop.plugin_name);
922 Dmsg1(100, "Send: %s", OKRestoreObject);
926 dir->fsend(_("2909 Bad RestoreObject command.\n"));
932 static bool init_fileset(JCR *jcr)
935 findFILESET *fileset;
944 fileset = (findFILESET *)malloc(sizeof(findFILESET));
945 memset(fileset, 0, sizeof(findFILESET));
946 ff->fileset = fileset;
947 fileset->state = state_none;
948 fileset->include_list.init(1, true);
949 fileset->exclude_list.init(1, true);
954 static void append_file(JCR *jcr, findINCEXE *incexe,
955 const char *buf, bool is_file)
958 incexe->name_list.append(new_dlistString(buf));
960 } else if (me->plugin_directory) {
961 generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
962 incexe->plugin_list.append(new_dlistString(buf));
965 Jmsg(jcr, M_FATAL, 0,
966 _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
972 * Add fname to include/exclude fileset list. First check for
973 * | and < and if necessary perform command.
975 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
977 findFILESET *fileset = jcr->ff->fileset;
990 p++; /* skip over | */
991 fn = get_pool_memory(PM_FNAME);
992 fn = edit_job_codes(jcr, fn, p, "", job_code_callback_filed);
993 bpipe = open_bpipe(fn, 0, "r");
996 Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
998 free_pool_memory(fn);
1001 free_pool_memory(fn);
1002 while (fgets(buf, sizeof(buf), bpipe->rfd)) {
1003 strip_trailing_junk(buf);
1004 append_file(jcr, fileset->incexe, buf, is_file);
1006 if ((stat=close_bpipe(bpipe)) != 0) {
1008 Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
1009 p, be.code(stat), be.bstrerror(stat));
1014 Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
1015 p++; /* skip over < */
1016 if ((ffd = fopen(p, "rb")) == NULL) {
1018 Jmsg(jcr, M_FATAL, 0,
1019 _("Cannot open FileSet input file: %s. ERR=%s\n"),
1023 while (fgets(buf, sizeof(buf), ffd)) {
1024 strip_trailing_junk(buf);
1025 append_file(jcr, fileset->incexe, buf, is_file);
1030 append_file(jcr, fileset->incexe, fname, is_file);
1035 findINCEXE *get_incexe(JCR *jcr)
1037 if (jcr->ff && jcr->ff->fileset) {
1038 return jcr->ff->fileset->incexe;
1043 void set_incexe(JCR *jcr, findINCEXE *incexe)
1045 findFILESET *fileset = jcr->ff->fileset;
1046 fileset->incexe = incexe;
1051 * Define a new Exclude block in the FileSet
1053 findINCEXE *new_exclude(JCR *jcr)
1055 findFILESET *fileset = jcr->ff->fileset;
1058 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1059 memset(fileset->incexe, 0, sizeof(findINCEXE));
1060 fileset->incexe->opts_list.init(1, true);
1061 fileset->incexe->name_list.init();
1062 fileset->incexe->plugin_list.init();
1063 fileset->exclude_list.append(fileset->incexe);
1064 return fileset->incexe;
1068 * Define a new Include block in the FileSet
1070 findINCEXE *new_include(JCR *jcr)
1072 findFILESET *fileset = jcr->ff->fileset;
1075 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1076 memset(fileset->incexe, 0, sizeof(findINCEXE));
1077 fileset->incexe->opts_list.init(1, true);
1078 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1079 fileset->incexe->plugin_list.init();
1080 fileset->include_list.append(fileset->incexe);
1081 return fileset->incexe;
1085 * Define a new preInclude block in the FileSet
1086 * That is the include is prepended to the other
1087 * Includes. This is used for plugin exclusions.
1089 findINCEXE *new_preinclude(JCR *jcr)
1091 findFILESET *fileset = jcr->ff->fileset;
1093 /* New pre-include */
1094 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1095 memset(fileset->incexe, 0, sizeof(findINCEXE));
1096 fileset->incexe->opts_list.init(1, true);
1097 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1098 fileset->incexe->plugin_list.init();
1099 fileset->include_list.prepend(fileset->incexe);
1100 return fileset->incexe;
1103 static findFOPTS *start_options(FF_PKT *ff)
1105 int state = ff->fileset->state;
1106 findINCEXE *incexe = ff->fileset->incexe;
1108 if (state != state_options) {
1109 ff->fileset->state = state_options;
1110 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1111 memset(fo, 0, sizeof(findFOPTS));
1112 fo->regex.init(1, true);
1113 fo->regexdir.init(1, true);
1114 fo->regexfile.init(1, true);
1115 fo->wild.init(1, true);
1116 fo->wilddir.init(1, true);
1117 fo->wildfile.init(1, true);
1118 fo->wildbase.init(1, true);
1119 fo->base.init(1, true);
1120 fo->fstype.init(1, true);
1121 fo->drivetype.init(1, true);
1122 incexe->current_opts = fo;
1123 incexe->opts_list.append(fo);
1125 return incexe->current_opts;
1129 * Used by plugins to define a new options block
1131 void new_options(JCR *jcr, findINCEXE *incexe)
1134 incexe = jcr->ff->fileset->incexe;
1136 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1137 memset(fo, 0, sizeof(findFOPTS));
1138 fo->regex.init(1, true);
1139 fo->regexdir.init(1, true);
1140 fo->regexfile.init(1, true);
1141 fo->wild.init(1, true);
1142 fo->wilddir.init(1, true);
1143 fo->wildfile.init(1, true);
1144 fo->wildbase.init(1, true);
1145 fo->base.init(1, true);
1146 fo->fstype.init(1, true);
1147 fo->drivetype.init(1, true);
1148 incexe->current_opts = fo;
1149 incexe->opts_list.prepend(fo);
1150 jcr->ff->fileset->state = state_options;
1154 * Add a regex to the current fileset
1156 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
1158 findFOPTS *current_opts = start_options(jcr->ff);
1163 preg = (regex_t *)malloc(sizeof(regex_t));
1164 if (current_opts->flags & FO_IGNORECASE) {
1165 rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1167 rc = regcomp(preg, item, REG_EXTENDED);
1170 regerror(rc, preg, prbuf, sizeof(prbuf));
1173 Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1177 current_opts->regex.append(preg);
1178 } else if (type == 'D') {
1179 current_opts->regexdir.append(preg);
1180 } else if (type == 'F') {
1181 current_opts->regexfile.append(preg);
1185 return state_options;
1189 * Add a wild card to the current fileset
1191 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1193 findFOPTS *current_opts = start_options(jcr->ff);
1196 current_opts->wild.append(bstrdup(item));
1197 } else if (type == 'D') {
1198 current_opts->wilddir.append(bstrdup(item));
1199 } else if (type == 'F') {
1200 current_opts->wildfile.append(bstrdup(item));
1201 } else if (type == 'B') {
1202 current_opts->wildbase.append(bstrdup(item));
1206 return state_options;
1211 * Add options to the current fileset
1213 int add_options_to_fileset(JCR *jcr, const char *item)
1215 findFOPTS *current_opts = start_options(jcr->ff);
1217 set_options(current_opts, item);
1218 return state_options;
1221 static void add_fileset(JCR *jcr, const char *item)
1223 FF_PKT *ff = jcr->ff;
1224 findFILESET *fileset = ff->fileset;
1225 int state = fileset->state;
1226 findFOPTS *current_opts;
1228 /* Get code, optional subcode, and position item past the dividing space */
1229 Dmsg1(100, "%s\n", item);
1234 int subcode = ' '; /* A space is always a valid subcode */
1235 if (item[0] != '\0' && item[0] != ' ') {
1243 /* Skip all lines we receive after an error */
1244 if (state == state_error) {
1245 Dmsg0(100, "State=error return\n");
1250 * The switch tests the code for validity.
1251 * The subcode is always good if it is a space, otherwise we must confirm.
1252 * We set state to state_error first assuming the subcode is invalid,
1253 * requiring state to be set in cases below that handle subcodes.
1255 if (subcode != ' ') {
1256 state = state_error;
1257 Dmsg0(100, "Set state=error or double code.\n");
1261 (void)new_include(jcr);
1264 (void)new_exclude(jcr);
1266 case 'N': /* null */
1269 case 'F': /* file = */
1270 /* File item to include or exclude list */
1271 state = state_include;
1272 add_file_to_fileset(jcr, item, true);
1274 case 'P': /* plugin */
1275 /* Plugin item to include list */
1276 state = state_include;
1277 add_file_to_fileset(jcr, item, false);
1279 case 'R': /* regex */
1280 state = add_regex_to_fileset(jcr, item, subcode);
1283 current_opts = start_options(ff);
1284 current_opts->base.append(bstrdup(item));
1285 state = state_options;
1287 case 'X': /* Filetype or Drive type */
1288 current_opts = start_options(ff);
1289 state = state_options;
1290 if (subcode == ' ') {
1291 current_opts->fstype.append(bstrdup(item));
1292 } else if (subcode == 'D') {
1293 current_opts->drivetype.append(bstrdup(item));
1295 state = state_error;
1298 case 'W': /* wild cards */
1299 state = add_wild_to_fileset(jcr, item, subcode);
1301 case 'O': /* Options */
1302 state = add_options_to_fileset(jcr, item);
1304 case 'Z': /* ignore dir */
1305 state = state_include;
1306 fileset->incexe->ignoredir = bstrdup(item);
1309 current_opts = start_options(ff);
1310 // current_opts->reader = bstrdup(item); /* deprecated */
1311 state = state_options;
1314 current_opts = start_options(ff);
1315 // current_opts->writer = bstrdup(item); /* deprecated */
1316 state = state_options;
1318 case 'G': /* Plugin command for this Option block */
1319 current_opts = start_options(ff);
1320 current_opts->plugin = bstrdup(item);
1321 state = state_options;
1324 Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1325 state = state_error;
1328 ff->fileset->state = state;
1331 static bool term_fileset(JCR *jcr)
1333 FF_PKT *ff = jcr->ff;
1335 #ifdef xxx_DEBUG_CODE
1336 findFILESET *fileset = ff->fileset;
1339 for (i=0; i<fileset->include_list.size(); i++) {
1340 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1342 for (j=0; j<incexe->opts_list.size(); j++) {
1343 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1344 for (k=0; k<fo->regex.size(); k++) {
1345 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1347 for (k=0; k<fo->regexdir.size(); k++) {
1348 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1350 for (k=0; k<fo->regexfile.size(); k++) {
1351 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1353 for (k=0; k<fo->wild.size(); k++) {
1354 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1356 for (k=0; k<fo->wilddir.size(); k++) {
1357 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1359 for (k=0; k<fo->wildfile.size(); k++) {
1360 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1362 for (k=0; k<fo->wildbase.size(); k++) {
1363 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1365 for (k=0; k<fo->base.size(); k++) {
1366 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1368 for (k=0; k<fo->fstype.size(); k++) {
1369 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1371 for (k=0; k<fo->drivetype.size(); k++) {
1372 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1375 if (incexe->ignoredir) {
1376 Dmsg1(400, "Z %s\n", incexe->ignoredir);
1379 foreach_dlist(node, &incexe->name_list) {
1380 Dmsg1(400, "F %s\n", node->c_str());
1382 foreach_dlist(node, &incexe->plugin_list) {
1383 Dmsg1(400, "P %s\n", node->c_str());
1386 for (i=0; i<fileset->exclude_list.size(); i++) {
1387 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1389 for (j=0; j<incexe->opts_list.size(); j++) {
1390 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1391 for (k=0; k<fo->regex.size(); k++) {
1392 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1394 for (k=0; k<fo->regexdir.size(); k++) {
1395 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1397 for (k=0; k<fo->regexfile.size(); k++) {
1398 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1400 for (k=0; k<fo->wild.size(); k++) {
1401 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1403 for (k=0; k<fo->wilddir.size(); k++) {
1404 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1406 for (k=0; k<fo->wildfile.size(); k++) {
1407 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1409 for (k=0; k<fo->wildbase.size(); k++) {
1410 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1412 for (k=0; k<fo->base.size(); k++) {
1413 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1415 for (k=0; k<fo->fstype.size(); k++) {
1416 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1418 for (k=0; k<fo->drivetype.size(); k++) {
1419 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1423 foreach_dlist(node, &incexe->name_list) {
1424 Dmsg1(400, "F %s\n", node->c_str());
1426 foreach_dlist(node, &incexe->plugin_list) {
1427 Dmsg1(400, "P %s\n", node->c_str());
1431 return ff->fileset->state != state_error;
1436 * As an optimization, we should do this during
1437 * "compile" time in filed/job.c, and keep only a bit mask
1438 * and the Verify options.
1440 static int set_options(findFOPTS *fo, const char *opts)
1446 // Commented out as it is not backward compatible - KES
1448 for (p=opts; *p; p++) {
1450 case 'a': /* alway replace */
1451 case '0': /* no option */
1454 fo->flags |= FO_EXCLUDE;
1457 fo->flags |= FO_MULTIFS;
1459 case 'h': /* no recursion */
1460 fo->flags |= FO_NO_RECURSION;
1462 case 'H': /* no hard link handling */
1463 fo->flags |= FO_NO_HARDLINK;
1466 fo->flags |= FO_IGNORECASE;
1469 fo->flags |= FO_MD5;
1472 fo->flags |= FO_NOREPLACE;
1474 case 'p': /* use portable data format */
1475 fo->flags |= FO_PORTABLE;
1477 case 'R': /* Resource forks and Finder Info */
1478 fo->flags |= FO_HFSPLUS;
1480 case 'r': /* read fifo */
1481 fo->flags |= FO_READFIFO;
1486 fo->flags |= FO_SHA1;
1491 fo->flags |= FO_SHA256;
1495 fo->flags |= FO_SHA512;
1501 * If 2 or 3 is seen here, SHA2 is not configured, so
1502 * eat the option, and drop back to SHA-1.
1504 if (p[1] == '2' || p[1] == '3') {
1507 fo->flags |= FO_SHA1;
1512 fo->flags |= FO_SPARSE;
1515 fo->flags |= FO_MTIMEONLY;
1518 fo->flags |= FO_KEEPATIME;
1521 fo->flags |= FO_ACL;
1523 case 'V': /* verify options */
1524 /* Copy Verify Options */
1525 for (j=0; *p && *p != ':'; p++) {
1526 fo->VerifyOpts[j] = *p;
1527 if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1531 fo->VerifyOpts[j] = 0;
1533 case 'C': /* accurate options */
1534 /* Copy Accurate Options */
1535 for (j=0; *p && *p != ':'; p++) {
1536 fo->AccurateOpts[j] = *p;
1537 if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1541 fo->AccurateOpts[j] = 0;
1543 case 'J': /* Basejob options */
1544 /* Copy BaseJob Options */
1545 for (j=0; *p && *p != ':'; p++) {
1546 fo->BaseJobOpts[j] = *p;
1547 if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1551 fo->BaseJobOpts[j] = 0;
1553 case 'P': /* strip path */
1556 for (j=0; *p && *p != ':'; p++) {
1558 if (j < (int)sizeof(strip) - 1) {
1563 fo->strip_path = atoi(strip);
1564 fo->flags |= FO_STRIPPATH;
1565 Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1568 fo->flags |= FO_IF_NEWER;
1571 fo->flags |= FO_ENHANCEDWILD;
1573 case 'Z': /* compression */
1575 if (*p >= '0' && *p <= '9') {
1576 fo->flags |= FO_COMPRESS;
1577 fo->Compress_algo = COMPRESS_GZIP;
1578 fo->Compress_level = *p - '0';
1580 else if (*p == 'o') {
1581 fo->flags |= FO_COMPRESS;
1582 fo->Compress_algo = COMPRESS_LZO1X;
1583 fo->Compress_level = 1; /* not used with LZO */
1587 fo->flags |= FO_NOATIME;
1590 fo->flags |= FO_CHKCHANGES;
1593 fo->flags |= FO_HONOR_NODUMP;
1596 fo->flags |= FO_XATTR;
1599 Jmsg1(NULL, M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1603 return state_options;
1608 * Director is passing his Fileset
1610 static int fileset_cmd(JCR *jcr)
1612 POOL_MEM buf(PM_MESSAGE);
1613 BSOCK *dir = jcr->dir_bsock;
1616 jcr->Snapshot = (strstr(dir->msg, "snap=1") != NULL);
1617 if (!init_fileset(jcr)) {
1620 while (dir->recv() >= 0) {
1621 strip_trailing_junk(dir->msg);
1622 Dmsg1(500, "Fileset: %s\n", dir->msg);
1623 pm_strcpy(buf, dir->msg);
1624 add_fileset(jcr, buf.c_str());
1626 if (!term_fileset(jcr)) {
1629 rtnstat = dir->fsend(OKinc);
1630 generate_plugin_event(jcr, bEventEndFileSet);
1636 * The Director sends us the component info file, which
1637 * we will in turn pass to the VSS plugin.
1639 static int component_cmd(JCR *jcr)
1641 BSOCK *dir = jcr->dir_bsock;
1643 while (dir->recv() >= 0) {
1644 Dmsg1(200, "filed<dird: component: %s", dir->msg);
1645 generate_plugin_event(jcr, bEventComponentInfo, (void *)dir->msg);
1647 return dir->fsend(OKComponentInfo);
1652 * Get backup level from Director
1654 * Note: there are odd things such as accurate_differential,
1655 * and accurate_incremental that are passed in level, thus
1656 * the calls to strstr() below.
1659 static int level_cmd(JCR *jcr)
1661 BSOCK *dir = jcr->dir_bsock;
1662 POOLMEM *level, *buf = NULL;
1665 level = get_memory(dir->msglen+1);
1666 Dmsg1(10, "level_cmd: %s", dir->msg);
1668 /* keep compatibility with older directors */
1669 if (strstr(dir->msg, "accurate")) {
1670 jcr->accurate = true;
1672 if (strstr(dir->msg, "rerunning")) {
1673 jcr->rerunning = true;
1675 if (sscanf(dir->msg, "level = %s ", level) != 1) {
1678 /* Base backup requested? */
1679 if (strcasecmp(level, "base") == 0) {
1680 jcr->setJobLevel(L_BASE);
1681 /* Full backup requested? */
1682 } else if (strcasecmp(level, "full") == 0) {
1683 jcr->setJobLevel(L_FULL);
1684 } else if (strstr(level, "differential")) {
1685 jcr->setJobLevel(L_DIFFERENTIAL);
1688 } else if (strstr(level, "incremental")) {
1689 jcr->setJobLevel(L_INCREMENTAL);
1693 * We get his UTC since time, then sync the clocks and correct it
1694 * to agree with our clock.
1696 } else if (strcasecmp(level, "since_utime") == 0) {
1697 buf = get_memory(dir->msglen+1);
1698 utime_t since_time, adj;
1699 btime_t his_time, bt_start, rt=0, bt_adj=0, his_time_prev=0, n=0;
1700 if (jcr->getJobLevel() == L_NONE) {
1701 jcr->setJobLevel(L_SINCE); /* if no other job level set, do it now */
1703 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d prev_job=%127s",
1704 buf, &mtime_only, jcr->PrevJob) != 3) {
1705 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1706 buf, &mtime_only) != 2) {
1710 since_time = str_to_uint64(buf); /* this is the since time */
1711 Dmsg2(100, "since_time=%lld prev_job=%s\n", since_time, jcr->PrevJob);
1712 char ed1[50], ed2[50];
1714 * Sync clocks by polling him for the time. We take
1715 * 10 samples of his time throwing out the first two.
1717 for (int i=0; i<10; i++) {
1718 bt_start = get_current_btime();
1719 dir->signal(BNET_BTIME); /* poll for time */
1720 if (dir->recv() <= 0) { /* get response */
1723 if (sscanf(dir->msg, "btime %s", buf) != 1) {
1726 his_time = str_to_uint64(buf);
1727 rt = get_current_btime() - bt_start; /* compute round trip time */
1728 /* skip first two results and check for leap second */
1729 /* if any of the FD or DIR went back in time, skip this iteration */
1730 if (i < 2 || (his_time_prev > 0 && his_time < his_time_prev) || rt<0) {
1731 his_time_prev = his_time;
1734 his_time_prev = his_time;
1736 Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1737 edit_uint64(bt_start, ed2));
1738 bt_adj += bt_start - his_time - rt/2;
1739 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1742 if (n > 0) { /* Should be 1 in the worst case */
1743 bt_adj = bt_adj / n; /* compute average time */
1744 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1745 adj = btime_to_utime(bt_adj);
1746 since_time += adj; /* adjust for clock difference */
1748 /* Don't notify if time within 3 seconds */
1749 if (adj > 3 || adj < -3) {
1751 if (adj > 600 || adj < -600) {
1756 Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1758 dir->signal(BNET_EOD);
1760 Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1761 jcr->incremental = 1; /* set incremental or decremental backup */
1762 jcr->mtime = since_time; /* set since time */
1763 generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1765 Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1773 generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1774 return dir->fsend(OKlevel);
1777 pm_strcpy(jcr->errmsg, dir->msg);
1778 Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1787 * Get session parameters from Director -- this is for a Restore command
1788 * This is deprecated. It is now passed via the bsr.
1790 static int session_cmd(JCR *jcr)
1792 BSOCK *dir = jcr->dir_bsock;
1794 Dmsg1(100, "SessionCmd: %s", dir->msg);
1795 if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1796 &jcr->VolSessionId, &jcr->VolSessionTime,
1797 &jcr->StartFile, &jcr->EndFile,
1798 &jcr->StartBlock, &jcr->EndBlock) != 7) {
1799 pm_strcpy(jcr->errmsg, dir->msg);
1800 Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1804 return dir->fsend(OKsession);
1807 static void set_storage_auth_key(JCR *jcr, char *key)
1809 /* if no key don't update anything */
1815 * We can be contacting multiple storage daemons.
1816 * So, make sure that any old jcr->store_bsock is cleaned up.
1818 free_bsock(jcr->store_bsock);
1821 * We can be contacting multiple storage daemons.
1822 * So, make sure that any old jcr->sd_auth_key is cleaned up.
1824 if (jcr->sd_auth_key) {
1826 * If we already have a Authorization key, director can do multi
1829 Dmsg0(5, "set multi_restore=true\n");
1830 jcr->multi_restore = true;
1831 bfree(jcr->sd_auth_key);
1834 jcr->sd_auth_key = bstrdup(key);
1835 Dmsg1(5, "set sd auth key %s\n", jcr->sd_auth_key);
1839 * Get address of storage daemon from Director
1842 static int storage_cmd(JCR *jcr)
1844 int stored_port = 0; /* storage daemon port */
1845 int enable_ssl; /* enable ssl to sd */
1846 POOL_MEM sd_auth_key(PM_MESSAGE);
1847 BSOCK *dir = jcr->dir_bsock;
1850 Dmsg1(100, "StorageCmd: %s", dir->msg);
1851 sd_auth_key.check_size(dir->msglen);
1852 if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port,
1853 &enable_ssl, sd_auth_key.c_str()) == 4) {
1854 Dmsg1(100, "Set auth key %s\n", sd_auth_key.c_str());
1855 set_storage_auth_key(jcr, sd_auth_key.c_str());
1856 } else if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
1857 &stored_port, &enable_ssl) != 3) {
1858 pm_strcpy(jcr->errmsg, dir->msg);
1859 Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1860 Pmsg1(010, "Bad storage command: %s", jcr->errmsg);
1865 /* TODO: see if we put limit on restore and backup... */
1866 if (!jcr->max_bandwidth) {
1867 if (jcr->director->max_bandwidth_per_job) {
1868 jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
1870 } else if (me->max_bandwidth_per_job) {
1871 jcr->max_bandwidth = me->max_bandwidth_per_job;
1875 if (stored_port != 0) { /* We are doing the connecting */
1876 Dmsg3(110, "Connect to storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port,
1878 jcr->sd_calls_client = false;
1880 /* Open command communications with Storage daemon */
1881 /* Try to connect for 1 hour at 10 second intervals */
1882 sd->set_source_address(me->FDsrc_addr);
1883 if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1884 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1885 /* destroy() OK because sd is local */
1887 Jmsg2(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1888 jcr->stored_addr, stored_port);
1889 Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1890 jcr->stored_addr, stored_port);
1894 Dmsg0(110, "Connection OK to SD.\n");
1895 jcr->store_bsock = sd;
1896 } else { /* The storage daemon called us */
1899 struct timespec timeout;
1902 free_bsock(jcr->store_bsock);
1903 jcr->sd_calls_client = true;
1906 * Wait for the Storage daemon to contact us to start the Job,
1907 * when he does, we will be released, unless the 30 minutes
1910 gettimeofday(&tv, &tz);
1911 timeout.tv_nsec = tv.tv_usec * 1000;
1912 timeout.tv_sec = tv.tv_sec + 30 * 60; /* wait 30 minutes */
1914 while (jcr->sd_calls_client_bsock == NULL && !jcr->is_job_canceled()) {
1915 errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
1916 if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
1919 Dmsg1(800, "=== Auth cond errstat=%d\n", errstat);
1922 Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr);
1924 /* We should already have a storage connection! */
1925 if (jcr->sd_calls_client_bsock == NULL) {
1926 Pmsg0(000, "Failed connect from Storage daemon. SD bsock=NULL.\n");
1927 Pmsg1(000, "Storagecmd: %s", dir->msg);
1928 Jmsg0(jcr, M_FATAL, 0, _("Failed connect from Storage daemon. SD bsock=NULL.\n"));
1931 if (jcr->is_job_canceled()) {
1934 /* Assign the new socket to the main one */
1936 jcr->store_bsock = jcr->sd_calls_client_bsock;
1937 jcr->sd_calls_client_bsock = NULL;
1940 jcr->store_bsock->set_bwlimit(jcr->max_bandwidth);
1942 if (!send_hello_sd(jcr, jcr->Job)) {
1946 if (!authenticate_storagedaemon(jcr)) {
1949 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
1950 Dmsg0(110, "Authenticated with SD.\n");
1952 /* Send OK to Director */
1953 return dir->fsend(OKstore);
1956 dir->fsend(BADcmd, "storage");
1964 static int backup_cmd(JCR *jcr)
1966 BSOCK *dir = jcr->dir_bsock;
1967 BSOCK *sd = jcr->store_bsock;
1972 if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1973 jcr->JobFiles = FileIndex;
1974 Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1978 * If explicitly requesting FO_ACL or FO_XATTR, fail job if it
1979 * is not available on Client machine
1981 if (jcr->ff->flags & FO_ACL && !(have_acl||have_win32)) {
1982 Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for Client.\n"));
1985 if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1986 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for Client.\n"));
1989 jcr->setJobStatus(JS_Blocked);
1990 jcr->setJobType(JT_BACKUP);
1991 Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1993 Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1994 dir->fsend(BADcmd, "backup");
1998 dir->fsend(OKbackup);
1999 Dmsg1(110, "filed>dird: %s", dir->msg);
2002 * Send Append Open Session to Storage daemon
2004 sd->fsend(append_open);
2005 Dmsg1(110, ">stored: %s", sd->msg);
2007 * Expect to receive back the Ticket number
2009 if (bget_msg(sd) >= 0) {
2010 Dmsg1(110, "<stored: %s", sd->msg);
2011 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2012 Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
2015 Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
2017 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
2022 * Send Append data command to Storage daemon
2024 sd->fsend(append_data, jcr->Ticket);
2025 Dmsg1(110, ">stored: %s", sd->msg);
2028 * Expect to get OK data
2030 Dmsg1(110, "<stored: %s", sd->msg);
2031 if (!response(jcr, sd, OK_data, "Append Data")) {
2035 generate_daemon_event(jcr, "JobStart");
2036 generate_plugin_event(jcr, bEventStartBackupJob);
2038 if (jcr->Snapshot) {
2039 Dmsg0(10, "Open a snapshot session\n");
2040 /* TODO: See if we abort the job */
2041 jcr->Snapshot = open_snapshot_backup_session(jcr);
2043 /* Call RunScript just after the Snapshot creation, usually, we restart services */
2044 run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2048 * Send Files to Storage daemon
2050 Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
2051 if (!blast_data_to_storage_daemon(jcr, NULL)) {
2052 jcr->setJobStatus(JS_ErrorTerminated);
2053 sd->suppress_error_messages(true);
2054 Dmsg0(110, "Error in blast_data.\n");
2056 jcr->setJobStatus(JS_Terminated);
2057 /* Note, the above set status will not override an error */
2058 if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
2059 sd->suppress_error_messages(true);
2060 goto cleanup; /* bail out now */
2063 * Expect to get response to append_data from Storage daemon
2065 if (!response(jcr, sd, OK_append, "Append Data")) {
2066 jcr->setJobStatus(JS_ErrorTerminated);
2071 * Send Append End Data to Storage daemon
2073 sd->fsend(append_end, jcr->Ticket);
2075 if (!response(jcr, sd, OK_end, "Append End")) {
2076 jcr->setJobStatus(JS_ErrorTerminated);
2081 * Send Append Close to Storage daemon
2083 sd->fsend(append_close, jcr->Ticket);
2085 while (bget_msg(sd) >= 0) { /* stop on signal or error */
2086 if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
2088 Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
2090 Dmsg1(100, "append_close: scan fail from %s\n", sd->msg);
2094 Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
2095 Dmsg1(100, "append_close: scan fail from %s\n", sd->msg);
2098 if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings ||
2099 SDJobStatus == JS_Incomplete)) {
2100 Jmsg(jcr, M_FATAL, 0, _("Bad status %d %c returned from Storage Daemon.\n"),
2101 SDJobStatus, (char)SDJobStatus);
2107 generate_plugin_event(jcr, bEventEndBackupJob);
2108 return 0; /* return and stop command loop */
2112 * Do a Verify for Director
2115 static int verify_cmd(JCR *jcr)
2117 BSOCK *dir = jcr->dir_bsock;
2118 BSOCK *sd = jcr->store_bsock;
2121 jcr->setJobType(JT_VERIFY);
2122 if (sscanf(dir->msg, verifycmd, level) != 1) {
2123 dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2127 if (strcasecmp(level, "init") == 0) {
2128 jcr->setJobLevel(L_VERIFY_INIT);
2129 } else if (strcasecmp(level, "catalog") == 0){
2130 jcr->setJobLevel(L_VERIFY_CATALOG);
2131 } else if (strcasecmp(level, "volume") == 0){
2132 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
2133 } else if (strcasecmp(level, "data") == 0){
2134 jcr->setJobLevel(L_VERIFY_DATA);
2135 } else if (strcasecmp(level, "disk_to_catalog") == 0) {
2136 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2138 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2142 dir->fsend(OKverify);
2144 generate_daemon_event(jcr, "JobStart");
2145 generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2146 generate_plugin_event(jcr, bEventStartVerifyJob);
2148 Dmsg1(110, "filed>dird: %s", dir->msg);
2150 switch (jcr->getJobLevel()) {
2152 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));