]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
89aa461d582084f6f2decc94a45b71a05ee539e3
[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       default:
1025          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1026          break;
1027       }
1028    }
1029 }
1030
1031
1032 /*
1033  * Director is passing his Fileset
1034  */
1035 static int fileset_cmd(JCR *jcr)
1036 {
1037    BSOCK *dir = jcr->dir_bsock;
1038
1039 #if defined(WIN32_VSS)
1040    int vss = 0;
1041
1042    sscanf(dir->msg, "fileset vss=%d", &vss);
1043    enable_vss = vss;
1044 #endif
1045
1046    if (!init_fileset(jcr)) {
1047       return 0;
1048    }
1049    while (bnet_recv(dir) >= 0) {
1050       strip_trailing_junk(dir->msg);
1051       Dmsg1(500, "Fileset: %s\n", dir->msg);
1052       add_fileset(jcr, dir->msg);
1053    }
1054    if (!term_fileset(jcr)) {
1055       return 0;
1056    }
1057    return bnet_fsend(dir, OKinc);
1058 }
1059
1060 static void free_bootstrap(JCR *jcr)
1061 {
1062    if (jcr->RestoreBootstrap) {
1063       unlink(jcr->RestoreBootstrap);
1064       free_pool_memory(jcr->RestoreBootstrap);
1065       jcr->RestoreBootstrap = NULL;
1066    }
1067 }
1068
1069
1070 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1071 static uint32_t bsr_uniq = 0;
1072
1073 /* 
1074  * The Director sends us the bootstrap file, which
1075  *   we will in turn pass to the SD.
1076  */
1077 static int bootstrap_cmd(JCR *jcr)
1078 {
1079    BSOCK *dir = jcr->dir_bsock;
1080    POOLMEM *fname = get_pool_memory(PM_FNAME);
1081    FILE *bs;
1082
1083    free_bootstrap(jcr);
1084    P(bsr_mutex);
1085    bsr_uniq++;
1086    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1087       jcr->Job, bsr_uniq);
1088    V(bsr_mutex);
1089    Dmsg1(400, "bootstrap=%s\n", fname);
1090    jcr->RestoreBootstrap = fname;
1091    bs = fopen(fname, "a+b");           /* create file */
1092    if (!bs) {
1093       berrno be;
1094       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1095          jcr->RestoreBootstrap, be.strerror());
1096       /*
1097        * Suck up what he is sending to us so that he will then
1098        *   read our error message.
1099        */
1100       while (bnet_recv(dir) >= 0)
1101         {  }
1102       free_bootstrap(jcr);
1103       set_jcr_job_status(jcr, JS_ErrorTerminated);
1104       return 0;
1105    }
1106
1107    while (bnet_recv(dir) >= 0) {
1108        Dmsg1(200, "filed<dird: bootstrap file %s\n", dir->msg);
1109        fputs(dir->msg, bs);
1110    }
1111    fclose(bs);
1112    /*
1113     * Note, do not free the bootstrap yet -- it needs to be 
1114     *  sent to the SD 
1115     */
1116    return bnet_fsend(dir, OKbootstrap);
1117 }
1118
1119
1120 /*
1121  * Get backup level from Director
1122  *
1123  */
1124 static int level_cmd(JCR *jcr)
1125 {
1126    BSOCK *dir = jcr->dir_bsock;
1127    POOLMEM *level, *buf = NULL;
1128    int mtime_only;
1129
1130    level = get_memory(dir->msglen+1);
1131    Dmsg1(110, "level_cmd: %s", dir->msg);
1132    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1133       goto bail_out;
1134    }
1135    /* Base backup requested? */
1136    if (strcmp(level, "base") == 0) {
1137       jcr->JobLevel = L_BASE;
1138    /* Full backup requested? */
1139    } else if (strcmp(level, "full") == 0) {
1140       jcr->JobLevel = L_FULL;
1141    } else if (strcmp(level, "differential") == 0) {
1142       jcr->JobLevel = L_DIFFERENTIAL;
1143       free_memory(level);
1144       return 1;
1145    } else if (strcmp(level, "incremental") == 0) {
1146       jcr->JobLevel = L_INCREMENTAL;
1147       free_memory(level);
1148       return 1;   
1149    /*
1150     * We get his UTC since time, then sync the clocks and correct it
1151     *   to agree with our clock.
1152     */
1153    } else if (strcmp(level, "since_utime") == 0) {
1154       buf = get_memory(dir->msglen+1);
1155       utime_t since_time, adj;
1156       btime_t his_time, bt_start, rt=0, bt_adj=0;
1157       if (jcr->JobLevel == L_NONE) {
1158          jcr->JobLevel = L_SINCE;     /* if no other job level set, do it now */
1159       }
1160       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1161                  buf, &mtime_only) != 2) {
1162          goto bail_out;
1163       }
1164       since_time = str_to_uint64(buf);  /* this is the since time */
1165       Dmsg1(100, "since_time=%d\n", (int)since_time);
1166       char ed1[50], ed2[50];
1167       /*
1168        * Sync clocks by polling him for the time. We take
1169        *   10 samples of his time throwing out the first two.
1170        */
1171       for (int i=0; i<10; i++) {
1172          bt_start = get_current_btime();
1173          bnet_sig(dir, BNET_BTIME);   /* poll for time */
1174          if (bnet_recv(dir) <= 0) {   /* get response */
1175             goto bail_out;
1176          }
1177          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1178             goto bail_out;
1179          }
1180          if (i < 2) {                 /* toss first two results */
1181             continue;
1182          }
1183          his_time = str_to_uint64(buf);
1184          rt = get_current_btime() - bt_start; /* compute round trip time */
1185          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1186                edit_uint64(bt_start, ed2));
1187          bt_adj +=  bt_start - his_time - rt/2;
1188          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1189       }
1190
1191       bt_adj = bt_adj / 8;            /* compute average time */
1192       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1193       adj = btime_to_utime(bt_adj);
1194       since_time += adj;              /* adjust for clock difference */
1195       if (adj != 0) {
1196          Jmsg(jcr, M_INFO, 0, _("DIR and FD clocks differ by %d seconds, FD automatically adjusting.\n"), adj);
1197       }
1198       bnet_sig(dir, BNET_EOD);
1199
1200       Dmsg2(100, "adj = %d since_time=%d\n", (int)adj, (int)since_time);
1201       jcr->incremental = 1;           /* set incremental or decremental backup */
1202       jcr->mtime = (time_t)since_time; /* set since time */
1203    } else {
1204       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1205       free_memory(level);
1206       return 0;
1207    }
1208    free_memory(level);
1209    if (buf) {
1210       free_memory(buf);
1211    }
1212    return bnet_fsend(dir, OKlevel);
1213
1214 bail_out:
1215    pm_strcpy(jcr->errmsg, dir->msg);
1216    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1217    free_memory(level);
1218    if (buf) {
1219       free_memory(buf);
1220    }
1221    return 0;
1222 }
1223
1224 /*
1225  * Get session parameters from Director -- this is for a Restore command
1226  */
1227 static int session_cmd(JCR *jcr)
1228 {
1229    BSOCK *dir = jcr->dir_bsock;
1230
1231    Dmsg1(100, "SessionCmd: %s", dir->msg);
1232    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1233               &jcr->VolSessionId, &jcr->VolSessionTime,
1234               &jcr->StartFile, &jcr->EndFile,
1235               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1236       pm_strcpy(jcr->errmsg, dir->msg);
1237       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1238       return 0;
1239    }
1240
1241    return bnet_fsend(dir, OKsession);
1242 }
1243
1244 /*
1245  * Get address of storage daemon from Director
1246  *
1247  */
1248 static int storage_cmd(JCR *jcr)
1249 {
1250    int stored_port;                /* storage daemon port */
1251    int enable_ssl;                 /* enable ssl to sd */
1252    BSOCK *dir = jcr->dir_bsock;
1253    BSOCK *sd;                         /* storage daemon bsock */
1254
1255    Dmsg1(100, "StorageCmd: %s", dir->msg);
1256    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, &enable_ssl) != 3) {
1257       pm_strcpy(jcr->errmsg, dir->msg);
1258       Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1259       return 0;
1260    }
1261    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, enable_ssl);
1262    /* Open command communications with Storage daemon */
1263    /* Try to connect for 1 hour at 10 second intervals */
1264    sd = bnet_connect(jcr, 10, (int)me->SDConnectTimeout, _("Storage daemon"),
1265                      jcr->stored_addr, NULL, stored_port, 1);
1266    if (sd == NULL) {
1267       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1268           jcr->stored_addr, stored_port);
1269       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1270           jcr->stored_addr, stored_port);
1271       return 0;
1272    }
1273    Dmsg0(110, "Connection OK to SD.\n");
1274
1275    jcr->store_bsock = sd;
1276
1277    bnet_fsend(sd, "Hello Start Job %s\n", jcr->Job);
1278    if (!authenticate_storagedaemon(jcr)) {
1279       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1280       return 0;
1281    }
1282    Dmsg0(110, "Authenticated with SD.\n");
1283
1284    /* Send OK to Director */
1285    return bnet_fsend(dir, OKstore);
1286 }
1287
1288
1289 /*
1290  * Do a backup.
1291  */
1292 static int backup_cmd(JCR *jcr)
1293 {
1294    BSOCK *dir = jcr->dir_bsock;
1295    BSOCK *sd = jcr->store_bsock;
1296    int ok = 0;
1297    int SDJobStatus;
1298    char ed1[50], ed2[50];
1299    bool bDoVSS = false;
1300
1301 #if defined(WIN32_VSS)
1302    // capture state here, if client is backed up by multiple directors
1303    // and one enables vss and the other does not then enable_vss can change
1304    // between here and where its evaluated after the job completes.
1305    bDoVSS = g_pVSSClient && enable_vss;
1306    if (bDoVSS) {
1307       /* Run only one at a time */
1308       P(vss_mutex);
1309    }
1310 #endif
1311
1312    set_jcr_job_status(jcr, JS_Blocked);
1313    jcr->JobType = JT_BACKUP;
1314    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1315
1316    if (sd == NULL) {
1317       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1318       goto cleanup;
1319    }
1320
1321    bnet_fsend(dir, OKbackup);
1322    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1323
1324    /*
1325     * Send Append Open Session to Storage daemon
1326     */
1327    bnet_fsend(sd, append_open);
1328    Dmsg1(110, ">stored: %s", sd->msg);
1329    /*
1330     * Expect to receive back the Ticket number
1331     */
1332    if (bget_msg(sd) >= 0) {
1333       Dmsg1(110, "<stored: %s", sd->msg);
1334       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1335          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1336          goto cleanup;
1337       }
1338       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1339    } else {
1340       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1341       goto cleanup;
1342    }
1343
1344    /*
1345     * Send Append data command to Storage daemon
1346     */
1347    bnet_fsend(sd, append_data, jcr->Ticket);
1348    Dmsg1(110, ">stored: %s", sd->msg);
1349
1350    /*
1351     * Expect to get OK data
1352     */
1353    Dmsg1(110, "<stored: %s", sd->msg);
1354    if (!response(jcr, sd, OK_data, "Append Data")) {
1355       goto cleanup;
1356    }
1357    
1358    generate_daemon_event(jcr, "JobStart");
1359
1360 #if defined(WIN32_VSS)
1361    /* START VSS ON WIN 32 */
1362    if (bDoVSS) {      
1363       if (g_pVSSClient->InitializeForBackup()) {   
1364         /* tell vss which drives to snapshot */   
1365         char szWinDriveLetters[27];   
1366         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1367             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1368             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1369                Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshots failed.\n"));
1370                jcr->Errors++;
1371             } else {
1372                /* tell user if snapshot creation of a specific drive failed */
1373                int i;
1374                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1375                   if (islower(szWinDriveLetters[i])) {
1376                      Jmsg(jcr, M_WARNING, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed. VSS support is disabled on this drive.\n"), szWinDriveLetters[i]);
1377                      jcr->Errors++;
1378                   }
1379                }
1380                /* inform user about writer states */
1381                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++)                
1382                   if (g_pVSSClient->GetWriterState(i) < 1) {
1383                      Jmsg(jcr, M_WARNING, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1384                      jcr->Errors++;
1385                   }                            
1386             }
1387         } else {
1388             Jmsg(jcr, M_INFO, 0, _("No drive letters found for generating VSS snapshots.\n"));
1389         }
1390       } else {
1391          berrno be;
1392          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.strerror());
1393       } 
1394    }
1395 #endif
1396
1397    /*
1398     * Send Files to Storage daemon
1399     */
1400    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1401    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1402       set_jcr_job_status(jcr, JS_ErrorTerminated);
1403       bnet_suppress_error_messages(sd, 1);
1404       bget_msg(sd);                   /* Read final response from append_data */
1405       Dmsg0(110, "Error in blast_data.\n");
1406    } else {
1407       set_jcr_job_status(jcr, JS_Terminated);
1408
1409       if (jcr->JobStatus != JS_Terminated) {
1410          bnet_suppress_error_messages(sd, 1);
1411          goto cleanup;                /* bail out now */
1412       }
1413       /*
1414        * Expect to get response to append_data from Storage daemon
1415        */
1416       if (!response(jcr, sd, OK_append, "Append Data")) {
1417          set_jcr_job_status(jcr, JS_ErrorTerminated);
1418          goto cleanup;
1419       }
1420
1421       /*
1422        * Send Append End Data to Storage daemon
1423        */
1424       bnet_fsend(sd, append_end, jcr->Ticket);
1425       /* Get end OK */
1426       if (!response(jcr, sd, OK_end, "Append End")) {
1427          set_jcr_job_status(jcr, JS_ErrorTerminated);
1428          goto cleanup;
1429       }
1430
1431       /*
1432        * Send Append Close to Storage daemon
1433        */
1434       bnet_fsend(sd, append_close, jcr->Ticket);
1435       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1436          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1437             ok = 1;
1438             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1439          }
1440       }
1441       if (!ok) {
1442          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1443          goto cleanup;
1444       }
1445       if (SDJobStatus != JS_Terminated) {
1446          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1447             SDJobStatus);
1448       }
1449    }
1450
1451 cleanup:
1452 #if defined(WIN32_VSS)
1453    /* STOP VSS ON WIN 32 */
1454    /* tell vss to close the backup session */
1455    if (bDoVSS) {
1456       if (g_pVSSClient->CloseBackup()) {             
1457          /* inform user about writer states */
1458          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
1459             int msg_type = M_INFO;
1460             if (g_pVSSClient->GetWriterState(i) < 1) {
1461                msg_type = M_WARNING;
1462                jcr->Errors++;
1463             }
1464             Jmsg(jcr, msg_type, 0, _("VSS Writer (BackupComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
1465          }
1466       }
1467       V(vss_mutex);
1468    }
1469 #endif
1470
1471    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1472       edit_uint64(jcr->ReadBytes, ed1),
1473       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, (int)bDoVSS, 
1474       jcr->pki_encrypt);
1475    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1476    
1477    return 0;                          /* return and stop command loop */
1478 }
1479
1480 /*
1481  * Do a Verify for Director
1482  *
1483  */
1484 static int verify_cmd(JCR *jcr)
1485 {
1486    BSOCK *dir = jcr->dir_bsock;
1487    BSOCK *sd  = jcr->store_bsock;
1488    char level[100], ed1[50], ed2[50];
1489
1490    jcr->JobType = JT_VERIFY;
1491    if (sscanf(dir->msg, verifycmd, level) != 1) {
1492       bnet_fsend(dir, _("2994 Bad verify command: %s\n"), dir->msg);
1493       return 0;
1494    }
1495
1496    if (strcasecmp(level, "init") == 0) {
1497       jcr->JobLevel = L_VERIFY_INIT;
1498    } else if (strcasecmp(level, "catalog") == 0){
1499       jcr->JobLevel = L_VERIFY_CATALOG;
1500    } else if (strcasecmp(level, "volume") == 0){
1501       jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
1502    } else if (strcasecmp(level, "data") == 0){
1503       jcr->JobLevel = L_VERIFY_DATA;
1504    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1505       jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
1506    } else {
1507       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1508       return 0;
1509    }
1510
1511    bnet_fsend(dir, OKverify);
1512
1513    generate_daemon_event(jcr, "JobStart");
1514
1515    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1516
1517    switch (jcr->JobLevel) {
1518    case L_VERIFY_INIT:
1519    case L_VERIFY_CATALOG:
1520       do_verify(jcr);
1521       break;
1522    case L_VERIFY_VOLUME_TO_CATALOG:
1523       if (!open_sd_read_session(jcr)) {
1524          return 0;
1525       }
1526       start_dir_heartbeat(jcr);
1527       do_verify_volume(jcr);
1528       stop_dir_heartbeat(jcr);
1529       /*
1530        * Send Close session command to Storage daemon
1531        */
1532       bnet_fsend(sd, read_close, jcr->Ticket);
1533       Dmsg1(130, "bfiled>stored: %s", sd->msg);
1534
1535       /* ****FIXME**** check response */
1536       bget_msg(sd);                      /* get OK */
1537
1538       /* Inform Storage daemon that we are done */
1539       bnet_sig(sd, BNET_TERMINATE);
1540
1541       break;
1542    case L_VERIFY_DISK_TO_CATALOG:
1543       do_verify(jcr);
1544       break;
1545    default:
1546       bnet_fsend(dir, _("2994 Bad verify level: %s\n"), dir->msg);
1547       return 0;
1548    }
1549
1550    bnet_sig(dir, BNET_EOD);
1551
1552    /* Send termination status back to Dir */
1553    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1554       edit_uint64(jcr->ReadBytes, ed1),
1555       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1556       jcr->pki_encrypt);
1557    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1558
1559    /* Inform Director that we are done */
1560    bnet_sig(dir, BNET_TERMINATE);
1561    return 0;                          /* return and terminate command loop */
1562 }
1563
1564 /*
1565  * Do a Restore for Director
1566  *
1567  */
1568 static int restore_cmd(JCR *jcr)
1569 {
1570    BSOCK *dir = jcr->dir_bsock;
1571    BSOCK *sd = jcr->store_bsock;
1572    POOLMEM *where;
1573    int prefix_links;
1574    char replace;
1575    char ed1[50], ed2[50];
1576
1577    /*
1578     * Scan WHERE (base directory for restore) from command
1579     */
1580    Dmsg0(150, "restore command\n");
1581    /* Pickup where string */
1582    where = get_memory(dir->msglen+1);
1583    *where = 0;
1584
1585    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, where) != 3) {
1586       if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
1587          pm_strcpy(jcr->errmsg, dir->msg);
1588          Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
1589          return 0;
1590       }
1591       *where = 0;
1592    }
1593    /* Turn / into nothing */
1594    if (IsPathSeparator(where[0]) && where[1] == '\0') {
1595       where[0] = '\0';
1596    }
1597
1598    Dmsg2(150, "Got replace %c, where=%s\n", replace, where);
1599    unbash_spaces(where);
1600    jcr->where = bstrdup(where);
1601    free_pool_memory(where);
1602    jcr->replace = replace;
1603    jcr->prefix_links = prefix_links;
1604
1605    bnet_fsend(dir, OKrestore);
1606    Dmsg1(110, "bfiled>dird: %s", dir->msg);
1607
1608    jcr->JobType = JT_RESTORE;
1609
1610    set_jcr_job_status(jcr, JS_Blocked);
1611
1612    if (!open_sd_read_session(jcr)) {
1613       set_jcr_job_status(jcr, JS_ErrorTerminated);
1614       goto bail_out;
1615    }
1616
1617    set_jcr_job_status(jcr, JS_Running);
1618
1619    /*
1620     * Do restore of files and data
1621     */
1622    start_dir_heartbeat(jcr);
1623    generate_daemon_event(jcr, "JobStart");
1624    do_restore(jcr);
1625    stop_dir_heartbeat(jcr);
1626
1627    set_jcr_job_status(jcr, JS_Terminated);
1628    if (jcr->JobStatus != JS_Terminated) {
1629       bnet_suppress_error_messages(sd, 1);
1630    }
1631
1632    /*
1633     * Send Close session command to Storage daemon
1634     */
1635    bnet_fsend(sd, read_close, jcr->Ticket);
1636    Dmsg1(130, "bfiled>stored: %s", sd->msg);
1637
1638    bget_msg(sd);                      /* get OK */
1639
1640    /* Inform Storage daemon that we are done */
1641    bnet_sig(sd, BNET_TERMINATE);
1642
1643 bail_out:
1644
1645    if (jcr->Errors) {
1646       set_jcr_job_status(jcr, JS_ErrorTerminated);
1647    }
1648    /* Send termination status back to Dir */
1649    bnet_fsend(dir, EndJob, jcr->JobStatus, jcr->JobFiles,
1650       edit_uint64(jcr->ReadBytes, ed1),
1651       edit_uint64(jcr->JobBytes, ed2), jcr->Errors, 0,
1652       jcr->pki_encrypt);
1653    Dmsg1(110, "End FD msg: %s\n", dir->msg);
1654
1655    /* Inform Director that we are done */
1656    bnet_sig(dir, BNET_TERMINATE);
1657
1658    Dmsg0(130, "Done in job.c\n");
1659    return 0;                          /* return and terminate command loop */
1660 }
1661
1662 static int open_sd_read_session(JCR *jcr)
1663 {
1664    BSOCK *sd = jcr->store_bsock;
1665
1666    if (!sd) {
1667       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
1668       return 0;
1669    }
1670    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
1671       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
1672    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
1673    /*
1674     * Open Read Session with Storage daemon
1675     */
1676    bnet_fsend(sd, read_open, "DummyVolume",
1677       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
1678       jcr->StartBlock, jcr->EndBlock);
1679    Dmsg1(110, ">stored: %s", sd->msg);
1680
1681    /*
1682     * Get ticket number
1683     */
1684    if (bget_msg(sd) >= 0) {
1685       Dmsg1(110, "bfiled<stored: %s", sd->msg);
1686       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1687          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
1688          return 0;
1689       }
1690       Dmsg1(110, "bfiled: got Ticket=%d\n", jcr->Ticket);
1691    } else {
1692       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
1693       return 0;
1694    }
1695
1696    if (!send_bootstrap_file(jcr)) {
1697       return 0;
1698    }
1699
1700    /*
1701     * Start read of data with Storage daemon
1702     */
1703    bnet_fsend(sd, read_data, jcr->Ticket);
1704    Dmsg1(110, ">stored: %s", sd->msg);
1705
1706    /*
1707     * Get OK data
1708     */
1709    if (!response(jcr, sd, OK_data, "Read Data")) {
1710       return 0;
1711    }
1712    return 1;
1713 }
1714
1715 /*
1716  * Destroy the Job Control Record and associated
1717  * resources (sockets).
1718  */
1719 static void filed_free_jcr(JCR *jcr)
1720 {
1721    if (jcr->store_bsock) {
1722       bnet_close(jcr->store_bsock);
1723    }
1724    free_bootstrap(jcr);
1725    if (jcr->last_fname) {
1726       free_pool_memory(jcr->last_fname);
1727    }
1728    free_runscripts(jcr->RunScripts);
1729    delete jcr->RunScripts;
1730
1731    return;
1732 }
1733
1734 /*
1735  * Get response from Storage daemon to a command we
1736  * sent. Check that the response is OK.
1737  *
1738  *  Returns: 0 on failure
1739  *           1 on success
1740  */
1741 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
1742 {
1743    if (sd->errors) {
1744       return 0;
1745    }
1746    if (bget_msg(sd) > 0) {
1747       Dmsg0(110, sd->msg);
1748       if (strcmp(sd->msg, resp) == 0) {
1749          return 1;
1750       }
1751    }
1752    if (job_canceled(jcr)) {
1753       return 0;                       /* if canceled avoid useless error messages */
1754    }
1755    if (is_bnet_error(sd)) {
1756       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
1757          cmd, bnet_strerror(sd));
1758    } else {
1759       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
1760          cmd, resp, sd->msg);
1761    }
1762    return 0;
1763 }
1764
1765 static int send_bootstrap_file(JCR *jcr)
1766 {
1767    FILE *bs;
1768    char buf[2000];
1769    BSOCK *sd = jcr->store_bsock;
1770    const char *bootstrap = "bootstrap\n";
1771    int stat = 0;
1772
1773    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
1774    if (!jcr->RestoreBootstrap) {
1775       return 1;
1776    }
1777    bs = fopen(jcr->RestoreBootstrap, "rb");
1778    if (!bs) {
1779       berrno be;
1780       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
1781          jcr->RestoreBootstrap, be.strerror());
1782       set_jcr_job_status(jcr, JS_ErrorTerminated);
1783       goto bail_out;
1784    }
1785    sd->msglen = pm_strcpy(sd->msg, bootstrap);
1786    bnet_send(sd);
1787    while (fgets(buf, sizeof(buf), bs)) {
1788       sd->msglen = Mmsg(sd->msg, "%s", buf);
1789       bnet_send(sd);
1790    }
1791    bnet_sig(sd, BNET_EOD);
1792    fclose(bs);
1793    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
1794       set_jcr_job_status(jcr, JS_ErrorTerminated);
1795       goto bail_out;
1796    }
1797    stat = 1;
1798
1799 bail_out:
1800    free_bootstrap(jcr);
1801    return stat;
1802 }