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