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