]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Implement RestoreObject for sqlite + cleanups
[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 OKBandwidth[] = "2000 OK Bandwidth\n";
161 static char OKinc[]       = "2000 OK include\n";
162 static char OKest[]       = "2000 OK estimate files=%s bytes=%s\n";
163 static char OKlevel[]     = "2000 OK level\n";
164 static char OKbackup[]    = "2000 OK backup\n";
165 static char OKbootstrap[] = "2000 OK bootstrap\n";
166 static char OKverify[]    = "2000 OK verify\n";
167 static char OKrestore[]   = "2000 OK restore\n";
168 static char OKsession[]   = "2000 OK session\n";
169 static char OKstore[]     = "2000 OK storage\n";
170 static char OKstoreend[]  = "2000 OK storage end\n";
171 static char OKjob[]       = "2000 OK Job %s (%s) %s,%s,%s";
172 static char OKsetdebug[]  = "2000 OK setdebug=%d trace=%d hangup=%d\n";
173 static char BADjob[]      = "2901 Bad Job\n";
174 static char EndJob[]      = "2800 End Job TermCode=%d JobFiles=%u ReadBytes=%s"
175                             " JobBytes=%s Errors=%u VSS=%d Encrypt=%d\n";
176 static char OKRunBefore[] = "2000 OK RunBefore\n";
177 static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
178 static char OKRunAfter[]  = "2000 OK RunAfter\n";
179 static char OKRunScript[] = "2000 OK RunScript\n";
180 static char BADcmd[]      = "2902 Bad %s\n";
181 static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
182
183
184 /* Responses received from Storage Daemon */
185 static char OK_end[]       = "3000 OK end\n";
186 static char OK_close[]     = "3000 OK close Status = %d\n";
187 static char OK_open[]      = "3000 OK open ticket = %d\n";
188 static char OK_data[]      = "3000 OK data\n";
189 static char OK_append[]    = "3000 OK append data\n";
190 static char OKSDbootstrap[]= "3000 OK bootstrap\n";
191
192
193 /* Commands sent to Storage Daemon */
194 static char append_open[]  = "append open session\n";
195 static char append_data[]  = "append data %d\n";
196 static char append_end[]   = "append end session %d\n";
197 static char append_close[] = "append close session %d\n";
198 static char read_open[]    = "read open session = %s %ld %ld %ld %ld %ld %ld\n";
199 static char read_data[]    = "read data %d\n";
200 static char read_close[]   = "read close session %d\n";
201
202 /**
203  * Accept requests from a Director
204  *
205  * NOTE! We are running as a separate thread
206  *
207  * Send output one line
208  * at a time followed by a zero length transmission.
209  *
210  * Return when the connection is terminated or there
211  * is an error.
212  *
213  * Basic task here is:
214  *   Authenticate Director (during Hello command).
215  *   Accept commands one at a time from the Director
216  *     and execute them.
217  *
218  * Concerning ClientRunBefore/After, the sequence of events
219  * is rather critical. If they are not done in the right
220  * order one can easily get FD->SD timeouts if the script
221  * runs a long time.
222  *
223  * The current sequence of events is:
224  *  1. Dir starts job with FD
225  *  2. Dir connects to SD
226  *  3. Dir connects to FD
227  *  4. FD connects to SD
228  *  5. FD gets/runs ClientRunBeforeJob and sends ClientRunAfterJob
229  *  6. Dir sends include/exclude
230  *  7. FD sends data to SD
231  *  8. SD/FD disconnects while SD despools data and attributes (optional)
232  *  9. FD runs ClientRunAfterJob
233  */
234
235 void *handle_client_request(void *dirp)
236 {
237    int i;
238    bool found, quit;
239    JCR *jcr;
240    BSOCK *dir = (BSOCK *)dirp;
241    const char jobname[12] = "*Director*";
242 // saveCWD save_cwd;
243
244    jcr = new_jcr(sizeof(JCR), filed_free_jcr); /* create JCR */
245    jcr->dir_bsock = dir;
246    jcr->ff = init_find_files();
247 // save_cwd.save(jcr);
248    jcr->start_time = time(NULL);
249    jcr->RunScripts = New(alist(10, not_owned_by_alist));
250    jcr->last_fname = get_pool_memory(PM_FNAME);
251    jcr->last_fname[0] = 0;
252    jcr->client_name = get_memory(strlen(my_name) + 1);
253    pm_strcpy(jcr->client_name, my_name);
254    bstrncpy(jcr->Job, jobname, sizeof(jobname));  /* dummy */
255    jcr->crypto.pki_sign = me->pki_sign;
256    jcr->crypto.pki_encrypt = me->pki_encrypt;
257    jcr->crypto.pki_keypair = me->pki_keypair;
258    jcr->crypto.pki_signers = me->pki_signers;
259    jcr->crypto.pki_recipients = me->pki_recipients;
260    dir->set_jcr(jcr);
261    enable_backup_privileges(NULL, 1 /* ignore_errors */);
262
263    /**********FIXME******* add command handler error code */
264
265    for (quit=false; !quit;) {
266       /* Read command */
267       if (dir->recv() < 0) {
268          break;               /* connection terminated */
269       }
270       dir->msg[dir->msglen] = 0;
271       Dmsg1(100, "<dird: %s", dir->msg);
272       found = false;
273       for (i=0; cmds[i].cmd; i++) {
274          if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
275             found = true;         /* indicate command found */
276             if (!jcr->authenticated && cmds[i].func != hello_cmd) {
277                dir->fsend(no_auth);
278                dir->signal(BNET_EOD);
279                break;
280             }
281             if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) {
282                Dmsg1(100, "Command \"%s\" is invalid.\n", cmds[i].cmd);
283                dir->fsend(invalid_cmd);
284                dir->signal(BNET_EOD);
285                break;
286             }
287             Dmsg1(100, "Executing %s command.\n", cmds[i].cmd);
288             if (!cmds[i].func(jcr)) {         /* do command */
289                quit = true;         /* error or fully terminated, get out */
290                Dmsg1(100, "Quit command loop. Canceled=%d\n", job_canceled(jcr));
291             }
292             break;
293          }
294       }
295       if (!found) {              /* command not found */
296          dir->fsend(errmsg);
297          quit = true;
298          break;
299       }
300    }
301
302    /* Inform Storage daemon that we are done */
303    if (jcr->store_bsock) {
304       jcr->store_bsock->signal(BNET_TERMINATE);
305    }
306
307    /* Run the after job */
308    run_scripts(jcr, jcr->RunScripts, "ClientAfterJob");
309
310    if (jcr->JobId) {            /* send EndJob if running a job */
311       char ed1[50], ed2[50];
312       /* Send termination status back to Dir */
313       dir->fsend(EndJob, jcr->JobStatus, jcr->JobFiles,
314                  edit_uint64(jcr->ReadBytes, ed1),
315                  edit_uint64(jcr->JobBytes, ed2), jcr->JobErrors, jcr->VSS,
316                  jcr->crypto.pki_encrypt);
317       Dmsg1(110, "End FD msg: %s\n", dir->msg);
318    }
319
320    generate_daemon_event(jcr, "JobEnd");
321    generate_plugin_event(jcr, bEventJobEnd);
322
323    dequeue_messages(jcr);             /* send any queued messages */
324
325    /* Inform Director that we are done */
326    dir->signal(BNET_TERMINATE);
327
328    free_plugins(jcr);                 /* release instantiated plugins */
329    free_and_null_pool_memory(jcr->job_metadata);
330
331    /* Clean up fileset */
332    FF_PKT *ff = jcr->ff;
333    findFILESET *fileset = ff->fileset;
334    if (fileset) {
335       int i, j, k;
336       /* Delete FileSet Include lists */
337       for (i=0; i<fileset->include_list.size(); i++) {
338          findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
339          for (j=0; j<incexe->opts_list.size(); j++) {
340             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
341             for (k=0; k<fo->regex.size(); k++) {
342                regfree((regex_t *)fo->regex.get(k));
343             }
344             for (k=0; k<fo->regexdir.size(); k++) {
345                regfree((regex_t *)fo->regexdir.get(k));
346             }
347             for (k=0; k<fo->regexfile.size(); k++) {
348                regfree((regex_t *)fo->regexfile.get(k));
349             }
350             fo->regex.destroy();
351             fo->regexdir.destroy();
352             fo->regexfile.destroy();
353             fo->wild.destroy();
354             fo->wilddir.destroy();
355             fo->wildfile.destroy();
356             fo->wildbase.destroy();
357             fo->base.destroy();
358             fo->fstype.destroy();
359             fo->drivetype.destroy();
360          }
361          incexe->opts_list.destroy();
362          incexe->name_list.destroy();
363          incexe->plugin_list.destroy();
364          if (incexe->ignoredir) {
365             free(incexe->ignoredir);
366          }
367       }
368       fileset->include_list.destroy();
369
370       /* Delete FileSet Exclude lists */
371       for (i=0; i<fileset->exclude_list.size(); i++) {
372          findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
373          for (j=0; j<incexe->opts_list.size(); j++) {
374             findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
375             fo->regex.destroy();
376             fo->regexdir.destroy();
377             fo->regexfile.destroy();
378             fo->wild.destroy();
379             fo->wilddir.destroy();
380             fo->wildfile.destroy();
381             fo->wildbase.destroy();
382             fo->base.destroy();
383             fo->fstype.destroy();
384             fo->drivetype.destroy();
385          }
386          incexe->opts_list.destroy();
387          incexe->name_list.destroy();
388          incexe->plugin_list.destroy();
389          if (incexe->ignoredir) {
390             free(incexe->ignoredir);
391          }
392       }
393       fileset->exclude_list.destroy();
394       free(fileset);
395    }
396    ff->fileset = NULL;
397    Dmsg0(100, "Calling term_find_files\n");
398    term_find_files(jcr->ff);
399 // save_cwd.restore(jcr);
400 // save_cwd.release();
401    jcr->ff = NULL;
402    Dmsg0(100, "Done with term_find_files\n");
403    free_jcr(jcr);                     /* destroy JCR record */
404    Dmsg0(100, "Done with free_jcr\n");
405    Dsm_check(100);
406    garbage_collect_memory_pool();
407    return NULL;
408 }
409
410 static int sm_dump_cmd(JCR *jcr)
411 {
412    close_memory_pool();
413    sm_dump(false, true);
414    jcr->dir_bsock->fsend("2000 sm_dump OK\n");
415    return 1;
416 }
417
418 #ifdef DEVELOPER
419 static int exit_cmd(JCR *jcr)
420 {
421    jcr->dir_bsock->fsend("2000 exit OK\n");
422    terminate_filed(0);
423    return 0;
424 }
425 #endif
426
427
428 /**
429  * Hello from Director he must identify himself and provide his
430  *  password.
431  */
432 static int hello_cmd(JCR *jcr)
433 {
434    Dmsg0(120, "Calling Authenticate\n");
435    if (!authenticate_director(jcr)) {
436       return 0;
437    }
438    Dmsg0(120, "OK Authenticate\n");
439    jcr->authenticated = true;
440    return 1;
441 }
442
443 /**
444  * Cancel a Job
445  */
446 static int cancel_cmd(JCR *jcr)
447 {
448    BSOCK *dir = jcr->dir_bsock;
449    char Job[MAX_NAME_LENGTH];
450    JCR *cjcr;
451
452    if (sscanf(dir->msg, "cancel Job=%127s", Job) == 1) {
453       if (!(cjcr=get_jcr_by_full_name(Job))) {
454          dir->fsend(_("2901 Job %s not found.\n"), Job);
455       } else {
456          generate_plugin_event(cjcr, bEventCancelCommand, NULL);
457          cjcr->setJobStatus(JS_Canceled);
458          if (cjcr->store_bsock) {
459             cjcr->store_bsock->set_timed_out();
460             cjcr->store_bsock->set_terminated();
461             cjcr->my_thread_send_signal(TIMEOUT_SIGNAL);
462          }
463          free_jcr(cjcr);
464          dir->fsend(_("2001 Job %s marked to be canceled.\n"), Job);
465       }
466    } else {
467       dir->fsend(_("2902 Error scanning cancel command.\n"));
468    }
469    dir->signal(BNET_EOD);
470    return 1;
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
1717    if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1718                 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1719      sd->destroy();
1720      sd = NULL;
1721    }
1722
1723    if (sd == NULL) {
1724       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1725           jcr->stored_addr, stored_port);
1726       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1727           jcr->stored_addr, stored_port);
1728       goto bail_out;
1729    }
1730    Dmsg0(110, "Connection OK to SD.\n");
1731
1732    jcr->store_bsock = sd;
1733
1734    sd->fsend("Hello Start Job %s\n", jcr->Job);
1735    if (!authenticate_storagedaemon(jcr)) {
1736       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1737       goto bail_out;
1738    }
1739    Dmsg0(110, "Authenticated with SD.\n");
1740
1741    /* Send OK to Director */
1742    return dir->fsend(OKstore);
1743
1744 bail_out:
1745    dir->fsend(BADcmd, "storage");
1746    return 0;
1747
1748 }
1749
1750
1751 /**
1752  * Do a backup.
1753  */
1754 static int backup_cmd(JCR *jcr)
1755 {
1756    BSOCK *dir = jcr->dir_bsock;
1757    BSOCK *sd = jcr->store_bsock;
1758    int ok = 0;
1759    int SDJobStatus;
1760    int32_t FileIndex;
1761
1762 #if defined(WIN32_VSS)
1763    // capture state here, if client is backed up by multiple directors
1764    // and one enables vss and the other does not then enable_vss can change
1765    // between here and where its evaluated after the job completes.
1766    jcr->VSS = g_pVSSClient && enable_vss;
1767    if (jcr->VSS) {
1768       /* Run only one at a time */
1769       P(vss_mutex);
1770    }
1771 #endif
1772   
1773    if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1774       jcr->JobFiles = FileIndex;
1775       Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1776    }
1777
1778    /**
1779     * Validate some options given to the backup make sense for the compiled in
1780     * options of this filed.
1781     */
1782    if (jcr->ff->flags & FO_ACL && !have_acl) {
1783       Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
1784       goto cleanup;
1785    }
1786    if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1787       Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
1788       goto cleanup;
1789    }
1790
1791    jcr->setJobStatus(JS_Blocked);
1792    jcr->setJobType(JT_BACKUP);
1793    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1794
1795    if (sd == NULL) {
1796       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1797       dir->fsend(BADcmd, "backup");
1798       goto cleanup;
1799    }
1800
1801    dir->fsend(OKbackup);
1802    Dmsg1(110, "filed>dird: %s", dir->msg);
1803
1804    /**
1805     * Send Append Open Session to Storage daemon
1806     */
1807    sd->fsend(append_open);
1808    Dmsg1(110, ">stored: %s", sd->msg);
1809    /**
1810     * Expect to receive back the Ticket number
1811     */
1812    if (bget_msg(sd) >= 0) {
1813       Dmsg1(110, "<stored: %s", sd->msg);
1814       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1815          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1816          goto cleanup;
1817       }
1818       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1819    } else {
1820       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1821       goto cleanup;
1822    }
1823
1824    /**
1825     * Send Append data command to Storage daemon
1826     */
1827    sd->fsend(append_data, jcr->Ticket);
1828    Dmsg1(110, ">stored: %s", sd->msg);
1829
1830    /**
1831     * Expect to get OK data
1832     */
1833    Dmsg1(110, "<stored: %s", sd->msg);
1834    if (!response(jcr, sd, OK_data, "Append Data")) {
1835       goto cleanup;
1836    }
1837    
1838    generate_daemon_event(jcr, "JobStart");
1839    generate_plugin_event(jcr, bEventStartBackupJob);
1840
1841 #if defined(WIN32_VSS)
1842    /* START VSS ON WIN32 */
1843    if (jcr->VSS) {      
1844       if (g_pVSSClient->InitializeForBackup(jcr)) {   
1845         generate_plugin_event(jcr, bEventVssBackupAddComponents);
1846         /* tell vss which drives to snapshot */   
1847         char szWinDriveLetters[27];
1848         *szWinDriveLetters=0;
1849         generate_plugin_event(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
1850         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1851             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1852             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1853                berrno be;
1854                Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
1855             } else {
1856                /* tell user if snapshot creation of a specific drive failed */
1857                int i;
1858                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1859                   if (islower(szWinDriveLetters[i])) {
1860                      Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed.\n"), szWinDriveLetters[i]);
1861                   }
1862                }
1863                /* inform user about writer states */
1864                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {               
1865                   if (g_pVSSClient->GetWriterState(i) < 1) {
1866                      Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1867                   }                            
1868                }
1869             }
1870         } else {
1871             Jmsg(jcr, M_FATAL, 0, _("No drive letters found for generating VSS snapshots.\n"));
1872         }
1873       } else {
1874          berrno be;
1875          Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly. ERR=%s\n"), be.bstrerror());
1876       } 
1877       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
1878    }
1879 #endif
1880
1881    /**
1882     * Send Files to Storage daemon
1883     */
1884    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1885    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1886       jcr->setJobStatus(JS_ErrorTerminated);
1887       bnet_suppress_error_messages(sd, 1);
1888       Dmsg0(110, "Error in blast_data.\n");
1889    } else {
1890       jcr->setJobStatus(JS_Terminated);
1891       /* Note, the above set status will not override an error */
1892       if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
1893          bnet_suppress_error_messages(sd, 1);
1894          goto cleanup;                /* bail out now */
1895       }
1896       /**
1897        * Expect to get response to append_data from Storage daemon
1898        */
1899       if (!response(jcr, sd, OK_append, "Append Data")) {
1900          jcr->setJobStatus(JS_ErrorTerminated);
1901          goto cleanup;
1902       }
1903
1904       /**
1905        * Send Append End Data to Storage daemon
1906        */
1907       sd->fsend(append_end, jcr->Ticket);
1908       /* Get end OK */
1909       if (!response(jcr, sd, OK_end, "Append End")) {
1910          jcr->setJobStatus(JS_ErrorTerminated);
1911          goto cleanup;
1912       }
1913
1914       /**
1915        * Send Append Close to Storage daemon
1916        */
1917       sd->fsend(append_close, jcr->Ticket);
1918       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1919          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1920             ok = 1;
1921             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1922          }
1923       }
1924       if (!ok) {
1925          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1926          goto cleanup;
1927       }
1928       if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings)) {
1929          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1930             SDJobStatus);
1931       }
1932    }
1933
1934 cleanup:
1935 #if defined(WIN32_VSS)
1936    if (jcr->VSS) {
1937       Win32ConvCleanupCache();
1938       g_pVSSClient->DestroyWriterInfo();
1939       V(vss_mutex);
1940    }
1941 #endif
1942
1943    generate_plugin_event(jcr, bEventEndBackupJob);
1944    return 0;                          /* return and stop command loop */
1945 }
1946
1947 /**
1948  * Do a Verify for Director
1949  *
1950  */
1951 static int verify_cmd(JCR *jcr)
1952 {
1953    BSOCK *dir = jcr->dir_bsock;
1954    BSOCK *sd  = jcr->store_bsock;
1955    char level[100];
1956
1957    jcr->setJobType(JT_VERIFY);
1958    if (sscanf(dir->msg, verifycmd, level) != 1) {
1959       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
1960       return 0;
1961    }
1962
1963    if (strcasecmp(level, "init") == 0) {
1964       jcr->setJobLevel(L_VERIFY_INIT);
1965    } else if (strcasecmp(level, "catalog") == 0){
1966       jcr->setJobLevel(L_VERIFY_CATALOG);
1967    } else if (strcasecmp(level, "volume") == 0){
1968       jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1969    } else if (strcasecmp(level, "data") == 0){
1970       jcr->setJobLevel(L_VERIFY_DATA);
1971    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1972       jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1973    } else {
1974       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
1975       return 0;
1976    }
1977
1978    dir->fsend(OKverify);
1979
1980    generate_daemon_event(jcr, "JobStart");
1981    generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
1982    generate_plugin_event(jcr, bEventStartVerifyJob);
1983
1984    Dmsg1(110, "filed>dird: %s", dir->msg);
1985
1986    switch (jcr->getJobLevel()) {
1987    case L_VERIFY_INIT:
1988    case L_VERIFY_CATALOG:
1989       do_verify(jcr);
1990       break;
1991    case L_VERIFY_VOLUME_TO_CATALOG:
1992       if (!open_sd_read_session(jcr)) {
1993          return 0;
1994       }
1995       start_dir_heartbeat(jcr);
1996       do_verify_volume(jcr);
1997       stop_dir_heartbeat(jcr);
1998       /*
1999        * Send Close session command to Storage daemon
2000        */
2001       sd->fsend(read_close, jcr->Ticket);
2002       Dmsg1(130, "filed>stored: %s", sd->msg);
2003
2004       /* ****FIXME**** check response */
2005       bget_msg(sd);                      /* get OK */
2006
2007       /* Inform Storage daemon that we are done */
2008       sd->signal(BNET_TERMINATE);
2009
2010       break;
2011    case L_VERIFY_DISK_TO_CATALOG:
2012       do_verify(jcr);
2013       break;
2014    default:
2015       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2016       return 0;
2017    }
2018
2019    dir->signal(BNET_EOD);
2020    generate_plugin_event(jcr, bEventEndVerifyJob);
2021    return 0;                          /* return and terminate command loop */
2022 }
2023
2024 #ifdef WIN32_VSS
2025 static bool vss_restore_init_callback(JCR *jcr, int init_type)
2026 {
2027    switch (init_type) {
2028    case VSS_INIT_RESTORE_AFTER_INIT:
2029       generate_plugin_event(jcr, bEventVssRestoreLoadComponentMetadata);
2030       return true;
2031    case VSS_INIT_RESTORE_AFTER_GATHER:
2032       generate_plugin_event(jcr, bEventVssRestoreSetComponentsSelected);
2033       return true;
2034    default:
2035       return false;
2036       break;
2037    }
2038 }
2039 #endif
2040
2041 /**
2042  * Do a Restore for Director
2043  *
2044  */
2045 static int restore_cmd(JCR *jcr)
2046 {
2047    BSOCK *dir = jcr->dir_bsock;
2048    BSOCK *sd = jcr->store_bsock;
2049    POOLMEM *args;
2050    bool use_regexwhere=false;
2051    int prefix_links;
2052    char replace;
2053
2054    /**
2055     * Scan WHERE (base directory for restore) from command
2056     */
2057    Dmsg0(100, "restore command\n");
2058 #if defined(WIN32_VSS)
2059
2060    /**
2061     * No need to enable VSS for restore if we do not have plugin
2062     *  data to restore 
2063     */
2064    enable_vss = jcr->job_metadata != NULL;
2065
2066    Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
2067    // capture state here, if client is backed up by multiple directors
2068    // and one enables vss and the other does not then enable_vss can change
2069    // between here and where its evaluated after the job completes.
2070    jcr->VSS = g_pVSSClient && enable_vss;
2071    if (jcr->VSS) {
2072       /* Run only one at a time */
2073       P(vss_mutex);
2074    }
2075 #endif
2076    /* Pickup where string */
2077    args = get_memory(dir->msglen+1);
2078    *args = 0;
2079
2080    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
2081       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
2082          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2083             pm_strcpy(jcr->errmsg, dir->msg);
2084             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2085             return 0;
2086          }
2087          *args = 0;
2088       }
2089       use_regexwhere = true;
2090    }
2091    /* Turn / into nothing */
2092    if (IsPathSeparator(args[0]) && args[1] == '\0') {
2093       args[0] = '\0';
2094    }
2095
2096    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2097    unbash_spaces(args);
2098
2099    if (use_regexwhere) {
2100       jcr->where_bregexp = get_bregexps(args);
2101       if (!jcr->where_bregexp) {
2102          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2103          free_pool_memory(args);
2104          return 0;
2105       }
2106    } else {
2107       jcr->where = bstrdup(args);
2108    }
2109
2110    free_pool_memory(args);
2111    jcr->replace = replace;
2112    jcr->prefix_links = prefix_links;
2113
2114    dir->fsend(OKrestore);
2115    Dmsg1(110, "filed>dird: %s", dir->msg);
2116
2117    jcr->setJobType(JT_RESTORE);
2118
2119    jcr->setJobStatus(JS_Blocked);
2120
2121    if (!open_sd_read_session(jcr)) {
2122       jcr->setJobStatus(JS_ErrorTerminated);
2123       goto bail_out;
2124    }
2125
2126    jcr->setJobStatus(JS_Running);
2127
2128    /**
2129     * Do restore of files and data
2130     */
2131    start_dir_heartbeat(jcr);
2132    generate_daemon_event(jcr, "JobStart");
2133    generate_plugin_event(jcr, bEventStartRestoreJob);
2134
2135 #if defined(WIN32_VSS)
2136    /* START VSS ON WIN32 */
2137    if (jcr->VSS) {
2138       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
2139             (WCHAR *)jcr->job_metadata)) {
2140
2141          /* inform user about writer states */
2142          int i;
2143          for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
2144             if (g_pVSSClient->GetWriterState(i) < 1) {
2145                Jmsg(jcr, M_INFO, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
2146                //jcr->JobErrors++;
2147             }
2148          }
2149       } else {
2150 /*
2151    int fd = open("C:\\eric.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777);
2152    write(fd, (WCHAR *)jcr->job_metadata, wcslen((WCHAR *)jcr->job_metadata) * sizeof(WCHAR));
2153    close(fd);
2154 */
2155          berrno be;
2156          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
2157       }
2158       free_and_null_pool_memory(jcr->job_metadata);
2159       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2160    }
2161 #endif
2162
2163    do_restore(jcr);
2164    stop_dir_heartbeat(jcr);
2165
2166    jcr->setJobStatus(JS_Terminated);
2167    if (jcr->JobStatus != JS_Terminated) {
2168       bnet_suppress_error_messages(sd, 1);
2169    }
2170
2171    /**
2172     * Send Close session command to Storage daemon
2173     */
2174    sd->fsend(read_close, jcr->Ticket);
2175    Dmsg1(100, "filed>stored: %s", sd->msg);
2176
2177    bget_msg(sd);                      /* get OK */
2178
2179    /* Inform Storage daemon that we are done */
2180    sd->signal(BNET_TERMINATE);
2181
2182 #if defined(WIN32_VSS)
2183    /* STOP VSS ON WIN32 */
2184    /* tell vss to close the restore session */
2185    Dmsg0(100, "About to call CloseRestore\n");
2186    if (jcr->VSS) {
2187       generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
2188       Dmsg0(100, "Really about to call CloseRestore\n");
2189       if (g_pVSSClient->CloseRestore()) {
2190          Dmsg0(100, "CloseRestore success\n");
2191          /* inform user about writer states */
2192          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
2193             int msg_type = M_INFO;
2194             if (g_pVSSClient->GetWriterState(i) < 1) {
2195                //msg_type = M_WARNING;
2196                //jcr->JobErrors++;
2197             }
2198             Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
2199          }
2200       }
2201       else
2202          Dmsg1(100, "CloseRestore fail - %08x\n", errno);
2203       V(vss_mutex);
2204    }
2205 #endif
2206
2207 bail_out:
2208    bfree_and_null(jcr->where);
2209
2210    if (jcr->JobErrors) {
2211       jcr->setJobStatus(JS_ErrorTerminated);
2212    }
2213
2214    Dmsg0(100, "Done in job.c\n");
2215
2216    int ret;
2217    if (jcr->multi_restore) {
2218       Dmsg0(100, OKstoreend);
2219       dir->fsend(OKstoreend);
2220       ret = 1;     /* we continue the loop, waiting for next part */
2221    } else {
2222       end_restore_cmd(jcr);
2223       ret = 0;     /* we stop here */
2224    }
2225
2226    if (job_canceled(jcr)) {
2227       ret = 0;     /* we stop here */
2228    }
2229
2230    return ret;
2231 }
2232
2233 static int end_restore_cmd(JCR *jcr) 
2234 {
2235    Dmsg0(5, "end_restore_cmd\n");
2236    generate_plugin_event(jcr, bEventEndRestoreJob);
2237    return 0;                          /* return and terminate command loop */
2238 }
2239
2240 static int open_sd_read_session(JCR *jcr)
2241 {
2242    BSOCK *sd = jcr->store_bsock;
2243
2244    if (!sd) {
2245       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2246       return 0;
2247    }
2248    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2249       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2250    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2251    /*
2252     * Open Read Session with Storage daemon
2253     */
2254    sd->fsend(read_open, "DummyVolume",
2255       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2256       jcr->StartBlock, jcr->EndBlock);
2257    Dmsg1(110, ">stored: %s", sd->msg);
2258
2259    /*
2260     * Get ticket number
2261     */
2262    if (bget_msg(sd) >= 0) {
2263       Dmsg1(110, "filed<stored: %s", sd->msg);
2264       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2265          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2266          return 0;
2267       }
2268       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2269    } else {
2270       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2271       return 0;
2272    }
2273
2274    if (!send_bootstrap_file(jcr)) {
2275       return 0;
2276    }
2277
2278    /*
2279     * Start read of data with Storage daemon
2280     */
2281    sd->fsend(read_data, jcr->Ticket);
2282    Dmsg1(110, ">stored: %s", sd->msg);
2283
2284    /*
2285     * Get OK data
2286     */
2287    if (!response(jcr, sd, OK_data, "Read Data")) {
2288       return 0;
2289    }
2290    return 1;
2291 }
2292
2293 /**
2294  * Destroy the Job Control Record and associated
2295  * resources (sockets).
2296  */
2297 static void filed_free_jcr(JCR *jcr)
2298 {
2299    if (jcr->store_bsock) {
2300       jcr->store_bsock->close();
2301    }
2302    free_bootstrap(jcr);
2303    if (jcr->last_fname) {
2304       free_pool_memory(jcr->last_fname);
2305    }
2306    free_runscripts(jcr->RunScripts);
2307    delete jcr->RunScripts;
2308
2309    if (jcr->JobId != 0)
2310       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2311
2312    return;
2313 }
2314
2315 /**
2316  * Get response from Storage daemon to a command we
2317  * sent. Check that the response is OK.
2318  *
2319  *  Returns: 0 on failure
2320  *           1 on success
2321  */
2322 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2323 {
2324    if (sd->errors) {
2325       return 0;
2326    }
2327    if (bget_msg(sd) > 0) {
2328       Dmsg0(110, sd->msg);
2329       if (strcmp(sd->msg, resp) == 0) {
2330          return 1;
2331       }
2332    }
2333    if (job_canceled(jcr)) {
2334       return 0;                       /* if canceled avoid useless error messages */
2335    }
2336    if (is_bnet_error(sd)) {
2337       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2338          cmd, bnet_strerror(sd));
2339    } else {
2340       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
2341          cmd, resp, sd->msg);
2342    }
2343    return 0;
2344 }
2345
2346 static int send_bootstrap_file(JCR *jcr)
2347 {
2348    FILE *bs;
2349    char buf[2000];
2350    BSOCK *sd = jcr->store_bsock;
2351    const char *bootstrap = "bootstrap\n";
2352    int stat = 0;
2353
2354    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
2355    if (!jcr->RestoreBootstrap) {
2356       return 1;
2357    }
2358    bs = fopen(jcr->RestoreBootstrap, "rb");
2359    if (!bs) {
2360       berrno be;
2361       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
2362          jcr->RestoreBootstrap, be.bstrerror());
2363       jcr->setJobStatus(JS_ErrorTerminated);
2364       goto bail_out;
2365    }
2366    sd->msglen = pm_strcpy(sd->msg, bootstrap);
2367    sd->send();
2368    while (fgets(buf, sizeof(buf), bs)) {
2369       sd->msglen = Mmsg(sd->msg, "%s", buf);
2370       sd->send();
2371    }
2372    sd->signal(BNET_EOD);
2373    fclose(bs);
2374    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
2375       jcr->setJobStatus(JS_ErrorTerminated);
2376       goto bail_out;
2377    }
2378    stat = 1;
2379
2380 bail_out:
2381    free_bootstrap(jcr);
2382    return stat;
2383 }