]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Create and put data into RestoreObject table
[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       Dmsg0(110, "Error in blast_data.\n");
1643    } else {
1644       set_jcr_job_status(jcr, JS_Terminated);
1645       /* Note, the above set status will not override an error */
1646       if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
1647          bnet_suppress_error_messages(sd, 1);
1648          goto cleanup;                /* bail out now */
1649       }
1650       /**
1651        * Expect to get response to append_data from Storage daemon
1652        */
1653       if (!response(jcr, sd, OK_append, "Append Data")) {
1654          set_jcr_job_status(jcr, JS_ErrorTerminated);
1655          goto cleanup;
1656       }
1657
1658       /**
1659        * Send Append End Data to Storage daemon
1660        */
1661       sd->fsend(append_end, jcr->Ticket);
1662       /* Get end OK */
1663       if (!response(jcr, sd, OK_end, "Append End")) {
1664          set_jcr_job_status(jcr, JS_ErrorTerminated);
1665          goto cleanup;
1666       }
1667
1668       /**
1669        * Send Append Close to Storage daemon
1670        */
1671       sd->fsend(append_close, jcr->Ticket);
1672       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1673          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1674             ok = 1;
1675             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1676          }
1677       }
1678       if (!ok) {
1679          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1680          goto cleanup;
1681       }
1682       if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings)) {
1683          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1684             SDJobStatus);
1685       }
1686    }
1687
1688 cleanup:
1689 #if defined(WIN32_VSS)
1690    /* STOP VSS ON WIN32 */
1691    /* tell vss to close the backup session */
1692    if (jcr->VSS) {
1693       if (g_pVSSClient->CloseBackup()) {             
1694          /* inform user about writer states */
1695          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1696             int msg_type = M_INFO;
1697             if (g_pVSSClient->GetWriterState(i) < 1) {
1698                msg_type = M_WARNING;
1699                jcr->JobErrors++;
1700             }
1701             Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1702          }
1703       }
1704       Win32ConvCleanupCache();
1705       V(vss_mutex);
1706    }
1707 #endif
1708
1709    generate_plugin_event(jcr, bEventEndBackupJob);
1710    return 0;                          /* return and stop command loop */
1711 }
1712
1713 /**
1714  * Do a Verify for Director
1715  *
1716  */
1717 static int verify_cmd(JCR *jcr)
1718 {
1719    BSOCK *dir = jcr->dir_bsock;
1720    BSOCK *sd  = jcr->store_bsock;
1721    char level[100];
1722
1723    jcr->set_JobType(JT_VERIFY);
1724    if (sscanf(dir->msg, verifycmd, level) != 1) {
1725       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
1726       return 0;
1727    }
1728
1729    if (strcasecmp(level, "init") == 0) {
1730       jcr->set_JobLevel(L_VERIFY_INIT);
1731    } else if (strcasecmp(level, "catalog") == 0){
1732       jcr->set_JobLevel(L_VERIFY_CATALOG);
1733    } else if (strcasecmp(level, "volume") == 0){
1734       jcr->set_JobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1735    } else if (strcasecmp(level, "data") == 0){
1736       jcr->set_JobLevel(L_VERIFY_DATA);
1737    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1738       jcr->set_JobLevel(L_VERIFY_DISK_TO_CATALOG);
1739    } else {
1740       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
1741       return 0;
1742    }
1743
1744    dir->fsend(OKverify);
1745
1746    generate_daemon_event(jcr, "JobStart");
1747    generate_plugin_event(jcr, bEventLevel, (void *)jcr->getJobLevel());
1748    generate_plugin_event(jcr, bEventStartVerifyJob);
1749
1750    Dmsg1(110, "filed>dird: %s", dir->msg);
1751
1752    switch (jcr->getJobLevel()) {
1753    case L_VERIFY_INIT:
1754    case L_VERIFY_CATALOG:
1755       do_verify(jcr);
1756       break;
1757    case L_VERIFY_VOLUME_TO_CATALOG:
1758       if (!open_sd_read_session(jcr)) {
1759          return 0;
1760       }
1761       start_dir_heartbeat(jcr);
1762       do_verify_volume(jcr);
1763       stop_dir_heartbeat(jcr);
1764       /*
1765        * Send Close session command to Storage daemon
1766        */
1767       sd->fsend(read_close, jcr->Ticket);
1768       Dmsg1(130, "filed>stored: %s", sd->msg);
1769
1770       /* ****FIXME**** check response */
1771       bget_msg(sd);                      /* get OK */
1772
1773       /* Inform Storage daemon that we are done */
1774       sd->signal(BNET_TERMINATE);
1775
1776       break;
1777    case L_VERIFY_DISK_TO_CATALOG:
1778       do_verify(jcr);
1779       break;
1780    default:
1781       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
1782       return 0;
1783    }
1784
1785    dir->signal(BNET_EOD);
1786    generate_plugin_event(jcr, bEventEndVerifyJob);
1787    return 0;                          /* return and terminate command loop */
1788 }
1789
1790 #ifdef WIN32_VSS
1791 static bool vss_restore_init_callback(JCR *jcr, int init_type)
1792 {
1793    switch (init_type)
1794    {
1795    case VSS_INIT_RESTORE_AFTER_INIT:
1796       generate_plugin_event(jcr, bEventVssRestoreLoadComponentMetadata);
1797       return true;
1798    case VSS_INIT_RESTORE_AFTER_GATHER:
1799       generate_plugin_event(jcr, bEventVssRestoreSetComponentsSelected);
1800       return true;
1801    default:
1802       return false;
1803       break;
1804    }
1805 }
1806 #endif
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 #if defined(WIN32_VSS)
1826
1827    /* TODO: this should be given from the director */
1828    enable_vss = 1;
1829
1830    Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
1831    // capture state here, if client is backed up by multiple directors
1832    // and one enables vss and the other does not then enable_vss can change
1833    // between here and where its evaluated after the job completes.
1834    jcr->VSS = g_pVSSClient && enable_vss;
1835    if (jcr->VSS) {
1836       /* Run only one at a time */
1837       P(vss_mutex);
1838    }
1839 #endif
1840    /* Pickup where string */
1841    args = get_memory(dir->msglen+1);
1842    *args = 0;
1843
1844    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
1845       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
1846          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
1847             pm_strcpy(jcr->errmsg, dir->msg);
1848             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
1849             return 0;
1850          }
1851          *args = 0;
1852       }
1853       use_regexwhere = true;
1854    }
1855    /* Turn / into nothing */
1856    if (IsPathSeparator(args[0]) && args[1] == '\0') {
1857       args[0] = '\0';
1858    }
1859
1860    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
1861    unbash_spaces(args);
1862
1863    if (use_regexwhere) {
1864       jcr->where_bregexp = get_bregexps(args);
1865       if (!jcr->where_bregexp) {
1866          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
1867          free_pool_memory(args);
1868          return 0;
1869       }
1870    } else {
1871       jcr->where = bstrdup(args);
1872    }
1873
1874    free_pool_memory(args);
1875    jcr->replace = replace;
1876    jcr->prefix_links = prefix_links;
1877
1878    dir->fsend(OKrestore);
1879    Dmsg1(110, "filed>dird: %s", dir->msg);
1880
1881    jcr->set_JobType(JT_RESTORE);
1882
1883    set_jcr_job_status(jcr, JS_Blocked);
1884
1885    if (!open_sd_read_session(jcr)) {
1886       set_jcr_job_status(jcr, JS_ErrorTerminated);
1887       goto bail_out;
1888    }
1889
1890    set_jcr_job_status(jcr, JS_Running);
1891
1892    /**
1893     * Do restore of files and data
1894     */
1895    start_dir_heartbeat(jcr);
1896    generate_daemon_event(jcr, "JobStart");
1897    generate_plugin_event(jcr, bEventStartRestoreJob);
1898
1899 #if defined(WIN32_VSS)
1900    /* START VSS ON WIN32 */
1901    if (jcr->VSS) {
1902       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback)) {
1903          /* inform user about writer states */
1904          int i;
1905          for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
1906             int msg_type = M_INFO;
1907             if (g_pVSSClient->GetWriterState(i) < 1) {
1908                msg_type = M_WARNING;
1909                jcr->JobErrors++;
1910             }
1911             if (g_pVSSClient->GetWriterState(i) < 1) {
1912                Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
1913                jcr->JobErrors++;
1914             }
1915          }
1916       } else {
1917          berrno be;
1918          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
1919       }
1920       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
1921    }
1922 #endif
1923
1924    do_restore(jcr);
1925    stop_dir_heartbeat(jcr);
1926
1927    set_jcr_job_status(jcr, JS_Terminated);
1928    if (jcr->JobStatus != JS_Terminated) {
1929       bnet_suppress_error_messages(sd, 1);
1930    }
1931
1932    /**
1933     * Send Close session command to Storage daemon
1934     */
1935    sd->fsend(read_close, jcr->Ticket);
1936    Dmsg1(130, "filed>stored: %s", sd->msg);
1937
1938    bget_msg(sd);                      /* get OK */
1939
1940    /* Inform Storage daemon that we are done */
1941    sd->signal(BNET_TERMINATE);
1942
1943 #if defined(WIN32_VSS)
1944    /* STOP VSS ON WIN32 */
1945    /* tell vss to close the restore session */
1946    Dmsg0(0, "About to call CloseRestore\n");
1947    if (jcr->VSS) {
1948       Dmsg0(0, "Really about to call CloseRestore\n");
1949       if (g_pVSSClient->CloseRestore()) {
1950          Dmsg0(0, "CloseRestore success\n");
1951          /* inform user about writer states */
1952          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1953             int msg_type = M_INFO;
1954             if (g_pVSSClient->GetWriterState(i) < 1) {
1955                msg_type = M_WARNING;
1956                jcr->JobErrors++;
1957             }
1958             Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1959          }
1960       }
1961       else
1962          Dmsg1(0, "CloseRestore fail - %08x\n", errno);
1963       V(vss_mutex);
1964    }
1965 #endif
1966
1967 bail_out:
1968    bfree_and_null(jcr->where);
1969
1970    if (jcr->JobErrors) {
1971       set_jcr_job_status(jcr, JS_ErrorTerminated);
1972    }
1973
1974    Dmsg0(130, "Done in job.c\n");
1975
1976    int ret;
1977    if (jcr->multi_restore) {
1978       dir->fsend(OKstoreend);
1979       ret = 1;     /* we continue the loop, waiting for next part */
1980    } else {
1981       end_restore_cmd(jcr);
1982       ret = 0;     /* we stop here */
1983    }
1984
1985    return ret;
1986 }
1987
1988 static int end_restore_cmd(JCR *jcr) 
1989 {
1990    Dmsg0(5, "end_restore_cmd\n");
1991    generate_plugin_event(jcr, bEventEndRestoreJob);
1992    return 0;                          /* return and terminate command loop */
1993 }
1994
1995 static int open_sd_read_session(JCR *jcr)
1996 {
1997    BSOCK *sd = jcr->store_bsock;
1998
1999    if (!sd) {
2000       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2001       return 0;
2002    }
2003    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2004       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2005    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2006    /*
2007     * Open Read Session with Storage daemon
2008     */
2009    sd->fsend(read_open, "DummyVolume",
2010       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2011       jcr->StartBlock, jcr->EndBlock);
2012    Dmsg1(110, ">stored: %s", sd->msg);
2013
2014    /*
2015     * Get ticket number
2016     */
2017    if (bget_msg(sd) >= 0) {
2018       Dmsg1(110, "filed<stored: %s", sd->msg);
2019       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2020          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2021          return 0;
2022       }
2023       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2024    } else {
2025       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2026       return 0;
2027    }
2028
2029    if (!send_bootstrap_file(jcr)) {
2030       return 0;
2031    }
2032
2033    /*
2034     * Start read of data with Storage daemon
2035     */
2036    sd->fsend(read_data, jcr->Ticket);
2037    Dmsg1(110, ">stored: %s", sd->msg);
2038
2039    /*
2040     * Get OK data
2041     */
2042    if (!response(jcr, sd, OK_data, "Read Data")) {
2043       return 0;
2044    }
2045    return 1;
2046 }
2047
2048 /**
2049  * Destroy the Job Control Record and associated
2050  * resources (sockets).
2051  */
2052 static void filed_free_jcr(JCR *jcr)
2053 {
2054    if (jcr->store_bsock) {
2055       jcr->store_bsock->close();
2056    }
2057    free_bootstrap(jcr);
2058    if (jcr->last_fname) {
2059       free_pool_memory(jcr->last_fname);
2060    }
2061    free_runscripts(jcr->RunScripts);
2062    delete jcr->RunScripts;
2063
2064    if (jcr->JobId != 0)
2065       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2066
2067    return;
2068 }
2069
2070 /**
2071  * Get response from Storage daemon to a command we
2072  * sent. Check that the response is OK.
2073  *
2074  *  Returns: 0 on failure
2075  *           1 on success
2076  */
2077 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2078 {
2079    if (sd->errors) {
2080       return 0;
2081    }
2082    if (bget_msg(sd) > 0) {
2083       Dmsg0(110, sd->msg);
2084       if (strcmp(sd->msg, resp) == 0) {
2085          return 1;
2086       }
2087    }
2088    if (job_canceled(jcr)) {
2089       return 0;                       /* if canceled avoid useless error messages */
2090    }
2091    if (is_bnet_error(sd)) {
2092       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2093          cmd, bnet_strerror(sd));
2094    } else {
2095       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
2096          cmd, resp, sd->msg);
2097    }
2098    return 0;
2099 }
2100
2101 static int send_bootstrap_file(JCR *jcr)
2102 {
2103    FILE *bs;
2104    char buf[2000];
2105    BSOCK *sd = jcr->store_bsock;
2106    const char *bootstrap = "bootstrap\n";
2107    int stat = 0;
2108
2109    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
2110    if (!jcr->RestoreBootstrap) {
2111       return 1;
2112    }
2113    bs = fopen(jcr->RestoreBootstrap, "rb");
2114    if (!bs) {
2115       berrno be;
2116       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
2117          jcr->RestoreBootstrap, be.bstrerror());
2118       set_jcr_job_status(jcr, JS_ErrorTerminated);
2119       goto bail_out;
2120    }
2121    sd->msglen = pm_strcpy(sd->msg, bootstrap);
2122    sd->send();
2123    while (fgets(buf, sizeof(buf), bs)) {
2124       sd->msglen = Mmsg(sd->msg, "%s", buf);
2125       sd->send();
2126    }
2127    sd->signal(BNET_EOD);
2128    fclose(bs);
2129    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
2130       set_jcr_job_status(jcr, JS_ErrorTerminated);
2131       goto bail_out;
2132    }
2133    stat = 1;
2134
2135 bail_out:
2136    free_bootstrap(jcr);
2137    return stat;
2138 }