]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Fix bug #1751 Make duplicate checking somewhat less naiv.
[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 #include "ch.h"
38
39 #if defined(WIN32_VSS)
40 #include "vss.h"
41
42 static pthread_mutex_t vss_mutex = PTHREAD_MUTEX_INITIALIZER;
43 static int enable_vss = 0;
44 #endif
45
46 /**
47  * As Windows saves ACLs as part of the standard backup stream
48  * we just pretend here that is has implicit acl support.
49  */
50 #if defined(HAVE_ACL) || defined(HAVE_WIN32)
51 const bool have_acl = true;
52 #else
53 const bool have_acl = false;
54 #endif
55
56 #if defined(HAVE_XATTR)
57 const bool have_xattr = true;
58 #else
59 const bool have_xattr = false;
60 #endif
61
62 extern CLIENT *me;                    /* our client resource */
63
64 /* Imported functions */
65 extern int status_cmd(JCR *jcr);
66 extern int qstatus_cmd(JCR *jcr);
67 extern int accurate_cmd(JCR *jcr);
68
69 /* Forward referenced functions */
70 static int backup_cmd(JCR *jcr);
71 static int bootstrap_cmd(JCR *jcr);
72 static int cancel_cmd(JCR *jcr);
73 static int setdebug_cmd(JCR *jcr);
74 static int estimate_cmd(JCR *jcr);
75 static int hello_cmd(JCR *jcr);
76 static int job_cmd(JCR *jcr);
77 static int fileset_cmd(JCR *jcr);
78 static int level_cmd(JCR *jcr);
79 static int verify_cmd(JCR *jcr);
80 static int restore_cmd(JCR *jcr);
81 static int end_restore_cmd(JCR *jcr);
82 static int storage_cmd(JCR *jcr);
83 static int session_cmd(JCR *jcr);
84 static int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd);
85 static void filed_free_jcr(JCR *jcr);
86 static int open_sd_read_session(JCR *jcr);
87 static int send_bootstrap_file(JCR *jcr);
88 static int runscript_cmd(JCR *jcr);
89 static int runbefore_cmd(JCR *jcr);
90 static int runafter_cmd(JCR *jcr);
91 static int runbeforenow_cmd(JCR *jcr);
92 static int restore_object_cmd(JCR *jcr);
93 static int set_options(findFOPTS *fo, const char *opts);
94 static void set_storage_auth_key(JCR *jcr, char *key);
95 static int sm_dump_cmd(JCR *jcr);
96 #ifdef DEVELOPER
97 static int exit_cmd(JCR *jcr);
98 #endif
99
100 /* Exported functions */
101
102 struct s_cmds {
103    const char *cmd;
104    int (*func)(JCR *);
105    int monitoraccess; /* specify if monitors have access to this function */
106 };
107
108 /**
109  * The following are the recognized commands from the Director.
110  */
111 static struct s_cmds cmds[] = {
112    {"backup",       backup_cmd,    0},
113    {"cancel",       cancel_cmd,    0},
114    {"setdebug=",    setdebug_cmd,  0},
115    {"estimate",     estimate_cmd,  0},
116    {"Hello",        hello_cmd,     1},
117    {"fileset",      fileset_cmd,   0},
118    {"JobId=",       job_cmd,       0},
119    {"level = ",     level_cmd,     0},
120    {"restore ",     restore_cmd,   0},
121    {"endrestore",   end_restore_cmd, 0},
122    {"session",      session_cmd,   0},
123    {"status",       status_cmd,    1},
124    {".status",      qstatus_cmd,   1},
125    {"storage ",     storage_cmd,   0},
126    {"verify",       verify_cmd,    0},
127    {"bootstrap",    bootstrap_cmd, 0},
128    {"RunBeforeNow", runbeforenow_cmd, 0},
129    {"RunBeforeJob", runbefore_cmd, 0},
130    {"RunAfterJob",  runafter_cmd,  0},
131    {"Run",          runscript_cmd, 0},
132    {"accurate",     accurate_cmd,  0},
133    {"restoreobject", restore_object_cmd, 0},
134    {"sm_dump",      sm_dump_cmd, 0},
135 #ifdef DEVELOPER
136    {"exit",         exit_cmd, 0},
137 #endif
138    {NULL,       NULL}                  /* list terminator */
139 };
140
141 /* Commands received from director that need scanning */
142 static char jobcmd[]      = "JobId=%d Job=%127s SDid=%d SDtime=%d Authorization=%100s";
143 static char storaddr[]    = "storage address=%s port=%d ssl=%d Authorization=%100s";
144 static char storaddr_v1[] = "storage address=%s port=%d ssl=%d";
145 static char sessioncmd[]  = "session %127s %ld %ld %ld %ld %ld %ld\n";
146 static char restorecmd[]  = "restore replace=%c prelinks=%d where=%s\n";
147 static char restorecmd1[] = "restore replace=%c prelinks=%d where=\n";
148 static char restorecmdR[] = "restore replace=%c prelinks=%d regexwhere=%s\n";
149 static char restoreobjcmd[] = "restoreobject JobId=%u %d,%d,%d,%d,%d,%d\n";
150 static char endrestoreobjectcmd[] = "restoreobject end\n";
151 static char verifycmd[]   = "verify level=%30s";
152 static char estimatecmd[] = "estimate listing=%d";
153 static char runbefore[]   = "RunBeforeJob %s";
154 static char runafter[]    = "RunAfterJob %s";
155 static char runscript[]   = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
156
157 /* Responses sent to Director */
158 static char errmsg[]      = "2999 Invalid command\n";
159 static char no_auth[]     = "2998 No Authorization\n";
160 static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\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':                 /* compression */
1390          p++;                   /* skip Z */
1391          if (*p >= '0' && *p <= '9') {
1392             fo->flags |= FO_COMPRESS;
1393             fo->Compress_algo = COMPRESS_GZIP;
1394             fo->Compress_level = *p - '0';
1395          }
1396          else if (*p == 'o') {
1397             fo->flags |= FO_COMPRESS;
1398             fo->Compress_algo = COMPRESS_LZO1X;
1399             fo->Compress_level = 1; /* not used with LZO */
1400          }
1401          break;
1402       case 'K':
1403          fo->flags |= FO_NOATIME;
1404          break;
1405       case 'c':
1406          fo->flags |= FO_CHKCHANGES;
1407          break;
1408       case 'N':
1409          fo->flags |= FO_HONOR_NODUMP;
1410          break;
1411       case 'X':
1412          fo->flags |= FO_XATTR;
1413          break;
1414       default:
1415          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1416          break;
1417       }
1418    }
1419    return state_options;
1420 }
1421
1422
1423 /**
1424  * Director is passing his Fileset
1425  */
1426 static int fileset_cmd(JCR *jcr)
1427 {
1428    BSOCK *dir = jcr->dir_bsock;
1429    int rtnstat;
1430
1431 #if defined(WIN32_VSS)
1432    int vss = 0;
1433
1434    sscanf(dir->msg, "fileset vss=%d", &vss);
1435    enable_vss = vss;
1436 #endif
1437
1438    if (!init_fileset(jcr)) {
1439       return 0;
1440    }
1441    while (dir->recv() >= 0) {
1442       strip_trailing_junk(dir->msg);
1443       Dmsg1(500, "Fileset: %s\n", dir->msg);
1444       add_fileset(jcr, dir->msg);
1445    }
1446    if (!term_fileset(jcr)) {
1447       return 0;
1448    }
1449    rtnstat = dir->fsend(OKinc);
1450    generate_plugin_event(jcr, bEventEndFileSet);
1451    return rtnstat;
1452 }
1453
1454 static void free_bootstrap(JCR *jcr)
1455 {
1456    if (jcr->RestoreBootstrap) {
1457       unlink(jcr->RestoreBootstrap);
1458       free_pool_memory(jcr->RestoreBootstrap);
1459       jcr->RestoreBootstrap = NULL;
1460    }
1461 }
1462
1463
1464 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1465 static uint32_t bsr_uniq = 0;
1466
1467 /**
1468  * The Director sends us the bootstrap file, which
1469  *   we will in turn pass to the SD.
1470  *   Deprecated.  The bsr is now sent directly from the
1471  *   Director to the SD.
1472  */
1473 static int bootstrap_cmd(JCR *jcr)
1474 {
1475    BSOCK *dir = jcr->dir_bsock;
1476    POOLMEM *fname = get_pool_memory(PM_FNAME);
1477    FILE *bs;
1478
1479    free_bootstrap(jcr);
1480    P(bsr_mutex);
1481    bsr_uniq++;
1482    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1483       jcr->Job, bsr_uniq);
1484    V(bsr_mutex);
1485    Dmsg1(400, "bootstrap=%s\n", fname);
1486    jcr->RestoreBootstrap = fname;
1487    bs = fopen(fname, "a+b");           /* create file */
1488    if (!bs) {
1489       berrno be;
1490       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1491          jcr->RestoreBootstrap, be.bstrerror());
1492       /*
1493        * Suck up what he is sending to us so that he will then
1494        *   read our error message.
1495        */
1496       while (dir->recv() >= 0)
1497         {  }
1498       free_bootstrap(jcr);
1499       jcr->setJobStatus(JS_ErrorTerminated);
1500       return 0;
1501    }
1502
1503    while (dir->recv() >= 0) {
1504        Dmsg1(200, "filed<dird: bootstrap: %s", dir->msg);
1505        fputs(dir->msg, bs);
1506    }
1507    fclose(bs);
1508    /*
1509     * Note, do not free the bootstrap yet -- it needs to be 
1510     *  sent to the SD 
1511     */
1512    return dir->fsend(OKbootstrap);
1513 }
1514
1515
1516 /**
1517  * Get backup level from Director
1518  *
1519  */
1520 static int level_cmd(JCR *jcr)
1521 {
1522    BSOCK *dir = jcr->dir_bsock;
1523    POOLMEM *level, *buf = NULL;
1524    int mtime_only;
1525
1526    level = get_memory(dir->msglen+1);
1527    Dmsg1(10, "level_cmd: %s", dir->msg);
1528
1529    /* keep compatibility with older directors */
1530    if (strstr(dir->msg, "accurate")) {
1531       jcr->accurate = true;
1532    }
1533    if (strstr(dir->msg, "rerunning")) {
1534       jcr->rerunning = true;
1535    }
1536    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1537       goto bail_out;
1538    }
1539    /* Base backup requested? */
1540    if (strcmp(level, "base") == 0) {
1541       jcr->setJobLevel(L_BASE);
1542    /* Full backup requested? */
1543    } else if (strcmp(level, "full") == 0) {
1544       jcr->setJobLevel(L_FULL);
1545    } else if (strstr(level, "differential")) {
1546       jcr->setJobLevel(L_DIFFERENTIAL);
1547       free_memory(level);
1548       return 1;
1549    } else if (strstr(level, "incremental")) {
1550       jcr->setJobLevel(L_INCREMENTAL);
1551       free_memory(level);
1552       return 1;
1553    /*
1554     * We get his UTC since time, then sync the clocks and correct it
1555     *   to agree with our clock.
1556     */
1557    } else if (strcmp(level, "since_utime") == 0) {
1558       buf = get_memory(dir->msglen+1);
1559       utime_t since_time, adj;
1560       btime_t his_time, bt_start, rt=0, bt_adj=0;
1561       if (jcr->getJobLevel() == L_NONE) {
1562          jcr->setJobLevel(L_SINCE);     /* if no other job level set, do it now */
1563       }
1564       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1565                  buf, &mtime_only) != 2) {
1566          goto bail_out;
1567       }
1568       since_time = str_to_uint64(buf);  /* this is the since time */
1569       Dmsg1(100, "since_time=%lld\n", since_time);
1570       char ed1[50], ed2[50];
1571       /*
1572        * Sync clocks by polling him for the time. We take
1573        *   10 samples of his time throwing out the first two.
1574        */
1575       for (int i=0; i<10; i++) {
1576          bt_start = get_current_btime();
1577          dir->signal(BNET_BTIME);     /* poll for time */
1578          if (dir->recv() <= 0) {      /* get response */
1579             goto bail_out;
1580          }
1581          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1582             goto bail_out;
1583          }
1584          if (i < 2) {                 /* toss first two results */
1585             continue;
1586          }
1587          his_time = str_to_uint64(buf);
1588          rt = get_current_btime() - bt_start; /* compute round trip time */
1589          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1590                edit_uint64(bt_start, ed2));
1591          bt_adj +=  bt_start - his_time - rt/2;
1592          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1593       }
1594
1595       bt_adj = bt_adj / 8;            /* compute average time */
1596       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1597       adj = btime_to_utime(bt_adj);
1598       since_time += adj;              /* adjust for clock difference */
1599       /* Don't notify if time within 3 seconds */
1600       if (adj > 3 || adj < -3) {
1601          int type;
1602          if (adj > 600 || adj < -600) {
1603             type = M_WARNING;
1604          } else {
1605             type = M_INFO;
1606          }
1607          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1608       }
1609       dir->signal(BNET_EOD);
1610
1611       Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1612       jcr->incremental = 1;           /* set incremental or decremental backup */
1613       jcr->mtime = since_time;        /* set since time */
1614       generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1615    } else {
1616       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1617       free_memory(level);
1618       return 0;
1619    }
1620    free_memory(level);
1621    if (buf) {
1622       free_memory(buf);
1623    }
1624    generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1625    return dir->fsend(OKlevel);
1626
1627 bail_out:
1628    pm_strcpy(jcr->errmsg, dir->msg);
1629    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1630    free_memory(level);
1631    if (buf) {
1632       free_memory(buf);
1633    }
1634    return 0;
1635 }
1636
1637 /**
1638  * Get session parameters from Director -- this is for a Restore command
1639  *   This is deprecated. It is now passed via the bsr.
1640  */
1641 static int session_cmd(JCR *jcr)
1642 {
1643    BSOCK *dir = jcr->dir_bsock;
1644
1645    Dmsg1(100, "SessionCmd: %s", dir->msg);
1646    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1647               &jcr->VolSessionId, &jcr->VolSessionTime,
1648               &jcr->StartFile, &jcr->EndFile,
1649               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1650       pm_strcpy(jcr->errmsg, dir->msg);
1651       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1652       return 0;
1653    }
1654
1655    return dir->fsend(OKsession);
1656 }
1657
1658 static void set_storage_auth_key(JCR *jcr, char *key)
1659 {
1660    /* if no key don't update anything */
1661    if (!*key) {                
1662       return;
1663    }
1664
1665    /**
1666     * We can be contacting multiple storage daemons.
1667     * So, make sure that any old jcr->store_bsock is cleaned up. 
1668     */
1669    if (jcr->store_bsock) {
1670       jcr->store_bsock->destroy();
1671       jcr->store_bsock = NULL;
1672    }
1673
1674    /**
1675     * We can be contacting multiple storage daemons.
1676     *   So, make sure that any old jcr->sd_auth_key is cleaned up. 
1677     */
1678    if (jcr->sd_auth_key) {
1679       /*
1680        * If we already have a Authorization key, director can do multi
1681        * storage restore
1682        */
1683       Dmsg0(5, "set multi_restore=true\n");
1684       jcr->multi_restore = true;
1685       bfree(jcr->sd_auth_key);
1686    }
1687
1688    jcr->sd_auth_key = bstrdup(key);
1689    Dmsg0(5, "set sd auth key\n");
1690 }
1691
1692 /**
1693  * Get address of storage daemon from Director
1694  *
1695  */
1696 static int storage_cmd(JCR *jcr)
1697 {
1698    int stored_port;                /* storage daemon port */
1699    int enable_ssl;                 /* enable ssl to sd */
1700    POOL_MEM sd_auth_key(PM_MESSAGE);
1701    BSOCK *dir = jcr->dir_bsock;
1702    BSOCK *sd = new_bsock();        /* storage daemon bsock */
1703
1704
1705    Dmsg1(100, "StorageCmd: %s", dir->msg);
1706    sd_auth_key.check_size(dir->msglen);
1707    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, 
1708               &enable_ssl, sd_auth_key.c_str()) != 4) {
1709       if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
1710                  &stored_port, &enable_ssl) != 3) {
1711          pm_strcpy(jcr->errmsg, dir->msg);
1712          Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1713          goto bail_out;
1714       }
1715    }
1716
1717    set_storage_auth_key(jcr, sd_auth_key.c_str());
1718
1719    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, 
1720          enable_ssl);
1721    /* Open command communications with Storage daemon */
1722    /* Try to connect for 1 hour at 10 second intervals */
1723
1724    sd->set_source_address(me->FDsrc_addr);
1725 <<<<<<< HEAD
1726 =======
1727
1728 >>>>>>> caaa5db... Implement RestoreObject for sqlite + cleanups
1729    if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1730                 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1731      sd->destroy();
1732      sd = NULL;
1733    }
1734
1735    if (sd == NULL) {
1736       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1737           jcr->stored_addr, stored_port);
1738       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1739           jcr->stored_addr, stored_port);
1740       goto bail_out;
1741    }
1742    Dmsg0(110, "Connection OK to SD.\n");
1743
1744    jcr->store_bsock = sd;
1745
1746    sd->fsend("Hello Start Job %s\n", jcr->Job);
1747    if (!authenticate_storagedaemon(jcr)) {
1748       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1749       goto bail_out;
1750    }
1751    Dmsg0(110, "Authenticated with SD.\n");
1752
1753    /* Send OK to Director */
1754    return dir->fsend(OKstore);
1755
1756 bail_out:
1757    dir->fsend(BADcmd, "storage");
1758    return 0;
1759
1760 }
1761
1762
1763 /**
1764  * Do a backup.
1765  */
1766 static int backup_cmd(JCR *jcr)
1767 {
1768    BSOCK *dir = jcr->dir_bsock;
1769    BSOCK *sd = jcr->store_bsock;
1770    int ok = 0;
1771    int SDJobStatus;
1772    int32_t FileIndex;
1773
1774 #if defined(WIN32_VSS)
1775    // capture state here, if client is backed up by multiple directors
1776    // and one enables vss and the other does not then enable_vss can change
1777    // between here and where its evaluated after the job completes.
1778    jcr->VSS = g_pVSSClient && enable_vss;
1779    if (jcr->VSS) {
1780       /* Run only one at a time */
1781       P(vss_mutex);
1782    }
1783 #endif
1784   
1785    if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1786       jcr->JobFiles = FileIndex;
1787       Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1788    }
1789
1790    /**
1791     * Validate some options given to the backup make sense for the compiled in
1792     * options of this filed.
1793     */
1794    if (jcr->ff->flags & FO_ACL && !have_acl) {
1795       Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
1796       goto cleanup;
1797    }
1798    if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1799       Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
1800       goto cleanup;
1801    }
1802
1803    jcr->setJobStatus(JS_Blocked);
1804    jcr->setJobType(JT_BACKUP);
1805    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1806
1807    if (sd == NULL) {
1808       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1809       dir->fsend(BADcmd, "backup");
1810       goto cleanup;
1811    }
1812
1813    dir->fsend(OKbackup);
1814    Dmsg1(110, "filed>dird: %s", dir->msg);
1815
1816    /**
1817     * Send Append Open Session to Storage daemon
1818     */
1819    sd->fsend(append_open);
1820    Dmsg1(110, ">stored: %s", sd->msg);
1821    /**
1822     * Expect to receive back the Ticket number
1823     */
1824    if (bget_msg(sd) >= 0) {
1825       Dmsg1(110, "<stored: %s", sd->msg);
1826       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1827          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1828          goto cleanup;
1829       }
1830       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1831    } else {
1832       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1833       goto cleanup;
1834    }
1835
1836    /**
1837     * Send Append data command to Storage daemon
1838     */
1839    sd->fsend(append_data, jcr->Ticket);
1840    Dmsg1(110, ">stored: %s", sd->msg);
1841
1842    /**
1843     * Expect to get OK data
1844     */
1845    Dmsg1(110, "<stored: %s", sd->msg);
1846    if (!response(jcr, sd, OK_data, "Append Data")) {
1847       goto cleanup;
1848    }
1849    
1850    generate_daemon_event(jcr, "JobStart");
1851    generate_plugin_event(jcr, bEventStartBackupJob);
1852
1853 #if defined(WIN32_VSS)
1854    /* START VSS ON WIN32 */
1855    if (jcr->VSS) {      
1856       if (g_pVSSClient->InitializeForBackup(jcr)) {   
1857         generate_plugin_event(jcr, bEventVssBackupAddComponents);
1858         /* tell vss which drives to snapshot */   
1859         char szWinDriveLetters[27];
1860         *szWinDriveLetters=0;
1861         generate_plugin_event(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
1862         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1863             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1864             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1865                berrno be;
1866                Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
1867             } else {
1868                /* tell user if snapshot creation of a specific drive failed */
1869                int i;
1870                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1871                   if (islower(szWinDriveLetters[i])) {
1872                      Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed.\n"), szWinDriveLetters[i]);
1873                   }
1874                }
1875                /* inform user about writer states */
1876                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {               
1877                   if (g_pVSSClient->GetWriterState(i) < 1) {
1878                      Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1879                   }                            
1880                }
1881             }
1882         } else {
1883             Jmsg(jcr, M_FATAL, 0, _("No drive letters found for generating VSS snapshots.\n"));
1884         }
1885       } else {
1886          berrno be;
1887          Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly. ERR=%s\n"), be.bstrerror());
1888       } 
1889       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
1890    }
1891 #endif
1892
1893    /**
1894     * Send Files to Storage daemon
1895     */
1896    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1897    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1898       jcr->setJobStatus(JS_ErrorTerminated);
1899       bnet_suppress_error_messages(sd, 1);
1900       Dmsg0(110, "Error in blast_data.\n");
1901    } else {
1902       jcr->setJobStatus(JS_Terminated);
1903       /* Note, the above set status will not override an error */
1904       if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
1905          bnet_suppress_error_messages(sd, 1);
1906          goto cleanup;                /* bail out now */
1907       }
1908       /**
1909        * Expect to get response to append_data from Storage daemon
1910        */
1911       if (!response(jcr, sd, OK_append, "Append Data")) {
1912          jcr->setJobStatus(JS_ErrorTerminated);
1913          goto cleanup;
1914       }
1915
1916       /**
1917        * Send Append End Data to Storage daemon
1918        */
1919       sd->fsend(append_end, jcr->Ticket);
1920       /* Get end OK */
1921       if (!response(jcr, sd, OK_end, "Append End")) {
1922          jcr->setJobStatus(JS_ErrorTerminated);
1923          goto cleanup;
1924       }
1925
1926       /**
1927        * Send Append Close to Storage daemon
1928        */
1929       sd->fsend(append_close, jcr->Ticket);
1930       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1931          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1932             ok = 1;
1933             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1934          }
1935       }
1936       if (!ok) {
1937          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1938          goto cleanup;
1939       }
1940       if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings)) {
1941          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1942             SDJobStatus);
1943       }
1944    }
1945
1946 cleanup:
1947 #if defined(WIN32_VSS)
1948    if (jcr->VSS) {
1949       Win32ConvCleanupCache();
1950       g_pVSSClient->DestroyWriterInfo();
1951       V(vss_mutex);
1952    }
1953 #endif
1954
1955    generate_plugin_event(jcr, bEventEndBackupJob);
1956    return 0;                          /* return and stop command loop */
1957 }
1958
1959 /**
1960  * Do a Verify for Director
1961  *
1962  */
1963 static int verify_cmd(JCR *jcr)
1964 {
1965    BSOCK *dir = jcr->dir_bsock;
1966    BSOCK *sd  = jcr->store_bsock;
1967    char level[100];
1968
1969    jcr->setJobType(JT_VERIFY);
1970    if (sscanf(dir->msg, verifycmd, level) != 1) {
1971       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
1972       return 0;
1973    }
1974
1975    if (strcasecmp(level, "init") == 0) {
1976       jcr->setJobLevel(L_VERIFY_INIT);
1977    } else if (strcasecmp(level, "catalog") == 0){
1978       jcr->setJobLevel(L_VERIFY_CATALOG);
1979    } else if (strcasecmp(level, "volume") == 0){
1980       jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1981    } else if (strcasecmp(level, "data") == 0){
1982       jcr->setJobLevel(L_VERIFY_DATA);
1983    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
1984       jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
1985    } else {
1986       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
1987       return 0;
1988    }
1989
1990    dir->fsend(OKverify);
1991
1992    generate_daemon_event(jcr, "JobStart");
1993    generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
1994    generate_plugin_event(jcr, bEventStartVerifyJob);
1995
1996    Dmsg1(110, "filed>dird: %s", dir->msg);
1997
1998    switch (jcr->getJobLevel()) {
1999    case L_VERIFY_INIT:
2000    case L_VERIFY_CATALOG:
2001       do_verify(jcr);
2002       break;
2003    case L_VERIFY_VOLUME_TO_CATALOG:
2004       if (!open_sd_read_session(jcr)) {
2005          return 0;
2006       }
2007       start_dir_heartbeat(jcr);
2008       do_verify_volume(jcr);
2009       stop_dir_heartbeat(jcr);
2010       /*
2011        * Send Close session command to Storage daemon
2012        */
2013       sd->fsend(read_close, jcr->Ticket);
2014       Dmsg1(130, "filed>stored: %s", sd->msg);
2015
2016       /* ****FIXME**** check response */
2017       bget_msg(sd);                      /* get OK */
2018
2019       /* Inform Storage daemon that we are done */
2020       sd->signal(BNET_TERMINATE);
2021
2022       break;
2023    case L_VERIFY_DISK_TO_CATALOG:
2024       do_verify(jcr);
2025       break;
2026    default:
2027       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2028       return 0;
2029    }
2030
2031    dir->signal(BNET_EOD);
2032    generate_plugin_event(jcr, bEventEndVerifyJob);
2033    return 0;                          /* return and terminate command loop */
2034 }
2035
2036 #ifdef WIN32_VSS
2037 static bool vss_restore_init_callback(JCR *jcr, int init_type)
2038 {
2039    switch (init_type) {
2040    case VSS_INIT_RESTORE_AFTER_INIT:
2041       generate_plugin_event(jcr, bEventVssRestoreLoadComponentMetadata);
2042       return true;
2043    case VSS_INIT_RESTORE_AFTER_GATHER:
2044       generate_plugin_event(jcr, bEventVssRestoreSetComponentsSelected);
2045       return true;
2046    default:
2047       return false;
2048       break;
2049    }
2050 }
2051 #endif
2052
2053 /**
2054  * Do a Restore for Director
2055  *
2056  */
2057 static int restore_cmd(JCR *jcr)
2058 {
2059    BSOCK *dir = jcr->dir_bsock;
2060    BSOCK *sd = jcr->store_bsock;
2061    POOLMEM *args;
2062    bool use_regexwhere=false;
2063    int prefix_links;
2064    char replace;
2065
2066    /**
2067     * Scan WHERE (base directory for restore) from command
2068     */
2069    Dmsg0(100, "restore command\n");
2070 #if defined(WIN32_VSS)
2071
2072    /**
2073     * No need to enable VSS for restore if we do not have plugin
2074     *  data to restore 
2075     */
2076    enable_vss = jcr->job_metadata != NULL;
2077
2078    Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
2079    // capture state here, if client is backed up by multiple directors
2080    // and one enables vss and the other does not then enable_vss can change
2081    // between here and where its evaluated after the job completes.
2082    jcr->VSS = g_pVSSClient && enable_vss;
2083    if (jcr->VSS) {
2084       /* Run only one at a time */
2085       P(vss_mutex);
2086    }
2087 #endif
2088    /* Pickup where string */
2089    args = get_memory(dir->msglen+1);
2090    *args = 0;
2091
2092    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
2093       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
2094          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2095             pm_strcpy(jcr->errmsg, dir->msg);
2096             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2097             return 0;
2098          }
2099          *args = 0;
2100       }
2101       use_regexwhere = true;
2102    }
2103    /* Turn / into nothing */
2104    if (IsPathSeparator(args[0]) && args[1] == '\0') {
2105       args[0] = '\0';
2106    }
2107
2108    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2109    unbash_spaces(args);
2110
2111    if (use_regexwhere) {
2112       jcr->where_bregexp = get_bregexps(args);
2113       if (!jcr->where_bregexp) {
2114          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2115          free_pool_memory(args);
2116          return 0;
2117       }
2118    } else {
2119       jcr->where = bstrdup(args);
2120    }
2121
2122    free_pool_memory(args);
2123    jcr->replace = replace;
2124    jcr->prefix_links = prefix_links;
2125
2126    dir->fsend(OKrestore);
2127    Dmsg1(110, "filed>dird: %s", dir->msg);
2128
2129    jcr->setJobType(JT_RESTORE);
2130
2131    jcr->setJobStatus(JS_Blocked);
2132
2133    if (!open_sd_read_session(jcr)) {
2134       jcr->setJobStatus(JS_ErrorTerminated);
2135       goto bail_out;
2136    }
2137
2138    jcr->setJobStatus(JS_Running);
2139
2140    /**
2141     * Do restore of files and data
2142     */
2143    start_dir_heartbeat(jcr);
2144    generate_daemon_event(jcr, "JobStart");
2145    generate_plugin_event(jcr, bEventStartRestoreJob);
2146
2147 #if defined(WIN32_VSS)
2148    /* START VSS ON WIN32 */
2149    if (jcr->VSS) {
2150       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
2151             (WCHAR *)jcr->job_metadata)) {
2152
2153          /* inform user about writer states */
2154          int i;
2155          for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
2156             if (g_pVSSClient->GetWriterState(i) < 1) {
2157                Jmsg(jcr, M_INFO, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
2158                //jcr->JobErrors++;
2159             }
2160          }
2161       } else {
2162 /*
2163    int fd = open("C:\\eric.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777);
2164    write(fd, (WCHAR *)jcr->job_metadata, wcslen((WCHAR *)jcr->job_metadata) * sizeof(WCHAR));
2165    close(fd);
2166 */
2167          berrno be;
2168          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
2169       }
2170       free_and_null_pool_memory(jcr->job_metadata);
2171       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2172    }
2173 #endif
2174
2175    do_restore(jcr);
2176    stop_dir_heartbeat(jcr);
2177
2178    jcr->setJobStatus(JS_Terminated);
2179    if (jcr->JobStatus != JS_Terminated) {
2180       bnet_suppress_error_messages(sd, 1);
2181    }
2182
2183    /**
2184     * Send Close session command to Storage daemon
2185     */
2186    sd->fsend(read_close, jcr->Ticket);
2187    Dmsg1(100, "filed>stored: %s", sd->msg);
2188
2189    bget_msg(sd);                      /* get OK */
2190
2191    /* Inform Storage daemon that we are done */
2192    sd->signal(BNET_TERMINATE);
2193
2194 #if defined(WIN32_VSS)
2195    /* STOP VSS ON WIN32 */
2196    /* tell vss to close the restore session */
2197    Dmsg0(100, "About to call CloseRestore\n");
2198    if (jcr->VSS) {
2199       generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
2200       Dmsg0(100, "Really about to call CloseRestore\n");
2201       if (g_pVSSClient->CloseRestore()) {
2202          Dmsg0(100, "CloseRestore success\n");
2203          /* inform user about writer states */
2204          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
2205             int msg_type = M_INFO;
2206             if (g_pVSSClient->GetWriterState(i) < 1) {
2207                //msg_type = M_WARNING;
2208                //jcr->JobErrors++;
2209             }
2210             Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
2211          }
2212       }
2213       else
2214          Dmsg1(100, "CloseRestore fail - %08x\n", errno);
2215       V(vss_mutex);
2216    }
2217 #endif
2218
2219 bail_out:
2220    bfree_and_null(jcr->where);
2221
2222    if (jcr->JobErrors) {
2223       jcr->setJobStatus(JS_ErrorTerminated);
2224    }
2225
2226    Dmsg0(100, "Done in job.c\n");
2227
2228    int ret;
2229    if (jcr->multi_restore) {
2230       Dmsg0(100, OKstoreend);
2231       dir->fsend(OKstoreend);
2232       ret = 1;     /* we continue the loop, waiting for next part */
2233    } else {
2234       end_restore_cmd(jcr);
2235       ret = 0;     /* we stop here */
2236    }
2237
2238    if (job_canceled(jcr)) {
2239       ret = 0;     /* we stop here */
2240    }
2241
2242    return ret;
2243 }
2244
2245 static int end_restore_cmd(JCR *jcr) 
2246 {
2247    Dmsg0(5, "end_restore_cmd\n");
2248    generate_plugin_event(jcr, bEventEndRestoreJob);
2249    return 0;                          /* return and terminate command loop */
2250 }
2251
2252 static int open_sd_read_session(JCR *jcr)
2253 {
2254    BSOCK *sd = jcr->store_bsock;
2255
2256    if (!sd) {
2257       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2258       return 0;
2259    }
2260    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2261       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2262    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2263    /*
2264     * Open Read Session with Storage daemon
2265     */
2266    sd->fsend(read_open, "DummyVolume",
2267       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2268       jcr->StartBlock, jcr->EndBlock);
2269    Dmsg1(110, ">stored: %s", sd->msg);
2270
2271    /*
2272     * Get ticket number
2273     */
2274    if (bget_msg(sd) >= 0) {
2275       Dmsg1(110, "filed<stored: %s", sd->msg);
2276       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2277          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2278          return 0;
2279       }
2280       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2281    } else {
2282       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2283       return 0;
2284    }
2285
2286    if (!send_bootstrap_file(jcr)) {
2287       return 0;
2288    }
2289
2290    /*
2291     * Start read of data with Storage daemon
2292     */
2293    sd->fsend(read_data, jcr->Ticket);
2294    Dmsg1(110, ">stored: %s", sd->msg);
2295
2296    /*
2297     * Get OK data
2298     */
2299    if (!response(jcr, sd, OK_data, "Read Data")) {
2300       return 0;
2301    }
2302    return 1;
2303 }
2304
2305 /**
2306  * Destroy the Job Control Record and associated
2307  * resources (sockets).
2308  */
2309 static void filed_free_jcr(JCR *jcr)
2310 {
2311    if (jcr->store_bsock) {
2312       jcr->store_bsock->close();
2313    }
2314    free_bootstrap(jcr);
2315    if (jcr->last_fname) {
2316       free_pool_memory(jcr->last_fname);
2317    }
2318    free_runscripts(jcr->RunScripts);
2319    delete jcr->RunScripts;
2320
2321    if (jcr->JobId != 0)
2322       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2323
2324    return;
2325 }
2326
2327 /**
2328  * Get response from Storage daemon to a command we
2329  * sent. Check that the response is OK.
2330  *
2331  *  Returns: 0 on failure
2332  *           1 on success
2333  */
2334 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2335 {
2336    if (sd->errors) {
2337       return 0;
2338    }
2339    if (bget_msg(sd) > 0) {
2340       Dmsg0(110, sd->msg);
2341       if (strcmp(sd->msg, resp) == 0) {
2342          return 1;
2343       }
2344    }
2345    if (job_canceled(jcr)) {
2346       return 0;                       /* if canceled avoid useless error messages */
2347    }
2348    if (is_bnet_error(sd)) {
2349       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2350          cmd, bnet_strerror(sd));
2351    } else {
2352       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
2353          cmd, resp, sd->msg);
2354    }
2355    return 0;
2356 }
2357
2358 static int send_bootstrap_file(JCR *jcr)
2359 {
2360    FILE *bs;
2361    char buf[2000];
2362    BSOCK *sd = jcr->store_bsock;
2363    const char *bootstrap = "bootstrap\n";
2364    int stat = 0;
2365
2366    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
2367    if (!jcr->RestoreBootstrap) {
2368       return 1;
2369    }
2370    bs = fopen(jcr->RestoreBootstrap, "rb");
2371    if (!bs) {
2372       berrno be;
2373       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
2374          jcr->RestoreBootstrap, be.bstrerror());
2375       jcr->setJobStatus(JS_ErrorTerminated);
2376       goto bail_out;
2377    }
2378    sd->msglen = pm_strcpy(sd->msg, bootstrap);
2379    sd->send();
2380    while (fgets(buf, sizeof(buf), bs)) {
2381       sd->msglen = Mmsg(sd->msg, "%s", buf);
2382       sd->send();
2383    }
2384    sd->signal(BNET_EOD);
2385    fclose(bs);
2386    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
2387       jcr->setJobStatus(JS_ErrorTerminated);
2388       goto bail_out;
2389    }
2390    stat = 1;
2391
2392 bail_out:
2393    free_bootstrap(jcr);
2394    return stat;
2395 }