1 /*
2    Bacula(R) - The Network Backup Solution
3 
4    Copyright (C) 2000-2020 Kern Sibbald
5 
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8 
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13 
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16 
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *   Parse a Bootstrap Records (used for restores)
21  *
22  *     Kern Sibbald, June MMII
23  *
24  */
25 
26 
27 #include "bacula.h"
28 #include "stored.h"
29 
30 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...);
31 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol, bool add_to_read_list);
32 
33 typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
34 
35 static BSR *store_client(LEX *lc, BSR *bsr);
36 static BSR *store_count(LEX *lc, BSR *bsr);
37 static BSR *store_device(LEX *lc, BSR *bsr);
38 static BSR *store_exclude(LEX *lc, BSR *bsr);
39 static BSR *store_fileregex(LEX *lc, BSR *bsr);
40 static BSR *store_findex(LEX *lc, BSR *bsr);
41 static BSR *store_include(LEX *lc, BSR *bsr);
42 static BSR *store_jobid(LEX *lc, BSR *bsr);
43 static BSR *store_joblevel(LEX *lc, BSR *bsr);
44 static BSR *store_job(LEX *lc, BSR *bsr);
45 static BSR *store_jobtype(LEX *lc, BSR *bsr);
46 static BSR *store_mediatype(LEX *lc, BSR *bsr);
47 static BSR *store_nothing(LEX *lc, BSR *bsr);
48 static BSR *store_sessid(LEX *lc, BSR *bsr);
49 static BSR *store_sesstime(LEX *lc, BSR *bsr);
50 static BSR *store_slot(LEX *lc, BSR *bsr);
51 static BSR *store_stream(LEX *lc, BSR *bsr);
52 static BSR *store_voladdr(LEX *lc, BSR *bsr);
53 static BSR *store_volblock(LEX *lc, BSR *bsr);
54 static BSR *store_volfile(LEX *lc, BSR *bsr);
55 static BSR *store_vol(LEX *lc, BSR *bsr);
56 static bool is_fast_rejection_ok(BSR *bsr);
57 static bool is_positioning_ok(BSR *bsr);
58 
59 struct kw_items {
60    const char *name;
61    ITEM_HANDLER *handler;
62 };
63 
64 /*
65  * List of all keywords permitted in bsr files and their handlers
66  */
67 struct kw_items items[] = {
68    {"client",    store_client},
69    {"count",     store_count},
70    {"device",    store_device},
71    {"exclude",   store_exclude},
72    {"fileindex", store_findex},
73    {"fileregex", store_fileregex},
74    {"include",   store_include},
75    {"jobid",     store_jobid},
76    {"joblevel",  store_joblevel},
77    {"job",       store_job},
78    {"jobtype",   store_jobtype},
79    {"mediatype", store_mediatype},
80    {"slot",      store_slot},
81    {"storage",   store_nothing},
82    {"stream",    store_stream},
83    {"voladdr",   store_voladdr},
84    {"volblock",  store_volblock},
85    {"volume",    store_vol},
86    {"volfile",   store_volfile},
87    {"volsessionid",   store_sessid},
88    {"volsessiontime", store_sesstime},
89    {NULL, NULL}
90 };
91 
92 /*
93  * Create a BSR record
94  */
new_bsr()95 BSR *new_bsr()
96 {
97    BSR *bsr = (BSR *)malloc(sizeof(BSR));
98    memset(bsr, 0, sizeof(BSR));
99    return bsr;
100 }
101 
102 
103 /*********************************************************************
104  *
105  *      Parse Bootstrap file
106  *
107  */
parse_bsr(JCR * jcr,char * fname)108 BSR *parse_bsr(JCR *jcr, char *fname)
109 {
110    LEX *lc = NULL;
111    int token, i;
112    BSR *root_bsr = new_bsr();
113    BSR *bsr = root_bsr;
114 
115    Dmsg1(300, "Enter parse_bsf %s\n", fname);
116    if ((lc = lex_open_file(lc, fname, s_err)) == NULL) {
117       berrno be;
118       Emsg2(M_ERROR_TERM, 0, _("Cannot open bootstrap file %s: %s\n"),
119             fname, be.bstrerror());
120    }
121    lc->caller_ctx = (void *)jcr;
122    while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
123       Dmsg1(300, "parse got token=%s\n", lex_tok_to_str(token));
124       if (token == T_EOL) {
125          continue;
126       }
127       for (i=0; items[i].name; i++) {
128          if (strcasecmp(items[i].name, lc->str) == 0) {
129             token = lex_get_token(lc, T_ALL);
130             Dmsg1 (300, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
131             if (token != T_EQUALS) {
132                scan_err1(lc, "expected an equals, got: %s", lc->str);
133                bsr = NULL;
134                break;
135             }
136             Dmsg1(300, "calling handler for %s\n", items[i].name);
137             /* Call item handler */
138             bsr = items[i].handler(lc, bsr);
139             i = -1;
140             break;
141          }
142       }
143       if (i >= 0) {
144          Dmsg1(300, "Keyword = %s\n", lc->str);
145          scan_err1(lc, "Keyword %s not found", lc->str);
146          bsr = NULL;
147          break;
148       }
149       if (!bsr) {
150          break;
151       }
152    }
153    lc = lex_close_file(lc);
154    Dmsg0(300, "Leave parse_bsf()\n");
155    if (!bsr) {
156       free_bsr(root_bsr);
157       root_bsr = NULL;
158    }
159    if (root_bsr) {
160       root_bsr->use_fast_rejection = is_fast_rejection_ok(root_bsr);
161       root_bsr->use_positioning = is_positioning_ok(root_bsr);
162    }
163    for (bsr=root_bsr; bsr; bsr=bsr->next) {
164       bsr->root = root_bsr;
165    }
166    return root_bsr;
167 }
168 
store_client(LEX * lc,BSR * bsr)169 static BSR *store_client(LEX *lc, BSR *bsr)
170 {
171    int token;
172    BSR_CLIENT *client;
173 
174    for (;;) {
175       token = lex_get_token(lc, T_NAME);
176       if (token == T_ERROR) {
177          return NULL;
178       }
179       client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
180       memset(client, 0, sizeof(BSR_CLIENT));
181       bstrncpy(client->ClientName, lc->str, sizeof(client->ClientName));
182       /* Add it to the end of the client chain */
183       if (!bsr->client) {
184          bsr->client = client;
185       } else {
186          BSR_CLIENT *bc = bsr->client;
187          for ( ;bc->next; bc=bc->next)
188             { }
189          bc->next = client;
190       }
191       token = lex_get_token(lc, T_ALL);
192       if (token != T_COMMA) {
193          break;
194       }
195    }
196    return bsr;
197 }
198 
store_count(LEX * lc,BSR * bsr)199 static BSR *store_count(LEX *lc, BSR *bsr)
200 {
201    int token;
202 
203    token = lex_get_token(lc, T_PINT32);
204    if (token == T_ERROR) {
205       return NULL;
206    }
207    bsr->count = lc->pint32_val;
208    scan_to_eol(lc);
209    return bsr;
210 }
211 
212 /* Shove the Device name in each Volume in the current bsr */
store_device(LEX * lc,BSR * bsr)213 static BSR *store_device(LEX *lc, BSR *bsr)
214 {
215    int token;
216 
217    token = lex_get_token(lc, T_STRING);
218    if (token == T_ERROR) {
219       return NULL;
220    }
221    if (!bsr->volume) {
222       Emsg1(M_ERROR,0, _("Device \"%s\" in bsr at inappropriate place.\n"),
223          lc->str);
224       return bsr;
225    }
226    BSR_VOLUME *bv;
227    for (bv=bsr->volume; bv; bv=bv->next) {
228       bstrncpy(bv->device, lc->str, sizeof(bv->device));
229    }
230    return bsr;
231 }
232 
store_findex(LEX * lc,BSR * bsr)233 static BSR *store_findex(LEX *lc, BSR *bsr)
234 {
235    int token;
236    BSR_FINDEX *findex;
237 
238    for (;;) {
239       token = lex_get_token(lc, T_PINT32_RANGE);
240       if (token == T_ERROR) {
241          return NULL;
242       }
243       findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
244       memset(findex, 0, sizeof(BSR_FINDEX));
245       findex->findex = lc->pint32_val;
246       findex->findex2 = lc->pint32_val2;
247       /* Add it to the end of the chain */
248       if (!bsr->FileIndex) {
249          bsr->FileIndex = findex;
250       } else {
251          /* Add to end of chain */
252          BSR_FINDEX *bs = bsr->FileIndex;
253          for ( ;bs->next; bs=bs->next)
254             {  }
255          bs->next = findex;
256       }
257       token = lex_get_token(lc, T_ALL);
258       if (token != T_COMMA) {
259          break;
260       }
261    }
262    return bsr;
263 }
264 
store_fileregex(LEX * lc,BSR * bsr)265 static BSR *store_fileregex(LEX *lc, BSR *bsr)
266 {
267    int token;
268    int rc;
269 
270    token = lex_get_token(lc, T_STRING);
271    if (token == T_ERROR) {
272       return NULL;
273    }
274 
275    if (bsr->fileregex) free(bsr->fileregex);
276    bsr->fileregex = bstrdup(lc->str);
277 
278    if (bsr->fileregex_re == NULL)
279       bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));
280 
281    rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
282    if (rc != 0) {
283       char prbuf[500];
284       regerror(rc, bsr->fileregex_re, prbuf, sizeof(prbuf));
285       Emsg2(M_ERROR, 0, _("REGEX '%s' compile error. ERR=%s\n"),
286             bsr->fileregex, prbuf);
287       return NULL;
288    }
289    return bsr;
290 }
291 
store_jobid(LEX * lc,BSR * bsr)292 static BSR *store_jobid(LEX *lc, BSR *bsr)
293 {
294    int token;
295    BSR_JOBID *jobid;
296 
297    for (;;) {
298       token = lex_get_token(lc, T_PINT32_RANGE);
299       if (token == T_ERROR) {
300          return NULL;
301       }
302       jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
303       memset(jobid, 0, sizeof(BSR_JOBID));
304       jobid->JobId = lc->pint32_val;
305       jobid->JobId2 = lc->pint32_val2;
306       /* Add it to the end of the chain */
307       if (!bsr->JobId) {
308          bsr->JobId = jobid;
309       } else {
310          /* Add to end of chain */
311          BSR_JOBID *bs = bsr->JobId;
312          for ( ;bs->next; bs=bs->next)
313             {  }
314          bs->next = jobid;
315       }
316       token = lex_get_token(lc, T_ALL);
317       if (token != T_COMMA) {
318          break;
319       }
320    }
321    return bsr;
322 }
323 
324 
store_jobtype(LEX * lc,BSR * bsr)325 static BSR *store_jobtype(LEX *lc, BSR *bsr)
326 {
327    /* *****FIXME****** */
328    Pmsg0(-1, _("JobType not yet implemented\n"));
329    return bsr;
330 }
331 
332 
store_joblevel(LEX * lc,BSR * bsr)333 static BSR *store_joblevel(LEX *lc, BSR *bsr)
334 {
335    /* *****FIXME****** */
336    Pmsg0(-1, _("JobLevel not yet implemented\n"));
337    return bsr;
338 }
339 
store_job(LEX * lc,BSR * bsr)340 static BSR *store_job(LEX *lc, BSR *bsr)
341 {
342    int token;
343    BSR_JOB *job;
344 
345    for (;;) {
346       token = lex_get_token(lc, T_NAME);
347       if (token == T_ERROR) {
348          return NULL;
349       }
350       job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
351       memset(job, 0, sizeof(BSR_JOB));
352       bstrncpy(job->Job, lc->str, sizeof(job->Job));
353       /* Add it to the end of the client chain */
354       if (!bsr->job) {
355          bsr->job = job;
356       } else {
357          /* Add to end of chain */
358          BSR_JOB *bc = bsr->job;
359          for ( ;bc->next; bc=bc->next)
360             { }
361          bc->next = job;
362       }
363       token = lex_get_token(lc, T_ALL);
364       if (token != T_COMMA) {
365          break;
366       }
367    }
368    return bsr;
369 }
370 
371 /* Shove the MediaType in each Volume in the current bsr */
store_mediatype(LEX * lc,BSR * bsr)372 static BSR *store_mediatype(LEX *lc, BSR *bsr)
373 {
374    int token;
375 
376    token = lex_get_token(lc, T_STRING);
377    if (token == T_ERROR) {
378       return NULL;
379    }
380    if (!bsr->volume) {
381       Emsg1(M_ERROR,0, _("MediaType %s in bsr at inappropriate place.\n"),
382          lc->str);
383       return bsr;
384    }
385    BSR_VOLUME *bv;
386    for (bv=bsr->volume; bv; bv=bv->next) {
387       bstrncpy(bv->MediaType, lc->str, sizeof(bv->MediaType));
388    }
389    return bsr;
390 }
391 
store_vol(LEX * lc,BSR * bsr)392 static BSR *store_vol(LEX *lc, BSR *bsr)
393 {
394    int token;
395    BSR_VOLUME *volume;
396    char *p, *n;
397 
398    token = lex_get_token(lc, T_STRING);
399    if (token == T_ERROR) {
400       return NULL;
401    }
402    if (bsr->volume) {
403       bsr->next = new_bsr();
404       bsr->next->prev = bsr;
405       bsr = bsr->next;
406    }
407    /* This may actually be more than one volume separated by a |
408     * If so, separate them.
409     */
410    for (p=lc->str; p && *p; ) {
411       n = strchr(p, '|');
412       if (n) {
413          *n++ = 0;
414       }
415       volume = (BSR_VOLUME *)malloc(sizeof(BSR_VOLUME));
416       memset(volume, 0, sizeof(BSR_VOLUME));
417       bstrncpy(volume->VolumeName, p, sizeof(volume->VolumeName));
418       /* Add it to the end of the volume chain */
419       if (!bsr->volume) {
420          bsr->volume = volume;
421       } else {
422          BSR_VOLUME *bc = bsr->volume;
423          for ( ;bc->next; bc=bc->next)
424             { }
425          bc->next = volume;
426       }
427       p = n;
428    }
429    return bsr;
430 }
431 
is_positioning_ok(BSR * bsr)432 static bool is_positioning_ok(BSR *bsr)
433 {
434    /*
435     * Every bsr should have a volfile entry and a volblock entry
436     * or a VolAddr
437     *   if we are going to use positioning
438     */
439    for ( ; bsr; bsr=bsr->next) {
440       if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
441          return false;
442       }
443    }
444    return true;
445 }
446 
is_fast_rejection_ok(BSR * bsr)447 static bool is_fast_rejection_ok(BSR *bsr)
448 {
449    /*
450     * Although, this can be optimized, for the moment, require
451     *  all bsrs to have both sesstime and sessid set before
452     *  we do fast rejection.
453     */
454    for ( ; bsr; bsr=bsr->next) {
455       if (!(bsr->sesstime && bsr->sessid)) {
456          return false;
457       }
458    }
459    return true;
460 }
461 
462 
store_nothing(LEX * lc,BSR * bsr)463 static BSR *store_nothing(LEX *lc, BSR *bsr)
464 {
465    int token;
466 
467    token = lex_get_token(lc, T_STRING);
468    if (token == T_ERROR) {
469       return NULL;
470    }
471    return bsr;
472 }
473 
474 
475 
476 /*
477  * Routine to handle Volume start/end file
478  */
store_volfile(LEX * lc,BSR * bsr)479 static BSR *store_volfile(LEX *lc, BSR *bsr)
480 {
481    int token;
482    BSR_VOLFILE *volfile;
483 
484    for (;;) {
485       token = lex_get_token(lc, T_PINT32_RANGE);
486       if (token == T_ERROR) {
487          return NULL;
488       }
489       volfile = (BSR_VOLFILE *)malloc(sizeof(BSR_VOLFILE));
490       memset(volfile, 0, sizeof(BSR_VOLFILE));
491       volfile->sfile = lc->pint32_val;
492       volfile->efile = lc->pint32_val2;
493       /* Add it to the end of the chain */
494       if (!bsr->volfile) {
495          bsr->volfile = volfile;
496       } else {
497          /* Add to end of chain */
498          BSR_VOLFILE *bs = bsr->volfile;
499          for ( ;bs->next; bs=bs->next)
500             {  }
501          bs->next = volfile;
502       }
503       token = lex_get_token(lc, T_ALL);
504       if (token != T_COMMA) {
505          break;
506       }
507    }
508    return bsr;
509 }
510 
511 
512 /*
513  * Routine to handle Volume start/end Block
514  */
store_volblock(LEX * lc,BSR * bsr)515 static BSR *store_volblock(LEX *lc, BSR *bsr)
516 {
517    int token;
518    BSR_VOLBLOCK *volblock;
519 
520    for (;;) {
521       token = lex_get_token(lc, T_PINT32_RANGE);
522       if (token == T_ERROR) {
523          return NULL;
524       }
525       volblock = (BSR_VOLBLOCK *)malloc(sizeof(BSR_VOLBLOCK));
526       memset(volblock, 0, sizeof(BSR_VOLBLOCK));
527       volblock->sblock = lc->pint32_val;
528       volblock->eblock = lc->pint32_val2;
529       /* Add it to the end of the chain */
530       if (!bsr->volblock) {
531          bsr->volblock = volblock;
532       } else {
533          /* Add to end of chain */
534          BSR_VOLBLOCK *bs = bsr->volblock;
535          for ( ;bs->next; bs=bs->next)
536             {  }
537          bs->next = volblock;
538       }
539       token = lex_get_token(lc, T_ALL);
540       if (token != T_COMMA) {
541          break;
542       }
543    }
544    return bsr;
545 }
546 
547 /*
548  * Routine to handle Volume start/end address
549  */
store_voladdr(LEX * lc,BSR * bsr)550 static BSR *store_voladdr(LEX *lc, BSR *bsr)
551 {
552    int token;
553    BSR_VOLADDR *voladdr;
554 
555    for (;;) {
556       token = lex_get_token(lc, T_PINT64_RANGE);
557       if (token == T_ERROR) {
558          return NULL;
559       }
560       voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR));
561       memset(voladdr, 0, sizeof(BSR_VOLADDR));
562       voladdr->saddr = lc->pint64_val;
563       voladdr->eaddr = lc->pint64_val2;
564       /* Add it to the end of the chain */
565       if (!bsr->voladdr) {
566          bsr->voladdr = voladdr;
567       } else {
568          /* Add to end of chain */
569          BSR_VOLADDR *bs = bsr->voladdr;
570          for ( ;bs->next; bs=bs->next)
571             {  }
572          bs->next = voladdr;
573       }
574       token = lex_get_token(lc, T_ALL);
575       if (token != T_COMMA) {
576          break;
577       }
578    }
579    return bsr;
580 }
581 
store_sessid(LEX * lc,BSR * bsr)582 static BSR *store_sessid(LEX *lc, BSR *bsr)
583 {
584    int token;
585    BSR_SESSID *sid;
586 
587    for (;;) {
588       token = lex_get_token(lc, T_PINT32_RANGE);
589       if (token == T_ERROR) {
590          return NULL;
591       }
592       sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
593       memset(sid, 0, sizeof(BSR_SESSID));
594       sid->sessid = lc->pint32_val;
595       sid->sessid2 = lc->pint32_val2;
596       /* Add it to the end of the chain */
597       if (!bsr->sessid) {
598          bsr->sessid = sid;
599       } else {
600          /* Add to end of chain */
601          BSR_SESSID *bs = bsr->sessid;
602          for ( ;bs->next; bs=bs->next)
603             {  }
604          bs->next = sid;
605       }
606       token = lex_get_token(lc, T_ALL);
607       if (token != T_COMMA) {
608          break;
609       }
610    }
611    return bsr;
612 }
613 
store_sesstime(LEX * lc,BSR * bsr)614 static BSR *store_sesstime(LEX *lc, BSR *bsr)
615 {
616    int token;
617    BSR_SESSTIME *stime;
618 
619    for (;;) {
620       token = lex_get_token(lc, T_PINT32);
621       if (token == T_ERROR) {
622          return NULL;
623       }
624       stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
625       memset(stime, 0, sizeof(BSR_SESSTIME));
626       stime->sesstime = lc->pint32_val;
627       /* Add it to the end of the chain */
628       if (!bsr->sesstime) {
629          bsr->sesstime = stime;
630       } else {
631          /* Add to end of chain */
632          BSR_SESSTIME *bs = bsr->sesstime;
633          for ( ;bs->next; bs=bs->next)
634             { }
635          bs->next = stime;
636       }
637       token = lex_get_token(lc, T_ALL);
638       if (token != T_COMMA) {
639          break;
640       }
641    }
642    return bsr;
643 }
644 
645 
store_stream(LEX * lc,BSR * bsr)646 static BSR *store_stream(LEX *lc, BSR *bsr)
647 {
648    int token;
649    BSR_STREAM *stream;
650 
651    for (;;) {
652       token = lex_get_token(lc, T_INT32);
653       if (token == T_ERROR) {
654          return NULL;
655       }
656       stream = (BSR_STREAM *)malloc(sizeof(BSR_STREAM));
657       memset(stream, 0, sizeof(BSR_STREAM));
658       stream->stream = lc->int32_val;
659       /* Add it to the end of the chain */
660       if (!bsr->stream) {
661          bsr->stream = stream;
662       } else {
663          /* Add to end of chain */
664          BSR_STREAM *bs = bsr->stream;
665          for ( ;bs->next; bs=bs->next)
666             { }
667          bs->next = stream;
668       }
669       token = lex_get_token(lc, T_ALL);
670       if (token != T_COMMA) {
671          break;
672       }
673    }
674    return bsr;
675 }
676 
store_slot(LEX * lc,BSR * bsr)677 static BSR *store_slot(LEX *lc, BSR *bsr)
678 {
679    int token;
680 
681    token = lex_get_token(lc, T_PINT32);
682    if (token == T_ERROR) {
683       return NULL;
684    }
685    if (!bsr->volume) {
686       Emsg1(M_ERROR,0, _("Slot %d in bsr at inappropriate place.\n"),
687          lc->pint32_val);
688       return bsr;
689    }
690    bsr->volume->Slot = lc->pint32_val;
691    scan_to_eol(lc);
692    return bsr;
693 }
694 
store_include(LEX * lc,BSR * bsr)695 static BSR *store_include(LEX *lc, BSR *bsr)
696 {
697    scan_to_eol(lc);
698    return bsr;
699 }
700 
store_exclude(LEX * lc,BSR * bsr)701 static BSR *store_exclude(LEX *lc, BSR *bsr)
702 {
703    scan_to_eol(lc);
704    return bsr;
705 }
706 
dump_volfile(BSR_VOLFILE * volfile)707 void dump_volfile(BSR_VOLFILE *volfile)
708 {
709    if (volfile) {
710       Pmsg2(-1, _("VolFile     : %u-%u\n"), volfile->sfile, volfile->efile);
711       dump_volfile(volfile->next);
712    }
713 }
714 
dump_volblock(BSR_VOLBLOCK * volblock)715 void dump_volblock(BSR_VOLBLOCK *volblock)
716 {
717    if (volblock) {
718       Pmsg2(-1, _("VolBlock    : %u-%u\n"), volblock->sblock, volblock->eblock);
719       dump_volblock(volblock->next);
720    }
721 }
722 
dump_voladdr(DEVICE * dev,BSR_VOLADDR * voladdr)723 void dump_voladdr(DEVICE *dev, BSR_VOLADDR *voladdr)
724 {
725    if (voladdr) {
726       if (dev) {
727          char ed1[50], ed2[50];
728          Pmsg2(-1, _("VolAddr    : %s-%llu\n"),
729             dev->print_addr(ed1, sizeof(ed1), voladdr->saddr),
730             dev->print_addr(ed2, sizeof(ed2), voladdr->eaddr));
731       } else {
732          Pmsg2(-1, _("VolAddr    : %llu-%llu\n"), voladdr->saddr, voladdr->eaddr);
733       }
734       dump_voladdr(dev, voladdr->next);
735    }
736 }
737 
dump_findex(BSR_FINDEX * FileIndex)738 void dump_findex(BSR_FINDEX *FileIndex)
739 {
740    if (FileIndex) {
741       if (FileIndex->findex == FileIndex->findex2) {
742          Pmsg1(-1, _("FileIndex   : %u\n"), FileIndex->findex);
743       } else {
744          Pmsg2(-1, _("FileIndex   : %u-%u\n"), FileIndex->findex, FileIndex->findex2);
745       }
746       dump_findex(FileIndex->next);
747    }
748 }
749 
dump_jobid(BSR_JOBID * jobid)750 void dump_jobid(BSR_JOBID *jobid)
751 {
752    if (jobid) {
753       if (jobid->JobId == jobid->JobId2) {
754          Pmsg1(-1, _("JobId       : %u\n"), jobid->JobId);
755       } else {
756          Pmsg2(-1, _("JobId       : %u-%u\n"), jobid->JobId, jobid->JobId2);
757       }
758       dump_jobid(jobid->next);
759    }
760 }
761 
dump_sessid(BSR_SESSID * sessid)762 void dump_sessid(BSR_SESSID *sessid)
763 {
764    if (sessid) {
765       if (sessid->sessid == sessid->sessid2) {
766          Pmsg1(-1, _("SessId      : %u\n"), sessid->sessid);
767       } else {
768          Pmsg2(-1, _("SessId      : %u-%u\n"), sessid->sessid, sessid->sessid2);
769       }
770       dump_sessid(sessid->next);
771    }
772 }
773 
dump_volume(BSR_VOLUME * volume)774 void dump_volume(BSR_VOLUME *volume)
775 {
776    if (volume) {
777       Pmsg1(-1, _("VolumeName  : %s\n"), volume->VolumeName);
778       Pmsg1(-1, _("  MediaType : %s\n"), volume->MediaType);
779       Pmsg1(-1, _("  Device    : %s\n"), volume->device);
780       Pmsg1(-1, _("  Slot      : %d\n"), volume->Slot);
781       dump_volume(volume->next);
782    }
783 }
784 
785 
dump_client(BSR_CLIENT * client)786 void dump_client(BSR_CLIENT *client)
787 {
788    if (client) {
789       Pmsg1(-1, _("Client      : %s\n"), client->ClientName);
790       dump_client(client->next);
791    }
792 }
793 
dump_job(BSR_JOB * job)794 void dump_job(BSR_JOB *job)
795 {
796    if (job) {
797       Pmsg1(-1, _("Job          : %s\n"), job->Job);
798       dump_job(job->next);
799    }
800 }
801 
dump_sesstime(BSR_SESSTIME * sesstime)802 void dump_sesstime(BSR_SESSTIME *sesstime)
803 {
804    if (sesstime) {
805       Pmsg1(-1, _("SessTime    : %u\n"), sesstime->sesstime);
806       dump_sesstime(sesstime->next);
807    }
808 }
809 
810 
dump_bsr(DEVICE * dev,BSR * bsr,bool recurse)811 void dump_bsr(DEVICE *dev, BSR *bsr, bool recurse)
812 {
813    int64_t save_debug = debug_level;
814    debug_level = 1;
815    if (!bsr) {
816       Pmsg0(-1, _("BSR is NULL\n"));
817       debug_level = save_debug;
818       return;
819    }
820    Pmsg1(-1,    _("Next        : 0x%x\n"), bsr->next);
821    Pmsg1(-1,    _("Root bsr    : 0x%x\n"), bsr->root);
822    dump_volume(bsr->volume);
823    dump_sessid(bsr->sessid);
824    dump_sesstime(bsr->sesstime);
825    dump_volfile(bsr->volfile);
826    dump_volblock(bsr->volblock);
827    dump_voladdr(dev, bsr->voladdr);
828    dump_client(bsr->client);
829    dump_jobid(bsr->JobId);
830    dump_job(bsr->job);
831    dump_findex(bsr->FileIndex);
832    if (bsr->count) {
833       Pmsg1(-1, _("count       : %u\n"), bsr->count);
834       Pmsg1(-1, _("found       : %u\n"), bsr->found);
835    }
836 
837    Pmsg1(-1,    _("done        : %s\n"), bsr->done?_("yes"):_("no"));
838    Pmsg1(-1,    _("positioning : %d\n"), bsr->use_positioning);
839    Pmsg1(-1,    _("fast_reject : %d\n"), bsr->use_fast_rejection);
840    if (recurse && bsr->next) {
841       Pmsg0(-1, "\n");
842       dump_bsr(dev, bsr->next, true);
843    }
844    debug_level = save_debug;
845 }
846 
847 /*********************************************************************
848  *
849  *      Free bsr resources
850  */
851 
free_bsr_item(BSR * bsr)852 static void free_bsr_item(BSR *bsr)
853 {
854    BSR *next;
855    while (bsr) {
856       next = bsr->next;
857       free(bsr);
858       bsr = next;
859    }
860 }
861 
862 /*
863  * Remove a single item from the bsr tree
864  */
remove_bsr(BSR * bsr)865 void remove_bsr(BSR *bsr)
866 {
867    free_bsr_item((BSR *)bsr->volume);
868    free_bsr_item((BSR *)bsr->client);
869    free_bsr_item((BSR *)bsr->sessid);
870    free_bsr_item((BSR *)bsr->sesstime);
871    free_bsr_item((BSR *)bsr->volfile);
872    free_bsr_item((BSR *)bsr->volblock);
873    free_bsr_item((BSR *)bsr->voladdr);
874    free_bsr_item((BSR *)bsr->JobId);
875    free_bsr_item((BSR *)bsr->job);
876    free_bsr_item((BSR *)bsr->FileIndex);
877    free_bsr_item((BSR *)bsr->JobType);
878    free_bsr_item((BSR *)bsr->JobLevel);
879    if (bsr->fileregex) {
880       bfree(bsr->fileregex);
881    }
882    if (bsr->fileregex_re) {
883       regfree(bsr->fileregex_re);
884       free(bsr->fileregex_re);
885    }
886    if (bsr->attr) {
887       free_attr(bsr->attr);
888    }
889    if (bsr->next) {
890       bsr->next->prev = bsr->prev;
891    }
892    if (bsr->prev) {
893       bsr->prev->next = bsr->next;
894    }
895    free(bsr);
896 }
897 
898 /*
899  * Free all bsrs in chain
900  */
free_bsr(BSR * bsr)901 void free_bsr(BSR *bsr)
902 {
903    BSR *next_bsr;
904    while (bsr) {
905       next_bsr = bsr->next;
906       /* Remove (free) current bsr */
907       remove_bsr(bsr);
908       /* Now get the next one */
909       bsr = next_bsr;
910    }
911 }
912 
913 /*****************************************************************
914  * Routines for handling volumes
915  */
new_restore_volume()916 static VOL_LIST *new_restore_volume()
917 {
918    VOL_LIST *vol;
919    vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
920    memset(vol, 0, sizeof(VOL_LIST));
921    return vol;
922 }
923 
924 /*
925  * Create a list of Volumes (and Slots and Start positions) to be
926  *  used in the current restore job.
927  */
create_restore_volume_list(JCR * jcr,bool add_to_read_list)928 void create_restore_volume_list(JCR *jcr, bool add_to_read_list)
929 {
930    char *p, *n;
931    VOL_LIST *vol;
932 
933    /*
934     * Build a list of volumes to be processed
935     */
936    jcr->NumReadVolumes = 0;
937    jcr->CurReadVolume = 0;
938    if (jcr->bsr) {
939       BSR *bsr = jcr->bsr;
940       if (!bsr->volume || !bsr->volume->VolumeName[0]) {
941          return;
942       }
943       for ( ; bsr; bsr=bsr->next) {
944          BSR_VOLUME *bsrvol;
945          BSR_VOLFILE *volfile;
946          uint32_t sfile = UINT32_MAX;
947 
948          /* Find minimum start file so that we can forward space to it */
949          for (volfile = bsr->volfile; volfile; volfile=volfile->next) {
950             if (volfile->sfile < sfile) {
951                sfile = volfile->sfile;
952             }
953          }
954          /* Now add volumes for this bsr */
955          for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) {
956             vol = new_restore_volume();
957             bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
958             bstrncpy(vol->MediaType,  bsrvol->MediaType,  sizeof(vol->MediaType));
959             bstrncpy(vol->device, bsrvol->device, sizeof(vol->device));
960             vol->Slot = bsrvol->Slot;
961             vol->start_file = sfile;
962             if (add_restore_volume(jcr, vol, add_to_read_list)) {
963                jcr->NumReadVolumes++;
964                Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName,
965                   vol->MediaType);
966             } else {
967                Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
968                free((char *)vol);
969             }
970             sfile = 0;                /* start at beginning of second volume */
971          }
972       }
973    } else {
974       /* This is the old way -- deprecated */
975       for (p = jcr->dcr->VolumeName; p && *p; ) {
976          n = strchr(p, '|');             /* volume name separator */
977          if (n) {
978             *n++ = 0;                    /* Terminate name */
979          }
980          vol = new_restore_volume();
981          bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
982          bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType));
983          if (add_restore_volume(jcr, vol, add_to_read_list)) {
984             jcr->NumReadVolumes++;
985          } else {
986             free((char *)vol);
987          }
988          p = n;
989       }
990    }
991 }
992 
993 /*
994  * Add current volume to end of list, only if the Volume
995  * is not already in the list.
996  *
997  *   returns: 1 if volume added
998  *            0 if volume already in list
999  */
add_restore_volume(JCR * jcr,VOL_LIST * vol,bool add_to_read_list)1000 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol, bool add_to_read_list)
1001 {
1002    VOL_LIST *next = jcr->VolList;
1003 
1004    if (add_to_read_list) {
1005       /* Add volume to volume manager's read list */
1006       add_read_volume(jcr, vol->VolumeName);
1007    }
1008 
1009    if (!next) {                       /* list empty ? */
1010       jcr->VolList = vol;             /* yes, add volume */
1011    } else {
1012       /* Loop through all but last */
1013       for ( ; next->next; next=next->next) {
1014          if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
1015             /* Save smallest start file */
1016             if (vol->start_file < next->start_file) {
1017                next->start_file = vol->start_file;
1018             }
1019             return false;              /* already in list */
1020          }
1021       }
1022       /* Check last volume in list */
1023       if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
1024          if (vol->start_file < next->start_file) {
1025             next->start_file = vol->start_file;
1026          }
1027          return false;                /* already in list */
1028       }
1029       next->next = vol;               /* add volume */
1030    }
1031    return true;
1032 }
1033 
free_restore_volume_list(JCR * jcr)1034 void free_restore_volume_list(JCR *jcr)
1035 {
1036    VOL_LIST *vol = jcr->VolList;
1037    VOL_LIST *tmp;
1038 
1039    for ( ; vol; ) {
1040       tmp = vol->next;
1041       remove_read_volume(jcr, vol->VolumeName);
1042       free(vol);
1043       vol = tmp;
1044    }
1045    jcr->VolList = NULL;
1046 }
1047 
1048 
1049 /*
1050  * Format a scanner error message
1051  */
s_err(const char * file,int line,LEX * lc,const char * msg,...)1052 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
1053 {
1054    JCR *jcr = (JCR *)(lc->caller_ctx);
1055    va_list arg_ptr;
1056    char buf[MAXSTRING];
1057 
1058    va_start(arg_ptr, msg);
1059    bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
1060    va_end(arg_ptr);
1061 
1062    if (jcr) {
1063       Jmsg(jcr, M_FATAL, 0, _("Bootstrap file error: %s\n"
1064 "            : Line %d, col %d of file %s\n%s\n"),
1065          buf, lc->line_no, lc->col_no, lc->fname, lc->line);
1066    } else {
1067       e_msg(file, line, M_FATAL, 0, _("Bootstrap file error: %s\n"
1068 "            : Line %d, col %d of file %s\n%s\n"),
1069          buf, lc->line_no, lc->col_no, lc->fname, lc->line);
1070    }
1071 }
1072