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