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