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