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