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