]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
kes Add dynamic dll entry point for SHGetFolderPath to Win32 code.
[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       Dmsg0(100, "State=error return\n");
680       return;
681    }
682
683    /*
684     * The switch tests the code for validity.
685     * The subcode is always good if it is a space, otherwise we must confirm.
686     * We set state to state_error first assuming the subcode is invalid,
687     * requiring state to be set in cases below that handle subcodes.
688     */
689    if (subcode != ' ') {
690       state = state_error;
691       Dmsg0(100, "Set state=error\n"); 
692    }
693    switch (code) {
694    case 'I':
695       /* New include */
696       fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
697       memset(fileset->incexe, 0, sizeof(findINCEXE));
698       fileset->incexe->opts_list.init(1, true);
699       fileset->incexe->name_list.init(1, true);
700       fileset->include_list.append(fileset->incexe);
701       break;
702    case 'E':
703       /* New exclude */
704       fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
705       memset(fileset->incexe, 0, sizeof(findINCEXE));
706       fileset->incexe->opts_list.init(1, true);
707       fileset->incexe->name_list.init(1, true);
708       fileset->exclude_list.append(fileset->incexe);
709       break;
710    case 'N':
711       state = state_none;
712       break;
713    case 'F':
714       /* File item to either include/include list */
715       state = state_include;
716       add_file_to_fileset(jcr, item, fileset);
717       break;
718    case 'R':
719       current_opts = start_options(ff);
720       regex_t *preg;
721       int rc;
722       char prbuf[500];
723       preg = (regex_t *)malloc(sizeof(regex_t));
724       if (current_opts->flags & FO_IGNORECASE) {
725          rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
726       } else {
727          rc = regcomp(preg, item, REG_EXTENDED);
728       }
729       if (rc != 0) {
730          regerror(rc, preg, prbuf, sizeof(prbuf));
731          regfree(preg);
732          free(preg);
733          Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
734          state = state_error;
735          break;
736       }
737       state = state_options;
738       if (subcode == ' ') {
739          current_opts->regex.append(preg);
740       } else if (subcode == 'D') {
741          current_opts->regexdir.append(preg);
742       } else if (subcode == 'F') {
743          current_opts->regexfile.append(preg);
744       } else {
745          state = state_error;
746       }
747       break;
748    case 'B':
749       current_opts = start_options(ff);
750       current_opts->base.append(bstrdup(item));
751       state = state_options;
752       break;
753    case 'X':
754       current_opts = start_options(ff);
755       state = state_options;
756       if (subcode == ' ') {
757          current_opts->fstype.append(bstrdup(item));
758       } else if (subcode == 'D') {
759          current_opts->drivetype.append(bstrdup(item));
760       } else {
761          state = state_error;
762       }
763       break;
764    case 'W':
765       current_opts = start_options(ff);
766       state = state_options;
767       if (subcode == ' ') {
768          current_opts->wild.append(bstrdup(item));
769       } else if (subcode == 'D') {
770          current_opts->wilddir.append(bstrdup(item));
771       } else if (subcode == 'F') {
772          current_opts->wildfile.append(bstrdup(item));
773       } else if (subcode == 'B') {
774          current_opts->wildbase.append(bstrdup(item));
775       } else {
776          state = state_error;
777       }
778       break;
779    case 'O':
780       current_opts = start_options(ff);
781       set_options(current_opts, item);
782       state = state_options;
783       break;
784    case 'D':
785       current_opts = start_options(ff);
786       current_opts->reader = bstrdup(item);
787       state = state_options;
788       break;
789    case 'T':
790       current_opts = start_options(ff);
791       current_opts->writer = bstrdup(item);
792       state = state_options;
793       break;
794    default:
795       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
796       state = state_error;
797       break;
798    }
799    ff->fileset->state = state;
800 }
801
802 static bool term_fileset(JCR *jcr)
803 {
804    FF_PKT *ff = jcr->ff;
805
806 #ifdef xxx
807    findFILESET *fileset = ff->fileset;
808    int i, j, k;
809
810    for (i=0; i<fileset->include_list.size(); i++) {
811       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
812       Dmsg0(400, "I\n");
813       for (j=0; j<incexe->opts_list.size(); j++) {
814          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
815          for (k=0; k<fo->regex.size(); k++) {
816             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
817          }
818          for (k=0; k<fo->regexdir.size(); k++) {
819             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
820          }
821          for (k=0; k<fo->regexfile.size(); k++) {
822             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
823          }
824          for (k=0; k<fo->wild.size(); k++) {
825             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
826          }
827          for (k=0; k<fo->wilddir.size(); k++) {
828             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
829          }
830          for (k=0; k<fo->wildfile.size(); k++) {
831             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
832          }
833          for (k=0; k<fo->wildbase.size(); k++) {
834             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
835          }
836          for (k=0; k<fo->base.size(); k++) {
837             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
838          }
839          for (k=0; k<fo->fstype.size(); k++) {
840             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
841          }
842          for (k=0; k<fo->drivetype.size(); k++) {
843             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
844          }
845          if (fo->reader) {
846             Dmsg1(400, "D %s\n", fo->reader);
847          }
848          if (fo->writer) {
849             Dmsg1(400, "T %s\n", fo->writer);
850          }
851       }
852       for (j=0; j<incexe->name_list.size(); j++) {
853          Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
854       }
855    }
856    for (i=0; i<fileset->exclude_list.size(); i++) {
857       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
858       Dmsg0(400, "E\n");
859       for (j=0; j<incexe->opts_list.size(); j++) {
860          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
861          for (k=0; k<fo->regex.size(); k++) {
862             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
863          }
864          for (k=0; k<fo->regexdir.size(); k++) {
865             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
866          }
867          for (k=0; k<fo->regexfile.size(); k++) {
868             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
869          }
870          for (k=0; k<fo->wild.size(); k++) {
871             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
872          }
873          for (k=0; k<fo->wilddir.size(); k++) {
874             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
875          }
876          for (k=0; k<fo->wildfile.size(); k++) {
877             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
878          }
879          for (k=0; k<fo->wildbase.size(); k++) {
880             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
881          }
882          for (k=0; k<fo->base.size(); k++) {
883             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
884          }
885          for (k=0; k<fo->fstype.size(); k++) {
886             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
887          }
888          for (k=0; k<fo->drivetype.size(); k++) {
889             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
890          }
891       }
892       for (j=0; j<incexe->name_list.size(); j++) {
893          Dmsg1(400, "F %s\n", (char *)incexe->name_list.get(j));
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       /* run shortly after end of data transmission */ 
1391       run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
1392       jcr->runscript_after=1;
1393
1394    } else {
1395       set_jcr_job_status(jcr, JS_Terminated);
1396
1397       /* run shortly after end of data transmission */   
1398       run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
1399       jcr->runscript_after=1;
1400
1401       if (jcr->JobStatus != JS_Terminated) {
1402          bnet_suppress_error_messages(sd, 1);
1403          goto cleanup;                /* bail out now */
1404       }
1405       /*
1406        * Expect to get response to append_data from Storage daemon
1407        */
1408       if (!response(jcr, sd, OK_append, "Append Data")) {
1409          set_jcr_job_status(jcr, JS_ErrorTerminated);
1410          goto cleanup;
1411       }
1412
1413       /*
1414        * Send Append End Data to Storage daemon
1415        */
1416       bnet_fsend(sd, append_end, jcr->Ticket);
1417       /* Get end OK */
1418       if (!response(jcr, sd, OK_end, "Append End")) {
1419          set_jcr_job_status(jcr, JS_ErrorTerminated);
1420          goto cleanup;
1421       }
1422
1423       /*
1424        * Send Append Close to Storage daemon
1425        */
1426       bnet_fsend(sd, append_close, jcr->Ticket);
1427       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1428          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1429             ok = 1;
1430             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1431          }
1432       }
1433       if (!ok) {
1434          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1435          goto cleanup;
1436       }
1437       if (SDJobStatus != JS_Terminated) {
1438          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1439             SDJobStatus);
1440       }
1441    }
1442
1443 cleanup:
1444 #if defined(WIN32_VSS)
1445    /* STOP VSS ON WIN 32 */
1446    /* tell vss to close the backup session */
1447    if (bDoVSS) {
1448       if (g_pVSSClient->CloseBackup()) {             
1449          /* inform user about writer states */
1450          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1451             int msg_type = M_INFO;
1452             if (g_pVSSClient->GetWriterState(i) < 1) {
1453                msg_type = M_WARNING;
1454                jcr->Errors++;
1455             }
1456             Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1457          }
1458       }
1459       V(vss_mutex);
1460    }
1461 #endif
1462
1463    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1464       edit_uint64(jcr->ReadBytes, ed1),
1465       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, (int)bDoVSS, 
1466       jcr->pki_encrypt);
1467    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1468    
1469    return 0;                          /* return and stop command loop */
1470 }
1471
1472 /*
1473  * Do a Verify for Director
1474  *
1475  */
1476 static int verify_cmd(JCR *jcr)
1477 {
1478    BSOCK *dir = jcr->dir_bsock;
1479    BSOCK *sd  = jcr->store_bsock;
1480    char level[100], ed1[50], ed2[50];
1481
1482    jcr->JobType = JT_VERIFY;
1483    if (sscanf(dir->msg, verifycmd, level) != 1) {
1484       bnet_fsend(dir, _("2994 Bad verify command: %s\n"), dir->msg);
1485       return 0;
1486    }
1487
1488    if (strcasecmp(level, "init") == 0) {
1489       jcr->JobLevel = L_VERIFY_INIT;
1490    } else if (strcasecmp(level, "catalog") == 0){
1491       jcr->JobLevel = L_VERIFY_CATALOG;
1492    } else if (strcasecmp(level, "volume") == 0){
1493       jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
1494    } else if (strcasecmp(level, "data") == 0){
1495       jcr->JobLevel = L_VERIFY_DATA;
1496    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1497       jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
1498    } else {
1499       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1500       return 0;
1501    }
1502
1503    bnet_fsend(dir, OKverify);
1504
1505    generate_daemon_event(jcr, "JobStart");
1506
1507    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1508
1509    switch (jcr->JobLevel) {
1510    case L_VERIFY_INIT:
1511    case L_VERIFY_CATALOG:
1512       do_verify(jcr);
1513       break;
1514    case L_VERIFY_VOLUME_TO_CATALOG:
1515       if (!open_sd_read_session(jcr)) {
1516          return 0;
1517       }
1518       start_dir_heartbeat(jcr);
1519       do_verify_volume(jcr);
1520       stop_dir_heartbeat(jcr);
1521       /*
1522        * Send Close session command to Storage daemon
1523        */
1524       bnet_fsend(sd, read_close, jcr->Ticket);
1525       Dmsg1(130, "bfiled>stored: %s", sd->msg);
1526
1527       /* ****FIXME**** check response */
1528       bget_msg(sd);                      /* get OK */
1529
1530       /* Inform Storage daemon that we are done */
1531       bnet_sig(sd, BNET_TERMINATE);
1532
1533       break;
1534    case L_VERIFY_DISK_TO_CATALOG:
1535       do_verify(jcr);
1536       break;
1537    default:
1538       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1539       return 0;
1540    }
1541
1542    bnet_sig(dir, BNET_EOD);
1543
1544    /* Send termination status back to Dir */
1545    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1546       edit_uint64(jcr->ReadBytes, ed1),
1547       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1548       jcr->pki_encrypt);
1549    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1550
1551    /* Inform Director that we are done */
1552    bnet_sig(dir, BNET_TERMINATE);
1553    return 0;                          /* return and terminate command loop */
1554 }
1555
1556 /*
1557  * Do a Restore for Director
1558  *
1559  */
1560 static int restore_cmd(JCR *jcr)
1561 {
1562    BSOCK *dir = jcr->dir_bsock;
1563    BSOCK *sd = jcr->store_bsock;
1564    POOLMEM *where;
1565    int prefix_links;
1566    char replace;
1567    char ed1[50], ed2[50];
1568
1569    /*
1570     * Scan WHERE (base directory for restore) from command
1571     */
1572    Dmsg0(150, "restore command\n");
1573    /* Pickup where string */
1574    where = get_memory(dir->msglen+1);
1575    *where = 0;
1576
1577    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) {
1578       if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
1579          pm_strcpy(jcr->errmsg, dir->msg);
1580          Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
1581          return 0;
1582       }
1583       *where = 0;
1584    }
1585    /* Turn / into nothing */
1586    if (IsPathSeparator(where[0]) && where[1] == '\0') {
1587       where[0] = '\0';
1588    }
1589
1590    Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
1591    unbash_spaces(where);
1592    jcr->where = bstrdup(where);
1593    free_pool_memory(where);
1594    jcr->replace = replace;
1595    jcr->prefix_links = prefix_links;
1596
1597    bnet_fsend(dir, OKrestore);
1598    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1599
1600    jcr->JobType = JT_RESTORE;
1601
1602    set_jcr_job_status(jcr, JS_Blocked);
1603
1604    if (!open_sd_read_session(jcr)) {
1605       set_jcr_job_status(jcr, JS_ErrorTerminated);
1606       goto bail_out;
1607    }
1608
1609    set_jcr_job_status(jcr, JS_Running);
1610
1611    /*
1612     * Do restore of files and data
1613     */
1614    start_dir_heartbeat(jcr);
1615    generate_daemon_event(jcr, "JobStart");
1616    do_restore(jcr);
1617    stop_dir_heartbeat(jcr);
1618
1619    set_jcr_job_status(jcr, JS_Terminated);
1620    if (jcr->JobStatus != JS_Terminated) {
1621       bnet_suppress_error_messages(sd, 1);
1622    }
1623
1624    /*
1625     * Send Close session command to Storage daemon
1626     */
1627    bnet_fsend(sd, read_close, jcr->Ticket);
1628    Dmsg1(130, "bfiled>stored: %s", sd->msg);
1629
1630    bget_msg(sd);                      /* get OK */
1631
1632    /* Inform Storage daemon that we are done */
1633    bnet_sig(sd, BNET_TERMINATE);
1634
1635 bail_out:
1636
1637    if (jcr->Errors) {
1638       set_jcr_job_status(jcr, JS_ErrorTerminated);
1639    }
1640    /* Send termination status back to Dir */
1641    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1642       edit_uint64(jcr->ReadBytes, ed1),
1643       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1644       jcr->pki_encrypt);
1645    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1646
1647    /* Inform Director that we are done */
1648    bnet_sig(dir, BNET_TERMINATE);
1649
1650    Dmsg0(130, "Done in job.c\n");
1651    return 0;                          /* return and terminate command loop */
1652 }
1653
1654 static int open_sd_read_session(JCR *jcr)
1655 {
1656    BSOCK *sd = jcr->store_bsock;
1657
1658    if (!sd) {
1659       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
1660       return 0;
1661    }
1662    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
1663       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
1664    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
1665    /*
1666     * Open Read Session with Storage daemon
1667     */
1668    bnet_fsend(sd, read_open, "DummyVolume",
1669       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
1670       jcr->StartBlock, jcr->EndBlock);
1671    Dmsg1(110, ">stored: %s", sd->msg);
1672
1673    /*
1674     * Get ticket number
1675     */
1676    if (bget_msg(sd) >= 0) {
1677       Dmsg1(110, "bfiled<stored: %s", sd->msg);
1678       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1679          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
1680          return 0;
1681       }
1682       Dmsg1(110, "bfiled: got Ticket=%d\n", jcr->Ticket);
1683    } else {
1684       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
1685       return 0;
1686    }
1687
1688    if (!send_bootstrap_file(jcr)) {
1689       return 0;
1690    }
1691
1692    /*
1693     * Start read of data with Storage daemon
1694     */
1695    bnet_fsend(sd, read_data, jcr->Ticket);
1696    Dmsg1(110, ">stored: %s", sd->msg);
1697
1698    /*
1699     * Get OK data
1700     */
1701    if (!response(jcr, sd, OK_data, "Read Data")) {
1702       return 0;
1703    }
1704    return 1;
1705 }
1706
1707 /*
1708  * Destroy the Job Control Record and associated
1709  * resources (sockets).
1710  */
1711 static void filed_free_jcr(JCR *jcr)
1712 {
1713    if (jcr->store_bsock) {
1714       bnet_close(jcr->store_bsock);
1715    }
1716    free_bootstrap(jcr);
1717    if (jcr->last_fname) {
1718       free_pool_memory(jcr->last_fname);
1719    }
1720    free_runscripts(jcr->RunScripts);
1721    delete jcr->RunScripts;
1722
1723    return;
1724 }
1725
1726 /*
1727  * Get response from Storage daemon to a command we
1728  * sent. Check that the response is OK.
1729  *
1730  *  Returns: 0 on failure
1731  *           1 on success
1732  */
1733 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
1734 {
1735    if (sd->errors) {
1736       return 0;
1737    }
1738    if (bget_msg(sd) > 0) {
1739       Dmsg0(110, sd->msg);
1740       if (strcmp(sd->msg, resp) == 0) {
1741          return 1;
1742       }
1743    }
1744    if (job_canceled(jcr)) {
1745       return 0;                       /* if canceled avoid useless error messages */
1746    }
1747    if (is_bnet_error(sd)) {
1748       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
1749          cmd, bnet_strerror(sd));
1750    } else {
1751       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
1752          cmd, resp, sd->msg);
1753    }
1754    return 0;
1755 }
1756
1757 static int send_bootstrap_file(JCR *jcr)
1758 {
1759    FILE *bs;
1760    char buf[2000];
1761    BSOCK *sd = jcr->store_bsock;
1762    const char *bootstrap = "bootstrap\n";
1763    int stat = 0;
1764
1765    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
1766    if (!jcr->RestoreBootstrap) {
1767       return 1;
1768    }
1769    bs = fopen(jcr->RestoreBootstrap, "rb");
1770    if (!bs) {
1771       berrno be;
1772       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
1773          jcr->RestoreBootstrap, be.strerror());
1774       set_jcr_job_status(jcr, JS_ErrorTerminated);
1775       goto bail_out;
1776    }
1777    sd->msglen = pm_strcpy(sd->msg, bootstrap);
1778    bnet_send(sd);
1779    while (fgets(buf, sizeof(buf), bs)) {
1780       sd->msglen = Mmsg(sd->msg, "%s", buf);
1781       bnet_send(sd);
1782    }
1783    bnet_sig(sd, BNET_EOD);
1784    fclose(bs);
1785    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
1786       set_jcr_job_status(jcr, JS_ErrorTerminated);
1787       goto bail_out;
1788    }
1789    stat = 1;
1790
1791 bail_out:
1792    free_bootstrap(jcr);
1793    return stat;
1794 }