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