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