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