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