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