]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
561297044b7fe73d9257a9f5079106fb28f549d9
[bacula/bacula] / bacula / src / filed / job.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2007 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *  Bacula File Daemon Job processing
30  *
31  *    Kern Sibbald, October MM
32  *
33  *   Version $Id$
34  *
35  */
36
37 #include "bacula.h"
38 #include "filed.h"
39
40 #if defined(WIN32_VSS)
41 #include "vss.h"
42
43 static pthread_mutex_t vss_mutex = PTHREAD_MUTEX_INITIALIZER;
44 static int enable_vss;
45 #endif
46
47 extern CLIENT *me;                    /* our client resource */
48
49 /* Imported functions */
50 extern int status_cmd(JCR *jcr);
51 extern int qstatus_cmd(JCR *jcr);
52
53 /* Forward referenced functions */
54 static int backup_cmd(JCR *jcr);
55 static int bootstrap_cmd(JCR *jcr);
56 static int cancel_cmd(JCR *jcr);
57 static int setdebug_cmd(JCR *jcr);
58 static int estimate_cmd(JCR *jcr);
59 static int hello_cmd(JCR *jcr);
60 static int job_cmd(JCR *jcr);
61 static int fileset_cmd(JCR *jcr);
62 static int level_cmd(JCR *jcr);
63 static int verify_cmd(JCR *jcr);
64 static int restore_cmd(JCR *jcr);
65 static int storage_cmd(JCR *jcr);
66 static int session_cmd(JCR *jcr);
67 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
68 static void filed_free_jcr(JCR *jcr);
69 static int open_sd_read_session(JCR *jcr);
70 static int send_bootstrap_file(JCR *jcr);
71 static int runscript_cmd(JCR *jcr);
72 static int runbefore_cmd(JCR *jcr);
73 static int runafter_cmd(JCR *jcr);
74 static int runbeforenow_cmd(JCR *jcr);
75 static void set_options(findFOPTS *fo, const char *opts);
76
77
78 /* Exported functions */
79
80 struct s_cmds {
81    const char *cmd;
82    int (*func)(JCR *);
83    int monitoraccess; /* specify if monitors have access to this function */
84 };
85
86 /*
87  * The following are the recognized commands from the Director.
88  */
89 static struct s_cmds cmds[] = {
90    {"backup",       backup_cmd,    0},
91    {"cancel",       cancel_cmd,    0},
92    {"setdebug=",    setdebug_cmd,  0},
93    {"estimate",     estimate_cmd,  0},
94    {"Hello",        hello_cmd,     1},
95    {"fileset",      fileset_cmd,   0},
96    {"JobId=",       job_cmd,       0},
97    {"level = ",     level_cmd,     0},
98    {"restore",      restore_cmd,   0},
99    {"session",      session_cmd,   0},
100    {"status",       status_cmd,    1},
101    {".status",      qstatus_cmd,   1},
102    {"storage ",     storage_cmd,   0},
103    {"verify",       verify_cmd,    0},
104    {"bootstrap",    bootstrap_cmd, 0},
105    {"RunBeforeNow", runbeforenow_cmd, 0},
106    {"RunBeforeJob", runbefore_cmd, 0},
107    {"RunAfterJob",  runafter_cmd,  0},
108    {"Run",          runscript_cmd, 0},
109    {NULL,       NULL}                  /* list terminator */
110 };
111
112 /* Commands received from director that need scanning */
113 static char jobcmd[]      = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
114 static char storaddr[]    = "storage address=%s port=%d ssl=%d";
115 static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
116 static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
117 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
118 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
119 static char verifycmd[]   = "verify level=%30s";
120 static char estimatecmd[] = "estimate listing=%d";
121 static char runbefore[]   = "RunBeforeJob %s";
122 static char runafter[]    = "RunAfterJob %s";
123 static char runscript[]   = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
124
125 /* Responses sent to Director */
126 static char errmsg[]      = "2999 Invalid command\n";
127 static char no_auth[]     = "2998 No Authorization\n";
128 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
129 static char OKinc[]       = "2000 OK include\n";
130 static char OKest[]       = "2000 OK estimate files=%u bytes=%s\n";
131 static char OKlevel[]     = "2000 OK level\n";
132 static char OKbackup[]    = "2000 OK backup\n";
133 static char OKbootstrap[] = "2000 OK bootstrap\n";
134 static char OKverify[]    = "2000 OK verify\n";
135 static char OKrestore[]   = "2000 OK restore\n";
136 static char OKsession[]   = "2000 OK session\n";
137 static char OKstore[]     = "2000 OK storage\n";
138 static char OKjob[]       = "2000 OK Job %s (%s) %s,%s,%s";
139 static char OKsetdebug[]  = "2000 OK setdebug=%d\n";
140 static char BADjob[]      = "2901 Bad Job\n";
141 static char EndJob[]      = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s"
142                             " JobBytes=%s Errors=%u VSS=%d Encrypt=%d\n";
143 static char OKRunBefore[] = "2000 OK RunBefore\n";
144 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
145 static char OKRunAfter[]  = "2000 OK RunAfter\n";
146 static char OKRunScript[] = "2000 OK RunScript\n";
147
148
149 /* Responses received from Storage Daemon */
150 static char OK_end[]       = "3000 OK end\n";
151 static char OK_close[]     = "3000 OK close Status = %d\n";
152 static char OK_open[]      = "3000 OK open ticket = %d\n";
153 static char OK_data[]      = "3000 OK data\n";
154 static char OK_append[]    = "3000 OK append data\n";
155 static char OKSDbootstrap[]= "3000 OK bootstrap\n";
156
157
158 /* Commands sent to Storage Daemon */
159 static char append_open[]  = "append open session\n";
160 static char append_data[]  = "append data %d\n";
161 static char append_end[]   = "append end session %d\n";
162 static char append_close[] = "append close session %d\n";
163 static char read_open[]    = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
164 static char read_data[]    = "read data %d\n";
165 static char read_close[]   = "read close session %d\n";
166
167 /*
168  * Accept requests from a Director
169  *
170  * NOTE! We are running as a separate thread
171  *
172  * Send output one line
173  * at a time followed by a zero length transmission.
174  *
175  * Return when the connection is terminated or there
176  * is an error.
177  *
178  * Basic task here is:
179  *   Authenticate Director (during Hello command).
180  *   Accept commands one at a time from the Director
181  *     and execute them.
182  *
183  * Concerning ClientRunBefore/After, the sequence of events
184  * is rather critical. If they are not done in the right
185  * order one can easily get FD->SD timeouts if the script
186  * runs a long time.
187  *
188  * The current sequence of events is:
189  *  1. Dir starts job with FD
190  *  2. Dir connects to SD
191  *  3. Dir connects to FD
192  *  4. FD connects to SD
193  *  5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
194  *  6. Dir sends include/exclude
195  *  7. FD sends data to SD
196  *  8. SD/FD disconnects while SD despools data and attributes (optionnal)
197  *  9. FD runs ClientRunAfterJob
198  */
199
200 void *handle_client_request(void *dirp)
201 {
202    int i;
203    bool found, quit;
204    JCR *jcr;
205    BSOCK *dir = (BSOCK *)dirp;
206
207    jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
208    jcr->dir_bsock = dir;
209    jcr->ff = init_find_files();
210    jcr->start_time = time(NULL);
211    jcr->RunScripts = New(alist(10, not_owned_by_alist));
212    jcr->last_fname = get_pool_memory(PM_FNAME);
213    jcr->last_fname[0] = 0;
214    jcr->client_name = get_memory(strlen(my_name) + 1);
215    pm_strcpy(jcr->client_name, my_name);
216    jcr->pki_sign = me->pki_sign;
217    jcr->pki_encrypt = me->pki_encrypt;
218    jcr->pki_keypair = me->pki_keypair;
219    jcr->pki_signers = me->pki_signers;
220    jcr->pki_recipients = me->pki_recipients;
221    dir->set_jcr(jcr);
222    enable_backup_privileges(NULL, 1 /* ignore_errors */);
223
224    /**********FIXME******* add command handler error code */
225
226    for (quit=false; !quit;) {
227
228       /* Read command */
229       if (bnet_recv(dir) < 0) {
230          break;               /* connection terminated */
231       }
232       dir->msg[dir->msglen] = 0;
233       Dmsg1(100, "<dird: %s", dir->msg);
234       found = false;
235       for (i=0; cmds[i].cmd; i++) {
236          if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
237             found = true;         /* indicate command found */
238             if (!jcr->authenticated && cmds[i].func != hello_cmd) {
239                bnet_fsend(dir, no_auth);
240                bnet_sig(dir, BNET_EOD);
241                break;
242             }
243             if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) {
244                Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
245                bnet_fsend(dir, invalid_cmd);
246                bnet_sig(dir, BNET_EOD);
247                break;
248             }
249             Dmsg1(100, "Executing %s command.\n", cmds[i].cmd);
250             if (!cmds[i].func(jcr)) {         /* do command */
251                quit = true;         /* error or fully terminated, get out */
252                Dmsg1(20, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
253             }
254             break;
255          }
256       }
257       if (!found) {              /* command not found */
258          bnet_fsend(dir, errmsg);
259          quit = true;
260          break;
261       }
262    }
263
264    /* Inform Storage daemon that we are done */
265    if (jcr->store_bsock) {
266       bnet_sig(jcr->store_bsock, BNET_TERMINATE);
267    }
268
269    /* Run the after job */
270    run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
271
272    generate_daemon_event(jcr, "JobEnd");
273
274    dequeue_messages(jcr);             /* send any queued messages */
275
276    /* Inform Director that we are done */
277    bnet_sig(dir, BNET_TERMINATE);
278
279    /* Clean up fileset */
280    FF_PKT *ff = jcr->ff;
281    findFILESET *fileset = ff->fileset;
282    if (fileset) {
283       int i, j, k;
284       /* Delete FileSet Include lists */
285       for (i=0; i<fileset->include_list.size(); i++) {
286          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
287          for (j=0; j<incexe->opts_list.size(); j++) {
288             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
289             for (k=0; k<fo->regex.size(); k++) {
290                regfree((regex_t *)fo->regex.get(k));
291             }
292             fo->regex.destroy();
293             fo->regexdir.destroy();
294             fo->regexfile.destroy();
295             fo->wild.destroy();
296             fo->wilddir.destroy();
297             fo->wildfile.destroy();
298             fo->wildbase.destroy();
299             fo->base.destroy();
300             fo->fstype.destroy();
301             fo->drivetype.destroy();
302             if (fo->reader) {
303                free(fo->reader);
304             }
305             if (fo->writer) {
306                free(fo->writer);
307             }
308          }
309          incexe->opts_list.destroy();
310          incexe->name_list.destroy();
311       }
312       fileset->include_list.destroy();
313
314       /* Delete FileSet Exclude lists */
315       for (i=0; i<fileset->exclude_list.size(); i++) {
316          findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
317          for (j=0; j<incexe->opts_list.size(); j++) {
318             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
319             fo->regex.destroy();
320             fo->regexdir.destroy();
321             fo->regexfile.destroy();
322             fo->wild.destroy();
323             fo->wilddir.destroy();
324             fo->wildfile.destroy();
325             fo->wildbase.destroy();
326             fo->base.destroy();
327             fo->fstype.destroy();
328             fo->drivetype.destroy();
329          }
330          incexe->opts_list.destroy();
331          incexe->name_list.destroy();
332       }
333       fileset->exclude_list.destroy();
334       free(fileset);
335    }
336    ff->fileset = NULL;
337    Dmsg0(100, "Calling term_find_files\n");
338    term_find_files(jcr->ff);
339    jcr->ff = NULL;
340    Dmsg0(100, "Done with term_find_files\n");
341    free_jcr(jcr);                     /* destroy JCR record */
342    Dmsg0(100, "Done with free_jcr\n");
343    Dsm_check(1);
344    return NULL;
345 }
346
347 /*
348  * Hello from Director he must identify himself and provide his
349  *  password.
350  */
351 static int hello_cmd(JCR *jcr)
352 {
353    Dmsg0(120, "Calling Authenticate\n");
354    if (!authenticate_director(jcr)) {
355       return 0;
356    }
357    Dmsg0(120, "OK Authenticate\n");
358    jcr->authenticated = true;
359    return 1;
360 }
361
362 /*
363  * Cancel a Job
364  */
365 static int cancel_cmd(JCR *jcr)
366 {
367    BSOCK *dir = jcr->dir_bsock;
368    char Job[MAX_NAME_LENGTH];
369    JCR *cjcr;
370
371    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
372       if (!(cjcr=get_jcr_by_full_name(Job))) {
373          bnet_fsend(dir, _("2901 Job %s not found.\n"), Job);
374       } else {
375          if (cjcr->store_bsock) {
376             cjcr->store_bsock->set_timed_out();
377             cjcr->store_bsock->set_terminated();
378             pthread_kill(cjcr->my_thread_id, TIMEOUT_SIGNAL);
379          }
380          set_jcr_job_status(cjcr, JS_Canceled);
381          free_jcr(cjcr);
382          bnet_fsend(dir, _("2001 Job %s marked to be canceled.\n"), Job);
383       }
384    } else {
385       bnet_fsend(dir, _("2902 Error scanning cancel command.\n"));
386    }
387    bnet_sig(dir, BNET_EOD);
388    return 1;
389 }
390
391
392 /*
393  * Set debug level as requested by the Director
394  *
395  */
396 static int setdebug_cmd(JCR *jcr)
397 {
398    BSOCK *dir = jcr->dir_bsock;
399    int level, trace_flag;
400
401    Dmsg1(110, "setdebug_cmd: %s", dir->msg);
402    if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) {
403       pm_strcpy(jcr->errmsg, dir->msg);
404       bnet_fsend(dir, _("2991 Bad setdebug command: %s\n"), jcr->errmsg);
405       return 0;
406    }
407    debug_level = level;
408    set_trace(trace_flag);
409    return dir->fsend(OKsetdebug, level);
410 }
411
412
413 static int estimate_cmd(JCR *jcr)
414 {
415    BSOCK *dir = jcr->dir_bsock;
416    char ed2[50];
417
418    if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
419       pm_strcpy(jcr->errmsg, dir->msg);
420       Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
421       dir->fsend(_("2992 Bad estimate command.\n"));
422       return 0;
423    }
424    make_estimate(jcr);
425    dir->fsend(OKest, jcr->num_files_examined,
426       edit_uint64_with_commas(jcr->JobBytes, ed2));
427    bnet_sig(dir, BNET_EOD);
428    return 1;
429 }
430
431 /*
432  * Get JobId and Storage Daemon Authorization key from Director
433  */
434 static int job_cmd(JCR *jcr)
435 {
436    BSOCK *dir = jcr->dir_bsock;
437    POOLMEM *sd_auth_key;
438
439    sd_auth_key = get_memory(dir->msglen);
440    if (debug_level == 3) {
441       Dmsg1(000, "<dird: %s", dir->msg);
442    }
443    if (sscanf(dir->msg, jobcmd,  &jcr->JobId, jcr->Job,
444               &jcr->VolSessionId, &jcr->VolSessionTime,
445               sd_auth_key) != 5) {
446       pm_strcpy(jcr->errmsg, dir->msg);
447       Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
448       bnet_fsend(dir, BADjob);
449       free_pool_memory(sd_auth_key);
450       return 0;
451    }
452    jcr->sd_auth_key = bstrdup(sd_auth_key);
453    if (debug_level == 3) {
454       Dmsg1(000, "sd_auth_key=%s\n", jcr->sd_auth_key);
455    }
456    free_pool_memory(sd_auth_key);
457    Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
458    return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
459 }
460
461 static int runbefore_cmd(JCR *jcr)
462 {
463    bool ok;
464    BSOCK *dir = jcr->dir_bsock;
465    POOLMEM *cmd = get_memory(dir->msglen+1);
466    RUNSCRIPT *script;
467
468    Dmsg1(100, "runbefore_cmd: %s", dir->msg);
469    if (sscanf(dir->msg, runbefore, cmd) != 1) {
470       pm_strcpy(jcr->errmsg, dir->msg);
471       Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
472       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
473       free_memory(cmd);
474       return 0;
475    }
476    unbash_spaces(cmd);
477
478    /* Run the command now */
479    script = new_runscript();
480    script->set_command(cmd);
481    script->when = SCRIPT_Before;
482    ok = script->run(jcr, "ClientRunBeforeJob");
483    free_runscript(script);
484
485    free_memory(cmd);
486    if (ok) {
487       bnet_fsend(dir, OKRunBefore);
488       return 1;
489    } else {
490       bnet_fsend(dir, _("2905 Bad RunBeforeJob command.\n"));
491       return 0;
492    }
493 }
494
495 static int runbeforenow_cmd(JCR *jcr)
496 {
497    BSOCK *dir = jcr->dir_bsock;
498
499    run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
500    if (job_canceled(jcr)) {
501       bnet_fsend(dir, _("2905 Bad RunBeforeNow command.\n"));
502       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
503       return 0;
504    } else {
505       bnet_fsend(dir, OKRunBeforeNow);
506       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
507       return 1;
508    }
509 }
510
511 static int runafter_cmd(JCR *jcr)
512 {
513    BSOCK *dir = jcr->dir_bsock;
514    POOLMEM *msg = get_memory(dir->msglen+1);
515    RUNSCRIPT *cmd;
516
517    Dmsg1(100, "runafter_cmd: %s", dir->msg);
518    if (sscanf(dir->msg, runafter, msg) != 1) {
519       pm_strcpy(jcr->errmsg, dir->msg);
520       Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
521       bnet_fsend(dir, _("2905 Bad RunAfterJob command.\n"));
522       free_memory(msg);
523       return 0;
524    }
525    unbash_spaces(msg);
526
527    cmd = new_runscript();
528    cmd->set_command(msg);
529    cmd->on_success = true;
530    cmd->on_failure = false;
531    cmd->when = SCRIPT_After;
532
533    jcr->RunScripts->append(cmd);
534
535    free_pool_memory(msg);
536    return bnet_fsend(dir, OKRunAfter);
537 }
538
539 static int runscript_cmd(JCR *jcr)
540 {
541    BSOCK *dir = jcr->dir_bsock;
542    POOLMEM *msg = get_memory(dir->msglen+1);
543    int on_success, on_failure, fail_on_error;
544
545    RUNSCRIPT *cmd = new_runscript() ;
546
547    Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
548    /* Note, we cannot sscanf into bools */
549    if (sscanf(dir->msg, runscript, &on_success, 
550                                   &on_failure,
551                                   &fail_on_error,
552                                   &cmd->when,
553                                   msg) != 5) {
554       pm_strcpy(jcr->errmsg, dir->msg);
555       Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
556       bnet_fsend(dir, _("2905 Bad RunScript command.\n"));
557       free_runscript(cmd);
558       free_memory(msg);
559       return 0;
560    }
561    cmd->on_success = on_success;
562    cmd->on_failure = on_failure;
563    cmd->fail_on_error = fail_on_error;
564    unbash_spaces(msg);
565
566    cmd->set_command(msg);
567    cmd->debug();
568    jcr->RunScripts->append(cmd);
569
570    free_pool_memory(msg);
571    return bnet_fsend(dir, OKRunScript);
572 }
573
574
575 static bool init_fileset(JCR *jcr)
576 {
577    FF_PKT *ff;
578    findFILESET *fileset;
579
580    if (!jcr->ff) {
581       return false;
582    }
583    ff = jcr->ff;
584    if (ff->fileset) {
585       return false;
586    }
587    fileset = (findFILESET *)malloc(sizeof(findFILESET));
588    memset(fileset, 0, sizeof(findFILESET));
589    ff->fileset = fileset;
590    fileset->state = state_none;
591    fileset->include_list.init(1, true);
592    fileset->exclude_list.init(1, true);
593    return true;
594 }
595
596 static findFOPTS *start_options(FF_PKT *ff)
597 {
598    int state = ff->fileset->state;
599    findINCEXE *incexe = ff->fileset->incexe;
600
601    if (state != state_options) {
602       ff->fileset->state = state_options;
603       findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
604       memset(fo, 0, sizeof(findFOPTS));
605       fo->regex.init(1, true);
606       fo->regexdir.init(1, true);
607       fo->regexfile.init(1, true);
608       fo->wild.init(1, true);
609       fo->wilddir.init(1, true);
610       fo->wildfile.init(1, true);
611       fo->wildbase.init(1, true);
612       fo->base.init(1, true);
613       fo->fstype.init(1, true);
614       fo->drivetype.init(1, true);
615       incexe->current_opts = fo;
616       incexe->opts_list.append(fo);
617    }
618    return incexe->current_opts;
619
620 }
621
622 /*
623  * Add fname to include/exclude fileset list. First check for
624  * | and < and if necessary perform command.
625  */
626 static void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *fileset)
627 {
628    char *p;
629    BPIPE *bpipe;
630    POOLMEM *fn;
631    FILE *ffd;
632    char buf[1000];
633    int ch;
634    int stat;
635
636    p = (char *)fname;
637    ch = (uint8_t)*p;
638    switch (ch) {
639    case '|':
640       p++;                            /* skip over | */
641       fn = get_pool_memory(PM_FNAME);
642       fn = edit_job_codes(jcr, fn, p, "");
643       bpipe = open_bpipe(fn, 0, "r");
644       if (!bpipe) {
645          berrno be;
646          Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
647             p, be.bstrerror());
648          free_pool_memory(fn);
649          return;
650       }
651       free_pool_memory(fn);
652       while (fgets(buf, sizeof(buf), bpipe->rfd)) {
653          strip_trailing_junk(buf);
654          fileset->incexe->name_list.append(new_dlistString(buf));
655       }
656       if ((stat=close_bpipe(bpipe)) != 0) {
657          berrno be;
658          Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
659             p, be.code(stat), be.bstrerror(stat));
660          return;
661       }
662       break;
663    case '<':
664       Dmsg0(100, "Doing < include on client.\n");
665       p++;                      /* skip over < */
666       if ((ffd = fopen(p, "rb")) == NULL) {
667          berrno be;
668          Jmsg(jcr, M_FATAL, 0, _("Cannot open FileSet input file: %s. ERR=%s\n"),
669             p, be.bstrerror());
670          return;
671       }
672       while (fgets(buf, sizeof(buf), ffd)) {
673          strip_trailing_junk(buf);
674          Dmsg1(100, "%s\n", buf);
675          fileset->incexe->name_list.append(new_dlistString(buf));
676       }
677       fclose(ffd);
678       break;
679    default:
680       fileset->incexe->name_list.append(new_dlistString(fname));
681       break;
682    }
683 }
684
685
686 static void add_fileset(JCR *jcr, const char *item)
687 {
688    FF_PKT *ff = jcr->ff;
689    findFILESET *fileset = ff->fileset;
690    int state = fileset->state;
691    findFOPTS *current_opts;
692
693    /* Get code, optional subcode, and position item past the dividing space */
694    Dmsg1(100, "%s\n", item);
695    int code = item[0];
696    if (code != '\0') {
697       ++item;
698    }
699    int subcode = ' ';               /* A space is always a valid subcode */
700    if (item[0] != '\0' && item[0] != ' ') {
701       subcode = item[0];
702       ++item;
703    }
704    if (*item == ' ') {
705       ++item;
706    }
707
708    /* Skip all lines we receive after an error */
709    if (state == state_error) {
710       Dmsg0(100, "State=error return\n");
711       return;
712    }
713
714    /*
715     * The switch tests the code for validity.
716     * The subcode is always good if it is a space, otherwise we must confirm.
717     * We set state to state_error first assuming the subcode is invalid,
718     * requiring state to be set in cases below that handle subcodes.
719     */
720    if (subcode != ' ') {
721       state = state_error;
722       Dmsg0(100, "Set state=error\n"); 
723    }
724    switch (code) {
725    case 'I':
726       /* New include */
727       fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
728       memset(fileset->incexe, 0, sizeof(findINCEXE));
729       fileset->incexe->opts_list.init(1, true);
730       fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
731       fileset->include_list.append(fileset->incexe);
732       break;
733    case 'E':
734       /* New exclude */
735       fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
736       memset(fileset->incexe, 0, sizeof(findINCEXE));
737       fileset->incexe->opts_list.init(1, true);
738       fileset->incexe->name_list.init();
739       fileset->exclude_list.append(fileset->incexe);
740       break;
741    case 'N':
742       state = state_none;
743       break;
744    case 'F':
745       /* File item to either include/include list */
746       state = state_include;
747       add_file_to_fileset(jcr, item, fileset);
748       break;
749    case 'R':
750       current_opts = start_options(ff);
751       regex_t *preg;
752       int rc;
753       char prbuf[500];
754       preg = (regex_t *)malloc(sizeof(regex_t));
755       if (current_opts->flags & FO_IGNORECASE) {
756          rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
757       } else {
758          rc = regcomp(preg, item, REG_EXTENDED);
759       }
760       if (rc != 0) {
761          regerror(rc, preg, prbuf, sizeof(prbuf));
762          regfree(preg);
763          free(preg);
764          Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
765          state = state_error;
766          break;
767       }
768       state = state_options;
769       if (subcode == ' ') {
770          current_opts->regex.append(preg);
771       } else if (subcode == 'D') {
772          current_opts->regexdir.append(preg);
773       } else if (subcode == 'F') {
774          current_opts->regexfile.append(preg);
775       } else {
776          state = state_error;
777       }
778       break;
779    case 'B':
780       current_opts = start_options(ff);
781       current_opts->base.append(bstrdup(item));
782       state = state_options;
783       break;
784    case 'X':
785       current_opts = start_options(ff);
786       state = state_options;
787       if (subcode == ' ') {
788          current_opts->fstype.append(bstrdup(item));
789       } else if (subcode == 'D') {
790          current_opts->drivetype.append(bstrdup(item));
791       } else {
792          state = state_error;
793       }
794       break;
795    case 'W':
796       current_opts = start_options(ff);
797       state = state_options;
798       if (subcode == ' ') {
799          current_opts->wild.append(bstrdup(item));
800       } else if (subcode == 'D') {
801          current_opts->wilddir.append(bstrdup(item));
802       } else if (subcode == 'F') {
803          current_opts->wildfile.append(bstrdup(item));
804       } else if (subcode == 'B') {
805          current_opts->wildbase.append(bstrdup(item));
806       } else {
807          state = state_error;
808       }
809       break;
810    case 'O':
811       current_opts = start_options(ff);
812       set_options(current_opts, item);
813       state = state_options;
814       break;
815    case 'D':
816       current_opts = start_options(ff);
817       current_opts->reader = bstrdup(item);
818       state = state_options;
819       break;
820    case 'T':
821       current_opts = start_options(ff);
822       current_opts->writer = bstrdup(item);
823       state = state_options;
824       break;
825    default:
826       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
827       state = state_error;
828       break;
829    }
830    ff->fileset->state = state;
831 }
832
833 static bool term_fileset(JCR *jcr)
834 {
835    FF_PKT *ff = jcr->ff;
836
837 #ifdef xxx
838    findFILESET *fileset = ff->fileset;
839    int i, j, k;
840
841    for (i=0; i<fileset->include_list.size(); i++) {
842       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
843       Dmsg0(400, "I\n");
844       for (j=0; j<incexe->opts_list.size(); j++) {
845          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
846          for (k=0; k<fo->regex.size(); k++) {
847             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
848          }
849          for (k=0; k<fo->regexdir.size(); k++) {
850             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
851          }
852          for (k=0; k<fo->regexfile.size(); k++) {
853             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
854          }
855          for (k=0; k<fo->wild.size(); k++) {
856             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
857          }
858          for (k=0; k<fo->wilddir.size(); k++) {
859             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
860          }
861          for (k=0; k<fo->wildfile.size(); k++) {
862             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
863          }
864          for (k=0; k<fo->wildbase.size(); k++) {
865             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
866          }
867          for (k=0; k<fo->base.size(); k++) {
868             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
869          }
870          for (k=0; k<fo->fstype.size(); k++) {
871             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
872          }
873          for (k=0; k<fo->drivetype.size(); k++) {
874             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
875          }
876          if (fo->reader) {
877             Dmsg1(400, "D %s\n", fo->reader);
878          }
879          if (fo->writer) {
880             Dmsg1(400, "T %s\n", fo->writer);
881          }
882       }
883       dlistString *node;
884       foreach_dlist(node, &incexe->name_list) {
885          Dmsg1(400, "F %s\n", node->c_str());
886       }
887    }
888    for (i=0; i<fileset->exclude_list.size(); i++) {
889       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
890       Dmsg0(400, "E\n");
891       for (j=0; j<incexe->opts_list.size(); j++) {
892          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
893          for (k=0; k<fo->regex.size(); k++) {
894             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
895          }
896          for (k=0; k<fo->regexdir.size(); k++) {
897             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
898          }
899          for (k=0; k<fo->regexfile.size(); k++) {
900             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
901          }
902          for (k=0; k<fo->wild.size(); k++) {
903             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
904          }
905          for (k=0; k<fo->wilddir.size(); k++) {
906             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
907          }
908          for (k=0; k<fo->wildfile.size(); k++) {
909             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
910          }
911          for (k=0; k<fo->wildbase.size(); k++) {
912             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
913          }
914          for (k=0; k<fo->base.size(); k++) {
915             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
916          }
917          for (k=0; k<fo->fstype.size(); k++) {
918             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
919          }
920          for (k=0; k<fo->drivetype.size(); k++) {
921             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
922          }
923       }
924       dlistString *node;
925       foreach_dlist(node, incexe->name_list) {
926          Dmsg1(400, "F %s\n", node->c_str());
927       }
928    }
929 #endif
930    return ff->fileset->state != state_error;
931 }
932
933
934 /*
935  * As an optimization, we should do this during
936  *  "compile" time in filed/job.c, and keep only a bit mask
937  *  and the Verify options.
938  */
939 static void set_options(findFOPTS *fo, const char *opts)
940 {
941    int j;
942    const char *p;
943    char strip[100];
944
945    for (p=opts; *p; p++) {
946       switch (*p) {
947       case 'a':                 /* alway replace */
948       case '0':                 /* no option */
949          break;
950       case 'e':
951          fo->flags |= FO_EXCLUDE;
952          break;
953       case 'f':
954          fo->flags |= FO_MULTIFS;
955          break;
956       case 'h':                 /* no recursion */
957          fo->flags |= FO_NO_RECURSION;
958          break;
959       case 'H':                 /* no hard link handling */
960          fo->flags |= FO_NO_HARDLINK;
961          break;
962       case 'i':
963          fo->flags |= FO_IGNORECASE;
964          break;
965       case 'M':                 /* MD5 */
966          fo->flags |= FO_MD5;
967          break;
968       case 'n':
969          fo->flags |= FO_NOREPLACE;
970          break;
971       case 'p':                 /* use portable data format */
972          fo->flags |= FO_PORTABLE;
973          break;
974       case 'R':                 /* Resource forks and Finder Info */
975          fo->flags |= FO_HFSPLUS;
976       case 'r':                 /* read fifo */
977          fo->flags |= FO_READFIFO;
978          break;
979       case 'S':
980          switch(*(p + 1)) {
981          case '1':
982             fo->flags |= FO_SHA1;
983             p++;
984             break;
985 #ifdef HAVE_SHA2
986          case '2':
987             fo->flags |= FO_SHA256;
988             p++;
989             break;
990          case '3':
991             fo->flags |= FO_SHA512;
992             p++;
993             break;
994 #endif
995          default:
996             /*
997              * If 2 or 3 is seen here, SHA2 is not configured, so
998              *  eat the option, and drop back to SHA-1.
999              */
1000             if (p[1] == '2' || p[1] == '3') {
1001                p++;
1002             }
1003             fo->flags |= FO_SHA1;
1004             break;
1005          }
1006          break;
1007       case 's':
1008          fo->flags |= FO_SPARSE;
1009          break;
1010       case 'm':
1011          fo->flags |= FO_MTIMEONLY;
1012          break;
1013       case 'k':
1014          fo->flags |= FO_KEEPATIME;
1015          break;
1016       case 'A':
1017          fo->flags |= FO_ACL;
1018          break;
1019       case 'V':                  /* verify options */
1020          /* Copy Verify Options */
1021          for (j=0; *p && *p != ':'; p++) {
1022             fo->VerifyOpts[j] = *p;
1023             if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1024                j++;
1025             }
1026          }
1027          fo->VerifyOpts[j] = 0;
1028          break;
1029       case 'P':                  /* strip path */
1030          /* Get integer */
1031          p++;                    /* skip P */
1032          for (j=0; *p && *p != ':'; p++) {
1033             strip[j] = *p;
1034             if (j < (int)sizeof(strip) - 1) {
1035                j++;
1036             }
1037          }
1038          strip[j] = 0;
1039          fo->strip_path = atoi(strip);
1040          fo->flags |= FO_STRIPPATH;
1041          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1042          break;
1043       case 'w':
1044          fo->flags |= FO_IF_NEWER;
1045          break;
1046       case 'W':
1047          fo->flags |= FO_ENHANCEDWILD;
1048          break;
1049       case 'Z':                 /* gzip compression */
1050          fo->flags |= FO_GZIP;
1051          fo->GZIP_level = *++p - '0';
1052          break;
1053       case 'K':
1054          fo->flags |= FO_NOATIME;
1055          break;
1056       case 'c':
1057          fo->flags |= FO_CHKCHANGES;
1058          break;
1059       default:
1060          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1061          break;
1062       }
1063    }
1064 }
1065
1066
1067 /*
1068  * Director is passing his Fileset
1069  */
1070 static int fileset_cmd(JCR *jcr)
1071 {
1072    BSOCK *dir = jcr->dir_bsock;
1073
1074 #if defined(WIN32_VSS)
1075    int vss = 0;
1076
1077    sscanf(dir->msg, "fileset vss=%d", &vss);
1078    enable_vss = vss;
1079 #endif
1080
1081    if (!init_fileset(jcr)) {
1082       return 0;
1083    }
1084    while (bnet_recv(dir) >= 0) {
1085       strip_trailing_junk(dir->msg);
1086       Dmsg1(500, "Fileset: %s\n", dir->msg);
1087       add_fileset(jcr, dir->msg);
1088    }
1089    if (!term_fileset(jcr)) {
1090       return 0;
1091    }
1092    return bnet_fsend(dir, OKinc);
1093 }
1094
1095 static void free_bootstrap(JCR *jcr)
1096 {
1097    if (jcr->RestoreBootstrap) {
1098       unlink(jcr->RestoreBootstrap);
1099       free_pool_memory(jcr->RestoreBootstrap);
1100       jcr->RestoreBootstrap = NULL;
1101    }
1102 }
1103
1104
1105 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1106 static uint32_t bsr_uniq = 0;
1107
1108 /* 
1109  * The Director sends us the bootstrap file, which
1110  *   we will in turn pass to the SD.
1111  */
1112 static int bootstrap_cmd(JCR *jcr)
1113 {
1114    BSOCK *dir = jcr->dir_bsock;
1115    POOLMEM *fname = get_pool_memory(PM_FNAME);
1116    FILE *bs;
1117
1118    free_bootstrap(jcr);
1119    P(bsr_mutex);
1120    bsr_uniq++;
1121    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1122       jcr->Job, bsr_uniq);
1123    V(bsr_mutex);
1124    Dmsg1(400, "bootstrap=%s\n", fname);
1125    jcr->RestoreBootstrap = fname;
1126    bs = fopen(fname, "a+b");           /* create file */
1127    if (!bs) {
1128       berrno be;
1129       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1130          jcr->RestoreBootstrap, be.bstrerror());
1131       /*
1132        * Suck up what he is sending to us so that he will then
1133        *   read our error message.
1134        */
1135       while (bnet_recv(dir) >= 0)
1136         {  }
1137       free_bootstrap(jcr);
1138       set_jcr_job_status(jcr, JS_ErrorTerminated);
1139       return 0;
1140    }
1141
1142    while (bnet_recv(dir) >= 0) {
1143        Dmsg1(200, "filed<dird: bootstrap file %s\n", dir->msg);
1144        fputs(dir->msg, bs);
1145    }
1146    fclose(bs);
1147    /*
1148     * Note, do not free the bootstrap yet -- it needs to be 
1149     *  sent to the SD 
1150     */
1151    return bnet_fsend(dir, OKbootstrap);
1152 }
1153
1154
1155 /*
1156  * Get backup level from Director
1157  *
1158  */
1159 static int level_cmd(JCR *jcr)
1160 {
1161    BSOCK *dir = jcr->dir_bsock;
1162    POOLMEM *level, *buf = NULL;
1163    int mtime_only;
1164
1165    level = get_memory(dir->msglen+1);
1166    Dmsg1(110, "level_cmd: %s", dir->msg);
1167    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1168       goto bail_out;
1169    }
1170    /* Base backup requested? */
1171    if (strcmp(level, "base") == 0) {
1172       jcr->JobLevel = L_BASE;
1173    /* Full backup requested? */
1174    } else if (strcmp(level, "full") == 0) {
1175       jcr->JobLevel = L_FULL;
1176    } else if (strcmp(level, "differential") == 0) {
1177       jcr->JobLevel = L_DIFFERENTIAL;
1178       free_memory(level);
1179       return 1;
1180    } else if (strcmp(level, "incremental") == 0) {
1181       jcr->JobLevel = L_INCREMENTAL;
1182       free_memory(level);
1183       return 1;   
1184    /*
1185     * We get his UTC since time, then sync the clocks and correct it
1186     *   to agree with our clock.
1187     */
1188    } else if (strcmp(level, "since_utime") == 0) {
1189       buf = get_memory(dir->msglen+1);
1190       utime_t since_time, adj;
1191       btime_t his_time, bt_start, rt=0, bt_adj=0;
1192       if (jcr->JobLevel == L_NONE) {
1193          jcr->JobLevel = L_SINCE;     /* if no other job level set, do it now */
1194       }
1195       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1196                  buf, &mtime_only) != 2) {
1197          goto bail_out;
1198       }
1199       since_time = str_to_uint64(buf);  /* this is the since time */
1200       Dmsg1(100, "since_time=%d\n", (int)since_time);
1201       char ed1[50], ed2[50];
1202       /*
1203        * Sync clocks by polling him for the time. We take
1204        *   10 samples of his time throwing out the first two.
1205        */
1206       for (int i=0; i<10; i++) {
1207          bt_start = get_current_btime();
1208          bnet_sig(dir, BNET_BTIME);   /* poll for time */
1209          if (bnet_recv(dir) <= 0) {   /* get response */
1210             goto bail_out;
1211          }
1212          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1213             goto bail_out;
1214          }
1215          if (i < 2) {                 /* toss first two results */
1216             continue;
1217          }
1218          his_time = str_to_uint64(buf);
1219          rt = get_current_btime() - bt_start; /* compute round trip time */
1220          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1221                edit_uint64(bt_start, ed2));
1222          bt_adj +=  bt_start - his_time - rt/2;
1223          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1224       }
1225
1226       bt_adj = bt_adj / 8;            /* compute average time */
1227       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1228       adj = btime_to_utime(bt_adj);
1229       since_time += adj;              /* adjust for clock difference */
1230       /* Don't notify if time within 3 seconds */
1231       if (adj > 3 || adj < -3) {
1232          int type;
1233          if (adj > 600 || adj < -600) {
1234             type = M_WARNING;
1235          } else {
1236             type = M_INFO;
1237          }
1238          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %d seconds, FD automatically compensating.\n"), adj);
1239       }
1240       bnet_sig(dir, BNET_EOD);
1241
1242       Dmsg2(100, "adj = %d since_time=%d\n", (int)adj, (int)since_time);
1243       jcr->incremental = 1;           /* set incremental or decremental backup */
1244       jcr->mtime = (time_t)since_time; /* set since time */
1245    } else {
1246       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1247       free_memory(level);
1248       return 0;
1249    }
1250    free_memory(level);
1251    if (buf) {
1252       free_memory(buf);
1253    }
1254    return bnet_fsend(dir, OKlevel);
1255
1256 bail_out:
1257    pm_strcpy(jcr->errmsg, dir->msg);
1258    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1259    free_memory(level);
1260    if (buf) {
1261       free_memory(buf);
1262    }
1263    return 0;
1264 }
1265
1266 /*
1267  * Get session parameters from Director -- this is for a Restore command
1268  */
1269 static int session_cmd(JCR *jcr)
1270 {
1271    BSOCK *dir = jcr->dir_bsock;
1272
1273    Dmsg1(100, "SessionCmd: %s", dir->msg);
1274    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1275               &jcr->VolSessionId, &jcr->VolSessionTime,
1276               &jcr->StartFile, &jcr->EndFile,
1277               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1278       pm_strcpy(jcr->errmsg, dir->msg);
1279       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1280       return 0;
1281    }
1282
1283    return bnet_fsend(dir, OKsession);
1284 }
1285
1286 /*
1287  * Get address of storage daemon from Director
1288  *
1289  */
1290 static int storage_cmd(JCR *jcr)
1291 {
1292    int stored_port;                /* storage daemon port */
1293    int enable_ssl;                 /* enable ssl to sd */
1294    BSOCK *dir = jcr->dir_bsock;
1295    BSOCK *sd;                         /* storage daemon bsock */
1296
1297    Dmsg1(100, "StorageCmd: %s", dir->msg);
1298    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, &enable_ssl) != 3) {
1299       pm_strcpy(jcr->errmsg, dir->msg);
1300       Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1301       return 0;
1302    }
1303    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, enable_ssl);
1304    /* Open command communications with Storage daemon */
1305    /* Try to connect for 1 hour at 10 second intervals */
1306    sd = bnet_connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1307                       _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1);
1308    if (sd == NULL) {
1309       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1310           jcr->stored_addr, stored_port);
1311       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1312           jcr->stored_addr, stored_port);
1313       return 0;
1314    }
1315    Dmsg0(110, "Connection OK to SD.\n");
1316
1317    jcr->store_bsock = sd;
1318
1319    bnet_fsend(sd, "Hello Start Job %s\n", jcr->Job);
1320    if (!authenticate_storagedaemon(jcr)) {
1321       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1322       return 0;
1323    }
1324    Dmsg0(110, "Authenticated with SD.\n");
1325
1326    /* Send OK to Director */
1327    return bnet_fsend(dir, OKstore);
1328 }
1329
1330
1331 /*
1332  * Do a backup.
1333  */
1334 static int backup_cmd(JCR *jcr)
1335 {
1336    BSOCK *dir = jcr->dir_bsock;
1337    BSOCK *sd = jcr->store_bsock;
1338    int ok = 0;
1339    int SDJobStatus;
1340    char ed1[50], ed2[50];
1341    bool bDoVSS = false;
1342
1343 #if defined(WIN32_VSS)
1344    // capture state here, if client is backed up by multiple directors
1345    // and one enables vss and the other does not then enable_vss can change
1346    // between here and where its evaluated after the job completes.
1347    bDoVSS = g_pVSSClient && enable_vss;
1348    if (bDoVSS) {
1349       /* Run only one at a time */
1350       P(vss_mutex);
1351    }
1352 #endif
1353
1354    set_jcr_job_status(jcr, JS_Blocked);
1355    jcr->JobType = JT_BACKUP;
1356    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1357
1358    if (sd == NULL) {
1359       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1360       goto cleanup;
1361    }
1362
1363    bnet_fsend(dir, OKbackup);
1364    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1365
1366    /*
1367     * Send Append Open Session to Storage daemon
1368     */
1369    bnet_fsend(sd, append_open);
1370    Dmsg1(110, ">stored: %s", sd->msg);
1371    /*
1372     * Expect to receive back the Ticket number
1373     */
1374    if (bget_msg(sd) >= 0) {
1375       Dmsg1(110, "<stored: %s", sd->msg);
1376       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1377          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1378          goto cleanup;
1379       }
1380       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1381    } else {
1382       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1383       goto cleanup;
1384    }
1385
1386    /*
1387     * Send Append data command to Storage daemon
1388     */
1389    bnet_fsend(sd, append_data, jcr->Ticket);
1390    Dmsg1(110, ">stored: %s", sd->msg);
1391
1392    /*
1393     * Expect to get OK data
1394     */
1395    Dmsg1(110, "<stored: %s", sd->msg);
1396    if (!response(jcr, sd, OK_data, "Append Data")) {
1397       goto cleanup;
1398    }
1399    
1400    generate_daemon_event(jcr, "JobStart");
1401
1402 #if defined(WIN32_VSS)
1403    /* START VSS ON WIN 32 */
1404    if (bDoVSS) {      
1405       if (g_pVSSClient->InitializeForBackup()) {   
1406         /* tell vss which drives to snapshot */   
1407         char szWinDriveLetters[27];   
1408         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1409             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1410             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1411                Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed.\n"));
1412                jcr->Errors++;
1413             } else {
1414                /* tell user if snapshot creation of a specific drive failed */
1415                int i;
1416                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1417                   if (islower(szWinDriveLetters[i])) {
1418                      Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed. VSS support is disabled on this drive.\n"), szWinDriveLetters[i]);
1419                      jcr->Errors++;
1420                   }
1421                }
1422                /* inform user about writer states */
1423                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++)                
1424                   if (g_pVSSClient->GetWriterState(i) < 1) {
1425                      Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1426                      jcr->Errors++;
1427                   }                            
1428             }
1429         } else {
1430             Jmsg(jcr, M_INFO, 0, _("No drive letters found for generating VSS snapshots.\n"));
1431         }
1432       } else {
1433          berrno be;
1434          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
1435       } 
1436    }
1437 #endif
1438
1439    /*
1440     * Send Files to Storage daemon
1441     */
1442    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1443    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1444       set_jcr_job_status(jcr, JS_ErrorTerminated);
1445       bnet_suppress_error_messages(sd, 1);
1446       bget_msg(sd);                   /* Read final response from append_data */
1447       Dmsg0(110, "Error in blast_data.\n");
1448    } else {
1449       set_jcr_job_status(jcr, JS_Terminated);
1450
1451       if (jcr->JobStatus != JS_Terminated) {
1452          bnet_suppress_error_messages(sd, 1);
1453          goto cleanup;                /* bail out now */
1454       }
1455       /*
1456        * Expect to get response to append_data from Storage daemon
1457        */
1458       if (!response(jcr, sd, OK_append, "Append Data")) {
1459          set_jcr_job_status(jcr, JS_ErrorTerminated);
1460          goto cleanup;
1461       }
1462
1463       /*
1464        * Send Append End Data to Storage daemon
1465        */
1466       bnet_fsend(sd, append_end, jcr->Ticket);
1467       /* Get end OK */
1468       if (!response(jcr, sd, OK_end, "Append End")) {
1469          set_jcr_job_status(jcr, JS_ErrorTerminated);
1470          goto cleanup;
1471       }
1472
1473       /*
1474        * Send Append Close to Storage daemon
1475        */
1476       bnet_fsend(sd, append_close, jcr->Ticket);
1477       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1478          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1479             ok = 1;
1480             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1481          }
1482       }
1483       if (!ok) {
1484          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1485          goto cleanup;
1486       }
1487       if (SDJobStatus != JS_Terminated) {
1488          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1489             SDJobStatus);
1490       }
1491    }
1492
1493 cleanup:
1494 #if defined(WIN32_VSS)
1495    /* STOP VSS ON WIN 32 */
1496    /* tell vss to close the backup session */
1497    if (bDoVSS) {
1498       if (g_pVSSClient->CloseBackup()) {             
1499          /* inform user about writer states */
1500          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1501             int msg_type = M_INFO;
1502             if (g_pVSSClient->GetWriterState(i) < 1) {
1503                msg_type = M_WARNING;
1504                jcr->Errors++;
1505             }
1506             Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1507          }
1508       }
1509       V(vss_mutex);
1510    }
1511 #endif
1512
1513    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1514       edit_uint64(jcr->ReadBytes, ed1),
1515       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, (int)bDoVSS, 
1516       jcr->pki_encrypt);
1517    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1518    
1519    return 0;                          /* return and stop command loop */
1520 }
1521
1522 /*
1523  * Do a Verify for Director
1524  *
1525  */
1526 static int verify_cmd(JCR *jcr)
1527 {
1528    BSOCK *dir = jcr->dir_bsock;
1529    BSOCK *sd  = jcr->store_bsock;
1530    char level[100], ed1[50], ed2[50];
1531
1532    jcr->JobType = JT_VERIFY;
1533    if (sscanf(dir->msg, verifycmd, level) != 1) {
1534       bnet_fsend(dir, _("2994 Bad verify command: %s\n"), dir->msg);
1535       return 0;
1536    }
1537
1538    if (strcasecmp(level, "init") == 0) {
1539       jcr->JobLevel = L_VERIFY_INIT;
1540    } else if (strcasecmp(level, "catalog") == 0){
1541       jcr->JobLevel = L_VERIFY_CATALOG;
1542    } else if (strcasecmp(level, "volume") == 0){
1543       jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
1544    } else if (strcasecmp(level, "data") == 0){
1545       jcr->JobLevel = L_VERIFY_DATA;
1546    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1547       jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
1548    } else {
1549       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1550       return 0;
1551    }
1552
1553    bnet_fsend(dir, OKverify);
1554
1555    generate_daemon_event(jcr, "JobStart");
1556
1557    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1558
1559    switch (jcr->JobLevel) {
1560    case L_VERIFY_INIT:
1561    case L_VERIFY_CATALOG:
1562       do_verify(jcr);
1563       break;
1564    case L_VERIFY_VOLUME_TO_CATALOG:
1565       if (!open_sd_read_session(jcr)) {
1566          return 0;
1567       }
1568       start_dir_heartbeat(jcr);
1569       do_verify_volume(jcr);
1570       stop_dir_heartbeat(jcr);
1571       /*
1572        * Send Close session command to Storage daemon
1573        */
1574       bnet_fsend(sd, read_close, jcr->Ticket);
1575       Dmsg1(130, "bfiled>stored: %s", sd->msg);
1576
1577       /* ****FIXME**** check response */
1578       bget_msg(sd);                      /* get OK */
1579
1580       /* Inform Storage daemon that we are done */
1581       bnet_sig(sd, BNET_TERMINATE);
1582
1583       break;
1584    case L_VERIFY_DISK_TO_CATALOG:
1585       do_verify(jcr);
1586       break;
1587    default:
1588       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1589       return 0;
1590    }
1591
1592    bnet_sig(dir, BNET_EOD);
1593
1594    /* Send termination status back to Dir */
1595    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1596       edit_uint64(jcr->ReadBytes, ed1),
1597       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1598       jcr->pki_encrypt);
1599    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1600
1601    /* Inform Director that we are done */
1602    bnet_sig(dir, BNET_TERMINATE);
1603    return 0;                          /* return and terminate command loop */
1604 }
1605
1606 /*
1607  * Do a Restore for Director
1608  *
1609  */
1610 static int restore_cmd(JCR *jcr)
1611 {
1612    BSOCK *dir = jcr->dir_bsock;
1613    BSOCK *sd = jcr->store_bsock;
1614    POOLMEM *args;
1615    bool use_regexwhere=false;
1616    int prefix_links;
1617    char replace;
1618    char ed1[50], ed2[50];
1619
1620    /*
1621     * Scan WHERE (base directory for restore) from command
1622     */
1623    Dmsg0(150, "restore command\n");
1624    /* Pickup where string */
1625    args = get_memory(dir->msglen+1);
1626    *args = 0;
1627
1628    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
1629       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
1630          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
1631             pm_strcpy(jcr->errmsg, dir->msg);
1632             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
1633             return 0;
1634          }
1635          *args = 0;
1636       }
1637       use_regexwhere = true;
1638    }
1639    /* Turn / into nothing */
1640    if (IsPathSeparator(args[0]) && args[1] == '\0') {
1641       args[0] = '\0';
1642    }
1643
1644    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
1645    unbash_spaces(args);
1646
1647    if (use_regexwhere) {
1648       jcr->where_bregexp = get_bregexps(args);
1649       if (!jcr->where_bregexp) {
1650          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
1651          free_pool_memory(args);
1652          return 0;
1653       }
1654    } else {
1655       jcr->where = bstrdup(args);
1656    }
1657
1658    free_pool_memory(args);
1659    jcr->replace = replace;
1660    jcr->prefix_links = prefix_links;
1661
1662    bnet_fsend(dir, OKrestore);
1663    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1664
1665    jcr->JobType = JT_RESTORE;
1666
1667    set_jcr_job_status(jcr, JS_Blocked);
1668
1669    if (!open_sd_read_session(jcr)) {
1670       set_jcr_job_status(jcr, JS_ErrorTerminated);
1671       goto bail_out;
1672    }
1673
1674    set_jcr_job_status(jcr, JS_Running);
1675
1676    /*
1677     * Do restore of files and data
1678     */
1679    start_dir_heartbeat(jcr);
1680    generate_daemon_event(jcr, "JobStart");
1681    do_restore(jcr);
1682    stop_dir_heartbeat(jcr);
1683
1684    set_jcr_job_status(jcr, JS_Terminated);
1685    if (jcr->JobStatus != JS_Terminated) {
1686       bnet_suppress_error_messages(sd, 1);
1687    }
1688
1689    /*
1690     * Send Close session command to Storage daemon
1691     */
1692    bnet_fsend(sd, read_close, jcr->Ticket);
1693    Dmsg1(130, "bfiled>stored: %s", sd->msg);
1694
1695    bget_msg(sd);                      /* get OK */
1696
1697    /* Inform Storage daemon that we are done */
1698    bnet_sig(sd, BNET_TERMINATE);
1699
1700 bail_out:
1701
1702    if (jcr->Errors) {
1703       set_jcr_job_status(jcr, JS_ErrorTerminated);
1704    }
1705    /* Send termination status back to Dir */
1706    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1707       edit_uint64(jcr->ReadBytes, ed1),
1708       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1709       jcr->pki_encrypt);
1710    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1711
1712    /* Inform Director that we are done */
1713    bnet_sig(dir, BNET_TERMINATE);
1714
1715    Dmsg0(130, "Done in job.c\n");
1716    return 0;                          /* return and terminate command loop */
1717 }
1718
1719 static int open_sd_read_session(JCR *jcr)
1720 {
1721    BSOCK *sd = jcr->store_bsock;
1722
1723    if (!sd) {
1724       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
1725       return 0;
1726    }
1727    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
1728       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
1729    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
1730    /*
1731     * Open Read Session with Storage daemon
1732     */
1733    bnet_fsend(sd, read_open, "DummyVolume",
1734       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
1735       jcr->StartBlock, jcr->EndBlock);
1736    Dmsg1(110, ">stored: %s", sd->msg);
1737
1738    /*
1739     * Get ticket number
1740     */
1741    if (bget_msg(sd) >= 0) {
1742       Dmsg1(110, "bfiled<stored: %s", sd->msg);
1743       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1744          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
1745          return 0;
1746       }
1747       Dmsg1(110, "bfiled: got Ticket=%d\n", jcr->Ticket);
1748    } else {
1749       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
1750       return 0;
1751    }
1752
1753    if (!send_bootstrap_file(jcr)) {
1754       return 0;
1755    }
1756
1757    /*
1758     * Start read of data with Storage daemon
1759     */
1760    bnet_fsend(sd, read_data, jcr->Ticket);
1761    Dmsg1(110, ">stored: %s", sd->msg);
1762
1763    /*
1764     * Get OK data
1765     */
1766    if (!response(jcr, sd, OK_data, "Read Data")) {
1767       return 0;
1768    }
1769    return 1;
1770 }
1771
1772 /*
1773  * Destroy the Job Control Record and associated
1774  * resources (sockets).
1775  */
1776 static void filed_free_jcr(JCR *jcr)
1777 {
1778    if (jcr->store_bsock) {
1779       bnet_close(jcr->store_bsock);
1780    }
1781    free_bootstrap(jcr);
1782    if (jcr->last_fname) {
1783       free_pool_memory(jcr->last_fname);
1784    }
1785    free_runscripts(jcr->RunScripts);
1786    delete jcr->RunScripts;
1787
1788    return;
1789 }
1790
1791 /*
1792  * Get response from Storage daemon to a command we
1793  * sent. Check that the response is OK.
1794  *
1795  *  Returns: 0 on failure
1796  *           1 on success
1797  */
1798 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
1799 {
1800    if (sd->errors) {
1801       return 0;
1802    }
1803    if (bget_msg(sd) > 0) {
1804       Dmsg0(110, sd->msg);
1805       if (strcmp(sd->msg, resp) == 0) {
1806          return 1;
1807       }
1808    }
1809    if (job_canceled(jcr)) {
1810       return 0;                       /* if canceled avoid useless error messages */
1811    }
1812    if (is_bnet_error(sd)) {
1813       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
1814          cmd, bnet_strerror(sd));
1815    } else {
1816       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
1817          cmd, resp, sd->msg);
1818    }
1819    return 0;
1820 }
1821
1822 static int send_bootstrap_file(JCR *jcr)
1823 {
1824    FILE *bs;
1825    char buf[2000];
1826    BSOCK *sd = jcr->store_bsock;
1827    const char *bootstrap = "bootstrap\n";
1828    int stat = 0;
1829
1830    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
1831    if (!jcr->RestoreBootstrap) {
1832       return 1;
1833    }
1834    bs = fopen(jcr->RestoreBootstrap, "rb");
1835    if (!bs) {
1836       berrno be;
1837       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
1838          jcr->RestoreBootstrap, be.bstrerror());
1839       set_jcr_job_status(jcr, JS_ErrorTerminated);
1840       goto bail_out;
1841    }
1842    sd->msglen = pm_strcpy(sd->msg, bootstrap);
1843    bnet_send(sd);
1844    while (fgets(buf, sizeof(buf), bs)) {
1845       sd->msglen = Mmsg(sd->msg, "%s", buf);
1846       bnet_send(sd);
1847    }
1848    bnet_sig(sd, BNET_EOD);
1849    fclose(bs);
1850    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
1851       set_jcr_job_status(jcr, JS_ErrorTerminated);
1852       goto bail_out;
1853    }
1854    stat = 1;
1855
1856 bail_out:
1857    free_bootstrap(jcr);
1858    return stat;
1859 }