]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Add extra Bacula plugin variables
[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
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 trace=%d hangup=%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          cjcr->setJobStatus(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    int32_t level, trace, hangup;
520    int scan;
521
522    Dmsg1(50, "setdebug_cmd: %s", dir->msg);
523    scan = sscanf(dir->msg, "setdebug=%d trace=%d hangup=%d",
524        &level, &trace, &hangup);
525    if (scan != 3) {
526       Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
527       if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace) != 2) {
528          pm_strcpy(jcr->errmsg, dir->msg);
529          dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
530          return 0;
531       } else {
532          hangup = -1;
533       }
534    }
535    if (level >= 0) {
536       debug_level = level;
537    }
538    set_trace(trace);
539    set_hangup(hangup);
540    Dmsg3(50, "level=%d trace=%d hangup=%d\n", level, get_trace(), get_hangup());
541    return dir->fsend(OKsetdebug, level, get_trace(), get_hangup());
542 }
543
544
545 static int estimate_cmd(JCR *jcr)
546 {
547    BSOCK *dir = jcr->dir_bsock;
548    char ed1[50], ed2[50];
549
550    if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
551       pm_strcpy(jcr->errmsg, dir->msg);
552       Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
553       dir->fsend(_("2992 Bad estimate command.\n"));
554       return 0;
555    }
556    make_estimate(jcr);
557    dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
558       edit_uint64_with_commas(jcr->JobBytes, ed2));
559    dir->signal(BNET_EOD);
560    return 1;
561 }
562
563 /**
564  * Get JobId and Storage Daemon Authorization key from Director
565  */
566 static int job_cmd(JCR *jcr)
567 {
568    BSOCK *dir = jcr->dir_bsock;
569    POOL_MEM sd_auth_key(PM_MESSAGE);
570    sd_auth_key.check_size(dir->msglen);
571
572    if (sscanf(dir->msg, jobcmd,  &jcr->JobId, jcr->Job,
573               &jcr->VolSessionId, &jcr->VolSessionTime, 
574               sd_auth_key.c_str()) != 5) {
575       pm_strcpy(jcr->errmsg, dir->msg);
576       Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
577       dir->fsend(BADjob);
578       return 0;
579    }
580    set_storage_auth_key(jcr, sd_auth_key.c_str());
581    Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
582    Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
583    new_plugins(jcr);                  /* instantiate plugins for this jcr */
584    generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
585    return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
586 }
587
588 static int runbefore_cmd(JCR *jcr)
589 {
590    bool ok;
591    BSOCK *dir = jcr->dir_bsock;
592    POOLMEM *cmd = get_memory(dir->msglen+1);
593    RUNSCRIPT *script;
594
595    Dmsg1(100, "runbefore_cmd: %s", dir->msg);
596    if (sscanf(dir->msg, runbefore, cmd) != 1) {
597       pm_strcpy(jcr->errmsg, dir->msg);
598       Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
599       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
600       free_memory(cmd);
601       return 0;
602    }
603    unbash_spaces(cmd);
604
605    /* Run the command now */
606    script = new_runscript();
607    script->set_command(cmd);
608    script->when = SCRIPT_Before;
609    ok = script->run(jcr, "ClientRunBeforeJob");
610    free_runscript(script);
611
612    free_memory(cmd);
613    if (ok) {
614       dir->fsend(OKRunBefore);
615       return 1;
616    } else {
617       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
618       return 0;
619    }
620 }
621
622 static int runbeforenow_cmd(JCR *jcr)
623 {
624    BSOCK *dir = jcr->dir_bsock;
625
626    run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
627    if (job_canceled(jcr)) {
628       dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
629       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
630       return 0;
631    } else {
632       dir->fsend(OKRunBeforeNow);
633       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
634       return 1;
635    }
636 }
637
638 static int runafter_cmd(JCR *jcr)
639 {
640    BSOCK *dir = jcr->dir_bsock;
641    POOLMEM *msg = get_memory(dir->msglen+1);
642    RUNSCRIPT *cmd;
643
644    Dmsg1(100, "runafter_cmd: %s", dir->msg);
645    if (sscanf(dir->msg, runafter, msg) != 1) {
646       pm_strcpy(jcr->errmsg, dir->msg);
647       Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
648       dir->fsend(_("2905 Bad RunAfterJob command.\n"));
649       free_memory(msg);
650       return 0;
651    }
652    unbash_spaces(msg);
653
654    cmd = new_runscript();
655    cmd->set_command(msg);
656    cmd->on_success = true;
657    cmd->on_failure = false;
658    cmd->when = SCRIPT_After;
659
660    jcr->RunScripts->append(cmd);
661
662    free_pool_memory(msg);
663    return dir->fsend(OKRunAfter);
664 }
665
666 static int runscript_cmd(JCR *jcr)
667 {
668    BSOCK *dir = jcr->dir_bsock;
669    POOLMEM *msg = get_memory(dir->msglen+1);
670    int on_success, on_failure, fail_on_error;
671
672    RUNSCRIPT *cmd = new_runscript() ;
673
674    Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
675    /* Note, we cannot sscanf into bools */
676    if (sscanf(dir->msg, runscript, &on_success, 
677                                   &on_failure,
678                                   &fail_on_error,
679                                   &cmd->when,
680                                   msg) != 5) {
681       pm_strcpy(jcr->errmsg, dir->msg);
682       Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
683       dir->fsend(_("2905 Bad RunScript command.\n"));
684       free_runscript(cmd);
685       free_memory(msg);
686       return 0;
687    }
688    cmd->on_success = on_success;
689    cmd->on_failure = on_failure;
690    cmd->fail_on_error = fail_on_error;
691    unbash_spaces(msg);
692
693    cmd->set_command(msg);
694    cmd->debug();
695    jcr->RunScripts->append(cmd);
696
697    free_pool_memory(msg);
698    return dir->fsend(OKRunScript);
699 }
700
701 /*
702  * This reads data sent from the Director from the
703  *   RestoreObject table that allows us to get objects
704  *   that were backed up (VSS .xml data) and are needed
705  *   before starting the restore.
706  */
707 static int restore_object_cmd(JCR *jcr)
708 {
709    BSOCK *dir = jcr->dir_bsock;
710    int32_t FileIndex;
711    restore_object_pkt rop;
712
713    memset(&rop, 0, sizeof(rop));
714    rop.pkt_size = sizeof(rop);
715    rop.pkt_end = sizeof(rop);
716    Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
717    if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
718       generate_plugin_event(jcr, bEventRestoreObject, NULL);
719       return dir->fsend(OKRestoreObject);
720    }
721
722    if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len, 
723               &rop.object_full_len, &rop.object_index, 
724               &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
725       Dmsg0(5, "Bad restore object command\n");
726       pm_strcpy(jcr->errmsg, dir->msg);
727       Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
728       goto bail_out;
729    }
730
731    Dmsg6(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d FI=%d\n",
732          rop.JobId, rop.object_len, rop.object_full_len, 
733          rop.object_index, rop.object_type, FileIndex);
734    /* Read Object name */
735    if (dir->recv() < 0) {
736       goto bail_out;
737    }
738    Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
739    rop.object_name = bstrdup(dir->msg);
740
741    /* Read Object */
742    if (dir->recv() < 0) {
743       goto bail_out;
744    }
745    /* Transfer object from message buffer, and get new message buffer */
746    rop.object = dir->msg;
747    dir->msg = get_pool_memory(PM_MESSAGE);
748
749    /* If object is compressed, uncompress it */
750    if (rop.object_compression == 1) {   /* zlib level 9 */
751       int stat;
752       int out_len = rop.object_full_len + 100;
753       POOLMEM *obj = get_memory(out_len);
754       Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
755       stat = Zinflate(rop.object, rop.object_len, obj, out_len);
756       Dmsg1(100, "Zinflate stat=%d\n", stat);
757       if (out_len != rop.object_full_len) {
758          Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
759             rop.object_full_len, out_len, rop.object_name);
760       }
761       free_pool_memory(rop.object);   /* release compressed object */
762       rop.object = obj;               /* new uncompressed object */
763       rop.object_len = out_len;
764    }
765    Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
766    /* Special Job meta data */
767    if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
768       Dmsg0(100, "got job metadata\n");
769       free_and_null_pool_memory(jcr->job_metadata);
770       jcr->job_metadata = rop.object;
771       rop.object = NULL;
772    } else {
773       /* pass to plugin */
774       generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
775    }
776
777    if (rop.object_name) {
778       free(rop.object_name);
779    }
780    if (rop.object) {
781       free_pool_memory(rop.object);
782    }
783
784    Dmsg1(100, "Send: %s", OKRestoreObject);
785    return 1;
786
787 bail_out:
788    dir->fsend(_("2909 Bad RestoreObject command.\n"));
789    return 0;
790
791 }
792
793
794 static bool init_fileset(JCR *jcr)
795 {
796    FF_PKT *ff;
797    findFILESET *fileset;
798
799    if (!jcr->ff) {
800       return false;
801    }
802    ff = jcr->ff;
803    if (ff->fileset) {
804       return false;
805    }
806    fileset = (findFILESET *)malloc(sizeof(findFILESET));
807    memset(fileset, 0, sizeof(findFILESET));
808    ff->fileset = fileset;
809    fileset->state = state_none;
810    fileset->include_list.init(1, true);
811    fileset->exclude_list.init(1, true);
812    return true;
813 }
814
815 static void append_file(JCR *jcr, findINCEXE *incexe, 
816                         const char *buf, bool is_file)
817 {
818    if (is_file) {
819       incexe->name_list.append(new_dlistString(buf));
820
821    } else if (me->plugin_directory) {
822       generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
823       incexe->plugin_list.append(new_dlistString(buf));
824
825    } else {
826       Jmsg(jcr, M_FATAL, 0, 
827            _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
828            buf);
829    }
830 }
831
832 /**
833  * Add fname to include/exclude fileset list. First check for
834  * | and < and if necessary perform command.
835  */
836 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
837 {
838    findFILESET *fileset = jcr->ff->fileset;
839    char *p;
840    BPIPE *bpipe;
841    POOLMEM *fn;
842    FILE *ffd;
843    char buf[1000];
844    int ch;
845    int stat;
846
847    p = (char *)fname;
848    ch = (uint8_t)*p;
849    switch (ch) {
850    case '|':
851       p++;                            /* skip over | */
852       fn = get_pool_memory(PM_FNAME);
853       fn = edit_job_codes(jcr, fn, p, "");
854       bpipe = open_bpipe(fn, 0, "r");
855       if (!bpipe) {
856          berrno be;
857          Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
858             p, be.bstrerror());
859          free_pool_memory(fn);
860          return;
861       }
862       free_pool_memory(fn);
863       while (fgets(buf, sizeof(buf), bpipe->rfd)) {
864          strip_trailing_junk(buf);
865          append_file(jcr, fileset->incexe, buf, is_file);
866       }
867       if ((stat=close_bpipe(bpipe)) != 0) {
868          berrno be;
869          Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
870             p, be.code(stat), be.bstrerror(stat));
871          return;
872       }
873       break;
874    case '<':
875       Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
876       p++;                      /* skip over < */
877       if ((ffd = fopen(p, "rb")) == NULL) {
878          berrno be;
879          Jmsg(jcr, M_FATAL, 0, 
880               _("Cannot open FileSet input file: %s. ERR=%s\n"),
881             p, be.bstrerror());
882          return;
883       }
884       while (fgets(buf, sizeof(buf), ffd)) {
885          strip_trailing_junk(buf);
886          append_file(jcr, fileset->incexe, buf, is_file);
887       }
888       fclose(ffd);
889       break;
890    default:
891       append_file(jcr, fileset->incexe, fname, is_file);
892       break;
893    }
894 }
895
896 void set_incexe(JCR *jcr, findINCEXE *incexe)
897 {
898    findFILESET *fileset = jcr->ff->fileset;
899    fileset->incexe = incexe;
900 }
901
902
903 /**
904  * Define a new Exclude block in the FileSet
905  */
906 findINCEXE *new_exclude(JCR *jcr)
907 {
908    findFILESET *fileset = jcr->ff->fileset;
909
910    /* New exclude */
911    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
912    memset(fileset->incexe, 0, sizeof(findINCEXE));
913    fileset->incexe->opts_list.init(1, true);
914    fileset->incexe->name_list.init();
915    fileset->incexe->plugin_list.init();
916    fileset->exclude_list.append(fileset->incexe);
917    return fileset->incexe;
918 }
919
920 /**
921  * Define a new Include block in the FileSet
922  */
923 findINCEXE *new_include(JCR *jcr)
924 {
925    findFILESET *fileset = jcr->ff->fileset;
926
927    /* New include */
928    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
929    memset(fileset->incexe, 0, sizeof(findINCEXE));
930    fileset->incexe->opts_list.init(1, true);
931    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
932    fileset->incexe->plugin_list.init();
933    fileset->include_list.append(fileset->incexe);
934    return fileset->incexe;
935 }
936
937 /**
938  * Define a new preInclude block in the FileSet
939  *   That is the include is prepended to the other
940  *   Includes.  This is used for plugin exclusions.
941  */
942 findINCEXE *new_preinclude(JCR *jcr)
943 {
944    findFILESET *fileset = jcr->ff->fileset;
945
946    /* New pre-include */
947    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
948    memset(fileset->incexe, 0, sizeof(findINCEXE));
949    fileset->incexe->opts_list.init(1, true);
950    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
951    fileset->incexe->plugin_list.init();
952    fileset->include_list.prepend(fileset->incexe);
953    return fileset->incexe;
954 }
955
956 static findFOPTS *start_options(FF_PKT *ff)
957 {
958    int state = ff->fileset->state;
959    findINCEXE *incexe = ff->fileset->incexe;
960
961    if (state != state_options) {
962       ff->fileset->state = state_options;
963       findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
964       memset(fo, 0, sizeof(findFOPTS));
965       fo->regex.init(1, true);
966       fo->regexdir.init(1, true);
967       fo->regexfile.init(1, true);
968       fo->wild.init(1, true);
969       fo->wilddir.init(1, true);
970       fo->wildfile.init(1, true);
971       fo->wildbase.init(1, true);
972       fo->base.init(1, true);
973       fo->fstype.init(1, true);
974       fo->drivetype.init(1, true);
975       incexe->current_opts = fo;
976       incexe->opts_list.append(fo);
977    }
978    return incexe->current_opts;
979 }
980
981 /*
982  * Used by plugins to define a new options block
983  */
984 void new_options(JCR *jcr, findINCEXE *incexe)
985 {
986    if (!incexe) {
987       incexe = jcr->ff->fileset->incexe;
988    }
989    findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
990    memset(fo, 0, sizeof(findFOPTS));
991    fo->regex.init(1, true);
992    fo->regexdir.init(1, true);
993    fo->regexfile.init(1, true);
994    fo->wild.init(1, true);
995    fo->wilddir.init(1, true);
996    fo->wildfile.init(1, true);
997    fo->wildbase.init(1, true);
998    fo->base.init(1, true);
999    fo->fstype.init(1, true);
1000    fo->drivetype.init(1, true);
1001    incexe->current_opts = fo;
1002    incexe->opts_list.prepend(fo);
1003    jcr->ff->fileset->state = state_options;
1004 }
1005
1006 /**
1007  * Add a regex to the current fileset
1008  */
1009 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
1010 {
1011    findFOPTS *current_opts = start_options(jcr->ff);
1012    regex_t *preg;
1013    int rc;
1014    char prbuf[500];
1015
1016    preg = (regex_t *)malloc(sizeof(regex_t));
1017    if (current_opts->flags & FO_IGNORECASE) {
1018       rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1019    } else {
1020       rc = regcomp(preg, item, REG_EXTENDED);
1021    }
1022    if (rc != 0) {
1023       regerror(rc, preg, prbuf, sizeof(prbuf));
1024       regfree(preg);
1025       free(preg);
1026       Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1027       return state_error;
1028    }
1029    if (type == ' ') {
1030       current_opts->regex.append(preg);
1031    } else if (type == 'D') {
1032       current_opts->regexdir.append(preg);
1033    } else if (type == 'F') {
1034       current_opts->regexfile.append(preg);
1035    } else {
1036       return state_error;
1037    }
1038    return state_options;
1039 }
1040
1041 /**
1042  * Add a wild card to the current fileset
1043  */
1044 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1045 {
1046    findFOPTS *current_opts = start_options(jcr->ff);
1047
1048    if (type == ' ') {
1049       current_opts->wild.append(bstrdup(item));
1050    } else if (type == 'D') {
1051       current_opts->wilddir.append(bstrdup(item));
1052    } else if (type == 'F') {
1053       current_opts->wildfile.append(bstrdup(item));
1054    } else if (type == 'B') {
1055       current_opts->wildbase.append(bstrdup(item));
1056    } else {
1057       return state_error;
1058    }
1059    return state_options;
1060 }
1061
1062
1063 /**
1064  * Add options to the current fileset
1065  */
1066 int add_options_to_fileset(JCR *jcr, const char *item)
1067 {
1068    findFOPTS *current_opts = start_options(jcr->ff);
1069
1070    set_options(current_opts, item);
1071    return state_options;
1072 }
1073
1074 static void add_fileset(JCR *jcr, const char *item)
1075 {
1076    FF_PKT *ff = jcr->ff;
1077    findFILESET *fileset = ff->fileset;
1078    int state = fileset->state;
1079    findFOPTS *current_opts;
1080
1081    /* Get code, optional subcode, and position item past the dividing space */
1082    Dmsg1(100, "%s\n", item);
1083    int code = item[0];
1084    if (code != '\0') {
1085       ++item;
1086    }
1087    int subcode = ' ';               /* A space is always a valid subcode */
1088    if (item[0] != '\0' && item[0] != ' ') {
1089       subcode = item[0];
1090       ++item;
1091    }
1092    if (*item == ' ') {
1093       ++item;
1094    }
1095
1096    /* Skip all lines we receive after an error */
1097    if (state == state_error) {
1098       Dmsg0(100, "State=error return\n");
1099       return;
1100    }
1101
1102    /**
1103     * The switch tests the code for validity.
1104     * The subcode is always good if it is a space, otherwise we must confirm.
1105     * We set state to state_error first assuming the subcode is invalid,
1106     * requiring state to be set in cases below that handle subcodes.
1107     */
1108    if (subcode != ' ') {
1109       state = state_error;
1110       Dmsg0(100, "Set state=error or double code.\n");
1111    }
1112    switch (code) {
1113    case 'I':
1114       (void)new_include(jcr);
1115       break;
1116    case 'E':
1117       (void)new_exclude(jcr);
1118       break;
1119    case 'N':                             /* null */
1120       state = state_none;
1121       break;
1122    case 'F':                             /* file = */
1123       /* File item to include or exclude list */
1124       state = state_include;
1125       add_file_to_fileset(jcr, item, true);
1126       break;
1127    case 'P':                              /* plugin */
1128       /* Plugin item to include list */
1129       state = state_include;
1130       add_file_to_fileset(jcr, item, false);
1131       break;
1132    case 'R':                              /* regex */
1133       state = add_regex_to_fileset(jcr, item, subcode);
1134       break;
1135    case 'B':
1136       current_opts = start_options(ff);
1137       current_opts->base.append(bstrdup(item));
1138       state = state_options;
1139       break;
1140    case 'X':                             /* Filetype or Drive type */
1141       current_opts = start_options(ff);
1142       state = state_options;
1143       if (subcode == ' ') {
1144          current_opts->fstype.append(bstrdup(item));
1145       } else if (subcode == 'D') {
1146          current_opts->drivetype.append(bstrdup(item));
1147       } else {
1148          state = state_error;
1149       }
1150       break;
1151    case 'W':                               /* wild cards */
1152       state = add_wild_to_fileset(jcr, item, subcode);
1153       break;
1154    case 'O':                                /* Options */
1155       state = add_options_to_fileset(jcr, item);
1156       break;
1157    case 'Z':                                /* ignore dir */
1158       state = state_include;
1159       fileset->incexe->ignoredir = bstrdup(item);
1160       break;
1161    case 'D':
1162       current_opts = start_options(ff);
1163 //    current_opts->reader = bstrdup(item); /* deprecated */
1164       state = state_options;
1165       break;
1166    case 'T':
1167       current_opts = start_options(ff);
1168 //    current_opts->writer = bstrdup(item); /* deprecated */
1169       state = state_options;
1170       break;
1171    default:
1172       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1173       state = state_error;
1174       break;
1175    }
1176    ff->fileset->state = state;
1177 }
1178
1179 static bool term_fileset(JCR *jcr)
1180 {
1181    FF_PKT *ff = jcr->ff;
1182
1183 #ifdef xxx_DEBUG_CODE
1184    findFILESET *fileset = ff->fileset;
1185    int i, j, k;
1186
1187    for (i=0; i<fileset->include_list.size(); i++) {
1188       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1189       Dmsg0(400, "I\n");
1190       for (j=0; j<incexe->opts_list.size(); j++) {
1191          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1192          for (k=0; k<fo->regex.size(); k++) {
1193             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1194          }
1195          for (k=0; k<fo->regexdir.size(); k++) {
1196             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1197          }
1198          for (k=0; k<fo->regexfile.size(); k++) {
1199             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1200          }
1201          for (k=0; k<fo->wild.size(); k++) {
1202             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1203          }
1204          for (k=0; k<fo->wilddir.size(); k++) {
1205             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1206          }
1207          for (k=0; k<fo->wildfile.size(); k++) {
1208             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1209          }
1210          for (k=0; k<fo->wildbase.size(); k++) {
1211             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1212          }
1213          for (k=0; k<fo->base.size(); k++) {
1214             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1215          }
1216          for (k=0; k<fo->fstype.size(); k++) {
1217             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1218          }
1219          for (k=0; k<fo->drivetype.size(); k++) {
1220             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1221          }
1222       }
1223       if (incexe->ignoredir) {
1224          Dmsg1(400, "Z %s\n", incexe->ignoredir);
1225       }
1226       dlistString *node;
1227       foreach_dlist(node, &incexe->name_list) {
1228          Dmsg1(400, "F %s\n", node->c_str());
1229       }
1230       foreach_dlist(node, &incexe->plugin_list) {
1231          Dmsg1(400, "P %s\n", node->c_str());
1232       }
1233    }
1234    for (i=0; i<fileset->exclude_list.size(); i++) {
1235       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1236       Dmsg0(400, "E\n");
1237       for (j=0; j<incexe->opts_list.size(); j++) {
1238          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1239          for (k=0; k<fo->regex.size(); k++) {
1240             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1241          }
1242          for (k=0; k<fo->regexdir.size(); k++) {
1243             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1244          }
1245          for (k=0; k<fo->regexfile.size(); k++) {
1246             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1247          }
1248          for (k=0; k<fo->wild.size(); k++) {
1249             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1250          }
1251          for (k=0; k<fo->wilddir.size(); k++) {
1252             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1253          }
1254          for (k=0; k<fo->wildfile.size(); k++) {
1255             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1256          }
1257          for (k=0; k<fo->wildbase.size(); k++) {
1258             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1259          }
1260          for (k=0; k<fo->base.size(); k++) {
1261             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1262          }
1263          for (k=0; k<fo->fstype.size(); k++) {
1264             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1265          }
1266          for (k=0; k<fo->drivetype.size(); k++) {
1267             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1268          }
1269       }
1270       dlistString *node;
1271       foreach_dlist(node, incexe->name_list) {
1272          Dmsg1(400, "F %s\n", node->c_str());
1273       }
1274       foreach_dlist(node, &incexe->plugin_list) {
1275          Dmsg1(400, "P %s\n", node->c_str());
1276       }
1277    }
1278 #endif
1279    return ff->fileset->state != state_error;
1280 }
1281
1282
1283 /**
1284  * As an optimization, we should do this during
1285  *  "compile" time in filed/job.c, and keep only a bit mask
1286  *  and the Verify options.
1287  */
1288 static int set_options(findFOPTS *fo, const char *opts)
1289 {
1290    int j;
1291    const char *p;
1292    char strip[100];
1293
1294 // Commented out as it is not backward compatible - KES
1295 #ifdef HAVE_WIN32
1296 //   fo->flags |= FO_IGNORECASE; /* always ignorecase under windows */
1297 #endif
1298
1299    for (p=opts; *p; p++) {
1300       switch (*p) {
1301       case 'a':                 /* alway replace */
1302       case '0':                 /* no option */
1303          break;
1304       case 'e':
1305          fo->flags |= FO_EXCLUDE;
1306          break;
1307       case 'f':
1308          fo->flags |= FO_MULTIFS;
1309          break;
1310       case 'h':                 /* no recursion */
1311          fo->flags |= FO_NO_RECURSION;
1312          break;
1313       case 'H':                 /* no hard link handling */
1314          fo->flags |= FO_NO_HARDLINK;
1315          break;
1316       case 'i':
1317          fo->flags |= FO_IGNORECASE;
1318          break;
1319       case 'M':                 /* MD5 */
1320          fo->flags |= FO_MD5;
1321          break;
1322       case 'n':
1323          fo->flags |= FO_NOREPLACE;
1324          break;
1325       case 'p':                 /* use portable data format */
1326          fo->flags |= FO_PORTABLE;
1327          break;
1328       case 'R':                 /* Resource forks and Finder Info */
1329          fo->flags |= FO_HFSPLUS;
1330          break;
1331       case 'r':                 /* read fifo */
1332          fo->flags |= FO_READFIFO;
1333          break;
1334       case 'S':
1335          switch(*(p + 1)) {
1336          case '1':
1337             fo->flags |= FO_SHA1;
1338             p++;
1339             break;
1340 #ifdef HAVE_SHA2
1341          case '2':
1342             fo->flags |= FO_SHA256;
1343             p++;
1344             break;
1345          case '3':
1346             fo->flags |= FO_SHA512;
1347             p++;
1348             break;
1349 #endif
1350          default:
1351             /*
1352              * If 2 or 3 is seen here, SHA2 is not configured, so
1353              *  eat the option, and drop back to SHA-1.
1354              */
1355             if (p[1] == '2' || p[1] == '3') {
1356                p++;
1357             }
1358             fo->flags |= FO_SHA1;
1359             break;
1360          }
1361          break;
1362       case 's':
1363          fo->flags |= FO_SPARSE;
1364          break;
1365       case 'm':
1366          fo->flags |= FO_MTIMEONLY;
1367          break;
1368       case 'k':
1369          fo->flags |= FO_KEEPATIME;
1370          break;
1371       case 'A':
1372          fo->flags |= FO_ACL;
1373          break;
1374       case 'V':                  /* verify options */
1375          /* Copy Verify Options */
1376          for (j=0; *p && *p != ':'; p++) {
1377             fo->VerifyOpts[j] = *p;
1378             if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1379                j++;
1380             }
1381          }
1382          fo->VerifyOpts[j] = 0;
1383          break;
1384       case 'C':                  /* accurate options */
1385          /* Copy Accurate Options */
1386          for (j=0; *p && *p != ':'; p++) {
1387             fo->AccurateOpts[j] = *p;
1388             if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1389                j++;
1390             }
1391          }
1392          fo->AccurateOpts[j] = 0;
1393          break;
1394       case 'J':                  /* Basejob options */
1395          /* Copy BaseJob Options */
1396          for (j=0; *p && *p != ':'; p++) {
1397             fo->BaseJobOpts[j] = *p;
1398             if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1399                j++;
1400             }
1401          }
1402          fo->BaseJobOpts[j] = 0;
1403          break;
1404       case 'P':                  /* strip path */
1405          /* Get integer */
1406          p++;                    /* skip P */
1407          for (j=0; *p && *p != ':'; p++) {
1408             strip[j] = *p;
1409             if (j < (int)sizeof(strip) - 1) {
1410                j++;
1411             }
1412          }
1413          strip[j] = 0;
1414          fo->strip_path = atoi(strip);
1415          fo->flags |= FO_STRIPPATH;
1416          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1417          break;
1418       case 'w':
1419          fo->flags |= FO_IF_NEWER;
1420          break;
1421       case 'W':
1422          fo->flags |= FO_ENHANCEDWILD;
1423          break;
1424       case 'Z':                 /* gzip compression */
1425          fo->flags |= FO_GZIP;
1426          fo->GZIP_level = *++p - '0';
1427          break;
1428       case 'K':
1429          fo->flags |= FO_NOATIME;
1430          break;
1431       case 'c':
1432          fo->flags |= FO_CHKCHANGES;
1433          break;
1434       case 'N':
1435          fo->flags |= FO_HONOR_NODUMP;
1436          break;
1437       case 'X':
1438          fo->flags |= FO_XATTR;
1439          break;
1440       default:
1441          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1442          break;
1443       }
1444    }
1445    return state_options;
1446 }
1447
1448
1449 /**
1450  * Director is passing his Fileset
1451  */
1452 static int fileset_cmd(JCR *jcr)
1453 {
1454    BSOCK *dir = jcr->dir_bsock;
1455    int rtnstat;
1456
1457 #if defined(WIN32_VSS)
1458    int vss = 0;
1459
1460    sscanf(dir->msg, "fileset vss=%d", &vss);
1461    enable_vss = vss;
1462 #endif
1463
1464    if (!init_fileset(jcr)) {
1465       return 0;
1466    }
1467    while (dir->recv() >= 0) {
1468       strip_trailing_junk(dir->msg);
1469       Dmsg1(500, "Fileset: %s\n", dir->msg);
1470       add_fileset(jcr, dir->msg);
1471    }
1472    if (!term_fileset(jcr)) {
1473       return 0;
1474    }
1475    rtnstat = dir->fsend(OKinc);
1476    generate_plugin_event(jcr, bEventEndFileSet);
1477    return rtnstat;
1478 }
1479
1480 static void free_bootstrap(JCR *jcr)
1481 {
1482    if (jcr->RestoreBootstrap) {
1483       unlink(jcr->RestoreBootstrap);
1484       free_pool_memory(jcr->RestoreBootstrap);
1485       jcr->RestoreBootstrap = NULL;
1486    }
1487 }
1488
1489
1490 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1491 static uint32_t bsr_uniq = 0;
1492
1493 /**
1494  * The Director sends us the bootstrap file, which
1495  *   we will in turn pass to the SD.
1496  *   Deprecated.  The bsr is now sent directly from the
1497  *   Director to the SD.
1498  */
1499 static int bootstrap_cmd(JCR *jcr)
1500 {
1501    BSOCK *dir = jcr->dir_bsock;
1502    POOLMEM *fname = get_pool_memory(PM_FNAME);
1503    FILE *bs;
1504
1505    free_bootstrap(jcr);
1506    P(bsr_mutex);
1507    bsr_uniq++;
1508    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1509       jcr->Job, bsr_uniq);
1510    V(bsr_mutex);
1511    Dmsg1(400, "bootstrap=%s\n", fname);
1512    jcr->RestoreBootstrap = fname;
1513    bs = fopen(fname, "a+b");           /* create file */
1514    if (!bs) {
1515       berrno be;
1516       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1517          jcr->RestoreBootstrap, be.bstrerror());
1518       /*
1519        * Suck up what he is sending to us so that he will then
1520        *   read our error message.
1521        */
1522       while (dir->recv() >= 0)
1523         {  }
1524       free_bootstrap(jcr);
1525       jcr->setJobStatus(JS_ErrorTerminated);
1526       return 0;
1527    }
1528
1529    while (dir->recv() >= 0) {
1530        Dmsg1(200, "filed<dird: bootstrap: %s", dir->msg);
1531        fputs(dir->msg, bs);
1532    }
1533    fclose(bs);
1534    /*
1535     * Note, do not free the bootstrap yet -- it needs to be 
1536     *  sent to the SD 
1537     */
1538    return dir->fsend(OKbootstrap);
1539 }
1540
1541
1542 /**
1543  * Get backup level from Director
1544  *
1545  */
1546 static int level_cmd(JCR *jcr)
1547 {
1548    BSOCK *dir = jcr->dir_bsock;
1549    POOLMEM *level, *buf = NULL;
1550    int mtime_only;
1551
1552    level = get_memory(dir->msglen+1);
1553    Dmsg1(10, "level_cmd: %s", dir->msg);
1554
1555    /* keep compatibility with older directors */
1556    if (strstr(dir->msg, "accurate")) {
1557       jcr->accurate = true;
1558    }
1559    if (strstr(dir->msg, "rerunning")) {
1560       jcr->rerunning = true;
1561    }
1562    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1563       goto bail_out;
1564    }
1565    /* Base backup requested? */
1566    if (strcmp(level, "base") == 0) {
1567       jcr->setJobLevel(L_BASE);
1568    /* Full backup requested? */
1569    } else if (strcmp(level, "full") == 0) {
1570       jcr->setJobLevel(L_FULL);
1571    } else if (strstr(level, "differential")) {
1572       jcr->setJobLevel(L_DIFFERENTIAL);
1573       free_memory(level);
1574       return 1;
1575    } else if (strstr(level, "incremental")) {
1576       jcr->setJobLevel(L_INCREMENTAL);
1577       free_memory(level);
1578       return 1;
1579    /*
1580     * We get his UTC since time, then sync the clocks and correct it
1581     *   to agree with our clock.
1582     */
1583    } else if (strcmp(level, "since_utime") == 0) {
1584       buf = get_memory(dir->msglen+1);
1585       utime_t since_time, adj;
1586       btime_t his_time, bt_start, rt=0, bt_adj=0;
1587       if (jcr->getJobLevel() == L_NONE) {
1588          jcr->setJobLevel(L_SINCE);     /* if no other job level set, do it now */
1589       }
1590       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1591                  buf, &mtime_only) != 2) {
1592          goto bail_out;
1593       }
1594       since_time = str_to_uint64(buf);  /* this is the since time */
1595       Dmsg1(100, "since_time=%lld\n", since_time);
1596       char ed1[50], ed2[50];
1597       /*
1598        * Sync clocks by polling him for the time. We take
1599        *   10 samples of his time throwing out the first two.
1600        */
1601       for (int i=0; i<10; i++) {
1602          bt_start = get_current_btime();
1603          dir->signal(BNET_BTIME);     /* poll for time */
1604          if (dir->recv() <= 0) {      /* get response */
1605             goto bail_out;
1606          }
1607          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1608             goto bail_out;
1609          }
1610          if (i < 2) {                 /* toss first two results */
1611             continue;
1612          }
1613          his_time = str_to_uint64(buf);
1614          rt = get_current_btime() - bt_start; /* compute round trip time */
1615          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1616                edit_uint64(bt_start, ed2));
1617          bt_adj +=  bt_start - his_time - rt/2;
1618          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1619       }
1620
1621       bt_adj = bt_adj / 8;            /* compute average time */
1622       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1623       adj = btime_to_utime(bt_adj);
1624       since_time += adj;              /* adjust for clock difference */
1625       /* Don't notify if time within 3 seconds */
1626       if (adj > 3 || adj < -3) {
1627          int type;
1628          if (adj > 600 || adj < -600) {
1629             type = M_WARNING;
1630          } else {
1631             type = M_INFO;
1632          }
1633          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1634       }
1635       dir->signal(BNET_EOD);
1636
1637       Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1638       jcr->incremental = 1;           /* set incremental or decremental backup */
1639       jcr->mtime = since_time;        /* set since time */
1640       generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1641    } else {
1642       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1643       free_memory(level);
1644       return 0;
1645    }
1646    free_memory(level);
1647    if (buf) {
1648       free_memory(buf);
1649    }
1650    generate_plugin_event(jcr, bEventLevel, (void *)jcr->getJobLevel());
1651    return dir->fsend(OKlevel);
1652
1653 bail_out:
1654    pm_strcpy(jcr->errmsg, dir->msg);
1655    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1656    free_memory(level);
1657    if (buf) {
1658       free_memory(buf);
1659    }
1660    return 0;
1661 }
1662
1663 /**
1664  * Get session parameters from Director -- this is for a Restore command
1665  *   This is deprecated. It is now passed via the bsr.
1666  */
1667 static int session_cmd(JCR *jcr)
1668 {
1669    BSOCK *dir = jcr->dir_bsock;
1670
1671    Dmsg1(100, "SessionCmd: %s", dir->msg);
1672    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1673               &jcr->VolSessionId, &jcr->VolSessionTime,
1674               &jcr->StartFile, &jcr->EndFile,
1675               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1676       pm_strcpy(jcr->errmsg, dir->msg);
1677       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1678       return 0;
1679    }
1680
1681    return dir->fsend(OKsession);
1682 }
1683
1684 static void set_storage_auth_key(JCR *jcr, char *key)
1685 {
1686    /* if no key don't update anything */
1687    if (!*key) {                
1688       return;
1689    }
1690
1691    /**
1692     * We can be contacting multiple storage daemons.
1693     * So, make sure that any old jcr->store_bsock is cleaned up. 
1694     */
1695    if (jcr->store_bsock) {
1696       jcr->store_bsock->destroy();
1697       jcr->store_bsock = NULL;
1698    }
1699
1700    /**
1701     * We can be contacting multiple storage daemons.
1702     *   So, make sure that any old jcr->sd_auth_key is cleaned up. 
1703     */
1704    if (jcr->sd_auth_key) {
1705       /*
1706        * If we already have a Authorization key, director can do multi
1707        * storage restore
1708        */
1709       Dmsg0(5, "set multi_restore=true\n");
1710       jcr->multi_restore = true;
1711       bfree(jcr->sd_auth_key);
1712    }
1713
1714    jcr->sd_auth_key = bstrdup(key);
1715    Dmsg0(5, "set sd auth key\n");
1716 }
1717
1718 /**
1719  * Get address of storage daemon from Director
1720  *
1721  */
1722 static int storage_cmd(JCR *jcr)
1723 {
1724    int stored_port;                /* storage daemon port */
1725    int enable_ssl;                 /* enable ssl to sd */
1726    POOL_MEM sd_auth_key(PM_MESSAGE);
1727    BSOCK *dir = jcr->dir_bsock;
1728    BSOCK *sd = new_bsock();        /* storage daemon bsock */
1729
1730
1731    Dmsg1(100, "StorageCmd: %s", dir->msg);
1732    sd_auth_key.check_size(dir->msglen);
1733    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, 
1734               &enable_ssl, sd_auth_key.c_str()) != 4) {
1735       if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
1736                  &stored_port, &enable_ssl) != 3) {
1737          pm_strcpy(jcr->errmsg, dir->msg);
1738          Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1739          goto bail_out;
1740       }
1741    }
1742
1743    set_storage_auth_key(jcr, sd_auth_key.c_str());
1744
1745    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, 
1746          enable_ssl);
1747    /* Open command communications with Storage daemon */
1748    /* Try to connect for 1 hour at 10 second intervals */
1749
1750    sd->set_source_address(me->FDsrc_addr);
1751
1752    /* TODO: see if we put limit on restore and backup... */
1753    if (!jcr->max_bandwidth) {
1754       if (jcr->director->max_bandwidth_per_job) {
1755          jcr->max_bandwidth = jcr->director->max_bandwidth_per_job;
1756          
1757       } else if (me->max_bandwidth_per_job) {
1758          jcr->max_bandwidth = me->max_bandwidth_per_job;
1759       }
1760    }
1761    sd->set_bwlimit(jcr->max_bandwidth);
1762
1763    if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1764                 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1765      sd->destroy();
1766      sd = NULL;
1767    }
1768
1769    if (sd == NULL) {
1770       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1771           jcr->stored_addr, stored_port);
1772       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1773           jcr->stored_addr, stored_port);
1774       goto bail_out;
1775    }
1776    Dmsg0(110, "Connection OK to SD.\n");
1777
1778    jcr->store_bsock = sd;
1779
1780    sd->fsend("Hello Start Job %s\n", jcr->Job);
1781    if (!authenticate_storagedaemon(jcr)) {
1782       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1783       goto bail_out;
1784    }
1785    Dmsg0(110, "Authenticated with SD.\n");
1786
1787    /* Send OK to Director */
1788    return dir->fsend(OKstore);
1789
1790 bail_out:
1791    dir->fsend(BADcmd, "storage");
1792    return 0;
1793
1794 }
1795
1796
1797 /**
1798  * Do a backup.
1799  */
1800 static int backup_cmd(JCR *jcr)
1801 {
1802    BSOCK *dir = jcr->dir_bsock;
1803    BSOCK *sd = jcr->store_bsock;
1804    int ok = 0;
1805    int SDJobStatus;
1806    int32_t FileIndex;
1807
1808 #if defined(WIN32_VSS)
1809    // capture state here, if client is backed up by multiple directors
1810    // and one enables vss and the other does not then enable_vss can change
1811    // between here and where its evaluated after the job completes.
1812    jcr->VSS = g_pVSSClient && enable_vss;
1813    if (jcr->VSS) {
1814       /* Run only one at a time */
1815       P(vss_mutex);
1816    }
1817 #endif
1818   
1819    if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1820       jcr->JobFiles = FileIndex;
1821       Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1822    }
1823
1824    /**
1825     * Validate some options given to the backup make sense for the compiled in
1826     * options of this filed.
1827     */
1828    if (jcr->ff->flags & FO_ACL && !have_acl) {
1829       Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
1830       goto cleanup;
1831    }
1832    if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1833       Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
1834       goto cleanup;
1835    }
1836
1837    jcr->setJobStatus(JS_Blocked);
1838    jcr->setJobType(JT_BACKUP);
1839    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1840
1841    if (sd == NULL) {
1842       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1843       dir->fsend(BADcmd, "backup");
1844       goto cleanup;
1845    }
1846
1847    dir->fsend(OKbackup);
1848    Dmsg1(110, "filed>dird: %s", dir->msg);
1849
1850    /**
1851     * Send Append Open Session to Storage daemon
1852     */
1853    sd->fsend(append_open);
1854    Dmsg1(110, ">stored: %s", sd->msg);
1855    /**
1856     * Expect to receive back the Ticket number
1857     */
1858    if (bget_msg(sd) >= 0) {
1859       Dmsg1(110, "<stored: %s", sd->msg);
1860       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1861          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1862          goto cleanup;
1863       }
1864       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1865    } else {
1866       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1867       goto cleanup;
1868    }
1869
1870    /**
1871     * Send Append data command to Storage daemon
1872     */
1873    sd->fsend(append_data, jcr->Ticket);
1874    Dmsg1(110, ">stored: %s", sd->msg);
1875
1876    /**
1877     * Expect to get OK data
1878     */
1879    Dmsg1(110, "<stored: %s", sd->msg);
1880    if (!response(jcr, sd, OK_data, "Append Data")) {
1881       goto cleanup;
1882    }
1883    
1884    generate_daemon_event(jcr, "JobStart");
1885    generate_plugin_event(jcr, bEventStartBackupJob);
1886
1887 #if defined(WIN32_VSS)
1888    /* START VSS ON WIN32 */
1889    if (jcr->VSS) {      
1890       if (g_pVSSClient->InitializeForBackup(jcr)) {   
1891         generate_plugin_event(jcr, bEventVssBackupAddComponents);
1892         /* tell vss which drives to snapshot */   
1893         char szWinDriveLetters[27];
1894         *szWinDriveLetters=0;
1895         generate_plugin_event(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
1896         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1897             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1898             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1899                berrno be;
1900                Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
1901             } else {
1902                /* tell user if snapshot creation of a specific drive failed */
1903                int i;
1904                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1905                   if (islower(szWinDriveLetters[i])) {
1906                      Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed.\n"), szWinDriveLetters[i]);
1907                   }
1908                }
1909                /* inform user about writer states */
1910                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {               
1911                   if (g_pVSSClient->GetWriterState(i) < 1) {
1912                      Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1913                   }                            
1914                }
1915             }
1916         } else {
1917             Jmsg(jcr, M_FATAL, 0, _("No drive letters found for generating VSS snapshots.\n"));
1918         }
1919       } else {
1920          berrno be;
1921          Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly. ERR=%s\n"), be.bstrerror());
1922       } 
1923       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
1924    }
1925 #endif
1926
1927    /**
1928     * Send Files to Storage daemon
1929     */
1930    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1931    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1932       jcr->setJobStatus(JS_ErrorTerminated);
1933       bnet_suppress_error_messages(sd, 1);
1934       Dmsg0(110, "Error in blast_data.\n");
1935    } else {
1936       jcr->setJobStatus(JS_Terminated);
1937       /* Note, the above set status will not override an error */
1938       if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
1939          bnet_suppress_error_messages(sd, 1);
1940          goto cleanup;                /* bail out now */
1941       }
1942       /**
1943        * Expect to get response to append_data from Storage daemon
1944        */
1945       if (!response(jcr, sd, OK_append, "Append Data")) {
1946          jcr->setJobStatus(JS_ErrorTerminated);
1947          goto cleanup;
1948       }
1949
1950       /**
1951        * Send Append End Data to Storage daemon
1952        */
1953       sd->fsend(append_end, jcr->Ticket);
1954       /* Get end OK */
1955       if (!response(jcr, sd, OK_end, "Append End")) {
1956          jcr->setJobStatus(JS_ErrorTerminated);
1957          goto cleanup;
1958       }
1959
1960       /**
1961        * Send Append Close to Storage daemon
1962        */
1963       sd->fsend(append_close, jcr->Ticket);
1964       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1965          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1966             ok = 1;
1967             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1968          }
1969       }
1970       if (!ok) {
1971          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1972          goto cleanup;
1973       }
1974       if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings)) {
1975          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1976             SDJobStatus);
1977       }
1978    }
1979
1980 cleanup:
1981 #if defined(WIN32_VSS)
1982    if (jcr->VSS) {
1983       Win32ConvCleanupCache();
1984       g_pVSSClient->DestroyWriterInfo();
1985       V(vss_mutex);
1986    }
1987 #endif
1988
1989    generate_plugin_event(jcr, bEventEndBackupJob);
1990    return 0;                          /* return and stop command loop */
1991 }
1992
1993 /**
1994  * Do a Verify for Director
1995  *
1996  */
1997 static int verify_cmd(JCR *jcr)
1998 {
1999    BSOCK *dir = jcr->dir_bsock;
2000    BSOCK *sd  = jcr->store_bsock;
2001    char level[100];
2002
2003    jcr->setJobType(JT_VERIFY);
2004    if (sscanf(dir->msg, verifycmd, level) != 1) {
2005       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
2006       return 0;
2007    }
2008
2009    if (strcasecmp(level, "init") == 0) {
2010       jcr->setJobLevel(L_VERIFY_INIT);
2011    } else if (strcasecmp(level, "catalog") == 0){
2012       jcr->setJobLevel(L_VERIFY_CATALOG);
2013    } else if (strcasecmp(level, "volume") == 0){
2014       jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
2015    } else if (strcasecmp(level, "data") == 0){
2016       jcr->setJobLevel(L_VERIFY_DATA);
2017    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
2018       jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2019    } else {
2020       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2021       return 0;
2022    }
2023
2024    dir->fsend(OKverify);
2025
2026    generate_daemon_event(jcr, "JobStart");
2027    generate_plugin_event(jcr, bEventLevel, (void *)jcr->getJobLevel());
2028    generate_plugin_event(jcr, bEventStartVerifyJob);
2029
2030    Dmsg1(110, "filed>dird: %s", dir->msg);
2031
2032    switch (jcr->getJobLevel()) {
2033    case L_VERIFY_INIT:
2034    case L_VERIFY_CATALOG:
2035       do_verify(jcr);
2036       break;
2037    case L_VERIFY_VOLUME_TO_CATALOG:
2038       if (!open_sd_read_session(jcr)) {
2039          return 0;
2040       }
2041       start_dir_heartbeat(jcr);
2042       do_verify_volume(jcr);
2043       stop_dir_heartbeat(jcr);
2044       /*
2045        * Send Close session command to Storage daemon
2046        */
2047       sd->fsend(read_close, jcr->Ticket);
2048       Dmsg1(130, "filed>stored: %s", sd->msg);
2049
2050       /* ****FIXME**** check response */
2051       bget_msg(sd);                      /* get OK */
2052
2053       /* Inform Storage daemon that we are done */
2054       sd->signal(BNET_TERMINATE);
2055
2056       break;
2057    case L_VERIFY_DISK_TO_CATALOG:
2058       do_verify(jcr);
2059       break;
2060    default:
2061       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2062       return 0;
2063    }
2064
2065    dir->signal(BNET_EOD);
2066    generate_plugin_event(jcr, bEventEndVerifyJob);
2067    return 0;                          /* return and terminate command loop */
2068 }
2069
2070 #ifdef WIN32_VSS
2071 static bool vss_restore_init_callback(JCR *jcr, int init_type)
2072 {
2073    switch (init_type) {
2074    case VSS_INIT_RESTORE_AFTER_INIT:
2075       generate_plugin_event(jcr, bEventVssRestoreLoadComponentMetadata);
2076       return true;
2077    case VSS_INIT_RESTORE_AFTER_GATHER:
2078       generate_plugin_event(jcr, bEventVssRestoreSetComponentsSelected);
2079       return true;
2080    default:
2081       return false;
2082       break;
2083    }
2084 }
2085 #endif
2086
2087 /**
2088  * Do a Restore for Director
2089  *
2090  */
2091 static int restore_cmd(JCR *jcr)
2092 {
2093    BSOCK *dir = jcr->dir_bsock;
2094    BSOCK *sd = jcr->store_bsock;
2095    POOLMEM *args;
2096    bool use_regexwhere=false;
2097    int prefix_links;
2098    char replace;
2099
2100    /**
2101     * Scan WHERE (base directory for restore) from command
2102     */
2103    Dmsg0(100, "restore command\n");
2104 #if defined(WIN32_VSS)
2105
2106    /**
2107     * No need to enable VSS for restore if we do not have plugin
2108     *  data to restore 
2109     */
2110    enable_vss = jcr->job_metadata != NULL;
2111
2112    Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
2113    // capture state here, if client is backed up by multiple directors
2114    // and one enables vss and the other does not then enable_vss can change
2115    // between here and where its evaluated after the job completes.
2116    jcr->VSS = g_pVSSClient && enable_vss;
2117    if (jcr->VSS) {
2118       /* Run only one at a time */
2119       P(vss_mutex);
2120    }
2121 #endif
2122    /* Pickup where string */
2123    args = get_memory(dir->msglen+1);
2124    *args = 0;
2125
2126    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
2127       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
2128          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2129             pm_strcpy(jcr->errmsg, dir->msg);
2130             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2131             return 0;
2132          }
2133          *args = 0;
2134       }
2135       use_regexwhere = true;
2136    }
2137    /* Turn / into nothing */
2138    if (IsPathSeparator(args[0]) && args[1] == '\0') {
2139       args[0] = '\0';
2140    }
2141
2142    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2143    unbash_spaces(args);
2144
2145    if (use_regexwhere) {
2146       jcr->where_bregexp = get_bregexps(args);
2147       if (!jcr->where_bregexp) {
2148          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2149          free_pool_memory(args);
2150          return 0;
2151       }
2152    } else {
2153       jcr->where = bstrdup(args);
2154    }
2155
2156    free_pool_memory(args);
2157    jcr->replace = replace;
2158    jcr->prefix_links = prefix_links;
2159
2160    dir->fsend(OKrestore);
2161    Dmsg1(110, "filed>dird: %s", dir->msg);
2162
2163    jcr->setJobType(JT_RESTORE);
2164
2165    jcr->setJobStatus(JS_Blocked);
2166
2167    if (!open_sd_read_session(jcr)) {
2168       jcr->setJobStatus(JS_ErrorTerminated);
2169       goto bail_out;
2170    }
2171
2172    jcr->setJobStatus(JS_Running);
2173
2174    /**
2175     * Do restore of files and data
2176     */
2177    start_dir_heartbeat(jcr);
2178    generate_daemon_event(jcr, "JobStart");
2179    generate_plugin_event(jcr, bEventStartRestoreJob);
2180
2181 #if defined(WIN32_VSS)
2182    /* START VSS ON WIN32 */
2183    if (jcr->VSS) {
2184       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
2185             (WCHAR *)jcr->job_metadata)) {
2186
2187          /* inform user about writer states */
2188          int i;
2189          for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
2190             if (g_pVSSClient->GetWriterState(i) < 1) {
2191                Jmsg(jcr, M_INFO, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
2192                //jcr->JobErrors++;
2193             }
2194          }
2195       } else {
2196 /*
2197    int fd = open("C:\\eric.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777);
2198    write(fd, (WCHAR *)jcr->job_metadata, wcslen((WCHAR *)jcr->job_metadata) * sizeof(WCHAR));
2199    close(fd);
2200 */
2201          berrno be;
2202          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
2203       }
2204       free_and_null_pool_memory(jcr->job_metadata);
2205       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2206    }
2207 #endif
2208
2209    do_restore(jcr);
2210    stop_dir_heartbeat(jcr);
2211
2212    jcr->setJobStatus(JS_Terminated);
2213    if (jcr->JobStatus != JS_Terminated) {
2214       bnet_suppress_error_messages(sd, 1);
2215    }
2216
2217    /**
2218     * Send Close session command to Storage daemon
2219     */
2220    sd->fsend(read_close, jcr->Ticket);
2221    Dmsg1(100, "filed>stored: %s", sd->msg);
2222
2223    bget_msg(sd);                      /* get OK */
2224
2225    /* Inform Storage daemon that we are done */
2226    sd->signal(BNET_TERMINATE);
2227
2228 #if defined(WIN32_VSS)
2229    /* STOP VSS ON WIN32 */
2230    /* tell vss to close the restore session */
2231    Dmsg0(100, "About to call CloseRestore\n");
2232    if (jcr->VSS) {
2233       generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
2234       Dmsg0(100, "Really about to call CloseRestore\n");
2235       if (g_pVSSClient->CloseRestore()) {
2236          Dmsg0(100, "CloseRestore success\n");
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       }
2247       else
2248          Dmsg1(100, "CloseRestore fail - %08x\n", errno);
2249       V(vss_mutex);
2250    }
2251 #endif
2252
2253 bail_out:
2254    bfree_and_null(jcr->where);
2255
2256    if (jcr->JobErrors) {
2257       jcr->setJobStatus(JS_ErrorTerminated);
2258    }
2259
2260    Dmsg0(100, "Done in job.c\n");
2261
2262    int ret;
2263    if (jcr->multi_restore) {
2264       Dmsg0(100, OKstoreend);
2265       dir->fsend(OKstoreend);
2266       ret = 1;     /* we continue the loop, waiting for next part */
2267    } else {
2268       end_restore_cmd(jcr);
2269       ret = 0;     /* we stop here */
2270    }
2271
2272    if (job_canceled(jcr)) {
2273       ret = 0;     /* we stop here */
2274    }
2275
2276    return ret;
2277 }
2278
2279 static int end_restore_cmd(JCR *jcr) 
2280 {
2281    Dmsg0(5, "end_restore_cmd\n");
2282    generate_plugin_event(jcr, bEventEndRestoreJob);
2283    return 0;                          /* return and terminate command loop */
2284 }
2285
2286 static int open_sd_read_session(JCR *jcr)
2287 {
2288    BSOCK *sd = jcr->store_bsock;
2289
2290    if (!sd) {
2291       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2292       return 0;
2293    }
2294    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2295       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2296    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2297    /*
2298     * Open Read Session with Storage daemon
2299     */
2300    sd->fsend(read_open, "DummyVolume",
2301       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2302       jcr->StartBlock, jcr->EndBlock);
2303    Dmsg1(110, ">stored: %s", sd->msg);
2304
2305    /*
2306     * Get ticket number
2307     */
2308    if (bget_msg(sd) >= 0) {
2309       Dmsg1(110, "filed<stored: %s", sd->msg);
2310       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2311          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2312          return 0;
2313       }
2314       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2315    } else {
2316       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2317       return 0;
2318    }
2319
2320    if (!send_bootstrap_file(jcr)) {
2321       return 0;
2322    }
2323
2324    /*
2325     * Start read of data with Storage daemon
2326     */
2327    sd->fsend(read_data, jcr->Ticket);
2328    Dmsg1(110, ">stored: %s", sd->msg);
2329
2330    /*
2331     * Get OK data
2332     */
2333    if (!response(jcr, sd, OK_data, "Read Data")) {
2334       return 0;
2335    }
2336    return 1;
2337 }
2338
2339 /**
2340  * Destroy the Job Control Record and associated
2341  * resources (sockets).
2342  */
2343 static void filed_free_jcr(JCR *jcr)
2344 {
2345    if (jcr->store_bsock) {
2346       jcr->store_bsock->close();
2347    }
2348    free_bootstrap(jcr);
2349    if (jcr->last_fname) {
2350       free_pool_memory(jcr->last_fname);
2351    }
2352    free_runscripts(jcr->RunScripts);
2353    delete jcr->RunScripts;
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 }
2391
2392 static int send_bootstrap_file(JCR *jcr)
2393 {
2394    FILE *bs;
2395    char buf[2000];
2396    BSOCK *sd = jcr->store_bsock;
2397    const char *bootstrap = "bootstrap\n";
2398    int stat = 0;
2399
2400    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
2401    if (!jcr->RestoreBootstrap) {
2402       return 1;
2403    }
2404    bs = fopen(jcr->RestoreBootstrap, "rb");
2405    if (!bs) {
2406       berrno be;
2407       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
2408          jcr->RestoreBootstrap, be.bstrerror());
2409       jcr->setJobStatus(JS_ErrorTerminated);
2410       goto bail_out;
2411    }
2412    sd->msglen = pm_strcpy(sd->msg, bootstrap);
2413    sd->send();
2414    while (fgets(buf, sizeof(buf), bs)) {
2415       sd->msglen = Mmsg(sd->msg, "%s", buf);
2416       sd->send();
2417    }
2418    sd->signal(BNET_EOD);
2419    fclose(bs);
2420    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
2421       jcr->setJobStatus(JS_ErrorTerminated);
2422       goto bail_out;
2423    }
2424    stat = 1;
2425
2426 bail_out:
2427    free_bootstrap(jcr);
2428    return stat;
2429 }