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