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