]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
kes Correctly detect Ubuntu systems, and add ubuntu platform directory.
[bacula/bacula] / bacula / src / filed / job.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 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 John Walker.
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  *   Version $Id$
34  *
35  */
36
37 #include "bacula.h"
38 #include "filed.h"
39
40 #if defined(WIN32_VSS)
41 #include "vss.h"
42
43 static pthread_mutex_t vss_mutex = PTHREAD_MUTEX_INITIALIZER;
44 static int enable_vss;
45 #endif
46
47 extern CLIENT *me;                    /* our client resource */
48
49 /* Imported functions */
50 extern int status_cmd(JCR *jcr);
51 extern int qstatus_cmd(JCR *jcr);
52 extern int accurate_cmd(JCR *jcr);
53
54 /* Forward referenced functions */
55 static int backup_cmd(JCR *jcr);
56 static int bootstrap_cmd(JCR *jcr);
57 static int cancel_cmd(JCR *jcr);
58 static int setdebug_cmd(JCR *jcr);
59 static int estimate_cmd(JCR *jcr);
60 static int hello_cmd(JCR *jcr);
61 static int job_cmd(JCR *jcr);
62 static int fileset_cmd(JCR *jcr);
63 static int level_cmd(JCR *jcr);
64 static int verify_cmd(JCR *jcr);
65 static int restore_cmd(JCR *jcr);
66 static int storage_cmd(JCR *jcr);
67 static int session_cmd(JCR *jcr);
68 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
69 static void filed_free_jcr(JCR *jcr);
70 static int open_sd_read_session(JCR *jcr);
71 static int send_bootstrap_file(JCR *jcr);
72 static int runscript_cmd(JCR *jcr);
73 static int runbefore_cmd(JCR *jcr);
74 static int runafter_cmd(JCR *jcr);
75 static int runbeforenow_cmd(JCR *jcr);
76 static void set_options(findFOPTS *fo, const char *opts);
77
78
79 /* Exported functions */
80
81 struct s_cmds {
82    const char *cmd;
83    int (*func)(JCR *);
84    int monitoraccess; /* specify if monitors have access to this function */
85 };
86
87 /*
88  * The following are the recognized commands from the Director.
89  */
90 static struct s_cmds cmds[] = {
91    {"backup",       backup_cmd,    0},
92    {"cancel",       cancel_cmd,    0},
93    {"setdebug=",    setdebug_cmd,  0},
94    {"estimate",     estimate_cmd,  0},
95    {"Hello",        hello_cmd,     1},
96    {"fileset",      fileset_cmd,   0},
97    {"JobId=",       job_cmd,       0},
98    {"level = ",     level_cmd,     0},
99    {"restore",      restore_cmd,   0},
100    {"session",      session_cmd,   0},
101    {"status",       status_cmd,    1},
102    {".status",      qstatus_cmd,   1},
103    {"storage ",     storage_cmd,   0},
104    {"verify",       verify_cmd,    0},
105    {"bootstrap",    bootstrap_cmd, 0},
106    {"RunBeforeNow", runbeforenow_cmd, 0},
107    {"RunBeforeJob", runbefore_cmd, 0},
108    {"RunAfterJob",  runafter_cmd,  0},
109    {"Run",          runscript_cmd, 0},
110    {"accurate",     accurate_cmd, 0},
111    {NULL,       NULL}                  /* list terminator */
112 };
113
114 /* Commands received from director that need scanning */
115 static char jobcmd[]      = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
116 static char storaddr[]    = "storage address=%s port=%d ssl=%d";
117 static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
118 static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
119 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
120 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
121 static char verifycmd[]   = "verify level=%30s";
122 static char estimatecmd[] = "estimate listing=%d";
123 static char runbefore[]   = "RunBeforeJob %s";
124 static char runafter[]    = "RunAfterJob %s";
125 static char runscript[]   = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
126
127 /* Responses sent to Director */
128 static char errmsg[]      = "2999 Invalid command\n";
129 static char no_auth[]     = "2998 No Authorization\n";
130 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
131 static char OKinc[]       = "2000 OK include\n";
132 static char OKest[]       = "2000 OK estimate files=%u bytes=%s\n";
133 static char OKlevel[]     = "2000 OK level\n";
134 static char OKbackup[]    = "2000 OK backup\n";
135 static char OKbootstrap[] = "2000 OK bootstrap\n";
136 static char OKverify[]    = "2000 OK verify\n";
137 static char OKrestore[]   = "2000 OK restore\n";
138 static char OKsession[]   = "2000 OK session\n";
139 static char OKstore[]     = "2000 OK storage\n";
140 static char OKjob[]       = "2000 OK Job %s (%s) %s,%s,%s";
141 static char OKsetdebug[]  = "2000 OK setdebug=%d\n";
142 static char BADjob[]      = "2901 Bad Job\n";
143 static char EndJob[]      = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s"
144                             " JobBytes=%s Errors=%u VSS=%d Encrypt=%d\n";
145 static char OKRunBefore[] = "2000 OK RunBefore\n";
146 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
147 static char OKRunAfter[]  = "2000 OK RunAfter\n";
148 static char OKRunScript[] = "2000 OK RunScript\n";
149
150
151 /* Responses received from Storage Daemon */
152 static char OK_end[]       = "3000 OK end\n";
153 static char OK_close[]     = "3000 OK close Status = %d\n";
154 static char OK_open[]      = "3000 OK open ticket = %d\n";
155 static char OK_data[]      = "3000 OK data\n";
156 static char OK_append[]    = "3000 OK append data\n";
157 static char OKSDbootstrap[]= "3000 OK bootstrap\n";
158
159
160 /* Commands sent to Storage Daemon */
161 static char append_open[]  = "append open session\n";
162 static char append_data[]  = "append data %d\n";
163 static char append_end[]   = "append end session %d\n";
164 static char append_close[] = "append close session %d\n";
165 static char read_open[]    = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
166 static char read_data[]    = "read data %d\n";
167 static char read_close[]   = "read close session %d\n";
168
169 /*
170  * Accept requests from a Director
171  *
172  * NOTE! We are running as a separate thread
173  *
174  * Send output one line
175  * at a time followed by a zero length transmission.
176  *
177  * Return when the connection is terminated or there
178  * is an error.
179  *
180  * Basic task here is:
181  *   Authenticate Director (during Hello command).
182  *   Accept commands one at a time from the Director
183  *     and execute them.
184  *
185  * Concerning ClientRunBefore/After, the sequence of events
186  * is rather critical. If they are not done in the right
187  * order one can easily get FD->SD timeouts if the script
188  * runs a long time.
189  *
190  * The current sequence of events is:
191  *  1. Dir starts job with FD
192  *  2. Dir connects to SD
193  *  3. Dir connects to FD
194  *  4. FD connects to SD
195  *  5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
196  *  6. Dir sends include/exclude
197  *  7. FD sends data to SD
198  *  8. SD/FD disconnects while SD despools data and attributes (optionnal)
199  *  9. FD runs ClientRunAfterJob
200  */
201
202 void *handle_client_request(void *dirp)
203 {
204    int i;
205    bool found, quit;
206    JCR *jcr;
207    BSOCK *dir = (BSOCK *)dirp;
208
209    jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
210    jcr->dir_bsock = dir;
211    jcr->ff = init_find_files();
212    jcr->start_time = time(NULL);
213    jcr->RunScripts = New(alist(10, not_owned_by_alist));
214    jcr->last_fname = get_pool_memory(PM_FNAME);
215    jcr->last_fname[0] = 0;
216    jcr->client_name = get_memory(strlen(my_name) + 1);
217    new_plugins(jcr);                  /* instantiate plugins for this jcr */
218    pm_strcpy(jcr->client_name, my_name);
219    jcr->crypto.pki_sign = me->pki_sign;
220    jcr->crypto.pki_encrypt = me->pki_encrypt;
221    jcr->crypto.pki_keypair = me->pki_keypair;
222    jcr->crypto.pki_signers = me->pki_signers;
223    jcr->crypto.pki_recipients = me->pki_recipients;
224    dir->set_jcr(jcr);
225    enable_backup_privileges(NULL, 1 /* ignore_errors */);
226
227    /**********FIXME******* add command handler error code */
228
229    for (quit=false; !quit;) {
230
231       /* Read command */
232       if (bnet_recv(dir) < 0) {
233          break;               /* connection terminated */
234       }
235       dir->msg[dir->msglen] = 0;
236       Dmsg1(100, "<dird: %s", dir->msg);
237       found = false;
238       for (i=0; cmds[i].cmd; i++) {
239          if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
240             found = true;         /* indicate command found */
241             if (!jcr->authenticated && cmds[i].func != hello_cmd) {
242                bnet_fsend(dir, no_auth);
243                bnet_sig(dir, BNET_EOD);
244                break;
245             }
246             if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) {
247                Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
248                bnet_fsend(dir, invalid_cmd);
249                bnet_sig(dir, BNET_EOD);
250                break;
251             }
252             Dmsg1(100, "Executing %s command.\n", cmds[i].cmd);
253             if (!cmds[i].func(jcr)) {         /* do command */
254                quit = true;         /* error or fully terminated, get out */
255                Dmsg1(20, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
256             }
257             break;
258          }
259       }
260       if (!found) {              /* command not found */
261          bnet_fsend(dir, errmsg);
262          quit = true;
263          break;
264       }
265    }
266
267    /* Inform Storage daemon that we are done */
268    if (jcr->store_bsock) {
269       bnet_sig(jcr->store_bsock, BNET_TERMINATE);
270    }
271
272    /* Run the after job */
273    run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
274
275    if (jcr->JobId) {            /* send EndJob if running a job */
276       char ed1[50], ed2[50];
277       /* Send termination status back to Dir */
278       bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
279                  edit_uint64(jcr->ReadBytes, ed1),
280                  edit_uint64(jcr->JobBytes, ed2), jcr->Errors, jcr->VSS,
281                  jcr->crypto.pki_encrypt);
282       Dmsg1(110, "End FD msg: %s\n", dir->msg);
283    }
284
285    generate_daemon_event(jcr, "JobEnd");
286    generate_plugin_event(jcr, bEventJobEnd);
287
288    dequeue_messages(jcr);             /* send any queued messages */
289
290    /* Inform Director that we are done */
291    dir->signal(BNET_TERMINATE);
292
293    free_plugins(jcr);                 /* release instantiated plugins */
294
295    /* Clean up fileset */
296    FF_PKT *ff = jcr->ff;
297    findFILESET *fileset = ff->fileset;
298    if (fileset) {
299       int i, j, k;
300       /* Delete FileSet Include lists */
301       for (i=0; i<fileset->include_list.size(); i++) {
302          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
303          for (j=0; j<incexe->opts_list.size(); j++) {
304             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
305             for (k=0; k<fo->regex.size(); k++) {
306                regfree((regex_t *)fo->regex.get(k));
307             }
308             for (k=0; k<fo->regexdir.size(); k++) {
309                regfree((regex_t *)fo->regexdir.get(k));
310             }
311             for (k=0; k<fo->regexfile.size(); k++) {
312                regfree((regex_t *)fo->regexfile.get(k));
313             }
314             fo->regex.destroy();
315             fo->regexdir.destroy();
316             fo->regexfile.destroy();
317             fo->wild.destroy();
318             fo->wilddir.destroy();
319             fo->wildfile.destroy();
320             fo->wildbase.destroy();
321             fo->base.destroy();
322             fo->fstype.destroy();
323             fo->drivetype.destroy();
324          }
325          incexe->opts_list.destroy();
326          incexe->name_list.destroy();
327          incexe->plugin_list.destroy();
328       }
329       fileset->include_list.destroy();
330
331       /* Delete FileSet Exclude lists */
332       for (i=0; i<fileset->exclude_list.size(); i++) {
333          findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
334          for (j=0; j<incexe->opts_list.size(); j++) {
335             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
336             fo->regex.destroy();
337             fo->regexdir.destroy();
338             fo->regexfile.destroy();
339             fo->wild.destroy();
340             fo->wilddir.destroy();
341             fo->wildfile.destroy();
342             fo->wildbase.destroy();
343             fo->base.destroy();
344             fo->fstype.destroy();
345             fo->drivetype.destroy();
346          }
347          incexe->opts_list.destroy();
348          incexe->name_list.destroy();
349          incexe->plugin_list.destroy();
350       }
351       fileset->exclude_list.destroy();
352       free(fileset);
353    }
354    ff->fileset = NULL;
355    Dmsg0(100, "Calling term_find_files\n");
356    term_find_files(jcr->ff);
357    jcr->ff = NULL;
358    Dmsg0(100, "Done with term_find_files\n");
359    free_jcr(jcr);                     /* destroy JCR record */
360    Dmsg0(100, "Done with free_jcr\n");
361    Dsm_check(1);
362    return NULL;
363 }
364
365 /*
366  * Hello from Director he must identify himself and provide his
367  *  password.
368  */
369 static int hello_cmd(JCR *jcr)
370 {
371    Dmsg0(120, "Calling Authenticate\n");
372    if (!authenticate_director(jcr)) {
373       return 0;
374    }
375    Dmsg0(120, "OK Authenticate\n");
376    jcr->authenticated = true;
377    return 1;
378 }
379
380 /*
381  * Cancel a Job
382  */
383 static int cancel_cmd(JCR *jcr)
384 {
385    BSOCK *dir = jcr->dir_bsock;
386    char Job[MAX_NAME_LENGTH];
387    JCR *cjcr;
388
389    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
390       if (!(cjcr=get_jcr_by_full_name(Job))) {
391          dir->fsend(_("2901 Job %s not found.\n"), Job);
392       } else {
393          if (cjcr->store_bsock) {
394             cjcr->store_bsock->set_timed_out();
395             cjcr->store_bsock->set_terminated();
396             pthread_kill(cjcr->my_thread_id, TIMEOUT_SIGNAL);
397          }
398          set_jcr_job_status(cjcr, JS_Canceled);
399          free_jcr(cjcr);
400          dir->fsend(_("2001 Job %s marked to be canceled.\n"), Job);
401       }
402    } else {
403       dir->fsend(_("2902 Error scanning cancel command.\n"));
404    }
405    dir->signal(BNET_EOD);
406    return 1;
407 }
408
409
410 /*
411  * Set debug level as requested by the Director
412  *
413  */
414 static int setdebug_cmd(JCR *jcr)
415 {
416    BSOCK *dir = jcr->dir_bsock;
417    int level, trace_flag;
418
419    Dmsg1(110, "setdebug_cmd: %s", dir->msg);
420    if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace_flag) != 2 || level < 0) {
421       pm_strcpy(jcr->errmsg, dir->msg);
422       dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
423       return 0;
424    }
425    debug_level = level;
426    set_trace(trace_flag);
427    return dir->fsend(OKsetdebug, level);
428 }
429
430
431 static int estimate_cmd(JCR *jcr)
432 {
433    BSOCK *dir = jcr->dir_bsock;
434    char ed2[50];
435
436    if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
437       pm_strcpy(jcr->errmsg, dir->msg);
438       Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
439       dir->fsend(_("2992 Bad estimate command.\n"));
440       return 0;
441    }
442    make_estimate(jcr);
443    dir->fsend(OKest, jcr->num_files_examined,
444       edit_uint64_with_commas(jcr->JobBytes, ed2));
445    dir->signal(BNET_EOD);
446    return 1;
447 }
448
449 /*
450  * Get JobId and Storage Daemon Authorization key from Director
451  */
452 static int job_cmd(JCR *jcr)
453 {
454    BSOCK *dir = jcr->dir_bsock;
455    POOLMEM *sd_auth_key;
456
457    sd_auth_key = get_memory(dir->msglen);
458    if (sscanf(dir->msg, jobcmd,  &jcr->JobId, jcr->Job,
459               &jcr->VolSessionId, &jcr->VolSessionTime,
460               sd_auth_key) != 5) {
461       pm_strcpy(jcr->errmsg, dir->msg);
462       Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
463       dir->fsend(BADjob);
464       free_pool_memory(sd_auth_key);
465       return 0;
466    }
467    jcr->sd_auth_key = bstrdup(sd_auth_key);
468    free_pool_memory(sd_auth_key);
469    Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
470    Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
471    generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
472    return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
473 }
474
475 static int runbefore_cmd(JCR *jcr)
476 {
477    bool ok;
478    BSOCK *dir = jcr->dir_bsock;
479    POOLMEM *cmd = get_memory(dir->msglen+1);
480    RUNSCRIPT *script;
481
482    Dmsg1(100, "runbefore_cmd: %s", dir->msg);
483    if (sscanf(dir->msg, runbefore, cmd) != 1) {
484       pm_strcpy(jcr->errmsg, dir->msg);
485       Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
486       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
487       free_memory(cmd);
488       return 0;
489    }
490    unbash_spaces(cmd);
491
492    /* Run the command now */
493    script = new_runscript();
494    script->set_command(cmd);
495    script->when = SCRIPT_Before;
496    ok = script->run(jcr, "ClientRunBeforeJob");
497    free_runscript(script);
498
499    free_memory(cmd);
500    if (ok) {
501       dir->fsend(OKRunBefore);
502       return 1;
503    } else {
504       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
505       return 0;
506    }
507 }
508
509 static int runbeforenow_cmd(JCR *jcr)
510 {
511    BSOCK *dir = jcr->dir_bsock;
512
513    run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
514    if (job_canceled(jcr)) {
515       dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
516       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
517       return 0;
518    } else {
519       dir->fsend(OKRunBeforeNow);
520       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
521       return 1;
522    }
523 }
524
525 static int runafter_cmd(JCR *jcr)
526 {
527    BSOCK *dir = jcr->dir_bsock;
528    POOLMEM *msg = get_memory(dir->msglen+1);
529    RUNSCRIPT *cmd;
530
531    Dmsg1(100, "runafter_cmd: %s", dir->msg);
532    if (sscanf(dir->msg, runafter, msg) != 1) {
533       pm_strcpy(jcr->errmsg, dir->msg);
534       Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
535       dir->fsend(_("2905 Bad RunAfterJob command.\n"));
536       free_memory(msg);
537       return 0;
538    }
539    unbash_spaces(msg);
540
541    cmd = new_runscript();
542    cmd->set_command(msg);
543    cmd->on_success = true;
544    cmd->on_failure = false;
545    cmd->when = SCRIPT_After;
546
547    jcr->RunScripts->append(cmd);
548
549    free_pool_memory(msg);
550    return dir->fsend(OKRunAfter);
551 }
552
553 static int runscript_cmd(JCR *jcr)
554 {
555    BSOCK *dir = jcr->dir_bsock;
556    POOLMEM *msg = get_memory(dir->msglen+1);
557    int on_success, on_failure, fail_on_error;
558
559    RUNSCRIPT *cmd = new_runscript() ;
560
561    Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
562    /* Note, we cannot sscanf into bools */
563    if (sscanf(dir->msg, runscript, &on_success, 
564                                   &on_failure,
565                                   &fail_on_error,
566                                   &cmd->when,
567                                   msg) != 5) {
568       pm_strcpy(jcr->errmsg, dir->msg);
569       Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
570       dir->fsend(_("2905 Bad RunScript command.\n"));
571       free_runscript(cmd);
572       free_memory(msg);
573       return 0;
574    }
575    cmd->on_success = on_success;
576    cmd->on_failure = on_failure;
577    cmd->fail_on_error = fail_on_error;
578    unbash_spaces(msg);
579
580    cmd->set_command(msg);
581    cmd->debug();
582    jcr->RunScripts->append(cmd);
583
584    free_pool_memory(msg);
585    return dir->fsend(OKRunScript);
586 }
587
588
589 static bool init_fileset(JCR *jcr)
590 {
591    FF_PKT *ff;
592    findFILESET *fileset;
593
594    if (!jcr->ff) {
595       return false;
596    }
597    ff = jcr->ff;
598    if (ff->fileset) {
599       return false;
600    }
601    fileset = (findFILESET *)malloc(sizeof(findFILESET));
602    memset(fileset, 0, sizeof(findFILESET));
603    ff->fileset = fileset;
604    fileset->state = state_none;
605    fileset->include_list.init(1, true);
606    fileset->exclude_list.init(1, true);
607    return true;
608 }
609
610 static findFOPTS *start_options(FF_PKT *ff)
611 {
612    int state = ff->fileset->state;
613    findINCEXE *incexe = ff->fileset->incexe;
614
615    if (state != state_options) {
616       ff->fileset->state = state_options;
617       findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
618       memset(fo, 0, sizeof(findFOPTS));
619       fo->regex.init(1, true);
620       fo->regexdir.init(1, true);
621       fo->regexfile.init(1, true);
622       fo->wild.init(1, true);
623       fo->wilddir.init(1, true);
624       fo->wildfile.init(1, true);
625       fo->wildbase.init(1, true);
626       fo->base.init(1, true);
627       fo->fstype.init(1, true);
628       fo->drivetype.init(1, true);
629       incexe->current_opts = fo;
630       incexe->opts_list.append(fo);
631    }
632    return incexe->current_opts;
633
634 }
635
636 /*
637  * Add fname to include/exclude fileset list. First check for
638  * | and < and if necessary perform command.
639  */
640 static void add_file_to_fileset(JCR *jcr, const char *fname, findFILESET *fileset,
641                                 bool is_file)
642 {
643    char *p;
644    BPIPE *bpipe;
645    POOLMEM *fn;
646    FILE *ffd;
647    char buf[1000];
648    int ch;
649    int stat;
650
651    p = (char *)fname;
652    ch = (uint8_t)*p;
653    switch (ch) {
654    case '|':
655       p++;                            /* skip over | */
656       fn = get_pool_memory(PM_FNAME);
657       fn = edit_job_codes(jcr, fn, p, "");
658       bpipe = open_bpipe(fn, 0, "r");
659       if (!bpipe) {
660          berrno be;
661          Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
662             p, be.bstrerror());
663          free_pool_memory(fn);
664          return;
665       }
666       free_pool_memory(fn);
667       while (fgets(buf, sizeof(buf), bpipe->rfd)) {
668          strip_trailing_junk(buf);
669          if (is_file) {
670             fileset->incexe->name_list.append(new_dlistString(buf));
671          } else {
672             fileset->incexe->plugin_list.append(new_dlistString(buf));
673          }
674       }
675       if ((stat=close_bpipe(bpipe)) != 0) {
676          berrno be;
677          Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
678             p, be.code(stat), be.bstrerror(stat));
679          return;
680       }
681       break;
682    case '<':
683       Dmsg0(100, "Doing < include on client.\n");
684       p++;                      /* skip over < */
685       if ((ffd = fopen(p, "rb")) == NULL) {
686          berrno be;
687          Jmsg(jcr, M_FATAL, 0, _("Cannot open FileSet input file: %s. ERR=%s\n"),
688             p, be.bstrerror());
689          return;
690       }
691       while (fgets(buf, sizeof(buf), ffd)) {
692          strip_trailing_junk(buf);
693          Dmsg1(100, "%s\n", buf);
694          if (is_file) {
695             fileset->incexe->name_list.append(new_dlistString(buf));
696          } else {
697             fileset->incexe->plugin_list.append(new_dlistString(buf));
698          }
699       }
700       fclose(ffd);
701       break;
702    default:
703       if (is_file) {
704          fileset->incexe->name_list.append(new_dlistString(fname));
705       } else {
706          fileset->incexe->plugin_list.append(new_dlistString(fname));
707       }
708       break;
709    }
710 }
711
712
713 static void add_fileset(JCR *jcr, const char *item)
714 {
715    FF_PKT *ff = jcr->ff;
716    findFILESET *fileset = ff->fileset;
717    int state = fileset->state;
718    findFOPTS *current_opts;
719
720    /* Get code, optional subcode, and position item past the dividing space */
721    Dmsg1(100, "%s\n", item);
722    int code = item[0];
723    if (code != '\0') {
724       ++item;
725    }
726    int subcode = ' ';               /* A space is always a valid subcode */
727    if (item[0] != '\0' && item[0] != ' ') {
728       subcode = item[0];
729       ++item;
730    }
731    if (*item == ' ') {
732       ++item;
733    }
734
735    /* Skip all lines we receive after an error */
736    if (state == state_error) {
737       Dmsg0(100, "State=error return\n");
738       return;
739    }
740
741    /*
742     * The switch tests the code for validity.
743     * The subcode is always good if it is a space, otherwise we must confirm.
744     * We set state to state_error first assuming the subcode is invalid,
745     * requiring state to be set in cases below that handle subcodes.
746     */
747    if (subcode != ' ') {
748       state = state_error;
749       Dmsg0(100, "Set state=error\n"); 
750    }
751    switch (code) {
752    case 'I':
753       /* New include */
754       fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
755       memset(fileset->incexe, 0, sizeof(findINCEXE));
756       fileset->incexe->opts_list.init(1, true);
757       fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
758       fileset->incexe->plugin_list.init();
759       fileset->include_list.append(fileset->incexe);
760       break;
761    case 'E':
762       /* New exclude */
763       fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
764       memset(fileset->incexe, 0, sizeof(findINCEXE));
765       fileset->incexe->opts_list.init(1, true);
766       fileset->incexe->name_list.init();
767       fileset->incexe->plugin_list.init();
768       fileset->exclude_list.append(fileset->incexe);
769       break;
770    case 'N':
771       state = state_none;
772       break;
773    case 'F':
774       /* File item to include or exclude list */
775       state = state_include;
776       add_file_to_fileset(jcr, item, fileset, true);
777       break;
778    case 'P':
779       /* Plugin item to include list */
780       state = state_include;
781       add_file_to_fileset(jcr, item, fileset, false);
782       break;
783    case 'R':
784       current_opts = start_options(ff);
785       regex_t *preg;
786       int rc;
787       char prbuf[500];
788       preg = (regex_t *)malloc(sizeof(regex_t));
789       if (current_opts->flags & FO_IGNORECASE) {
790          rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
791       } else {
792          rc = regcomp(preg, item, REG_EXTENDED);
793       }
794       if (rc != 0) {
795          regerror(rc, preg, prbuf, sizeof(prbuf));
796          regfree(preg);
797          free(preg);
798          Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
799          state = state_error;
800          break;
801       }
802       state = state_options;
803       if (subcode == ' ') {
804          current_opts->regex.append(preg);
805       } else if (subcode == 'D') {
806          current_opts->regexdir.append(preg);
807       } else if (subcode == 'F') {
808          current_opts->regexfile.append(preg);
809       } else {
810          state = state_error;
811       }
812       break;
813    case 'B':
814       current_opts = start_options(ff);
815       current_opts->base.append(bstrdup(item));
816       state = state_options;
817       break;
818    case 'X':
819       current_opts = start_options(ff);
820       state = state_options;
821       if (subcode == ' ') {
822          current_opts->fstype.append(bstrdup(item));
823       } else if (subcode == 'D') {
824          current_opts->drivetype.append(bstrdup(item));
825       } else {
826          state = state_error;
827       }
828       break;
829    case 'W':
830       current_opts = start_options(ff);
831       state = state_options;
832       if (subcode == ' ') {
833          current_opts->wild.append(bstrdup(item));
834       } else if (subcode == 'D') {
835          current_opts->wilddir.append(bstrdup(item));
836       } else if (subcode == 'F') {
837          current_opts->wildfile.append(bstrdup(item));
838       } else if (subcode == 'B') {
839          current_opts->wildbase.append(bstrdup(item));
840       } else {
841          state = state_error;
842       }
843       break;
844    case 'O':
845       current_opts = start_options(ff);
846       set_options(current_opts, item);
847       state = state_options;
848       break;
849    case 'D':
850       current_opts = start_options(ff);
851 //    current_opts->reader = bstrdup(item);
852       state = state_options;
853       break;
854    case 'T':
855       current_opts = start_options(ff);
856 //    current_opts->writer = bstrdup(item);
857       state = state_options;
858       break;
859    default:
860       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
861       state = state_error;
862       break;
863    }
864    ff->fileset->state = state;
865 }
866
867 static bool term_fileset(JCR *jcr)
868 {
869    FF_PKT *ff = jcr->ff;
870
871 #ifdef xxx_DEBUG_CODE
872    findFILESET *fileset = ff->fileset;
873    int i, j, k;
874
875    for (i=0; i<fileset->include_list.size(); i++) {
876       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
877       Dmsg0(400, "I\n");
878       for (j=0; j<incexe->opts_list.size(); j++) {
879          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
880          for (k=0; k<fo->regex.size(); k++) {
881             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
882          }
883          for (k=0; k<fo->regexdir.size(); k++) {
884             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
885          }
886          for (k=0; k<fo->regexfile.size(); k++) {
887             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
888          }
889          for (k=0; k<fo->wild.size(); k++) {
890             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
891          }
892          for (k=0; k<fo->wilddir.size(); k++) {
893             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
894          }
895          for (k=0; k<fo->wildfile.size(); k++) {
896             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
897          }
898          for (k=0; k<fo->wildbase.size(); k++) {
899             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
900          }
901          for (k=0; k<fo->base.size(); k++) {
902             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
903          }
904          for (k=0; k<fo->fstype.size(); k++) {
905             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
906          }
907          for (k=0; k<fo->drivetype.size(); k++) {
908             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
909          }
910       }
911       dlistString *node;
912       foreach_dlist(node, &incexe->name_list) {
913          Dmsg1(400, "F %s\n", node->c_str());
914       }
915       foreach_dlist(node, &incexe->plugin_list) {
916          Dmsg1(400, "P %s\n", node->c_str());
917       }
918    }
919    for (i=0; i<fileset->exclude_list.size(); i++) {
920       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
921       Dmsg0(400, "E\n");
922       for (j=0; j<incexe->opts_list.size(); j++) {
923          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
924          for (k=0; k<fo->regex.size(); k++) {
925             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
926          }
927          for (k=0; k<fo->regexdir.size(); k++) {
928             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
929          }
930          for (k=0; k<fo->regexfile.size(); k++) {
931             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
932          }
933          for (k=0; k<fo->wild.size(); k++) {
934             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
935          }
936          for (k=0; k<fo->wilddir.size(); k++) {
937             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
938          }
939          for (k=0; k<fo->wildfile.size(); k++) {
940             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
941          }
942          for (k=0; k<fo->wildbase.size(); k++) {
943             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
944          }
945          for (k=0; k<fo->base.size(); k++) {
946             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
947          }
948          for (k=0; k<fo->fstype.size(); k++) {
949             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
950          }
951          for (k=0; k<fo->drivetype.size(); k++) {
952             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
953          }
954       }
955       dlistString *node;
956       foreach_dlist(node, incexe->name_list) {
957          Dmsg1(400, "F %s\n", node->c_str());
958       }
959       foreach_dlist(node, &incexe->plugin_list) {
960          Dmsg1(400, "P %s\n", node->c_str());
961       }
962    }
963 #endif
964    return ff->fileset->state != state_error;
965 }
966
967
968 /*
969  * As an optimization, we should do this during
970  *  "compile" time in filed/job.c, and keep only a bit mask
971  *  and the Verify options.
972  */
973 static void set_options(findFOPTS *fo, const char *opts)
974 {
975    int j;
976    const char *p;
977    char strip[100];
978
979 // Commented out as it is not backward compatible - KES
980 #ifdef HAVE_WIN32
981 //   fo->flags |= FO_IGNORECASE; /* always ignorecase under windows */
982 #endif
983
984    for (p=opts; *p; p++) {
985       switch (*p) {
986       case 'a':                 /* alway replace */
987       case '0':                 /* no option */
988          break;
989       case 'e':
990          fo->flags |= FO_EXCLUDE;
991          break;
992       case 'f':
993          fo->flags |= FO_MULTIFS;
994          break;
995       case 'h':                 /* no recursion */
996          fo->flags |= FO_NO_RECURSION;
997          break;
998       case 'H':                 /* no hard link handling */
999          fo->flags |= FO_NO_HARDLINK;
1000          break;
1001       case 'i':
1002          fo->flags |= FO_IGNORECASE;
1003          break;
1004       case 'M':                 /* MD5 */
1005          fo->flags |= FO_MD5;
1006          break;
1007       case 'n':
1008          fo->flags |= FO_NOREPLACE;
1009          break;
1010       case 'p':                 /* use portable data format */
1011          fo->flags |= FO_PORTABLE;
1012          break;
1013       case 'R':                 /* Resource forks and Finder Info */
1014          fo->flags |= FO_HFSPLUS;
1015       case 'r':                 /* read fifo */
1016          fo->flags |= FO_READFIFO;
1017          break;
1018       case 'S':
1019          switch(*(p + 1)) {
1020          case '1':
1021             fo->flags |= FO_SHA1;
1022             p++;
1023             break;
1024 #ifdef HAVE_SHA2
1025          case '2':
1026             fo->flags |= FO_SHA256;
1027             p++;
1028             break;
1029          case '3':
1030             fo->flags |= FO_SHA512;
1031             p++;
1032             break;
1033 #endif
1034          default:
1035             /*
1036              * If 2 or 3 is seen here, SHA2 is not configured, so
1037              *  eat the option, and drop back to SHA-1.
1038              */
1039             if (p[1] == '2' || p[1] == '3') {
1040                p++;
1041             }
1042             fo->flags |= FO_SHA1;
1043             break;
1044          }
1045          break;
1046       case 's':
1047          fo->flags |= FO_SPARSE;
1048          break;
1049       case 'm':
1050          fo->flags |= FO_MTIMEONLY;
1051          break;
1052       case 'k':
1053          fo->flags |= FO_KEEPATIME;
1054          break;
1055       case 'A':
1056          fo->flags |= FO_ACL;
1057          break;
1058       case 'V':                  /* verify options */
1059          /* Copy Verify Options */
1060          for (j=0; *p && *p != ':'; p++) {
1061             fo->VerifyOpts[j] = *p;
1062             if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1063                j++;
1064             }
1065          }
1066          fo->VerifyOpts[j] = 0;
1067          break;
1068       case 'C':                  /* accurate options */
1069          /* Copy Accurate Options */
1070          for (j=0; *p && *p != ':'; p++) {
1071             fo->AccurateOpts[j] = *p;
1072             if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1073                j++;
1074             }
1075          }
1076          fo->AccurateOpts[j] = 0;
1077          break;
1078       case 'P':                  /* strip path */
1079          /* Get integer */
1080          p++;                    /* skip P */
1081          for (j=0; *p && *p != ':'; p++) {
1082             strip[j] = *p;
1083             if (j < (int)sizeof(strip) - 1) {
1084                j++;
1085             }
1086          }
1087          strip[j] = 0;
1088          fo->strip_path = atoi(strip);
1089          fo->flags |= FO_STRIPPATH;
1090          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1091          break;
1092       case 'w':
1093          fo->flags |= FO_IF_NEWER;
1094          break;
1095       case 'W':
1096          fo->flags |= FO_ENHANCEDWILD;
1097          break;
1098       case 'Z':                 /* gzip compression */
1099          fo->flags |= FO_GZIP;
1100          fo->GZIP_level = *++p - '0';
1101          break;
1102       case 'K':
1103          fo->flags |= FO_NOATIME;
1104          break;
1105       case 'c':
1106          fo->flags |= FO_CHKCHANGES;
1107          break;
1108       case 'N':
1109          fo->flags |= FO_HONOR_NODUMP;
1110          break;
1111       default:
1112          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1113          break;
1114       }
1115    }
1116 }
1117
1118
1119 /*
1120  * Director is passing his Fileset
1121  */
1122 static int fileset_cmd(JCR *jcr)
1123 {
1124    BSOCK *dir = jcr->dir_bsock;
1125
1126 #if defined(WIN32_VSS)
1127    int vss = 0;
1128
1129    sscanf(dir->msg, "fileset vss=%d", &vss);
1130    enable_vss = vss;
1131 #endif
1132
1133    if (!init_fileset(jcr)) {
1134       return 0;
1135    }
1136    while (dir->recv() >= 0) {
1137       strip_trailing_junk(dir->msg);
1138       Dmsg1(500, "Fileset: %s\n", dir->msg);
1139       add_fileset(jcr, dir->msg);
1140    }
1141    if (!term_fileset(jcr)) {
1142       return 0;
1143    }
1144    return dir->fsend(OKinc);
1145 }
1146
1147 static void free_bootstrap(JCR *jcr)
1148 {
1149    if (jcr->RestoreBootstrap) {
1150       unlink(jcr->RestoreBootstrap);
1151       free_pool_memory(jcr->RestoreBootstrap);
1152       jcr->RestoreBootstrap = NULL;
1153    }
1154 }
1155
1156
1157 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1158 static uint32_t bsr_uniq = 0;
1159
1160 /* 
1161  * The Director sends us the bootstrap file, which
1162  *   we will in turn pass to the SD.
1163  */
1164 static int bootstrap_cmd(JCR *jcr)
1165 {
1166    BSOCK *dir = jcr->dir_bsock;
1167    POOLMEM *fname = get_pool_memory(PM_FNAME);
1168    FILE *bs;
1169
1170    free_bootstrap(jcr);
1171    P(bsr_mutex);
1172    bsr_uniq++;
1173    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1174       jcr->Job, bsr_uniq);
1175    V(bsr_mutex);
1176    Dmsg1(400, "bootstrap=%s\n", fname);
1177    jcr->RestoreBootstrap = fname;
1178    bs = fopen(fname, "a+b");           /* create file */
1179    if (!bs) {
1180       berrno be;
1181       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1182          jcr->RestoreBootstrap, be.bstrerror());
1183       /*
1184        * Suck up what he is sending to us so that he will then
1185        *   read our error message.
1186        */
1187       while (dir->recv() >= 0)
1188         {  }
1189       free_bootstrap(jcr);
1190       set_jcr_job_status(jcr, JS_ErrorTerminated);
1191       return 0;
1192    }
1193
1194    while (dir->recv() >= 0) {
1195        Dmsg1(200, "filed<dird: bootstrap file %s\n", dir->msg);
1196        fputs(dir->msg, bs);
1197    }
1198    fclose(bs);
1199    /*
1200     * Note, do not free the bootstrap yet -- it needs to be 
1201     *  sent to the SD 
1202     */
1203    return dir->fsend(OKbootstrap);
1204 }
1205
1206
1207 /*
1208  * Get backup level from Director
1209  *
1210  */
1211 static int level_cmd(JCR *jcr)
1212 {
1213    BSOCK *dir = jcr->dir_bsock;
1214    POOLMEM *level, *buf = NULL;
1215    int mtime_only;
1216
1217    level = get_memory(dir->msglen+1);
1218    Dmsg1(110, "level_cmd: %s", dir->msg);
1219    if (strstr(dir->msg, "accurate")) {
1220       jcr->accurate = true;
1221    }
1222    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1223       goto bail_out;
1224    }
1225    /* Base backup requested? */
1226    if (strcmp(level, "base") == 0) {
1227       jcr->JobLevel = L_BASE;
1228    /* Full backup requested? */
1229    } else if (strcmp(level, "full") == 0) {
1230       jcr->JobLevel = L_FULL;
1231    } else if (strstr(level, "differential")) {
1232       jcr->JobLevel = L_DIFFERENTIAL;
1233       free_memory(level);
1234       return 1;
1235    } else if (strstr(level, "incremental")) {
1236       jcr->JobLevel = L_INCREMENTAL;
1237       free_memory(level);
1238       return 1;
1239    /*
1240     * We get his UTC since time, then sync the clocks and correct it
1241     *   to agree with our clock.
1242     */
1243    } else if (strcmp(level, "since_utime") == 0) {
1244       buf = get_memory(dir->msglen+1);
1245       utime_t since_time, adj;
1246       btime_t his_time, bt_start, rt=0, bt_adj=0;
1247       if (jcr->JobLevel == L_NONE) {
1248          jcr->JobLevel = L_SINCE;     /* if no other job level set, do it now */
1249       }
1250       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1251                  buf, &mtime_only) != 2) {
1252          goto bail_out;
1253       }
1254       since_time = str_to_uint64(buf);  /* this is the since time */
1255       Dmsg1(100, "since_time=%d\n", (int)since_time);
1256       char ed1[50], ed2[50];
1257       /*
1258        * Sync clocks by polling him for the time. We take
1259        *   10 samples of his time throwing out the first two.
1260        */
1261       for (int i=0; i<10; i++) {
1262          bt_start = get_current_btime();
1263          dir->signal(BNET_BTIME);     /* poll for time */
1264          if (dir->recv() <= 0) {      /* get response */
1265             goto bail_out;
1266          }
1267          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1268             goto bail_out;
1269          }
1270          if (i < 2) {                 /* toss first two results */
1271             continue;
1272          }
1273          his_time = str_to_uint64(buf);
1274          rt = get_current_btime() - bt_start; /* compute round trip time */
1275          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1276                edit_uint64(bt_start, ed2));
1277          bt_adj +=  bt_start - his_time - rt/2;
1278          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1279       }
1280
1281       bt_adj = bt_adj / 8;            /* compute average time */
1282       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1283       adj = btime_to_utime(bt_adj);
1284       since_time += adj;              /* adjust for clock difference */
1285       /* Don't notify if time within 3 seconds */
1286       if (adj > 3 || adj < -3) {
1287          int type;
1288          if (adj > 600 || adj < -600) {
1289             type = M_WARNING;
1290          } else {
1291             type = M_INFO;
1292          }
1293          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %d seconds, FD automatically compensating.\n"), adj);
1294       }
1295       dir->signal(BNET_EOD);
1296
1297       Dmsg2(100, "adj = %d since_time=%d\n", (int)adj, (int)since_time);
1298       jcr->incremental = 1;           /* set incremental or decremental backup */
1299       jcr->mtime = (time_t)since_time; /* set since time */
1300       generate_plugin_event(jcr, bEventSince, (void *)jcr->mtime);
1301    } else {
1302       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1303       free_memory(level);
1304       return 0;
1305    }
1306    free_memory(level);
1307    if (buf) {
1308       free_memory(buf);
1309    }
1310    generate_plugin_event(jcr, bEventLevel, (void *)jcr->JobLevel);
1311    return dir->fsend(OKlevel);
1312
1313 bail_out:
1314    pm_strcpy(jcr->errmsg, dir->msg);
1315    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1316    free_memory(level);
1317    if (buf) {
1318       free_memory(buf);
1319    }
1320    return 0;
1321 }
1322
1323 /*
1324  * Get session parameters from Director -- this is for a Restore command
1325  */
1326 static int session_cmd(JCR *jcr)
1327 {
1328    BSOCK *dir = jcr->dir_bsock;
1329
1330    Dmsg1(100, "SessionCmd: %s", dir->msg);
1331    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1332               &jcr->VolSessionId, &jcr->VolSessionTime,
1333               &jcr->StartFile, &jcr->EndFile,
1334               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1335       pm_strcpy(jcr->errmsg, dir->msg);
1336       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1337       return 0;
1338    }
1339
1340    return bnet_fsend(dir, OKsession);
1341 }
1342
1343 /*
1344  * Get address of storage daemon from Director
1345  *
1346  */
1347 static int storage_cmd(JCR *jcr)
1348 {
1349    int stored_port;                /* storage daemon port */
1350    int enable_ssl;                 /* enable ssl to sd */
1351    BSOCK *dir = jcr->dir_bsock;
1352    BSOCK *sd;                         /* storage daemon bsock */
1353
1354    Dmsg1(100, "StorageCmd: %s", dir->msg);
1355    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, &enable_ssl) != 3) {
1356       pm_strcpy(jcr->errmsg, dir->msg);
1357       Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1358       return 0;
1359    }
1360    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, enable_ssl);
1361    /* Open command communications with Storage daemon */
1362    /* Try to connect for 1 hour at 10 second intervals */
1363    sd = bnet_connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1364                       _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1);
1365    if (sd == NULL) {
1366       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1367           jcr->stored_addr, stored_port);
1368       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1369           jcr->stored_addr, stored_port);
1370       return 0;
1371    }
1372    Dmsg0(110, "Connection OK to SD.\n");
1373
1374    jcr->store_bsock = sd;
1375
1376    sd->fsend("Hello Start Job %s\n", jcr->Job);
1377    if (!authenticate_storagedaemon(jcr)) {
1378       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1379       return 0;
1380    }
1381    Dmsg0(110, "Authenticated with SD.\n");
1382
1383    /* Send OK to Director */
1384    return dir->fsend(OKstore);
1385 }
1386
1387
1388 /*
1389  * Do a backup.
1390  */
1391 static int backup_cmd(JCR *jcr)
1392 {
1393    BSOCK *dir = jcr->dir_bsock;
1394    BSOCK *sd = jcr->store_bsock;
1395    int ok = 0;
1396    int SDJobStatus;
1397
1398 #if defined(WIN32_VSS)
1399    // capture state here, if client is backed up by multiple directors
1400    // and one enables vss and the other does not then enable_vss can change
1401    // between here and where its evaluated after the job completes.
1402    jcr->VSS = g_pVSSClient && enable_vss;
1403    if (jcr->VSS) {
1404       /* Run only one at a time */
1405       P(vss_mutex);
1406    }
1407 #endif
1408
1409    set_jcr_job_status(jcr, JS_Blocked);
1410    jcr->JobType = JT_BACKUP;
1411    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1412
1413    if (sd == NULL) {
1414       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1415       goto cleanup;
1416    }
1417
1418    dir->fsend(OKbackup);
1419    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1420
1421    /*
1422     * Send Append Open Session to Storage daemon
1423     */
1424    sd->fsend(append_open);
1425    Dmsg1(110, ">stored: %s", sd->msg);
1426    /*
1427     * Expect to receive back the Ticket number
1428     */
1429    if (bget_msg(sd) >= 0) {
1430       Dmsg1(110, "<stored: %s", sd->msg);
1431       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1432          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1433          goto cleanup;
1434       }
1435       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1436    } else {
1437       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1438       goto cleanup;
1439    }
1440
1441    /*
1442     * Send Append data command to Storage daemon
1443     */
1444    sd->fsend(append_data, jcr->Ticket);
1445    Dmsg1(110, ">stored: %s", sd->msg);
1446
1447    /*
1448     * Expect to get OK data
1449     */
1450    Dmsg1(110, "<stored: %s", sd->msg);
1451    if (!response(jcr, sd, OK_data, "Append Data")) {
1452       goto cleanup;
1453    }
1454    
1455    generate_daemon_event(jcr, "JobStart");
1456    generate_plugin_event(jcr, bEventStartBackupJob);
1457
1458 #if defined(WIN32_VSS)
1459    /* START VSS ON WIN32 */
1460    if (jcr->VSS) {      
1461       if (g_pVSSClient->InitializeForBackup()) {   
1462         /* tell vss which drives to snapshot */   
1463         char szWinDriveLetters[27];   
1464         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1465             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1466             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1467                Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed.\n"));
1468                jcr->Errors++;
1469             } else {
1470                /* tell user if snapshot creation of a specific drive failed */
1471                int i;
1472                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1473                   if (islower(szWinDriveLetters[i])) {
1474                      Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed. VSS support is disabled on this drive.\n"), szWinDriveLetters[i]);
1475                      jcr->Errors++;
1476                   }
1477                }
1478                /* inform user about writer states */
1479                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++)                
1480                   if (g_pVSSClient->GetWriterState(i) < 1) {
1481                      Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1482                      jcr->Errors++;
1483                   }                            
1484             }
1485         } else {
1486             Jmsg(jcr, M_INFO, 0, _("No drive letters found for generating VSS snapshots.\n"));
1487         }
1488       } else {
1489          berrno be;
1490          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
1491       } 
1492       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
1493    }
1494 #endif
1495
1496    /*
1497     * Send Files to Storage daemon
1498     */
1499    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1500    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1501       set_jcr_job_status(jcr, JS_ErrorTerminated);
1502       bnet_suppress_error_messages(sd, 1);
1503       bget_msg(sd);                   /* Read final response from append_data */
1504       Dmsg0(110, "Error in blast_data.\n");
1505    } else {
1506       set_jcr_job_status(jcr, JS_Terminated);
1507
1508       if (jcr->JobStatus != JS_Terminated) {
1509          bnet_suppress_error_messages(sd, 1);
1510          goto cleanup;                /* bail out now */
1511       }
1512       /*
1513        * Expect to get response to append_data from Storage daemon
1514        */
1515       if (!response(jcr, sd, OK_append, "Append Data")) {
1516          set_jcr_job_status(jcr, JS_ErrorTerminated);
1517          goto cleanup;
1518       }
1519
1520       /*
1521        * Send Append End Data to Storage daemon
1522        */
1523       sd->fsend(append_end, jcr->Ticket);
1524       /* Get end OK */
1525       if (!response(jcr, sd, OK_end, "Append End")) {
1526          set_jcr_job_status(jcr, JS_ErrorTerminated);
1527          goto cleanup;
1528       }
1529
1530       /*
1531        * Send Append Close to Storage daemon
1532        */
1533       sd->fsend(append_close, jcr->Ticket);
1534       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1535          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1536             ok = 1;
1537             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1538          }
1539       }
1540       if (!ok) {
1541          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1542          goto cleanup;
1543       }
1544       if (SDJobStatus != JS_Terminated) {
1545          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1546             SDJobStatus);
1547       }
1548    }
1549
1550 cleanup:
1551 #if defined(WIN32_VSS)
1552    /* STOP VSS ON WIN32 */
1553    /* tell vss to close the backup session */
1554    if (jcr->VSS) {
1555       if (g_pVSSClient->CloseBackup()) {             
1556          /* inform user about writer states */
1557          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1558             int msg_type = M_INFO;
1559             if (g_pVSSClient->GetWriterState(i) < 1) {
1560                msg_type = M_WARNING;
1561                jcr->Errors++;
1562             }
1563             Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1564          }
1565       }
1566       V(vss_mutex);
1567    }
1568 #endif
1569
1570    generate_plugin_event(jcr, bEventEndBackupJob);
1571    return 0;                          /* return and stop command loop */
1572 }
1573
1574 /*
1575  * Do a Verify for Director
1576  *
1577  */
1578 static int verify_cmd(JCR *jcr)
1579 {
1580    BSOCK *dir = jcr->dir_bsock;
1581    BSOCK *sd  = jcr->store_bsock;
1582    char level[100];
1583
1584    jcr->JobType = JT_VERIFY;
1585    if (sscanf(dir->msg, verifycmd, level) != 1) {
1586       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
1587       return 0;
1588    }
1589
1590    if (strcasecmp(level, "init") == 0) {
1591       jcr->JobLevel = L_VERIFY_INIT;
1592    } else if (strcasecmp(level, "catalog") == 0){
1593       jcr->JobLevel = L_VERIFY_CATALOG;
1594    } else if (strcasecmp(level, "volume") == 0){
1595       jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
1596    } else if (strcasecmp(level, "data") == 0){
1597       jcr->JobLevel = L_VERIFY_DATA;
1598    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1599       jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
1600    } else {
1601       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
1602       return 0;
1603    }
1604
1605    dir->fsend(OKverify);
1606
1607    generate_daemon_event(jcr, "JobStart");
1608    generate_plugin_event(jcr, bEventLevel, (void *)jcr->JobLevel);
1609    generate_plugin_event(jcr, bEventStartVerifyJob);
1610
1611    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1612
1613    switch (jcr->JobLevel) {
1614    case L_VERIFY_INIT:
1615    case L_VERIFY_CATALOG:
1616       do_verify(jcr);
1617       break;
1618    case L_VERIFY_VOLUME_TO_CATALOG:
1619       if (!open_sd_read_session(jcr)) {
1620          return 0;
1621       }
1622       start_dir_heartbeat(jcr);
1623       do_verify_volume(jcr);
1624       stop_dir_heartbeat(jcr);
1625       /*
1626        * Send Close session command to Storage daemon
1627        */
1628       sd->fsend(read_close, jcr->Ticket);
1629       Dmsg1(130, "bfiled>stored: %s", sd->msg);
1630
1631       /* ****FIXME**** check response */
1632       bget_msg(sd);                      /* get OK */
1633
1634       /* Inform Storage daemon that we are done */
1635       sd->signal(BNET_TERMINATE);
1636
1637       break;
1638    case L_VERIFY_DISK_TO_CATALOG:
1639       do_verify(jcr);
1640       break;
1641    default:
1642       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
1643       return 0;
1644    }
1645
1646    dir->signal(BNET_EOD);
1647    generate_plugin_event(jcr, bEventEndVerifyJob);
1648    return 0;                          /* return and terminate command loop */
1649 }
1650
1651 /*
1652  * Do a Restore for Director
1653  *
1654  */
1655 static int restore_cmd(JCR *jcr)
1656 {
1657    BSOCK *dir = jcr->dir_bsock;
1658    BSOCK *sd = jcr->store_bsock;
1659    POOLMEM *args;
1660    bool use_regexwhere=false;
1661    int prefix_links;
1662    char replace;
1663
1664    /*
1665     * Scan WHERE (base directory for restore) from command
1666     */
1667    Dmsg0(150, "restore command\n");
1668    /* Pickup where string */
1669    args = get_memory(dir->msglen+1);
1670    *args = 0;
1671
1672    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
1673       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
1674          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
1675             pm_strcpy(jcr->errmsg, dir->msg);
1676             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
1677             return 0;
1678          }
1679          *args = 0;
1680       }
1681       use_regexwhere = true;
1682    }
1683    /* Turn / into nothing */
1684    if (IsPathSeparator(args[0]) && args[1] == '\0') {
1685       args[0] = '\0';
1686    }
1687
1688    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
1689    unbash_spaces(args);
1690
1691    if (use_regexwhere) {
1692       jcr->where_bregexp = get_bregexps(args);
1693       if (!jcr->where_bregexp) {
1694          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
1695          free_pool_memory(args);
1696          return 0;
1697       }
1698    } else {
1699       jcr->where = bstrdup(args);
1700    }
1701
1702    free_pool_memory(args);
1703    jcr->replace = replace;
1704    jcr->prefix_links = prefix_links;
1705
1706    dir->fsend(OKrestore);
1707    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1708
1709    jcr->JobType = JT_RESTORE;
1710
1711    set_jcr_job_status(jcr, JS_Blocked);
1712
1713    if (!open_sd_read_session(jcr)) {
1714       set_jcr_job_status(jcr, JS_ErrorTerminated);
1715       goto bail_out;
1716    }
1717
1718    set_jcr_job_status(jcr, JS_Running);
1719
1720    /*
1721     * Do restore of files and data
1722     */
1723    start_dir_heartbeat(jcr);
1724    generate_daemon_event(jcr, "JobStart");
1725    generate_plugin_event(jcr, bEventStartRestoreJob);
1726    do_restore(jcr);
1727    stop_dir_heartbeat(jcr);
1728
1729    set_jcr_job_status(jcr, JS_Terminated);
1730    if (jcr->JobStatus != JS_Terminated) {
1731       bnet_suppress_error_messages(sd, 1);
1732    }
1733
1734    /*
1735     * Send Close session command to Storage daemon
1736     */
1737    sd->fsend(read_close, jcr->Ticket);
1738    Dmsg1(130, "bfiled>stored: %s", sd->msg);
1739
1740    bget_msg(sd);                      /* get OK */
1741
1742    /* Inform Storage daemon that we are done */
1743    sd->signal(BNET_TERMINATE);
1744
1745 bail_out:
1746
1747    if (jcr->Errors) {
1748       set_jcr_job_status(jcr, JS_ErrorTerminated);
1749    }
1750
1751    Dmsg0(130, "Done in job.c\n");
1752    generate_plugin_event(jcr, bEventEndRestoreJob);
1753    return 0;                          /* return and terminate command loop */
1754 }
1755
1756 static int open_sd_read_session(JCR *jcr)
1757 {
1758    BSOCK *sd = jcr->store_bsock;
1759
1760    if (!sd) {
1761       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
1762       return 0;
1763    }
1764    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
1765       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
1766    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
1767    /*
1768     * Open Read Session with Storage daemon
1769     */
1770    bnet_fsend(sd, read_open, "DummyVolume",
1771       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
1772       jcr->StartBlock, jcr->EndBlock);
1773    Dmsg1(110, ">stored: %s", sd->msg);
1774
1775    /*
1776     * Get ticket number
1777     */
1778    if (bget_msg(sd) >= 0) {
1779       Dmsg1(110, "bfiled<stored: %s", sd->msg);
1780       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1781          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
1782          return 0;
1783       }
1784       Dmsg1(110, "bfiled: got Ticket=%d\n", jcr->Ticket);
1785    } else {
1786       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
1787       return 0;
1788    }
1789
1790    if (!send_bootstrap_file(jcr)) {
1791       return 0;
1792    }
1793
1794    /*
1795     * Start read of data with Storage daemon
1796     */
1797    bnet_fsend(sd, read_data, jcr->Ticket);
1798    Dmsg1(110, ">stored: %s", sd->msg);
1799
1800    /*
1801     * Get OK data
1802     */
1803    if (!response(jcr, sd, OK_data, "Read Data")) {
1804       return 0;
1805    }
1806    return 1;
1807 }
1808
1809 /*
1810  * Destroy the Job Control Record and associated
1811  * resources (sockets).
1812  */
1813 static void filed_free_jcr(JCR *jcr)
1814 {
1815    if (jcr->store_bsock) {
1816       bnet_close(jcr->store_bsock);
1817    }
1818    free_bootstrap(jcr);
1819    if (jcr->last_fname) {
1820       free_pool_memory(jcr->last_fname);
1821    }
1822    free_runscripts(jcr->RunScripts);
1823    delete jcr->RunScripts;
1824
1825    if (jcr->JobId != 0)
1826       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
1827
1828    return;
1829 }
1830
1831 /*
1832  * Get response from Storage daemon to a command we
1833  * sent. Check that the response is OK.
1834  *
1835  *  Returns: 0 on failure
1836  *           1 on success
1837  */
1838 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
1839 {
1840    if (sd->errors) {
1841       return 0;
1842    }
1843    if (bget_msg(sd) > 0) {
1844       Dmsg0(110, sd->msg);
1845       if (strcmp(sd->msg, resp) == 0) {
1846          return 1;
1847       }
1848    }
1849    if (job_canceled(jcr)) {
1850       return 0;                       /* if canceled avoid useless error messages */
1851    }
1852    if (is_bnet_error(sd)) {
1853       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
1854          cmd, bnet_strerror(sd));
1855    } else {
1856       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
1857          cmd, resp, sd->msg);
1858    }
1859    return 0;
1860 }
1861
1862 static int send_bootstrap_file(JCR *jcr)
1863 {
1864    FILE *bs;
1865    char buf[2000];
1866    BSOCK *sd = jcr->store_bsock;
1867    const char *bootstrap = "bootstrap\n";
1868    int stat = 0;
1869
1870    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
1871    if (!jcr->RestoreBootstrap) {
1872       return 1;
1873    }
1874    bs = fopen(jcr->RestoreBootstrap, "rb");
1875    if (!bs) {
1876       berrno be;
1877       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
1878          jcr->RestoreBootstrap, be.bstrerror());
1879       set_jcr_job_status(jcr, JS_ErrorTerminated);
1880       goto bail_out;
1881    }
1882    sd->msglen = pm_strcpy(sd->msg, bootstrap);
1883    bnet_send(sd);
1884    while (fgets(buf, sizeof(buf), bs)) {
1885       sd->msglen = Mmsg(sd->msg, "%s", buf);
1886       bnet_send(sd);
1887    }
1888    bnet_sig(sd, BNET_EOD);
1889    fclose(bs);
1890    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
1891       set_jcr_job_status(jcr, JS_ErrorTerminated);
1892       goto bail_out;
1893    }
1894    stat = 1;
1895
1896 bail_out:
1897    free_bootstrap(jcr);
1898    return stat;
1899 }