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