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