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