]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Change all sm_checks into Dsm_check for performance reasons
[bacula/bacula] / bacula / src / filed / job.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2011 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 three of the GNU Affero 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 Affero 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 Kern Sibbald.
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  */
34
35 #include "bacula.h"
36 #include "filed.h"
37
38 #if defined(WIN32_VSS)
39 #include "vss.h"
40
41 static pthread_mutex_t vss_mutex = PTHREAD_MUTEX_INITIALIZER;
42 static int enable_vss = 0;
43 #endif
44
45 /**
46  * As Windows saves ACLs as part of the standard backup stream
47  * we just pretend here that is has implicit acl support.
48  */
49 #if defined(HAVE_ACL) || defined(HAVE_WIN32)
50 const bool have_acl = true;
51 #else
52 const bool have_acl = false;
53 #endif
54
55 #if defined(HAVE_XATTR)
56 const bool have_xattr = true;
57 #else
58 const bool have_xattr = false;
59 #endif
60
61 extern CLIENT *me;                    /* our client resource */
62
63 /* Imported functions */
64 extern int status_cmd(JCR *jcr);
65 extern int qstatus_cmd(JCR *jcr);
66 extern int accurate_cmd(JCR *jcr);
67
68 /* Forward referenced functions */
69 static int backup_cmd(JCR *jcr);
70 static int bootstrap_cmd(JCR *jcr);
71 static int cancel_cmd(JCR *jcr);
72 static int setdebug_cmd(JCR *jcr);
73 static int estimate_cmd(JCR *jcr);
74 static int hello_cmd(JCR *jcr);
75 static int job_cmd(JCR *jcr);
76 static int fileset_cmd(JCR *jcr);
77 static int level_cmd(JCR *jcr);
78 static int verify_cmd(JCR *jcr);
79 static int restore_cmd(JCR *jcr);
80 static int end_restore_cmd(JCR *jcr);
81 static int storage_cmd(JCR *jcr);
82 static int session_cmd(JCR *jcr);
83 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
84 static void filed_free_jcr(JCR *jcr);
85 static int open_sd_read_session(JCR *jcr);
86 static int send_bootstrap_file(JCR *jcr);
87 static int runscript_cmd(JCR *jcr);
88 static int runbefore_cmd(JCR *jcr);
89 static int runafter_cmd(JCR *jcr);
90 static int runbeforenow_cmd(JCR *jcr);
91 static int restore_object_cmd(JCR *jcr);
92 static int set_options(findFOPTS *fo, const char *opts);
93 static void set_storage_auth_key(JCR *jcr, char *key);
94 static int sm_dump_cmd(JCR *jcr);
95 #ifdef DEVELOPER
96 static int exit_cmd(JCR *jcr);
97 #endif
98
99 /* Exported functions */
100
101 struct s_cmds {
102    const char *cmd;
103    int (*func)(JCR *);
104    int monitoraccess; /* specify if monitors have access to this function */
105 };
106
107 /**
108  * The following are the recognized commands from the Director.
109  */
110 static struct s_cmds cmds[] = {
111    {"backup",       backup_cmd,    0},
112    {"cancel",       cancel_cmd,    0},
113    {"setdebug=",    setdebug_cmd,  0},
114    {"estimate",     estimate_cmd,  0},
115    {"Hello",        hello_cmd,     1},
116    {"fileset",      fileset_cmd,   0},
117    {"JobId=",       job_cmd,       0},
118    {"level = ",     level_cmd,     0},
119    {"restore ",     restore_cmd,   0},
120    {"endrestore",   end_restore_cmd, 0},
121    {"session",      session_cmd,   0},
122    {"status",       status_cmd,    1},
123    {".status",      qstatus_cmd,   1},
124    {"storage ",     storage_cmd,   0},
125    {"verify",       verify_cmd,    0},
126    {"bootstrap",    bootstrap_cmd, 0},
127    {"RunBeforeNow", runbeforenow_cmd, 0},
128    {"RunBeforeJob", runbefore_cmd, 0},
129    {"RunAfterJob",  runafter_cmd,  0},
130    {"Run",          runscript_cmd, 0},
131    {"accurate",     accurate_cmd,  0},
132    {"restoreobject", restore_object_cmd, 0},
133    {"sm_dump",      sm_dump_cmd, 0},
134 #ifdef DEVELOPER
135    {"exit",         exit_cmd, 0},
136 #endif
137    {NULL,       NULL}                  /* list terminator */
138 };
139
140 /* Commands received from director that need scanning */
141 static char jobcmd[]      = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
142 static char storaddr[]    = "storage address=%s port=%d ssl=%d Authorization=%100s";
143 static char storaddr_v1[] = "storage address=%s port=%d ssl=%d";
144 static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
145 static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
146 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
147 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
148 static char restoreobjcmd[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
149 static char endrestoreobjectcmd[] = "restoreobject end\n";
150 static char verifycmd[]   = "verify level=%30s";
151 static char estimatecmd[] = "estimate listing=%d";
152 static char runbefore[]   = "RunBeforeJob %s";
153 static char runafter[]    = "RunAfterJob %s";
154 static char runscript[]   = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
155
156 /* Responses sent to Director */
157 static char errmsg[]      = "2999 Invalid command\n";
158 static char no_auth[]     = "2998 No Authorization\n";
159 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
160 static char OKinc[]       = "2000 OK include\n";
161 static char OKest[]       = "2000 OK estimate files=%s bytes=%s\n";
162 static char OKlevel[]     = "2000 OK level\n";
163 static char OKbackup[]    = "2000 OK backup\n";
164 static char OKbootstrap[] = "2000 OK bootstrap\n";
165 static char OKverify[]    = "2000 OK verify\n";
166 static char OKrestore[]   = "2000 OK restore\n";
167 static char OKsession[]   = "2000 OK session\n";
168 static char OKstore[]     = "2000 OK storage\n";
169 static char OKstoreend[]  = "2000 OK storage end\n";
170 static char OKjob[]       = "2000 OK Job %s (%s) %s,%s,%s";
171 static char OKsetdebug[]  = "2000 OK setdebug=%d trace=%d hangup=%d\n";
172 static char BADjob[]      = "2901 Bad Job\n";
173 static char EndJob[]      = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s"
174                             " JobBytes=%s Errors=%u VSS=%d Encrypt=%d\n";
175 static char OKRunBefore[] = "2000 OK RunBefore\n";
176 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
177 static char OKRunAfter[]  = "2000 OK RunAfter\n";
178 static char OKRunScript[] = "2000 OK RunScript\n";
179 static char BADcmd[]      = "2902 Bad %s\n";
180 static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
181
182
183 /* Responses received from Storage Daemon */
184 static char OK_end[]       = "3000 OK end\n";
185 static char OK_close[]     = "3000 OK close Status = %d\n";
186 static char OK_open[]      = "3000 OK open ticket = %d\n";
187 static char OK_data[]      = "3000 OK data\n";
188 static char OK_append[]    = "3000 OK append data\n";
189 static char OKSDbootstrap[]= "3000 OK bootstrap\n";
190
191
192 /* Commands sent to Storage Daemon */
193 static char append_open[]  = "append open session\n";
194 static char append_data[]  = "append data %d\n";
195 static char append_end[]   = "append end session %d\n";
196 static char append_close[] = "append close session %d\n";
197 static char read_open[]    = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
198 static char read_data[]    = "read data %d\n";
199 static char read_close[]   = "read close session %d\n";
200
201 /**
202  * Accept requests from a Director
203  *
204  * NOTE! We are running as a separate thread
205  *
206  * Send output one line
207  * at a time followed by a zero length transmission.
208  *
209  * Return when the connection is terminated or there
210  * is an error.
211  *
212  * Basic task here is:
213  *   Authenticate Director (during Hello command).
214  *   Accept commands one at a time from the Director
215  *     and execute them.
216  *
217  * Concerning ClientRunBefore/After, the sequence of events
218  * is rather critical. If they are not done in the right
219  * order one can easily get FD->SD timeouts if the script
220  * runs a long time.
221  *
222  * The current sequence of events is:
223  *  1. Dir starts job with FD
224  *  2. Dir connects to SD
225  *  3. Dir connects to FD
226  *  4. FD connects to SD
227  *  5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
228  *  6. Dir sends include/exclude
229  *  7. FD sends data to SD
230  *  8. SD/FD disconnects while SD despools data and attributes (optional)
231  *  9. FD runs ClientRunAfterJob
232  */
233
234 void *handle_client_request(void *dirp)
235 {
236    int i;
237    bool found, quit;
238    JCR *jcr;
239    BSOCK *dir = (BSOCK *)dirp;
240    const char jobname[12] = "*Director*";
241 // saveCWD save_cwd;
242
243    jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
244    jcr->dir_bsock = dir;
245    jcr->ff = init_find_files();
246 // save_cwd.save(jcr);
247    jcr->start_time = time(NULL);
248    jcr->RunScripts = New(alist(10, not_owned_by_alist));
249    jcr->last_fname = get_pool_memory(PM_FNAME);
250    jcr->last_fname[0] = 0;
251    jcr->client_name = get_memory(strlen(my_name) + 1);
252    pm_strcpy(jcr->client_name, my_name);
253    bstrncpy(jcr->Job, jobname, sizeof(jobname));  /* dummy */
254    jcr->crypto.pki_sign = me->pki_sign;
255    jcr->crypto.pki_encrypt = me->pki_encrypt;
256    jcr->crypto.pki_keypair = me->pki_keypair;
257    jcr->crypto.pki_signers = me->pki_signers;
258    jcr->crypto.pki_recipients = me->pki_recipients;
259    dir->set_jcr(jcr);
260    enable_backup_privileges(NULL, 1 /* ignore_errors */);
261
262    /**********FIXME******* add command handler error code */
263
264    for (quit=false; !quit;) {
265       /* Read command */
266       if (dir->recv() < 0) {
267          break;               /* connection terminated */
268       }
269       dir->msg[dir->msglen] = 0;
270       Dmsg1(100, "<dird: %s", dir->msg);
271       found = false;
272       for (i=0; cmds[i].cmd; i++) {
273          if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
274             found = true;         /* indicate command found */
275             if (!jcr->authenticated && cmds[i].func != hello_cmd) {
276                dir->fsend(no_auth);
277                dir->signal(BNET_EOD);
278                break;
279             }
280             if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) {
281                Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
282                dir->fsend(invalid_cmd);
283                dir->signal(BNET_EOD);
284                break;
285             }
286             Dmsg1(100, "Executing %s command.\n", cmds[i].cmd);
287             if (!cmds[i].func(jcr)) {         /* do command */
288                quit = true;         /* error or fully terminated, get out */
289                Dmsg1(100, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
290             }
291             break;
292          }
293       }
294       if (!found) {              /* command not found */
295          dir->fsend(errmsg);
296          quit = true;
297          break;
298       }
299    }
300
301    /* Inform Storage daemon that we are done */
302    if (jcr->store_bsock) {
303       jcr->store_bsock->signal(BNET_TERMINATE);
304    }
305
306    /* Run the after job */
307    run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
308
309    if (jcr->JobId) {            /* send EndJob if running a job */
310       char ed1[50], ed2[50];
311       /* Send termination status back to Dir */
312       dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles,
313                  edit_uint64(jcr->ReadBytes, ed1),
314                  edit_uint64(jcr->JobBytes, ed2), jcr->JobErrors, jcr->VSS,
315                  jcr->crypto.pki_encrypt);
316       Dmsg1(110, "End FD msg: %s\n", dir->msg);
317    }
318
319    generate_daemon_event(jcr, "JobEnd");
320    generate_plugin_event(jcr, bEventJobEnd);
321
322    dequeue_messages(jcr);             /* send any queued messages */
323
324    /* Inform Director that we are done */
325    dir->signal(BNET_TERMINATE);
326
327    free_plugins(jcr);                 /* release instantiated plugins */
328    free_and_null_pool_memory(jcr->job_metadata);
329
330    /* Clean up fileset */
331    FF_PKT *ff = jcr->ff;
332    findFILESET *fileset = ff->fileset;
333    if (fileset) {
334       int i, j, k;
335       /* Delete FileSet Include lists */
336       for (i=0; i<fileset->include_list.size(); i++) {
337          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
338          for (j=0; j<incexe->opts_list.size(); j++) {
339             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
340             for (k=0; k<fo->regex.size(); k++) {
341                regfree((regex_t *)fo->regex.get(k));
342             }
343             for (k=0; k<fo->regexdir.size(); k++) {
344                regfree((regex_t *)fo->regexdir.get(k));
345             }
346             for (k=0; k<fo->regexfile.size(); k++) {
347                regfree((regex_t *)fo->regexfile.get(k));
348             }
349             fo->regex.destroy();
350             fo->regexdir.destroy();
351             fo->regexfile.destroy();
352             fo->wild.destroy();
353             fo->wilddir.destroy();
354             fo->wildfile.destroy();
355             fo->wildbase.destroy();
356             fo->base.destroy();
357             fo->fstype.destroy();
358             fo->drivetype.destroy();
359          }
360          incexe->opts_list.destroy();
361          incexe->name_list.destroy();
362          incexe->plugin_list.destroy();
363          if (incexe->ignoredir) {
364             free(incexe->ignoredir);
365          }
366       }
367       fileset->include_list.destroy();
368
369       /* Delete FileSet Exclude lists */
370       for (i=0; i<fileset->exclude_list.size(); i++) {
371          findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
372          for (j=0; j<incexe->opts_list.size(); j++) {
373             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
374             fo->regex.destroy();
375             fo->regexdir.destroy();
376             fo->regexfile.destroy();
377             fo->wild.destroy();
378             fo->wilddir.destroy();
379             fo->wildfile.destroy();
380             fo->wildbase.destroy();
381             fo->base.destroy();
382             fo->fstype.destroy();
383             fo->drivetype.destroy();
384          }
385          incexe->opts_list.destroy();
386          incexe->name_list.destroy();
387          incexe->plugin_list.destroy();
388          if (incexe->ignoredir) {
389             free(incexe->ignoredir);
390          }
391       }
392       fileset->exclude_list.destroy();
393       free(fileset);
394    }
395    ff->fileset = NULL;
396    Dmsg0(100, "Calling term_find_files\n");
397    term_find_files(jcr->ff);
398 // save_cwd.restore(jcr);
399 // save_cwd.release();
400    jcr->ff = NULL;
401    Dmsg0(100, "Done with term_find_files\n");
402    free_jcr(jcr);                     /* destroy JCR record */
403    Dmsg0(100, "Done with free_jcr\n");
404    Dsm_check(100);
405    garbage_collect_memory_pool();
406    return NULL;
407 }
408
409 static int sm_dump_cmd(JCR *jcr)
410 {
411    close_memory_pool();
412    sm_dump(false, true);
413    jcr->dir_bsock->fsend("2000 sm_dump OK\n");
414    return 1;
415 }
416
417 #ifdef DEVELOPER
418 static int exit_cmd(JCR *jcr)
419 {
420    jcr->dir_bsock->fsend("2000 exit OK\n");
421    terminate_filed(0);
422    return 0;
423 }
424 #endif
425
426
427 /**
428  * Hello from Director he must identify himself and provide his
429  *  password.
430  */
431 static int hello_cmd(JCR *jcr)
432 {
433    Dmsg0(120, "Calling Authenticate\n");
434    if (!authenticate_director(jcr)) {
435       return 0;
436    }
437    Dmsg0(120, "OK Authenticate\n");
438    jcr->authenticated = true;
439    return 1;
440 }
441
442 /**
443  * Cancel a Job
444  */
445 static int cancel_cmd(JCR *jcr)
446 {
447    BSOCK *dir = jcr->dir_bsock;
448    char Job[MAX_NAME_LENGTH];
449    JCR *cjcr;
450
451    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
452       if (!(cjcr=get_jcr_by_full_name(Job))) {
453          dir->fsend(_("2901 Job %s not found.\n"), Job);
454       } else {
455          generate_plugin_event(cjcr, bEventCancelCommand, NULL);
456          cjcr->setJobStatus(JS_Canceled);
457          if (cjcr->store_bsock) {
458             cjcr->store_bsock->set_timed_out();
459             cjcr->store_bsock->set_terminated();
460             cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
461          }
462          free_jcr(cjcr);
463          dir->fsend(_("2001 Job %s marked to be canceled.\n"), Job);
464       }
465    } else {
466       dir->fsend(_("2902 Error scanning cancel command.\n"));
467    }
468    dir->signal(BNET_EOD);
469    return 1;
470 }
471
472
473 /**
474  * Set debug level as requested by the Director
475  *
476  */
477 static int setdebug_cmd(JCR *jcr)
478 {
479    BSOCK *dir = jcr->dir_bsock;
480    int32_t level, trace, hangup;
481    int scan;
482
483    Dmsg1(50, "setdebug_cmd: %s", dir->msg);
484    scan = sscanf(dir->msg, "setdebug=%d trace=%d hangup=%d",
485        &level, &trace, &hangup);
486    if (scan != 3) {
487       Dmsg2(20, "sscanf failed: msg=%s scan=%d\n", dir->msg, scan);
488       if (sscanf(dir->msg, "setdebug=%d trace=%d", &level, &trace) != 2) {
489          pm_strcpy(jcr->errmsg, dir->msg);
490          dir->fsend(_("2991 Bad setdebug command: %s\n"), jcr->errmsg);
491          return 0;
492       } else {
493          hangup = -1;
494       }
495    }
496    if (level >= 0) {
497       debug_level = level;
498    }
499    set_trace(trace);
500    set_hangup(hangup);
501    Dmsg3(50, "level=%d trace=%d hangup=%d\n", level, get_trace(), get_hangup());
502    return dir->fsend(OKsetdebug, level, get_trace(), get_hangup());
503 }
504
505
506 static int estimate_cmd(JCR *jcr)
507 {
508    BSOCK *dir = jcr->dir_bsock;
509    char ed1[50], ed2[50];
510
511    if (sscanf(dir->msg, estimatecmd, &jcr->listing) != 1) {
512       pm_strcpy(jcr->errmsg, dir->msg);
513       Jmsg(jcr, M_FATAL, 0, _("Bad estimate command: %s"), jcr->errmsg);
514       dir->fsend(_("2992 Bad estimate command.\n"));
515       return 0;
516    }
517    make_estimate(jcr);
518    dir->fsend(OKest, edit_uint64_with_commas(jcr->num_files_examined, ed1),
519       edit_uint64_with_commas(jcr->JobBytes, ed2));
520    dir->signal(BNET_EOD);
521    return 1;
522 }
523
524 /**
525  * Get JobId and Storage Daemon Authorization key from Director
526  */
527 static int job_cmd(JCR *jcr)
528 {
529    BSOCK *dir = jcr->dir_bsock;
530    POOL_MEM sd_auth_key(PM_MESSAGE);
531    sd_auth_key.check_size(dir->msglen);
532
533    if (sscanf(dir->msg, jobcmd,  &jcr->JobId, jcr->Job,
534               &jcr->VolSessionId, &jcr->VolSessionTime, 
535               sd_auth_key.c_str()) != 5) {
536       pm_strcpy(jcr->errmsg, dir->msg);
537       Jmsg(jcr, M_FATAL, 0, _("Bad Job Command: %s"), jcr->errmsg);
538       dir->fsend(BADjob);
539       return 0;
540    }
541    set_storage_auth_key(jcr, sd_auth_key.c_str());
542    Dmsg2(120, "JobId=%d Auth=%s\n", jcr->JobId, jcr->sd_auth_key);
543    Mmsg(jcr->errmsg, "JobId=%d Job=%s", jcr->JobId, jcr->Job);
544    new_plugins(jcr);                  /* instantiate plugins for this jcr */
545    generate_plugin_event(jcr, bEventJobStart, (void *)jcr->errmsg);
546 #ifdef HAVE_WIN32
547    return dir->fsend(OKjob, VERSION, LSMDATE, win_os, DISTNAME, DISTVER);
548 #else
549    return dir->fsend(OKjob, VERSION, LSMDATE, HOST_OS, DISTNAME, DISTVER);
550 #endif
551 }
552
553 static int runbefore_cmd(JCR *jcr)
554 {
555    bool ok;
556    BSOCK *dir = jcr->dir_bsock;
557    POOLMEM *cmd = get_memory(dir->msglen+1);
558    RUNSCRIPT *script;
559
560    Dmsg1(100, "runbefore_cmd: %s", dir->msg);
561    if (sscanf(dir->msg, runbefore, cmd) != 1) {
562       pm_strcpy(jcr->errmsg, dir->msg);
563       Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
564       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
565       free_memory(cmd);
566       return 0;
567    }
568    unbash_spaces(cmd);
569
570    /* Run the command now */
571    script = new_runscript();
572    script->set_command(cmd);
573    script->when = SCRIPT_Before;
574    ok = script->run(jcr, "ClientRunBeforeJob");
575    free_runscript(script);
576
577    free_memory(cmd);
578    if (ok) {
579       dir->fsend(OKRunBefore);
580       return 1;
581    } else {
582       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
583       return 0;
584    }
585 }
586
587 static int runbeforenow_cmd(JCR *jcr)
588 {
589    BSOCK *dir = jcr->dir_bsock;
590
591    run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
592    if (job_canceled(jcr)) {
593       dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
594       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
595       return 0;
596    } else {
597       dir->fsend(OKRunBeforeNow);
598       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
599       return 1;
600    }
601 }
602
603 static int runafter_cmd(JCR *jcr)
604 {
605    BSOCK *dir = jcr->dir_bsock;
606    POOLMEM *msg = get_memory(dir->msglen+1);
607    RUNSCRIPT *cmd;
608
609    Dmsg1(100, "runafter_cmd: %s", dir->msg);
610    if (sscanf(dir->msg, runafter, msg) != 1) {
611       pm_strcpy(jcr->errmsg, dir->msg);
612       Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
613       dir->fsend(_("2905 Bad RunAfterJob command.\n"));
614       free_memory(msg);
615       return 0;
616    }
617    unbash_spaces(msg);
618
619    cmd = new_runscript();
620    cmd->set_command(msg);
621    cmd->on_success = true;
622    cmd->on_failure = false;
623    cmd->when = SCRIPT_After;
624
625    jcr->RunScripts->append(cmd);
626
627    free_pool_memory(msg);
628    return dir->fsend(OKRunAfter);
629 }
630
631 static int runscript_cmd(JCR *jcr)
632 {
633    BSOCK *dir = jcr->dir_bsock;
634    POOLMEM *msg = get_memory(dir->msglen+1);
635    int on_success, on_failure, fail_on_error;
636
637    RUNSCRIPT *cmd = new_runscript() ;
638
639    Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
640    /* Note, we cannot sscanf into bools */
641    if (sscanf(dir->msg, runscript, &on_success, 
642                                   &on_failure,
643                                   &fail_on_error,
644                                   &cmd->when,
645                                   msg) != 5) {
646       pm_strcpy(jcr->errmsg, dir->msg);
647       Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
648       dir->fsend(_("2905 Bad RunScript command.\n"));
649       free_runscript(cmd);
650       free_memory(msg);
651       return 0;
652    }
653    cmd->on_success = on_success;
654    cmd->on_failure = on_failure;
655    cmd->fail_on_error = fail_on_error;
656    unbash_spaces(msg);
657
658    cmd->set_command(msg);
659    cmd->debug();
660    jcr->RunScripts->append(cmd);
661
662    free_pool_memory(msg);
663    return dir->fsend(OKRunScript);
664 }
665
666 /*
667  * This reads data sent from the Director from the
668  *   RestoreObject table that allows us to get objects
669  *   that were backed up (VSS .xml data) and are needed
670  *   before starting the restore.
671  */
672 static int restore_object_cmd(JCR *jcr)
673 {
674    BSOCK *dir = jcr->dir_bsock;
675    int32_t FileIndex;
676    restore_object_pkt rop;
677
678    memset(&rop, 0, sizeof(rop));
679    rop.pkt_size = sizeof(rop);
680    rop.pkt_end = sizeof(rop);
681    Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
682    if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
683       generate_plugin_event(jcr, bEventRestoreObject, NULL);
684       return dir->fsend(OKRestoreObject);
685    }
686
687    if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len, 
688               &rop.object_full_len, &rop.object_index, 
689               &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
690       Dmsg0(5, "Bad restore object command\n");
691       pm_strcpy(jcr->errmsg, dir->msg);
692       Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
693       goto bail_out;
694    }
695
696    Dmsg6(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d FI=%d\n",
697          rop.JobId, rop.object_len, rop.object_full_len, 
698          rop.object_index, rop.object_type, FileIndex);
699    /* Read Object name */
700    if (dir->recv() < 0) {
701       goto bail_out;
702    }
703    Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
704    rop.object_name = bstrdup(dir->msg);
705
706    /* Read Object */
707    if (dir->recv() < 0) {
708       goto bail_out;
709    }
710    /* Transfer object from message buffer, and get new message buffer */
711    rop.object = dir->msg;
712    dir->msg = get_pool_memory(PM_MESSAGE);
713
714    /* If object is compressed, uncompress it */
715    if (rop.object_compression == 1) {   /* zlib level 9 */
716       int stat;
717       int out_len = rop.object_full_len + 100;
718       POOLMEM *obj = get_memory(out_len);
719       Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
720       stat = Zinflate(rop.object, rop.object_len, obj, out_len);
721       Dmsg1(100, "Zinflate stat=%d\n", stat);
722       if (out_len != rop.object_full_len) {
723          Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
724             rop.object_full_len, out_len, rop.object_name);
725       }
726       free_pool_memory(rop.object);   /* release compressed object */
727       rop.object = obj;               /* new uncompressed object */
728       rop.object_len = out_len;
729    }
730    Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
731    /* Special Job meta data */
732    if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
733       Dmsg0(100, "got job metadata\n");
734       free_and_null_pool_memory(jcr->job_metadata);
735       jcr->job_metadata = rop.object;
736       rop.object = NULL;
737    } else {
738       /* pass to plugin */
739       generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
740    }
741
742    if (rop.object_name) {
743       free(rop.object_name);
744    }
745    if (rop.object) {
746       free_pool_memory(rop.object);
747    }
748
749    Dmsg1(100, "Send: %s", OKRestoreObject);
750    return 1;
751
752 bail_out:
753    dir->fsend(_("2909 Bad RestoreObject command.\n"));
754    return 0;
755
756 }
757
758
759 static bool init_fileset(JCR *jcr)
760 {
761    FF_PKT *ff;
762    findFILESET *fileset;
763
764    if (!jcr->ff) {
765       return false;
766    }
767    ff = jcr->ff;
768    if (ff->fileset) {
769       return false;
770    }
771    fileset = (findFILESET *)malloc(sizeof(findFILESET));
772    memset(fileset, 0, sizeof(findFILESET));
773    ff->fileset = fileset;
774    fileset->state = state_none;
775    fileset->include_list.init(1, true);
776    fileset->exclude_list.init(1, true);
777    return true;
778 }
779
780 static void append_file(JCR *jcr, findINCEXE *incexe, 
781                         const char *buf, bool is_file)
782 {
783    if (is_file) {
784       incexe->name_list.append(new_dlistString(buf));
785
786    } else if (me->plugin_directory) {
787       generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
788       incexe->plugin_list.append(new_dlistString(buf));
789
790    } else {
791       Jmsg(jcr, M_FATAL, 0, 
792            _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
793            buf);
794    }
795 }
796
797 /**
798  * Add fname to include/exclude fileset list. First check for
799  * | and < and if necessary perform command.
800  */
801 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
802 {
803    findFILESET *fileset = jcr->ff->fileset;
804    char *p;
805    BPIPE *bpipe;
806    POOLMEM *fn;
807    FILE *ffd;
808    char buf[1000];
809    int ch;
810    int stat;
811
812    p = (char *)fname;
813    ch = (uint8_t)*p;
814    switch (ch) {
815    case '|':
816       p++;                            /* skip over | */
817       fn = get_pool_memory(PM_FNAME);
818       fn = edit_job_codes(jcr, fn, p, "");
819       bpipe = open_bpipe(fn, 0, "r");
820       if (!bpipe) {
821          berrno be;
822          Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
823             p, be.bstrerror());
824          free_pool_memory(fn);
825          return;
826       }
827       free_pool_memory(fn);
828       while (fgets(buf, sizeof(buf), bpipe->rfd)) {
829          strip_trailing_junk(buf);
830          append_file(jcr, fileset->incexe, buf, is_file);
831       }
832       if ((stat=close_bpipe(bpipe)) != 0) {
833          berrno be;
834          Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
835             p, be.code(stat), be.bstrerror(stat));
836          return;
837       }
838       break;
839    case '<':
840       Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
841       p++;                      /* skip over < */
842       if ((ffd = fopen(p, "rb")) == NULL) {
843          berrno be;
844          Jmsg(jcr, M_FATAL, 0, 
845               _("Cannot open FileSet input file: %s. ERR=%s\n"),
846             p, be.bstrerror());
847          return;
848       }
849       while (fgets(buf, sizeof(buf), ffd)) {
850          strip_trailing_junk(buf);
851          append_file(jcr, fileset->incexe, buf, is_file);
852       }
853       fclose(ffd);
854       break;
855    default:
856       append_file(jcr, fileset->incexe, fname, is_file);
857       break;
858    }
859 }
860
861 void set_incexe(JCR *jcr, findINCEXE *incexe)
862 {
863    findFILESET *fileset = jcr->ff->fileset;
864    fileset->incexe = incexe;
865 }
866
867
868 /**
869  * Define a new Exclude block in the FileSet
870  */
871 findINCEXE *new_exclude(JCR *jcr)
872 {
873    findFILESET *fileset = jcr->ff->fileset;
874
875    /* New exclude */
876    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
877    memset(fileset->incexe, 0, sizeof(findINCEXE));
878    fileset->incexe->opts_list.init(1, true);
879    fileset->incexe->name_list.init();
880    fileset->incexe->plugin_list.init();
881    fileset->exclude_list.append(fileset->incexe);
882    return fileset->incexe;
883 }
884
885 /**
886  * Define a new Include block in the FileSet
887  */
888 findINCEXE *new_include(JCR *jcr)
889 {
890    findFILESET *fileset = jcr->ff->fileset;
891
892    /* New include */
893    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
894    memset(fileset->incexe, 0, sizeof(findINCEXE));
895    fileset->incexe->opts_list.init(1, true);
896    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
897    fileset->incexe->plugin_list.init();
898    fileset->include_list.append(fileset->incexe);
899    return fileset->incexe;
900 }
901
902 /**
903  * Define a new preInclude block in the FileSet
904  *   That is the include is prepended to the other
905  *   Includes.  This is used for plugin exclusions.
906  */
907 findINCEXE *new_preinclude(JCR *jcr)
908 {
909    findFILESET *fileset = jcr->ff->fileset;
910
911    /* New pre-include */
912    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
913    memset(fileset->incexe, 0, sizeof(findINCEXE));
914    fileset->incexe->opts_list.init(1, true);
915    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
916    fileset->incexe->plugin_list.init();
917    fileset->include_list.prepend(fileset->incexe);
918    return fileset->incexe;
919 }
920
921 static findFOPTS *start_options(FF_PKT *ff)
922 {
923    int state = ff->fileset->state;
924    findINCEXE *incexe = ff->fileset->incexe;
925
926    if (state != state_options) {
927       ff->fileset->state = state_options;
928       findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
929       memset(fo, 0, sizeof(findFOPTS));
930       fo->regex.init(1, true);
931       fo->regexdir.init(1, true);
932       fo->regexfile.init(1, true);
933       fo->wild.init(1, true);
934       fo->wilddir.init(1, true);
935       fo->wildfile.init(1, true);
936       fo->wildbase.init(1, true);
937       fo->base.init(1, true);
938       fo->fstype.init(1, true);
939       fo->drivetype.init(1, true);
940       incexe->current_opts = fo;
941       incexe->opts_list.append(fo);
942    }
943    return incexe->current_opts;
944 }
945
946 /*
947  * Used by plugins to define a new options block
948  */
949 void new_options(JCR *jcr, findINCEXE *incexe)
950 {
951    if (!incexe) {
952       incexe = jcr->ff->fileset->incexe;
953    }
954    findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
955    memset(fo, 0, sizeof(findFOPTS));
956    fo->regex.init(1, true);
957    fo->regexdir.init(1, true);
958    fo->regexfile.init(1, true);
959    fo->wild.init(1, true);
960    fo->wilddir.init(1, true);
961    fo->wildfile.init(1, true);
962    fo->wildbase.init(1, true);
963    fo->base.init(1, true);
964    fo->fstype.init(1, true);
965    fo->drivetype.init(1, true);
966    incexe->current_opts = fo;
967    incexe->opts_list.prepend(fo);
968    jcr->ff->fileset->state = state_options;
969 }
970
971 /**
972  * Add a regex to the current fileset
973  */
974 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
975 {
976    findFOPTS *current_opts = start_options(jcr->ff);
977    regex_t *preg;
978    int rc;
979    char prbuf[500];
980
981    preg = (regex_t *)malloc(sizeof(regex_t));
982    if (current_opts->flags & FO_IGNORECASE) {
983       rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
984    } else {
985       rc = regcomp(preg, item, REG_EXTENDED);
986    }
987    if (rc != 0) {
988       regerror(rc, preg, prbuf, sizeof(prbuf));
989       regfree(preg);
990       free(preg);
991       Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
992       return state_error;
993    }
994    if (type == ' ') {
995       current_opts->regex.append(preg);
996    } else if (type == 'D') {
997       current_opts->regexdir.append(preg);
998    } else if (type == 'F') {
999       current_opts->regexfile.append(preg);
1000    } else {
1001       return state_error;
1002    }
1003    return state_options;
1004 }
1005
1006 /**
1007  * Add a wild card to the current fileset
1008  */
1009 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1010 {
1011    findFOPTS *current_opts = start_options(jcr->ff);
1012
1013    if (type == ' ') {
1014       current_opts->wild.append(bstrdup(item));
1015    } else if (type == 'D') {
1016       current_opts->wilddir.append(bstrdup(item));
1017    } else if (type == 'F') {
1018       current_opts->wildfile.append(bstrdup(item));
1019    } else if (type == 'B') {
1020       current_opts->wildbase.append(bstrdup(item));
1021    } else {
1022       return state_error;
1023    }
1024    return state_options;
1025 }
1026
1027
1028 /**
1029  * Add options to the current fileset
1030  */
1031 int add_options_to_fileset(JCR *jcr, const char *item)
1032 {
1033    findFOPTS *current_opts = start_options(jcr->ff);
1034
1035    set_options(current_opts, item);
1036    return state_options;
1037 }
1038
1039 static void add_fileset(JCR *jcr, const char *item)
1040 {
1041    FF_PKT *ff = jcr->ff;
1042    findFILESET *fileset = ff->fileset;
1043    int state = fileset->state;
1044    findFOPTS *current_opts;
1045
1046    /* Get code, optional subcode, and position item past the dividing space */
1047    Dmsg1(100, "%s\n", item);
1048    int code = item[0];
1049    if (code != '\0') {
1050       ++item;
1051    }
1052    int subcode = ' ';               /* A space is always a valid subcode */
1053    if (item[0] != '\0' && item[0] != ' ') {
1054       subcode = item[0];
1055       ++item;
1056    }
1057    if (*item == ' ') {
1058       ++item;
1059    }
1060
1061    /* Skip all lines we receive after an error */
1062    if (state == state_error) {
1063       Dmsg0(100, "State=error return\n");
1064       return;
1065    }
1066
1067    /**
1068     * The switch tests the code for validity.
1069     * The subcode is always good if it is a space, otherwise we must confirm.
1070     * We set state to state_error first assuming the subcode is invalid,
1071     * requiring state to be set in cases below that handle subcodes.
1072     */
1073    if (subcode != ' ') {
1074       state = state_error;
1075       Dmsg0(100, "Set state=error or double code.\n");
1076    }
1077    switch (code) {
1078    case 'I':
1079       (void)new_include(jcr);
1080       break;
1081    case 'E':
1082       (void)new_exclude(jcr);
1083       break;
1084    case 'N':                             /* null */
1085       state = state_none;
1086       break;
1087    case 'F':                             /* file = */
1088       /* File item to include or exclude list */
1089       state = state_include;
1090       add_file_to_fileset(jcr, item, true);
1091       break;
1092    case 'P':                              /* plugin */
1093       /* Plugin item to include list */
1094       state = state_include;
1095       add_file_to_fileset(jcr, item, false);
1096       break;
1097    case 'R':                              /* regex */
1098       state = add_regex_to_fileset(jcr, item, subcode);
1099       break;
1100    case 'B':
1101       current_opts = start_options(ff);
1102       current_opts->base.append(bstrdup(item));
1103       state = state_options;
1104       break;
1105    case 'X':                             /* Filetype or Drive type */
1106       current_opts = start_options(ff);
1107       state = state_options;
1108       if (subcode == ' ') {
1109          current_opts->fstype.append(bstrdup(item));
1110       } else if (subcode == 'D') {
1111          current_opts->drivetype.append(bstrdup(item));
1112       } else {
1113          state = state_error;
1114       }
1115       break;
1116    case 'W':                               /* wild cards */
1117       state = add_wild_to_fileset(jcr, item, subcode);
1118       break;
1119    case 'O':                                /* Options */
1120       state = add_options_to_fileset(jcr, item);
1121       break;
1122    case 'Z':                                /* ignore dir */
1123       state = state_include;
1124       fileset->incexe->ignoredir = bstrdup(item);
1125       break;
1126    case 'D':
1127       current_opts = start_options(ff);
1128 //    current_opts->reader = bstrdup(item); /* deprecated */
1129       state = state_options;
1130       break;
1131    case 'T':
1132       current_opts = start_options(ff);
1133 //    current_opts->writer = bstrdup(item); /* deprecated */
1134       state = state_options;
1135       break;
1136    default:
1137       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1138       state = state_error;
1139       break;
1140    }
1141    ff->fileset->state = state;
1142 }
1143
1144 static bool term_fileset(JCR *jcr)
1145 {
1146    FF_PKT *ff = jcr->ff;
1147
1148 #ifdef xxx_DEBUG_CODE
1149    findFILESET *fileset = ff->fileset;
1150    int i, j, k;
1151
1152    for (i=0; i<fileset->include_list.size(); i++) {
1153       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1154       Dmsg0(400, "I\n");
1155       for (j=0; j<incexe->opts_list.size(); j++) {
1156          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1157          for (k=0; k<fo->regex.size(); k++) {
1158             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1159          }
1160          for (k=0; k<fo->regexdir.size(); k++) {
1161             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1162          }
1163          for (k=0; k<fo->regexfile.size(); k++) {
1164             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1165          }
1166          for (k=0; k<fo->wild.size(); k++) {
1167             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1168          }
1169          for (k=0; k<fo->wilddir.size(); k++) {
1170             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1171          }
1172          for (k=0; k<fo->wildfile.size(); k++) {
1173             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1174          }
1175          for (k=0; k<fo->wildbase.size(); k++) {
1176             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1177          }
1178          for (k=0; k<fo->base.size(); k++) {
1179             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1180          }
1181          for (k=0; k<fo->fstype.size(); k++) {
1182             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1183          }
1184          for (k=0; k<fo->drivetype.size(); k++) {
1185             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1186          }
1187       }
1188       if (incexe->ignoredir) {
1189          Dmsg1(400, "Z %s\n", incexe->ignoredir);
1190       }
1191       dlistString *node;
1192       foreach_dlist(node, &incexe->name_list) {
1193          Dmsg1(400, "F %s\n", node->c_str());
1194       }
1195       foreach_dlist(node, &incexe->plugin_list) {
1196          Dmsg1(400, "P %s\n", node->c_str());
1197       }
1198    }
1199    for (i=0; i<fileset->exclude_list.size(); i++) {
1200       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1201       Dmsg0(400, "E\n");
1202       for (j=0; j<incexe->opts_list.size(); j++) {
1203          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1204          for (k=0; k<fo->regex.size(); k++) {
1205             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1206          }
1207          for (k=0; k<fo->regexdir.size(); k++) {
1208             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1209          }
1210          for (k=0; k<fo->regexfile.size(); k++) {
1211             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1212          }
1213          for (k=0; k<fo->wild.size(); k++) {
1214             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1215          }
1216          for (k=0; k<fo->wilddir.size(); k++) {
1217             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1218          }
1219          for (k=0; k<fo->wildfile.size(); k++) {
1220             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1221          }
1222          for (k=0; k<fo->wildbase.size(); k++) {
1223             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1224          }
1225          for (k=0; k<fo->base.size(); k++) {
1226             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1227          }
1228          for (k=0; k<fo->fstype.size(); k++) {
1229             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1230          }
1231          for (k=0; k<fo->drivetype.size(); k++) {
1232             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1233          }
1234       }
1235       dlistString *node;
1236       foreach_dlist(node, incexe->name_list) {
1237          Dmsg1(400, "F %s\n", node->c_str());
1238       }
1239       foreach_dlist(node, &incexe->plugin_list) {
1240          Dmsg1(400, "P %s\n", node->c_str());
1241       }
1242    }
1243 #endif
1244    return ff->fileset->state != state_error;
1245 }
1246
1247
1248 /**
1249  * As an optimization, we should do this during
1250  *  "compile" time in filed/job.c, and keep only a bit mask
1251  *  and the Verify options.
1252  */
1253 static int set_options(findFOPTS *fo, const char *opts)
1254 {
1255    int j;
1256    const char *p;
1257    char strip[100];
1258
1259 // Commented out as it is not backward compatible - KES
1260 #ifdef HAVE_WIN32
1261 //   fo->flags |= FO_IGNORECASE; /* always ignorecase under windows */
1262 #endif
1263
1264    for (p=opts; *p; p++) {
1265       switch (*p) {
1266       case 'a':                 /* alway replace */
1267       case '0':                 /* no option */
1268          break;
1269       case 'e':
1270          fo->flags |= FO_EXCLUDE;
1271          break;
1272       case 'f':
1273          fo->flags |= FO_MULTIFS;
1274          break;
1275       case 'h':                 /* no recursion */
1276          fo->flags |= FO_NO_RECURSION;
1277          break;
1278       case 'H':                 /* no hard link handling */
1279          fo->flags |= FO_NO_HARDLINK;
1280          break;
1281       case 'i':
1282          fo->flags |= FO_IGNORECASE;
1283          break;
1284       case 'M':                 /* MD5 */
1285          fo->flags |= FO_MD5;
1286          break;
1287       case 'n':
1288          fo->flags |= FO_NOREPLACE;
1289          break;
1290       case 'p':                 /* use portable data format */
1291          fo->flags |= FO_PORTABLE;
1292          break;
1293       case 'R':                 /* Resource forks and Finder Info */
1294          fo->flags |= FO_HFSPLUS;
1295          break;
1296       case 'r':                 /* read fifo */
1297          fo->flags |= FO_READFIFO;
1298          break;
1299       case 'S':
1300          switch(*(p + 1)) {
1301          case '1':
1302             fo->flags |= FO_SHA1;
1303             p++;
1304             break;
1305 #ifdef HAVE_SHA2
1306          case '2':
1307             fo->flags |= FO_SHA256;
1308             p++;
1309             break;
1310          case '3':
1311             fo->flags |= FO_SHA512;
1312             p++;
1313             break;
1314 #endif
1315          default:
1316             /*
1317              * If 2 or 3 is seen here, SHA2 is not configured, so
1318              *  eat the option, and drop back to SHA-1.
1319              */
1320             if (p[1] == '2' || p[1] == '3') {
1321                p++;
1322             }
1323             fo->flags |= FO_SHA1;
1324             break;
1325          }
1326          break;
1327       case 's':
1328          fo->flags |= FO_SPARSE;
1329          break;
1330       case 'm':
1331          fo->flags |= FO_MTIMEONLY;
1332          break;
1333       case 'k':
1334          fo->flags |= FO_KEEPATIME;
1335          break;
1336       case 'A':
1337          fo->flags |= FO_ACL;
1338          break;
1339       case 'V':                  /* verify options */
1340          /* Copy Verify Options */
1341          for (j=0; *p && *p != ':'; p++) {
1342             fo->VerifyOpts[j] = *p;
1343             if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1344                j++;
1345             }
1346          }
1347          fo->VerifyOpts[j] = 0;
1348          break;
1349       case 'C':                  /* accurate options */
1350          /* Copy Accurate Options */
1351          for (j=0; *p && *p != ':'; p++) {
1352             fo->AccurateOpts[j] = *p;
1353             if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1354                j++;
1355             }
1356          }
1357          fo->AccurateOpts[j] = 0;
1358          break;
1359       case 'J':                  /* Basejob options */
1360          /* Copy BaseJob Options */
1361          for (j=0; *p && *p != ':'; p++) {
1362             fo->BaseJobOpts[j] = *p;
1363             if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1364                j++;
1365             }
1366          }
1367          fo->BaseJobOpts[j] = 0;
1368          break;
1369       case 'P':                  /* strip path */
1370          /* Get integer */
1371          p++;                    /* skip P */
1372          for (j=0; *p && *p != ':'; p++) {
1373             strip[j] = *p;
1374             if (j < (int)sizeof(strip) - 1) {
1375                j++;
1376             }
1377          }
1378          strip[j] = 0;
1379          fo->strip_path = atoi(strip);
1380          fo->flags |= FO_STRIPPATH;
1381          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1382          break;
1383       case 'w':
1384          fo->flags |= FO_IF_NEWER;
1385          break;
1386       case 'W':
1387          fo->flags |= FO_ENHANCEDWILD;
1388          break;
1389       case 'Z':                 /* gzip compression */
1390          fo->flags |= FO_GZIP;
1391          fo->GZIP_level = *++p - '0';
1392          break;
1393       case 'K':
1394          fo->flags |= FO_NOATIME;
1395          break;
1396       case 'c':
1397          fo->flags |= FO_CHKCHANGES;
1398          break;
1399       case 'N':
1400          fo->flags |= FO_HONOR_NODUMP;
1401          break;
1402       case 'X':
1403          fo->flags |= FO_XATTR;
1404          break;
1405       default:
1406          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1407          break;
1408       }
1409    }
1410    return state_options;
1411 }
1412
1413
1414 /**
1415  * Director is passing his Fileset
1416  */
1417 static int fileset_cmd(JCR *jcr)
1418 {
1419    BSOCK *dir = jcr->dir_bsock;
1420    int rtnstat;
1421
1422 #if defined(WIN32_VSS)
1423    int vss = 0;
1424
1425    sscanf(dir->msg, "fileset vss=%d", &vss);
1426    enable_vss = vss;
1427 #endif
1428
1429    if (!init_fileset(jcr)) {
1430       return 0;
1431    }
1432    while (dir->recv() >= 0) {
1433       strip_trailing_junk(dir->msg);
1434       Dmsg1(500, "Fileset: %s\n", dir->msg);
1435       add_fileset(jcr, dir->msg);
1436    }
1437    if (!term_fileset(jcr)) {
1438       return 0;
1439    }
1440    rtnstat = dir->fsend(OKinc);
1441    generate_plugin_event(jcr, bEventEndFileSet);
1442    return rtnstat;
1443 }
1444
1445 static void free_bootstrap(JCR *jcr)
1446 {
1447    if (jcr->RestoreBootstrap) {
1448       unlink(jcr->RestoreBootstrap);
1449       free_pool_memory(jcr->RestoreBootstrap);
1450       jcr->RestoreBootstrap = NULL;
1451    }
1452 }
1453
1454
1455 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1456 static uint32_t bsr_uniq = 0;
1457
1458 /**
1459  * The Director sends us the bootstrap file, which
1460  *   we will in turn pass to the SD.
1461  *   Deprecated.  The bsr is now sent directly from the
1462  *   Director to the SD.
1463  */
1464 static int bootstrap_cmd(JCR *jcr)
1465 {
1466    BSOCK *dir = jcr->dir_bsock;
1467    POOLMEM *fname = get_pool_memory(PM_FNAME);
1468    FILE *bs;
1469
1470    free_bootstrap(jcr);
1471    P(bsr_mutex);
1472    bsr_uniq++;
1473    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1474       jcr->Job, bsr_uniq);
1475    V(bsr_mutex);
1476    Dmsg1(400, "bootstrap=%s\n", fname);
1477    jcr->RestoreBootstrap = fname;
1478    bs = fopen(fname, "a+b");           /* create file */
1479    if (!bs) {
1480       berrno be;
1481       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1482          jcr->RestoreBootstrap, be.bstrerror());
1483       /*
1484        * Suck up what he is sending to us so that he will then
1485        *   read our error message.
1486        */
1487       while (dir->recv() >= 0)
1488         {  }
1489       free_bootstrap(jcr);
1490       jcr->setJobStatus(JS_ErrorTerminated);
1491       return 0;
1492    }
1493
1494    while (dir->recv() >= 0) {
1495        Dmsg1(200, "filed<dird: bootstrap: %s", dir->msg);
1496        fputs(dir->msg, bs);
1497    }
1498    fclose(bs);
1499    /*
1500     * Note, do not free the bootstrap yet -- it needs to be 
1501     *  sent to the SD 
1502     */
1503    return dir->fsend(OKbootstrap);
1504 }
1505
1506
1507 /**
1508  * Get backup level from Director
1509  *
1510  */
1511 static int level_cmd(JCR *jcr)
1512 {
1513    BSOCK *dir = jcr->dir_bsock;
1514    POOLMEM *level, *buf = NULL;
1515    int mtime_only;
1516
1517    level = get_memory(dir->msglen+1);
1518    Dmsg1(10, "level_cmd: %s", dir->msg);
1519
1520    /* keep compatibility with older directors */
1521    if (strstr(dir->msg, "accurate")) {
1522       jcr->accurate = true;
1523    }
1524    if (strstr(dir->msg, "rerunning")) {
1525       jcr->rerunning = true;
1526    }
1527    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1528       goto bail_out;
1529    }
1530    /* Base backup requested? */
1531    if (strcmp(level, "base") == 0) {
1532       jcr->setJobLevel(L_BASE);
1533    /* Full backup requested? */
1534    } else if (strcmp(level, "full") == 0) {
1535       jcr->setJobLevel(L_FULL);
1536    } else if (strstr(level, "differential")) {
1537       jcr->setJobLevel(L_DIFFERENTIAL);
1538       free_memory(level);
1539       return 1;
1540    } else if (strstr(level, "incremental")) {
1541       jcr->setJobLevel(L_INCREMENTAL);
1542       free_memory(level);
1543       return 1;
1544    /*
1545     * We get his UTC since time, then sync the clocks and correct it
1546     *   to agree with our clock.
1547     */
1548    } else if (strcmp(level, "since_utime") == 0) {
1549       buf = get_memory(dir->msglen+1);
1550       utime_t since_time, adj;
1551       btime_t his_time, bt_start, rt=0, bt_adj=0;
1552       if (jcr->getJobLevel() == L_NONE) {
1553          jcr->setJobLevel(L_SINCE);     /* if no other job level set, do it now */
1554       }
1555       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1556                  buf, &mtime_only) != 2) {
1557          goto bail_out;
1558       }
1559       since_time = str_to_uint64(buf);  /* this is the since time */
1560       Dmsg1(100, "since_time=%lld\n", since_time);
1561       char ed1[50], ed2[50];
1562       /*
1563        * Sync clocks by polling him for the time. We take
1564        *   10 samples of his time throwing out the first two.
1565        */
1566       for (int i=0; i<10; i++) {
1567          bt_start = get_current_btime();
1568          dir->signal(BNET_BTIME);     /* poll for time */
1569          if (dir->recv() <= 0) {      /* get response */
1570             goto bail_out;
1571          }
1572          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1573             goto bail_out;
1574          }
1575          if (i < 2) {                 /* toss first two results */
1576             continue;
1577          }
1578          his_time = str_to_uint64(buf);
1579          rt = get_current_btime() - bt_start; /* compute round trip time */
1580          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1581                edit_uint64(bt_start, ed2));
1582          bt_adj +=  bt_start - his_time - rt/2;
1583          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1584       }
1585
1586       bt_adj = bt_adj / 8;            /* compute average time */
1587       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1588       adj = btime_to_utime(bt_adj);
1589       since_time += adj;              /* adjust for clock difference */
1590       /* Don't notify if time within 3 seconds */
1591       if (adj > 3 || adj < -3) {
1592          int type;
1593          if (adj > 600 || adj < -600) {
1594             type = M_WARNING;
1595          } else {
1596             type = M_INFO;
1597          }
1598          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1599       }
1600       dir->signal(BNET_EOD);
1601
1602       Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1603       jcr->incremental = 1;           /* set incremental or decremental backup */
1604       jcr->mtime = since_time;        /* set since time */
1605       generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1606    } else {
1607       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1608       free_memory(level);
1609       return 0;
1610    }
1611    free_memory(level);
1612    if (buf) {
1613       free_memory(buf);
1614    }
1615    generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1616    return dir->fsend(OKlevel);
1617
1618 bail_out:
1619    pm_strcpy(jcr->errmsg, dir->msg);
1620    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1621    free_memory(level);
1622    if (buf) {
1623       free_memory(buf);
1624    }
1625    return 0;
1626 }
1627
1628 /**
1629  * Get session parameters from Director -- this is for a Restore command
1630  *   This is deprecated. It is now passed via the bsr.
1631  */
1632 static int session_cmd(JCR *jcr)
1633 {
1634    BSOCK *dir = jcr->dir_bsock;
1635
1636    Dmsg1(100, "SessionCmd: %s", dir->msg);
1637    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1638               &jcr->VolSessionId, &jcr->VolSessionTime,
1639               &jcr->StartFile, &jcr->EndFile,
1640               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1641       pm_strcpy(jcr->errmsg, dir->msg);
1642       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1643       return 0;
1644    }
1645
1646    return dir->fsend(OKsession);
1647 }
1648
1649 static void set_storage_auth_key(JCR *jcr, char *key)
1650 {
1651    /* if no key don't update anything */
1652    if (!*key) {                
1653       return;
1654    }
1655
1656    /**
1657     * We can be contacting multiple storage daemons.
1658     * So, make sure that any old jcr->store_bsock is cleaned up. 
1659     */
1660    if (jcr->store_bsock) {
1661       jcr->store_bsock->destroy();
1662       jcr->store_bsock = NULL;
1663    }
1664
1665    /**
1666     * We can be contacting multiple storage daemons.
1667     *   So, make sure that any old jcr->sd_auth_key is cleaned up. 
1668     */
1669    if (jcr->sd_auth_key) {
1670       /*
1671        * If we already have a Authorization key, director can do multi
1672        * storage restore
1673        */
1674       Dmsg0(5, "set multi_restore=true\n");
1675       jcr->multi_restore = true;
1676       bfree(jcr->sd_auth_key);
1677    }
1678
1679    jcr->sd_auth_key = bstrdup(key);
1680    Dmsg0(5, "set sd auth key\n");
1681 }
1682
1683 /**
1684  * Get address of storage daemon from Director
1685  *
1686  */
1687 static int storage_cmd(JCR *jcr)
1688 {
1689    int stored_port;                /* storage daemon port */
1690    int enable_ssl;                 /* enable ssl to sd */
1691    POOL_MEM sd_auth_key(PM_MESSAGE);
1692    BSOCK *dir = jcr->dir_bsock;
1693    BSOCK *sd = new_bsock();        /* storage daemon bsock */
1694
1695
1696    Dmsg1(100, "StorageCmd: %s", dir->msg);
1697    sd_auth_key.check_size(dir->msglen);
1698    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, 
1699               &enable_ssl, sd_auth_key.c_str()) != 4) {
1700       if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
1701                  &stored_port, &enable_ssl) != 3) {
1702          pm_strcpy(jcr->errmsg, dir->msg);
1703          Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1704          goto bail_out;
1705       }
1706    }
1707
1708    set_storage_auth_key(jcr, sd_auth_key.c_str());
1709
1710    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, 
1711          enable_ssl);
1712    /* Open command communications with Storage daemon */
1713    /* Try to connect for 1 hour at 10 second intervals */
1714
1715    sd->set_source_address(me->FDsrc_addr);
1716    if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1717                 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1718      sd->destroy();
1719      sd = NULL;
1720    }
1721
1722    if (sd == NULL) {
1723       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1724           jcr->stored_addr, stored_port);
1725       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1726           jcr->stored_addr, stored_port);
1727       goto bail_out;
1728    }
1729    Dmsg0(110, "Connection OK to SD.\n");
1730
1731    jcr->store_bsock = sd;
1732
1733    sd->fsend("Hello Start Job %s\n", jcr->Job);
1734    if (!authenticate_storagedaemon(jcr)) {
1735       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1736       goto bail_out;
1737    }
1738    Dmsg0(110, "Authenticated with SD.\n");
1739
1740    /* Send OK to Director */
1741    return dir->fsend(OKstore);
1742
1743 bail_out:
1744    dir->fsend(BADcmd, "storage");
1745    return 0;
1746
1747 }
1748
1749
1750 /**
1751  * Do a backup.
1752  */
1753 static int backup_cmd(JCR *jcr)
1754 {
1755    BSOCK *dir = jcr->dir_bsock;
1756    BSOCK *sd = jcr->store_bsock;
1757    int ok = 0;
1758    int SDJobStatus;
1759    int32_t FileIndex;
1760
1761 #if defined(WIN32_VSS)
1762    // capture state here, if client is backed up by multiple directors
1763    // and one enables vss and the other does not then enable_vss can change
1764    // between here and where its evaluated after the job completes.
1765    jcr->VSS = g_pVSSClient && enable_vss;
1766    if (jcr->VSS) {
1767       /* Run only one at a time */
1768       P(vss_mutex);
1769    }
1770 #endif
1771   
1772    if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1773       jcr->JobFiles = FileIndex;
1774       Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1775    }
1776
1777    /**
1778     * Validate some options given to the backup make sense for the compiled in
1779     * options of this filed.
1780     */
1781    if (jcr->ff->flags & FO_ACL && !have_acl) {
1782       Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
1783       goto cleanup;
1784    }
1785    if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1786       Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
1787       goto cleanup;
1788    }
1789
1790    jcr->setJobStatus(JS_Blocked);
1791    jcr->setJobType(JT_BACKUP);
1792    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1793
1794    if (sd == NULL) {
1795       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1796       dir->fsend(BADcmd, "backup");
1797       goto cleanup;
1798    }
1799
1800    dir->fsend(OKbackup);
1801    Dmsg1(110, "filed>dird: %s", dir->msg);
1802
1803    /**
1804     * Send Append Open Session to Storage daemon
1805     */
1806    sd->fsend(append_open);
1807    Dmsg1(110, ">stored: %s", sd->msg);
1808    /**
1809     * Expect to receive back the Ticket number
1810     */
1811    if (bget_msg(sd) >= 0) {
1812       Dmsg1(110, "<stored: %s", sd->msg);
1813       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1814          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1815          goto cleanup;
1816       }
1817       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1818    } else {
1819       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1820       goto cleanup;
1821    }
1822
1823    /**
1824     * Send Append data command to Storage daemon
1825     */
1826    sd->fsend(append_data, jcr->Ticket);
1827    Dmsg1(110, ">stored: %s", sd->msg);
1828
1829    /**
1830     * Expect to get OK data
1831     */
1832    Dmsg1(110, "<stored: %s", sd->msg);
1833    if (!response(jcr, sd, OK_data, "Append Data")) {
1834       goto cleanup;
1835    }
1836    
1837    generate_daemon_event(jcr, "JobStart");
1838    generate_plugin_event(jcr, bEventStartBackupJob);
1839
1840 #if defined(WIN32_VSS)
1841    /* START VSS ON WIN32 */
1842    if (jcr->VSS) {      
1843       if (g_pVSSClient->InitializeForBackup(jcr)) {   
1844         generate_plugin_event(jcr, bEventVssBackupAddComponents);
1845         /* tell vss which drives to snapshot */   
1846         char szWinDriveLetters[27];
1847         *szWinDriveLetters=0;
1848         generate_plugin_event(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
1849         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1850             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1851             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1852                berrno be;
1853                Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
1854             } else {
1855                /* tell user if snapshot creation of a specific drive failed */
1856                int i;
1857                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1858                   if (islower(szWinDriveLetters[i])) {
1859                      Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed.\n"), szWinDriveLetters[i]);
1860                   }
1861                }
1862                /* inform user about writer states */
1863                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {               
1864                   if (g_pVSSClient->GetWriterState(i) < 1) {
1865                      Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1866                   }                            
1867                }
1868             }
1869         } else {
1870             Jmsg(jcr, M_FATAL, 0, _("No drive letters found for generating VSS snapshots.\n"));
1871         }
1872       } else {
1873          berrno be;
1874          Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly. ERR=%s\n"), be.bstrerror());
1875       } 
1876       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
1877    }
1878 #endif
1879
1880    /**
1881     * Send Files to Storage daemon
1882     */
1883    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1884    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1885       jcr->setJobStatus(JS_ErrorTerminated);
1886       bnet_suppress_error_messages(sd, 1);
1887       Dmsg0(110, "Error in blast_data.\n");
1888    } else {
1889       jcr->setJobStatus(JS_Terminated);
1890       /* Note, the above set status will not override an error */
1891       if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
1892          bnet_suppress_error_messages(sd, 1);
1893          goto cleanup;                /* bail out now */
1894       }
1895       /**
1896        * Expect to get response to append_data from Storage daemon
1897        */
1898       if (!response(jcr, sd, OK_append, "Append Data")) {
1899          jcr->setJobStatus(JS_ErrorTerminated);
1900          goto cleanup;
1901       }
1902
1903       /**
1904        * Send Append End Data to Storage daemon
1905        */
1906       sd->fsend(append_end, jcr->Ticket);
1907       /* Get end OK */
1908       if (!response(jcr, sd, OK_end, "Append End")) {
1909          jcr->setJobStatus(JS_ErrorTerminated);
1910          goto cleanup;
1911       }
1912
1913       /**
1914        * Send Append Close to Storage daemon
1915        */
1916       sd->fsend(append_close, jcr->Ticket);
1917       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1918          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1919             ok = 1;
1920             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1921          }
1922       }
1923       if (!ok) {
1924          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1925          goto cleanup;
1926       }
1927       if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings)) {
1928          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1929             SDJobStatus);
1930       }
1931    }
1932
1933 cleanup:
1934 #if defined(WIN32_VSS)
1935    if (jcr->VSS) {
1936       Win32ConvCleanupCache();
1937       g_pVSSClient->DestroyWriterInfo();
1938       V(vss_mutex);
1939    }
1940 #endif
1941
1942    generate_plugin_event(jcr, bEventEndBackupJob);
1943    return 0;                          /* return and stop command loop */
1944 }
1945
1946 /**
1947  * Do a Verify for Director
1948  *
1949  */
1950 static int verify_cmd(JCR *jcr)
1951 {
1952    BSOCK *dir = jcr->dir_bsock;
1953    BSOCK *sd  = jcr->store_bsock;
1954    char level[100];
1955
1956    jcr->setJobType(JT_VERIFY);
1957    if (sscanf(dir->msg, verifycmd, level) != 1) {
1958       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
1959       return 0;
1960    }
1961
1962    if (strcasecmp(level, "init") == 0) {
1963       jcr->setJobLevel(L_VERIFY_INIT);
1964    } else if (strcasecmp(level, "catalog") == 0){
1965       jcr->setJobLevel(L_VERIFY_CATALOG);
1966    } else if (strcasecmp(level, "volume") == 0){
1967       jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1968    } else if (strcasecmp(level, "data") == 0){
1969       jcr->setJobLevel(L_VERIFY_DATA);
1970    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1971       jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1972    } else {
1973       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
1974       return 0;
1975    }
1976
1977    dir->fsend(OKverify);
1978
1979    generate_daemon_event(jcr, "JobStart");
1980    generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
1981    generate_plugin_event(jcr, bEventStartVerifyJob);
1982
1983    Dmsg1(110, "filed>dird: %s", dir->msg);
1984
1985    switch (jcr->getJobLevel()) {
1986    case L_VERIFY_INIT:
1987    case L_VERIFY_CATALOG:
1988       do_verify(jcr);
1989       break;
1990    case L_VERIFY_VOLUME_TO_CATALOG:
1991       if (!open_sd_read_session(jcr)) {
1992          return 0;
1993       }
1994       start_dir_heartbeat(jcr);
1995       do_verify_volume(jcr);
1996       stop_dir_heartbeat(jcr);
1997       /*
1998        * Send Close session command to Storage daemon
1999        */
2000       sd->fsend(read_close, jcr->Ticket);
2001       Dmsg1(130, "filed>stored: %s", sd->msg);
2002
2003       /* ****FIXME**** check response */
2004       bget_msg(sd);                      /* get OK */
2005
2006       /* Inform Storage daemon that we are done */
2007       sd->signal(BNET_TERMINATE);
2008
2009       break;
2010    case L_VERIFY_DISK_TO_CATALOG:
2011       do_verify(jcr);
2012       break;
2013    default:
2014       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2015       return 0;
2016    }
2017
2018    dir->signal(BNET_EOD);
2019    generate_plugin_event(jcr, bEventEndVerifyJob);
2020    return 0;                          /* return and terminate command loop */
2021 }
2022
2023 #ifdef WIN32_VSS
2024 static bool vss_restore_init_callback(JCR *jcr, int init_type)
2025 {
2026    switch (init_type) {
2027    case VSS_INIT_RESTORE_AFTER_INIT:
2028       generate_plugin_event(jcr, bEventVssRestoreLoadComponentMetadata);
2029       return true;
2030    case VSS_INIT_RESTORE_AFTER_GATHER:
2031       generate_plugin_event(jcr, bEventVssRestoreSetComponentsSelected);
2032       return true;
2033    default:
2034       return false;
2035       break;
2036    }
2037 }
2038 #endif
2039
2040 /**
2041  * Do a Restore for Director
2042  *
2043  */
2044 static int restore_cmd(JCR *jcr)
2045 {
2046    BSOCK *dir = jcr->dir_bsock;
2047    BSOCK *sd = jcr->store_bsock;
2048    POOLMEM *args;
2049    bool use_regexwhere=false;
2050    int prefix_links;
2051    char replace;
2052
2053    /**
2054     * Scan WHERE (base directory for restore) from command
2055     */
2056    Dmsg0(100, "restore command\n");
2057 #if defined(WIN32_VSS)
2058
2059    /**
2060     * No need to enable VSS for restore if we do not have plugin
2061     *  data to restore 
2062     */
2063    enable_vss = jcr->job_metadata != NULL;
2064
2065    Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
2066    // capture state here, if client is backed up by multiple directors
2067    // and one enables vss and the other does not then enable_vss can change
2068    // between here and where its evaluated after the job completes.
2069    jcr->VSS = g_pVSSClient && enable_vss;
2070    if (jcr->VSS) {
2071       /* Run only one at a time */
2072       P(vss_mutex);
2073    }
2074 #endif
2075    /* Pickup where string */
2076    args = get_memory(dir->msglen+1);
2077    *args = 0;
2078
2079    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
2080       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
2081          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2082             pm_strcpy(jcr->errmsg, dir->msg);
2083             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2084             return 0;
2085          }
2086          *args = 0;
2087       }
2088       use_regexwhere = true;
2089    }
2090    /* Turn / into nothing */
2091    if (IsPathSeparator(args[0]) && args[1] == '\0') {
2092       args[0] = '\0';
2093    }
2094
2095    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2096    unbash_spaces(args);
2097
2098    if (use_regexwhere) {
2099       jcr->where_bregexp = get_bregexps(args);
2100       if (!jcr->where_bregexp) {
2101          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2102          free_pool_memory(args);
2103          return 0;
2104       }
2105    } else {
2106       jcr->where = bstrdup(args);
2107    }
2108
2109    free_pool_memory(args);
2110    jcr->replace = replace;
2111    jcr->prefix_links = prefix_links;
2112
2113    dir->fsend(OKrestore);
2114    Dmsg1(110, "filed>dird: %s", dir->msg);
2115
2116    jcr->setJobType(JT_RESTORE);
2117
2118    jcr->setJobStatus(JS_Blocked);
2119
2120    if (!open_sd_read_session(jcr)) {
2121       jcr->setJobStatus(JS_ErrorTerminated);
2122       goto bail_out;
2123    }
2124
2125    jcr->setJobStatus(JS_Running);
2126
2127    /**
2128     * Do restore of files and data
2129     */
2130    start_dir_heartbeat(jcr);
2131    generate_daemon_event(jcr, "JobStart");
2132    generate_plugin_event(jcr, bEventStartRestoreJob);
2133
2134 #if defined(WIN32_VSS)
2135    /* START VSS ON WIN32 */
2136    if (jcr->VSS) {
2137       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
2138             (WCHAR *)jcr->job_metadata)) {
2139
2140          /* inform user about writer states */
2141          int i;
2142          for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
2143             if (g_pVSSClient->GetWriterState(i) < 1) {
2144                Jmsg(jcr, M_INFO, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
2145                //jcr->JobErrors++;
2146             }
2147          }
2148       } else {
2149 /*
2150    int fd = open("C:\\eric.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777);
2151    write(fd, (WCHAR *)jcr->job_metadata, wcslen((WCHAR *)jcr->job_metadata) * sizeof(WCHAR));
2152    close(fd);
2153 */
2154          berrno be;
2155          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
2156       }
2157       free_and_null_pool_memory(jcr->job_metadata);
2158       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2159    }
2160 #endif
2161
2162    do_restore(jcr);
2163    stop_dir_heartbeat(jcr);
2164
2165    jcr->setJobStatus(JS_Terminated);
2166    if (jcr->JobStatus != JS_Terminated) {
2167       bnet_suppress_error_messages(sd, 1);
2168    }
2169
2170    /**
2171     * Send Close session command to Storage daemon
2172     */
2173    sd->fsend(read_close, jcr->Ticket);
2174    Dmsg1(100, "filed>stored: %s", sd->msg);
2175
2176    bget_msg(sd);                      /* get OK */
2177
2178    /* Inform Storage daemon that we are done */
2179    sd->signal(BNET_TERMINATE);
2180
2181 #if defined(WIN32_VSS)
2182    /* STOP VSS ON WIN32 */
2183    /* tell vss to close the restore session */
2184    Dmsg0(100, "About to call CloseRestore\n");
2185    if (jcr->VSS) {
2186       generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
2187       Dmsg0(100, "Really about to call CloseRestore\n");
2188       if (g_pVSSClient->CloseRestore()) {
2189          Dmsg0(100, "CloseRestore success\n");
2190          /* inform user about writer states */
2191          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
2192             int msg_type = M_INFO;
2193             if (g_pVSSClient->GetWriterState(i) < 1) {
2194                //msg_type = M_WARNING;
2195                //jcr->JobErrors++;
2196             }
2197             Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
2198          }
2199       }
2200       else
2201          Dmsg1(100, "CloseRestore fail - %08x\n", errno);
2202       V(vss_mutex);
2203    }
2204 #endif
2205
2206 bail_out:
2207    bfree_and_null(jcr->where);
2208
2209    if (jcr->JobErrors) {
2210       jcr->setJobStatus(JS_ErrorTerminated);
2211    }
2212
2213    Dmsg0(100, "Done in job.c\n");
2214
2215    int ret;
2216    if (jcr->multi_restore) {
2217       Dmsg0(100, OKstoreend);
2218       dir->fsend(OKstoreend);
2219       ret = 1;     /* we continue the loop, waiting for next part */
2220    } else {
2221       end_restore_cmd(jcr);
2222       ret = 0;     /* we stop here */
2223    }
2224
2225    if (job_canceled(jcr)) {
2226       ret = 0;     /* we stop here */
2227    }
2228
2229    return ret;
2230 }
2231
2232 static int end_restore_cmd(JCR *jcr) 
2233 {
2234    Dmsg0(5, "end_restore_cmd\n");
2235    generate_plugin_event(jcr, bEventEndRestoreJob);
2236    return 0;                          /* return and terminate command loop */
2237 }
2238
2239 static int open_sd_read_session(JCR *jcr)
2240 {
2241    BSOCK *sd = jcr->store_bsock;
2242
2243    if (!sd) {
2244       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2245       return 0;
2246    }
2247    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2248       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2249    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2250    /*
2251     * Open Read Session with Storage daemon
2252     */
2253    sd->fsend(read_open, "DummyVolume",
2254       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2255       jcr->StartBlock, jcr->EndBlock);
2256    Dmsg1(110, ">stored: %s", sd->msg);
2257
2258    /*
2259     * Get ticket number
2260     */
2261    if (bget_msg(sd) >= 0) {
2262       Dmsg1(110, "filed<stored: %s", sd->msg);
2263       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2264          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2265          return 0;
2266       }
2267       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2268    } else {
2269       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2270       return 0;
2271    }
2272
2273    if (!send_bootstrap_file(jcr)) {
2274       return 0;
2275    }
2276
2277    /*
2278     * Start read of data with Storage daemon
2279     */
2280    sd->fsend(read_data, jcr->Ticket);
2281    Dmsg1(110, ">stored: %s", sd->msg);
2282
2283    /*
2284     * Get OK data
2285     */
2286    if (!response(jcr, sd, OK_data, "Read Data")) {
2287       return 0;
2288    }
2289    return 1;
2290 }
2291
2292 /**
2293  * Destroy the Job Control Record and associated
2294  * resources (sockets).
2295  */
2296 static void filed_free_jcr(JCR *jcr)
2297 {
2298    if (jcr->store_bsock) {
2299       jcr->store_bsock->close();
2300    }
2301    free_bootstrap(jcr);
2302    if (jcr->last_fname) {
2303       free_pool_memory(jcr->last_fname);
2304    }
2305    free_runscripts(jcr->RunScripts);
2306    delete jcr->RunScripts;
2307
2308    if (jcr->JobId != 0)
2309       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2310
2311    return;
2312 }
2313
2314 /**
2315  * Get response from Storage daemon to a command we
2316  * sent. Check that the response is OK.
2317  *
2318  *  Returns: 0 on failure
2319  *           1 on success
2320  */
2321 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2322 {
2323    if (sd->errors) {
2324       return 0;
2325    }
2326    if (bget_msg(sd) > 0) {
2327       Dmsg0(110, sd->msg);
2328       if (strcmp(sd->msg, resp) == 0) {
2329          return 1;
2330       }
2331    }
2332    if (job_canceled(jcr)) {
2333       return 0;                       /* if canceled avoid useless error messages */
2334    }
2335    if (is_bnet_error(sd)) {
2336       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2337          cmd, bnet_strerror(sd));
2338    } else {
2339       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
2340          cmd, resp, sd->msg);
2341    }
2342    return 0;
2343 }
2344
2345 static int send_bootstrap_file(JCR *jcr)
2346 {
2347    FILE *bs;
2348    char buf[2000];
2349    BSOCK *sd = jcr->store_bsock;
2350    const char *bootstrap = "bootstrap\n";
2351    int stat = 0;
2352
2353    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
2354    if (!jcr->RestoreBootstrap) {
2355       return 1;
2356    }
2357    bs = fopen(jcr->RestoreBootstrap, "rb");
2358    if (!bs) {
2359       berrno be;
2360       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
2361          jcr->RestoreBootstrap, be.bstrerror());
2362       jcr->setJobStatus(JS_ErrorTerminated);
2363       goto bail_out;
2364    }
2365    sd->msglen = pm_strcpy(sd->msg, bootstrap);
2366    sd->send();
2367    while (fgets(buf, sizeof(buf), bs)) {
2368       sd->msglen = Mmsg(sd->msg, "%s", buf);
2369       sd->send();
2370    }
2371    sd->signal(BNET_EOD);
2372    fclose(bs);
2373    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
2374       jcr->setJobStatus(JS_ErrorTerminated);
2375       goto bail_out;
2376    }
2377    stat = 1;
2378
2379 bail_out:
2380    free_bootstrap(jcr);
2381    return stat;
2382 }