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