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