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