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