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