]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Big backport from Enterprise
[bacula/bacula] / bacula / src / filed / job.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2017 Kern Sibbald
5
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.
8
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.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *  Bacula File Daemon Job processing
21  *
22  *    Written by Kern Sibbald, October MM
23  */
24
25 #include "bacula.h"
26 #include "filed.h"
27 #include "ch.h"
28
29 /* Globals */
30 bool win32decomp = false;
31 bool no_win32_write_errors = false;
32
33 /* Static variables */
34 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
35
36 #ifdef HAVE_ACL
37 const bool have_acl = true; 
38 #else 
39 const bool have_acl = false; 
40 #endif 
41
42 #if HAVE_XATTR
43 const bool have_xattr = true; 
44 #else 
45 const bool have_xattr = false; 
46 #endif 
47  
48 extern CLIENT *me;                    /* our client resource */
49
50 /* Imported functions */
51 extern int status_cmd(JCR *jcr);
52 extern int qstatus_cmd(JCR *jcr);
53 extern int accurate_cmd(JCR *jcr);
54
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);
84 #ifdef DEVELOPER
85 static int exit_cmd(JCR *jcr);
86 #endif
87
88 /* Exported functions */
89
90 #define ACCESS_MONITOR    1
91 #define ACCESS_REMOTE     2
92
93 /*
94  * The following are the recognized commands from the Director.
95  */
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},
125 #ifdef DEVELOPER
126    {"exit",         exit_cmd, 0},
127 #endif
128    {NULL,       NULL}                  /* list terminator */
129 };
130
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";
136
137 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
138 static char restorefcmd1[] = "restore files=%d replace=%c prelinks=%d where=\n";
139
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.
143  *
144  * So, the code will add %s\n to the end of the following restore commands
145  */
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=";
150
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";
160
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";
189
190
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";
197
198
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";
208
209 /* Should tell us if a command is authorized or not */
210 static bool access_ok(struct s_cmds *cmd, DIRRES* dir)
211 {
212    if ((cmd->access & ACCESS_MONITOR) && dir->monitor) {
213       return true;
214    }
215    if ((cmd->access & ACCESS_REMOTE) && dir->remote) {
216       return true;
217    }
218    if (!dir->remote && !dir->monitor) {
219       return true;
220    }
221    return false;
222 }
223
224 /*
225  * Accept requests from a Director
226  *
227  * NOTE! We are running as a separate thread
228  *
229  * Send output one line
230  * at a time followed by a zero length transmission.
231  *
232  * Return when the connection is terminated or there
233  * is an error.
234  *
235  * Basic task here is:
236  *   Authenticate Director (during Hello command).
237  *   Accept commands one at a time from the Director
238  *     and execute them.
239  *
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
243  * runs a long time.
244  *
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
255  */
256
257 static void *handle_director_request(BSOCK *dir)
258 {
259    int i;
260    bool found, quit;
261    bool first = true;
262    JCR *jcr;
263    const char jobname[12] = "*Director*";
264
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;
283
284    dir->set_jcr(jcr);
285    /* Initialize SD start condition variable */
286    int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
287    if (errstat != 0) {
288       berrno be;
289       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat));
290       goto bail_out;
291    }
292    enable_backup_privileges(NULL, 1 /* ignore_errors */);
293
294    for (quit=false; !quit;) {
295       if (!first) {      /* first call the read is done */
296          /* Read command */
297          if (dir->recv() < 0) {
298             break;               /* connection terminated */
299          }
300       }
301       if (dir->msglen == 0) {    /* Bad connection */
302          break;
303       }
304       first = false;
305       dir->msg[dir->msglen] = 0;
306       Dmsg1(100, "<dird: %s", dir->msg);
307       found = false;
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) {
312                dir->fsend(no_auth);
313                dir->signal(BNET_EOD);
314                break;
315             }
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);
320                break;
321             }
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);
326                 quit = true;
327                 break;
328             }
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));
333             }
334             break;
335          }
336       }
337       if (!found) {              /* command not found */
338          dir->fsend(errmsg);
339          quit = true;
340          break;
341       }
342    }
343
344    /* Inform Storage daemon that we are done */
345    if (jcr->store_bsock) {
346       jcr->store_bsock->signal(BNET_TERMINATE);
347    }
348
349    /* Run the after job */
350    run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
351
352    /* send any queued messages before reporting the jobstatus to the director */
353    dequeue_messages(jcr);
354
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();
362       } else {
363          CommBytes = CommCompressedBytes = 0;
364       }
365       encrypt = jcr->crypto.pki_encrypt;
366       vss = jcr->Snapshot;
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);
371    }
372
373    generate_daemon_event(jcr, "JobEnd");
374    generate_plugin_event(jcr, bEventJobEnd);
375
376 bail_out:
377    dequeue_messages(jcr);  /* send any queued messages, will no longer impact
378                             * the job status... */
379
380    /* Inform Director that we are done */
381    dir->signal(BNET_TERMINATE);
382
383    free_and_null_pool_memory(jcr->job_metadata);
384
385    /* Clean up fileset */
386    FF_PKT *ff = jcr->ff;
387    findFILESET *fileset = ff->fileset;
388    if (fileset) {
389       int i, j, k;
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);
395             if (fo->plugin) {
396                free(fo->plugin);
397             }
398             for (k=0; k<fo->regex.size(); k++) {
399                regfree((regex_t *)fo->regex.get(k));
400             }
401             for (k=0; k<fo->regexdir.size(); k++) {
402                regfree((regex_t *)fo->regexdir.get(k));
403             }
404             for (k=0; k<fo->regexfile.size(); k++) {
405                regfree((regex_t *)fo->regexfile.get(k));
406             }
407             fo->regex.destroy();
408             fo->regexdir.destroy();
409             fo->regexfile.destroy();
410             fo->wild.destroy();
411             fo->wilddir.destroy();
412             fo->wildfile.destroy();
413             fo->wildbase.destroy();
414             fo->base.destroy();
415             fo->fstype.destroy();
416             fo->drivetype.destroy();
417          }
418          incexe->opts_list.destroy();
419          incexe->name_list.destroy();
420          incexe->plugin_list.destroy();
421          if (incexe->ignoredir) {
422             free(incexe->ignoredir);
423          }
424       }
425       fileset->include_list.destroy();
426
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);
432             fo->regex.destroy();
433             fo->regexdir.destroy();
434             fo->regexfile.destroy();
435             fo->wild.destroy();
436             fo->wilddir.destroy();
437             fo->wildfile.destroy();
438             fo->wildbase.destroy();
439             fo->base.destroy();
440             fo->fstype.destroy();
441             fo->drivetype.destroy();
442          }
443          incexe->opts_list.destroy();
444          incexe->name_list.destroy();
445          incexe->plugin_list.destroy();
446          if (incexe->ignoredir) {
447             free(incexe->ignoredir);
448          }
449       }
450       fileset->exclude_list.destroy();
451       free(fileset);
452    }
453    ff->fileset = NULL;
454    ff->mount_points.destroy();
455    Dmsg0(100, "Calling term_find_files\n");
456    term_find_files(jcr->ff);
457    jcr->ff = NULL;
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 */
463    Dsm_check(100);
464    garbage_collect_memory_pool();
465    return NULL;
466 }
467
468
469 /*
470  * Accept requests from a Director or a Storage daemon
471  */
472 void *handle_connection_request(void *caller)
473 {
474    BSOCK *bs = (BSOCK *)caller;
475
476    if (bs->recv() > 0) {
477       if (strncmp(bs->msg, "Ping", 4) == 0) {
478          bs->fsend("2000 Ping OK\n");
479          bs->destroy();
480          return NULL;
481       }
482       if (bs->msglen < 25 || bs->msglen > 500) {
483          goto bail_out;
484       }
485       if (strncmp(bs->msg, "Hello FD: Bacula Storage", 20) ==0) {
486          return handle_storage_connection(bs);
487       }
488       if (strncmp(bs->msg, "Hello ", 5) == 0) {
489          return handle_director_request(bs);
490       }
491    }
492 bail_out:
493    Dmsg2(100, "Bad command from %s. Len=%d.\n", bs->who(), bs->msglen);
494    char addr[64];
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);
497    bs->destroy();
498    return NULL;
499 }
500
501
502 /* 
503  * Test the Network between FD/SD
504  */
505 static int fd_testnetwork_cmd(JCR *jcr)
506 {
507    bool can_compress, ok=true;
508    BSOCK *sd = jcr->store_bsock;
509    int64_t nb=0, nb2=0;
510    char ed1[50];
511    btime_t start, end;
512
513    if (!sd || !jcr->dir_bsock) {
514       return 1;
515    }
516    if (sscanf(jcr->dir_bsock->msg, "testnetwork bytes=%lld", &nb) != 1 || nb <= 0) {
517       sd->fsend("2999 testnetwork command error\n");
518       return 1;
519    }
520
521    /* We disable the comline compression, else all numbers will be wrong */
522    can_compress = sd->can_compress();
523
524    sd->fsend("testnetwork bytes=%lld\n", nb);
525    sd->clear_compress();
526
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);
530
531    start = get_current_btime();
532    for (nb2 = nb ; nb2 > 0 && ok ; nb2 -= sd->msglen) {
533       if (nb2 < sd->msglen) {
534          sd->msglen = nb2;
535       }
536       ok = sd->send();
537    }
538    sd->signal(BNET_EOD);
539    end = get_current_btime() + 1;
540
541    if (!ok) {
542       goto bail_out;
543    }
544
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));
548
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;
553
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));
557
558    jcr->dir_bsock->signal(BNET_CMD_OK);
559
560 bail_out:
561    if (can_compress) {
562       sd->set_compress();
563    }
564    if (!ok) {
565       jcr->dir_bsock->fsend("2999 network test failed ERR=%s\n", sd->errmsg);
566       jcr->dir_bsock->signal(BNET_CMD_FAILED);
567    }
568
569    return 1;
570 }
571
572 static int proxy_cmd(JCR *jcr)
573 {
574    bool OK=true, fdcalled = false;
575    BSOCK *cons_bsock;
576    CONSRES *cons = jcr->director->console;
577    int v, maxfd;
578    fd_set fdset;
579    struct timeval tv;
580
581    if (!cons) {
582       cons = (CONSRES *)GetNextRes(R_CONSOLE, NULL);
583    }
584    /* Here, dir_bsock is not really the director, this is a console */
585    cons_bsock = connect_director(jcr, cons);
586    if (!cons_bsock) {
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 */
591       return 1;
592    }
593
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);
597    
598    maxfd = MAX(cons_bsock->m_fd, jcr->dir_bsock->m_fd) + 1;
599
600    /* Start to forward events from one to the other
601     * It can be done with 2 threads, or with a select
602     */
603    do {
604       FD_ZERO(&fdset);
605       FD_SET((unsigned)cons_bsock->m_fd, &fdset);
606       FD_SET((unsigned)jcr->dir_bsock->m_fd, &fdset);
607
608       tv.tv_sec = 5;
609       tv.tv_usec = 0;
610       switch ((v = select(maxfd, &fdset, NULL, NULL, &tv))) {
611       case 0:                      /* timeout */
612          OK = !jcr->is_canceled();
613          break;
614       case -1:
615          Dmsg1(0, "Bad call to select ERR=%d\n", errno);
616          OK = false;
617       default:
618 #ifdef HAVE_TLS
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);
622          }
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);
626          }
627 #endif
628          break;
629       }
630       Dmsg1(DT_NETWORK, "select = %d\n", v);
631       if (OK) {
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) {
636                   OK = false;
637                   fdcalled = true;
638                } else {
639                   jcr->dir_bsock->signal(cons_bsock->msglen);
640                }
641
642             } else if (v >= 0) {
643                jcr->dir_bsock->fsend("%s", cons_bsock->msg);
644
645             } else {
646                /* We should not have such kind of message */
647                OK = false;
648             }
649          }
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);
654             } else if (v >= 0) {
655                cons_bsock->fsend("%s", jcr->dir_bsock->msg);
656             } else {
657                /* We should not have such kind of message */
658                OK = false;
659             }
660          }
661       }
662       if (cons_bsock->is_error() || jcr->dir_bsock->is_error()) {
663          OK = false;
664       }
665    } while (OK && !jcr->is_canceled());
666    
667    /* Close the socket, nothing more will come */
668    jcr->dir_bsock->signal(BNET_TERMINATE);
669    jcr->dir_bsock->close();
670    if (fdcalled) {
671       handle_connection_request(cons_bsock); /* will release the socket */
672    } else {
673       free_bsock(cons_bsock);
674    }
675    return 1;
676 }
677
678 static int sm_dump_cmd(JCR *jcr)
679 {
680    close_memory_pool();
681    sm_dump(false, true);
682    jcr->dir_bsock->fsend("2000 sm_dump OK\n");
683    return 1;
684 }
685
686 #ifdef DEVELOPER
687 static int exit_cmd(JCR *jcr)
688 {
689    jcr->dir_bsock->fsend("2000 exit OK\n");
690    terminate_filed(0);
691    return 0;
692 }
693 #endif
694
695 /*
696  * Hello from Director he must identify himself and provide his
697  *  password.
698  */
699 static int hello_cmd(JCR *jcr)
700 {
701    Dmsg0(120, "Calling Authenticate\n");
702    if (!validate_dir_hello(jcr)) {
703       return 0;
704    }
705    if (!authenticate_director(jcr)) {
706       return 0;
707    }
708    Dmsg0(120, "OK Authenticate\n");
709    jcr->authenticated = true;
710
711    dequeue_messages(jcr);     /* dequeue any daemon messages */
712    return 1;
713 }
714
715 /*
716  * Cancel a Job
717  */
718 static int cancel_cmd(JCR *jcr)
719 {
720    BSOCK *dir = jcr->dir_bsock;
721    char Job[MAX_NAME_LENGTH];
722    JCR *cjcr;
723    int status;
724    const char *reason;
725
726    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
727       status = JS_Canceled;
728       reason = "canceled";
729    } else if (sscanf(dir->msg, "stop Job=%127s", Job) == 1) {
730       status = JS_Incomplete;
731       reason = "stopped";
732    } else {
733       dir->fsend(_("2902 Error scanning cancel command.\n"));
734       goto bail_out;
735    }
736    if (!(cjcr=get_jcr_by_full_name(Job))) {
737       dir->fsend(_("2901 Job %s not found.\n"), Job);
738    } else {
739       generate_plugin_event(cjcr, bEventCancelCommand, NULL);
740       cjcr->setJobStatus(status);
741       if (cjcr->store_bsock) {
742          cjcr->store_bsock->cancel();
743       }
744       cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
745       free_jcr(cjcr);
746       dir->fsend(_("2001 Job \"%s\" marked to be %s.\n"),
747          Job, reason);
748    }
749
750 bail_out:
751    dir->signal(BNET_EOD);
752    return 1;
753 }
754
755 /**
756  * Set bandwidth limit as requested by the Director
757  *
758  */
759 static int setbandwidth_cmd(JCR *jcr)
760 {
761    BSOCK *dir = jcr->dir_bsock;
762    int64_t bw=0;
763    JCR *cjcr;
764    char Job[MAX_NAME_LENGTH];
765    *Job=0;
766
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);
770       return 0;
771    }
772
773    if (*Job) {
774       if(!(cjcr=get_jcr_by_full_name(Job))) {
775          dir->fsend(_("2901 Job %s not found.\n"), Job);
776       } else {
777          cjcr->max_bandwidth = bw;
778          if (cjcr->store_bsock) {
779             cjcr->store_bsock->set_bwlimit(bw);
780          }
781          free_jcr(cjcr);
782       }
783
784    } else {                           /* No job requested, apply globally */
785       me->max_bandwidth_per_job = bw; /* Overwrite directive */
786       foreach_jcr(cjcr) {
787          cjcr->max_bandwidth = bw;
788          if (cjcr->store_bsock) {
789             cjcr->store_bsock->set_bwlimit(bw);
790          }
791       }
792       endeach_jcr(cjcr);
793    }
794
795    return dir->fsend(OKBandwidth);
796 }
797
798 /**
799  * Set debug level as requested by the Director
800  *
801  */
802 static int setdebug_cmd(JCR *jcr)
803 {
804    BSOCK *dir = jcr->dir_bsock;
805    int32_t trace, lvl;
806    int32_t hangup = -1;
807    int32_t blowup = -1;
808    int64_t level, level_tags = 0;
809    int scan;
810    char options[60];
811    char tags[512];
812
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);
818    if (scan != 6) {
819       scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld",
820                     &lvl, &trace, &hangup);
821       if (scan != 3) {
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);
826             return 0;
827          } else {
828             hangup = -1;
829          }
830       }
831    }
832    level = lvl;
833    set_trace(trace);
834    set_hangup(hangup);
835    set_blowup(blowup);
836    if (!debug_parse_tags(tags, &level_tags)) {
837       *tags = 0;
838    }
839    if (level >= 0) {
840       debug_level = level;
841    }
842    debug_level_tags = level_tags;
843
844    /* Parse specific FD options */
845    for (char *p = options; *p ; p++) {
846       switch(*p) {
847       case 'i':
848          /* Turn on/off ignore bwrite() errors on restore */
849          no_win32_write_errors = true;
850          break;
851       case 'd':
852          /* Turn on/off decomp of BackupRead() streams */
853          win32decomp = true;
854          break;
855       }
856    }
857
858    /* handle other options */
859    set_debug_flags(options);
860
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);
865 }
866
867
868 static int estimate_cmd(JCR *jcr)
869 {
870    BSOCK *dir = jcr->dir_bsock;
871    char ed1[50], ed2[50];
872
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"));
877       return 0;
878    }
879    make_estimate(jcr);
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);
883    return 1;
884 }
885
886 /**
887  * Get JobId and Storage Daemon Authorization key from Director
888  */
889 static int job_cmd(JCR *jcr)
890 {
891    BSOCK *dir = jcr->dir_bsock;
892    POOL_MEM sd_auth_key(PM_MESSAGE);
893    sd_auth_key.check_size(dir->msglen);
894
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);
900       dir->fsend(BADjob);
901       return 0;
902    }
903    set_jcr_in_tsd(jcr);
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);
910 }
911
912 extern "C" char *job_code_callback_filed(JCR *jcr, const char* param, char *buf, int buflen)
913 {
914    switch (param[0]) {
915    case 'D':
916       if (jcr->director) {
917          return jcr->director->hdr.name;
918       }
919       break;
920    case 'S':
921       return jcr->PrevJob;
922    }
923    return NULL;
924
925 }
926
927 static int runbefore_cmd(JCR *jcr)
928 {
929    bool ok;
930    BSOCK *dir = jcr->dir_bsock;
931    POOLMEM *cmd = get_memory(dir->msglen+1);
932    RUNSCRIPT *script;
933
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"));
939       free_memory(cmd);
940       return 0;
941    }
942    unbash_spaces(cmd);
943
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);
951
952    free_memory(cmd);
953    if (ok) {
954       dir->fsend(OKRunBefore);
955       return 1;
956    } else {
957       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
958       return 0;
959    }
960 }
961
962 static int runbeforenow_cmd(JCR *jcr)
963 {
964    BSOCK *dir = jcr->dir_bsock;
965
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");
970       return 0;
971    } else {
972       dir->fsend(OKRunBeforeNow);
973       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
974       return 1;
975    }
976 }
977
978 static int runafter_cmd(JCR *jcr)
979 {
980    BSOCK *dir = jcr->dir_bsock;
981    POOLMEM *msg = get_memory(dir->msglen+1);
982    RUNSCRIPT *cmd;
983
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"));
989       free_memory(msg);
990       return 0;
991    }
992    unbash_spaces(msg);
993
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;
1000
1001    jcr->RunScripts->append(cmd);
1002
1003    free_pool_memory(msg);
1004    return dir->fsend(OKRunAfter);
1005 }
1006
1007 static int runscript_cmd(JCR *jcr)
1008 {
1009    BSOCK *dir = jcr->dir_bsock;
1010    POOLMEM *msg = get_memory(dir->msglen+1);
1011    int on_success, on_failure, fail_on_error;
1012
1013    RUNSCRIPT *cmd = new_runscript() ;
1014    cmd->set_job_code_callback(job_code_callback_filed);
1015
1016    Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
1017    /* Note, we cannot sscanf into bools */
1018    if (sscanf(dir->msg, runscript, &on_success,
1019                                   &on_failure,
1020                                   &fail_on_error,
1021                                   &cmd->when,
1022                                   msg) != 5) {
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);
1027       free_memory(msg);
1028       return 0;
1029    }
1030    cmd->on_success = on_success;
1031    cmd->on_failure = on_failure;
1032    cmd->fail_on_error = fail_on_error;
1033    unbash_spaces(msg);
1034
1035    cmd->set_command(msg);
1036    cmd->debug();
1037    jcr->RunScripts->append(cmd);
1038
1039    free_pool_memory(msg);
1040    return dir->fsend(OKRunScript);
1041 }
1042
1043 /*
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.
1048  */
1049 static int restore_object_cmd(JCR *jcr)
1050 {
1051    BSOCK *dir = jcr->dir_bsock;
1052    int32_t FileIndex;
1053    restore_object_pkt rop;
1054
1055    memset(&rop, 0, sizeof(rop));
1056    rop.pkt_size = sizeof(rop);
1057    rop.pkt_end = sizeof(rop);
1058
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);
1064    }
1065
1066    rop.plugin_name = (char *)malloc(dir->msglen);
1067    *rop.plugin_name = 0;
1068
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) {
1073
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);
1081          goto bail_out;
1082       }
1083    }
1084
1085    unbash_spaces(rop.plugin_name);
1086
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) {
1093       goto bail_out;
1094    }
1095    Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
1096    rop.object_name = bstrdup(dir->msg);
1097
1098    /* Read Object */
1099    if (dir->recv() < 0) {
1100       goto bail_out;
1101    }
1102    /* Transfer object from message buffer, and get new message buffer */
1103    rop.object = dir->msg;
1104    dir->msg = get_pool_memory(PM_MESSAGE);
1105
1106    /* If object is compressed, uncompress it */
1107    if (rop.object_compression == 1) {   /* zlib level 9 */
1108       int stat;
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);
1117       }
1118       free_pool_memory(rop.object);   /* release compressed object */
1119       rop.object = obj;               /* new uncompressed object */
1120       rop.object_len = out_len;
1121    }
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;
1127    }
1128
1129    generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
1130
1131    if (rop.object_name) {
1132       free(rop.object_name);
1133    }
1134    if (rop.object) {
1135       free_pool_memory(rop.object);
1136    }
1137    if (rop.plugin_name) {
1138       free(rop.plugin_name);
1139    }
1140
1141    Dmsg1(100, "Send: %s", OKRestoreObject);
1142    return 1;
1143
1144 bail_out:
1145    dir->fsend(_("2909 Bad RestoreObject command.\n"));
1146    return 0;
1147
1148 }
1149
1150
1151 static bool init_fileset(JCR *jcr)
1152 {
1153    FF_PKT *ff;
1154    findFILESET *fileset;
1155
1156    if (!jcr->ff) {
1157       return false;
1158    }
1159    ff = jcr->ff;
1160    if (ff->fileset) {
1161       return false;
1162    }
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);
1169    return true;
1170 }
1171
1172 static void append_file(JCR *jcr, findINCEXE *incexe,
1173                         const char *buf, bool is_file)
1174 {
1175    if (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));
1180    } else {
1181       Jmsg(jcr, M_FATAL, 0,
1182            _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
1183            buf);
1184    }
1185 }
1186
1187 /**
1188  * Add fname to include/exclude fileset list. First check for
1189  * | and < and if necessary perform command.
1190  */
1191 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
1192 {
1193    findFILESET *fileset = jcr->ff->fileset;
1194    char *p;
1195    BPIPE *bpipe;
1196    POOLMEM *fn;
1197    FILE *ffd;
1198    char buf[1000];
1199    int ch;
1200    int stat;
1201
1202    p = (char *)fname;
1203    ch = (uint8_t)*p;
1204    switch (ch) {
1205    case '|':
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");
1210       if (!bpipe) {
1211          berrno be;
1212          Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
1213             p, be.bstrerror());
1214          free_pool_memory(fn);
1215          return;
1216       }
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);
1221       }
1222       if ((stat=close_bpipe(bpipe)) != 0) {
1223          berrno be;
1224          Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
1225             p, be.code(stat), be.bstrerror(stat));
1226          return;
1227       }
1228       break;
1229    case '<':
1230       Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
1231       p++;                      /* skip over < */
1232       if ((ffd = fopen(p, "rb")) == NULL) {
1233          berrno be;
1234          Jmsg(jcr, M_FATAL, 0,
1235               _("Cannot open FileSet input file: %s. ERR=%s\n"),
1236             p, be.bstrerror());
1237          return;
1238       }
1239       while (fgets(buf, sizeof(buf), ffd)) {
1240          strip_trailing_junk(buf);
1241          append_file(jcr, fileset->incexe, buf, is_file);
1242       }
1243       fclose(ffd);
1244       break;
1245    default:
1246       append_file(jcr, fileset->incexe, fname, is_file);
1247       break;
1248    }
1249 }
1250
1251 findINCEXE *get_incexe(JCR *jcr)
1252 {
1253    if (jcr->ff && jcr->ff->fileset) {
1254       return jcr->ff->fileset->incexe;
1255    }
1256    return NULL;
1257 }
1258
1259 void set_incexe(JCR *jcr, findINCEXE *incexe)
1260 {
1261    findFILESET *fileset = jcr->ff->fileset;
1262    fileset->incexe = incexe;
1263 }
1264
1265
1266 /**
1267  * Define a new Exclude block in the FileSet
1268  */
1269 findINCEXE *new_exclude(JCR *jcr)
1270 {
1271    findFILESET *fileset = jcr->ff->fileset;
1272
1273    /* New exclude */
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;
1281 }
1282
1283 /**
1284  * Define a new Include block in the FileSet
1285  */
1286 findINCEXE *new_include(JCR *jcr)
1287 {
1288    findFILESET *fileset = jcr->ff->fileset;
1289
1290    /* New include */
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;
1298 }
1299
1300 /**
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.
1304  */
1305 findINCEXE *new_preinclude(JCR *jcr)
1306 {
1307    findFILESET *fileset = jcr->ff->fileset;
1308
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;
1317 }
1318
1319 static findFOPTS *start_options(FF_PKT *ff)
1320 {
1321    int state = ff->fileset->state;
1322    findINCEXE *incexe = ff->fileset->incexe;
1323
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);
1340    }
1341    return incexe->current_opts;
1342 }
1343
1344 /*
1345  * Used by plugins to define a new options block
1346  */
1347 void new_options(JCR *jcr, findINCEXE *incexe)
1348 {
1349    if (!incexe) {
1350       incexe = jcr->ff->fileset->incexe;
1351    }
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;
1367 }
1368
1369 /**
1370  * Add a regex to the current fileset
1371  */
1372 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
1373 {
1374    findFOPTS *current_opts = start_options(jcr->ff);
1375    regex_t *preg;
1376    int rc;
1377    char prbuf[500];
1378
1379    preg = (regex_t *)malloc(sizeof(regex_t));
1380    if (current_opts->flags & FO_IGNORECASE) {
1381       rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1382    } else {
1383       rc = regcomp(preg, item, REG_EXTENDED);
1384    }
1385    if (rc != 0) {
1386       regerror(rc, preg, prbuf, sizeof(prbuf));
1387       regfree(preg);
1388       free(preg);
1389       Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1390       return state_error;
1391    }
1392    if (type == ' ') {
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);
1398    } else {
1399       return state_error;
1400    }
1401    return state_options;
1402 }
1403
1404 /**
1405  * Add a wild card to the current fileset
1406  */
1407 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1408 {
1409    findFOPTS *current_opts = start_options(jcr->ff);
1410
1411    if (type == ' ') {
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));
1419    } else {
1420       return state_error;
1421    }
1422    return state_options;
1423 }
1424
1425
1426 /**
1427  * Add options to the current fileset
1428  */
1429 int add_options_to_fileset(JCR *jcr, const char *item)
1430 {
1431    findFOPTS *current_opts = start_options(jcr->ff);
1432
1433    set_options(current_opts, item);
1434    return state_options;
1435 }
1436
1437 static void add_fileset(JCR *jcr, const char *item)
1438 {
1439    FF_PKT *ff = jcr->ff;
1440    findFILESET *fileset = ff->fileset;
1441    int state = fileset->state;
1442    findFOPTS *current_opts;
1443
1444    /* Get code, optional subcode, and position item past the dividing space */
1445    Dmsg1(100, "%s\n", item);
1446    int code = item[0];
1447    if (code != '\0') {
1448       ++item;
1449    }
1450    int subcode = ' ';               /* A space is always a valid subcode */
1451    if (item[0] != '\0' && item[0] != ' ') {
1452       subcode = item[0];
1453       ++item;
1454    }
1455    if (*item == ' ') {
1456       ++item;
1457    }
1458
1459    /* Skip all lines we receive after an error */
1460    if (state == state_error) {
1461       Dmsg0(100, "State=error return\n");
1462       return;
1463    }
1464
1465    /**
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.
1470     */
1471    if (subcode != ' ') {
1472       state = state_error;
1473       Dmsg0(100, "Set state=error or double code.\n");
1474    }
1475    switch (code) {
1476    case 'I':
1477       (void)new_include(jcr);
1478       break;
1479    case 'E':
1480       (void)new_exclude(jcr);
1481       break;
1482    case 'N':                             /* null */
1483       state = state_none;
1484       break;
1485    case 'F':                             /* file = */
1486       /* File item to include or exclude list */
1487       state = state_include;
1488       add_file_to_fileset(jcr, item, true);
1489       break;
1490    case 'P':                              /* plugin */
1491       /* Plugin item to include list */
1492       state = state_include;
1493       add_file_to_fileset(jcr, item, false);
1494       break;
1495    case 'R':                              /* regex */
1496       state = add_regex_to_fileset(jcr, item, subcode);
1497       break;
1498    case 'B':
1499       current_opts = start_options(ff);
1500       current_opts->base.append(bstrdup(item));
1501       state = state_options;
1502       break;
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));
1510       } else {
1511          state = state_error;
1512       }
1513       break;
1514    case 'W':                               /* wild cards */
1515       state = add_wild_to_fileset(jcr, item, subcode);
1516       break;
1517    case 'O':                                /* Options */
1518       state = add_options_to_fileset(jcr, item);
1519       break;
1520    case 'Z':                                /* ignore dir */
1521       state = state_include;
1522       fileset->incexe->ignoredir = bstrdup(item);
1523       break;
1524    case 'D':
1525       current_opts = start_options(ff);
1526 //    current_opts->reader = bstrdup(item); /* deprecated */
1527       state = state_options;
1528       break;
1529    case 'T':
1530       current_opts = start_options(ff);
1531 //    current_opts->writer = bstrdup(item); /* deprecated */
1532       state = state_options;
1533       break;
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;
1538       break;
1539    default:
1540       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1541       state = state_error;
1542       break;
1543    }
1544    ff->fileset->state = state;
1545 }
1546
1547 static bool term_fileset(JCR *jcr)
1548 {
1549    FF_PKT *ff = jcr->ff;
1550
1551 #ifdef xxx_DEBUG_CODE
1552    findFILESET *fileset = ff->fileset;
1553    int i, j, k;
1554
1555    for (i=0; i<fileset->include_list.size(); i++) {
1556       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1557       Dmsg0(400, "I\n");
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));
1562          }
1563          for (k=0; k<fo->regexdir.size(); k++) {
1564             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1565          }
1566          for (k=0; k<fo->regexfile.size(); k++) {
1567             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1568          }
1569          for (k=0; k<fo->wild.size(); k++) {
1570             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1571          }
1572          for (k=0; k<fo->wilddir.size(); k++) {
1573             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1574          }
1575          for (k=0; k<fo->wildfile.size(); k++) {
1576             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1577          }
1578          for (k=0; k<fo->wildbase.size(); k++) {
1579             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1580          }
1581          for (k=0; k<fo->base.size(); k++) {
1582             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1583          }
1584          for (k=0; k<fo->fstype.size(); k++) {
1585             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1586          }
1587          for (k=0; k<fo->drivetype.size(); k++) {
1588             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1589          }
1590       }
1591       if (incexe->ignoredir) {
1592          Dmsg1(400, "Z %s\n", incexe->ignoredir);
1593       }
1594       dlistString *node;
1595       foreach_dlist(node, &incexe->name_list) {
1596          Dmsg1(400, "F %s\n", node->c_str());
1597       }
1598       foreach_dlist(node, &incexe->plugin_list) {
1599          Dmsg1(400, "P %s\n", node->c_str());
1600       }
1601    }
1602    for (i=0; i<fileset->exclude_list.size(); i++) {
1603       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1604       Dmsg0(400, "E\n");
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));
1609          }
1610          for (k=0; k<fo->regexdir.size(); k++) {
1611             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1612          }
1613          for (k=0; k<fo->regexfile.size(); k++) {
1614             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1615          }
1616          for (k=0; k<fo->wild.size(); k++) {
1617             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1618          }
1619          for (k=0; k<fo->wilddir.size(); k++) {
1620             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1621          }
1622          for (k=0; k<fo->wildfile.size(); k++) {
1623             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1624          }
1625          for (k=0; k<fo->wildbase.size(); k++) {
1626             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1627          }
1628          for (k=0; k<fo->base.size(); k++) {
1629             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1630          }
1631          for (k=0; k<fo->fstype.size(); k++) {
1632             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1633          }
1634          for (k=0; k<fo->drivetype.size(); k++) {
1635             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1636          }
1637       }
1638       dlistString *node;
1639       foreach_dlist(node, &incexe->name_list) {
1640          Dmsg1(400, "F %s\n", node->c_str());
1641       }
1642       foreach_dlist(node, &incexe->plugin_list) {
1643          Dmsg1(400, "P %s\n", node->c_str());
1644       }
1645    }
1646 #endif
1647    return ff->fileset->state != state_error;
1648 }
1649
1650
1651 /**
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.
1655  */
1656 static int set_options(findFOPTS *fo, const char *opts)
1657 {
1658    int j;
1659    const char *p;
1660    char strip[100];
1661
1662 // Commented out as it is not backward compatible - KES
1663
1664    for (p=opts; *p; p++) {
1665       switch (*p) {
1666       case 'a':                 /* alway replace */
1667       case '0':                 /* no option */
1668          break;
1669       case 'e':
1670          fo->flags |= FO_EXCLUDE;
1671          break;
1672       case 'f':
1673          fo->flags |= FO_MULTIFS;
1674          break;
1675       case 'h':                 /* no recursion */
1676          fo->flags |= FO_NO_RECURSION;
1677          break;
1678       case 'H':                 /* no hard link handling */
1679          fo->flags |= FO_NO_HARDLINK;
1680          break;
1681       case 'i':
1682          fo->flags |= FO_IGNORECASE;
1683          break;
1684       case 'M':                 /* MD5 */
1685          fo->flags |= FO_MD5;
1686          break;
1687       case 'n':
1688          fo->flags |= FO_NOREPLACE;
1689          break;
1690       case 'p':                 /* use portable data format */
1691          fo->flags |= FO_PORTABLE;
1692          break;
1693       case 'R':                 /* Resource forks and Finder Info */
1694          fo->flags |= FO_HFSPLUS;
1695          break;
1696       case 'r':                 /* read fifo */
1697          fo->flags |= FO_READFIFO;
1698          break;
1699       case 'S':
1700          switch(*(p + 1)) {
1701          case '1':
1702             fo->flags |= FO_SHA1;
1703             p++;
1704             break;
1705 #ifdef HAVE_SHA2
1706          case '2':
1707             fo->flags |= FO_SHA256;
1708             p++;
1709             break;
1710          case '3':
1711             fo->flags |= FO_SHA512;
1712             p++;
1713             break;
1714 #endif
1715          default:
1716             /*
1717              * If 2 or 3 is seen here, SHA2 is not configured, so
1718              *  eat the option, and drop back to SHA-1.
1719              */
1720             if (p[1] == '2' || p[1] == '3') {
1721                p++;
1722             }
1723             fo->flags |= FO_SHA1;
1724             break;
1725          }
1726          break;
1727       case 's':
1728          fo->flags |= FO_SPARSE;
1729          break;
1730       case 'm':
1731          fo->flags |= FO_MTIMEONLY;
1732          break;
1733       case 'k':
1734          fo->flags |= FO_KEEPATIME;
1735          break;
1736       case 'A':
1737          fo->flags |= FO_ACL;
1738          break;
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) {
1744                j++;
1745             }
1746          }
1747          fo->VerifyOpts[j] = 0;
1748          break;
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) {
1754                j++;
1755             }
1756          }
1757          fo->AccurateOpts[j] = 0;
1758          break;
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) {
1764                j++;
1765             }
1766          }
1767          fo->BaseJobOpts[j] = 0;
1768          break;
1769       case 'P':                  /* strip path */
1770          /* Get integer */
1771          p++;                    /* skip P */
1772          for (j=0; *p && *p != ':'; p++) {
1773             strip[j] = *p;
1774             if (j < (int)sizeof(strip) - 1) {
1775                j++;
1776             }
1777          }
1778          strip[j] = 0;
1779          fo->strip_path = atoi(strip);
1780          fo->flags |= FO_STRIPPATH;
1781          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1782          break;
1783       case 'w':
1784          fo->flags |= FO_IF_NEWER;
1785          break;
1786       case 'W':
1787          fo->flags |= FO_ENHANCEDWILD;
1788          break;
1789       case 'Z':                 /* compression */
1790          p++;                   /* skip Z */
1791          if (*p >= '0' && *p <= '9') {
1792             fo->flags |= FO_COMPRESS;
1793             fo->Compress_algo = COMPRESS_GZIP;
1794             fo->Compress_level = *p - '0';
1795          }
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 */
1800          }
1801          break;
1802       case 'K':
1803          fo->flags |= FO_NOATIME;
1804          break;
1805       case 'c':
1806          fo->flags |= FO_CHKCHANGES;
1807          break;
1808       case 'N':
1809          fo->flags |= FO_HONOR_NODUMP;
1810          break;
1811       case 'X':
1812          fo->flags |= FO_XATTR;
1813          break;
1814       default:
1815          Jmsg1(NULL, M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1816          break;
1817       }
1818    }
1819    return state_options;
1820 }
1821
1822
1823 /**
1824  * Director is passing his Fileset
1825  */
1826 static int fileset_cmd(JCR *jcr)
1827 {
1828    POOL_MEM buf(PM_MESSAGE);
1829    BSOCK *dir = jcr->dir_bsock;
1830    int rtnstat;
1831
1832    jcr->Snapshot = (strstr(dir->msg, "snap=1") != NULL);
1833    if (!init_fileset(jcr)) {
1834       return 0;
1835    }
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());
1841    }
1842    if (!term_fileset(jcr)) {
1843       return 0;
1844    }
1845    rtnstat = dir->fsend(OKinc);
1846    generate_plugin_event(jcr, bEventEndFileSet);
1847    return rtnstat;
1848 }
1849
1850
1851 /*
1852  * The Director sends us the component info file, which
1853  *   we will in turn pass to the VSS plugin.
1854  */
1855 static int component_cmd(JCR *jcr)
1856 {
1857    BSOCK *dir = jcr->dir_bsock;
1858
1859    while (dir->recv() >= 0) {
1860        Dmsg1(200, "filed<dird: component: %s", dir->msg);
1861        generate_plugin_event(jcr, bEventComponentInfo, (void *)dir->msg);
1862    }
1863    return dir->fsend(OKComponentInfo);
1864 }
1865
1866
1867 /**
1868  * Get backup level from Director
1869  *
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.
1873  *
1874  */
1875 static int level_cmd(JCR *jcr)
1876 {
1877    BSOCK *dir = jcr->dir_bsock;
1878    POOLMEM *level, *buf = NULL;
1879    int mtime_only;
1880
1881    level = get_memory(dir->msglen+1);
1882    Dmsg1(10, "level_cmd: %s", dir->msg);
1883
1884    /* keep compatibility with older directors */
1885    if (strstr(dir->msg, "accurate")) {
1886       jcr->accurate = true;
1887    }
1888    if (strstr(dir->msg, "rerunning")) {
1889       jcr->rerunning = true;
1890    }
1891    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1892       goto bail_out;
1893    }
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);
1902       free_memory(level);
1903       return 1;
1904    } else if (strstr(level, "incremental")) {
1905       jcr->setJobLevel(L_INCREMENTAL);
1906       free_memory(level);
1907       return 1;
1908    /*
1909     * We get his UTC since time, then sync the clocks and correct it
1910     *   to agree with our clock.
1911     */
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 */
1918       }
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) {
1923             goto bail_out;
1924          }
1925       }
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];
1929       /*
1930        * Sync clocks by polling him for the time. We take
1931        *   10 samples of his time throwing out the first two.
1932        */
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 */
1937             goto bail_out;
1938          }
1939          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1940             goto bail_out;
1941          }
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;
1948             continue;
1949          }
1950          his_time_prev = his_time;
1951          n++;
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));
1956       }
1957       adj = 0;
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 */
1963       }
1964       /* Don't notify if time within 3 seconds */
1965       if (adj > 3 || adj < -3) {
1966          int type;
1967          if (adj > 600 || adj < -600) {
1968             type = M_WARNING;
1969          } else {
1970             type = M_INFO;
1971          }
1972          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1973       }
1974       dir->signal(BNET_EOD);
1975
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);
1980    } else {
1981       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1982       free_memory(level);
1983       return 0;
1984    }
1985    free_memory(level);
1986    if (buf) {
1987       free_memory(buf);
1988    }
1989    generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1990    return dir->fsend(OKlevel);
1991
1992 bail_out:
1993    pm_strcpy(jcr->errmsg, dir->msg);
1994    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1995    free_memory(level);
1996    if (buf) {
1997       free_memory(buf);
1998    }
1999    return 0;
2000 }
2001
2002 /**
2003  * Get session parameters from Director -- this is for a Restore command
2004  *   This is deprecated. It is now passed via the bsr.
2005  */
2006 static int session_cmd(JCR *jcr)
2007 {
2008    BSOCK *dir = jcr->dir_bsock;
2009
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);
2017       return 0;
2018    }
2019
2020    return dir->fsend(OKsession);
2021 }
2022
2023 static void set_storage_auth_key(JCR *jcr, char *key)
2024 {
2025    /* if no key don't update anything */
2026    if (!*key) {
2027       return;
2028    }
2029
2030    /**
2031     * We can be contacting multiple storage daemons.
2032     * So, make sure that any old jcr->store_bsock is cleaned up.
2033     */
2034    free_bsock(jcr->store_bsock);
2035
2036    /**
2037     * We can be contacting multiple storage daemons.
2038     *   So, make sure that any old jcr->sd_auth_key is cleaned up.
2039     */
2040    if (jcr->sd_auth_key) {
2041       /*
2042        * If we already have a Authorization key, director can do multi
2043        * storage restore
2044        */
2045       Dmsg0(5, "set multi_restore=true\n");
2046       jcr->multi_restore = true;
2047       bfree(jcr->sd_auth_key);
2048    }
2049
2050    jcr->sd_auth_key = bstrdup(key);
2051    Dmsg1(200, "set sd auth key %s\n", jcr->sd_auth_key);
2052 }
2053
2054 /**
2055  * Get address of storage daemon from Director
2056  *
2057  */
2058 static int storage_cmd(JCR *jcr)
2059 {
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;
2064    BSOCK *sd;
2065
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);
2077       goto bail_out;
2078    }
2079
2080
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;
2085
2086       } else if (me->max_bandwidth_per_job) {
2087          jcr->max_bandwidth = me->max_bandwidth_per_job;
2088       }
2089    }
2090
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,
2093             enable_ssl);
2094       jcr->sd_calls_client = false;
2095       sd = new_bsock();
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 */
2102          sd->destroy();
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);
2107          goto bail_out;
2108       }
2109
2110       Dmsg0(110, "Connection OK to SD.\n");
2111       jcr->store_bsock = sd;
2112    } else {                      /* The storage daemon called us */
2113       struct timeval tv;
2114       struct timezone tz;
2115       struct timespec timeout;
2116       int errstat;
2117
2118       free_bsock(jcr->store_bsock);
2119       jcr->sd_calls_client = true;
2120
2121       /*
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
2124        *  expires.
2125        */
2126       gettimeofday(&tv, &tz);
2127       timeout.tv_nsec = tv.tv_usec * 1000;
2128       timeout.tv_sec = tv.tv_sec + 30 * 60;  /* wait 30 minutes */
2129       P(mutex);
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) {
2133             break;
2134          }
2135          Dmsg1(800, "=== Auth cond errstat=%d\n", errstat);
2136       }
2137       V(mutex);
2138       Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr);
2139
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"));
2145          goto bail_out;
2146       }
2147       if (jcr->is_job_canceled()) {
2148          goto bail_out;
2149       }
2150       /* Assign the new socket to the main one */
2151       jcr->lock_auth();
2152       jcr->store_bsock = jcr->sd_calls_client_bsock;
2153       jcr->sd_calls_client_bsock = NULL;
2154       jcr->unlock_auth();
2155    }
2156    jcr->store_bsock->set_bwlimit(jcr->max_bandwidth);
2157
2158    if (!send_hello_sd(jcr, jcr->Job)) {
2159       goto bail_out;
2160    }
2161
2162    if (!authenticate_storagedaemon(jcr)) {
2163       goto bail_out;
2164    }
2165    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
2166    Dmsg0(110, "Authenticated with SD.\n");
2167
2168    /* Send OK to Director */
2169    return dir->fsend(OKstore);
2170
2171 bail_out:
2172    dir->fsend(BADcmd, "storage");
2173    return 0;
2174 }
2175
2176
2177 /*
2178  * Do a backup.
2179  */
2180 static int backup_cmd(JCR *jcr)
2181 {
2182    BSOCK *dir = jcr->dir_bsock;
2183    BSOCK *sd = jcr->store_bsock;
2184    int ok = 0;
2185    int SDJobStatus;
2186    int32_t FileIndex;
2187
2188    if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
2189       jcr->JobFiles = FileIndex;
2190       Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
2191    }
2192
2193    /*
2194     * If explicitly requesting FO_ACL or FO_XATTR, fail job if it
2195     *  is not available on Client machine
2196     */ 
2197    if (jcr->ff->flags & FO_ACL && !(have_acl)) {
2198       Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for Client.\n"));
2199       goto cleanup; 
2200    } 
2201    if (jcr->ff->flags & FO_XATTR && !have_xattr) { 
2202       Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for Client.\n"));
2203       goto cleanup; 
2204    } 
2205    jcr->setJobStatus(JS_Blocked);
2206    jcr->setJobType(JT_BACKUP);
2207    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
2208    if (sd == NULL) {
2209       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
2210       dir->fsend(BADcmd, "backup");
2211       goto cleanup;
2212    }
2213
2214    dir->fsend(OKbackup);
2215    Dmsg1(110, "filed>dird: %s", dir->msg);
2216
2217    /*
2218     * Send Append Open Session to Storage daemon
2219     */
2220    sd->fsend(append_open);
2221    Dmsg1(110, ">stored: %s", sd->msg);
2222    /**
2223     * Expect to receive back the Ticket number
2224     */
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);
2229          goto cleanup;
2230       }
2231       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
2232    } else {
2233       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
2234       goto cleanup;
2235    }
2236
2237    /**
2238     * Send Append data command to Storage daemon
2239     */
2240    sd->fsend(append_data, jcr->Ticket);
2241    Dmsg1(110, ">stored: %s", sd->msg);
2242
2243    /**
2244     * Expect to get OK data
2245     */
2246    Dmsg1(110, "<stored: %s", sd->msg);
2247    if (!response(jcr, sd, OK_data, "Append Data")) {
2248       goto cleanup;
2249    }
2250
2251    generate_daemon_event(jcr, "JobStart");
2252    generate_plugin_event(jcr, bEventStartBackupJob);
2253
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);
2258    }
2259    /* Call RunScript just after the Snapshot creation, usually, we restart services */
2260    run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2261
2262    /*
2263     * Send Files to Storage daemon
2264     */
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");
2270    } else {
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 */
2276       }
2277       /**
2278        * Expect to get response to append_data from Storage daemon
2279        */
2280       if (!response(jcr, sd, OK_append, "Append Data")) {
2281          jcr->setJobStatus(JS_ErrorTerminated);
2282          goto cleanup;
2283       }
2284
2285       /**
2286        * Send Append End Data to Storage daemon
2287        */
2288       sd->fsend(append_end, jcr->Ticket);
2289       /* Get end OK */
2290       if (!response(jcr, sd, OK_end, "Append End")) {
2291          jcr->setJobStatus(JS_ErrorTerminated);
2292          goto cleanup;
2293       }
2294
2295       /**
2296        * Send Append Close to Storage daemon
2297        */
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) {
2301             ok = 1;
2302             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
2303          }
2304       }
2305       if (!ok) {
2306          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
2307          goto cleanup;
2308       }
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);
2313       }
2314    }
2315
2316 cleanup:
2317    generate_plugin_event(jcr, bEventEndBackupJob);
2318    return 0;                          /* return and stop command loop */
2319 }
2320
2321 /**
2322  * Do a Verify for Director
2323  *
2324  */
2325 static int verify_cmd(JCR *jcr)
2326 {
2327    BSOCK *dir = jcr->dir_bsock;
2328    BSOCK *sd  = jcr->store_bsock;
2329    char level[100];
2330
2331    jcr->setJobType(JT_VERIFY);
2332    if (sscanf(dir->msg, verifycmd, level) != 1) {
2333       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2334       return 0;
2335    }
2336
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);
2347    } else {
2348       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2349       return 0;
2350    }
2351
2352    dir->fsend(OKverify);
2353
2354    generate_daemon_event(jcr, "JobStart");
2355    generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2356    generate_plugin_event(jcr, bEventStartVerifyJob);
2357
2358    Dmsg1(110, "filed>dird: %s", dir->msg);
2359
2360    switch (jcr->getJobLevel()) {
2361    case L_VERIFY_INIT:
2362    case L_VERIFY_CATALOG:
2363       do_verify(jcr);
2364       break;
2365    case L_VERIFY_DATA:
2366    case L_VERIFY_VOLUME_TO_CATALOG:
2367       if (!open_sd_read_session(jcr)) {
2368          return 0;
2369       }
2370       start_dir_heartbeat(jcr);
2371       do_verify_volume(jcr);
2372       stop_dir_heartbeat(jcr);
2373       /*
2374        * Send Close session command to Storage daemon
2375        */
2376       sd->fsend(read_close, jcr->Ticket);
2377       Dmsg1(130, "filed>stored: %s", sd->msg);
2378
2379       /* ****FIXME**** check response */
2380       bget_msg(sd);                      /* get OK */
2381
2382       /* Inform Storage daemon that we are done */
2383       sd->signal(BNET_TERMINATE);
2384
2385       break;
2386    case L_VERIFY_DISK_TO_CATALOG:
2387       do_verify(jcr);
2388       break;
2389    default:
2390       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2391       return 0;
2392    }
2393
2394    dir->signal(BNET_EOD);
2395    generate_plugin_event(jcr, bEventEndVerifyJob);
2396    return 0;                          /* return and terminate command loop */
2397 }
2398
2399 /*
2400  * Do a Restore for Director
2401  *
2402  */
2403 static int restore_cmd(JCR *jcr)
2404 {
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;
2409    int prefix_links;
2410    char replace;
2411    bool scan_ok = true;
2412    int files;
2413    int ret = 0;
2414
2415    /**
2416     * Scan WHERE (base directory for restore) from command
2417     */
2418    Dmsg0(100, "restore command\n");
2419
2420    /* Pickup where string */
2421    args = get_memory(dir->msglen+1);
2422    *args = 0;
2423
2424    restore_where = get_pool_memory(PM_FNAME);
2425    restore_rwhere = get_pool_memory(PM_FNAME);
2426
2427    /* We don't know the size of where/rwhere in advance,
2428     * where= -> where=%202s\n
2429     */
2430    Mmsg(restore_where, "%s%%%ds\n", restorefcmd, dir->msglen);
2431    Mmsg(restore_rwhere, "%s%%%ds\n", restorefcmdR, dir->msglen);
2432
2433    Dmsg2(200, "where=%srwhere=%s", restore_where, restore_rwhere);
2434
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) {
2439             scan_ok = false;
2440          }
2441          *args = 0;             /* No where argument */
2442       } else {
2443          use_regexwhere = true;
2444       }
2445    }
2446
2447    if (scan_ok) {
2448       jcr->ExpectedFiles = files;
2449    } else {
2450       /* Scan for old form without number of files */
2451       jcr->ExpectedFiles = 0;
2452
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);
2456
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);
2462                goto free_mempool;
2463             }
2464             *args = 0;          /* No where argument */
2465          } else {
2466             use_regexwhere = true;
2467          }
2468       }
2469    }
2470
2471    /* Turn / into nothing */
2472    if (IsPathSeparator(args[0]) && args[1] == '\0') {
2473       args[0] = '\0';
2474    }
2475
2476    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2477    unbash_spaces(args);
2478
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;
2482    }
2483
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);
2488          goto free_mempool;
2489       }
2490    } else {
2491       jcr->where = bstrdup(args);
2492    }
2493
2494    jcr->replace = replace;
2495    jcr->prefix_links = prefix_links;
2496
2497    dir->fsend(OKrestore);
2498    Dmsg1(110, "filed>dird: %s", dir->msg);
2499
2500    jcr->setJobType(JT_RESTORE);
2501
2502    jcr->setJobStatus(JS_Blocked);
2503
2504    if (!open_sd_read_session(jcr)) {
2505       jcr->setJobStatus(JS_ErrorTerminated);
2506       goto bail_out;
2507    }
2508
2509    jcr->setJobStatus(JS_Running);
2510
2511    /**
2512     * Do restore of files and data
2513     */
2514    start_dir_heartbeat(jcr);
2515    generate_daemon_event(jcr, "JobStart");
2516    generate_plugin_event(jcr, bEventStartRestoreJob);
2517
2518    if (!jcr->is_canceled()) {
2519       do_restore(jcr);
2520    }
2521
2522    stop_dir_heartbeat(jcr);
2523
2524    jcr->setJobStatus(JS_Terminated);
2525    if (jcr->JobStatus != JS_Terminated) {
2526       sd->suppress_error_messages(true);
2527    }
2528
2529    /**
2530     * Send Close session command to Storage daemon
2531     */
2532    sd->fsend(read_close, jcr->Ticket);
2533    Dmsg1(100, "filed>stored: %s", sd->msg);
2534
2535    bget_msg(sd);                      /* get OK */
2536
2537    /* Inform Storage daemon that we are done */
2538    sd->signal(BNET_TERMINATE);
2539
2540 bail_out:
2541    bfree_and_null(jcr->where);
2542
2543    if (jcr->JobErrors) {
2544       jcr->setJobStatus(JS_ErrorTerminated);
2545    }
2546
2547    Dmsg0(100, "Done in job.c\n");
2548
2549    if (jcr->multi_restore) {
2550       Dmsg0(100, OKstoreend);
2551       dir->fsend(OKstoreend);
2552       ret = 1;     /* we continue the loop, waiting for next part */
2553    } else {
2554       ret = 0;     /* we stop here */
2555    }
2556
2557    if (job_canceled(jcr)) {
2558       ret = 0;     /* we stop here */
2559    }
2560
2561    if (ret == 0) {
2562       end_restore_cmd(jcr);  /* stopping so send bEventEndRestoreJob */
2563    }
2564
2565 free_mempool:
2566    free_and_null_pool_memory(args);
2567    free_and_null_pool_memory(restore_where);
2568    free_and_null_pool_memory(restore_rwhere);
2569
2570    return ret;
2571 }
2572
2573 static int end_restore_cmd(JCR *jcr)
2574 {
2575    Dmsg0(5, "end_restore_cmd\n");
2576    generate_plugin_event(jcr, bEventEndRestoreJob);
2577    return 0;                          /* return and terminate command loop */
2578 }
2579
2580 static int open_sd_read_session(JCR *jcr)
2581 {
2582    BSOCK *sd = jcr->store_bsock;
2583
2584    if (!sd) {
2585       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2586       return 0;
2587    }
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");
2591    /*
2592     * Open Read Session with Storage daemon
2593     */
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);
2598
2599    /*
2600     * Get ticket number
2601     */
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);
2606          return 0;
2607       }
2608       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2609    } else {
2610       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2611       return 0;
2612    }
2613
2614    /*
2615     * Use interactive session for the current restore
2616     */
2617    if (jcr->interactive_session) {
2618       sd->fsend(read_ctrl, jcr->Ticket);
2619       Dmsg1(110, ">stored: %s", sd->msg);
2620    }
2621
2622    /*
2623     * Start read of data with Storage daemon
2624     */
2625    sd->fsend(read_data, jcr->Ticket);
2626    Dmsg1(110, ">stored: %s", sd->msg);
2627
2628    /*
2629     * Get OK data
2630     */
2631    if (!response(jcr, sd, OK_data, "Read Data")) {
2632       return 0;
2633    }
2634    return 1;
2635 }
2636
2637 /**
2638  * Destroy the Job Control Record and associated
2639  * resources (sockets).
2640  */
2641 static void filed_free_jcr(JCR *jcr)
2642 {
2643    if (jcr->dir_bsock) {
2644       free_bsock(jcr->dir_bsock);
2645       jcr->dir_bsock = NULL;
2646    }
2647    if (jcr->sd_calls_client_bsock) {
2648       free_bsock(jcr->sd_calls_client_bsock);
2649       jcr->sd_calls_client_bsock = NULL;
2650    }
2651    if (jcr->store_bsock) {
2652       free_bsock(jcr->store_bsock);
2653       jcr->store_bsock = NULL;
2654    }
2655    if (jcr->last_fname) {
2656       free_pool_memory(jcr->last_fname);
2657    }
2658    free_plugins(jcr);                 /* release instantiated plugins */
2659    free_runscripts(jcr->RunScripts);
2660    delete jcr->RunScripts;
2661    free_path_list(jcr);
2662
2663    if (jcr->JobId != 0) {
2664       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2665    }
2666    return;
2667 }
2668
2669 /**
2670  * Get response from Storage daemon to a command we
2671  * sent. Check that the response is OK.
2672  *
2673  *  Returns: 0 on failure
2674  *           1 on success
2675  */
2676 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2677 {
2678    int ret;
2679
2680    if (sd->errors) {
2681       return 0;
2682    }
2683    if ((ret = bget_msg(sd)) > 0) {
2684       Dmsg0(110, sd->msg);
2685       if (strcmp(sd->msg, resp) == 0) {
2686          return 1;
2687       }
2688    }
2689    if (job_canceled(jcr)) {
2690       return 0;                       /* if canceled avoid useless error messages */
2691    }
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());
2695    } else {
2696       char buf[256];
2697       if (ret > 0) {
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)));
2700       } else {
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));
2703       }
2704    }
2705    return 0;
2706 }