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