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