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