2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 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
30 bool win32decomp = false;
31 bool no_win32_write_errors = false;
33 /* Static variables */
34 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
37 const bool have_acl = true;
39 const bool have_acl = false;
43 const bool have_xattr = true;
45 const bool have_xattr = false;
48 extern CLIENT *me; /* our client resource */
50 /* Imported functions */
51 extern int status_cmd(JCR *jcr);
52 extern int qstatus_cmd(JCR *jcr);
53 extern int accurate_cmd(JCR *jcr);
55 /* Forward referenced functions */
56 static int backup_cmd(JCR *jcr);
57 static int component_cmd(JCR *jcr);
58 static int cancel_cmd(JCR *jcr);
59 static int setdebug_cmd(JCR *jcr);
60 static int setbandwidth_cmd(JCR *jcr);
61 static int estimate_cmd(JCR *jcr);
62 static int hello_cmd(JCR *jcr);
63 static int job_cmd(JCR *jcr);
64 static int fileset_cmd(JCR *jcr);
65 static int level_cmd(JCR *jcr);
66 static int verify_cmd(JCR *jcr);
67 static int restore_cmd(JCR *jcr);
68 static int end_restore_cmd(JCR *jcr);
69 static int storage_cmd(JCR *jcr);
70 static int session_cmd(JCR *jcr);
71 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
72 static void filed_free_jcr(JCR *jcr);
73 static int open_sd_read_session(JCR *jcr);
74 static int runscript_cmd(JCR *jcr);
75 static int runbefore_cmd(JCR *jcr);
76 static int runafter_cmd(JCR *jcr);
77 static int runbeforenow_cmd(JCR *jcr);
78 static int restore_object_cmd(JCR *jcr);
79 static int set_options(findFOPTS *fo, const char *opts);
80 static void set_storage_auth_key(JCR *jcr, char *key);
81 static int sm_dump_cmd(JCR *jcr);
82 static int proxy_cmd(JCR *jcr);
83 static int fd_testnetwork_cmd(JCR *jcr);
85 static int exit_cmd(JCR *jcr);
88 /* Exported functions */
90 #define ACCESS_MONITOR 1
91 #define ACCESS_REMOTE 2
94 * The following are the recognized commands from the Director.
96 struct s_cmds cmds[] = {
97 {"backup", backup_cmd, 0},
98 {"cancel", cancel_cmd, ACCESS_REMOTE},
99 {"setdebug=", setdebug_cmd, 0},
100 {"setbandwidth=",setbandwidth_cmd, ACCESS_REMOTE},
101 {"snapshot", snapshot_cmd, 0},
102 {"estimate", estimate_cmd, 0},
103 {"Hello", hello_cmd, 1},
104 {"fileset", fileset_cmd, 0},
105 {"JobId=", job_cmd, 0},
106 {"level = ", level_cmd, 0},
107 {"restore ", restore_cmd, 0},
108 {"endrestore", end_restore_cmd, 0},
109 {"session", session_cmd, 0},
110 {"status", status_cmd, ACCESS_MONITOR|ACCESS_REMOTE},
111 {".status", qstatus_cmd, ACCESS_MONITOR|ACCESS_REMOTE},
112 {"storage ", storage_cmd, 0},
113 {"verify", verify_cmd, 0},
114 {"component", component_cmd, 0},
115 {"RunBeforeNow", runbeforenow_cmd, 0},
116 {"RunBeforeJob", runbefore_cmd, 0},
117 {"RunAfterJob", runafter_cmd, 0},
118 {"Run", runscript_cmd, 0},
119 {"accurate", accurate_cmd, 0},
120 {"restoreobject", restore_object_cmd, 0},
121 {"sm_dump", sm_dump_cmd, 0},
122 {"stop", cancel_cmd, ACCESS_REMOTE},
123 {"proxy", proxy_cmd, ACCESS_REMOTE},
124 {"testnetwork", fd_testnetwork_cmd, 0},
126 {"exit", exit_cmd, 0},
128 {NULL, NULL} /* list terminator */
131 /* Commands received from director that need scanning */
132 static char jobcmd[] = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
133 static char storaddr[] = "storage address=%s port=%d ssl=%d Authorization=%100s";
134 static char storaddr_v1[] = "storage address=%s port=%d ssl=%d";
135 static char sessioncmd[] = "session %127s %ld %ld %ld %ld %ld %ld\n";
137 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
138 static char restorefcmd1[] = "restore files=%d replace=%c prelinks=%d where=\n";
140 /* The following restore commands may have a big where=/regexwhere= parameter
141 * the bsscanf is limiting the default %s to 1000c. To allow more than 1000 bytes,
142 * we can specify %xxxxs where xxxx is the size expected in bytes.
144 * So, the code will add %s\n to the end of the following restore commands
146 static char restorecmd[] = "restore replace=%c prelinks=%d where=";
147 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=";
148 static char restorefcmd[] = "restore files=%d replace=%c prelinks=%d where=";
149 static char restorefcmdR[] = "restore files=%d replace=%c prelinks=%d regexwhere=";
151 static char restoreobjcmd[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d,%s";
152 static char restoreobjcmd1[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
153 static char endrestoreobjectcmd[] = "restoreobject end\n";
154 static char verifycmd[] = "verify level=%30s";
155 static char estimatecmd[] = "estimate listing=%d";
156 static char runbefore[] = "RunBeforeJob %s";
157 static char runafter[] = "RunAfterJob %s";
158 static char runscript[] = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
159 static char setbandwidth[]= "setbandwidth=%lld Job=%127s";
161 /* Responses sent to Director */
162 static char errmsg[] = "2999 Invalid command\n";
163 static char no_auth[] = "2998 No Authorization\n";
164 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
165 static char OKBandwidth[] = "2000 OK Bandwidth\n";
166 static char OKinc[] = "2000 OK include\n";
167 static char OKest[] = "2000 OK estimate files=%s bytes=%s\n";
168 static char OKlevel[] = "2000 OK level\n";
169 static char OKbackup[] = "2000 OK backup\n";
170 static char OKverify[] = "2000 OK verify\n";
171 static char OKrestore[] = "2000 OK restore\n";
172 static char OKsession[] = "2000 OK session\n";
173 static char OKstore[] = "2000 OK storage\n";
174 static char OKstoreend[] = "2000 OK storage end\n";
175 static char OKjob[] = "2000 OK Job %s (%s) %s,%s,%s";
176 static char OKsetdebug[] = "2000 OK setdebug=%ld trace=%ld hangup=%ld"
177 " blowup=%ld options=%s tags=%s\n";
178 static char BADjob[] = "2901 Bad Job\n";
179 static char EndJob[] = "2800 End Job TermCode=%d JobFiles=%d ReadBytes=%lld"
180 " JobBytes=%lld Errors=%d VSS=%d Encrypt=%d"
181 " CommBytes=%lld CompressCommBytes=%lld\n";
182 static char OKRunBefore[] = "2000 OK RunBefore\n";
183 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
184 static char OKRunAfter[] = "2000 OK RunAfter\n";
185 static char OKRunScript[] = "2000 OK RunScript\n";
186 static char BADcmd[] = "2902 Bad %s\n";
187 static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
188 static char OKComponentInfo[] = "2000 OK ComponentInfo\n";
191 /* Responses received from Storage Daemon */
192 static char OK_end[] = "3000 OK end\n";
193 static char OK_close[] = "3000 OK close Status = %d\n";
194 static char OK_open[] = "3000 OK open ticket = %d\n";
195 static char OK_data[] = "3000 OK data\n";
196 static char OK_append[] = "3000 OK append data\n";
199 /* Commands sent to Storage Daemon */
200 static char append_open[] = "append open session\n";
201 static char append_data[] = "append data %d\n";
202 static char append_end[] = "append end session %d\n";
203 static char append_close[] = "append close session %d\n";
204 static char read_open[] = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
205 static char read_data[] = "read data %d\n";
206 static char read_close[] = "read close session %d\n";
207 static char read_ctrl[] = "read control %d\n";
209 /* Should tell us if a command is authorized or not */
210 static bool access_ok(struct s_cmds *cmd, DIRRES* dir)
212 if ((cmd->access & ACCESS_MONITOR) && dir->monitor) {
215 if ((cmd->access & ACCESS_REMOTE) && dir->remote) {
218 if (!dir->remote && !dir->monitor) {
225 * Accept requests from a Director
227 * NOTE! We are running as a separate thread
229 * Send output one line
230 * at a time followed by a zero length transmission.
232 * Return when the connection is terminated or there
235 * Basic task here is:
236 * Authenticate Director (during Hello command).
237 * Accept commands one at a time from the Director
240 * Concerning ClientRunBefore/After, the sequence of events
241 * is rather critical. If they are not done in the right
242 * order one can easily get FD->SD timeouts if the script
245 * The current sequence of events is:
246 * 1. Dir starts job with FD
247 * 2. Dir connects to SD
248 * 3. Dir connects to FD
249 * 4. FD connects to SD
250 * 5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
251 * 6. Dir sends include/exclude
252 * 7. FD sends the file data to SD
253 * 8. SD/FD disconnects while the SD despools data and attributes (optional)
254 * 9. FD runs ClientRunAfterJob
257 static void *handle_director_request(BSOCK *dir)
263 const char jobname[12] = "*Director*";
265 prevent_os_suspensions(); /* do not suspend during backup/restore */
266 jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
267 jcr->sd_calls_client_bsock = NULL;
268 jcr->sd_calls_client = false;
269 jcr->dir_bsock = dir;
270 jcr->ff = init_find_files();
271 jcr->start_time = time(NULL);
272 jcr->RunScripts = New(alist(10, not_owned_by_alist));
273 jcr->last_fname = get_pool_memory(PM_FNAME);
274 jcr->last_fname[0] = 0;
275 jcr->client_name = get_memory(strlen(my_name) + 1);
276 pm_strcpy(jcr->client_name, my_name);
277 bstrncpy(jcr->Job, jobname, sizeof(jobname)); /* dummy */
278 jcr->crypto.pki_sign = me->pki_sign;
279 jcr->crypto.pki_encrypt = me->pki_encrypt;
280 jcr->crypto.pki_keypair = me->pki_keypair;
281 jcr->crypto.pki_signers = me->pki_signers;
282 jcr->crypto.pki_recipients = me->pki_recipients;
285 /* Initialize SD start condition variable */
286 int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
289 Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat));
292 enable_backup_privileges(NULL, 1 /* ignore_errors */);
294 for (quit=false; !quit;) {
295 if (!first) { /* first call the read is done */
297 if (dir->recv() < 0) {
298 break; /* connection terminated */
301 if (dir->msglen == 0) { /* Bad connection */
305 dir->msg[dir->msglen] = 0;
306 Dmsg1(100, "<dird: %s", dir->msg);
308 for (i=0; cmds[i].cmd; i++) {
309 if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
310 found = true; /* indicate command found */
311 if (!jcr->authenticated && cmds[i].func != hello_cmd) {
313 dir->signal(BNET_EOD);
316 if (jcr->authenticated && !access_ok(&cmds[i], jcr->director)) {
317 Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
318 dir->fsend(invalid_cmd);
319 dir->signal(BNET_EOD);
322 if ((me->disabled_cmds_array && me->disabled_cmds_array[i]) ||
323 (jcr->director && jcr->director->disabled_cmds_array &&
324 jcr->director->disabled_cmds_array[i])) {
325 Jmsg(jcr, M_FATAL, 0, _("Command: \"%s\" is disabled.\n"), cmds[i].cmd);
329 Dmsg1(100, "Executing Dir %s command.\n", dir->msg);
330 if (!cmds[i].func(jcr)) { /* do command */
331 quit = true; /* error or fully terminated, get out */
332 Dmsg1(100, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
337 if (!found) { /* command not found */
344 /* Inform Storage daemon that we are done */
345 if (jcr->store_bsock) {
346 jcr->store_bsock->signal(BNET_TERMINATE);
349 /* Run the after job */
350 run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
352 /* send any queued messages before reporting the jobstatus to the director */
353 dequeue_messages(jcr);
355 if (jcr->JobId) { /* send EndJob if running a job */
356 uint64_t CommBytes, CommCompressedBytes;
357 uint32_t vss, encrypt;
358 /* Send termination status back to Dir */
359 if (jcr->store_bsock) {
360 CommBytes = jcr->store_bsock->CommBytes();
361 CommCompressedBytes = jcr->store_bsock->CommCompressedBytes();
363 CommBytes = CommCompressedBytes = 0;
365 encrypt = jcr->crypto.pki_encrypt;
367 dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles,
368 jcr->ReadBytes, jcr->JobBytes, jcr->JobErrors, vss,
369 encrypt, CommBytes, CommCompressedBytes);
370 //Dmsg0(0, dir->msg);
373 generate_daemon_event(jcr, "JobEnd");
374 generate_plugin_event(jcr, bEventJobEnd);
377 dequeue_messages(jcr); /* send any queued messages, will no longer impact
378 * the job status... */
380 /* Inform Director that we are done */
381 dir->signal(BNET_TERMINATE);
383 free_and_null_pool_memory(jcr->job_metadata);
385 /* Clean up fileset */
386 FF_PKT *ff = jcr->ff;
387 findFILESET *fileset = ff->fileset;
390 /* Delete FileSet Include lists */
391 for (i=0; i<fileset->include_list.size(); i++) {
392 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
393 for (j=0; j<incexe->opts_list.size(); j++) {
394 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
398 for (k=0; k<fo->regex.size(); k++) {
399 regfree((regex_t *)fo->regex.get(k));
401 for (k=0; k<fo->regexdir.size(); k++) {
402 regfree((regex_t *)fo->regexdir.get(k));
404 for (k=0; k<fo->regexfile.size(); k++) {
405 regfree((regex_t *)fo->regexfile.get(k));
408 fo->regexdir.destroy();
409 fo->regexfile.destroy();
411 fo->wilddir.destroy();
412 fo->wildfile.destroy();
413 fo->wildbase.destroy();
415 fo->fstype.destroy();
416 fo->drivetype.destroy();
418 incexe->opts_list.destroy();
419 incexe->name_list.destroy();
420 incexe->plugin_list.destroy();
421 if (incexe->ignoredir) {
422 free(incexe->ignoredir);
425 fileset->include_list.destroy();
427 /* Delete FileSet Exclude lists */
428 for (i=0; i<fileset->exclude_list.size(); i++) {
429 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
430 for (j=0; j<incexe->opts_list.size(); j++) {
431 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
433 fo->regexdir.destroy();
434 fo->regexfile.destroy();
436 fo->wilddir.destroy();
437 fo->wildfile.destroy();
438 fo->wildbase.destroy();
440 fo->fstype.destroy();
441 fo->drivetype.destroy();
443 incexe->opts_list.destroy();
444 incexe->name_list.destroy();
445 incexe->plugin_list.destroy();
446 if (incexe->ignoredir) {
447 free(incexe->ignoredir);
450 fileset->exclude_list.destroy();
454 ff->mount_points.destroy();
455 Dmsg0(100, "Calling term_find_files\n");
456 term_find_files(jcr->ff);
458 Dmsg0(100, "Done with term_find_files\n");
459 pthread_cond_destroy(&jcr->job_start_wait);
460 free_jcr(jcr); /* destroy JCR record */
461 Dmsg0(100, "Done with free_jcr\n");
462 allow_os_suspensions(); /* FD can now be suspended */
464 garbage_collect_memory_pool();
470 * Accept requests from a Director or a Storage daemon
472 void *handle_connection_request(void *caller)
474 BSOCK *bs = (BSOCK *)caller;
476 if (bs->recv() > 0) {
477 if (strncmp(bs->msg, "Ping", 4) == 0) {
478 bs->fsend("2000 Ping OK\n");
482 if (bs->msglen < 25 || bs->msglen > 500) {
485 if (strncmp(bs->msg, "Hello FD: Bacula Storage", 20) ==0) {
486 return handle_storage_connection(bs);
488 if (strncmp(bs->msg, "Hello ", 5) == 0) {
489 return handle_director_request(bs);
493 Dmsg2(100, "Bad command from %s. Len=%d.\n", bs->who(), bs->msglen);
495 char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
496 Jmsg2(NULL, M_FATAL, 0, _("Bad command from %s. Len=%d.\n"), who, bs->msglen);
503 * Test the Network between FD/SD
505 static int fd_testnetwork_cmd(JCR *jcr)
507 bool can_compress, ok=true;
508 BSOCK *sd = jcr->store_bsock;
513 if (!sd || !jcr->dir_bsock) {
516 if (sscanf(jcr->dir_bsock->msg, "testnetwork bytes=%lld", &nb) != 1 || nb <= 0) {
517 sd->fsend("2999 testnetwork command error\n");
521 /* We disable the comline compression, else all numbers will be wrong */
522 can_compress = sd->can_compress();
524 sd->fsend("testnetwork bytes=%lld\n", nb);
525 sd->clear_compress();
527 /* In the first step, we send X bytes to the SD */
528 memset(sd->msg, 0xAA, sizeof_pool_memory(sd->msg));
529 sd->msglen = sizeof_pool_memory(sd->msg);
531 start = get_current_btime();
532 for (nb2 = nb ; nb2 > 0 && ok ; nb2 -= sd->msglen) {
533 if (nb2 < sd->msglen) {
538 sd->signal(BNET_EOD);
539 end = get_current_btime() + 1;
545 jcr->dir_bsock->fsend("2000 OK bytes=%lld duration=%lldms write_speed=%sB/s\n",
546 nb, end/1000 - start/1000,
547 edit_uint64_with_suffix(nb * 1000000 / (end - start), ed1));
549 /* Now we receive X bytes from the SD */
550 start = get_current_btime();
551 for (nb2 = 0; sd->recv() > 0; nb2 += sd->msglen) { }
552 end = get_current_btime() + 1;
554 jcr->dir_bsock->fsend("2000 OK bytes=%lld duration=%lldms read_speed=%sB/s\n",
555 nb2, end/1000 - start/1000,
556 edit_uint64_with_suffix(nb2 * 1000000 / (end - start), ed1));
558 jcr->dir_bsock->signal(BNET_CMD_OK);
565 jcr->dir_bsock->fsend("2999 network test failed ERR=%s\n", sd->errmsg);
566 jcr->dir_bsock->signal(BNET_CMD_FAILED);
572 static int proxy_cmd(JCR *jcr)
574 bool OK=true, fdcalled = false;
576 CONSRES *cons = jcr->director->console;
582 cons = (CONSRES *)GetNextRes(R_CONSOLE, NULL);
584 /* Here, dir_bsock is not really the director, this is a console */
585 cons_bsock = connect_director(jcr, cons);
587 jcr->dir_bsock->signal(BNET_ERROR_MSG);
588 jcr->dir_bsock->fsend("2999 proxy error. ERR=%s\n", jcr->errmsg);
589 jcr->dir_bsock->signal(BNET_MAIN_PROMPT);
590 /* Error during the connect */
594 /* Inform the console that the command is OK */
595 jcr->dir_bsock->fsend("2000 proxy OK.\n");
596 jcr->dir_bsock->signal(BNET_MAIN_PROMPT);
598 maxfd = MAX(cons_bsock->m_fd, jcr->dir_bsock->m_fd) + 1;
600 /* Start to forward events from one to the other
601 * It can be done with 2 threads, or with a select
605 FD_SET((unsigned)cons_bsock->m_fd, &fdset);
606 FD_SET((unsigned)jcr->dir_bsock->m_fd, &fdset);
610 switch ((v = select(maxfd, &fdset, NULL, NULL, &tv))) {
611 case 0: /* timeout */
612 OK = !jcr->is_canceled();
615 Dmsg1(0, "Bad call to select ERR=%d\n", errno);
619 if (cons_bsock->tls && !tls_bsock_probe(cons_bsock)) {
620 /* maybe a session key negotiation waked up the socket */
621 FD_CLR(cons_bsock->m_fd, &fdset);
623 if (jcr->dir_bsock->tls && !tls_bsock_probe(jcr->dir_bsock)) {
624 /* maybe a session key negotiation waked up the socket */
625 FD_CLR(jcr->dir_bsock->m_fd, &fdset);
630 Dmsg1(DT_NETWORK, "select = %d\n", v);
632 if (FD_ISSET(cons_bsock->m_fd, &fdset)) {
633 v = cons_bsock->recv();
634 if (v == BNET_SIGNAL) {
635 if (cons_bsock->msglen == BNET_FDCALLED) {
639 jcr->dir_bsock->signal(cons_bsock->msglen);
643 jcr->dir_bsock->fsend("%s", cons_bsock->msg);
646 /* We should not have such kind of message */
650 if (FD_ISSET(jcr->dir_bsock->m_fd, &fdset)) {
651 v = jcr->dir_bsock->recv();
652 if (v == BNET_SIGNAL) {
653 cons_bsock->signal(jcr->dir_bsock->msglen);
655 cons_bsock->fsend("%s", jcr->dir_bsock->msg);
657 /* We should not have such kind of message */
662 if (cons_bsock->is_error() || jcr->dir_bsock->is_error()) {
665 } while (OK && !jcr->is_canceled());
667 /* Close the socket, nothing more will come */
668 jcr->dir_bsock->signal(BNET_TERMINATE);
669 jcr->dir_bsock->close();
671 handle_connection_request(cons_bsock); /* will release the socket */
673 free_bsock(cons_bsock);
678 static int sm_dump_cmd(JCR *jcr)
681 sm_dump(false, true);
682 jcr->dir_bsock->fsend("2000 sm_dump OK\n");
687 static int exit_cmd(JCR *jcr)
689 jcr->dir_bsock->fsend("2000 exit OK\n");
696 * Hello from Director he must identify himself and provide his
699 static int hello_cmd(JCR *jcr)
701 Dmsg0(120, "Calling Authenticate\n");
702 if (!validate_dir_hello(jcr)) {
705 if (!authenticate_director(jcr)) {
708 Dmsg0(120, "OK Authenticate\n");
709 jcr->authenticated = true;
711 dequeue_messages(jcr); /* dequeue any daemon messages */
718 static int cancel_cmd(JCR *jcr)
720 BSOCK *dir = jcr->dir_bsock;
721 char Job[MAX_NAME_LENGTH];
726 if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
727 status = JS_Canceled;
729 } else if (sscanf(dir->msg, "stop Job=%127s", Job) == 1) {
730 status = JS_Incomplete;
733 dir->fsend(_("2902 Error scanning cancel command.\n"));
736 if (!(cjcr=get_jcr_by_full_name(Job))) {
737 dir->fsend(_("2901 Job %s not found.\n"), Job);
739 generate_plugin_event(cjcr, bEventCancelCommand, NULL);
740 cjcr->setJobStatus(status);
741 if (cjcr->store_bsock) {
742 cjcr->store_bsock->cancel();
744 cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
746 dir->fsend(_("2001 Job \"%s\" marked to be %s.\n"),
751 dir->signal(BNET_EOD);
756 * Set bandwidth limit as requested by the Director
759 static int setbandwidth_cmd(JCR *jcr)
761 BSOCK *dir = jcr->dir_bsock;
764 char Job[MAX_NAME_LENGTH];
767 if (sscanf(dir->msg, setbandwidth, &bw, Job) != 2 || bw < 0) {
768 pm_strcpy(jcr->errmsg, dir->msg);
769 dir->fsend(_("2991 Bad setbandwidth command: %s\n"), jcr->errmsg);
774 if(!(cjcr=get_jcr_by_full_name(Job))) {
775 dir->fsend(_("2901 Job %s not found.\n"), Job);
777 cjcr->max_bandwidth = bw;
778 if (cjcr->store_bsock) {
779 cjcr->store_bsock->set_bwlimit(bw);
784 } else { /* No job requested, apply globally */
785 me->max_bandwidth_per_job = bw; /* Overwrite directive */
787 cjcr->max_bandwidth = bw;
788 if (cjcr->store_bsock) {
789 cjcr->store_bsock->set_bwlimit(bw);
795 return dir->fsend(OKBandwidth);
799 * Set debug level as requested by the Director
802 static int setdebug_cmd(JCR *jcr)
804 BSOCK *dir = jcr->dir_bsock;
808 int64_t level, level_tags = 0;
813 Dmsg1(50, "setdebug_cmd: %s", dir->msg);
814 tags[0] = options[0] = 0;
815 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld blowup=%ld"
816 " options=%55s tags=%511s",
817 &lvl, &trace, &hangup, &blowup, options, tags);
819 scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld",
820 &lvl, &trace, &hangup);
822 Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
823 if (sscanf(dir->msg, "setdebug=%ld trace=%ld", &lvl, &trace) != 2) {
824 pm_strcpy(jcr->errmsg, dir->msg);
825 dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
836 if (!debug_parse_tags(tags, &level_tags)) {
842 debug_level_tags = level_tags;
844 /* Parse specific FD options */
845 for (char *p = options; *p ; p++) {
848 /* Turn on/off ignore bwrite() errors on restore */
849 no_win32_write_errors = true;
852 /* Turn on/off decomp of BackupRead() streams */
858 /* handle other options */
859 set_debug_flags(options);
861 Dmsg6(150, "level=%ld trace=%ld hangup=%ld blowup=%d options=%s tags=%s\n",
862 lvl, get_trace(), get_hangup(), get_blowup(), options, tags);
863 return dir->fsend(OKsetdebug, lvl, get_trace(), get_hangup(),
864 get_blowup(), options, tags);
868 static int estimate_cmd(JCR *jcr)
870 BSOCK *dir = jcr->dir_bsock;
871 char ed1[50], ed2[50];
873 if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
874 pm_strcpy(jcr->errmsg, dir->msg);
875 Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
876 dir->fsend(_("2992 Bad estimate command.\n"));
880 dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
881 edit_uint64_with_commas(jcr->JobBytes, ed2));
882 dir->signal(BNET_EOD);
887 * Get JobId and Storage Daemon Authorization key from Director
889 static int job_cmd(JCR *jcr)
891 BSOCK *dir = jcr->dir_bsock;
892 POOL_MEM sd_auth_key(PM_MESSAGE);
893 sd_auth_key.check_size(dir->msglen);
895 if (sscanf(dir->msg, jobcmd, &jcr->JobId, jcr->Job,
896 &jcr->VolSessionId, &jcr->VolSessionTime,
897 sd_auth_key.c_str()) != 5) {
898 pm_strcpy(jcr->errmsg, dir->msg);
899 Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
904 set_storage_auth_key(jcr, sd_auth_key.c_str());
905 Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
906 Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
907 new_plugins(jcr); /* instantiate plugins for this jcr */
908 generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
909 return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
912 extern "C" char *job_code_callback_filed(JCR *jcr, const char* param, char *buf, int buflen)
917 return jcr->director->hdr.name;
927 static int runbefore_cmd(JCR *jcr)
930 BSOCK *dir = jcr->dir_bsock;
931 POOLMEM *cmd = get_memory(dir->msglen+1);
934 Dmsg1(100, "runbefore_cmd: %s", dir->msg);
935 if (sscanf(dir->msg, runbefore, cmd) != 1) {
936 pm_strcpy(jcr->errmsg, dir->msg);
937 Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
938 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
944 /* Run the command now */
945 script = new_runscript();
946 script->set_job_code_callback(job_code_callback_filed);
947 script->set_command(cmd);
948 script->when = SCRIPT_Before;
949 ok = script->run(jcr, "ClientRunBeforeJob");
950 free_runscript(script);
954 dir->fsend(OKRunBefore);
957 dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
962 static int runbeforenow_cmd(JCR *jcr)
964 BSOCK *dir = jcr->dir_bsock;
966 run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
967 if (job_canceled(jcr)) {
968 dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
969 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
972 dir->fsend(OKRunBeforeNow);
973 Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
978 static int runafter_cmd(JCR *jcr)
980 BSOCK *dir = jcr->dir_bsock;
981 POOLMEM *msg = get_memory(dir->msglen+1);
984 Dmsg1(100, "runafter_cmd: %s", dir->msg);
985 if (sscanf(dir->msg, runafter, msg) != 1) {
986 pm_strcpy(jcr->errmsg, dir->msg);
987 Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
988 dir->fsend(_("2905 Bad RunAfterJob command.\n"));
994 cmd = new_runscript();
995 cmd->set_job_code_callback(job_code_callback_filed);
996 cmd->set_command(msg);
997 cmd->on_success = true;
998 cmd->on_failure = false;
999 cmd->when = SCRIPT_After;
1001 jcr->RunScripts->append(cmd);
1003 free_pool_memory(msg);
1004 return dir->fsend(OKRunAfter);
1007 static int runscript_cmd(JCR *jcr)
1009 BSOCK *dir = jcr->dir_bsock;
1010 POOLMEM *msg = get_memory(dir->msglen+1);
1011 int on_success, on_failure, fail_on_error;
1013 RUNSCRIPT *cmd = new_runscript() ;
1014 cmd->set_job_code_callback(job_code_callback_filed);
1016 Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
1017 /* Note, we cannot sscanf into bools */
1018 if (sscanf(dir->msg, runscript, &on_success,
1023 pm_strcpy(jcr->errmsg, dir->msg);
1024 Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
1025 dir->fsend(_("2905 Bad RunScript command.\n"));
1026 free_runscript(cmd);
1030 cmd->on_success = on_success;
1031 cmd->on_failure = on_failure;
1032 cmd->fail_on_error = fail_on_error;
1035 cmd->set_command(msg);
1037 jcr->RunScripts->append(cmd);
1039 free_pool_memory(msg);
1040 return dir->fsend(OKRunScript);
1044 * This reads data sent from the Director from the
1045 * RestoreObject table that allows us to get objects
1046 * that were backed up (VSS .xml data) and are needed
1047 * before starting the restore.
1049 static int restore_object_cmd(JCR *jcr)
1051 BSOCK *dir = jcr->dir_bsock;
1053 restore_object_pkt rop;
1055 memset(&rop, 0, sizeof(rop));
1056 rop.pkt_size = sizeof(rop);
1057 rop.pkt_end = sizeof(rop);
1059 Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
1060 if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
1061 Dmsg0(20, "Got endrestoreobject\n");
1062 generate_plugin_event(jcr, bEventRestoreObject, NULL);
1063 return dir->fsend(OKRestoreObject);
1066 rop.plugin_name = (char *)malloc(dir->msglen);
1067 *rop.plugin_name = 0;
1069 if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len,
1070 &rop.object_full_len, &rop.object_index,
1071 &rop.object_type, &rop.object_compression, &FileIndex,
1072 rop.plugin_name) != 8) {
1074 /* Old version, no plugin_name */
1075 if (sscanf(dir->msg, restoreobjcmd1, &rop.JobId, &rop.object_len,
1076 &rop.object_full_len, &rop.object_index,
1077 &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
1078 Dmsg0(5, "Bad restore object command\n");
1079 pm_strcpy(jcr->errmsg, dir->msg);
1080 Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
1085 unbash_spaces(rop.plugin_name);
1087 Dmsg7(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d "
1088 "FI=%d plugin_name=%s\n",
1089 rop.JobId, rop.object_len, rop.object_full_len,
1090 rop.object_index, rop.object_type, FileIndex, rop.plugin_name);
1091 /* Read Object name */
1092 if (dir->recv() < 0) {
1095 Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
1096 rop.object_name = bstrdup(dir->msg);
1099 if (dir->recv() < 0) {
1102 /* Transfer object from message buffer, and get new message buffer */
1103 rop.object = dir->msg;
1104 dir->msg = get_pool_memory(PM_MESSAGE);
1106 /* If object is compressed, uncompress it */
1107 if (rop.object_compression == 1) { /* zlib level 9 */
1109 int out_len = rop.object_full_len + 100;
1110 POOLMEM *obj = get_memory(out_len);
1111 Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
1112 stat = Zinflate(rop.object, rop.object_len, obj, out_len);
1113 Dmsg1(100, "Zinflate stat=%d\n", stat);
1114 if (out_len != rop.object_full_len) {
1115 Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
1116 rop.object_full_len, out_len, rop.object_name);
1118 free_pool_memory(rop.object); /* release compressed object */
1119 rop.object = obj; /* new uncompressed object */
1120 rop.object_len = out_len;
1122 Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
1123 /* we still need to do this to detect a vss restore */
1124 if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
1125 Dmsg0(100, "got job metadata\n");
1126 jcr->got_metadata = true;
1129 generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
1131 if (rop.object_name) {
1132 free(rop.object_name);
1135 free_pool_memory(rop.object);
1137 if (rop.plugin_name) {
1138 free(rop.plugin_name);
1141 Dmsg1(100, "Send: %s", OKRestoreObject);
1145 dir->fsend(_("2909 Bad RestoreObject command.\n"));
1151 static bool init_fileset(JCR *jcr)
1154 findFILESET *fileset;
1163 fileset = (findFILESET *)malloc(sizeof(findFILESET));
1164 memset(fileset, 0, sizeof(findFILESET));
1165 ff->fileset = fileset;
1166 fileset->state = state_none;
1167 fileset->include_list.init(1, true);
1168 fileset->exclude_list.init(1, true);
1172 static void append_file(JCR *jcr, findINCEXE *incexe,
1173 const char *buf, bool is_file)
1176 incexe->name_list.append(new_dlistString(buf));
1177 } else if (me->plugin_directory) {
1178 generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
1179 incexe->plugin_list.append(new_dlistString(buf));
1181 Jmsg(jcr, M_FATAL, 0,
1182 _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
1188 * Add fname to include/exclude fileset list. First check for
1189 * | and < and if necessary perform command.
1191 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
1193 findFILESET *fileset = jcr->ff->fileset;
1206 p++; /* skip over | */
1207 fn = get_pool_memory(PM_FNAME);
1208 fn = edit_job_codes(jcr, fn, p, "", job_code_callback_filed);
1209 bpipe = open_bpipe(fn, 0, "r");
1212 Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
1214 free_pool_memory(fn);
1217 free_pool_memory(fn);
1218 while (fgets(buf, sizeof(buf), bpipe->rfd)) {
1219 strip_trailing_junk(buf);
1220 append_file(jcr, fileset->incexe, buf, is_file);
1222 if ((stat=close_bpipe(bpipe)) != 0) {
1224 Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
1225 p, be.code(stat), be.bstrerror(stat));
1230 Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
1231 p++; /* skip over < */
1232 if ((ffd = fopen(p, "rb")) == NULL) {
1234 Jmsg(jcr, M_FATAL, 0,
1235 _("Cannot open FileSet input file: %s. ERR=%s\n"),
1239 while (fgets(buf, sizeof(buf), ffd)) {
1240 strip_trailing_junk(buf);
1241 append_file(jcr, fileset->incexe, buf, is_file);
1246 append_file(jcr, fileset->incexe, fname, is_file);
1251 findINCEXE *get_incexe(JCR *jcr)
1253 if (jcr->ff && jcr->ff->fileset) {
1254 return jcr->ff->fileset->incexe;
1259 void set_incexe(JCR *jcr, findINCEXE *incexe)
1261 findFILESET *fileset = jcr->ff->fileset;
1262 fileset->incexe = incexe;
1267 * Define a new Exclude block in the FileSet
1269 findINCEXE *new_exclude(JCR *jcr)
1271 findFILESET *fileset = jcr->ff->fileset;
1274 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1275 memset(fileset->incexe, 0, sizeof(findINCEXE));
1276 fileset->incexe->opts_list.init(1, true);
1277 fileset->incexe->name_list.init();
1278 fileset->incexe->plugin_list.init();
1279 fileset->exclude_list.append(fileset->incexe);
1280 return fileset->incexe;
1284 * Define a new Include block in the FileSet
1286 findINCEXE *new_include(JCR *jcr)
1288 findFILESET *fileset = jcr->ff->fileset;
1291 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1292 memset(fileset->incexe, 0, sizeof(findINCEXE));
1293 fileset->incexe->opts_list.init(1, true);
1294 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1295 fileset->incexe->plugin_list.init();
1296 fileset->include_list.append(fileset->incexe);
1297 return fileset->incexe;
1301 * Define a new preInclude block in the FileSet
1302 * That is the include is prepended to the other
1303 * Includes. This is used for plugin exclusions.
1305 findINCEXE *new_preinclude(JCR *jcr)
1307 findFILESET *fileset = jcr->ff->fileset;
1309 /* New pre-include */
1310 fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1311 memset(fileset->incexe, 0, sizeof(findINCEXE));
1312 fileset->incexe->opts_list.init(1, true);
1313 fileset->incexe->name_list.init(); /* for dlist; was 1,true for alist */
1314 fileset->incexe->plugin_list.init();
1315 fileset->include_list.prepend(fileset->incexe);
1316 return fileset->incexe;
1319 static findFOPTS *start_options(FF_PKT *ff)
1321 int state = ff->fileset->state;
1322 findINCEXE *incexe = ff->fileset->incexe;
1324 if (state != state_options) {
1325 ff->fileset->state = state_options;
1326 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1327 memset(fo, 0, sizeof(findFOPTS));
1328 fo->regex.init(1, true);
1329 fo->regexdir.init(1, true);
1330 fo->regexfile.init(1, true);
1331 fo->wild.init(1, true);
1332 fo->wilddir.init(1, true);
1333 fo->wildfile.init(1, true);
1334 fo->wildbase.init(1, true);
1335 fo->base.init(1, true);
1336 fo->fstype.init(1, true);
1337 fo->drivetype.init(1, true);
1338 incexe->current_opts = fo;
1339 incexe->opts_list.append(fo);
1341 return incexe->current_opts;
1345 * Used by plugins to define a new options block
1347 void new_options(JCR *jcr, findINCEXE *incexe)
1350 incexe = jcr->ff->fileset->incexe;
1352 findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1353 memset(fo, 0, sizeof(findFOPTS));
1354 fo->regex.init(1, true);
1355 fo->regexdir.init(1, true);
1356 fo->regexfile.init(1, true);
1357 fo->wild.init(1, true);
1358 fo->wilddir.init(1, true);
1359 fo->wildfile.init(1, true);
1360 fo->wildbase.init(1, true);
1361 fo->base.init(1, true);
1362 fo->fstype.init(1, true);
1363 fo->drivetype.init(1, true);
1364 incexe->current_opts = fo;
1365 incexe->opts_list.prepend(fo);
1366 jcr->ff->fileset->state = state_options;
1370 * Add a regex to the current fileset
1372 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
1374 findFOPTS *current_opts = start_options(jcr->ff);
1379 preg = (regex_t *)malloc(sizeof(regex_t));
1380 if (current_opts->flags & FO_IGNORECASE) {
1381 rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1383 rc = regcomp(preg, item, REG_EXTENDED);
1386 regerror(rc, preg, prbuf, sizeof(prbuf));
1389 Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1393 current_opts->regex.append(preg);
1394 } else if (type == 'D') {
1395 current_opts->regexdir.append(preg);
1396 } else if (type == 'F') {
1397 current_opts->regexfile.append(preg);
1401 return state_options;
1405 * Add a wild card to the current fileset
1407 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1409 findFOPTS *current_opts = start_options(jcr->ff);
1412 current_opts->wild.append(bstrdup(item));
1413 } else if (type == 'D') {
1414 current_opts->wilddir.append(bstrdup(item));
1415 } else if (type == 'F') {
1416 current_opts->wildfile.append(bstrdup(item));
1417 } else if (type == 'B') {
1418 current_opts->wildbase.append(bstrdup(item));
1422 return state_options;
1427 * Add options to the current fileset
1429 int add_options_to_fileset(JCR *jcr, const char *item)
1431 findFOPTS *current_opts = start_options(jcr->ff);
1433 set_options(current_opts, item);
1434 return state_options;
1437 static void add_fileset(JCR *jcr, const char *item)
1439 FF_PKT *ff = jcr->ff;
1440 findFILESET *fileset = ff->fileset;
1441 int state = fileset->state;
1442 findFOPTS *current_opts;
1444 /* Get code, optional subcode, and position item past the dividing space */
1445 Dmsg1(100, "%s\n", item);
1450 int subcode = ' '; /* A space is always a valid subcode */
1451 if (item[0] != '\0' && item[0] != ' ') {
1459 /* Skip all lines we receive after an error */
1460 if (state == state_error) {
1461 Dmsg0(100, "State=error return\n");
1466 * The switch tests the code for validity.
1467 * The subcode is always good if it is a space, otherwise we must confirm.
1468 * We set state to state_error first assuming the subcode is invalid,
1469 * requiring state to be set in cases below that handle subcodes.
1471 if (subcode != ' ') {
1472 state = state_error;
1473 Dmsg0(100, "Set state=error or double code.\n");
1477 (void)new_include(jcr);
1480 (void)new_exclude(jcr);
1482 case 'N': /* null */
1485 case 'F': /* file = */
1486 /* File item to include or exclude list */
1487 state = state_include;
1488 add_file_to_fileset(jcr, item, true);
1490 case 'P': /* plugin */
1491 /* Plugin item to include list */
1492 state = state_include;
1493 add_file_to_fileset(jcr, item, false);
1495 case 'R': /* regex */
1496 state = add_regex_to_fileset(jcr, item, subcode);
1499 current_opts = start_options(ff);
1500 current_opts->base.append(bstrdup(item));
1501 state = state_options;
1503 case 'X': /* Filetype or Drive type */
1504 current_opts = start_options(ff);
1505 state = state_options;
1506 if (subcode == ' ') {
1507 current_opts->fstype.append(bstrdup(item));
1508 } else if (subcode == 'D') {
1509 current_opts->drivetype.append(bstrdup(item));
1511 state = state_error;
1514 case 'W': /* wild cards */
1515 state = add_wild_to_fileset(jcr, item, subcode);
1517 case 'O': /* Options */
1518 state = add_options_to_fileset(jcr, item);
1520 case 'Z': /* ignore dir */
1521 state = state_include;
1522 fileset->incexe->ignoredir = bstrdup(item);
1525 current_opts = start_options(ff);
1526 // current_opts->reader = bstrdup(item); /* deprecated */
1527 state = state_options;
1530 current_opts = start_options(ff);
1531 // current_opts->writer = bstrdup(item); /* deprecated */
1532 state = state_options;
1534 case 'G': /* Plugin command for this Option block */
1535 current_opts = start_options(ff);
1536 current_opts->plugin = bstrdup(item);
1537 state = state_options;
1540 Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1541 state = state_error;
1544 ff->fileset->state = state;
1547 static bool term_fileset(JCR *jcr)
1549 FF_PKT *ff = jcr->ff;
1551 #ifdef xxx_DEBUG_CODE
1552 findFILESET *fileset = ff->fileset;
1555 for (i=0; i<fileset->include_list.size(); i++) {
1556 findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1558 for (j=0; j<incexe->opts_list.size(); j++) {
1559 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1560 for (k=0; k<fo->regex.size(); k++) {
1561 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1563 for (k=0; k<fo->regexdir.size(); k++) {
1564 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1566 for (k=0; k<fo->regexfile.size(); k++) {
1567 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1569 for (k=0; k<fo->wild.size(); k++) {
1570 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1572 for (k=0; k<fo->wilddir.size(); k++) {
1573 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1575 for (k=0; k<fo->wildfile.size(); k++) {
1576 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1578 for (k=0; k<fo->wildbase.size(); k++) {
1579 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1581 for (k=0; k<fo->base.size(); k++) {
1582 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1584 for (k=0; k<fo->fstype.size(); k++) {
1585 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1587 for (k=0; k<fo->drivetype.size(); k++) {
1588 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1591 if (incexe->ignoredir) {
1592 Dmsg1(400, "Z %s\n", incexe->ignoredir);
1595 foreach_dlist(node, &incexe->name_list) {
1596 Dmsg1(400, "F %s\n", node->c_str());
1598 foreach_dlist(node, &incexe->plugin_list) {
1599 Dmsg1(400, "P %s\n", node->c_str());
1602 for (i=0; i<fileset->exclude_list.size(); i++) {
1603 findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1605 for (j=0; j<incexe->opts_list.size(); j++) {
1606 findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1607 for (k=0; k<fo->regex.size(); k++) {
1608 Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1610 for (k=0; k<fo->regexdir.size(); k++) {
1611 Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1613 for (k=0; k<fo->regexfile.size(); k++) {
1614 Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1616 for (k=0; k<fo->wild.size(); k++) {
1617 Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1619 for (k=0; k<fo->wilddir.size(); k++) {
1620 Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1622 for (k=0; k<fo->wildfile.size(); k++) {
1623 Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1625 for (k=0; k<fo->wildbase.size(); k++) {
1626 Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1628 for (k=0; k<fo->base.size(); k++) {
1629 Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1631 for (k=0; k<fo->fstype.size(); k++) {
1632 Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1634 for (k=0; k<fo->drivetype.size(); k++) {
1635 Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1639 foreach_dlist(node, &incexe->name_list) {
1640 Dmsg1(400, "F %s\n", node->c_str());
1642 foreach_dlist(node, &incexe->plugin_list) {
1643 Dmsg1(400, "P %s\n", node->c_str());
1647 return ff->fileset->state != state_error;
1652 * As an optimization, we should do this during
1653 * "compile" time in filed/job.c, and keep only a bit mask
1654 * and the Verify options.
1656 static int set_options(findFOPTS *fo, const char *opts)
1662 // Commented out as it is not backward compatible - KES
1664 for (p=opts; *p; p++) {
1666 case 'a': /* alway replace */
1667 case '0': /* no option */
1670 fo->flags |= FO_EXCLUDE;
1673 fo->flags |= FO_MULTIFS;
1675 case 'h': /* no recursion */
1676 fo->flags |= FO_NO_RECURSION;
1678 case 'H': /* no hard link handling */
1679 fo->flags |= FO_NO_HARDLINK;
1682 fo->flags |= FO_IGNORECASE;
1685 fo->flags |= FO_MD5;
1688 fo->flags |= FO_NOREPLACE;
1690 case 'p': /* use portable data format */
1691 fo->flags |= FO_PORTABLE;
1693 case 'R': /* Resource forks and Finder Info */
1694 fo->flags |= FO_HFSPLUS;
1696 case 'r': /* read fifo */
1697 fo->flags |= FO_READFIFO;
1702 fo->flags |= FO_SHA1;
1707 fo->flags |= FO_SHA256;
1711 fo->flags |= FO_SHA512;
1717 * If 2 or 3 is seen here, SHA2 is not configured, so
1718 * eat the option, and drop back to SHA-1.
1720 if (p[1] == '2' || p[1] == '3') {
1723 fo->flags |= FO_SHA1;
1728 fo->flags |= FO_SPARSE;
1731 fo->flags |= FO_MTIMEONLY;
1734 fo->flags |= FO_KEEPATIME;
1737 fo->flags |= FO_ACL;
1739 case 'V': /* verify options */
1740 /* Copy Verify Options */
1741 for (j=0; *p && *p != ':'; p++) {
1742 fo->VerifyOpts[j] = *p;
1743 if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1747 fo->VerifyOpts[j] = 0;
1749 case 'C': /* accurate options */
1750 /* Copy Accurate Options */
1751 for (j=0; *p && *p != ':'; p++) {
1752 fo->AccurateOpts[j] = *p;
1753 if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1757 fo->AccurateOpts[j] = 0;
1759 case 'J': /* Basejob options */
1760 /* Copy BaseJob Options */
1761 for (j=0; *p && *p != ':'; p++) {
1762 fo->BaseJobOpts[j] = *p;
1763 if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1767 fo->BaseJobOpts[j] = 0;
1769 case 'P': /* strip path */
1772 for (j=0; *p && *p != ':'; p++) {
1774 if (j < (int)sizeof(strip) - 1) {
1779 fo->strip_path = atoi(strip);
1780 fo->flags |= FO_STRIPPATH;
1781 Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1784 fo->flags |= FO_IF_NEWER;
1787 fo->flags |= FO_ENHANCEDWILD;
1789 case 'Z': /* compression */
1791 if (*p >= '0' && *p <= '9') {
1792 fo->flags |= FO_COMPRESS;
1793 fo->Compress_algo = COMPRESS_GZIP;
1794 fo->Compress_level = *p - '0';
1796 else if (*p == 'o') {
1797 fo->flags |= FO_COMPRESS;
1798 fo->Compress_algo = COMPRESS_LZO1X;
1799 fo->Compress_level = 1; /* not used with LZO */
1803 fo->flags |= FO_NOATIME;
1806 fo->flags |= FO_CHKCHANGES;
1809 fo->flags |= FO_HONOR_NODUMP;
1812 fo->flags |= FO_XATTR;
1815 Jmsg1(NULL, M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1819 return state_options;
1824 * Director is passing his Fileset
1826 static int fileset_cmd(JCR *jcr)
1828 POOL_MEM buf(PM_MESSAGE);
1829 BSOCK *dir = jcr->dir_bsock;
1832 jcr->Snapshot = (strstr(dir->msg, "snap=1") != NULL);
1833 if (!init_fileset(jcr)) {
1836 while (dir->recv() >= 0) {
1837 strip_trailing_junk(dir->msg);
1838 Dmsg1(500, "Fileset: %s\n", dir->msg);
1839 pm_strcpy(buf, dir->msg);
1840 add_fileset(jcr, buf.c_str());
1842 if (!term_fileset(jcr)) {
1845 rtnstat = dir->fsend(OKinc);
1846 generate_plugin_event(jcr, bEventEndFileSet);
1852 * The Director sends us the component info file, which
1853 * we will in turn pass to the VSS plugin.
1855 static int component_cmd(JCR *jcr)
1857 BSOCK *dir = jcr->dir_bsock;
1859 while (dir->recv() >= 0) {
1860 Dmsg1(200, "filed<dird: component: %s", dir->msg);
1861 generate_plugin_event(jcr, bEventComponentInfo, (void *)dir->msg);
1863 return dir->fsend(OKComponentInfo);
1868 * Get backup level from Director
1870 * Note: there are odd things such as accurate_differential,
1871 * and accurate_incremental that are passed in level, thus
1872 * the calls to strstr() below.
1875 static int level_cmd(JCR *jcr)
1877 BSOCK *dir = jcr->dir_bsock;
1878 POOLMEM *level, *buf = NULL;
1881 level = get_memory(dir->msglen+1);
1882 Dmsg1(10, "level_cmd: %s", dir->msg);
1884 /* keep compatibility with older directors */
1885 if (strstr(dir->msg, "accurate")) {
1886 jcr->accurate = true;
1888 if (strstr(dir->msg, "rerunning")) {
1889 jcr->rerunning = true;
1891 if (sscanf(dir->msg, "level = %s ", level) != 1) {
1894 /* Base backup requested? */
1895 if (strcasecmp(level, "base") == 0) {
1896 jcr->setJobLevel(L_BASE);
1897 /* Full backup requested? */
1898 } else if (strcasecmp(level, "full") == 0) {
1899 jcr->setJobLevel(L_FULL);
1900 } else if (strstr(level, "differential")) {
1901 jcr->setJobLevel(L_DIFFERENTIAL);
1904 } else if (strstr(level, "incremental")) {
1905 jcr->setJobLevel(L_INCREMENTAL);
1909 * We get his UTC since time, then sync the clocks and correct it
1910 * to agree with our clock.
1912 } else if (strcasecmp(level, "since_utime") == 0) {
1913 buf = get_memory(dir->msglen+1);
1914 utime_t since_time, adj;
1915 btime_t his_time, bt_start, rt=0, bt_adj=0, his_time_prev=0, n=0;
1916 if (jcr->getJobLevel() == L_NONE) {
1917 jcr->setJobLevel(L_SINCE); /* if no other job level set, do it now */
1919 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d prev_job=%127s",
1920 buf, &mtime_only, jcr->PrevJob) != 3) {
1921 if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1922 buf, &mtime_only) != 2) {
1926 since_time = str_to_uint64(buf); /* this is the since time */
1927 Dmsg2(100, "since_time=%lld prev_job=%s\n", since_time, jcr->PrevJob);
1928 char ed1[50], ed2[50];
1930 * Sync clocks by polling him for the time. We take
1931 * 10 samples of his time throwing out the first two.
1933 for (int i=0; i<10; i++) {
1934 bt_start = get_current_btime();
1935 dir->signal(BNET_BTIME); /* poll for time */
1936 if (dir->recv() <= 0) { /* get response */
1939 if (sscanf(dir->msg, "btime %s", buf) != 1) {
1942 his_time = str_to_uint64(buf);
1943 rt = get_current_btime() - bt_start; /* compute round trip time */
1944 /* skip first two results and check for leap second */
1945 /* if any of the FD or DIR went back in time, skip this iteration */
1946 if (i < 2 || (his_time_prev > 0 && his_time < his_time_prev) || rt<0) {
1947 his_time_prev = his_time;
1950 his_time_prev = his_time;
1952 Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1953 edit_uint64(bt_start, ed2));
1954 bt_adj += bt_start - his_time - rt/2;
1955 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1958 if (n > 0) { /* Should be 1 in the worst case */
1959 bt_adj = bt_adj / n; /* compute average time */
1960 Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1961 adj = btime_to_utime(bt_adj);
1962 since_time += adj; /* adjust for clock difference */
1964 /* Don't notify if time within 3 seconds */
1965 if (adj > 3 || adj < -3) {
1967 if (adj > 600 || adj < -600) {
1972 Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1974 dir->signal(BNET_EOD);
1976 Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1977 jcr->incremental = 1; /* set incremental or decremental backup */
1978 jcr->mtime = since_time; /* set since time */
1979 generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1981 Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1989 generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1990 return dir->fsend(OKlevel);
1993 pm_strcpy(jcr->errmsg, dir->msg);
1994 Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
2003 * Get session parameters from Director -- this is for a Restore command
2004 * This is deprecated. It is now passed via the bsr.
2006 static int session_cmd(JCR *jcr)
2008 BSOCK *dir = jcr->dir_bsock;
2010 Dmsg1(100, "SessionCmd: %s", dir->msg);
2011 if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
2012 &jcr->VolSessionId, &jcr->VolSessionTime,
2013 &jcr->StartFile, &jcr->EndFile,
2014 &jcr->StartBlock, &jcr->EndBlock) != 7) {
2015 pm_strcpy(jcr->errmsg, dir->msg);
2016 Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
2020 return dir->fsend(OKsession);
2023 static void set_storage_auth_key(JCR *jcr, char *key)
2025 /* if no key don't update anything */
2031 * We can be contacting multiple storage daemons.
2032 * So, make sure that any old jcr->store_bsock is cleaned up.
2034 free_bsock(jcr->store_bsock);
2037 * We can be contacting multiple storage daemons.
2038 * So, make sure that any old jcr->sd_auth_key is cleaned up.
2040 if (jcr->sd_auth_key) {
2042 * If we already have a Authorization key, director can do multi
2045 Dmsg0(5, "set multi_restore=true\n");
2046 jcr->multi_restore = true;
2047 bfree(jcr->sd_auth_key);
2050 jcr->sd_auth_key = bstrdup(key);
2051 Dmsg1(200, "set sd auth key %s\n", jcr->sd_auth_key);
2055 * Get address of storage daemon from Director
2058 static int storage_cmd(JCR *jcr)
2060 int stored_port = 0; /* storage daemon port */
2061 int enable_ssl; /* enable ssl to sd */
2062 POOL_MEM sd_auth_key(PM_MESSAGE);
2063 BSOCK *dir = jcr->dir_bsock;
2066 Dmsg1(100, "StorageCmd: %s", dir->msg);
2067 sd_auth_key.check_size(dir->msglen);
2068 if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port,
2069 &enable_ssl, sd_auth_key.c_str()) == 4) {
2070 Dmsg1(100, "Set auth key %s\n", sd_auth_key.c_str());
2071 set_storage_auth_key(jcr, sd_auth_key.c_str());
2072 } else if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
2073 &stored_port, &enable_ssl) != 3) {
2074 pm_strcpy(jcr->errmsg, dir->msg);
2075 Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
2076 Pmsg1(010, "Bad storage command: %s", jcr->errmsg);
2081 /* TODO: see if we put limit on restore and backup... */
2082 if (!jcr->max_bandwidth) {
2083 if (jcr->director->max_bandwidth_per_job) {
2084 jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
2086 } else if (me->max_bandwidth_per_job) {
2087 jcr->max_bandwidth = me->max_bandwidth_per_job;
2091 if (stored_port != 0) { /* We are doing the connecting */
2092 Dmsg3(110, "Connect to storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port,
2094 jcr->sd_calls_client = false;
2096 /* Open command communications with Storage daemon */
2097 /* Try to connect for 1 hour at 10 second intervals */
2098 sd->set_source_address(me->FDsrc_addr);
2099 if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
2100 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
2101 /* destroy() OK because sd is local */
2103 Jmsg2(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
2104 jcr->stored_addr, stored_port);
2105 Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
2106 jcr->stored_addr, stored_port);
2110 Dmsg0(110, "Connection OK to SD.\n");
2111 jcr->store_bsock = sd;
2112 } else { /* The storage daemon called us */
2115 struct timespec timeout;
2118 free_bsock(jcr->store_bsock);
2119 jcr->sd_calls_client = true;
2122 * Wait for the Storage daemon to contact us to start the Job,
2123 * when he does, we will be released, unless the 30 minutes
2126 gettimeofday(&tv, &tz);
2127 timeout.tv_nsec = tv.tv_usec * 1000;
2128 timeout.tv_sec = tv.tv_sec + 30 * 60; /* wait 30 minutes */
2130 while (jcr->sd_calls_client_bsock == NULL && !jcr->is_job_canceled()) {
2131 errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
2132 if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
2135 Dmsg1(800, "=== Auth cond errstat=%d\n", errstat);
2138 Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr);
2140 /* We should already have a storage connection! */
2141 if (jcr->sd_calls_client_bsock == NULL) {
2142 Pmsg0(000, "Failed connect from Storage daemon. SD bsock=NULL.\n");
2143 Pmsg1(000, "Storagecmd: %s", dir->msg);
2144 Jmsg0(jcr, M_FATAL, 0, _("Failed connect from Storage daemon. SD bsock=NULL.\n"));
2147 if (jcr->is_job_canceled()) {
2150 /* Assign the new socket to the main one */
2152 jcr->store_bsock = jcr->sd_calls_client_bsock;
2153 jcr->sd_calls_client_bsock = NULL;
2156 jcr->store_bsock->set_bwlimit(jcr->max_bandwidth);
2158 if (!send_hello_sd(jcr, jcr->Job)) {
2162 if (!authenticate_storagedaemon(jcr)) {
2165 memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
2166 Dmsg0(110, "Authenticated with SD.\n");
2168 /* Send OK to Director */
2169 return dir->fsend(OKstore);
2172 dir->fsend(BADcmd, "storage");
2180 static int backup_cmd(JCR *jcr)
2182 BSOCK *dir = jcr->dir_bsock;
2183 BSOCK *sd = jcr->store_bsock;
2188 if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
2189 jcr->JobFiles = FileIndex;
2190 Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
2194 * If explicitly requesting FO_ACL or FO_XATTR, fail job if it
2195 * is not available on Client machine
2197 if (jcr->ff->flags & FO_ACL && !(have_acl)) {
2198 Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for Client.\n"));
2201 if (jcr->ff->flags & FO_XATTR && !have_xattr) {
2202 Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for Client.\n"));
2205 jcr->setJobStatus(JS_Blocked);
2206 jcr->setJobType(JT_BACKUP);
2207 Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
2209 Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
2210 dir->fsend(BADcmd, "backup");
2214 dir->fsend(OKbackup);
2215 Dmsg1(110, "filed>dird: %s", dir->msg);
2218 * Send Append Open Session to Storage daemon
2220 sd->fsend(append_open);
2221 Dmsg1(110, ">stored: %s", sd->msg);
2223 * Expect to receive back the Ticket number
2225 if (bget_msg(sd) >= 0) {
2226 Dmsg1(110, "<stored: %s", sd->msg);
2227 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2228 Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
2231 Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
2233 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
2238 * Send Append data command to Storage daemon
2240 sd->fsend(append_data, jcr->Ticket);
2241 Dmsg1(110, ">stored: %s", sd->msg);
2244 * Expect to get OK data
2246 Dmsg1(110, "<stored: %s", sd->msg);
2247 if (!response(jcr, sd, OK_data, "Append Data")) {
2251 generate_daemon_event(jcr, "JobStart");
2252 generate_plugin_event(jcr, bEventStartBackupJob);
2254 if (jcr->Snapshot) {
2255 Dmsg0(10, "Open a snapshot session\n");
2256 /* TODO: See if we abort the job */
2257 jcr->Snapshot = open_snapshot_backup_session(jcr);
2259 /* Call RunScript just after the Snapshot creation, usually, we restart services */
2260 run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2263 * Send Files to Storage daemon
2265 Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
2266 if (!blast_data_to_storage_daemon(jcr, NULL)) {
2267 jcr->setJobStatus(JS_ErrorTerminated);
2268 sd->suppress_error_messages(true);
2269 Dmsg0(110, "Error in blast_data.\n");
2271 jcr->setJobStatus(JS_Terminated);
2272 /* Note, the above set status will not override an error */
2273 if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
2274 sd->suppress_error_messages(true);
2275 goto cleanup; /* bail out now */
2278 * Expect to get response to append_data from Storage daemon
2280 if (!response(jcr, sd, OK_append, "Append Data")) {
2281 jcr->setJobStatus(JS_ErrorTerminated);
2286 * Send Append End Data to Storage daemon
2288 sd->fsend(append_end, jcr->Ticket);
2290 if (!response(jcr, sd, OK_end, "Append End")) {
2291 jcr->setJobStatus(JS_ErrorTerminated);
2296 * Send Append Close to Storage daemon
2298 sd->fsend(append_close, jcr->Ticket);
2299 while (bget_msg(sd) >= 0) { /* stop on signal or error */
2300 if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
2302 Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
2306 Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
2309 if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings ||
2310 SDJobStatus == JS_Incomplete)) {
2311 Jmsg(jcr, M_FATAL, 0, _("Bad status %d %c returned from Storage Daemon.\n"),
2312 SDJobStatus, (char)SDJobStatus);
2317 generate_plugin_event(jcr, bEventEndBackupJob);
2318 return 0; /* return and stop command loop */
2322 * Do a Verify for Director
2325 static int verify_cmd(JCR *jcr)
2327 BSOCK *dir = jcr->dir_bsock;
2328 BSOCK *sd = jcr->store_bsock;
2331 jcr->setJobType(JT_VERIFY);
2332 if (sscanf(dir->msg, verifycmd, level) != 1) {
2333 dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2337 if (strcasecmp(level, "init") == 0) {
2338 jcr->setJobLevel(L_VERIFY_INIT);
2339 } else if (strcasecmp(level, "catalog") == 0){
2340 jcr->setJobLevel(L_VERIFY_CATALOG);
2341 } else if (strcasecmp(level, "volume") == 0){
2342 jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
2343 } else if (strcasecmp(level, "data") == 0){
2344 jcr->setJobLevel(L_VERIFY_DATA);
2345 } else if (strcasecmp(level, "disk_to_catalog") == 0) {
2346 jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2348 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2352 dir->fsend(OKverify);
2354 generate_daemon_event(jcr, "JobStart");
2355 generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2356 generate_plugin_event(jcr, bEventStartVerifyJob);
2358 Dmsg1(110, "filed>dird: %s", dir->msg);
2360 switch (jcr->getJobLevel()) {
2362 case L_VERIFY_CATALOG:
2366 case L_VERIFY_VOLUME_TO_CATALOG:
2367 if (!open_sd_read_session(jcr)) {
2370 start_dir_heartbeat(jcr);
2371 do_verify_volume(jcr);
2372 stop_dir_heartbeat(jcr);
2374 * Send Close session command to Storage daemon
2376 sd->fsend(read_close, jcr->Ticket);
2377 Dmsg1(130, "filed>stored: %s", sd->msg);
2379 /* ****FIXME**** check response */
2380 bget_msg(sd); /* get OK */
2382 /* Inform Storage daemon that we are done */
2383 sd->signal(BNET_TERMINATE);
2386 case L_VERIFY_DISK_TO_CATALOG:
2390 dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2394 dir->signal(BNET_EOD);
2395 generate_plugin_event(jcr, bEventEndVerifyJob);
2396 return 0; /* return and terminate command loop */
2400 * Do a Restore for Director
2403 static int restore_cmd(JCR *jcr)
2405 BSOCK *dir = jcr->dir_bsock;
2406 BSOCK *sd = jcr->store_bsock;
2407 POOLMEM *args=NULL, *restore_where=NULL, *restore_rwhere=NULL;
2408 bool use_regexwhere=false;
2411 bool scan_ok = true;
2416 * Scan WHERE (base directory for restore) from command
2418 Dmsg0(100, "restore command\n");
2420 /* Pickup where string */
2421 args = get_memory(dir->msglen+1);
2424 restore_where = get_pool_memory(PM_FNAME);
2425 restore_rwhere = get_pool_memory(PM_FNAME);
2427 /* We don't know the size of where/rwhere in advance,
2428 * where= -> where=%202s\n
2430 Mmsg(restore_where, "%s%%%ds\n", restorefcmd, dir->msglen);
2431 Mmsg(restore_rwhere, "%s%%%ds\n", restorefcmdR, dir->msglen);
2433 Dmsg2(200, "where=%srwhere=%s", restore_where, restore_rwhere);
2435 /* Scan for new form with number of files to restore */
2436 if (sscanf(dir->msg, restore_where, &files, &replace, &prefix_links, args) != 4) {
2437 if (sscanf(dir->msg, restore_rwhere, &files, &replace, &prefix_links, args) != 4) {
2438 if (sscanf(dir->msg, restorefcmd1, &files, &replace, &prefix_links) != 3) {
2441 *args = 0; /* No where argument */
2443 use_regexwhere = true;
2448 jcr->ExpectedFiles = files;
2450 /* Scan for old form without number of files */
2451 jcr->ExpectedFiles = 0;
2453 /* where= -> where=%202s\n */
2454 Mmsg(restore_where, "%s%%%ds\n", restorecmd, dir->msglen);
2455 Mmsg(restore_rwhere, "%s%%%ds\n", restorecmdR, dir->msglen);
2457 if (sscanf(dir->msg, restore_where, &replace, &prefix_links, args) != 3) {
2458 if (sscanf(dir->msg, restore_rwhere, &replace, &prefix_links, args) != 3){
2459 if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2460 pm_strcpy(jcr->errmsg, dir->msg);
2461 Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2464 *args = 0; /* No where argument */
2466 use_regexwhere = true;
2471 /* Turn / into nothing */
2472 if (IsPathSeparator(args[0]) && args[1] == '\0') {
2476 Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2477 unbash_spaces(args);
2479 /* Keep track of newly created directories to apply them correct attributes */
2480 if (replace == REPLACE_NEVER || replace == REPLACE_IFNEWER) {
2481 jcr->keep_path_list = true;
2484 if (use_regexwhere) {
2485 jcr->where_bregexp = get_bregexps(args);
2486 if (!jcr->where_bregexp) {
2487 Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2491 jcr->where = bstrdup(args);
2494 jcr->replace = replace;
2495 jcr->prefix_links = prefix_links;
2497 dir->fsend(OKrestore);
2498 Dmsg1(110, "filed>dird: %s", dir->msg);
2500 jcr->setJobType(JT_RESTORE);
2502 jcr->setJobStatus(JS_Blocked);
2504 if (!open_sd_read_session(jcr)) {
2505 jcr->setJobStatus(JS_ErrorTerminated);
2509 jcr->setJobStatus(JS_Running);
2512 * Do restore of files and data
2514 start_dir_heartbeat(jcr);
2515 generate_daemon_event(jcr, "JobStart");
2516 generate_plugin_event(jcr, bEventStartRestoreJob);
2518 if (!jcr->is_canceled()) {
2522 stop_dir_heartbeat(jcr);
2524 jcr->setJobStatus(JS_Terminated);
2525 if (jcr->JobStatus != JS_Terminated) {
2526 sd->suppress_error_messages(true);
2530 * Send Close session command to Storage daemon
2532 sd->fsend(read_close, jcr->Ticket);
2533 Dmsg1(100, "filed>stored: %s", sd->msg);
2535 bget_msg(sd); /* get OK */
2537 /* Inform Storage daemon that we are done */
2538 sd->signal(BNET_TERMINATE);
2541 bfree_and_null(jcr->where);
2543 if (jcr->JobErrors) {
2544 jcr->setJobStatus(JS_ErrorTerminated);
2547 Dmsg0(100, "Done in job.c\n");
2549 if (jcr->multi_restore) {
2550 Dmsg0(100, OKstoreend);
2551 dir->fsend(OKstoreend);
2552 ret = 1; /* we continue the loop, waiting for next part */
2554 ret = 0; /* we stop here */
2557 if (job_canceled(jcr)) {
2558 ret = 0; /* we stop here */
2562 end_restore_cmd(jcr); /* stopping so send bEventEndRestoreJob */
2566 free_and_null_pool_memory(args);
2567 free_and_null_pool_memory(restore_where);
2568 free_and_null_pool_memory(restore_rwhere);
2573 static int end_restore_cmd(JCR *jcr)
2575 Dmsg0(5, "end_restore_cmd\n");
2576 generate_plugin_event(jcr, bEventEndRestoreJob);
2577 return 0; /* return and terminate command loop */
2580 static int open_sd_read_session(JCR *jcr)
2582 BSOCK *sd = jcr->store_bsock;
2585 Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2588 Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2589 jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2590 Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2592 * Open Read Session with Storage daemon
2594 sd->fsend(read_open, "DummyVolume",
2595 jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2596 jcr->StartBlock, jcr->EndBlock);
2597 Dmsg1(110, ">stored: %s", sd->msg);
2602 if (bget_msg(sd) >= 0) {
2603 Dmsg1(110, "filed<stored: %s", sd->msg);
2604 if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2605 Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2608 Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2610 Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2615 * Use interactive session for the current restore
2617 if (jcr->interactive_session) {
2618 sd->fsend(read_ctrl, jcr->Ticket);
2619 Dmsg1(110, ">stored: %s", sd->msg);
2623 * Start read of data with Storage daemon
2625 sd->fsend(read_data, jcr->Ticket);
2626 Dmsg1(110, ">stored: %s", sd->msg);
2631 if (!response(jcr, sd, OK_data, "Read Data")) {
2638 * Destroy the Job Control Record and associated
2639 * resources (sockets).
2641 static void filed_free_jcr(JCR *jcr)
2643 if (jcr->dir_bsock) {
2644 free_bsock(jcr->dir_bsock);
2645 jcr->dir_bsock = NULL;
2647 if (jcr->sd_calls_client_bsock) {
2648 free_bsock(jcr->sd_calls_client_bsock);
2649 jcr->sd_calls_client_bsock = NULL;
2651 if (jcr->store_bsock) {
2652 free_bsock(jcr->store_bsock);
2653 jcr->store_bsock = NULL;
2655 if (jcr->last_fname) {
2656 free_pool_memory(jcr->last_fname);
2658 free_plugins(jcr); /* release instantiated plugins */
2659 free_runscripts(jcr->RunScripts);
2660 delete jcr->RunScripts;
2661 free_path_list(jcr);
2663 if (jcr->JobId != 0) {
2664 write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2670 * Get response from Storage daemon to a command we
2671 * sent. Check that the response is OK.
2673 * Returns: 0 on failure
2676 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2683 if ((ret = bget_msg(sd)) > 0) {
2684 Dmsg0(110, sd->msg);
2685 if (strcmp(sd->msg, resp) == 0) {
2689 if (job_canceled(jcr)) {
2690 return 0; /* if canceled avoid useless error messages */
2692 if (sd->is_error()) {
2693 Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2694 cmd, sd->bstrerror());
2698 Jmsg4(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got len=%ld msg=\"%s\"\n"),
2699 cmd, resp, sd->msglen, smartdump(sd->msg, sd->msglen, buf, sizeof(buf)));
2701 Jmsg3(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got SIGNAL %s\n"),
2702 cmd, resp, bnet_sig_to_ascii(ret));