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