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