]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/job.c
Fix seg fault in plugin event loop
[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 extern "C" char *job_code_callback_filed(JCR *jcr, const char* param)
554 {
555    switch (param[0]) {
556       case 'D':
557          if (jcr->director) { 
558             return jcr->director->hdr.name;
559          }
560          break;
561    }
562    return NULL;
563
564 }
565
566 static int runbefore_cmd(JCR *jcr)
567 {
568    bool ok;
569    BSOCK *dir = jcr->dir_bsock;
570    POOLMEM *cmd = get_memory(dir->msglen+1);
571    RUNSCRIPT *script;
572
573    Dmsg1(100, "runbefore_cmd: %s", dir->msg);
574    if (sscanf(dir->msg, runbefore, cmd) != 1) {
575       pm_strcpy(jcr->errmsg, dir->msg);
576       Jmsg1(jcr, M_FATAL, 0, _("Bad RunBeforeJob command: %s\n"), jcr->errmsg);
577       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
578       free_memory(cmd);
579       return 0;
580    }
581    unbash_spaces(cmd);
582
583    /* Run the command now */
584    script = new_runscript();
585    script->set_job_code_callback(job_code_callback_filed);
586    script->set_command(cmd);
587    script->when = SCRIPT_Before;
588    ok = script->run(jcr, "ClientRunBeforeJob");
589    free_runscript(script);
590
591    free_memory(cmd);
592    if (ok) {
593       dir->fsend(OKRunBefore);
594       return 1;
595    } else {
596       dir->fsend(_("2905 Bad RunBeforeJob command.\n"));
597       return 0;
598    }
599 }
600
601 static int runbeforenow_cmd(JCR *jcr)
602 {
603    BSOCK *dir = jcr->dir_bsock;
604
605    run_scripts(jcr, jcr->RunScripts, "ClientBeforeJob");
606    if (job_canceled(jcr)) {
607       dir->fsend(_("2905 Bad RunBeforeNow command.\n"));
608       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: FAILED\n");
609       return 0;
610    } else {
611       dir->fsend(OKRunBeforeNow);
612       Dmsg0(100, "Back from run_scripts ClientBeforeJob now: OK\n");
613       return 1;
614    }
615 }
616
617 static int runafter_cmd(JCR *jcr)
618 {
619    BSOCK *dir = jcr->dir_bsock;
620    POOLMEM *msg = get_memory(dir->msglen+1);
621    RUNSCRIPT *cmd;
622
623    Dmsg1(100, "runafter_cmd: %s", dir->msg);
624    if (sscanf(dir->msg, runafter, msg) != 1) {
625       pm_strcpy(jcr->errmsg, dir->msg);
626       Jmsg1(jcr, M_FATAL, 0, _("Bad RunAfter command: %s\n"), jcr->errmsg);
627       dir->fsend(_("2905 Bad RunAfterJob command.\n"));
628       free_memory(msg);
629       return 0;
630    }
631    unbash_spaces(msg);
632
633    cmd = new_runscript();
634    cmd->set_job_code_callback(job_code_callback_filed);
635    cmd->set_command(msg);
636    cmd->on_success = true;
637    cmd->on_failure = false;
638    cmd->when = SCRIPT_After;
639
640    jcr->RunScripts->append(cmd);
641
642    free_pool_memory(msg);
643    return dir->fsend(OKRunAfter);
644 }
645
646 static int runscript_cmd(JCR *jcr)
647 {
648    BSOCK *dir = jcr->dir_bsock;
649    POOLMEM *msg = get_memory(dir->msglen+1);
650    int on_success, on_failure, fail_on_error;
651
652    RUNSCRIPT *cmd = new_runscript() ;
653    cmd->set_job_code_callback(job_code_callback_filed);
654
655    Dmsg1(100, "runscript_cmd: '%s'\n", dir->msg);
656    /* Note, we cannot sscanf into bools */
657    if (sscanf(dir->msg, runscript, &on_success, 
658                                   &on_failure,
659                                   &fail_on_error,
660                                   &cmd->when,
661                                   msg) != 5) {
662       pm_strcpy(jcr->errmsg, dir->msg);
663       Jmsg1(jcr, M_FATAL, 0, _("Bad RunScript command: %s\n"), jcr->errmsg);
664       dir->fsend(_("2905 Bad RunScript command.\n"));
665       free_runscript(cmd);
666       free_memory(msg);
667       return 0;
668    }
669    cmd->on_success = on_success;
670    cmd->on_failure = on_failure;
671    cmd->fail_on_error = fail_on_error;
672    unbash_spaces(msg);
673
674    cmd->set_command(msg);
675    cmd->debug();
676    jcr->RunScripts->append(cmd);
677
678    free_pool_memory(msg);
679    return dir->fsend(OKRunScript);
680 }
681
682 /*
683  * This reads data sent from the Director from the
684  *   RestoreObject table that allows us to get objects
685  *   that were backed up (VSS .xml data) and are needed
686  *   before starting the restore.
687  */
688 static int restore_object_cmd(JCR *jcr)
689 {
690    BSOCK *dir = jcr->dir_bsock;
691    int32_t FileIndex;
692    restore_object_pkt rop;
693
694    memset(&rop, 0, sizeof(rop));
695    rop.pkt_size = sizeof(rop);
696    rop.pkt_end = sizeof(rop);
697    Dmsg1(100, "Enter restoreobject_cmd: %s", dir->msg);
698    if (strcmp(dir->msg, endrestoreobjectcmd) == 0) {
699       generate_plugin_event(jcr, bEventRestoreObject, NULL);
700       return dir->fsend(OKRestoreObject);
701    }
702
703    if (sscanf(dir->msg, restoreobjcmd, &rop.JobId, &rop.object_len, 
704               &rop.object_full_len, &rop.object_index, 
705               &rop.object_type, &rop.object_compression, &FileIndex) != 7) {
706       Dmsg0(5, "Bad restore object command\n");
707       pm_strcpy(jcr->errmsg, dir->msg);
708       Jmsg1(jcr, M_FATAL, 0, _("Bad RestoreObject command: %s\n"), jcr->errmsg);
709       goto bail_out;
710    }
711
712    Dmsg6(100, "Recv object: JobId=%u objlen=%d full_len=%d objinx=%d objtype=%d FI=%d\n",
713          rop.JobId, rop.object_len, rop.object_full_len, 
714          rop.object_index, rop.object_type, FileIndex);
715    /* Read Object name */
716    if (dir->recv() < 0) {
717       goto bail_out;
718    }
719    Dmsg2(100, "Recv Oname object: len=%d Oname=%s\n", dir->msglen, dir->msg);
720    rop.object_name = bstrdup(dir->msg);
721
722    /* Read Object */
723    if (dir->recv() < 0) {
724       goto bail_out;
725    }
726    /* Transfer object from message buffer, and get new message buffer */
727    rop.object = dir->msg;
728    dir->msg = get_pool_memory(PM_MESSAGE);
729
730    /* If object is compressed, uncompress it */
731    if (rop.object_compression == 1) {   /* zlib level 9 */
732       int stat;
733       int out_len = rop.object_full_len + 100;
734       POOLMEM *obj = get_memory(out_len);
735       Dmsg2(100, "Inflating from %d to %d\n", rop.object_len, rop.object_full_len);
736       stat = Zinflate(rop.object, rop.object_len, obj, out_len);
737       Dmsg1(100, "Zinflate stat=%d\n", stat);
738       if (out_len != rop.object_full_len) {
739          Jmsg3(jcr, M_ERROR, 0, ("Decompression failed. Len wanted=%d got=%d. Object=%s\n"),
740             rop.object_full_len, out_len, rop.object_name);
741       }
742       free_pool_memory(rop.object);   /* release compressed object */
743       rop.object = obj;               /* new uncompressed object */
744       rop.object_len = out_len;
745    }
746    Dmsg2(100, "Recv Object: len=%d Object=%s\n", rop.object_len, rop.object);
747    /* Special Job meta data */
748    if (strcmp(rop.object_name, "job_metadata.xml") == 0) {
749       Dmsg0(100, "got job metadata\n");
750       free_and_null_pool_memory(jcr->job_metadata);
751       jcr->job_metadata = rop.object;
752       rop.object = NULL;
753    } else {
754       /* pass to plugin */
755       generate_plugin_event(jcr, bEventRestoreObject, (void *)&rop);
756    }
757
758    if (rop.object_name) {
759       free(rop.object_name);
760    }
761    if (rop.object) {
762       free_pool_memory(rop.object);
763    }
764
765    Dmsg1(100, "Send: %s", OKRestoreObject);
766    return 1;
767
768 bail_out:
769    dir->fsend(_("2909 Bad RestoreObject command.\n"));
770    return 0;
771
772 }
773
774
775 static bool init_fileset(JCR *jcr)
776 {
777    FF_PKT *ff;
778    findFILESET *fileset;
779
780    if (!jcr->ff) {
781       return false;
782    }
783    ff = jcr->ff;
784    if (ff->fileset) {
785       return false;
786    }
787    fileset = (findFILESET *)malloc(sizeof(findFILESET));
788    memset(fileset, 0, sizeof(findFILESET));
789    ff->fileset = fileset;
790    fileset->state = state_none;
791    fileset->include_list.init(1, true);
792    fileset->exclude_list.init(1, true);
793    return true;
794 }
795
796 static void append_file(JCR *jcr, findINCEXE *incexe, 
797                         const char *buf, bool is_file)
798 {
799    if (is_file) {
800       incexe->name_list.append(new_dlistString(buf));
801
802    } else if (me->plugin_directory) {
803       generate_plugin_event(jcr, bEventPluginCommand, (void *)buf);
804       incexe->plugin_list.append(new_dlistString(buf));
805
806    } else {
807       Jmsg(jcr, M_FATAL, 0, 
808            _("Plugin Directory not defined. Cannot use plugin: \"%s\"\n"),
809            buf);
810    }
811 }
812
813 /**
814  * Add fname to include/exclude fileset list. First check for
815  * | and < and if necessary perform command.
816  */
817 void add_file_to_fileset(JCR *jcr, const char *fname, bool is_file)
818 {
819    findFILESET *fileset = jcr->ff->fileset;
820    char *p;
821    BPIPE *bpipe;
822    POOLMEM *fn;
823    FILE *ffd;
824    char buf[1000];
825    int ch;
826    int stat;
827
828    p = (char *)fname;
829    ch = (uint8_t)*p;
830    switch (ch) {
831    case '|':
832       p++;                            /* skip over | */
833       fn = get_pool_memory(PM_FNAME);
834       fn = edit_job_codes(jcr, fn, p, "", job_code_callback_filed);
835       bpipe = open_bpipe(fn, 0, "r");
836       if (!bpipe) {
837          berrno be;
838          Jmsg(jcr, M_FATAL, 0, _("Cannot run program: %s. ERR=%s\n"),
839             p, be.bstrerror());
840          free_pool_memory(fn);
841          return;
842       }
843       free_pool_memory(fn);
844       while (fgets(buf, sizeof(buf), bpipe->rfd)) {
845          strip_trailing_junk(buf);
846          append_file(jcr, fileset->incexe, buf, is_file);
847       }
848       if ((stat=close_bpipe(bpipe)) != 0) {
849          berrno be;
850          Jmsg(jcr, M_FATAL, 0, _("Error running program: %s. stat=%d: ERR=%s\n"),
851             p, be.code(stat), be.bstrerror(stat));
852          return;
853       }
854       break;
855    case '<':
856       Dmsg1(100, "Doing < of '%s' include on client.\n", p + 1);
857       p++;                      /* skip over < */
858       if ((ffd = fopen(p, "rb")) == NULL) {
859          berrno be;
860          Jmsg(jcr, M_FATAL, 0, 
861               _("Cannot open FileSet input file: %s. ERR=%s\n"),
862             p, be.bstrerror());
863          return;
864       }
865       while (fgets(buf, sizeof(buf), ffd)) {
866          strip_trailing_junk(buf);
867          append_file(jcr, fileset->incexe, buf, is_file);
868       }
869       fclose(ffd);
870       break;
871    default:
872       append_file(jcr, fileset->incexe, fname, is_file);
873       break;
874    }
875 }
876
877 void set_incexe(JCR *jcr, findINCEXE *incexe)
878 {
879    findFILESET *fileset = jcr->ff->fileset;
880    fileset->incexe = incexe;
881 }
882
883
884 /**
885  * Define a new Exclude block in the FileSet
886  */
887 findINCEXE *new_exclude(JCR *jcr)
888 {
889    findFILESET *fileset = jcr->ff->fileset;
890
891    /* New exclude */
892    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
893    memset(fileset->incexe, 0, sizeof(findINCEXE));
894    fileset->incexe->opts_list.init(1, true);
895    fileset->incexe->name_list.init();
896    fileset->incexe->plugin_list.init();
897    fileset->exclude_list.append(fileset->incexe);
898    return fileset->incexe;
899 }
900
901 /**
902  * Define a new Include block in the FileSet
903  */
904 findINCEXE *new_include(JCR *jcr)
905 {
906    findFILESET *fileset = jcr->ff->fileset;
907
908    /* New include */
909    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
910    memset(fileset->incexe, 0, sizeof(findINCEXE));
911    fileset->incexe->opts_list.init(1, true);
912    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
913    fileset->incexe->plugin_list.init();
914    fileset->include_list.append(fileset->incexe);
915    return fileset->incexe;
916 }
917
918 /**
919  * Define a new preInclude block in the FileSet
920  *   That is the include is prepended to the other
921  *   Includes.  This is used for plugin exclusions.
922  */
923 findINCEXE *new_preinclude(JCR *jcr)
924 {
925    findFILESET *fileset = jcr->ff->fileset;
926
927    /* New pre-include */
928    fileset->incexe = (findINCEXE *)malloc(sizeof(findINCEXE));
929    memset(fileset->incexe, 0, sizeof(findINCEXE));
930    fileset->incexe->opts_list.init(1, true);
931    fileset->incexe->name_list.init(); /* for dlist;  was 1,true for alist */
932    fileset->incexe->plugin_list.init();
933    fileset->include_list.prepend(fileset->incexe);
934    return fileset->incexe;
935 }
936
937 static findFOPTS *start_options(FF_PKT *ff)
938 {
939    int state = ff->fileset->state;
940    findINCEXE *incexe = ff->fileset->incexe;
941
942    if (state != state_options) {
943       ff->fileset->state = state_options;
944       findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
945       memset(fo, 0, sizeof(findFOPTS));
946       fo->regex.init(1, true);
947       fo->regexdir.init(1, true);
948       fo->regexfile.init(1, true);
949       fo->wild.init(1, true);
950       fo->wilddir.init(1, true);
951       fo->wildfile.init(1, true);
952       fo->wildbase.init(1, true);
953       fo->base.init(1, true);
954       fo->fstype.init(1, true);
955       fo->drivetype.init(1, true);
956       incexe->current_opts = fo;
957       incexe->opts_list.append(fo);
958    }
959    return incexe->current_opts;
960 }
961
962 /*
963  * Used by plugins to define a new options block
964  */
965 void new_options(JCR *jcr, findINCEXE *incexe)
966 {
967    if (!incexe) {
968       incexe = jcr->ff->fileset->incexe;
969    }
970    findFOPTS *fo = (findFOPTS *)malloc(sizeof(findFOPTS));
971    memset(fo, 0, sizeof(findFOPTS));
972    fo->regex.init(1, true);
973    fo->regexdir.init(1, true);
974    fo->regexfile.init(1, true);
975    fo->wild.init(1, true);
976    fo->wilddir.init(1, true);
977    fo->wildfile.init(1, true);
978    fo->wildbase.init(1, true);
979    fo->base.init(1, true);
980    fo->fstype.init(1, true);
981    fo->drivetype.init(1, true);
982    incexe->current_opts = fo;
983    incexe->opts_list.prepend(fo);
984    jcr->ff->fileset->state = state_options;
985 }
986
987 /**
988  * Add a regex to the current fileset
989  */
990 int add_regex_to_fileset(JCR *jcr, const char *item, int type)
991 {
992    findFOPTS *current_opts = start_options(jcr->ff);
993    regex_t *preg;
994    int rc;
995    char prbuf[500];
996
997    preg = (regex_t *)malloc(sizeof(regex_t));
998    if (current_opts->flags & FO_IGNORECASE) {
999       rc = regcomp(preg, item, REG_EXTENDED|REG_ICASE);
1000    } else {
1001       rc = regcomp(preg, item, REG_EXTENDED);
1002    }
1003    if (rc != 0) {
1004       regerror(rc, preg, prbuf, sizeof(prbuf));
1005       regfree(preg);
1006       free(preg);
1007       Jmsg(jcr, M_FATAL, 0, _("REGEX %s compile error. ERR=%s\n"), item, prbuf);
1008       return state_error;
1009    }
1010    if (type == ' ') {
1011       current_opts->regex.append(preg);
1012    } else if (type == 'D') {
1013       current_opts->regexdir.append(preg);
1014    } else if (type == 'F') {
1015       current_opts->regexfile.append(preg);
1016    } else {
1017       return state_error;
1018    }
1019    return state_options;
1020 }
1021
1022 /**
1023  * Add a wild card to the current fileset
1024  */
1025 int add_wild_to_fileset(JCR *jcr, const char *item, int type)
1026 {
1027    findFOPTS *current_opts = start_options(jcr->ff);
1028
1029    if (type == ' ') {
1030       current_opts->wild.append(bstrdup(item));
1031    } else if (type == 'D') {
1032       current_opts->wilddir.append(bstrdup(item));
1033    } else if (type == 'F') {
1034       current_opts->wildfile.append(bstrdup(item));
1035    } else if (type == 'B') {
1036       current_opts->wildbase.append(bstrdup(item));
1037    } else {
1038       return state_error;
1039    }
1040    return state_options;
1041 }
1042
1043
1044 /**
1045  * Add options to the current fileset
1046  */
1047 int add_options_to_fileset(JCR *jcr, const char *item)
1048 {
1049    findFOPTS *current_opts = start_options(jcr->ff);
1050
1051    set_options(current_opts, item);
1052    return state_options;
1053 }
1054
1055 static void add_fileset(JCR *jcr, const char *item)
1056 {
1057    FF_PKT *ff = jcr->ff;
1058    findFILESET *fileset = ff->fileset;
1059    int state = fileset->state;
1060    findFOPTS *current_opts;
1061
1062    /* Get code, optional subcode, and position item past the dividing space */
1063    Dmsg1(100, "%s\n", item);
1064    int code = item[0];
1065    if (code != '\0') {
1066       ++item;
1067    }
1068    int subcode = ' ';               /* A space is always a valid subcode */
1069    if (item[0] != '\0' && item[0] != ' ') {
1070       subcode = item[0];
1071       ++item;
1072    }
1073    if (*item == ' ') {
1074       ++item;
1075    }
1076
1077    /* Skip all lines we receive after an error */
1078    if (state == state_error) {
1079       Dmsg0(100, "State=error return\n");
1080       return;
1081    }
1082
1083    /**
1084     * The switch tests the code for validity.
1085     * The subcode is always good if it is a space, otherwise we must confirm.
1086     * We set state to state_error first assuming the subcode is invalid,
1087     * requiring state to be set in cases below that handle subcodes.
1088     */
1089    if (subcode != ' ') {
1090       state = state_error;
1091       Dmsg0(100, "Set state=error or double code.\n");
1092    }
1093    switch (code) {
1094    case 'I':
1095       (void)new_include(jcr);
1096       break;
1097    case 'E':
1098       (void)new_exclude(jcr);
1099       break;
1100    case 'N':                             /* null */
1101       state = state_none;
1102       break;
1103    case 'F':                             /* file = */
1104       /* File item to include or exclude list */
1105       state = state_include;
1106       add_file_to_fileset(jcr, item, true);
1107       break;
1108    case 'P':                              /* plugin */
1109       /* Plugin item to include list */
1110       state = state_include;
1111       add_file_to_fileset(jcr, item, false);
1112       break;
1113    case 'R':                              /* regex */
1114       state = add_regex_to_fileset(jcr, item, subcode);
1115       break;
1116    case 'B':
1117       current_opts = start_options(ff);
1118       current_opts->base.append(bstrdup(item));
1119       state = state_options;
1120       break;
1121    case 'X':                             /* Filetype or Drive type */
1122       current_opts = start_options(ff);
1123       state = state_options;
1124       if (subcode == ' ') {
1125          current_opts->fstype.append(bstrdup(item));
1126       } else if (subcode == 'D') {
1127          current_opts->drivetype.append(bstrdup(item));
1128       } else {
1129          state = state_error;
1130       }
1131       break;
1132    case 'W':                               /* wild cards */
1133       state = add_wild_to_fileset(jcr, item, subcode);
1134       break;
1135    case 'O':                                /* Options */
1136       state = add_options_to_fileset(jcr, item);
1137       break;
1138    case 'Z':                                /* ignore dir */
1139       state = state_include;
1140       fileset->incexe->ignoredir = bstrdup(item);
1141       break;
1142    case 'D':
1143       current_opts = start_options(ff);
1144 //    current_opts->reader = bstrdup(item); /* deprecated */
1145       state = state_options;
1146       break;
1147    case 'T':
1148       current_opts = start_options(ff);
1149 //    current_opts->writer = bstrdup(item); /* deprecated */
1150       state = state_options;
1151       break;
1152    default:
1153       Jmsg(jcr, M_FATAL, 0, _("Invalid FileSet command: %s\n"), item);
1154       state = state_error;
1155       break;
1156    }
1157    ff->fileset->state = state;
1158 }
1159
1160 static bool term_fileset(JCR *jcr)
1161 {
1162    FF_PKT *ff = jcr->ff;
1163
1164 #ifdef xxx_DEBUG_CODE
1165    findFILESET *fileset = ff->fileset;
1166    int i, j, k;
1167
1168    for (i=0; i<fileset->include_list.size(); i++) {
1169       findINCEXE *incexe = (findINCEXE *)fileset->include_list.get(i);
1170       Dmsg0(400, "I\n");
1171       for (j=0; j<incexe->opts_list.size(); j++) {
1172          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1173          for (k=0; k<fo->regex.size(); k++) {
1174             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1175          }
1176          for (k=0; k<fo->regexdir.size(); k++) {
1177             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1178          }
1179          for (k=0; k<fo->regexfile.size(); k++) {
1180             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1181          }
1182          for (k=0; k<fo->wild.size(); k++) {
1183             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1184          }
1185          for (k=0; k<fo->wilddir.size(); k++) {
1186             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1187          }
1188          for (k=0; k<fo->wildfile.size(); k++) {
1189             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1190          }
1191          for (k=0; k<fo->wildbase.size(); k++) {
1192             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1193          }
1194          for (k=0; k<fo->base.size(); k++) {
1195             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1196          }
1197          for (k=0; k<fo->fstype.size(); k++) {
1198             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1199          }
1200          for (k=0; k<fo->drivetype.size(); k++) {
1201             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1202          }
1203       }
1204       if (incexe->ignoredir) {
1205          Dmsg1(400, "Z %s\n", incexe->ignoredir);
1206       }
1207       dlistString *node;
1208       foreach_dlist(node, &incexe->name_list) {
1209          Dmsg1(400, "F %s\n", node->c_str());
1210       }
1211       foreach_dlist(node, &incexe->plugin_list) {
1212          Dmsg1(400, "P %s\n", node->c_str());
1213       }
1214    }
1215    for (i=0; i<fileset->exclude_list.size(); i++) {
1216       findINCEXE *incexe = (findINCEXE *)fileset->exclude_list.get(i);
1217       Dmsg0(400, "E\n");
1218       for (j=0; j<incexe->opts_list.size(); j++) {
1219          findFOPTS *fo = (findFOPTS *)incexe->opts_list.get(j);
1220          for (k=0; k<fo->regex.size(); k++) {
1221             Dmsg1(400, "R %s\n", (char *)fo->regex.get(k));
1222          }
1223          for (k=0; k<fo->regexdir.size(); k++) {
1224             Dmsg1(400, "RD %s\n", (char *)fo->regexdir.get(k));
1225          }
1226          for (k=0; k<fo->regexfile.size(); k++) {
1227             Dmsg1(400, "RF %s\n", (char *)fo->regexfile.get(k));
1228          }
1229          for (k=0; k<fo->wild.size(); k++) {
1230             Dmsg1(400, "W %s\n", (char *)fo->wild.get(k));
1231          }
1232          for (k=0; k<fo->wilddir.size(); k++) {
1233             Dmsg1(400, "WD %s\n", (char *)fo->wilddir.get(k));
1234          }
1235          for (k=0; k<fo->wildfile.size(); k++) {
1236             Dmsg1(400, "WF %s\n", (char *)fo->wildfile.get(k));
1237          }
1238          for (k=0; k<fo->wildbase.size(); k++) {
1239             Dmsg1(400, "WB %s\n", (char *)fo->wildbase.get(k));
1240          }
1241          for (k=0; k<fo->base.size(); k++) {
1242             Dmsg1(400, "B %s\n", (char *)fo->base.get(k));
1243          }
1244          for (k=0; k<fo->fstype.size(); k++) {
1245             Dmsg1(400, "X %s\n", (char *)fo->fstype.get(k));
1246          }
1247          for (k=0; k<fo->drivetype.size(); k++) {
1248             Dmsg1(400, "XD %s\n", (char *)fo->drivetype.get(k));
1249          }
1250       }
1251       dlistString *node;
1252       foreach_dlist(node, &incexe->name_list) {
1253          Dmsg1(400, "F %s\n", node->c_str());
1254       }
1255       foreach_dlist(node, &incexe->plugin_list) {
1256          Dmsg1(400, "P %s\n", node->c_str());
1257       }
1258    }
1259 #endif
1260    return ff->fileset->state != state_error;
1261 }
1262
1263
1264 /**
1265  * As an optimization, we should do this during
1266  *  "compile" time in filed/job.c, and keep only a bit mask
1267  *  and the Verify options.
1268  */
1269 static int set_options(findFOPTS *fo, const char *opts)
1270 {
1271    int j;
1272    const char *p;
1273    char strip[100];
1274
1275 // Commented out as it is not backward compatible - KES
1276 #ifdef HAVE_WIN32
1277 //   fo->flags |= FO_IGNORECASE; /* always ignorecase under windows */
1278 #endif
1279
1280    for (p=opts; *p; p++) {
1281       switch (*p) {
1282       case 'a':                 /* alway replace */
1283       case '0':                 /* no option */
1284          break;
1285       case 'e':
1286          fo->flags |= FO_EXCLUDE;
1287          break;
1288       case 'f':
1289          fo->flags |= FO_MULTIFS;
1290          break;
1291       case 'h':                 /* no recursion */
1292          fo->flags |= FO_NO_RECURSION;
1293          break;
1294       case 'H':                 /* no hard link handling */
1295          fo->flags |= FO_NO_HARDLINK;
1296          break;
1297       case 'i':
1298          fo->flags |= FO_IGNORECASE;
1299          break;
1300       case 'M':                 /* MD5 */
1301          fo->flags |= FO_MD5;
1302          break;
1303       case 'n':
1304          fo->flags |= FO_NOREPLACE;
1305          break;
1306       case 'p':                 /* use portable data format */
1307          fo->flags |= FO_PORTABLE;
1308          break;
1309       case 'R':                 /* Resource forks and Finder Info */
1310          fo->flags |= FO_HFSPLUS;
1311          break;
1312       case 'r':                 /* read fifo */
1313          fo->flags |= FO_READFIFO;
1314          break;
1315       case 'S':
1316          switch(*(p + 1)) {
1317          case '1':
1318             fo->flags |= FO_SHA1;
1319             p++;
1320             break;
1321 #ifdef HAVE_SHA2
1322          case '2':
1323             fo->flags |= FO_SHA256;
1324             p++;
1325             break;
1326          case '3':
1327             fo->flags |= FO_SHA512;
1328             p++;
1329             break;
1330 #endif
1331          default:
1332             /*
1333              * If 2 or 3 is seen here, SHA2 is not configured, so
1334              *  eat the option, and drop back to SHA-1.
1335              */
1336             if (p[1] == '2' || p[1] == '3') {
1337                p++;
1338             }
1339             fo->flags |= FO_SHA1;
1340             break;
1341          }
1342          break;
1343       case 's':
1344          fo->flags |= FO_SPARSE;
1345          break;
1346       case 'm':
1347          fo->flags |= FO_MTIMEONLY;
1348          break;
1349       case 'k':
1350          fo->flags |= FO_KEEPATIME;
1351          break;
1352       case 'A':
1353          fo->flags |= FO_ACL;
1354          break;
1355       case 'V':                  /* verify options */
1356          /* Copy Verify Options */
1357          for (j=0; *p && *p != ':'; p++) {
1358             fo->VerifyOpts[j] = *p;
1359             if (j < (int)sizeof(fo->VerifyOpts) - 1) {
1360                j++;
1361             }
1362          }
1363          fo->VerifyOpts[j] = 0;
1364          break;
1365       case 'C':                  /* accurate options */
1366          /* Copy Accurate Options */
1367          for (j=0; *p && *p != ':'; p++) {
1368             fo->AccurateOpts[j] = *p;
1369             if (j < (int)sizeof(fo->AccurateOpts) - 1) {
1370                j++;
1371             }
1372          }
1373          fo->AccurateOpts[j] = 0;
1374          break;
1375       case 'J':                  /* Basejob options */
1376          /* Copy BaseJob Options */
1377          for (j=0; *p && *p != ':'; p++) {
1378             fo->BaseJobOpts[j] = *p;
1379             if (j < (int)sizeof(fo->BaseJobOpts) - 1) {
1380                j++;
1381             }
1382          }
1383          fo->BaseJobOpts[j] = 0;
1384          break;
1385       case 'P':                  /* strip path */
1386          /* Get integer */
1387          p++;                    /* skip P */
1388          for (j=0; *p && *p != ':'; p++) {
1389             strip[j] = *p;
1390             if (j < (int)sizeof(strip) - 1) {
1391                j++;
1392             }
1393          }
1394          strip[j] = 0;
1395          fo->strip_path = atoi(strip);
1396          fo->flags |= FO_STRIPPATH;
1397          Dmsg2(100, "strip=%s strip_path=%d\n", strip, fo->strip_path);
1398          break;
1399       case 'w':
1400          fo->flags |= FO_IF_NEWER;
1401          break;
1402       case 'W':
1403          fo->flags |= FO_ENHANCEDWILD;
1404          break;
1405       case 'Z':                 /* compression */
1406          p++;                   /* skip Z */
1407          if (*p >= '0' && *p <= '9') {
1408             fo->flags |= FO_COMPRESS;
1409             fo->Compress_algo = COMPRESS_GZIP;
1410             fo->Compress_level = *p - '0';
1411          }
1412          else if (*p == 'o') {
1413             fo->flags |= FO_COMPRESS;
1414             fo->Compress_algo = COMPRESS_LZO1X;
1415             fo->Compress_level = 1; /* not used with LZO */
1416          }
1417          break;
1418       case 'K':
1419          fo->flags |= FO_NOATIME;
1420          break;
1421       case 'c':
1422          fo->flags |= FO_CHKCHANGES;
1423          break;
1424       case 'N':
1425          fo->flags |= FO_HONOR_NODUMP;
1426          break;
1427       case 'X':
1428          fo->flags |= FO_XATTR;
1429          break;
1430       default:
1431          Emsg1(M_ERROR, 0, _("Unknown include/exclude option: %c\n"), *p);
1432          break;
1433       }
1434    }
1435    return state_options;
1436 }
1437
1438
1439 /**
1440  * Director is passing his Fileset
1441  */
1442 static int fileset_cmd(JCR *jcr)
1443 {
1444    BSOCK *dir = jcr->dir_bsock;
1445    int rtnstat;
1446
1447 #if defined(WIN32_VSS)
1448    int vss = 0;
1449
1450    sscanf(dir->msg, "fileset vss=%d", &vss);
1451    enable_vss = vss;
1452 #endif
1453
1454    if (!init_fileset(jcr)) {
1455       return 0;
1456    }
1457    while (dir->recv() >= 0) {
1458       strip_trailing_junk(dir->msg);
1459       Dmsg1(500, "Fileset: %s\n", dir->msg);
1460       add_fileset(jcr, dir->msg);
1461    }
1462    if (!term_fileset(jcr)) {
1463       return 0;
1464    }
1465    rtnstat = dir->fsend(OKinc);
1466    generate_plugin_event(jcr, bEventEndFileSet);
1467    return rtnstat;
1468 }
1469
1470 static void free_bootstrap(JCR *jcr)
1471 {
1472    if (jcr->RestoreBootstrap) {
1473       unlink(jcr->RestoreBootstrap);
1474       free_pool_memory(jcr->RestoreBootstrap);
1475       jcr->RestoreBootstrap = NULL;
1476    }
1477 }
1478
1479
1480 static pthread_mutex_t bsr_mutex = PTHREAD_MUTEX_INITIALIZER;
1481 static uint32_t bsr_uniq = 0;
1482
1483 /**
1484  * The Director sends us the bootstrap file, which
1485  *   we will in turn pass to the SD.
1486  *   Deprecated.  The bsr is now sent directly from the
1487  *   Director to the SD.
1488  */
1489 static int bootstrap_cmd(JCR *jcr)
1490 {
1491    BSOCK *dir = jcr->dir_bsock;
1492    POOLMEM *fname = get_pool_memory(PM_FNAME);
1493    FILE *bs;
1494
1495    free_bootstrap(jcr);
1496    P(bsr_mutex);
1497    bsr_uniq++;
1498    Mmsg(fname, "%s/%s.%s.%d.bootstrap", me->working_directory, me->hdr.name,
1499       jcr->Job, bsr_uniq);
1500    V(bsr_mutex);
1501    Dmsg1(400, "bootstrap=%s\n", fname);
1502    jcr->RestoreBootstrap = fname;
1503    bs = fopen(fname, "a+b");           /* create file */
1504    if (!bs) {
1505       berrno be;
1506       Jmsg(jcr, M_FATAL, 0, _("Could not create bootstrap file %s: ERR=%s\n"),
1507          jcr->RestoreBootstrap, be.bstrerror());
1508       /*
1509        * Suck up what he is sending to us so that he will then
1510        *   read our error message.
1511        */
1512       while (dir->recv() >= 0)
1513         {  }
1514       free_bootstrap(jcr);
1515       jcr->setJobStatus(JS_ErrorTerminated);
1516       return 0;
1517    }
1518
1519    while (dir->recv() >= 0) {
1520        Dmsg1(200, "filed<dird: bootstrap: %s", dir->msg);
1521        fputs(dir->msg, bs);
1522    }
1523    fclose(bs);
1524    /*
1525     * Note, do not free the bootstrap yet -- it needs to be 
1526     *  sent to the SD 
1527     */
1528    return dir->fsend(OKbootstrap);
1529 }
1530
1531
1532 /**
1533  * Get backup level from Director
1534  *
1535  */
1536 static int level_cmd(JCR *jcr)
1537 {
1538    BSOCK *dir = jcr->dir_bsock;
1539    POOLMEM *level, *buf = NULL;
1540    int mtime_only;
1541
1542    level = get_memory(dir->msglen+1);
1543    Dmsg1(10, "level_cmd: %s", dir->msg);
1544
1545    /* keep compatibility with older directors */
1546    if (strstr(dir->msg, "accurate")) {
1547       jcr->accurate = true;
1548    }
1549    if (strstr(dir->msg, "rerunning")) {
1550       jcr->rerunning = true;
1551    }
1552    if (sscanf(dir->msg, "level = %s ", level) != 1) {
1553       goto bail_out;
1554    }
1555    /* Base backup requested? */
1556    if (strcmp(level, "base") == 0) {
1557       jcr->setJobLevel(L_BASE);
1558    /* Full backup requested? */
1559    } else if (strcmp(level, "full") == 0) {
1560       jcr->setJobLevel(L_FULL);
1561    } else if (strstr(level, "differential")) {
1562       jcr->setJobLevel(L_DIFFERENTIAL);
1563       free_memory(level);
1564       return 1;
1565    } else if (strstr(level, "incremental")) {
1566       jcr->setJobLevel(L_INCREMENTAL);
1567       free_memory(level);
1568       return 1;
1569    /*
1570     * We get his UTC since time, then sync the clocks and correct it
1571     *   to agree with our clock.
1572     */
1573    } else if (strcmp(level, "since_utime") == 0) {
1574       buf = get_memory(dir->msglen+1);
1575       utime_t since_time, adj;
1576       btime_t his_time, bt_start, rt=0, bt_adj=0;
1577       if (jcr->getJobLevel() == L_NONE) {
1578          jcr->setJobLevel(L_SINCE);     /* if no other job level set, do it now */
1579       }
1580       if (sscanf(dir->msg, "level = since_utime %s mtime_only=%d",
1581                  buf, &mtime_only) != 2) {
1582          goto bail_out;
1583       }
1584       since_time = str_to_uint64(buf);  /* this is the since time */
1585       Dmsg1(100, "since_time=%lld\n", since_time);
1586       char ed1[50], ed2[50];
1587       /*
1588        * Sync clocks by polling him for the time. We take
1589        *   10 samples of his time throwing out the first two.
1590        */
1591       for (int i=0; i<10; i++) {
1592          bt_start = get_current_btime();
1593          dir->signal(BNET_BTIME);     /* poll for time */
1594          if (dir->recv() <= 0) {      /* get response */
1595             goto bail_out;
1596          }
1597          if (sscanf(dir->msg, "btime %s", buf) != 1) {
1598             goto bail_out;
1599          }
1600          if (i < 2) {                 /* toss first two results */
1601             continue;
1602          }
1603          his_time = str_to_uint64(buf);
1604          rt = get_current_btime() - bt_start; /* compute round trip time */
1605          Dmsg2(100, "Dirtime=%s FDtime=%s\n", edit_uint64(his_time, ed1),
1606                edit_uint64(bt_start, ed2));
1607          bt_adj +=  bt_start - his_time - rt/2;
1608          Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1609       }
1610
1611       bt_adj = bt_adj / 8;            /* compute average time */
1612       Dmsg2(100, "rt=%s adj=%s\n", edit_uint64(rt, ed1), edit_uint64(bt_adj, ed2));
1613       adj = btime_to_utime(bt_adj);
1614       since_time += adj;              /* adjust for clock difference */
1615       /* Don't notify if time within 3 seconds */
1616       if (adj > 3 || adj < -3) {
1617          int type;
1618          if (adj > 600 || adj < -600) {
1619             type = M_WARNING;
1620          } else {
1621             type = M_INFO;
1622          }
1623          Jmsg(jcr, type, 0, _("DIR and FD clocks differ by %lld seconds, FD automatically compensating.\n"), adj);
1624       }
1625       dir->signal(BNET_EOD);
1626
1627       Dmsg2(100, "adj=%lld since_time=%lld\n", adj, since_time);
1628       jcr->incremental = 1;           /* set incremental or decremental backup */
1629       jcr->mtime = since_time;        /* set since time */
1630       generate_plugin_event(jcr, bEventSince, (void *)(time_t)jcr->mtime);
1631    } else {
1632       Jmsg1(jcr, M_FATAL, 0, _("Unknown backup level: %s\n"), level);
1633       free_memory(level);
1634       return 0;
1635    }
1636    free_memory(level);
1637    if (buf) {
1638       free_memory(buf);
1639    }
1640    generate_plugin_event(jcr, bEventLevel, (void*)(intptr_t)jcr->getJobLevel());
1641    return dir->fsend(OKlevel);
1642
1643 bail_out:
1644    pm_strcpy(jcr->errmsg, dir->msg);
1645    Jmsg1(jcr, M_FATAL, 0, _("Bad level command: %s\n"), jcr->errmsg);
1646    free_memory(level);
1647    if (buf) {
1648       free_memory(buf);
1649    }
1650    return 0;
1651 }
1652
1653 /**
1654  * Get session parameters from Director -- this is for a Restore command
1655  *   This is deprecated. It is now passed via the bsr.
1656  */
1657 static int session_cmd(JCR *jcr)
1658 {
1659    BSOCK *dir = jcr->dir_bsock;
1660
1661    Dmsg1(100, "SessionCmd: %s", dir->msg);
1662    if (sscanf(dir->msg, sessioncmd, jcr->VolumeName,
1663               &jcr->VolSessionId, &jcr->VolSessionTime,
1664               &jcr->StartFile, &jcr->EndFile,
1665               &jcr->StartBlock, &jcr->EndBlock) != 7) {
1666       pm_strcpy(jcr->errmsg, dir->msg);
1667       Jmsg(jcr, M_FATAL, 0, _("Bad session command: %s"), jcr->errmsg);
1668       return 0;
1669    }
1670
1671    return dir->fsend(OKsession);
1672 }
1673
1674 static void set_storage_auth_key(JCR *jcr, char *key)
1675 {
1676    /* if no key don't update anything */
1677    if (!*key) {                
1678       return;
1679    }
1680
1681    /**
1682     * We can be contacting multiple storage daemons.
1683     * So, make sure that any old jcr->store_bsock is cleaned up. 
1684     */
1685    if (jcr->store_bsock) {
1686       jcr->store_bsock->destroy();
1687       jcr->store_bsock = NULL;
1688    }
1689
1690    /**
1691     * We can be contacting multiple storage daemons.
1692     *   So, make sure that any old jcr->sd_auth_key is cleaned up. 
1693     */
1694    if (jcr->sd_auth_key) {
1695       /*
1696        * If we already have a Authorization key, director can do multi
1697        * storage restore
1698        */
1699       Dmsg0(5, "set multi_restore=true\n");
1700       jcr->multi_restore = true;
1701       bfree(jcr->sd_auth_key);
1702    }
1703
1704    jcr->sd_auth_key = bstrdup(key);
1705    Dmsg0(5, "set sd auth key\n");
1706 }
1707
1708 /**
1709  * Get address of storage daemon from Director
1710  *
1711  */
1712 static int storage_cmd(JCR *jcr)
1713 {
1714    int stored_port;                /* storage daemon port */
1715    int enable_ssl;                 /* enable ssl to sd */
1716    POOL_MEM sd_auth_key(PM_MESSAGE);
1717    BSOCK *dir = jcr->dir_bsock;
1718    BSOCK *sd = new_bsock();        /* storage daemon bsock */
1719
1720
1721    Dmsg1(100, "StorageCmd: %s", dir->msg);
1722    sd_auth_key.check_size(dir->msglen);
1723    if (sscanf(dir->msg, storaddr, &jcr->stored_addr, &stored_port, 
1724               &enable_ssl, sd_auth_key.c_str()) != 4) {
1725       if (sscanf(dir->msg, storaddr_v1, &jcr->stored_addr,
1726                  &stored_port, &enable_ssl) != 3) {
1727          pm_strcpy(jcr->errmsg, dir->msg);
1728          Jmsg(jcr, M_FATAL, 0, _("Bad storage command: %s"), jcr->errmsg);
1729          goto bail_out;
1730       }
1731    }
1732
1733    set_storage_auth_key(jcr, sd_auth_key.c_str());
1734
1735    Dmsg3(110, "Open storage: %s:%d ssl=%d\n", jcr->stored_addr, stored_port, 
1736          enable_ssl);
1737    /* Open command communications with Storage daemon */
1738    /* Try to connect for 1 hour at 10 second intervals */
1739
1740    sd->set_source_address(me->FDsrc_addr);
1741 <<<<<<< HEAD
1742 =======
1743
1744 >>>>>>> caaa5db... Implement RestoreObject for sqlite + cleanups
1745    if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
1746                 _("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
1747      sd->destroy();
1748      sd = NULL;
1749    }
1750
1751    if (sd == NULL) {
1752       Jmsg(jcr, M_FATAL, 0, _("Failed to connect to Storage daemon: %s:%d\n"),
1753           jcr->stored_addr, stored_port);
1754       Dmsg2(100, "Failed to connect to Storage daemon: %s:%d\n",
1755           jcr->stored_addr, stored_port);
1756       goto bail_out;
1757    }
1758    Dmsg0(110, "Connection OK to SD.\n");
1759
1760    jcr->store_bsock = sd;
1761
1762    sd->fsend("Hello Start Job %s\n", jcr->Job);
1763    if (!authenticate_storagedaemon(jcr)) {
1764       Jmsg(jcr, M_FATAL, 0, _("Failed to authenticate Storage daemon.\n"));
1765       goto bail_out;
1766    }
1767    Dmsg0(110, "Authenticated with SD.\n");
1768
1769    /* Send OK to Director */
1770    return dir->fsend(OKstore);
1771
1772 bail_out:
1773    dir->fsend(BADcmd, "storage");
1774    return 0;
1775
1776 }
1777
1778
1779 /**
1780  * Do a backup.
1781  */
1782 static int backup_cmd(JCR *jcr)
1783 {
1784    BSOCK *dir = jcr->dir_bsock;
1785    BSOCK *sd = jcr->store_bsock;
1786    int ok = 0;
1787    int SDJobStatus;
1788    int32_t FileIndex;
1789
1790 #if defined(WIN32_VSS)
1791    // capture state here, if client is backed up by multiple directors
1792    // and one enables vss and the other does not then enable_vss can change
1793    // between here and where its evaluated after the job completes.
1794    jcr->VSS = g_pVSSClient && enable_vss;
1795    if (jcr->VSS) {
1796       /* Run only one at a time */
1797       P(vss_mutex);
1798    }
1799 #endif
1800   
1801    if (sscanf(dir->msg, "backup FileIndex=%ld\n", &FileIndex) == 1) {
1802       jcr->JobFiles = FileIndex;
1803       Dmsg1(100, "JobFiles=%ld\n", jcr->JobFiles);
1804    }
1805
1806    /**
1807     * Validate some options given to the backup make sense for the compiled in
1808     * options of this filed.
1809     */
1810    if (jcr->ff->flags & FO_ACL && !have_acl) {
1811       Jmsg(jcr, M_FATAL, 0, _("ACL support not configured for your machine.\n"));
1812       goto cleanup;
1813    }
1814    if (jcr->ff->flags & FO_XATTR && !have_xattr) {
1815       Jmsg(jcr, M_FATAL, 0, _("XATTR support not configured for your machine.\n"));
1816       goto cleanup;
1817    }
1818
1819    jcr->setJobStatus(JS_Blocked);
1820    jcr->setJobType(JT_BACKUP);
1821    Dmsg1(100, "begin backup ff=%p\n", jcr->ff);
1822
1823    if (sd == NULL) {
1824       Jmsg(jcr, M_FATAL, 0, _("Cannot contact Storage daemon\n"));
1825       dir->fsend(BADcmd, "backup");
1826       goto cleanup;
1827    }
1828
1829    dir->fsend(OKbackup);
1830    Dmsg1(110, "filed>dird: %s", dir->msg);
1831
1832    /**
1833     * Send Append Open Session to Storage daemon
1834     */
1835    sd->fsend(append_open);
1836    Dmsg1(110, ">stored: %s", sd->msg);
1837    /**
1838     * Expect to receive back the Ticket number
1839     */
1840    if (bget_msg(sd) >= 0) {
1841       Dmsg1(110, "<stored: %s", sd->msg);
1842       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
1843          Jmsg(jcr, M_FATAL, 0, _("Bad response to append open: %s\n"), sd->msg);
1844          goto cleanup;
1845       }
1846       Dmsg1(110, "Got Ticket=%d\n", jcr->Ticket);
1847    } else {
1848       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to open command\n"));
1849       goto cleanup;
1850    }
1851
1852    /**
1853     * Send Append data command to Storage daemon
1854     */
1855    sd->fsend(append_data, jcr->Ticket);
1856    Dmsg1(110, ">stored: %s", sd->msg);
1857
1858    /**
1859     * Expect to get OK data
1860     */
1861    Dmsg1(110, "<stored: %s", sd->msg);
1862    if (!response(jcr, sd, OK_data, "Append Data")) {
1863       goto cleanup;
1864    }
1865    
1866    generate_daemon_event(jcr, "JobStart");
1867    generate_plugin_event(jcr, bEventStartBackupJob);
1868
1869 #if defined(WIN32_VSS)
1870    /* START VSS ON WIN32 */
1871    if (jcr->VSS) {      
1872       if (g_pVSSClient->InitializeForBackup(jcr)) {   
1873         generate_plugin_event(jcr, bEventVssBackupAddComponents);
1874         /* tell vss which drives to snapshot */   
1875         char szWinDriveLetters[27];
1876         *szWinDriveLetters=0;
1877         generate_plugin_event(jcr, bEventVssPrepareSnapshot, szWinDriveLetters);
1878         if (get_win32_driveletters(jcr->ff, szWinDriveLetters)) {
1879             Jmsg(jcr, M_INFO, 0, _("Generate VSS snapshots. Driver=\"%s\", Drive(s)=\"%s\"\n"), g_pVSSClient->GetDriverName(), szWinDriveLetters);
1880             if (!g_pVSSClient->CreateSnapshots(szWinDriveLetters)) {               
1881                berrno be;
1882                Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshots failed. ERR=%s\n"), be.bstrerror());
1883             } else {
1884                /* tell user if snapshot creation of a specific drive failed */
1885                int i;
1886                for (i=0; i < (int)strlen(szWinDriveLetters); i++) {
1887                   if (islower(szWinDriveLetters[i])) {
1888                      Jmsg(jcr, M_FATAL, 0, _("Generate VSS snapshot of drive \"%c:\\\" failed.\n"), szWinDriveLetters[i]);
1889                   }
1890                }
1891                /* inform user about writer states */
1892                for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {               
1893                   if (g_pVSSClient->GetWriterState(i) < 1) {
1894                      Jmsg(jcr, M_INFO, 0, _("VSS Writer (PrepareForBackup): %s\n"), g_pVSSClient->GetWriterInfo(i));                    
1895                   }                            
1896                }
1897             }
1898         } else {
1899             Jmsg(jcr, M_FATAL, 0, _("No drive letters found for generating VSS snapshots.\n"));
1900         }
1901       } else {
1902          berrno be;
1903          Jmsg(jcr, M_FATAL, 0, _("VSS was not initialized properly. ERR=%s\n"), be.bstrerror());
1904       } 
1905       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
1906    }
1907 #endif
1908
1909    /**
1910     * Send Files to Storage daemon
1911     */
1912    Dmsg1(110, "begin blast ff=%p\n", (FF_PKT *)jcr->ff);
1913    if (!blast_data_to_storage_daemon(jcr, NULL)) {
1914       jcr->setJobStatus(JS_ErrorTerminated);
1915       bnet_suppress_error_messages(sd, 1);
1916       Dmsg0(110, "Error in blast_data.\n");
1917    } else {
1918       jcr->setJobStatus(JS_Terminated);
1919       /* Note, the above set status will not override an error */
1920       if (!(jcr->JobStatus == JS_Terminated || jcr->JobStatus == JS_Warnings)) {
1921          bnet_suppress_error_messages(sd, 1);
1922          goto cleanup;                /* bail out now */
1923       }
1924       /**
1925        * Expect to get response to append_data from Storage daemon
1926        */
1927       if (!response(jcr, sd, OK_append, "Append Data")) {
1928          jcr->setJobStatus(JS_ErrorTerminated);
1929          goto cleanup;
1930       }
1931
1932       /**
1933        * Send Append End Data to Storage daemon
1934        */
1935       sd->fsend(append_end, jcr->Ticket);
1936       /* Get end OK */
1937       if (!response(jcr, sd, OK_end, "Append End")) {
1938          jcr->setJobStatus(JS_ErrorTerminated);
1939          goto cleanup;
1940       }
1941
1942       /**
1943        * Send Append Close to Storage daemon
1944        */
1945       sd->fsend(append_close, jcr->Ticket);
1946       while (bget_msg(sd) >= 0) {    /* stop on signal or error */
1947          if (sscanf(sd->msg, OK_close, &SDJobStatus) == 1) {
1948             ok = 1;
1949             Dmsg2(200, "SDJobStatus = %d %c\n", SDJobStatus, (char)SDJobStatus);
1950          }
1951       }
1952       if (!ok) {
1953          Jmsg(jcr, M_FATAL, 0, _("Append Close with SD failed.\n"));
1954          goto cleanup;
1955       }
1956       if (!(SDJobStatus == JS_Terminated || SDJobStatus == JS_Warnings)) {
1957          Jmsg(jcr, M_FATAL, 0, _("Bad status %d returned from Storage Daemon.\n"),
1958             SDJobStatus);
1959       }
1960    }
1961
1962 cleanup:
1963 #if defined(WIN32_VSS)
1964    if (jcr->VSS) {
1965       Win32ConvCleanupCache();
1966       g_pVSSClient->DestroyWriterInfo();
1967       V(vss_mutex);
1968    }
1969 #endif
1970
1971    generate_plugin_event(jcr, bEventEndBackupJob);
1972    return 0;                          /* return and stop command loop */
1973 }
1974
1975 /**
1976  * Do a Verify for Director
1977  *
1978  */
1979 static int verify_cmd(JCR *jcr)
1980 {
1981    BSOCK *dir = jcr->dir_bsock;
1982    BSOCK *sd  = jcr->store_bsock;
1983    char level[100];
1984
1985    jcr->setJobType(JT_VERIFY);
1986    if (sscanf(dir->msg, verifycmd, level) != 1) {
1987       dir->fsend(_("2994 Bad verify command: %s\n"), dir->msg);
1988       return 0;
1989    }
1990
1991    if (strcasecmp(level, "init") == 0) {
1992       jcr->setJobLevel(L_VERIFY_INIT);
1993    } else if (strcasecmp(level, "catalog") == 0){
1994       jcr->setJobLevel(L_VERIFY_CATALOG);
1995    } else if (strcasecmp(level, "volume") == 0){
1996       jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
1997    } else if (strcasecmp(level, "data") == 0){
1998       jcr->setJobLevel(L_VERIFY_DATA);
1999    } else if (strcasecmp(level, "disk_to_catalog") == 0) {
2000       jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
2001    } else {
2002       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2003       return 0;
2004    }
2005
2006    dir->fsend(OKverify);
2007
2008    generate_daemon_event(jcr, "JobStart");
2009    generate_plugin_event(jcr, bEventLevel,(void *)(intptr_t)jcr->getJobLevel());
2010    generate_plugin_event(jcr, bEventStartVerifyJob);
2011
2012    Dmsg1(110, "filed>dird: %s", dir->msg);
2013
2014    switch (jcr->getJobLevel()) {
2015    case L_VERIFY_INIT:
2016    case L_VERIFY_CATALOG:
2017       do_verify(jcr);
2018       break;
2019    case L_VERIFY_VOLUME_TO_CATALOG:
2020       if (!open_sd_read_session(jcr)) {
2021          return 0;
2022       }
2023       start_dir_heartbeat(jcr);
2024       do_verify_volume(jcr);
2025       stop_dir_heartbeat(jcr);
2026       /*
2027        * Send Close session command to Storage daemon
2028        */
2029       sd->fsend(read_close, jcr->Ticket);
2030       Dmsg1(130, "filed>stored: %s", sd->msg);
2031
2032       /* ****FIXME**** check response */
2033       bget_msg(sd);                      /* get OK */
2034
2035       /* Inform Storage daemon that we are done */
2036       sd->signal(BNET_TERMINATE);
2037
2038       break;
2039    case L_VERIFY_DISK_TO_CATALOG:
2040       do_verify(jcr);
2041       break;
2042    default:
2043       dir->fsend(_("2994 Bad verify level: %s\n"), dir->msg);
2044       return 0;
2045    }
2046
2047    dir->signal(BNET_EOD);
2048    generate_plugin_event(jcr, bEventEndVerifyJob);
2049    return 0;                          /* return and terminate command loop */
2050 }
2051
2052 #ifdef WIN32_VSS
2053 static bool vss_restore_init_callback(JCR *jcr, int init_type)
2054 {
2055    switch (init_type) {
2056    case VSS_INIT_RESTORE_AFTER_INIT:
2057       generate_plugin_event(jcr, bEventVssRestoreLoadComponentMetadata);
2058       return true;
2059    case VSS_INIT_RESTORE_AFTER_GATHER:
2060       generate_plugin_event(jcr, bEventVssRestoreSetComponentsSelected);
2061       return true;
2062    default:
2063       return false;
2064       break;
2065    }
2066 }
2067 #endif
2068
2069 /**
2070  * Do a Restore for Director
2071  *
2072  */
2073 static int restore_cmd(JCR *jcr)
2074 {
2075    BSOCK *dir = jcr->dir_bsock;
2076    BSOCK *sd = jcr->store_bsock;
2077    POOLMEM *args;
2078    bool use_regexwhere=false;
2079    int prefix_links;
2080    char replace;
2081
2082    /**
2083     * Scan WHERE (base directory for restore) from command
2084     */
2085    Dmsg0(100, "restore command\n");
2086 #if defined(WIN32_VSS)
2087
2088    /**
2089     * No need to enable VSS for restore if we do not have plugin
2090     *  data to restore 
2091     */
2092    enable_vss = jcr->job_metadata != NULL;
2093
2094    Dmsg2(50, "g_pVSSClient = %p, enable_vss = %d\n", g_pVSSClient, enable_vss);
2095    // capture state here, if client is backed up by multiple directors
2096    // and one enables vss and the other does not then enable_vss can change
2097    // between here and where its evaluated after the job completes.
2098    jcr->VSS = g_pVSSClient && enable_vss;
2099    if (jcr->VSS) {
2100       /* Run only one at a time */
2101       P(vss_mutex);
2102    }
2103 #endif
2104    /* Pickup where string */
2105    args = get_memory(dir->msglen+1);
2106    *args = 0;
2107
2108    if (sscanf(dir->msg, restorecmd, &replace, &prefix_links, args) != 3) {
2109       if (sscanf(dir->msg, restorecmdR, &replace, &prefix_links, args) != 3){
2110          if (sscanf(dir->msg, restorecmd1, &replace, &prefix_links) != 2) {
2111             pm_strcpy(jcr->errmsg, dir->msg);
2112             Jmsg(jcr, M_FATAL, 0, _("Bad replace command. CMD=%s\n"), jcr->errmsg);
2113             return 0;
2114          }
2115          *args = 0;
2116       }
2117       use_regexwhere = true;
2118    }
2119    /* Turn / into nothing */
2120    if (IsPathSeparator(args[0]) && args[1] == '\0') {
2121       args[0] = '\0';
2122    }
2123
2124    Dmsg2(150, "Got replace %c, where=%s\n", replace, args);
2125    unbash_spaces(args);
2126
2127    if (use_regexwhere) {
2128       jcr->where_bregexp = get_bregexps(args);
2129       if (!jcr->where_bregexp) {
2130          Jmsg(jcr, M_FATAL, 0, _("Bad where regexp. where=%s\n"), args);
2131          free_pool_memory(args);
2132          return 0;
2133       }
2134    } else {
2135       jcr->where = bstrdup(args);
2136    }
2137
2138    free_pool_memory(args);
2139    jcr->replace = replace;
2140    jcr->prefix_links = prefix_links;
2141
2142    dir->fsend(OKrestore);
2143    Dmsg1(110, "filed>dird: %s", dir->msg);
2144
2145    jcr->setJobType(JT_RESTORE);
2146
2147    jcr->setJobStatus(JS_Blocked);
2148
2149    if (!open_sd_read_session(jcr)) {
2150       jcr->setJobStatus(JS_ErrorTerminated);
2151       goto bail_out;
2152    }
2153
2154    jcr->setJobStatus(JS_Running);
2155
2156    /**
2157     * Do restore of files and data
2158     */
2159    start_dir_heartbeat(jcr);
2160    generate_daemon_event(jcr, "JobStart");
2161    generate_plugin_event(jcr, bEventStartRestoreJob);
2162
2163 #if defined(WIN32_VSS)
2164    /* START VSS ON WIN32 */
2165    if (jcr->VSS) {
2166       if (g_pVSSClient->InitializeForRestore(jcr, vss_restore_init_callback,
2167             (WCHAR *)jcr->job_metadata)) {
2168
2169          /* inform user about writer states */
2170          int i;
2171          for (i=0; i < (int)g_pVSSClient->GetWriterCount(); i++) {
2172             if (g_pVSSClient->GetWriterState(i) < 1) {
2173                Jmsg(jcr, M_INFO, 0, _("VSS Writer (PreRestore): %s\n"), g_pVSSClient->GetWriterInfo(i));
2174                //jcr->JobErrors++;
2175             }
2176          }
2177       } else {
2178 /*
2179    int fd = open("C:\\eric.xml", O_CREAT | O_WRONLY | O_TRUNC, 0777);
2180    write(fd, (WCHAR *)jcr->job_metadata, wcslen((WCHAR *)jcr->job_metadata) * sizeof(WCHAR));
2181    close(fd);
2182 */
2183          berrno be;
2184          Jmsg(jcr, M_WARNING, 0, _("VSS was not initialized properly. VSS support is disabled. ERR=%s\n"), be.bstrerror());
2185       }
2186       free_and_null_pool_memory(jcr->job_metadata);
2187       run_scripts(jcr, jcr->RunScripts, "ClientAfterVSS");
2188    }
2189 #endif
2190
2191    do_restore(jcr);
2192    stop_dir_heartbeat(jcr);
2193
2194    jcr->setJobStatus(JS_Terminated);
2195    if (jcr->JobStatus != JS_Terminated) {
2196       bnet_suppress_error_messages(sd, 1);
2197    }
2198
2199    /**
2200     * Send Close session command to Storage daemon
2201     */
2202    sd->fsend(read_close, jcr->Ticket);
2203    Dmsg1(100, "filed>stored: %s", sd->msg);
2204
2205    bget_msg(sd);                      /* get OK */
2206
2207    /* Inform Storage daemon that we are done */
2208    sd->signal(BNET_TERMINATE);
2209
2210 #if defined(WIN32_VSS)
2211    /* STOP VSS ON WIN32 */
2212    /* tell vss to close the restore session */
2213    Dmsg0(100, "About to call CloseRestore\n");
2214    if (jcr->VSS) {
2215       generate_plugin_event(jcr, bEventVssBeforeCloseRestore);
2216       Dmsg0(100, "Really about to call CloseRestore\n");
2217       if (g_pVSSClient->CloseRestore()) {
2218          Dmsg0(100, "CloseRestore success\n");
2219          /* inform user about writer states */
2220          for (int i=0; i<(int)g_pVSSClient->GetWriterCount(); i++) {
2221             int msg_type = M_INFO;
2222             if (g_pVSSClient->GetWriterState(i) < 1) {
2223                //msg_type = M_WARNING;
2224                //jcr->JobErrors++;
2225             }
2226             Jmsg(jcr, msg_type, 0, _("VSS Writer (RestoreComplete): %s\n"), g_pVSSClient->GetWriterInfo(i));
2227          }
2228       }
2229       else
2230          Dmsg1(100, "CloseRestore fail - %08x\n", errno);
2231       V(vss_mutex);
2232    }
2233 #endif
2234
2235 bail_out:
2236    bfree_and_null(jcr->where);
2237
2238    if (jcr->JobErrors) {
2239       jcr->setJobStatus(JS_ErrorTerminated);
2240    }
2241
2242    Dmsg0(100, "Done in job.c\n");
2243
2244    int ret;
2245    if (jcr->multi_restore) {
2246       Dmsg0(100, OKstoreend);
2247       dir->fsend(OKstoreend);
2248       ret = 1;     /* we continue the loop, waiting for next part */
2249    } else {
2250       end_restore_cmd(jcr);
2251       ret = 0;     /* we stop here */
2252    }
2253
2254    if (job_canceled(jcr)) {
2255       ret = 0;     /* we stop here */
2256    }
2257
2258    return ret;
2259 }
2260
2261 static int end_restore_cmd(JCR *jcr) 
2262 {
2263    Dmsg0(5, "end_restore_cmd\n");
2264    generate_plugin_event(jcr, bEventEndRestoreJob);
2265    return 0;                          /* return and terminate command loop */
2266 }
2267
2268 static int open_sd_read_session(JCR *jcr)
2269 {
2270    BSOCK *sd = jcr->store_bsock;
2271
2272    if (!sd) {
2273       Jmsg(jcr, M_FATAL, 0, _("Improper calling sequence.\n"));
2274       return 0;
2275    }
2276    Dmsg4(120, "VolSessId=%ld VolsessT=%ld SF=%ld EF=%ld\n",
2277       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile);
2278    Dmsg2(120, "JobId=%d vol=%s\n", jcr->JobId, "DummyVolume");
2279    /*
2280     * Open Read Session with Storage daemon
2281     */
2282    sd->fsend(read_open, "DummyVolume",
2283       jcr->VolSessionId, jcr->VolSessionTime, jcr->StartFile, jcr->EndFile,
2284       jcr->StartBlock, jcr->EndBlock);
2285    Dmsg1(110, ">stored: %s", sd->msg);
2286
2287    /*
2288     * Get ticket number
2289     */
2290    if (bget_msg(sd) >= 0) {
2291       Dmsg1(110, "filed<stored: %s", sd->msg);
2292       if (sscanf(sd->msg, OK_open, &jcr->Ticket) != 1) {
2293          Jmsg(jcr, M_FATAL, 0, _("Bad response to SD read open: %s\n"), sd->msg);
2294          return 0;
2295       }
2296       Dmsg1(110, "filed: got Ticket=%d\n", jcr->Ticket);
2297    } else {
2298       Jmsg(jcr, M_FATAL, 0, _("Bad response from stored to read open command\n"));
2299       return 0;
2300    }
2301
2302    if (!send_bootstrap_file(jcr)) {
2303       return 0;
2304    }
2305
2306    /*
2307     * Start read of data with Storage daemon
2308     */
2309    sd->fsend(read_data, jcr->Ticket);
2310    Dmsg1(110, ">stored: %s", sd->msg);
2311
2312    /*
2313     * Get OK data
2314     */
2315    if (!response(jcr, sd, OK_data, "Read Data")) {
2316       return 0;
2317    }
2318    return 1;
2319 }
2320
2321 /**
2322  * Destroy the Job Control Record and associated
2323  * resources (sockets).
2324  */
2325 static void filed_free_jcr(JCR *jcr)
2326 {
2327    if (jcr->store_bsock) {
2328       jcr->store_bsock->close();
2329    }
2330    free_bootstrap(jcr);
2331    if (jcr->last_fname) {
2332       free_pool_memory(jcr->last_fname);
2333    }
2334    free_runscripts(jcr->RunScripts);
2335    delete jcr->RunScripts;
2336
2337    if (jcr->JobId != 0)
2338       write_state_file(me->working_directory, "bacula-fd", get_first_port_host_order(me->FDaddrs));
2339
2340    return;
2341 }
2342
2343 /**
2344  * Get response from Storage daemon to a command we
2345  * sent. Check that the response is OK.
2346  *
2347  *  Returns: 0 on failure
2348  *           1 on success
2349  */
2350 int response(JCR *jcr, BSOCK *sd, char *resp, const char *cmd)
2351 {
2352    if (sd->errors) {
2353       return 0;
2354    }
2355    if (bget_msg(sd) > 0) {
2356       Dmsg0(110, sd->msg);
2357       if (strcmp(sd->msg, resp) == 0) {
2358          return 1;
2359       }
2360    }
2361    if (job_canceled(jcr)) {
2362       return 0;                       /* if canceled avoid useless error messages */
2363    }
2364    if (is_bnet_error(sd)) {
2365       Jmsg2(jcr, M_FATAL, 0, _("Comm error with SD. bad response to %s. ERR=%s\n"),
2366          cmd, bnet_strerror(sd));
2367    } else {
2368       Jmsg3(jcr, M_FATAL, 0, _("Bad response to %s command. Wanted %s, got %s\n"),
2369          cmd, resp, sd->msg);
2370    }
2371    return 0;
2372 }
2373
2374 static int send_bootstrap_file(JCR *jcr)
2375 {
2376    FILE *bs;
2377    char buf[2000];
2378    BSOCK *sd = jcr->store_bsock;
2379    const char *bootstrap = "bootstrap\n";
2380    int stat = 0;
2381
2382    Dmsg1(400, "send_bootstrap_file: %s\n", jcr->RestoreBootstrap);
2383    if (!jcr->RestoreBootstrap) {
2384       return 1;
2385    }
2386    bs = fopen(jcr->RestoreBootstrap, "rb");
2387    if (!bs) {
2388       berrno be;
2389       Jmsg(jcr, M_FATAL, 0, _("Could not open bootstrap file %s: ERR=%s\n"),
2390          jcr->RestoreBootstrap, be.bstrerror());
2391       jcr->setJobStatus(JS_ErrorTerminated);
2392       goto bail_out;
2393    }
2394    sd->msglen = pm_strcpy(sd->msg, bootstrap);
2395    sd->send();
2396    while (fgets(buf, sizeof(buf), bs)) {
2397       sd->msglen = Mmsg(sd->msg, "%s", buf);
2398       sd->send();
2399    }
2400    sd->signal(BNET_EOD);
2401    fclose(bs);
2402    if (!response(jcr, sd, OKSDbootstrap, "Bootstrap")) {
2403       jcr->setJobStatus(JS_ErrorTerminated);
2404       goto bail_out;
2405    }
2406    stat = 1;
2407
2408 bail_out:
2409    free_bootstrap(jcr);
2410    return stat;
2411 }