]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
ebl fix the last patch to do only ignorecase on win32
[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 #ifdef HAVE_WIN32
940    fo->flags |= FO_IGNORECASE; /* always ignorecase under windows */
941 #endif
942
943    for (p=opts; *p; p++) {
944       switch (*p) {
945       case 'a':                 /* alway replace */
946       case '0':                 /* no option */
947          break;
948       case 'e':
949          fo->flags |= FO_EXCLUDE;
950          break;
951       case 'f':
952          fo->flags |= FO_MULTIFS;
953          break;
954       case 'h':                 /* no recursion */
955          fo->flags |= FO_NO_RECURSION;
956          break;
957       case 'H':                 /* no hard link handling */
958          fo->flags |= FO_NO_HARDLINK;
959          break;
960       case 'i':
961          fo->flags |= FO_IGNORECASE;
962          break;
963       case 'M':                 /* MD5 */
964          fo->flags |= FO_MD5;
965          break;
966       case 'n':
967          fo->flags |= FO_NOREPLACE;
968          break;
969       case 'p':                 /* use portable data format */
970          fo->flags |= FO_PORTABLE;
971          break;
972       case 'R':                 /* Resource forks and Finder Info */
973          fo->flags |= FO_HFSPLUS;
974       case 'r':                 /* read fifo */
975          fo->flags |= FO_READFIFO;
976          break;
977       case 'S':
978          switch(*(p + 1)) {
979          case '1':
980             fo->flags |= FO_SHA1;
981             p++;
982             break;
983 #ifdef HAVE_SHA2
984          case '2':
985             fo->flags |= FO_SHA256;
986             p++;
987             break;
988          case '3':
989             fo->flags |= FO_SHA512;
990             p++;
991             break;
992 #endif
993          default:
994             /*
995              * If 2 or 3 is seen here, SHA2 is not configured, so
996              *  eat the option, and drop back to SHA-1.
997              */
998             if (p[1] == '2' || p[1] == '3') {
999                p++;
1000             }
1001             fo->flags |= FO_SHA1;
1002             break;
1003          }
1004          break;
1005       case 's':
1006          fo->flags |= FO_SPARSE;
1007          break;
1008       case 'm':
1009          fo->flags |= FO_MTIMEONLY;
1010          break;
1011       case 'k':
1012          fo->flags |= FO_KEEPATIME;
1013          break;
1014       case 'A':
1015          fo->flags |= FO_ACL;
1016          break;
1017       case 'V':                  /* verify options */
1018          /* Copy Verify Options */
1019          for (j=0; *p && *p != ':'; p++) {
1020             fo->VerifyOpts[j] = *p;
1021             if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1022                j++;
1023             }
1024          }
1025          fo->VerifyOpts[j] = 0;
1026          break;
1027       case 'P':                  /* strip path */
1028          /* Get integer */
1029          p++;                    /* skip P */
1030          for (j=0; *p && *p != ':'; p++) {
1031             strip[j] = *p;
1032             if (j < (int)sizeof(strip) - 1) {
1033                j++;
1034             }
1035          }
1036          strip[j] = 0;
1037          fo->strip_path = atoi(strip);
1038          fo->flags |= FO_STRIPPATH;
1039          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1040          break;
1041       case 'w':
1042          fo->flags |= FO_IF_NEWER;
1043          break;
1044       case 'W':
1045          fo->flags |= FO_ENHANCEDWILD;
1046          break;
1047       case 'Z':                 /* gzip compression */
1048          fo->flags |= FO_GZIP;
1049          fo->GZIP_level = *++p - '0';
1050          break;
1051       case 'K':
1052          fo->flags |= FO_NOATIME;
1053          break;
1054       case 'c':
1055          fo->flags |= FO_CHKCHANGES;
1056          break;
1057       default:
1058          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1059          break;
1060       }
1061    }
1062 }
1063
1064
1065 /*
1066  * Director is passing his Fileset
1067  */
1068 static int fileset_cmd(JCR *jcr)
1069 {
1070    BSOCK *dir = jcr->dir_bsock;
1071
1072 #if defined(WIN32_VSS)
1073    int vss = 0;
1074
1075    sscanf(dir->msg, "fileset vss=%d", &vss);
1076    enable_vss = vss;
1077 #endif
1078
1079    if (!init_fileset(jcr)) {
1080       return 0;
1081    }
1082    while (bnet_recv(dir) >= 0) {
1083       strip_trailing_junk(dir->msg);
1084       Dmsg1(500, "Fileset: %s\n", dir->msg);
1085       add_fileset(jcr, dir->msg);
1086    }
1087    if (!term_fileset(jcr)) {
1088       return 0;
1089    }
1090    return bnet_fsend(dir, OKinc);
1091 }
1092
1093 static void free_bootstrap(JCR *jcr)
1094 {
1095    if (jcr->RestoreBootstrap) {
1096       unlink(jcr->RestoreBootstrap);
1097       free_pool_memory(jcr->RestoreBootstrap);
1098       jcr->RestoreBootstrap = NULL;
1099    }
1100 }
1101
1102
1103 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1104 static uint32_t bsr_uniq = 0;
1105
1106 /* 
1107  * The Director sends us the bootstrap file, which
1108  *   we will in turn pass to the SD.
1109  */
1110 static int bootstrap_cmd(JCR *jcr)
1111 {
1112    BSOCK *dir = jcr->dir_bsock;
1113    POOLMEM *fname = get_pool_memory(PM_FNAME);
1114    FILE *bs;
1115
1116    free_bootstrap(jcr);
1117    P(bsr_mutex);
1118    bsr_uniq++;
1119    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1120       jcr->Job, bsr_uniq);
1121    V(bsr_mutex);
1122    Dmsg1(400, "bootstrap=%s\n", fname);
1123    jcr->RestoreBootstrap = fname;
1124    bs = fopen(fname, "a+b");           /* create file */
1125    if (!bs) {
1126       berrno be;
1127       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1128          jcr->RestoreBootstrap, be.bstrerror());
1129       /*
1130        * Suck up what he is sending to us so that he will then
1131        *   read our error message.
1132        */
1133       while (bnet_recv(dir) >= 0)
1134         {  }
1135       free_bootstrap(jcr);
1136       set_jcr_job_status(jcr, JS_ErrorTerminated);
1137       return 0;
1138    }
1139
1140    while (bnet_recv(dir) >= 0) {
1141        Dmsg1(200, "filed<dird: bootstrap file %s\n", dir->msg);
1142        fputs(dir->msg, bs);
1143    }
1144    fclose(bs);
1145    /*
1146     * Note, do not free the bootstrap yet -- it needs to be 
1147     *  sent to the SD 
1148     */
1149    return bnet_fsend(dir, OKbootstrap);
1150 }
1151
1152
1153 /*
1154  * Get backup level from Director
1155  *
1156  */
1157 static int level_cmd(JCR *jcr)
1158 {
1159    BSOCK *dir = jcr->dir_bsock;
1160    POOLMEM *level, *buf = NULL;
1161    int mtime_only;
1162
1163    level = get_memory(dir->msglen+1);
1164    Dmsg1(110, "level_cmd: %s", dir->msg);
1165    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1166       goto bail_out;
1167    }
1168    /* Base backup requested? */
1169    if (strcmp(level, "base") == 0) {
1170       jcr->JobLevel = L_BASE;
1171    /* Full backup requested? */
1172    } else if (strcmp(level, "full") == 0) {
1173       jcr->JobLevel = L_FULL;
1174    } else if (strcmp(level, "differential") == 0) {
1175       jcr->JobLevel = L_DIFFERENTIAL;
1176       free_memory(level);
1177       return 1;
1178    } else if (strcmp(level, "incremental") == 0) {
1179       jcr->JobLevel = L_INCREMENTAL;
1180       free_memory(level);
1181       return 1;   
1182    /*
1183     * We get his UTC since time, then sync the clocks and correct it
1184     *   to agree with our clock.
1185     */
1186    } else if (strcmp(level, "since_utime") == 0) {
1187       buf = get_memory(dir->msglen+1);
1188       utime_t since_time, adj;
1189       btime_t his_time, bt_start, rt=0, bt_adj=0;
1190       if (jcr->JobLevel == L_NONE) {
1191          jcr->JobLevel = L_SINCE;     /* if no other job level set, do it now */
1192       }
1193       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1194                  buf, &mtime_only) != 2) {
1195          goto bail_out;
1196       }
1197       since_time = str_to_uint64(buf);  /* this is the since time */
1198       Dmsg1(100, "since_time=%d\n", (int)since_time);
1199       char ed1[50], ed2[50];
1200       /*
1201        * Sync clocks by polling him for the time. We take
1202        *   10 samples of his time throwing out the first two.
1203        */
1204       for (int i=0; i<10; i++) {
1205          bt_start = get_current_btime();
1206          bnet_sig(dir, BNET_BTIME);   /* poll for time */
1207          if (bnet_recv(dir) <= 0) {   /* get response */
1208             goto bail_out;
1209          }
1210          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1211             goto bail_out;
1212          }
1213          if (i < 2) {                 /* toss first two results */
1214             continue;
1215          }
1216          his_time = str_to_uint64(buf);
1217          rt = get_current_btime() - bt_start; /* compute round trip time */
1218          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1219                edit_uint64(bt_start, ed2));
1220          bt_adj +=  bt_start - his_time - rt/2;
1221          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1222       }
1223
1224       bt_adj = bt_adj / 8;            /* compute average time */
1225       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1226       adj = btime_to_utime(bt_adj);
1227       since_time += adj;              /* adjust for clock difference */
1228       /* Don't notify if time within 3 seconds */
1229       if (adj > 3 || adj < -3) {
1230          int type;
1231          if (adj > 600 || adj < -600) {
1232             type = M_WARNING;
1233          } else {
1234             type = M_INFO;
1235          }
1236          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %d seconds, FD automatically compensating.\n"), adj);
1237       }
1238       bnet_sig(dir, BNET_EOD);
1239
1240       Dmsg2(100, "adj = %d since_time=%d\n", (int)adj, (int)since_time);
1241       jcr->incremental = 1;           /* set incremental or decremental backup */
1242       jcr->mtime = (time_t)since_time; /* set since time */
1243    } else {
1244       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1245       free_memory(level);
1246       return 0;
1247    }
1248    free_memory(level);
1249    if (buf) {
1250       free_memory(buf);
1251    }
1252    return bnet_fsend(dir, OKlevel);
1253
1254 bail_out:
1255    pm_strcpy(jcr->errmsg, dir->msg);
1256    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1257    free_memory(level);
1258    if (buf) {
1259       free_memory(buf);
1260    }
1261    return 0;
1262 }
1263
1264 /*
1265  * Get session parameters from Director -- this is for a Restore command
1266  */
1267 static int session_cmd(JCR *jcr)
1268 {
1269    BSOCK *dir = jcr->dir_bsock;
1270
1271    Dmsg1(100, "SessionCmd: %s", dir->msg);
1272    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1273               &jcr->VolSessionId, &jcr->VolSessionTime,
1274               &jcr->StartFile, &jcr->EndFile,
1275               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1276       pm_strcpy(jcr->errmsg, dir->msg);
1277       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1278       return 0;
1279    }
1280
1281    return bnet_fsend(dir, OKsession);
1282 }
1283
1284 /*
1285  * Get address of storage daemon from Director
1286  *
1287  */
1288 static int storage_cmd(JCR *jcr)
1289 {
1290    int stored_port;                /* storage daemon port */
1291    int enable_ssl;                 /* enable ssl to sd */
1292    BSOCK *dir = jcr->dir_bsock;
1293    BSOCK *sd;                         /* storage daemon bsock */
1294
1295    Dmsg1(100, "StorageCmd: %s", dir->msg);
1296    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, &enable_ssl) != 3) {
1297       pm_strcpy(jcr->errmsg, dir->msg);
1298       Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1299       return 0;
1300    }
1301    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, enable_ssl);
1302    /* Open command communications with Storage daemon */
1303    /* Try to connect for 1 hour at 10 second intervals */
1304    sd = bnet_connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1305                       _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1);
1306    if (sd == NULL) {
1307       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1308           jcr->stored_addr, stored_port);
1309       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1310           jcr->stored_addr, stored_port);
1311       return 0;
1312    }
1313    Dmsg0(110, "Connection OK to SD.\n");
1314
1315    jcr->store_bsock = sd;
1316
1317    sd->fsend("Hello Start Job %s\n", jcr->Job);
1318    if (!authenticate_storagedaemon(jcr)) {
1319       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1320       return 0;
1321    }
1322    Dmsg0(110, "Authenticated with SD.\n");
1323
1324    /* Send OK to Director */
1325    return dir->fsend(OKstore);
1326 }
1327
1328
1329 /*
1330  * Do a backup.
1331  */
1332 static int backup_cmd(JCR *jcr)
1333 {
1334    BSOCK *dir = jcr->dir_bsock;
1335    BSOCK *sd = jcr->store_bsock;
1336    int ok = 0;
1337    int SDJobStatus;
1338    char ed1[50], ed2[50];
1339    bool bDoVSS = false;
1340
1341 #if defined(WIN32_VSS)
1342    // capture state here, if client is backed up by multiple directors
1343    // and one enables vss and the other does not then enable_vss can change
1344    // between here and where its evaluated after the job completes.
1345    bDoVSS = g_pVSSClient && enable_vss;
1346    if (bDoVSS) {
1347       /* Run only one at a time */
1348       P(vss_mutex);
1349    }
1350 #endif
1351
1352    set_jcr_job_status(jcr, JS_Blocked);
1353    jcr->JobType = JT_BACKUP;
1354    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1355
1356    if (sd == NULL) {
1357       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1358       goto cleanup;
1359    }
1360
1361    bnet_fsend(dir, OKbackup);
1362    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1363
1364    /*
1365     * Send Append Open Session to Storage daemon
1366     */
1367    bnet_fsend(sd, append_open);
1368    Dmsg1(110, ">stored: %s", sd->msg);
1369    /*
1370     * Expect to receive back the Ticket number
1371     */
1372    if (bget_msg(sd) >= 0) {
1373       Dmsg1(110, "<stored: %s", sd->msg);
1374       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1375          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1376          goto cleanup;
1377       }
1378       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1379    } else {
1380       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1381       goto cleanup;
1382    }
1383
1384    /*
1385     * Send Append data command to Storage daemon
1386     */
1387    bnet_fsend(sd, append_data, jcr->Ticket);
1388    Dmsg1(110, ">stored: %s", sd->msg);
1389
1390    /*
1391     * Expect to get OK data
1392     */
1393    Dmsg1(110, "<stored: %s", sd->msg);
1394    if (!response(jcr, sd, OK_data, "Append Data")) {
1395       goto cleanup;
1396    }
1397    
1398    generate_daemon_event(jcr, "JobStart");
1399
1400 #if defined(WIN32_VSS)
1401    /* START VSS ON WIN 32 */
1402    if (bDoVSS) {      
1403       if (g_pVSSClient->InitializeForBackup()) {   
1404         /* tell vss which drives to snapshot */   
1405         char szWinDriveLetters[27];   
1406         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1407             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1408             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1409                Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed.\n"));
1410                jcr->Errors++;
1411             } else {
1412                /* tell user if snapshot creation of a specific drive failed */
1413                int i;
1414                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1415                   if (islower(szWinDriveLetters[i])) {
1416                      Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed. VSS support is disabled on this drive.\n"), szWinDriveLetters[i]);
1417                      jcr->Errors++;
1418                   }
1419                }
1420                /* inform user about writer states */
1421                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++)                
1422                   if (g_pVSSClient->GetWriterState(i) < 1) {
1423                      Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1424                      jcr->Errors++;
1425                   }                            
1426             }
1427         } else {
1428             Jmsg(jcr, M_INFO, 0, _("No drive letters found for generating VSS snapshots.\n"));
1429         }
1430       } else {
1431          berrno be;
1432          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
1433       } 
1434    }
1435 #endif
1436
1437    /*
1438     * Send Files to Storage daemon
1439     */
1440    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1441    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1442       set_jcr_job_status(jcr, JS_ErrorTerminated);
1443       bnet_suppress_error_messages(sd, 1);
1444       bget_msg(sd);                   /* Read final response from append_data */
1445       Dmsg0(110, "Error in blast_data.\n");
1446    } else {
1447       set_jcr_job_status(jcr, JS_Terminated);
1448
1449       if (jcr->JobStatus != JS_Terminated) {
1450          bnet_suppress_error_messages(sd, 1);
1451          goto cleanup;                /* bail out now */
1452       }
1453       /*
1454        * Expect to get response to append_data from Storage daemon
1455        */
1456       if (!response(jcr, sd, OK_append, "Append Data")) {
1457          set_jcr_job_status(jcr, JS_ErrorTerminated);
1458          goto cleanup;
1459       }
1460
1461       /*
1462        * Send Append End Data to Storage daemon
1463        */
1464       bnet_fsend(sd, append_end, jcr->Ticket);
1465       /* Get end OK */
1466       if (!response(jcr, sd, OK_end, "Append End")) {
1467          set_jcr_job_status(jcr, JS_ErrorTerminated);
1468          goto cleanup;
1469       }
1470
1471       /*
1472        * Send Append Close to Storage daemon
1473        */
1474       bnet_fsend(sd, append_close, jcr->Ticket);
1475       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1476          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1477             ok = 1;
1478             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1479          }
1480       }
1481       if (!ok) {
1482          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1483          goto cleanup;
1484       }
1485       if (SDJobStatus != JS_Terminated) {
1486          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1487             SDJobStatus);
1488       }
1489    }
1490
1491 cleanup:
1492 #if defined(WIN32_VSS)
1493    /* STOP VSS ON WIN 32 */
1494    /* tell vss to close the backup session */
1495    if (bDoVSS) {
1496       if (g_pVSSClient->CloseBackup()) {             
1497          /* inform user about writer states */
1498          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1499             int msg_type = M_INFO;
1500             if (g_pVSSClient->GetWriterState(i) < 1) {
1501                msg_type = M_WARNING;
1502                jcr->Errors++;
1503             }
1504             Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1505          }
1506       }
1507       V(vss_mutex);
1508    }
1509 #endif
1510
1511    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1512       edit_uint64(jcr->ReadBytes, ed1),
1513       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, (int)bDoVSS, 
1514       jcr->pki_encrypt);
1515    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1516    
1517    return 0;                          /* return and stop command loop */
1518 }
1519
1520 /*
1521  * Do a Verify for Director
1522  *
1523  */
1524 static int verify_cmd(JCR *jcr)
1525 {
1526    BSOCK *dir = jcr->dir_bsock;
1527    BSOCK *sd  = jcr->store_bsock;
1528    char level[100], ed1[50], ed2[50];
1529
1530    jcr->JobType = JT_VERIFY;
1531    if (sscanf(dir->msg, verifycmd, level) != 1) {
1532       bnet_fsend(dir, _("2994 Bad verify command: %s\n"), dir->msg);
1533       return 0;
1534    }
1535
1536    if (strcasecmp(level, "init") == 0) {
1537       jcr->JobLevel = L_VERIFY_INIT;
1538    } else if (strcasecmp(level, "catalog") == 0){
1539       jcr->JobLevel = L_VERIFY_CATALOG;
1540    } else if (strcasecmp(level, "volume") == 0){
1541       jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
1542    } else if (strcasecmp(level, "data") == 0){
1543       jcr->JobLevel = L_VERIFY_DATA;
1544    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1545       jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
1546    } else {
1547       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1548       return 0;
1549    }
1550
1551    bnet_fsend(dir, OKverify);
1552
1553    generate_daemon_event(jcr, "JobStart");
1554
1555    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1556
1557    switch (jcr->JobLevel) {
1558    case L_VERIFY_INIT:
1559    case L_VERIFY_CATALOG:
1560       do_verify(jcr);
1561       break;
1562    case L_VERIFY_VOLUME_TO_CATALOG:
1563       if (!open_sd_read_session(jcr)) {
1564          return 0;
1565       }
1566       start_dir_heartbeat(jcr);
1567       do_verify_volume(jcr);
1568       stop_dir_heartbeat(jcr);
1569       /*
1570        * Send Close session command to Storage daemon
1571        */
1572       bnet_fsend(sd, read_close, jcr->Ticket);
1573       Dmsg1(130, "bfiled>stored: %s", sd->msg);
1574
1575       /* ****FIXME**** check response */
1576       bget_msg(sd);                      /* get OK */
1577
1578       /* Inform Storage daemon that we are done */
1579       bnet_sig(sd, BNET_TERMINATE);
1580
1581       break;
1582    case L_VERIFY_DISK_TO_CATALOG:
1583       do_verify(jcr);
1584       break;
1585    default:
1586       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1587       return 0;
1588    }
1589
1590    bnet_sig(dir, BNET_EOD);
1591
1592    /* Send termination status back to Dir */
1593    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1594       edit_uint64(jcr->ReadBytes, ed1),
1595       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1596       jcr->pki_encrypt);
1597    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1598
1599    /* Inform Director that we are done */
1600    bnet_sig(dir, BNET_TERMINATE);
1601    return 0;                          /* return and terminate command loop */
1602 }
1603
1604 /*
1605  * Do a Restore for Director
1606  *
1607  */
1608 static int restore_cmd(JCR *jcr)
1609 {
1610    BSOCK *dir = jcr->dir_bsock;
1611    BSOCK *sd = jcr->store_bsock;
1612    POOLMEM *args;
1613    bool use_regexwhere=false;
1614    int prefix_links;
1615    char replace;
1616    char ed1[50], ed2[50];
1617
1618    /*
1619     * Scan WHERE (base directory for restore) from command
1620     */
1621    Dmsg0(150, "restore command\n");
1622    /* Pickup where string */
1623    args = get_memory(dir->msglen+1);
1624    *args = 0;
1625
1626    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
1627       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
1628          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
1629             pm_strcpy(jcr->errmsg, dir->msg);
1630             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
1631             return 0;
1632          }
1633          *args = 0;
1634       }
1635       use_regexwhere = true;
1636    }
1637    /* Turn / into nothing */
1638    if (IsPathSeparator(args[0]) && args[1] == '\0') {
1639       args[0] = '\0';
1640    }
1641
1642    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
1643    unbash_spaces(args);
1644
1645    if (use_regexwhere) {
1646       jcr->where_bregexp = get_bregexps(args);
1647       if (!jcr->where_bregexp) {
1648          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
1649          free_pool_memory(args);
1650          return 0;
1651       }
1652    } else {
1653       jcr->where = bstrdup(args);
1654    }
1655
1656    free_pool_memory(args);
1657    jcr->replace = replace;
1658    jcr->prefix_links = prefix_links;
1659
1660    bnet_fsend(dir, OKrestore);
1661    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1662
1663    jcr->JobType = JT_RESTORE;
1664
1665    set_jcr_job_status(jcr, JS_Blocked);
1666
1667    if (!open_sd_read_session(jcr)) {
1668       set_jcr_job_status(jcr, JS_ErrorTerminated);
1669       goto bail_out;
1670    }
1671
1672    set_jcr_job_status(jcr, JS_Running);
1673
1674    /*
1675     * Do restore of files and data
1676     */
1677    start_dir_heartbeat(jcr);
1678    generate_daemon_event(jcr, "JobStart");
1679    do_restore(jcr);
1680    stop_dir_heartbeat(jcr);
1681
1682    set_jcr_job_status(jcr, JS_Terminated);
1683    if (jcr->JobStatus != JS_Terminated) {
1684       bnet_suppress_error_messages(sd, 1);
1685    }
1686
1687    /*
1688     * Send Close session command to Storage daemon
1689     */
1690    bnet_fsend(sd, read_close, jcr->Ticket);
1691    Dmsg1(130, "bfiled>stored: %s", sd->msg);
1692
1693    bget_msg(sd);                      /* get OK */
1694
1695    /* Inform Storage daemon that we are done */
1696    bnet_sig(sd, BNET_TERMINATE);
1697
1698 bail_out:
1699
1700    if (jcr->Errors) {
1701       set_jcr_job_status(jcr, JS_ErrorTerminated);
1702    }
1703    /* Send termination status back to Dir */
1704    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1705       edit_uint64(jcr->ReadBytes, ed1),
1706       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1707       jcr->pki_encrypt);
1708    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1709
1710    /* Inform Director that we are done */
1711    bnet_sig(dir, BNET_TERMINATE);
1712
1713    Dmsg0(130, "Done in job.c\n");
1714    return 0;                          /* return and terminate command loop */
1715 }
1716
1717 static int open_sd_read_session(JCR *jcr)
1718 {
1719    BSOCK *sd = jcr->store_bsock;
1720
1721    if (!sd) {
1722       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
1723       return 0;
1724    }
1725    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
1726       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
1727    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
1728    /*
1729     * Open Read Session with Storage daemon
1730     */
1731    bnet_fsend(sd, read_open, "DummyVolume",
1732       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
1733       jcr->StartBlock, jcr->EndBlock);
1734    Dmsg1(110, ">stored: %s", sd->msg);
1735
1736    /*
1737     * Get ticket number
1738     */
1739    if (bget_msg(sd) >= 0) {
1740       Dmsg1(110, "bfiled<stored: %s", sd->msg);
1741       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1742          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
1743          return 0;
1744       }
1745       Dmsg1(110, "bfiled: got Ticket=%d\n", jcr->Ticket);
1746    } else {
1747       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
1748       return 0;
1749    }
1750
1751    if (!send_bootstrap_file(jcr)) {
1752       return 0;
1753    }
1754
1755    /*
1756     * Start read of data with Storage daemon
1757     */
1758    bnet_fsend(sd, read_data, jcr->Ticket);
1759    Dmsg1(110, ">stored: %s", sd->msg);
1760
1761    /*
1762     * Get OK data
1763     */
1764    if (!response(jcr, sd, OK_data, "Read Data")) {
1765       return 0;
1766    }
1767    return 1;
1768 }
1769
1770 /*
1771  * Destroy the Job Control Record and associated
1772  * resources (sockets).
1773  */
1774 static void filed_free_jcr(JCR *jcr)
1775 {
1776    if (jcr->store_bsock) {
1777       bnet_close(jcr->store_bsock);
1778    }
1779    free_bootstrap(jcr);
1780    if (jcr->last_fname) {
1781       free_pool_memory(jcr->last_fname);
1782    }
1783    free_runscripts(jcr->RunScripts);
1784    delete jcr->RunScripts;
1785
1786    return;
1787 }
1788
1789 /*
1790  * Get response from Storage daemon to a command we
1791  * sent. Check that the response is OK.
1792  *
1793  *  Returns: 0 on failure
1794  *           1 on success
1795  */
1796 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
1797 {
1798    if (sd->errors) {
1799       return 0;
1800    }
1801    if (bget_msg(sd) > 0) {
1802       Dmsg0(110, sd->msg);
1803       if (strcmp(sd->msg, resp) == 0) {
1804          return 1;
1805       }
1806    }
1807    if (job_canceled(jcr)) {
1808       return 0;                       /* if canceled avoid useless error messages */
1809    }
1810    if (is_bnet_error(sd)) {
1811       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
1812          cmd, bnet_strerror(sd));
1813    } else {
1814       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
1815          cmd, resp, sd->msg);
1816    }
1817    return 0;
1818 }
1819
1820 static int send_bootstrap_file(JCR *jcr)
1821 {
1822    FILE *bs;
1823    char buf[2000];
1824    BSOCK *sd = jcr->store_bsock;
1825    const char *bootstrap = "bootstrap\n";
1826    int stat = 0;
1827
1828    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
1829    if (!jcr->RestoreBootstrap) {
1830       return 1;
1831    }
1832    bs = fopen(jcr->RestoreBootstrap, "rb");
1833    if (!bs) {
1834       berrno be;
1835       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
1836          jcr->RestoreBootstrap, be.bstrerror());
1837       set_jcr_job_status(jcr, JS_ErrorTerminated);
1838       goto bail_out;
1839    }
1840    sd->msglen = pm_strcpy(sd->msg, bootstrap);
1841    bnet_send(sd);
1842    while (fgets(buf, sizeof(buf), bs)) {
1843       sd->msglen = Mmsg(sd->msg, "%s", buf);
1844       bnet_send(sd);
1845    }
1846    bnet_sig(sd, BNET_EOD);
1847    fclose(bs);
1848    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
1849       set_jcr_job_status(jcr, JS_ErrorTerminated);
1850       goto bail_out;
1851    }
1852    stat = 1;
1853
1854 bail_out:
1855    free_bootstrap(jcr);
1856    return stat;
1857 }