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