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