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