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