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