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