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