]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Restore win32 dir from Branch-5.2 and update it
[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 #ifdef WIN32_VSS
29 #include "vss.h"
30 static pthread_mutex_t vss_mutex = PTHREAD_MUTEX_INITIALIZER;
31 #endif
32
33 /* Globals */
34 bool win32decomp = false;
35 bool no_win32_write_errors = false;
36
37 /* Static variables */
38 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
39
40 #ifdef HAVE_WIN32
41 const bool have_win32 = true;
42 #else 
43 const bool have_win32 = false;
44 #endif
45
46 #ifdef HAVE_ACL
47 const bool have_acl = true; 
48 #else 
49 const bool have_acl = false; 
50 #endif 
51
52 #if HAVE_XATTR
53 const bool have_xattr = true; 
54 #else 
55 const bool have_xattr = false; 
56 #endif 
57  
58 extern CLIENT *me;                    /* our client resource */
59
60 /* Imported functions */
61 extern int status_cmd(JCR *jcr);
62 extern int qstatus_cmd(JCR *jcr);
63 extern int accurate_cmd(JCR *jcr);
64
65 /* Forward referenced functions */
66 static int backup_cmd(JCR *jcr);
67 static int component_cmd(JCR *jcr);
68 static int cancel_cmd(JCR *jcr);
69 static int setdebug_cmd(JCR *jcr);
70 static int setbandwidth_cmd(JCR *jcr);
71 static int estimate_cmd(JCR *jcr);
72 static int hello_cmd(JCR *jcr);
73 static int job_cmd(JCR *jcr);
74 static int fileset_cmd(JCR *jcr);
75 static int level_cmd(JCR *jcr);
76 static int verify_cmd(JCR *jcr);
77 static int restore_cmd(JCR *jcr);
78 static int end_restore_cmd(JCR *jcr);
79 static int storage_cmd(JCR *jcr);
80 static int session_cmd(JCR *jcr);
81 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
82 static void filed_free_jcr(JCR *jcr);
83 static int open_sd_read_session(JCR *jcr);
84 static int runscript_cmd(JCR *jcr);
85 static int runbefore_cmd(JCR *jcr);
86 static int runafter_cmd(JCR *jcr);
87 static int runbeforenow_cmd(JCR *jcr);
88 static int restore_object_cmd(JCR *jcr);
89 static int set_options(findFOPTS *fo, const char *opts);
90 static void set_storage_auth_key(JCR *jcr, char *key);
91 static int sm_dump_cmd(JCR *jcr);
92 static int proxy_cmd(JCR *jcr);
93 static int fd_testnetwork_cmd(JCR *jcr);
94 #ifdef DEVELOPER
95 static int exit_cmd(JCR *jcr);
96 #endif
97
98 /* Exported functions */
99
100 #define ACCESS_MONITOR    1
101 #define ACCESS_REMOTE     2
102
103 /*
104  * The following are the recognized commands from the Director.
105  */
106 struct s_cmds cmds[] = {
107    {"backup",       backup_cmd,    0},
108    {"cancel",       cancel_cmd,    ACCESS_REMOTE},
109    {"setdebug=",    setdebug_cmd,  0},
110    {"setbandwidth=",setbandwidth_cmd, ACCESS_REMOTE},
111    {"snapshot",     snapshot_cmd,  0},
112    {"estimate",     estimate_cmd,  0},
113    {"Hello",        hello_cmd,     1},
114    {"fileset",      fileset_cmd,   0},
115    {"JobId=",       job_cmd,       0},
116    {"level = ",     level_cmd,     0},
117    {"restore ",     restore_cmd,   0},
118    {"endrestore",   end_restore_cmd, 0},
119    {"session",      session_cmd,   0},
120    {"status",       status_cmd,    ACCESS_MONITOR|ACCESS_REMOTE},
121    {".status",      qstatus_cmd,   ACCESS_MONITOR|ACCESS_REMOTE},
122    {"storage ",     storage_cmd,   0},
123    {"verify",       verify_cmd,    0},
124    {"component",    component_cmd, 0},
125    {"RunBeforeNow", runbeforenow_cmd, 0},
126    {"RunBeforeJob", runbefore_cmd, 0},
127    {"RunAfterJob",  runafter_cmd,  0},
128    {"Run",          runscript_cmd, 0},
129    {"accurate",     accurate_cmd,  0},
130    {"restoreobject", restore_object_cmd, 0},
131    {"sm_dump",      sm_dump_cmd, 0},
132    {"stop",         cancel_cmd,  ACCESS_REMOTE},
133    {"proxy",        proxy_cmd,   ACCESS_REMOTE},
134    {"testnetwork",  fd_testnetwork_cmd, 0},
135 #ifdef DEVELOPER
136    {"exit",         exit_cmd, 0},
137 #endif
138    {NULL,       NULL}                  /* list terminator */
139 };
140
141 /* Commands received from director that need scanning */
142 static char jobcmd[]      = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
143 static char storaddr[]    = "storage address=%s port=%d ssl=%d Authorization=%100s";
144 static char storaddr_v1[] = "storage address=%s port=%d ssl=%d";
145 static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
146
147 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
148 static char restorefcmd1[] = "restore files=%d replace=%c prelinks=%d where=\n";
149
150 /* The following restore commands may have a big where=/regexwhere= parameter
151  * the bsscanf is limiting the default %s to 1000c. To allow more than 1000 bytes,
152  * we can specify %xxxxs where xxxx is the size expected in bytes.
153  *
154  * So, the code will add %s\n to the end of the following restore commands
155  */
156 static char restorecmd[]  = "restore replace=%c prelinks=%d where=";
157 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=";
158 static char restorefcmd[]  = "restore files=%d replace=%c prelinks=%d where=";
159 static char restorefcmdR[] = "restore files=%d replace=%c prelinks=%d regexwhere=";
160
161 static char restoreobjcmd[]  = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d,%s";
162 static char restoreobjcmd1[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
163 static char endrestoreobjectcmd[] = "restoreobject end\n";
164 static char verifycmd[]   = "verify level=%30s";
165 static char estimatecmd[] = "estimate listing=%d";
166 static char runbefore[]   = "RunBeforeJob %s";
167 static char runafter[]    = "RunAfterJob %s";
168 static char runscript[]   = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
169 static char setbandwidth[]= "setbandwidth=%lld Job=%127s";
170
171 /* Responses sent to Director */
172 static char errmsg[]      = "2999 Invalid command\n";
173 static char no_auth[]     = "2998 No Authorization\n";
174 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
175 static char OKBandwidth[] = "2000 OK Bandwidth\n";
176 static char OKinc[]       = "2000 OK include\n";
177 static char OKest[]       = "2000 OK estimate files=%s bytes=%s\n";
178 static char OKlevel[]     = "2000 OK level\n";
179 static char OKbackup[]    = "2000 OK backup\n";
180 static char OKverify[]    = "2000 OK verify\n";
181 static char OKrestore[]   = "2000 OK restore\n";
182 static char OKsession[]   = "2000 OK session\n";
183 static char OKstore[]     = "2000 OK storage\n";
184 static char OKstoreend[]  = "2000 OK storage end\n";
185 static char OKjob[]       = "2000 OK Job %s (%s) %s,%s,%s";
186 static char OKsetdebug[]  = "2000 OK setdebug=%ld trace=%ld hangup=%ld"
187                             " blowup=%ld options=%s tags=%s\n";
188 static char BADjob[]      = "2901 Bad Job\n";
189 static char EndJob[]      = "2800 End Job TermCode=%d JobFiles=%d ReadBytes=%lld"
190                             " JobBytes=%lld Errors=%d VSS=%d Encrypt=%d"
191                             " CommBytes=%lld CompressCommBytes=%lld\n";
192 static char OKRunBefore[] = "2000 OK RunBefore\n";
193 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
194 static char OKRunAfter[]  = "2000 OK RunAfter\n";
195 static char OKRunScript[] = "2000 OK RunScript\n";
196 static char BADcmd[]      = "2902 Bad %s\n";
197 static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
198 static char OKComponentInfo[] = "2000 OK ComponentInfo\n";
199
200
201 /* Responses received from Storage Daemon */
202 static char OK_end[]       = "3000 OK end\n";
203 static char OK_close[]     = "3000 OK close Status = %d\n";
204 static char OK_open[]      = "3000 OK open ticket = %d\n";
205 static char OK_data[]      = "3000 OK data\n";
206 static char OK_append[]    = "3000 OK append data\n";
207
208
209 /* Commands sent to Storage Daemon */
210 static char append_open[]  = "append open session\n";
211 static char append_data[]  = "append data %d\n";
212 static char append_end[]   = "append end session %d\n";
213 static char append_close[] = "append close session %d\n";
214 static char read_open[]    = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
215 static char read_data[]    = "read data %d\n";
216 static char read_close[]   = "read close session %d\n";
217 static char read_ctrl[]    = "read control %d\n";
218
219 /* Should tell us if a command is authorized or not */
220 static bool access_ok(struct s_cmds *cmd, DIRRES* dir)
221 {
222    if ((cmd->access & ACCESS_MONITOR) && dir->monitor) {
223       return true;
224    }
225    if ((cmd->access & ACCESS_REMOTE) && dir->remote) {
226       return true;
227    }
228    if (!dir->remote && !dir->monitor) {
229       return true;
230    }
231    return false;
232 }
233
234 /*
235  * Accept requests from a Director
236  *
237  * NOTE! We are running as a separate thread
238  *
239  * Send output one line
240  * at a time followed by a zero length transmission.
241  *
242  * Return when the connection is terminated or there
243  * is an error.
244  *
245  * Basic task here is:
246  *   Authenticate Director (during Hello command).
247  *   Accept commands one at a time from the Director
248  *     and execute them.
249  *
250  * Concerning ClientRunBefore/After, the sequence of events
251  * is rather critical. If they are not done in the right
252  * order one can easily get FD->SD timeouts if the script
253  * runs a long time.
254  *
255  * The current sequence of events is:
256  *  1. Dir starts job with FD
257  *  2. Dir connects to SD
258  *  3. Dir connects to FD
259  *  4. FD connects to SD
260  *  5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
261  *  6. Dir sends include/exclude
262  *  7. FD sends the file data to SD
263  *  8. SD/FD disconnects while the SD despools data and attributes (optional)
264  *  9. FD runs ClientRunAfterJob
265  */
266
267 static void *handle_director_request(BSOCK *dir)
268 {
269    int i;
270    bool found, quit;
271    bool first = true;
272    JCR *jcr;
273    const char jobname[12] = "*Director*";
274
275    prevent_os_suspensions();   /* do not suspend during backup/restore */
276    jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
277    jcr->sd_calls_client_bsock = NULL;
278    jcr->sd_calls_client = false;
279    jcr->dir_bsock = dir;
280    jcr->ff = init_find_files();
281    jcr->start_time = time(NULL);
282    jcr->RunScripts = New(alist(10, not_owned_by_alist));
283    jcr->last_fname = get_pool_memory(PM_FNAME);
284    jcr->last_fname[0] = 0;
285    jcr->client_name = get_memory(strlen(my_name) + 1);
286    pm_strcpy(jcr->client_name, my_name);
287    bstrncpy(jcr->Job, jobname, sizeof(jobname));  /* dummy */
288    jcr->crypto.pki_sign = me->pki_sign;
289    jcr->crypto.pki_encrypt = me->pki_encrypt;
290    jcr->crypto.pki_keypair = me->pki_keypair;
291    jcr->crypto.pki_signers = me->pki_signers;
292    jcr->crypto.pki_recipients = me->pki_recipients;
293
294    dir->set_jcr(jcr);
295    jcr->set_killable(true);    /* allow dir to kill/cancel job */
296    /* Initialize SD start condition variable */
297    int errstat = pthread_cond_init(&jcr->job_start_wait, NULL);
298    if (errstat != 0) {
299       berrno be;
300       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat));
301       goto bail_out;
302    }
303    enable_backup_privileges(NULL, 1 /* ignore_errors */);
304
305    for (quit=false; !quit;) {
306       if (!first) {      /* first call the read is done */
307          /* Read command */
308          if (dir->recv() < 0) {
309             break;               /* connection terminated */
310          }
311       }
312       if (dir->msglen == 0) {    /* Bad connection */
313          break;
314       }
315       first = false;
316       dir->msg[dir->msglen] = 0;
317       Dmsg1(100, "<dird: %s", dir->msg);
318       found = false;
319       for (i=0; cmds[i].cmd; i++) {
320          if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
321             found = true;         /* indicate command found */
322             if (!jcr->authenticated && cmds[i].func != hello_cmd) {
323                dir->fsend(no_auth);
324                dir->signal(BNET_EOD);
325                break;
326             }
327             if (jcr->authenticated && !access_ok(&cmds[i], jcr->director)) {
328                Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
329                dir->fsend(invalid_cmd);
330                dir->signal(BNET_EOD);
331                break;
332             }
333             if ((me->disabled_cmds_array && me->disabled_cmds_array[i]) ||
334                 (jcr->director && jcr->director->disabled_cmds_array &&
335                  jcr->director->disabled_cmds_array[i])) {
336                 Jmsg(jcr, M_FATAL, 0, _("Command: \"%s\" is disabled.\n"), cmds[i].cmd);
337                 quit = true;
338                 break;
339             }
340             Dmsg2(100, "Executing %s Dir %s command.\n", cmds[i].cmd, dir->msg);
341             if (!cmds[i].func(jcr)) {         /* do command */
342                quit = true;         /* error or fully terminated, get out */
343                Dmsg1(100, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
344             }
345             break;
346          }
347       }
348       if (!found) {              /* command not found */
349          dir->fsend(errmsg);
350          quit = true;
351          break;
352       }
353    }
354
355    /* Inform Storage daemon that we are done */
356    if (jcr->store_bsock) {
357       jcr->store_bsock->signal(BNET_TERMINATE);
358    }
359
360    /* Run the after job */
361    run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
362
363    /* send any queued messages before reporting the jobstatus to the director */
364    dequeue_messages(jcr);
365
366    if (jcr->JobId) {            /* send EndJob if running a job */
367       uint64_t CommBytes, CommCompressedBytes;
368       uint32_t vss, encrypt;
369       /* Send termination status back to Dir */
370       if (jcr->store_bsock) {
371          CommBytes = jcr->store_bsock->CommBytes();
372          CommCompressedBytes = jcr->store_bsock->CommCompressedBytes();
373       } else {
374          CommBytes = CommCompressedBytes = 0;
375       }
376       encrypt = jcr->crypto.pki_encrypt;
377       vss = jcr->Snapshot;
378       dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles,
379               jcr->ReadBytes, jcr->JobBytes, jcr->JobErrors, vss,
380               encrypt, CommBytes, CommCompressedBytes);
381       //Dmsg0(0, dir->msg);
382    }
383
384    generate_daemon_event(jcr, "JobEnd");
385    generate_plugin_event(jcr, bEventJobEnd);
386
387 bail_out:
388    dequeue_messages(jcr);  /* send any queued messages, will no longer impact
389                             * the job status... */
390
391    /* Inform Director that we are done */
392    dir->signal(BNET_TERMINATE);
393
394    free_and_null_pool_memory(jcr->job_metadata);
395
396    /* Clean up fileset */
397    FF_PKT *ff = jcr->ff;
398    findFILESET *fileset = ff->fileset;
399    if (fileset) {
400       int i, j, k;
401       /* Delete FileSet Include lists */
402       for (i=0; i<fileset->include_list.size(); i++) {
403          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
404          for (j=0; j<incexe->opts_list.size(); j++) {
405             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
406             if (fo->plugin) {
407                free(fo->plugin);
408             }
409             for (k=0; k<fo->regex.size(); k++) {
410                regfree((regex_t *)fo->regex.get(k));
411             }
412             for (k=0; k<fo->regexdir.size(); k++) {
413                regfree((regex_t *)fo->regexdir.get(k));
414             }
415             for (k=0; k<fo->regexfile.size(); k++) {
416                regfree((regex_t *)fo->regexfile.get(k));
417             }
418             fo->regex.destroy();
419             fo->regexdir.destroy();
420             fo->regexfile.destroy();
421             fo->wild.destroy();
422             fo->wilddir.destroy();
423             fo->wildfile.destroy();
424             fo->wildbase.destroy();
425             fo->base.destroy();
426             fo->fstype.destroy();
427             fo->drivetype.destroy();
428          }
429          incexe->opts_list.destroy();
430          incexe->name_list.destroy();
431          incexe->plugin_list.destroy();
432          if (incexe->ignoredir) {
433             free(incexe->ignoredir);
434          }
435       }
436       fileset->include_list.destroy();
437
438       /* Delete FileSet Exclude lists */
439       for (i=0; i<fileset->exclude_list.size(); i++) {
440          findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
441          for (j=0; j<incexe->opts_list.size(); j++) {
442             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
443             fo->regex.destroy();
444             fo->regexdir.destroy();
445             fo->regexfile.destroy();
446             fo->wild.destroy();
447             fo->wilddir.destroy();
448             fo->wildfile.destroy();
449             fo->wildbase.destroy();
450             fo->base.destroy();
451             fo->fstype.destroy();
452             fo->drivetype.destroy();
453          }
454          incexe->opts_list.destroy();
455          incexe->name_list.destroy();
456          incexe->plugin_list.destroy();
457          if (incexe->ignoredir) {
458             free(incexe->ignoredir);
459          }
460       }
461       fileset->exclude_list.destroy();
462       free(fileset);
463    }
464    ff->fileset = NULL;
465    ff->mount_points.destroy();
466    Dmsg0(100, "Calling term_find_files\n");
467    term_find_files(jcr->ff);
468    jcr->ff = NULL;
469    Dmsg0(100, "Done with term_find_files\n");
470    pthread_cond_destroy(&jcr->job_start_wait);
471    free_jcr(jcr);                     /* destroy JCR record */
472    Dmsg0(100, "Done with free_jcr\n");
473    allow_os_suspensions();            /* FD can now be suspended */
474    Dsm_check(100);
475    garbage_collect_memory_pool();
476    return NULL;
477 }
478
479
480 /*
481  * Accept requests from a Director or a Storage daemon
482  */
483 void *handle_connection_request(void *caller)
484 {
485    BSOCK *bs = (BSOCK *)caller;
486
487    if (bs->recv() > 0) {
488       if (strncmp(bs->msg, "Ping", 4) == 0) {
489          bs->fsend("2000 Ping OK\n");
490          bs->destroy();
491          return NULL;
492       }
493       if (bs->msglen < 25 || bs->msglen > 500) {
494          goto bail_out;
495       }
496       if (strncmp(bs->msg, "Hello FD: Bacula Storage", 20) ==0) {
497          return handle_storage_connection(bs);
498       }
499       if (strncmp(bs->msg, "Hello ", 5) == 0) {
500          return handle_director_request(bs);
501       }
502    }
503 bail_out:
504    Dmsg2(100, "Bad command from %s. Len=%d.\n", bs->who(), bs->msglen);
505    char addr[64];
506    char *who = bs->get_peer(addr, sizeof(addr)) ? bs->who() : addr;
507    Jmsg2(NULL, M_FATAL, 0, _("Bad command from %s. Len=%d.\n"), who, bs->msglen);
508    bs->destroy();
509    return NULL;
510 }
511
512
513 /* 
514  * Test the Network between FD/SD
515  */
516 static int fd_testnetwork_cmd(JCR *jcr)
517 {
518    bool can_compress, ok=true;
519    BSOCK *sd = jcr->store_bsock;
520    int64_t nb=0, nb2=0;
521    char ed1[50];
522    btime_t start, end;
523
524    if (!sd || !jcr->dir_bsock) {
525       return 1;
526    }
527    if (sscanf(jcr->dir_bsock->msg, "testnetwork bytes=%lld", &nb) != 1 || nb <= 0) {
528       sd->fsend("2999 testnetwork command error\n");
529       return 1;
530    }
531
532    /* We disable the comline compression, else all numbers will be wrong */
533    can_compress = sd->can_compress();
534
535    sd->fsend("testnetwork bytes=%lld\n", nb);
536    sd->clear_compress();
537
538    /* In the first step, we send X bytes to the SD */
539    memset(sd->msg, 0xAA, sizeof_pool_memory(sd->msg));
540    sd->msglen = sizeof_pool_memory(sd->msg);
541
542    start = get_current_btime();
543    for (nb2 = nb ; nb2 > 0 && ok ; nb2 -= sd->msglen) {
544       if (nb2 < sd->msglen) {
545          sd->msglen = nb2;
546       }
547       ok = sd->send();
548    }
549    sd->signal(BNET_EOD);
550    end = get_current_btime() + 1;
551
552    if (!ok) {
553       goto bail_out;
554    }
555
556    jcr->dir_bsock->fsend("2000 OK bytes=%lld duration=%lldms write_speed=%sB/s\n",
557                          nb, end/1000 - start/1000,
558                          edit_uint64_with_suffix(nb * 1000000 / (end - start), ed1));
559
560    /* Now we receive X bytes from the SD */
561    start = get_current_btime();
562    for (nb2 = 0; sd->recv() > 0; nb2 += sd->msglen) { }
563    end = get_current_btime() + 1;
564
565    jcr->dir_bsock->fsend("2000 OK bytes=%lld duration=%lldms read_speed=%sB/s\n",
566                          nb2, end/1000 - start/1000,
567                          edit_uint64_with_suffix(nb2 * 1000000 / (end - start), ed1));
568
569    jcr->dir_bsock->signal(BNET_CMD_OK);
570
571 bail_out:
572    if (can_compress) {
573       sd->set_compress();
574    }
575    if (!ok) {
576       jcr->dir_bsock->fsend("2999 network test failed ERR=%s\n", sd->errmsg);
577       jcr->dir_bsock->signal(BNET_CMD_FAILED);
578    }
579
580    return 1;
581 }
582
583 static int proxy_cmd(JCR *jcr)
584 {
585    bool OK=true, fdcalled = false;
586    BSOCK *cons_bsock;
587    CONSRES *cons = jcr->director->console;
588    int v, maxfd;
589    fd_set fdset;
590    struct timeval tv;
591
592    if (!cons) {
593       cons = (CONSRES *)GetNextRes(R_CONSOLE, NULL);
594    }
595    /* Here, dir_bsock is not really the director, this is a console */
596    cons_bsock = connect_director(jcr, cons);
597    if (!cons_bsock) {
598       jcr->dir_bsock->signal(BNET_ERROR_MSG);
599       jcr->dir_bsock->fsend("2999 proxy error. ERR=%s\n", jcr->errmsg);
600       jcr->dir_bsock->signal(BNET_MAIN_PROMPT);
601       /* Error during the connect */
602       return 1;
603    }
604
605    /* Inform the console that the command is OK */
606    jcr->dir_bsock->fsend("2000 proxy OK.\n");
607    jcr->dir_bsock->signal(BNET_MAIN_PROMPT);
608    
609    maxfd = MAX(cons_bsock->m_fd, jcr->dir_bsock->m_fd) + 1;
610
611    /* Start to forward events from one to the other
612     * It can be done with 2 threads, or with a select
613     */
614    do {
615       FD_ZERO(&fdset);
616       FD_SET((unsigned)cons_bsock->m_fd, &fdset);
617       FD_SET((unsigned)jcr->dir_bsock->m_fd, &fdset);
618
619       tv.tv_sec = 5;
620       tv.tv_usec = 0;
621       switch ((v = select(maxfd, &fdset, NULL, NULL, &tv))) {
622       case 0:                      /* timeout */
623          OK = !jcr->is_canceled();
624          break;
625       case -1:
626          Dmsg1(0, "Bad call to select ERR=%d\n", errno);
627          OK = false;
628       default:
629 #ifdef HAVE_TLS
630          if (cons_bsock->tls && !tls_bsock_probe(cons_bsock)) {
631             /* maybe a session key negotiation waked up the socket */
632             FD_CLR(cons_bsock->m_fd, &fdset);
633          }
634          if (jcr->dir_bsock->tls && !tls_bsock_probe(jcr->dir_bsock)) {
635             /* maybe a session key negotiation waked up the socket */
636             FD_CLR(jcr->dir_bsock->m_fd, &fdset);
637          }
638 #endif
639          break;
640       }
641       Dmsg1(DT_NETWORK, "select = %d\n", v);
642       if (OK) {
643          if (FD_ISSET(cons_bsock->m_fd, &fdset)) {
644             v = cons_bsock->recv();
645             if (v == BNET_SIGNAL) {
646                if (cons_bsock->msglen == BNET_FDCALLED) {
647                   OK = false;
648                   fdcalled = true;
649                } else {
650                   jcr->dir_bsock->signal(cons_bsock->msglen);
651                }
652
653             } else if (v >= 0) {
654                jcr->dir_bsock->fsend("%s", cons_bsock->msg);
655
656             } else {
657                /* We should not have such kind of message */
658                OK = false;
659             }
660          }
661          if (FD_ISSET(jcr->dir_bsock->m_fd, &fdset)) {
662             v = jcr->dir_bsock->recv();
663             if (v == BNET_SIGNAL) {
664                cons_bsock->signal(jcr->dir_bsock->msglen);
665             } else if (v >= 0) {
666                cons_bsock->fsend("%s", jcr->dir_bsock->msg);
667             } else {
668                /* We should not have such kind of message */
669                OK = false;
670             }
671          }
672       }
673       if (cons_bsock->is_error() || jcr->dir_bsock->is_error()) {
674          OK = false;
675       }
676    } while (OK && !jcr->is_canceled());
677    
678    /* Close the socket, nothing more will come */
679    jcr->dir_bsock->signal(BNET_TERMINATE);
680    jcr->dir_bsock->close();
681    if (fdcalled) {
682       handle_connection_request(cons_bsock); /* will release the socket */
683    } else {
684       free_bsock(cons_bsock);
685    }
686    return 1;
687 }
688
689 static int sm_dump_cmd(JCR *jcr)
690 {
691    close_memory_pool();
692    sm_dump(false, true);
693    jcr->dir_bsock->fsend("2000 sm_dump OK\n");
694    return 1;
695 }
696
697 #ifdef DEVELOPER
698 static int exit_cmd(JCR *jcr)
699 {
700    jcr->dir_bsock->fsend("2000 exit OK\n");
701    terminate_filed(0);
702    return 0;
703 }
704 #endif
705
706 /*
707  * Hello from Director he must identify himself and provide his
708  *  password.
709  */
710 static int hello_cmd(JCR *jcr)
711 {
712    Dmsg0(120, "Calling Authenticate\n");
713    if (!validate_dir_hello(jcr)) {
714       return 0;
715    }
716    if (!authenticate_director(jcr)) {
717       return 0;
718    }
719    Dmsg0(120, "OK Authenticate\n");
720    jcr->authenticated = true;
721
722    dequeue_messages(jcr);     /* dequeue any daemon messages */
723    return 1;
724 }
725
726 /*
727  * Cancel a Job
728  */
729 static int cancel_cmd(JCR *jcr)
730 {
731    BSOCK *dir = jcr->dir_bsock;
732    char Job[MAX_NAME_LENGTH];
733    JCR *cjcr;
734    int status;
735    const char *reason;
736
737    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
738       status = JS_Canceled;
739       reason = "canceled";
740    } else if (sscanf(dir->msg, "stop Job=%127s", Job) == 1) {
741       status = JS_Incomplete;
742       reason = "stopped";
743    } else {
744       dir->fsend(_("2902 Error scanning cancel command.\n"));
745       goto bail_out;
746    }
747    if (!(cjcr=get_jcr_by_full_name(Job))) {
748       dir->fsend(_("2901 Job %s not found.\n"), Job);
749    } else {
750       generate_plugin_event(cjcr, bEventCancelCommand, NULL);
751       cjcr->setJobStatus(status);
752       if (cjcr->store_bsock) {
753          cjcr->store_bsock->cancel();
754       }
755       cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
756       free_jcr(cjcr);
757       dir->fsend(_("2001 Job \"%s\" marked to be %s.\n"),
758          Job, reason);
759    }
760
761 bail_out:
762    dir->signal(BNET_EOD);
763    return 1;
764 }
765
766 /**
767  * Set bandwidth limit as requested by the Director
768  *
769  */
770 static int setbandwidth_cmd(JCR *jcr)
771 {
772    BSOCK *dir = jcr->dir_bsock;
773    int64_t bw=0;
774    JCR *cjcr;
775    char Job[MAX_NAME_LENGTH];
776    *Job=0;
777
778    if (sscanf(dir->msg, setbandwidth, &bw, Job) != 2 || bw < 0) {
779       pm_strcpy(jcr->errmsg, dir->msg);
780       dir->fsend(_("2991 Bad setbandwidth command: %s\n"), jcr->errmsg);
781       return 0;
782    }
783
784    if (*Job) {
785       if(!(cjcr=get_jcr_by_full_name(Job))) {
786          dir->fsend(_("2901 Job %s not found.\n"), Job);
787       } else {
788          cjcr->max_bandwidth = bw;
789          if (cjcr->store_bsock) {
790             cjcr->store_bsock->set_bwlimit(bw);
791          }
792          free_jcr(cjcr);
793       }
794
795    } else {                           /* No job requested, apply globally */
796       me->max_bandwidth_per_job = bw; /* Overwrite directive */
797       foreach_jcr(cjcr) {
798          cjcr->max_bandwidth = bw;
799          if (cjcr->store_bsock) {
800             cjcr->store_bsock->set_bwlimit(bw);
801          }
802       }
803       endeach_jcr(cjcr);
804    }
805
806    return dir->fsend(OKBandwidth);
807 }
808
809 /**
810  * Set debug level as requested by the Director
811  *
812  */
813 static int setdebug_cmd(JCR *jcr)
814 {
815    BSOCK *dir = jcr->dir_bsock;
816    int32_t trace, lvl;
817    int32_t hangup = -1;
818    int32_t blowup = -1;
819    int64_t level, level_tags = 0;
820    int scan;
821    char options[60];
822    char tags[512];
823
824    Dmsg1(50, "setdebug_cmd: %s", dir->msg);
825    tags[0] = options[0] = 0;
826    scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld blowup=%ld"
827              " options=%55s tags=%511s",
828                  &lvl, &trace, &hangup, &blowup, options, tags);
829    if (scan != 6) {
830       scan = sscanf(dir->msg, "setdebug=%ld trace=%ld hangup=%ld",
831                     &lvl, &trace, &hangup);
832       if (scan != 3) {
833          Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
834          if (sscanf(dir->msg, "setdebug=%ld trace=%ld", &lvl, &trace) != 2) {
835             pm_strcpy(jcr->errmsg, dir->msg);
836             dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
837             return 0;
838          } else {
839             hangup = -1;
840          }
841       }
842    }
843    level = lvl;
844    set_trace(trace);
845    set_hangup(hangup);
846    set_blowup(blowup);
847    if (!debug_parse_tags(tags, &level_tags)) {
848       *tags = 0;
849    }
850    if (level >= 0) {
851       debug_level = level;
852    }
853    debug_level_tags = level_tags;
854
855    /* Parse specific FD options */
856    for (char *p = options; *p ; p++) {
857       switch(*p) {
858       case 'i':
859          /* Turn on/off ignore bwrite() errors on restore */
860          no_win32_write_errors = true;
861          break;
862       case 'd':
863          /* Turn on/off decomp of BackupRead() streams */
864          win32decomp = true;
865          break;
866       }
867    }
868
869    /* handle other options */
870    set_debug_flags(options);
871
872    Dmsg6(150, "level=%ld trace=%ld hangup=%ld blowup=%d options=%s tags=%s\n",
873          lvl, get_trace(), get_hangup(), get_blowup(), options, tags);
874    return dir->fsend(OKsetdebug, lvl, get_trace(), get_hangup(),
875              get_blowup(), options, tags);
876 }
877
878
879 static int estimate_cmd(JCR *jcr)
880 {
881    BSOCK *dir = jcr->dir_bsock;
882    char ed1[50], ed2[50];
883
884    if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
885       pm_strcpy(jcr->errmsg, dir->msg);
886       Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
887       dir->fsend(_("2992 Bad estimate command.\n"));
888       return 0;
889    }
890    make_estimate(jcr);
891    dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
892       edit_uint64_with_commas(jcr->JobBytes, ed2));
893    dir->signal(BNET_EOD);
894    return 1;
895 }
896
897 /**
898  * Get JobId and Storage Daemon Authorization key from Director
899  */
900 static int job_cmd(JCR *jcr)
901 {
902    BSOCK *dir = jcr->dir_bsock;
903    POOL_MEM sd_auth_key(PM_MESSAGE);
904    sd_auth_key.check_size(dir->msglen);
905
906    if (sscanf(dir->msg, jobcmd,  &jcr->JobId, jcr->Job,
907               &jcr->VolSessionId, &jcr->VolSessionTime,
908               sd_auth_key.c_str()) != 5) {
909       pm_strcpy(jcr->errmsg, dir->msg);
910       Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
911       dir->fsend(BADjob);
912       return 0;
913    }
914    set_jcr_in_tsd(jcr);
915    set_storage_auth_key(jcr, sd_auth_key.c_str());
916    Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
917    Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
918    new_plugins(jcr);                  /* instantiate plugins for this jcr */
919    generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
920 #ifdef HAVE_WIN32
921    return dir->fsend(OKjob, VERSION, LSMDATE, win_os, DISTNAME, DISTVER);
922 #else
923     return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
924 #endif
925 }
926
927 extern "C" char *job_code_callback_filed(JCR *jcr, const char* param, char *buf, int buflen)
928 {
929    switch (param[0]) {
930    case 'D':
931       if (jcr->director) {
932          return jcr->director->hdr.name;
933       }
934       break;
935    case 'S':
936       return jcr->PrevJob;
937    }
938    return NULL;
939
940 }
941
942 static int runbefore_cmd(JCR *jcr)
943 {
944    bool ok;
945    BSOCK *dir = jcr->dir_bsock;
946    POOLMEM *cmd = get_memory(dir->msglen+1);
947    RUNSCRIPT *script;
948
949    Dmsg1(100, "runbefore_cmd: %s", dir->msg);
950    if (sscanf(dir->msg, runbefore, cmd) != 1) {
951       pm_strcpy(jcr->errmsg, dir->msg);
952       Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
953       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
954       free_memory(cmd);
955       return 0;
956    }
957    unbash_spaces(cmd);
958
959    /* Run the command now */
960    script = new_runscript();
961    script->set_job_code_callback(job_code_callback_filed);
962    script->set_command(cmd);
963    script->when = SCRIPT_Before;
964    ok = script->run(jcr, "ClientRunBeforeJob");
965    free_runscript(script);
966
967    free_memory(cmd);
968    if (ok) {
969       dir->fsend(OKRunBefore);
970       return 1;
971    } else {
972       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
973       return 0;
974    }
975 }
976
977 static int runbeforenow_cmd(JCR *jcr)
978 {
979    BSOCK *dir = jcr->dir_bsock;
980
981    run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
982    if (job_canceled(jcr)) {
983       dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
984       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
985       return 0;
986    } else {
987       dir->fsend(OKRunBeforeNow);
988       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
989       return 1;
990    }
991 }
992
993 static int runafter_cmd(JCR *jcr)
994 {
995    BSOCK *dir = jcr->dir_bsock;
996    POOLMEM *msg = get_memory(dir->msglen+1);
997    RUNSCRIPT *cmd;
998
999    Dmsg1(100, "runafter_cmd: %s", dir->msg);
1000    if (sscanf(dir->msg, runafter, msg) != 1) {
1001       pm_strcpy(jcr->errmsg, dir->msg);
1002       Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
1003       dir->fsend(_("2905 Bad RunAfterJob command.\n"));
1004       free_memory(msg);
1005       return 0;
1006    }
1007    unbash_spaces(msg);
1008
1009    cmd = new_runscript();
1010    cmd->set_job_code_callback(job_code_callback_filed);
1011    cmd->set_command(msg);
1012    cmd->on_success = true;
1013    cmd->on_failure = false;
1014    cmd->when = SCRIPT_After;
1015
1016    jcr->RunScripts->append(cmd);
1017
1018    free_pool_memory(msg);
1019    return dir->fsend(OKRunAfter);
1020 }
1021
1022 static int runscript_cmd(JCR *jcr)
1023 {
1024    BSOCK *dir = jcr->dir_bsock;
1025    POOLMEM *msg = get_memory(dir->msglen+1);
1026    int on_success, on_failure, fail_on_error;
1027
1028    RUNSCRIPT *cmd = new_runscript() ;
1029    cmd->set_job_code_callback(job_code_callback_filed);
1030
1031    Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
1032    /* Note, we cannot sscanf into bools */
1033    if (sscanf(dir->msg, runscript, &on_success,
1034                                   &on_failure,
1035                                   &fail_on_error,
1036                                   &cmd->when,
1037                                   msg) != 5) {
1038       pm_strcpy(jcr->errmsg, dir->msg);
1039       Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
1040       dir->fsend(_("2905 Bad RunScript command.\n"));
1041       free_runscript(cmd);
1042       free_memory(msg);
1043       return 0;
1044    }
1045    cmd->on_success = on_success;
1046    cmd->on_failure = on_failure;
1047    cmd->fail_on_error = fail_on_error;
1048    unbash_spaces(msg);
1049
1050    cmd->set_command(msg);
1051    cmd->debug();
1052    jcr->RunScripts->append(cmd);
1053
1054    free_pool_memory(msg);
1055    return dir->fsend(OKRunScript);
1056 }
1057
1058 /*
1059  * This reads data sent from the Director from the
1060  *   RestoreObject table that allows us to get objects
1061  *   that were backed up (VSS .xml data) and are needed
1062  *   before starting the restore.
1063  */
1064 static int restore_object_cmd(JCR *jcr)
1065 {
1066    BSOCK *dir = jcr->dir_bsock;
1067    int32_t FileIndex;
1068    restore_object_pkt rop;
1069
1070    memset(&rop, 0, sizeof(rop));
1071    rop.pkt_size = sizeof(rop);
1072    rop.pkt_end = sizeof(rop);
1073
1074    Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
1075    if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
1076       Dmsg0(20, "Got endrestoreobject\n");
1077       generate_plugin_event(jcr, bEventRestoreObject, NULL);
1078       return dir->fsend(OKRestoreObject);
1079    }
1080
1081    rop.plugin_name = (char *)malloc(dir->msglen);
1082    *rop.plugin_name = 0;
1083
1084    if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len,
1085               &rop.object_full_len, &rop.object_index,
1086               &rop.object_type, &rop.object_compression, &FileIndex,
1087               rop.plugin_name) != 8) {
1088
1089       /* Old version, no plugin_name */
1090       if (sscanf(dir->msg, restoreobjcmd1, &rop.JobId, &rop.object_len,
1091                  &rop.object_full_len, &rop.object_index,
1092                  &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
1093          Dmsg0(5, "Bad restore object command\n");
1094          pm_strcpy(jcr->errmsg, dir->msg);
1095          Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
1096          goto bail_out;
1097       }
1098    }
1099
1100    unbash_spaces(rop.plugin_name);
1101
1102    Dmsg7(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d "
1103          "FI=%d plugin_name=%s\n",
1104          rop.JobId, rop.object_len, rop.object_full_len,
1105          rop.object_index, rop.object_type, FileIndex, rop.plugin_name);
1106    /* Read Object name */
1107    if (dir->recv() < 0) {
1108       goto bail_out;
1109    }
1110    Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
1111    rop.object_name = bstrdup(dir->msg);
1112
1113    /* Read Object */
1114    if (dir->recv() < 0) {
1115       goto bail_out;
1116    }
1117    /* Transfer object from message buffer, and get new message buffer */
1118    rop.object = dir->msg;
1119    dir->msg = get_pool_memory(PM_MESSAGE);
1120
1121    /* If object is compressed, uncompress it */
1122    if (rop.object_compression == 1) {   /* zlib level 9 */
1123       int stat;
1124       int out_len = rop.object_full_len + 100;
1125       POOLMEM *obj = get_memory(out_len);
1126       Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
1127       stat = Zinflate(rop.object, rop.object_len, obj, out_len);
1128       Dmsg1(100, "Zinflate stat=%d\n", stat);
1129       if (out_len != rop.object_full_len) {
1130          Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
1131             rop.object_full_len, out_len, rop.object_name);
1132       }
1133       free_pool_memory(rop.object);   /* release compressed object */
1134       rop.object = obj;               /* new uncompressed object */
1135       rop.object_len = out_len;
1136    }
1137    Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
1138    /* we still need to do this to detect a vss restore */
1139    if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
1140       Dmsg0(100, "got job metadata\n");
1141       jcr->got_metadata = true;
1142    }
1143
1144    generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
1145
1146    if (rop.object_name) {
1147       free(rop.object_name);
1148    }
1149    if (rop.object) {
1150       free_pool_memory(rop.object);
1151    }
1152    if (rop.plugin_name) {
1153       free(rop.plugin_name);
1154    }
1155
1156    Dmsg1(100, "Send: %s", OKRestoreObject);
1157    return 1;
1158
1159 bail_out:
1160    dir->fsend(_("2909 Bad RestoreObject command.\n"));
1161    return 0;
1162
1163 }
1164
1165
1166 static bool init_fileset(JCR *jcr)
1167 {
1168    FF_PKT *ff;
1169    findFILESET *fileset;
1170
1171    if (!jcr->ff) {
1172       return false;
1173    }
1174    ff = jcr->ff;
1175    if (ff->fileset) {
1176       return false;
1177    }
1178    fileset = (findFILESET *)malloc(sizeof(findFILESET));
1179    memset(fileset, 0, sizeof(findFILESET));
1180    ff->fileset = fileset;
1181    fileset->state = state_none;
1182    fileset->include_list.init(1, true);
1183    fileset->exclude_list.init(1, true);
1184    return true;
1185 }
1186
1187 static void append_file(JCR *jcr, findINCEXE *incexe,
1188                         const char *buf, bool is_file)
1189 {
1190    if (is_file) {
1191 #ifdef HAVE_WIN32
1192       /* Special case for / under Win32,
1193        * user is requesting to include all local drives
1194        */
1195       if (strcmp(buf, "/") == 0) {
1196          //list_drives(&incexe->name_list);
1197
1198       } else {
1199          incexe->name_list.append(new_dlistString(buf));
1200       }
1201 #else
1202       incexe->name_list.append(new_dlistString(buf));
1203 #endif  /* HAVE_WIN32 */
1204
1205    } else if (me->plugin_directory) {
1206       generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
1207       incexe->plugin_list.append(new_dlistString(buf));
1208    } else {
1209       Jmsg(jcr, M_FATAL, 0,
1210            _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
1211            buf);
1212    }
1213 }
1214
1215 /**
1216  * Add fname to include/exclude fileset list. First check for
1217  * | and < and if necessary perform command.
1218  */
1219 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
1220 {
1221    findFILESET *fileset = jcr->ff->fileset;
1222    char *p;
1223    BPIPE *bpipe;
1224    POOLMEM *fn;
1225    FILE *ffd;
1226    char buf[1000];
1227    int ch;
1228    int stat;
1229
1230    p = (char *)fname;
1231    ch = (uint8_t)*p;
1232    switch (ch) {
1233    case '|':
1234       p++;                            /* skip over | */
1235       fn = get_pool_memory(PM_FNAME);
1236       fn = edit_job_codes(jcr, fn, p, "", job_code_callback_filed);
1237       bpipe = open_bpipe(fn, 0, "r");
1238       if (!bpipe) {
1239          berrno be;
1240          Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
1241             p, be.bstrerror());
1242          free_pool_memory(fn);
1243          return;
1244       }
1245       free_pool_memory(fn);
1246       while (fgets(buf, sizeof(buf), bpipe->rfd)) {
1247          strip_trailing_junk(buf);
1248          append_file(jcr, fileset->incexe, buf, is_file);
1249       }
1250       if ((stat=close_bpipe(bpipe)) != 0) {
1251          berrno be;
1252          Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
1253             p, be.code(stat), be.bstrerror(stat));
1254          return;
1255       }
1256       break;
1257    case '<':
1258       Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
1259       p++;                      /* skip over < */
1260       if ((ffd = fopen(p, "rb")) == NULL) {
1261          berrno be;
1262          Jmsg(jcr, M_FATAL, 0,
1263               _("Cannot open FileSet input file: %s. ERR=%s\n"),
1264             p, be.bstrerror());
1265          return;
1266       }
1267       while (fgets(buf, sizeof(buf), ffd)) {
1268          strip_trailing_junk(buf);
1269          append_file(jcr, fileset->incexe, buf, is_file);
1270       }
1271       fclose(ffd);
1272       break;
1273    default:
1274       append_file(jcr, fileset->incexe, fname, is_file);
1275       break;
1276    }
1277 }
1278
1279 findINCEXE *get_incexe(JCR *jcr)
1280 {
1281    if (jcr->ff && jcr->ff->fileset) {
1282       return jcr->ff->fileset->incexe;
1283    }
1284    return NULL;
1285 }
1286
1287 void set_incexe(JCR *jcr, findINCEXE *incexe)
1288 {
1289    findFILESET *fileset = jcr->ff->fileset;
1290    fileset->incexe = incexe;
1291 }
1292
1293
1294 /**
1295  * Define a new Exclude block in the FileSet
1296  */
1297 findINCEXE *new_exclude(JCR *jcr)
1298 {
1299    findFILESET *fileset = jcr->ff->fileset;
1300
1301    /* New exclude */
1302    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1303    memset(fileset->incexe, 0, sizeof(findINCEXE));
1304    fileset->incexe->opts_list.init(1, true);
1305    fileset->incexe->name_list.init();
1306    fileset->incexe->plugin_list.init();
1307    fileset->exclude_list.append(fileset->incexe);
1308    return fileset->incexe;
1309 }
1310
1311 /**
1312  * Define a new Include block in the FileSet
1313  */
1314 findINCEXE *new_include(JCR *jcr)
1315 {
1316    findFILESET *fileset = jcr->ff->fileset;
1317
1318    /* New include */
1319    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1320    memset(fileset->incexe, 0, sizeof(findINCEXE));
1321    fileset->incexe->opts_list.init(1, true);
1322    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
1323    fileset->incexe->plugin_list.init();
1324    fileset->include_list.append(fileset->incexe);
1325    return fileset->incexe;
1326 }
1327
1328 /**
1329  * Define a new preInclude block in the FileSet
1330  *   That is the include is prepended to the other
1331  *   Includes.  This is used for plugin exclusions.
1332  */
1333 findINCEXE *new_preinclude(JCR *jcr)
1334 {
1335    findFILESET *fileset = jcr->ff->fileset;
1336
1337    /* New pre-include */
1338    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
1339    memset(fileset->incexe, 0, sizeof(findINCEXE));
1340    fileset->incexe->opts_list.init(1, true);
1341    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
1342    fileset->incexe->plugin_list.init();
1343    fileset->include_list.prepend(fileset->incexe);
1344    return fileset->incexe;
1345 }
1346
1347 static findFOPTS *start_options(FF_PKT *ff)
1348 {
1349    int state = ff->fileset->state;
1350    findINCEXE *incexe = ff->fileset->incexe;
1351
1352    if (state != state_options) {
1353       ff->fileset->state = state_options;
1354       findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1355       memset(fo, 0, sizeof(findFOPTS));
1356       fo->regex.init(1, true);
1357       fo->regexdir.init(1, true);
1358       fo->regexfile.init(1, true);
1359       fo->wild.init(1, true);
1360       fo->wilddir.init(1, true);
1361       fo->wildfile.init(1, true);
1362       fo->wildbase.init(1, true);
1363       fo->base.init(1, true);
1364       fo->fstype.init(1, true);
1365       fo->drivetype.init(1, true);
1366       incexe->current_opts = fo;
1367       incexe->opts_list.append(fo);
1368    }
1369    return incexe->current_opts;
1370 }
1371
1372 /*
1373  * Used by plugins to define a new options block
1374  */
1375 void new_options(JCR *jcr, findINCEXE *incexe)
1376 {
1377    if (!incexe) {
1378       incexe = jcr->ff->fileset->incexe;
1379    }
1380    findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
1381    memset(fo, 0, sizeof(findFOPTS));
1382    fo->regex.init(1, true);
1383    fo->regexdir.init(1, true);
1384    fo->regexfile.init(1, true);
1385    fo->wild.init(1, true);
1386    fo->wilddir.init(1, true);
1387    fo->wildfile.init(1, true);
1388    fo->wildbase.init(1, true);
1389    fo->base.init(1, true);
1390    fo->fstype.init(1, true);
1391    fo->drivetype.init(1, true);
1392    incexe->current_opts = fo;
1393    incexe->opts_list.prepend(fo);
1394    jcr->ff->fileset->state = state_options;
1395 }
1396
1397 /**
1398  * Add a regex to the current fileset
1399  */
1400 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
1401 {
1402    findFOPTS *current_opts = start_options(jcr->ff);
1403    regex_t *preg;
1404    int rc;
1405    char prbuf[500];
1406
1407    preg = (regex_t *)malloc(sizeof(regex_t));
1408    if (current_opts->flags & FO_IGNORECASE) {
1409       rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1410    } else {
1411       rc = regcomp(preg, item, REG_EXTENDED);
1412    }
1413    if (rc != 0) {
1414       regerror(rc, preg, prbuf, sizeof(prbuf));
1415       regfree(preg);
1416       free(preg);
1417       Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1418       return state_error;
1419    }
1420    if (type == ' ') {
1421       current_opts->regex.append(preg);
1422    } else if (type == 'D') {
1423       current_opts->regexdir.append(preg);
1424    } else if (type == 'F') {
1425       current_opts->regexfile.append(preg);
1426    } else {
1427       return state_error;
1428    }
1429    return state_options;
1430 }
1431
1432 /**
1433  * Add a wild card to the current fileset
1434  */
1435 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1436 {
1437    findFOPTS *current_opts = start_options(jcr->ff);
1438
1439    if (type == ' ') {
1440       current_opts->wild.append(bstrdup(item));
1441    } else if (type == 'D') {
1442       current_opts->wilddir.append(bstrdup(item));
1443    } else if (type == 'F') {
1444       current_opts->wildfile.append(bstrdup(item));
1445    } else if (type == 'B') {
1446       current_opts->wildbase.append(bstrdup(item));
1447    } else {
1448       return state_error;
1449    }
1450    return state_options;
1451 }
1452
1453
1454 /**
1455  * Add options to the current fileset
1456  */
1457 int add_options_to_fileset(JCR *jcr, const char *item)
1458 {
1459    findFOPTS *current_opts = start_options(jcr->ff);
1460
1461    set_options(current_opts, item);
1462    return state_options;
1463 }
1464
1465 static void add_fileset(JCR *jcr, const char *item)
1466 {
1467    FF_PKT *ff = jcr->ff;
1468    findFILESET *fileset = ff->fileset;
1469    int state = fileset->state;
1470    findFOPTS *current_opts;
1471
1472    /* Get code, optional subcode, and position item past the dividing space */
1473    Dmsg1(100, "%s\n", item);
1474    int code = item[0];
1475    if (code != '\0') {
1476       ++item;
1477    }
1478    int subcode = ' ';               /* A space is always a valid subcode */
1479    if (item[0] != '\0' && item[0] != ' ') {
1480       subcode = item[0];
1481       ++item;
1482    }
1483    if (*item == ' ') {
1484       ++item;
1485    }
1486
1487    /* Skip all lines we receive after an error */
1488    if (state == state_error) {
1489       Dmsg0(100, "State=error return\n");
1490       return;
1491    }
1492
1493    /**
1494     * The switch tests the code for validity.
1495     * The subcode is always good if it is a space, otherwise we must confirm.
1496     * We set state to state_error first assuming the subcode is invalid,
1497     * requiring state to be set in cases below that handle subcodes.
1498     */
1499    if (subcode != ' ') {
1500       state = state_error;
1501       Dmsg0(100, "Set state=error or double code.\n");
1502    }
1503    switch (code) {
1504    case 'I':
1505       (void)new_include(jcr);
1506       break;
1507    case 'E':
1508       (void)new_exclude(jcr);
1509       break;
1510    case 'N':                             /* null */
1511       state = state_none;
1512       break;
1513    case 'F':                             /* file = */
1514       /* File item to include or exclude list */
1515       state = state_include;
1516       add_file_to_fileset(jcr, item, true);
1517       break;
1518    case 'P':                              /* plugin */
1519       /* Plugin item to include list */
1520       state = state_include;
1521       add_file_to_fileset(jcr, item, false);
1522       break;
1523    case 'R':                              /* regex */
1524       state = add_regex_to_fileset(jcr, item, subcode);
1525       break;
1526    case 'B':
1527       current_opts = start_options(ff);
1528       current_opts->base.append(bstrdup(item));
1529       state = state_options;
1530       break;
1531    case 'X':                             /* Filetype or Drive type */
1532       current_opts = start_options(ff);
1533       state = state_options;
1534       if (subcode == ' ') {
1535          current_opts->fstype.append(bstrdup(item));
1536       } else if (subcode == 'D') {
1537          current_opts->drivetype.append(bstrdup(item));
1538       } else {
1539          state = state_error;
1540       }
1541       break;
1542    case 'W':                               /* wild cards */
1543       state = add_wild_to_fileset(jcr, item, subcode);
1544       break;
1545    case 'O':                                /* Options */
1546       state = add_options_to_fileset(jcr, item);
1547       break;
1548    case 'Z':                                /* ignore dir */
1549       state = state_include;
1550       fileset->incexe->ignoredir = bstrdup(item);
1551       break;
1552    case 'D':
1553       current_opts = start_options(ff);
1554 //    current_opts->reader = bstrdup(item); /* deprecated */
1555       state = state_options;
1556       break;
1557    case 'T':
1558       current_opts = start_options(ff);
1559 //    current_opts->writer = bstrdup(item); /* deprecated */
1560       state = state_options;
1561       break;
1562    case 'G':                    /* Plugin command for this Option block */
1563       current_opts = start_options(ff);
1564       current_opts->plugin = bstrdup(item);
1565       state = state_options;
1566       break;
1567    default:
1568       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1569       state = state_error;
1570       break;
1571    }
1572    ff->fileset->state = state;
1573 }
1574
1575 static bool term_fileset(JCR *jcr)
1576 {
1577    FF_PKT *ff = jcr->ff;
1578
1579 #ifdef xxx_DEBUG_CODE
1580    findFILESET *fileset = ff->fileset;
1581    int i, j, k;
1582
1583    for (i=0; i<fileset->include_list.size(); i++) {
1584       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1585       Dmsg0(400, "I\n");
1586       for (j=0; j<incexe->opts_list.size(); j++) {
1587          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1588          for (k=0; k<fo->regex.size(); k++) {
1589             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1590          }
1591          for (k=0; k<fo->regexdir.size(); k++) {
1592             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1593          }
1594          for (k=0; k<fo->regexfile.size(); k++) {
1595             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1596          }
1597          for (k=0; k<fo->wild.size(); k++) {
1598             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1599          }
1600          for (k=0; k<fo->wilddir.size(); k++) {
1601             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1602          }
1603          for (k=0; k<fo->wildfile.size(); k++) {
1604             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1605          }
1606          for (k=0; k<fo->wildbase.size(); k++) {
1607             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1608          }
1609          for (k=0; k<fo->base.size(); k++) {
1610             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1611          }
1612          for (k=0; k<fo->fstype.size(); k++) {
1613             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1614          }
1615          for (k=0; k<fo->drivetype.size(); k++) {
1616             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1617          }
1618       }
1619       if (incexe->ignoredir) {
1620          Dmsg1(400, "Z %s\n", incexe->ignoredir);
1621       }
1622       dlistString *node;
1623       foreach_dlist(node, &incexe->name_list) {
1624          Dmsg1(400, "F %s\n", node->c_str());
1625       }
1626       foreach_dlist(node, &incexe->plugin_list) {
1627          Dmsg1(400, "P %s\n", node->c_str());
1628       }
1629    }
1630    for (i=0; i<fileset->exclude_list.size(); i++) {
1631       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1632       Dmsg0(400, "E\n");
1633       for (j=0; j<incexe->opts_list.size(); j++) {
1634          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1635          for (k=0; k<fo->regex.size(); k++) {
1636             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1637          }
1638          for (k=0; k<fo->regexdir.size(); k++) {
1639             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1640          }
1641          for (k=0; k<fo->regexfile.size(); k++) {
1642             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1643          }
1644          for (k=0; k<fo->wild.size(); k++) {
1645             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1646          }
1647          for (k=0; k<fo->wilddir.size(); k++) {
1648             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1649          }
1650          for (k=0; k<fo->wildfile.size(); k++) {
1651             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1652          }
1653          for (k=0; k<fo->wildbase.size(); k++) {
1654             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1655          }
1656          for (k=0; k<fo->base.size(); k++) {
1657             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1658          }
1659          for (k=0; k<fo->fstype.size(); k++) {
1660             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1661          }
1662          for (k=0; k<fo->drivetype.size(); k++) {
1663             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1664          }
1665       }
1666       dlistString *node;
1667       foreach_dlist(node, &incexe->name_list) {
1668          Dmsg1(400, "F %s\n", node->c_str());
1669       }
1670       foreach_dlist(node, &incexe->plugin_list) {
1671          Dmsg1(400, "P %s\n", node->c_str());
1672       }
1673    }
1674 #endif
1675    return ff->fileset->state != state_error;
1676 }
1677
1678
1679 /**
1680  * As an optimization, we should do this during
1681  *  "compile" time in filed/job.c, and keep only a bit mask
1682  *  and the Verify options.
1683  */
1684 static int set_options(findFOPTS *fo, const char *opts)
1685 {
1686    int j;
1687    const char *p;
1688    char strip[100];
1689
1690 // Commented out as it is not backward compatible - KES
1691
1692    for (p=opts; *p; p++) {
1693       switch (*p) {
1694       case 'a':                 /* alway replace */
1695       case '0':                 /* no option */
1696          break;
1697       case 'e':
1698          fo->flags |= FO_EXCLUDE;
1699          break;
1700       case 'f':
1701          fo->flags |= FO_MULTIFS;
1702          break;
1703       case 'h':                 /* no recursion */
1704          fo->flags |= FO_NO_RECURSION;
1705          break;
1706       case 'H':                 /* no hard link handling */
1707          fo->flags |= FO_NO_HARDLINK;
1708          break;
1709       case 'i':
1710          fo->flags |= FO_IGNORECASE;
1711          break;
1712       case 'M':                 /* MD5 */
1713          fo->flags |= FO_MD5;
1714          break;
1715       case 'n':
1716          fo->flags |= FO_NOREPLACE;
1717          break;
1718       case 'p':                 /* use portable data format */
1719          fo->flags |= FO_PORTABLE;
1720          break;
1721       case 'R':                 /* Resource forks and Finder Info */
1722          fo->flags |= FO_HFSPLUS;
1723          break;
1724       case 'r':                 /* read fifo */
1725          fo->flags |= FO_READFIFO;
1726          break;
1727       case 'S':
1728          switch(*(p + 1)) {
1729          case '1':
1730             fo->flags |= FO_SHA1;
1731             p++;
1732             break;
1733 #ifdef HAVE_SHA2
1734          case '2':
1735             fo->flags |= FO_SHA256;
1736             p++;
1737             break;
1738          case '3':
1739             fo->flags |= FO_SHA512;
1740             p++;
1741             break;
1742 #endif
1743          default:
1744             /*
1745              * If 2 or 3 is seen here, SHA2 is not configured, so
1746              *  eat the option, and drop back to SHA-1.
1747              */
1748             if (p[1] == '2' || p[1] == '3') {
1749                p++;
1750             }
1751             fo->flags |= FO_SHA1;
1752             break;
1753          }
1754          break;
1755       case 's':
1756          fo->flags |= FO_SPARSE;
1757          break;
1758       case 'm':
1759          fo->flags |= FO_MTIMEONLY;
1760          break;
1761       case 'k':
1762          fo->flags |= FO_KEEPATIME;
1763          break;
1764       case 'A':
1765          fo->flags |= FO_ACL;
1766          break;
1767       case 'V':                  /* verify options */
1768          /* Copy Verify Options */
1769          for (j=0; *p && *p != ':'; p++) {
1770             fo->VerifyOpts[j] = *p;
1771             if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1772                j++;
1773             }
1774          }
1775          fo->VerifyOpts[j] = 0;
1776          break;
1777       case 'C':                  /* accurate options */
1778          /* Copy Accurate Options */
1779          for (j=0; *p && *p != ':'; p++) {
1780             fo->AccurateOpts[j] = *p;
1781             if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1782                j++;
1783             }
1784          }
1785          fo->AccurateOpts[j] = 0;
1786          break;
1787       case 'J':                  /* Basejob options */
1788          /* Copy BaseJob Options */
1789          for (j=0; *p && *p != ':'; p++) {
1790             fo->BaseJobOpts[j] = *p;
1791             if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1792                j++;
1793             }
1794          }
1795          fo->BaseJobOpts[j] = 0;
1796          break;
1797       case 'P':                  /* strip path */
1798          /* Get integer */
1799          p++;                    /* skip P */
1800          for (j=0; *p && *p != ':'; p++) {
1801             strip[j] = *p;
1802             if (j < (int)sizeof(strip) - 1) {
1803                j++;
1804             }
1805          }
1806          strip[j] = 0;
1807          fo->strip_path = atoi(strip);
1808          fo->flags |= FO_STRIPPATH;
1809          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1810          break;
1811       case 'w':
1812          fo->flags |= FO_IF_NEWER;
1813          break;
1814       case 'W':
1815          fo->flags |= FO_ENHANCEDWILD;
1816          break;
1817       case 'Z':                 /* compression */
1818          p++;                   /* skip Z */
1819          if (*p >= '0' && *p <= '9') {
1820             fo->flags |= FO_COMPRESS;
1821             fo->Compress_algo = COMPRESS_GZIP;
1822             fo->Compress_level = *p - '0';
1823          }
1824          else if (*p == 'o') {
1825             fo->flags |= FO_COMPRESS;
1826             fo->Compress_algo = COMPRESS_LZO1X;
1827             fo->Compress_level = 1; /* not used with LZO */
1828          }
1829          break;
1830       case 'K':
1831          fo->flags |= FO_NOATIME;
1832          break;
1833       case 'c':
1834          fo->flags |= FO_CHKCHANGES;
1835          break;
1836       case 'N':
1837          fo->flags |= FO_HONOR_NODUMP;
1838          break;
1839       case 'X':
1840          fo->flags |= FO_XATTR;
1841          break;
1842       default:
1843          Jmsg1(NULL, M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1844          break;
1845       }
1846    }
1847    return state_options;
1848 }
1849
1850
1851 /**
1852  * Director is passing his Fileset
1853  */
1854 static int fileset_cmd(JCR *jcr)
1855 {
1856    POOL_MEM buf(PM_MESSAGE);
1857    BSOCK *dir = jcr->dir_bsock;
1858    int rtnstat;
1859
1860 #if HAVE_WIN32
1861    jcr->Snapshot = (strstr(dir->msg, "vss=1") != NULL);
1862 #else
1863    jcr->Snapshot = (strstr(dir->msg, "snap=1") != NULL);
1864 #endif
1865    if (!init_fileset(jcr)) {
1866       return 0;
1867    }
1868    while (dir->recv() >= 0) {
1869       strip_trailing_junk(dir->msg);
1870       Dmsg1(500, "Fileset: %s\n", dir->msg);
1871       pm_strcpy(buf, dir->msg);
1872       add_fileset(jcr, buf.c_str());
1873    }
1874    if (!term_fileset(jcr)) {
1875       return 0;
1876    }
1877    rtnstat = dir->fsend(OKinc);
1878    generate_plugin_event(jcr, bEventEndFileSet);
1879    return rtnstat;
1880 }
1881
1882
1883 /*
1884  * The Director sends us the component info file, which
1885  *   we will in turn pass to the VSS plugin.
1886  */
1887 static int component_cmd(JCR *jcr)
1888 {
1889    BSOCK *dir = jcr->dir_bsock;
1890
1891    while (dir->recv() >= 0) {
1892        Dmsg1(200, "filed<dird: component: %s", dir->msg);
1893        generate_plugin_event(jcr, bEventComponentInfo, (void *)dir->msg);
1894    }
1895    return dir->fsend(OKComponentInfo);
1896 }
1897
1898
1899 /**
1900  * Get backup level from Director
1901  *
1902  * Note: there are odd things such as accurate_differential,
1903  *  and accurate_incremental that are passed in level, thus
1904  *  the calls to strstr() below.
1905  *
1906  */
1907 static int level_cmd(JCR *jcr)
1908 {
1909    BSOCK *dir = jcr->dir_bsock;
1910    POOLMEM *level, *buf = NULL;
1911    int mtime_only;
1912
1913    level = get_memory(dir->msglen+1);
1914    Dmsg1(10, "level_cmd: %s", dir->msg);
1915
1916    /* keep compatibility with older directors */
1917    if (strstr(dir->msg, "accurate")) {
1918       jcr->accurate = true;
1919    }
1920    if (strstr(dir->msg, "rerunning")) {
1921       jcr->rerunning = true;
1922    }
1923    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1924       goto bail_out;
1925    }
1926    /* Base backup requested? */
1927    if (strcasecmp(level, "base") == 0) {
1928       jcr->setJobLevel(L_BASE);
1929    /* Full backup requested? */
1930    } else if (strcasecmp(level, "full") == 0) {
1931       jcr->setJobLevel(L_FULL);
1932    } else if (strstr(level, "differential")) {
1933       jcr->setJobLevel(L_DIFFERENTIAL);
1934       free_memory(level);
1935       return 1;
1936    } else if (strstr(level, "incremental")) {
1937       jcr->setJobLevel(L_INCREMENTAL);
1938       free_memory(level);
1939       return 1;
1940    /*
1941     * We get his UTC since time, then sync the clocks and correct it
1942     *   to agree with our clock.
1943     */
1944    } else if (strcasecmp(level, "since_utime") == 0) {
1945       buf = get_memory(dir->msglen+1);
1946       utime_t since_time, adj;
1947       btime_t his_time, bt_start, rt=0, bt_adj=0, his_time_prev=0, n=0;
1948       if (jcr->getJobLevel() == L_NONE) {
1949          jcr->setJobLevel(L_SINCE);     /* if no other job level set, do it now */
1950       }
1951       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d prev_job=%127s",
1952                  buf, &mtime_only, jcr->PrevJob) != 3) {
1953          if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1954                     buf, &mtime_only) != 2) {
1955             goto bail_out;
1956          }
1957       }
1958       since_time = str_to_uint64(buf);  /* this is the since time */
1959       Dmsg2(100, "since_time=%lld prev_job=%s\n", since_time, jcr->PrevJob);
1960       char ed1[50], ed2[50];
1961       /*
1962        * Sync clocks by polling him for the time. We take
1963        *   10 samples of his time throwing out the first two.
1964        */
1965       for (int i=0; i<10; i++) {
1966          bt_start = get_current_btime();
1967          dir->signal(BNET_BTIME);     /* poll for time */
1968          if (dir->recv() <= 0) {      /* get response */
1969             goto bail_out;
1970          }
1971          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1972             goto bail_out;
1973          }
1974          his_time = str_to_uint64(buf);
1975          rt = get_current_btime() - bt_start; /* compute round trip time */
1976          /* skip first two results and check for leap second */
1977          /* if any of the FD or DIR went back in time, skip this iteration */
1978          if (i < 2 || (his_time_prev > 0 && his_time < his_time_prev) || rt<0) {
1979             his_time_prev = his_time;
1980             continue;
1981          }
1982          his_time_prev = his_time;
1983          n++;
1984          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1985                edit_uint64(bt_start, ed2));
1986          bt_adj +=  bt_start - his_time - rt/2;
1987          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1988       }
1989       adj = 0;
1990       if (n > 0) { /* Should be 1 in the worst case */
1991          bt_adj = bt_adj / n;            /* compute average time */
1992          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1993          adj = btime_to_utime(bt_adj);
1994          since_time += adj;              /* adjust for clock difference */
1995       }
1996       /* Don't notify if time within 3 seconds */
1997       if (adj > 3 || adj < -3) {
1998          int type;
1999          if (adj > 600 || adj < -600) {
2000             type = M_WARNING;
2001          } else {
2002             type = M_INFO;
2003          }
2004          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
2005       }
2006       dir->signal(BNET_EOD);
2007
2008       Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
2009       jcr->incremental = 1;           /* set incremental or decremental backup */
2010       jcr->mtime = since_time;        /* set since time */
2011       generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
2012    } else {
2013       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
2014       free_memory(level);
2015       return 0;
2016    }
2017    free_memory(level);
2018    if (buf) {
2019       free_memory(buf);
2020    }
2021    generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
2022    return dir->fsend(OKlevel);
2023
2024 bail_out:
2025    pm_strcpy(jcr->errmsg, dir->msg);
2026    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
2027    free_memory(level);
2028    if (buf) {
2029       free_memory(buf);
2030    }
2031    return 0;
2032 }
2033
2034 /**
2035  * Get session parameters from Director -- this is for a Restore command
2036  *   This is deprecated. It is now passed via the bsr.
2037  */
2038 static int session_cmd(JCR *jcr)
2039 {
2040    BSOCK *dir = jcr->dir_bsock;
2041
2042    Dmsg1(100, "SessionCmd: %s", dir->msg);
2043    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
2044               &jcr->VolSessionId, &jcr->VolSessionTime,
2045               &jcr->StartFile, &jcr->EndFile,
2046               &jcr->StartBlock, &jcr->EndBlock) != 7) {
2047       pm_strcpy(jcr->errmsg, dir->msg);
2048       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
2049       return 0;
2050    }
2051
2052    return dir->fsend(OKsession);
2053 }
2054
2055 static void set_storage_auth_key(JCR *jcr, char *key)
2056 {
2057    /* if no key don't update anything */
2058    if (!*key) {
2059       return;
2060    }
2061
2062    /**
2063     * We can be contacting multiple storage daemons.
2064     * So, make sure that any old jcr->store_bsock is cleaned up.
2065     */
2066    free_bsock(jcr->store_bsock);
2067
2068    /**
2069     * We can be contacting multiple storage daemons.
2070     *   So, make sure that any old jcr->sd_auth_key is cleaned up.
2071     */
2072    if (jcr->sd_auth_key) {
2073       /*
2074        * If we already have a Authorization key, director can do multi
2075        * storage restore
2076        */
2077       Dmsg0(5, "set multi_restore=true\n");
2078       jcr->multi_restore = true;
2079       bfree(jcr->sd_auth_key);
2080    }
2081
2082    jcr->sd_auth_key = bstrdup(key);
2083    Dmsg1(200, "set sd auth key %s\n", jcr->sd_auth_key);
2084 }
2085
2086 /**
2087  * Get address of storage daemon from Director
2088  *
2089  */
2090 static int storage_cmd(JCR *jcr)
2091 {
2092    int stored_port = 0;            /* storage daemon port */
2093    int enable_ssl;                 /* enable ssl to sd */
2094    POOL_MEM sd_auth_key(PM_MESSAGE);
2095    BSOCK *dir = jcr->dir_bsock;
2096    BSOCK *sd;
2097
2098    Dmsg1(100, "StorageCmd: %s", dir->msg);
2099    sd_auth_key.check_size(dir->msglen);
2100    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port,
2101               &enable_ssl, sd_auth_key.c_str()) == 4) {
2102       Dmsg1(100, "Set auth key %s\n", sd_auth_key.c_str());
2103       set_storage_auth_key(jcr, sd_auth_key.c_str());
2104   } else if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
2105                  &stored_port, &enable_ssl) != 3) {
2106       pm_strcpy(jcr->errmsg, dir->msg);
2107       Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
2108       Pmsg1(010, "Bad storage command: %s", jcr->errmsg);
2109       goto bail_out;
2110    }
2111
2112
2113    /* TODO: see if we put limit on restore and backup... */
2114    if (!jcr->max_bandwidth) {
2115       if (jcr->director->max_bandwidth_per_job) {
2116          jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
2117
2118       } else if (me->max_bandwidth_per_job) {
2119          jcr->max_bandwidth = me->max_bandwidth_per_job;
2120       }
2121    }
2122
2123    if (stored_port != 0) { /* We are doing the connecting */
2124       Dmsg3(110, "Connect to storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port,
2125             enable_ssl);
2126       jcr->sd_calls_client = false;
2127       sd = new_bsock();
2128       /* Open command communications with Storage daemon */
2129       /* Try to connect for 1 hour at 10 second intervals */
2130       sd->set_source_address(me->FDsrc_addr);
2131       if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
2132                 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
2133          /* destroy() OK because sd is local */
2134          sd->destroy();
2135          Jmsg2(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
2136              jcr->stored_addr, stored_port);
2137          Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
2138              jcr->stored_addr, stored_port);
2139          goto bail_out;
2140       }
2141
2142       Dmsg0(110, "Connection OK to SD.\n");
2143       jcr->store_bsock = sd;
2144    } else {                      /* The storage daemon called us */
2145       struct timeval tv;
2146       struct timezone tz;
2147       struct timespec timeout;
2148       int errstat;
2149
2150       free_bsock(jcr->store_bsock);
2151       jcr->sd_calls_client = true;
2152
2153       /*
2154        * Wait for the Storage daemon to contact us to start the Job,
2155        *  when he does, we will be released, unless the 30 minutes
2156        *  expires.
2157        */
2158       gettimeofday(&tv, &tz);
2159       timeout.tv_nsec = tv.tv_usec * 1000;
2160       timeout.tv_sec = tv.tv_sec + 30 * 60;  /* wait 30 minutes */
2161       P(mutex);
2162       while (jcr->sd_calls_client_bsock == NULL && !jcr->is_job_canceled()) {
2163          errstat = pthread_cond_timedwait(&jcr->job_start_wait, &mutex, &timeout);
2164          if (errstat == ETIMEDOUT || errstat == EINVAL || errstat == EPERM) {
2165             break;
2166          }
2167          Dmsg1(800, "=== Auth cond errstat=%d\n", errstat);
2168       }
2169       V(mutex);
2170       Dmsg2(800, "Auth fail or cancel for jid=%d %p\n", jcr->JobId, jcr);
2171
2172       /* We should already have a storage connection! */
2173       if (jcr->sd_calls_client_bsock == NULL) {
2174          Pmsg0(000, "Failed connect from Storage daemon. SD bsock=NULL.\n");
2175          Pmsg1(000, "Storagecmd: %s", dir->msg);
2176          Jmsg0(jcr, M_FATAL, 0, _("Failed connect from Storage daemon. SD bsock=NULL.\n"));
2177          goto bail_out;
2178       }
2179       if (jcr->is_job_canceled()) {
2180          goto bail_out;
2181       }
2182       /* Assign the new socket to the main one */
2183       jcr->lock_auth();
2184       jcr->store_bsock = jcr->sd_calls_client_bsock;
2185       jcr->sd_calls_client_bsock = NULL;
2186       jcr->unlock_auth();
2187    }
2188    jcr->store_bsock->set_bwlimit(jcr->max_bandwidth);
2189
2190    if (!send_hello_sd(jcr, jcr->Job)) {
2191       goto bail_out;
2192    }
2193
2194    if (!authenticate_storagedaemon(jcr)) {
2195       goto bail_out;
2196    }
2197    memset(jcr->sd_auth_key, 0, strlen(jcr->sd_auth_key));
2198    Dmsg0(110, "Authenticated with SD.\n");
2199
2200    /* Send OK to Director */
2201    return dir->fsend(OKstore);
2202
2203 bail_out:
2204    dir->fsend(BADcmd, "storage");
2205    return 0;
2206 }
2207
2208 #ifdef HAVE_WIN32
2209 /* TODO: merge find.c ? */
2210 static bool is_excluded(findFILESET *fileset, char *path)
2211 {
2212    int fnm_flags=FNM_CASEFOLD;
2213    int fnmode=0;
2214
2215    /* Now apply the Exclude { } directive */
2216    for (int i=0; i<fileset->exclude_list.size(); i++) {
2217       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
2218       dlistString *node;
2219
2220       foreach_dlist(node, &incexe->name_list) {
2221          char *fname = node->c_str();
2222          Dmsg2(DT_VOLUME|50, "Testing %s against %s\n", path, fname);
2223          if (fnmatch(fname, path, fnmode|fnm_flags) == 0) {
2224             Dmsg1(050, "Reject wild2: %s\n", path);
2225             return true;
2226          }
2227          /* On windows, the path separator is a bit complex to handle. For
2228           * example, in fnmatch(), \ is written as \\\\ in the config file / is
2229           * different from \ So we have our own little strcmp for filenames
2230           */
2231          char *p;
2232          bool same=true;
2233          for (p = path; *p && *fname && same ; p++, fname++) {
2234             if (!((IsPathSeparator(*p) && IsPathSeparator(*fname)) ||
2235                   (tolower(*p) == tolower(*fname)))) {
2236                same = false;           /* Stop after the first one */
2237             }
2238          }
2239
2240          if (same) {
2241             /* End of the for loop, strings looks to be identical */
2242             Dmsg1(DT_VOLUME|50, "Reject: %s\n", path);
2243             return true;
2244          }
2245
2246          /* Looks to be the same string, but with a trailing slash */
2247          if (fname[0] && IsPathSeparator(fname[0]) && fname[1] == '\0'
2248              && p[0] == '\0')
2249          {
2250             Dmsg1(DT_VOLUME|50, "Reject: %s\n", path);
2251             return true;
2252          }
2253       }
2254    }
2255    return false;
2256 }
2257
2258 /*
2259  * For VSS we need to know which windows drives
2260  * are used, because we create a snapshot of all used
2261  * drives before operation
2262  *
2263  */
2264 static int
2265 get_win32_driveletters(JCR *jcr, FF_PKT *ff, char* szDrives)
2266 {
2267    int nCount = 0;
2268
2269    findFILESET *fileset = ff->fileset;
2270    int  flags = 0;
2271    char drive[4];
2272
2273    MTab mtab;
2274    mtab.get();                  /* read the disk structure */
2275
2276    /* Keep this part for compatibility reasons */
2277    strcpy(drive, "c:\\");
2278    for (int i=0; szDrives[i] ; i++) {
2279       drive[0] = szDrives[i];
2280       if (mtab.addInSnapshotSet(drive)) { /* When all volumes are selected, we can stop */
2281          Dmsg0(DT_VOLUME|50, "All Volumes are marked, stopping the loop here\n");
2282          goto all_included;
2283       }
2284    }
2285
2286    if (fileset) {
2287       dlistString *node;
2288
2289       for (int i=0; i<fileset->include_list.size(); i++) {
2290
2291          findFOPTS  *fo;
2292          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
2293
2294          /* look through all files */
2295          foreach_dlist(node, &incexe->name_list) {
2296             char *fname = node->c_str();
2297             if (mtab.addInSnapshotSet(fname)) {
2298                /* When all volumes are selected, we can stop */
2299                Dmsg0(DT_VOLUME|50, "All Volumes are marked, stopping the loop here\n");
2300                goto all_included;
2301             }
2302          }
2303
2304          foreach_alist(fo, &incexe->opts_list) {
2305             flags |= fo->flags; /* We are looking for FO_MULTIFS and recurse */
2306          }
2307       }
2308
2309       /* TODO: it needs to be done Include by Include, but in the worst case,
2310        * we take too much snapshots...
2311        */
2312       if (flags & FO_MULTIFS) {
2313          /* Need to add subdirectories */
2314          POOLMEM   *fn = get_pool_memory(PM_FNAME);
2315          MTabEntry *elt, *elt2;
2316          int len;
2317
2318          Dmsg0(DT_VOLUME|50, "OneFS is set, looking for remaining volumes\n");
2319
2320          foreach_rblist(elt, mtab.entries) {
2321             if (elt->in_SnapshotSet) {
2322                continue;         /* Already in */
2323             }
2324             /* A volume can have multiple mount points */
2325             for (wchar_t *p = elt->first() ; p && *p ; p = elt->next(p)) {
2326                wchar_2_UTF8(&fn, p);
2327
2328                Dmsg1(DT_VOLUME|50, "Looking for path %s\n", fn);
2329
2330                /* First case, root drive (c:/, e:/, d:/), not a submount point */
2331                len = strlen(fn);
2332                if (len <= 3) {
2333                   Dmsg1(DT_VOLUME|50, "Skiping %s\n", fn);
2334                   continue;
2335                }
2336
2337                /* First thing is to look in the exclude list to see if this directory
2338                 * is explicitely excluded
2339                 */
2340                if (is_excluded(fileset, fn)) {
2341                   Dmsg1(DT_VOLUME|50, "Looks to be excluded %s\n", fn);
2342                   continue;
2343                }
2344
2345                /* c:/vol/vol2/vol3
2346                 * will look c:/, then c:/vol/, then c:/vol2/ and if one of them
2347                 * is selected, the sub volume will be directly marked.
2348                 */
2349                for (char *p1 = fn ; *p1 && !elt->in_SnapshotSet ; p1++) {
2350                   if (IsPathSeparator(*p1)) {
2351
2352                      char c = *(p1 + 1);
2353                      *(p1 + 1) = 0;
2354
2355                      /* We look for the previous directory, and if marked, we mark
2356                       * the current one as well
2357                       */
2358                      Dmsg1(DT_VOLUME|50, "Looking for %s\n", fn);
2359                      elt2 = mtab.search(fn);
2360                      if (elt2 && elt2->in_SnapshotSet) {
2361                         Dmsg0(DT_VOLUME|50, "Put volume in SnapshotSet\n");
2362                         elt->setInSnapshotSet();
2363                      }
2364
2365                      *(p1 + 1) = c; /* restore path separator */
2366                   }
2367                }
2368             }
2369          }
2370          free_pool_memory(fn);
2371       }
2372    all_included:
2373       /* Now, we look the volume list to know which one to include */
2374       MTabEntry *elt;
2375       foreach_rblist(elt, mtab.entries) {
2376          if (elt->in_SnapshotSet) {
2377             Dmsg1(DT_VOLUME|50,"Adding volume in mount_points list %ls\n",elt->volumeName);
2378             nCount++;
2379             ff->mount_points.append(bwcsdup(elt->volumeName));
2380          }
2381       }
2382    }
2383
2384    return nCount;
2385 }
2386 #endif  /* HAVE_WIN32 */
2387
2388 /*
2389  * Do a backup.
2390  */
2391 static int backup_cmd(JCR *jcr)
2392 {
2393    BSOCK *dir = jcr->dir_bsock;
2394    BSOCK *sd = jcr->store_bsock;
2395    int ok = 0;
2396    int SDJobStatus;
2397    int32_t FileIndex;
2398
2399    if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
2400       jcr->JobFiles = FileIndex;
2401       Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
2402    }
2403
2404    /*
2405     * If explicitly requesting FO_ACL or FO_XATTR, fail job if it
2406     *  is not available on Client machine
2407     */ 
2408    if (jcr->ff->flags & FO_ACL && !(have_acl||have_win32)) {
2409       Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for Client.\n"));
2410       goto cleanup; 
2411    } 
2412    if (jcr->ff->flags & FO_XATTR && !have_xattr) { 
2413       Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for Client.\n"));
2414       goto cleanup; 
2415    } 
2416    jcr->setJobStatus(JS_Blocked);
2417    jcr->setJobType(JT_BACKUP);
2418    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
2419    if (sd == NULL) {
2420       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
2421       dir->fsend(BADcmd, "backup");
2422       goto cleanup;
2423    }
2424
2425    dir->fsend(OKbackup);
2426    Dmsg1(110, "filed>dird: %s", dir->msg);
2427
2428    /*
2429     * Send Append Open Session to Storage daemon
2430     */
2431    sd->fsend(append_open);
2432    Dmsg1(110, ">stored: %s", sd->msg);
2433    /**
2434     * Expect to receive back the Ticket number
2435     */
2436    if (bget_msg(sd) >= 0) {
2437       Dmsg1(110, "<stored: %s", sd->msg);
2438       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2439          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
2440          goto cleanup;
2441       }
2442       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
2443    } else {
2444       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
2445       goto cleanup;
2446    }
2447
2448    /**
2449     * Send Append data command to Storage daemon
2450     */
2451    sd->fsend(append_data, jcr->Ticket);
2452    Dmsg1(110, ">stored: %s", sd->msg);
2453
2454    /**
2455     * Expect to get OK data
2456     */
2457    Dmsg1(110, "<stored: %s", sd->msg);
2458    if (!response(jcr, sd, OK_data, "Append Data")) {
2459       goto cleanup;
2460    }
2461
2462    generate_daemon_event(jcr, "JobStart");
2463    generate_plugin_event(jcr, bEventStartBackupJob);
2464
2465    if (jcr->Snapshot) {
2466 #if defined(WIN32_VSS)
2467       P(vss_mutex);
2468    /* START VSS ON WIN32 */
2469       jcr->pVSSClient = VSSInit();
2470       if (jcr->pVSSClient->InitializeForBackup(jcr)) {
2471          generate_plugin_event(jcr, bEventVssBackupAddComponents);
2472          /* tell vss which drives to snapshot */
2473          char szWinDriveLetters[27];
2474          *szWinDriveLetters=0;
2475          generate_plugin_event(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
2476          if (get_win32_driveletters(jcr, jcr->ff, szWinDriveLetters)) {
2477             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\"\n"),
2478                  jcr->pVSSClient->GetDriverName());
2479
2480             if (!jcr->pVSSClient->CreateSnapshots(&jcr->ff->mount_points)) {
2481                berrno be;
2482                Jmsg(jcr, M_FATAL, 0, _("VSS CreateSnapshots failed. ERR=%s\n"),
2483                     be.bstrerror());
2484             } else {
2485                /* inform user about writer states */
2486                for (int i=0; i < (int)jcr->pVSSClient->GetWriterCount(); i++) {
2487                   if (jcr->pVSSClient->GetWriterState(i) < 1) {
2488                      Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"),
2489                           jcr->pVSSClient->GetWriterInfo(i));
2490                   }
2491                }
2492             }
2493          } else {
2494             Jmsg(jcr, M_WARNING, 0, _("No drive letters found for generating VSS snapshots.\n"));
2495          }
2496       } else {
2497          berrno be;
2498          Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly. ERR=%s\n"),
2499             be.bstrerror());
2500       }
2501       V(vss_mutex);
2502 #else
2503       Dmsg0(10, "Open a snapshot session\n");
2504       /* TODO: See if we abort the job */
2505       jcr->Snapshot = open_snapshot_backup_session(jcr);
2506 #endif
2507    }
2508    /* Call RunScript just after the Snapshot creation, usually, we restart services */
2509    run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2510
2511    /*
2512     * Send Files to Storage daemon
2513     */
2514    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
2515    if (!blast_data_to_storage_daemon(jcr, NULL)) {
2516       jcr->setJobStatus(JS_ErrorTerminated);
2517       sd->suppress_error_messages(true);
2518       Dmsg0(110, "Error in blast_data.\n");
2519    } else {
2520       jcr->setJobStatus(JS_Terminated);
2521       /* Note, the above set status will not override an error */
2522       if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
2523          sd->suppress_error_messages(true);
2524          goto cleanup;                /* bail out now */
2525       }
2526       /**
2527        * Expect to get response to append_data from Storage daemon
2528        */
2529       if (!response(jcr, sd, OK_append, "Append Data")) {
2530          jcr->setJobStatus(JS_ErrorTerminated);
2531          goto cleanup;
2532       }
2533
2534       /**
2535        * Send Append End Data to Storage daemon
2536        */
2537       sd->fsend(append_end, jcr->Ticket);
2538       /* Get end OK */
2539       if (!response(jcr, sd, OK_end, "Append End")) {
2540          jcr->setJobStatus(JS_ErrorTerminated);
2541          goto cleanup;
2542       }
2543
2544       /**
2545        * Send Append Close to Storage daemon
2546        */
2547       sd->fsend(append_close, jcr->Ticket);
2548       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
2549          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
2550             ok = 1;
2551             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
2552          }
2553       }
2554       if (!ok) {
2555          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
2556          goto cleanup;
2557       }
2558       if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings ||
2559             SDJobStatus == JS_Incomplete)) {
2560          Jmsg(jcr, M_FATAL, 0, _("Bad status %d %c returned from Storage Daemon.\n"),
2561             SDJobStatus, (char)SDJobStatus);
2562       }
2563    }
2564
2565 cleanup:
2566 #if defined(WIN32_VSS)
2567    if (jcr->Snapshot) {
2568       Win32ConvCleanupCache();
2569       if (jcr->pVSSClient) {
2570          jcr->pVSSClient->DestroyWriterInfo();
2571       }
2572    }
2573 #endif
2574    generate_plugin_event(jcr, bEventEndBackupJob);
2575    return 0;                          /* return and stop command loop */
2576 }
2577
2578 /**
2579  * Do a Verify for Director
2580  *
2581  */
2582 static int verify_cmd(JCR *jcr)
2583 {
2584    BSOCK *dir = jcr->dir_bsock;
2585    BSOCK *sd  = jcr->store_bsock;
2586    char level[100];
2587
2588    jcr->setJobType(JT_VERIFY);
2589    if (sscanf(dir->msg, verifycmd, level) != 1) {
2590       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2591       return 0;
2592    }
2593
2594    if (strcasecmp(level, "init") == 0) {
2595       jcr->setJobLevel(L_VERIFY_INIT);
2596    } else if (strcasecmp(level, "catalog") == 0){
2597       jcr->setJobLevel(L_VERIFY_CATALOG);
2598    } else if (strcasecmp(level, "volume") == 0){
2599       jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
2600    } else if (strcasecmp(level, "data") == 0){
2601       jcr->setJobLevel(L_VERIFY_DATA);
2602    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
2603       jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2604    } else {
2605       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2606       return 0;
2607    }
2608
2609    dir->fsend(OKverify);
2610
2611    generate_daemon_event(jcr, "JobStart");
2612    generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2613    generate_plugin_event(jcr, bEventStartVerifyJob);
2614
2615    Dmsg1(110, "filed>dird: %s", dir->msg);
2616
2617    switch (jcr->getJobLevel()) {
2618    case L_VERIFY_INIT:
2619    case L_VERIFY_CATALOG:
2620       do_verify(jcr);
2621       break;
2622    case L_VERIFY_DATA:
2623    case L_VERIFY_VOLUME_TO_CATALOG:
2624       if (!open_sd_read_session(jcr)) {
2625          return 0;
2626       }
2627       start_dir_heartbeat(jcr);
2628       do_verify_volume(jcr);
2629       stop_dir_heartbeat(jcr);
2630       /*
2631        * Send Close session command to Storage daemon
2632        */
2633       sd->fsend(read_close, jcr->Ticket);
2634       Dmsg1(130, "filed>stored: %s", sd->msg);
2635
2636       /* ****FIXME**** check response */
2637       bget_msg(sd);                      /* get OK */
2638
2639       /* Inform Storage daemon that we are done */
2640       sd->signal(BNET_TERMINATE);
2641
2642       break;
2643    case L_VERIFY_DISK_TO_CATALOG:
2644       do_verify(jcr);
2645       break;
2646    default:
2647       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2648       return 0;
2649    }
2650
2651    dir->signal(BNET_EOD);
2652    generate_plugin_event(jcr, bEventEndVerifyJob);
2653    return 0;                          /* return and terminate command loop */
2654 }
2655
2656 /*
2657  * Do a Restore for Director
2658  *
2659  */
2660 static int restore_cmd(JCR *jcr)
2661 {
2662    BSOCK *dir = jcr->dir_bsock;
2663    BSOCK *sd = jcr->store_bsock;
2664    POOLMEM *args=NULL, *restore_where=NULL, *restore_rwhere=NULL;
2665    bool use_regexwhere=false;
2666    int prefix_links;
2667    char replace;
2668    bool scan_ok = true;
2669    int files;
2670    int ret = 0;
2671
2672    /**
2673     * Scan WHERE (base directory for restore) from command
2674     */
2675    Dmsg0(100, "restore command\n");
2676 #if defined(WIN32_VSS)
2677
2678    /**
2679     * No need to enable VSS for restore if we do not have plugin
2680     *  data to restore
2681     */
2682    jcr->Snapshot = jcr->got_metadata;
2683 #endif
2684
2685    /* Pickup where string */
2686    args = get_memory(dir->msglen+1);
2687    *args = 0;
2688
2689    restore_where = get_pool_memory(PM_FNAME);
2690    restore_rwhere = get_pool_memory(PM_FNAME);
2691
2692    /* We don't know the size of where/rwhere in advance,
2693     * where= -> where=%202s\n
2694     */
2695    Mmsg(restore_where, "%s%%%ds\n", restorefcmd, dir->msglen);
2696    Mmsg(restore_rwhere, "%s%%%ds\n", restorefcmdR, dir->msglen);
2697
2698    Dmsg2(200, "where=%srwhere=%s", restore_where, restore_rwhere);
2699
2700    /* Scan for new form with number of files to restore */
2701    if (sscanf(dir->msg, restore_where, &files, &replace, &prefix_links, args) != 4) {
2702       if (sscanf(dir->msg, restore_rwhere, &files, &replace, &prefix_links, args) != 4) {
2703          if (sscanf(dir->msg, restorefcmd1, &files, &replace, &prefix_links) != 3) {
2704             scan_ok = false;
2705          }
2706          *args = 0;             /* No where argument */
2707       } else {
2708          use_regexwhere = true;
2709       }
2710    }
2711
2712    if (scan_ok) {
2713       jcr->ExpectedFiles = files;
2714    } else {
2715       /* Scan for old form without number of files */
2716       jcr->ExpectedFiles = 0;
2717
2718       /* where= -> where=%202s\n */
2719       Mmsg(restore_where, "%s%%%ds\n", restorecmd, dir->msglen);
2720       Mmsg(restore_rwhere, "%s%%%ds\n", restorecmdR, dir->msglen);
2721
2722       if (sscanf(dir->msg, restore_where, &replace, &prefix_links, args) != 3) {
2723          if (sscanf(dir->msg, restore_rwhere, &replace, &prefix_links, args) != 3){
2724             if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2725                pm_strcpy(jcr->errmsg, dir->msg);
2726                Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2727                goto free_mempool;
2728             }
2729             jcr->RegexWhere = bstrdup(args);
2730             *args = 0;          /* No where argument */
2731          } else {
2732             use_regexwhere = true;
2733          }
2734       }
2735    }
2736
2737    /* Turn / into nothing */
2738    if (IsPathSeparator(args[0]) && args[1] == '\0') {
2739       args[0] = '\0';
2740    }
2741
2742    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2743    unbash_spaces(args);
2744
2745    /* Keep track of newly created directories to apply them correct attributes */
2746    if (replace == REPLACE_NEVER || replace == REPLACE_IFNEWER) {
2747       jcr->keep_path_list = true;
2748    }
2749
2750    if (use_regexwhere) {
2751       jcr->where_bregexp = get_bregexps(args);
2752       if (!jcr->where_bregexp) {
2753          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2754          goto free_mempool;
2755       }
2756    } else {
2757       jcr->where = bstrdup(args);
2758    }
2759
2760    jcr->replace = replace;
2761    jcr->prefix_links = prefix_links;
2762
2763    dir->fsend(OKrestore);
2764    Dmsg1(110, "filed>dird: %s", dir->msg);
2765
2766    jcr->setJobType(JT_RESTORE);
2767
2768    jcr->setJobStatus(JS_Blocked);
2769
2770    if (!open_sd_read_session(jcr)) {
2771       jcr->setJobStatus(JS_ErrorTerminated);
2772       goto bail_out;
2773    }
2774
2775    jcr->setJobStatus(JS_Running);
2776
2777    /**
2778     * Do restore of files and data
2779     */
2780    start_dir_heartbeat(jcr);
2781    generate_daemon_event(jcr, "JobStart");
2782    generate_plugin_event(jcr, bEventStartRestoreJob);
2783
2784 #if defined(WIN32_VSS)
2785    /* START VSS ON WIN32 */
2786    if (jcr->Snapshot) {
2787       jcr->pVSSClient = VSSInit();
2788       if (!jcr->pVSSClient->InitializeForRestore(jcr)) {
2789          berrno be;
2790          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
2791       }
2792       //free_and_null_pool_memory(jcr->job_metadata);
2793       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2794    }
2795 #endif
2796
2797    if (!jcr->is_canceled()) {
2798       do_restore(jcr);
2799    }
2800
2801    stop_dir_heartbeat(jcr);
2802
2803    jcr->setJobStatus(JS_Terminated);
2804    if (jcr->JobStatus != JS_Terminated) {
2805       sd->suppress_error_messages(true);
2806    }
2807
2808    /**
2809     * Send Close session command to Storage daemon
2810     */
2811    sd->fsend(read_close, jcr->Ticket);
2812    Dmsg1(100, "filed>stored: %s", sd->msg);
2813
2814    bget_msg(sd);                      /* get OK */
2815
2816    /* Inform Storage daemon that we are done */
2817    sd->signal(BNET_TERMINATE);
2818
2819 #if defined(WIN32_VSS)
2820    /* STOP VSS ON WIN32 */
2821    /* tell vss to close the restore session */
2822    Dmsg0(100, "About to call CloseRestore\n");
2823    if (jcr->Snapshot) {
2824 #if 0
2825       generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
2826 #endif
2827       Dmsg0(100, "Really about to call CloseRestore\n");
2828       if (jcr->pVSSClient->CloseRestore()) {
2829          Dmsg0(100, "CloseRestore success\n");
2830 #if 0
2831          /* inform user about writer states */
2832          for (int i=0; i<(int)jcr->pVSSClient->GetWriterCount(); i++) {
2833             int msg_type = M_INFO;
2834             if (jcr->pVSSClient->GetWriterState(i) < 1) {
2835                //msg_type = M_WARNING;
2836                //jcr->JobErrors++;
2837             }
2838             Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"),
2839                  jcr->pVSSClient->GetWriterInfo(i));
2840          }
2841 #endif
2842       }
2843       else {
2844          Dmsg1(100, "CloseRestore fail - %08x\n", errno);
2845       }
2846    }
2847 #endif
2848
2849 bail_out:
2850    bfree_and_null(jcr->where);
2851    bfree_and_null(jcr->RegexWhere);
2852
2853    if (jcr->JobErrors) {
2854       jcr->setJobStatus(JS_ErrorTerminated);
2855    }
2856
2857    Dmsg0(100, "Done in job.c\n");
2858
2859    if (jcr->multi_restore) {
2860       Dmsg0(100, OKstoreend);
2861       dir->fsend(OKstoreend);
2862       ret = 1;     /* we continue the loop, waiting for next part */
2863    } else {
2864       ret = 0;     /* we stop here */
2865    }
2866
2867    if (job_canceled(jcr)) {
2868       ret = 0;     /* we stop here */
2869    }
2870
2871    if (ret == 0) {
2872       end_restore_cmd(jcr);  /* stopping so send bEventEndRestoreJob */
2873    }
2874
2875 free_mempool:
2876    free_and_null_pool_memory(args);
2877    free_and_null_pool_memory(restore_where);
2878    free_and_null_pool_memory(restore_rwhere);
2879
2880    return ret;
2881 }
2882
2883 static int end_restore_cmd(JCR *jcr)
2884 {
2885    Dmsg0(5, "end_restore_cmd\n");
2886    generate_plugin_event(jcr, bEventEndRestoreJob);
2887    return 0;                          /* return and terminate command loop */
2888 }
2889
2890 static int open_sd_read_session(JCR *jcr)
2891 {
2892    BSOCK *sd = jcr->store_bsock;
2893
2894    if (!sd) {
2895       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2896       return 0;
2897    }
2898    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2899       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2900    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2901    /*
2902     * Open Read Session with Storage daemon
2903     */
2904    sd->fsend(read_open, "DummyVolume",
2905       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2906       jcr->StartBlock, jcr->EndBlock);
2907    Dmsg1(110, ">stored: %s", sd->msg);
2908
2909    /*
2910     * Get ticket number
2911     */
2912    if (bget_msg(sd) >= 0) {
2913       Dmsg1(110, "filed<stored: %s", sd->msg);
2914       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2915          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2916          return 0;
2917       }
2918       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2919    } else {
2920       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2921       return 0;
2922    }
2923
2924    /*
2925     * Use interactive session for the current restore
2926     */
2927    if (jcr->interactive_session) {
2928       sd->fsend(read_ctrl, jcr->Ticket);
2929       Dmsg1(110, ">stored: %s", sd->msg);
2930    }
2931
2932    /*
2933     * Start read of data with Storage daemon
2934     */
2935    sd->fsend(read_data, jcr->Ticket);
2936    Dmsg1(110, ">stored: %s", sd->msg);
2937
2938    /*
2939     * Get OK data
2940     */
2941    if (!response(jcr, sd, OK_data, "Read Data")) {
2942       return 0;
2943    }
2944    return 1;
2945 }
2946
2947 /**
2948  * Destroy the Job Control Record and associated
2949  * resources (sockets).
2950  */
2951 static void filed_free_jcr(JCR *jcr)
2952 {
2953    if (jcr->dir_bsock) {
2954       free_bsock(jcr->dir_bsock);
2955       jcr->dir_bsock = NULL;
2956    }
2957    if (jcr->sd_calls_client_bsock) {
2958       free_bsock(jcr->sd_calls_client_bsock);
2959       jcr->sd_calls_client_bsock = NULL;
2960    }
2961    if (jcr->store_bsock) {
2962       free_bsock(jcr->store_bsock);
2963       jcr->store_bsock = NULL;
2964    }
2965    if (jcr->last_fname) {
2966       free_pool_memory(jcr->last_fname);
2967    }
2968 #ifdef WIN32_VSS
2969    VSSCleanup(jcr->pVSSClient);
2970 #endif
2971    free_plugins(jcr);                 /* release instantiated plugins */
2972    free_runscripts(jcr->RunScripts);
2973    delete jcr->RunScripts;
2974    free_path_list(jcr);
2975
2976    if (jcr->JobId != 0) {
2977       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2978    }
2979    return;
2980 }
2981
2982 /**
2983  * Get response from Storage daemon to a command we
2984  * sent. Check that the response is OK.
2985  *
2986  *  Returns: 0 on failure
2987  *           1 on success
2988  */
2989 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2990 {
2991    int ret;
2992
2993    if (sd->errors) {
2994       return 0;
2995    }
2996    if ((ret = bget_msg(sd)) > 0) {
2997       Dmsg0(110, sd->msg);
2998       if (strcmp(sd->msg, resp) == 0) {
2999          return 1;
3000       }
3001    }
3002    if (job_canceled(jcr)) {
3003       return 0;                       /* if canceled avoid useless error messages */
3004    }
3005    if (sd->is_error()) {
3006       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
3007          cmd, sd->bstrerror());
3008    } else {
3009       char buf[256];
3010       if (ret > 0) {
3011          Jmsg4(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got len=%ld msg=\"%s\"\n"),
3012             cmd, resp, sd->msglen, smartdump(sd->msg, sd->msglen, buf, sizeof(buf)));
3013       } else {
3014          Jmsg3(jcr, M_FATAL, 0, _("Bad response from SD to %s command. Wanted %s, got SIGNAL %s\n"),
3015             cmd, resp, bnet_sig_to_ascii(ret));
3016       }
3017    }
3018    return 0;
3019 }