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