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