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