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