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