2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2014 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from many
7 others, a complete list can be found in the file AUTHORS.
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.
14 Bacula® is a registered trademark of Kern Sibbald.
17 * Parse a Bootstrap Records (used for restores)
19 * Kern Sibbald, June MMII
27 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...);
28 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol);
30 typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
32 static BSR *store_client(LEX *lc, BSR *bsr);
33 static BSR *store_count(LEX *lc, BSR *bsr);
34 static BSR *store_device(LEX *lc, BSR *bsr);
35 static BSR *store_exclude(LEX *lc, BSR *bsr);
36 static BSR *store_fileregex(LEX *lc, BSR *bsr);
37 static BSR *store_findex(LEX *lc, BSR *bsr);
38 static BSR *store_include(LEX *lc, BSR *bsr);
39 static BSR *store_jobid(LEX *lc, BSR *bsr);
40 static BSR *store_joblevel(LEX *lc, BSR *bsr);
41 static BSR *store_job(LEX *lc, BSR *bsr);
42 static BSR *store_jobtype(LEX *lc, BSR *bsr);
43 static BSR *store_mediatype(LEX *lc, BSR *bsr);
44 static BSR *store_nothing(LEX *lc, BSR *bsr);
45 static BSR *store_sessid(LEX *lc, BSR *bsr);
46 static BSR *store_sesstime(LEX *lc, BSR *bsr);
47 static BSR *store_slot(LEX *lc, BSR *bsr);
48 static BSR *store_stream(LEX *lc, BSR *bsr);
49 static BSR *store_voladdr(LEX *lc, BSR *bsr);
50 static BSR *store_volblock(LEX *lc, BSR *bsr);
51 static BSR *store_volfile(LEX *lc, BSR *bsr);
52 static BSR *store_vol(LEX *lc, BSR *bsr);
53 static bool is_fast_rejection_ok(BSR *bsr);
54 static bool is_positioning_ok(BSR *bsr);
58 ITEM_HANDLER *handler;
62 * List of all keywords permitted in bsr files and their handlers
64 struct kw_items items[] = {
65 {"client", store_client},
66 {"count", store_count},
67 {"device", store_device},
68 {"exclude", store_exclude},
69 {"fileindex", store_findex},
70 {"fileregex", store_fileregex},
71 {"include", store_include},
72 {"jobid", store_jobid},
73 {"joblevel", store_joblevel},
75 {"jobtype", store_jobtype},
76 {"mediatype", store_mediatype},
78 {"storage", store_nothing},
79 {"stream", store_stream},
80 {"voladdr", store_voladdr},
81 {"volblock", store_volblock},
82 {"volume", store_vol},
83 {"volfile", store_volfile},
84 {"volsessionid", store_sessid},
85 {"volsessiontime", store_sesstime},
94 BSR *bsr = (BSR *)malloc(sizeof(BSR));
95 memset(bsr, 0, sizeof(BSR));
100 /*********************************************************************
102 * Parse Bootstrap file
105 BSR *parse_bsr(JCR *jcr, char *fname)
109 BSR *root_bsr = new_bsr();
112 Dmsg1(300, "Enter parse_bsf %s\n", fname);
113 if ((lc = lex_open_file(lc, fname, s_err)) == NULL) {
115 Emsg2(M_ERROR_TERM, 0, _("Cannot open bootstrap file %s: %s\n"),
116 fname, be.bstrerror());
118 lc->caller_ctx = (void *)jcr;
119 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
120 Dmsg1(300, "parse got token=%s\n", lex_tok_to_str(token));
121 if (token == T_EOL) {
124 for (i=0; items[i].name; i++) {
125 if (strcasecmp(items[i].name, lc->str) == 0) {
126 token = lex_get_token(lc, T_ALL);
127 Dmsg1 (300, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
128 if (token != T_EQUALS) {
129 scan_err1(lc, "expected an equals, got: %s", lc->str);
133 Dmsg1(300, "calling handler for %s\n", items[i].name);
134 /* Call item handler */
135 bsr = items[i].handler(lc, bsr);
141 Dmsg1(300, "Keyword = %s\n", lc->str);
142 scan_err1(lc, "Keyword %s not found", lc->str);
150 lc = lex_close_file(lc);
151 Dmsg0(300, "Leave parse_bsf()\n");
157 root_bsr->use_fast_rejection = is_fast_rejection_ok(root_bsr);
158 root_bsr->use_positioning = is_positioning_ok(root_bsr);
160 for (bsr=root_bsr; bsr; bsr=bsr->next) {
161 bsr->root = root_bsr;
166 static BSR *store_client(LEX *lc, BSR *bsr)
172 token = lex_get_token(lc, T_NAME);
173 if (token == T_ERROR) {
176 client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
177 memset(client, 0, sizeof(BSR_CLIENT));
178 bstrncpy(client->ClientName, lc->str, sizeof(client->ClientName));
179 /* Add it to the end of the client chain */
181 bsr->client = client;
183 BSR_CLIENT *bc = bsr->client;
184 for ( ;bc->next; bc=bc->next)
188 token = lex_get_token(lc, T_ALL);
189 if (token != T_COMMA) {
196 static BSR *store_count(LEX *lc, BSR *bsr)
200 token = lex_get_token(lc, T_PINT32);
201 if (token == T_ERROR) {
204 bsr->count = lc->pint32_val;
209 /* Shove the Device name in each Volume in the current bsr */
210 static BSR *store_device(LEX *lc, BSR *bsr)
214 token = lex_get_token(lc, T_STRING);
215 if (token == T_ERROR) {
219 Emsg1(M_ERROR,0, _("Device \"%s\" in bsr at inappropriate place.\n"),
224 for (bv=bsr->volume; bv; bv=bv->next) {
225 bstrncpy(bv->device, lc->str, sizeof(bv->device));
230 static BSR *store_findex(LEX *lc, BSR *bsr)
236 token = lex_get_token(lc, T_PINT32_RANGE);
237 if (token == T_ERROR) {
240 findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
241 memset(findex, 0, sizeof(BSR_FINDEX));
242 findex->findex = lc->pint32_val;
243 findex->findex2 = lc->pint32_val2;
244 /* Add it to the end of the chain */
245 if (!bsr->FileIndex) {
246 bsr->FileIndex = findex;
248 /* Add to end of chain */
249 BSR_FINDEX *bs = bsr->FileIndex;
250 for ( ;bs->next; bs=bs->next)
254 token = lex_get_token(lc, T_ALL);
255 if (token != T_COMMA) {
262 static BSR *store_fileregex(LEX *lc, BSR *bsr)
267 token = lex_get_token(lc, T_STRING);
268 if (token == T_ERROR) {
272 if (bsr->fileregex) free(bsr->fileregex);
273 bsr->fileregex = bstrdup(lc->str);
275 if (bsr->fileregex_re == NULL)
276 bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));
278 rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
281 regerror(rc, bsr->fileregex_re, prbuf, sizeof(prbuf));
282 Emsg2(M_ERROR, 0, _("REGEX '%s' compile error. ERR=%s\n"),
283 bsr->fileregex, prbuf);
289 static BSR *store_jobid(LEX *lc, BSR *bsr)
295 token = lex_get_token(lc, T_PINT32_RANGE);
296 if (token == T_ERROR) {
299 jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
300 memset(jobid, 0, sizeof(BSR_JOBID));
301 jobid->JobId = lc->pint32_val;
302 jobid->JobId2 = lc->pint32_val2;
303 /* Add it to the end of the chain */
307 /* Add to end of chain */
308 BSR_JOBID *bs = bsr->JobId;
309 for ( ;bs->next; bs=bs->next)
313 token = lex_get_token(lc, T_ALL);
314 if (token != T_COMMA) {
322 static BSR *store_jobtype(LEX *lc, BSR *bsr)
324 /* *****FIXME****** */
325 Pmsg0(-1, _("JobType not yet implemented\n"));
330 static BSR *store_joblevel(LEX *lc, BSR *bsr)
332 /* *****FIXME****** */
333 Pmsg0(-1, _("JobLevel not yet implemented\n"));
337 static BSR *store_job(LEX *lc, BSR *bsr)
343 token = lex_get_token(lc, T_NAME);
344 if (token == T_ERROR) {
347 job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
348 memset(job, 0, sizeof(BSR_JOB));
349 bstrncpy(job->Job, lc->str, sizeof(job->Job));
350 /* Add it to the end of the client chain */
354 /* Add to end of chain */
355 BSR_JOB *bc = bsr->job;
356 for ( ;bc->next; bc=bc->next)
360 token = lex_get_token(lc, T_ALL);
361 if (token != T_COMMA) {
368 /* Shove the MediaType in each Volume in the current bsr */
369 static BSR *store_mediatype(LEX *lc, BSR *bsr)
373 token = lex_get_token(lc, T_STRING);
374 if (token == T_ERROR) {
378 Emsg1(M_ERROR,0, _("MediaType %s in bsr at inappropriate place.\n"),
383 for (bv=bsr->volume; bv; bv=bv->next) {
384 bstrncpy(bv->MediaType, lc->str, sizeof(bv->MediaType));
389 static BSR *store_vol(LEX *lc, BSR *bsr)
395 token = lex_get_token(lc, T_STRING);
396 if (token == T_ERROR) {
400 bsr->next = new_bsr();
401 bsr->next->prev = bsr;
404 /* This may actually be more than one volume separated by a |
405 * If so, separate them.
407 for (p=lc->str; p && *p; ) {
412 volume = (BSR_VOLUME *)malloc(sizeof(BSR_VOLUME));
413 memset(volume, 0, sizeof(BSR_VOLUME));
414 bstrncpy(volume->VolumeName, p, sizeof(volume->VolumeName));
415 /* Add it to the end of the volume chain */
417 bsr->volume = volume;
419 BSR_VOLUME *bc = bsr->volume;
420 for ( ;bc->next; bc=bc->next)
429 static bool is_positioning_ok(BSR *bsr)
432 * Every bsr should have a volfile entry and a volblock entry
434 * if we are going to use positioning
436 for ( ; bsr; bsr=bsr->next) {
437 if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
444 static bool is_fast_rejection_ok(BSR *bsr)
447 * Although, this can be optimized, for the moment, require
448 * all bsrs to have both sesstime and sessid set before
449 * we do fast rejection.
451 for ( ; bsr; bsr=bsr->next) {
452 if (!(bsr->sesstime && bsr->sessid)) {
460 static BSR *store_nothing(LEX *lc, BSR *bsr)
464 token = lex_get_token(lc, T_STRING);
465 if (token == T_ERROR) {
474 * Routine to handle Volume start/end file
476 static BSR *store_volfile(LEX *lc, BSR *bsr)
479 BSR_VOLFILE *volfile;
482 token = lex_get_token(lc, T_PINT32_RANGE);
483 if (token == T_ERROR) {
486 volfile = (BSR_VOLFILE *)malloc(sizeof(BSR_VOLFILE));
487 memset(volfile, 0, sizeof(BSR_VOLFILE));
488 volfile->sfile = lc->pint32_val;
489 volfile->efile = lc->pint32_val2;
490 /* Add it to the end of the chain */
492 bsr->volfile = volfile;
494 /* Add to end of chain */
495 BSR_VOLFILE *bs = bsr->volfile;
496 for ( ;bs->next; bs=bs->next)
500 token = lex_get_token(lc, T_ALL);
501 if (token != T_COMMA) {
510 * Routine to handle Volume start/end Block
512 static BSR *store_volblock(LEX *lc, BSR *bsr)
515 BSR_VOLBLOCK *volblock;
518 token = lex_get_token(lc, T_PINT32_RANGE);
519 if (token == T_ERROR) {
522 volblock = (BSR_VOLBLOCK *)malloc(sizeof(BSR_VOLBLOCK));
523 memset(volblock, 0, sizeof(BSR_VOLBLOCK));
524 volblock->sblock = lc->pint32_val;
525 volblock->eblock = lc->pint32_val2;
526 /* Add it to the end of the chain */
527 if (!bsr->volblock) {
528 bsr->volblock = volblock;
530 /* Add to end of chain */
531 BSR_VOLBLOCK *bs = bsr->volblock;
532 for ( ;bs->next; bs=bs->next)
536 token = lex_get_token(lc, T_ALL);
537 if (token != T_COMMA) {
545 * Routine to handle Volume start/end address
547 static BSR *store_voladdr(LEX *lc, BSR *bsr)
550 BSR_VOLADDR *voladdr;
553 token = lex_get_token(lc, T_PINT64_RANGE);
554 if (token == T_ERROR) {
557 voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR));
558 memset(voladdr, 0, sizeof(BSR_VOLADDR));
559 voladdr->saddr = lc->pint64_val;
560 voladdr->eaddr = lc->pint64_val2;
561 /* Add it to the end of the chain */
563 bsr->voladdr = voladdr;
565 /* Add to end of chain */
566 BSR_VOLADDR *bs = bsr->voladdr;
567 for ( ;bs->next; bs=bs->next)
571 token = lex_get_token(lc, T_ALL);
572 if (token != T_COMMA) {
579 static BSR *store_sessid(LEX *lc, BSR *bsr)
585 token = lex_get_token(lc, T_PINT32_RANGE);
586 if (token == T_ERROR) {
589 sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
590 memset(sid, 0, sizeof(BSR_SESSID));
591 sid->sessid = lc->pint32_val;
592 sid->sessid2 = lc->pint32_val2;
593 /* Add it to the end of the chain */
597 /* Add to end of chain */
598 BSR_SESSID *bs = bsr->sessid;
599 for ( ;bs->next; bs=bs->next)
603 token = lex_get_token(lc, T_ALL);
604 if (token != T_COMMA) {
611 static BSR *store_sesstime(LEX *lc, BSR *bsr)
617 token = lex_get_token(lc, T_PINT32);
618 if (token == T_ERROR) {
621 stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
622 memset(stime, 0, sizeof(BSR_SESSTIME));
623 stime->sesstime = lc->pint32_val;
624 /* Add it to the end of the chain */
625 if (!bsr->sesstime) {
626 bsr->sesstime = stime;
628 /* Add to end of chain */
629 BSR_SESSTIME *bs = bsr->sesstime;
630 for ( ;bs->next; bs=bs->next)
634 token = lex_get_token(lc, T_ALL);
635 if (token != T_COMMA) {
643 static BSR *store_stream(LEX *lc, BSR *bsr)
649 token = lex_get_token(lc, T_INT32);
650 if (token == T_ERROR) {
653 stream = (BSR_STREAM *)malloc(sizeof(BSR_STREAM));
654 memset(stream, 0, sizeof(BSR_STREAM));
655 stream->stream = lc->int32_val;
656 /* Add it to the end of the chain */
658 bsr->stream = stream;
660 /* Add to end of chain */
661 BSR_STREAM *bs = bsr->stream;
662 for ( ;bs->next; bs=bs->next)
666 token = lex_get_token(lc, T_ALL);
667 if (token != T_COMMA) {
674 static BSR *store_slot(LEX *lc, BSR *bsr)
678 token = lex_get_token(lc, T_PINT32);
679 if (token == T_ERROR) {
683 Emsg1(M_ERROR,0, _("Slot %d in bsr at inappropriate place.\n"),
687 bsr->volume->Slot = lc->pint32_val;
692 static BSR *store_include(LEX *lc, BSR *bsr)
698 static BSR *store_exclude(LEX *lc, BSR *bsr)
704 void dump_volfile(BSR_VOLFILE *volfile)
707 Pmsg2(-1, _("VolFile : %u-%u\n"), volfile->sfile, volfile->efile);
708 dump_volfile(volfile->next);
712 void dump_volblock(BSR_VOLBLOCK *volblock)
715 Pmsg2(-1, _("VolBlock : %u-%u\n"), volblock->sblock, volblock->eblock);
716 dump_volblock(volblock->next);
720 void dump_voladdr(BSR_VOLADDR *voladdr)
723 Pmsg2(-1, _("VolAddr : %llu-%llu\n"), voladdr->saddr, voladdr->eaddr);
724 dump_voladdr(voladdr->next);
728 void dump_findex(BSR_FINDEX *FileIndex)
731 if (FileIndex->findex == FileIndex->findex2) {
732 Pmsg1(-1, _("FileIndex : %u\n"), FileIndex->findex);
734 Pmsg2(-1, _("FileIndex : %u-%u\n"), FileIndex->findex, FileIndex->findex2);
736 dump_findex(FileIndex->next);
740 void dump_jobid(BSR_JOBID *jobid)
743 if (jobid->JobId == jobid->JobId2) {
744 Pmsg1(-1, _("JobId : %u\n"), jobid->JobId);
746 Pmsg2(-1, _("JobId : %u-%u\n"), jobid->JobId, jobid->JobId2);
748 dump_jobid(jobid->next);
752 void dump_sessid(BSR_SESSID *sessid)
755 if (sessid->sessid == sessid->sessid2) {
756 Pmsg1(-1, _("SessId : %u\n"), sessid->sessid);
758 Pmsg2(-1, _("SessId : %u-%u\n"), sessid->sessid, sessid->sessid2);
760 dump_sessid(sessid->next);
764 void dump_volume(BSR_VOLUME *volume)
767 Pmsg1(-1, _("VolumeName : %s\n"), volume->VolumeName);
768 Pmsg1(-1, _(" MediaType : %s\n"), volume->MediaType);
769 Pmsg1(-1, _(" Device : %s\n"), volume->device);
770 Pmsg1(-1, _(" Slot : %d\n"), volume->Slot);
771 dump_volume(volume->next);
776 void dump_client(BSR_CLIENT *client)
779 Pmsg1(-1, _("Client : %s\n"), client->ClientName);
780 dump_client(client->next);
784 void dump_job(BSR_JOB *job)
787 Pmsg1(-1, _("Job : %s\n"), job->Job);
792 void dump_sesstime(BSR_SESSTIME *sesstime)
795 Pmsg1(-1, _("SessTime : %u\n"), sesstime->sesstime);
796 dump_sesstime(sesstime->next);
801 void dump_bsr(BSR *bsr, bool recurse)
803 int64_t save_debug = debug_level;
806 Pmsg0(-1, _("BSR is NULL\n"));
807 debug_level = save_debug;
810 Pmsg1(-1, _("Next : 0x%x\n"), bsr->next);
811 Pmsg1(-1, _("Root bsr : 0x%x\n"), bsr->root);
812 dump_volume(bsr->volume);
813 dump_sessid(bsr->sessid);
814 dump_sesstime(bsr->sesstime);
815 dump_volfile(bsr->volfile);
816 dump_volblock(bsr->volblock);
817 dump_voladdr(bsr->voladdr);
818 dump_client(bsr->client);
819 dump_jobid(bsr->JobId);
821 dump_findex(bsr->FileIndex);
823 Pmsg1(-1, _("count : %u\n"), bsr->count);
824 Pmsg1(-1, _("found : %u\n"), bsr->found);
827 Pmsg1(-1, _("done : %s\n"), bsr->done?_("yes"):_("no"));
828 Pmsg1(-1, _("positioning : %d\n"), bsr->use_positioning);
829 Pmsg1(-1, _("fast_reject : %d\n"), bsr->use_fast_rejection);
830 if (recurse && bsr->next) {
832 dump_bsr(bsr->next, true);
834 debug_level = save_debug;
839 /*********************************************************************
844 static void free_bsr_item(BSR *bsr)
847 free_bsr_item(bsr->next);
853 * Remove a single item from the bsr tree
855 void remove_bsr(BSR *bsr)
857 free_bsr_item((BSR *)bsr->volume);
858 free_bsr_item((BSR *)bsr->client);
859 free_bsr_item((BSR *)bsr->sessid);
860 free_bsr_item((BSR *)bsr->sesstime);
861 free_bsr_item((BSR *)bsr->volfile);
862 free_bsr_item((BSR *)bsr->volblock);
863 free_bsr_item((BSR *)bsr->voladdr);
864 free_bsr_item((BSR *)bsr->JobId);
865 free_bsr_item((BSR *)bsr->job);
866 free_bsr_item((BSR *)bsr->FileIndex);
867 free_bsr_item((BSR *)bsr->JobType);
868 free_bsr_item((BSR *)bsr->JobLevel);
869 if (bsr->fileregex) {
870 bfree(bsr->fileregex);
872 if (bsr->fileregex_re) {
873 regfree(bsr->fileregex_re);
874 free(bsr->fileregex_re);
877 free_attr(bsr->attr);
880 bsr->next->prev = bsr->prev;
883 bsr->prev->next = bsr->next;
889 * Free all bsrs in chain
891 void free_bsr(BSR *bsr)
898 next_bsr = bsr->next;
899 /* Remove (free) current bsr */
901 /* Now get the next one */
905 /*****************************************************************
906 * Routines for handling volumes
908 static VOL_LIST *new_restore_volume()
911 vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
912 memset(vol, 0, sizeof(VOL_LIST));
917 * Create a list of Volumes (and Slots and Start positions) to be
918 * used in the current restore job.
920 void create_restore_volume_list(JCR *jcr)
926 * Build a list of volumes to be processed
928 jcr->NumReadVolumes = 0;
929 jcr->CurReadVolume = 0;
932 if (!bsr->volume || !bsr->volume->VolumeName[0]) {
935 for ( ; bsr; bsr=bsr->next) {
937 BSR_VOLFILE *volfile;
938 uint32_t sfile = UINT32_MAX;
940 /* Find minimum start file so that we can forward space to it */
941 for (volfile = bsr->volfile; volfile; volfile=volfile->next) {
942 if (volfile->sfile < sfile) {
943 sfile = volfile->sfile;
946 /* Now add volumes for this bsr */
947 for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) {
948 vol = new_restore_volume();
949 bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
950 bstrncpy(vol->MediaType, bsrvol->MediaType, sizeof(vol->MediaType));
951 bstrncpy(vol->device, bsrvol->device, sizeof(vol->device));
952 vol->Slot = bsrvol->Slot;
953 vol->start_file = sfile;
954 if (add_restore_volume(jcr, vol)) {
955 jcr->NumReadVolumes++;
956 Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName,
959 Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
962 sfile = 0; /* start at beginning of second volume */
966 /* This is the old way -- deprecated */
967 for (p = jcr->dcr->VolumeName; p && *p; ) {
968 n = strchr(p, '|'); /* volume name separator */
970 *n++ = 0; /* Terminate name */
972 vol = new_restore_volume();
973 bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
974 bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType));
975 if (add_restore_volume(jcr, vol)) {
976 jcr->NumReadVolumes++;
986 * Add current volume to end of list, only if the Volume
987 * is not already in the list.
989 * returns: 1 if volume added
990 * 0 if volume already in list
992 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol)
994 VOL_LIST *next = jcr->VolList;
996 /* Add volume to volume manager's read list */
997 add_read_volume(jcr, vol->VolumeName);
999 if (!next) { /* list empty ? */
1000 jcr->VolList = vol; /* yes, add volume */
1002 /* Loop through all but last */
1003 for ( ; next->next; next=next->next) {
1004 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
1005 /* Save smallest start file */
1006 if (vol->start_file < next->start_file) {
1007 next->start_file = vol->start_file;
1009 return false; /* already in list */
1012 /* Check last volume in list */
1013 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
1014 if (vol->start_file < next->start_file) {
1015 next->start_file = vol->start_file;
1017 return false; /* already in list */
1019 next->next = vol; /* add volume */
1024 void free_restore_volume_list(JCR *jcr)
1026 VOL_LIST *vol = jcr->VolList;
1031 remove_read_volume(jcr, vol->VolumeName);
1035 jcr->VolList = NULL;
1040 * Format a scanner error message
1042 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
1044 JCR *jcr = (JCR *)(lc->caller_ctx);
1046 char buf[MAXSTRING];
1048 va_start(arg_ptr, msg);
1049 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
1053 Jmsg(jcr, M_FATAL, 0, _("Bootstrap file error: %s\n"
1054 " : Line %d, col %d of file %s\n%s\n"),
1055 buf, lc->line_no, lc->col_no, lc->fname, lc->line);
1057 e_msg(file, line, M_FATAL, 0, _("Bootstrap file error: %s\n"
1058 " : Line %d, col %d of file %s\n%s\n"),
1059 buf, lc->line_no, lc->col_no, lc->fname, lc->line);