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