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