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