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