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