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