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