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