2 Bacula(R) - The Network Backup Solution
4 Copyright (C) 2000-2017 Kern Sibbald
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.
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 This notice must be preserved when any source code is
15 conveyed and/or propagated.
17 Bacula(R) is a registered trademark of Kern Sibbald.
20 * Parse a Bootstrap Records (used for restores)
22 * Kern Sibbald, June MMII
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);
33 typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
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);
61 ITEM_HANDLER *handler;
65 * List of all keywords permitted in bsr files and their handlers
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},
78 {"jobtype", store_jobtype},
79 {"mediatype", store_mediatype},
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},
97 BSR *bsr = (BSR *)malloc(sizeof(BSR));
98 memset(bsr, 0, sizeof(BSR));
103 /*********************************************************************
105 * Parse Bootstrap file
108 BSR *parse_bsr(JCR *jcr, char *fname)
112 BSR *root_bsr = new_bsr();
115 Dmsg1(300, "Enter parse_bsf %s\n", fname);
116 if ((lc = lex_open_file(lc, fname, s_err)) == NULL) {
118 Emsg2(M_ERROR_TERM, 0, _("Cannot open bootstrap file %s: %s\n"),
119 fname, be.bstrerror());
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) {
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);
136 Dmsg1(300, "calling handler for %s\n", items[i].name);
137 /* Call item handler */
138 bsr = items[i].handler(lc, bsr);
144 Dmsg1(300, "Keyword = %s\n", lc->str);
145 scan_err1(lc, "Keyword %s not found", lc->str);
153 lc = lex_close_file(lc);
154 Dmsg0(300, "Leave parse_bsf()\n");
160 root_bsr->use_fast_rejection = is_fast_rejection_ok(root_bsr);
161 root_bsr->use_positioning = is_positioning_ok(root_bsr);
163 for (bsr=root_bsr; bsr; bsr=bsr->next) {
164 bsr->root = root_bsr;
169 static BSR *store_client(LEX *lc, BSR *bsr)
175 token = lex_get_token(lc, T_NAME);
176 if (token == T_ERROR) {
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 */
184 bsr->client = client;
186 BSR_CLIENT *bc = bsr->client;
187 for ( ;bc->next; bc=bc->next)
191 token = lex_get_token(lc, T_ALL);
192 if (token != T_COMMA) {
199 static BSR *store_count(LEX *lc, BSR *bsr)
203 token = lex_get_token(lc, T_PINT32);
204 if (token == T_ERROR) {
207 bsr->count = lc->pint32_val;
212 /* Shove the Device name in each Volume in the current bsr */
213 static BSR *store_device(LEX *lc, BSR *bsr)
217 token = lex_get_token(lc, T_STRING);
218 if (token == T_ERROR) {
222 Emsg1(M_ERROR,0, _("Device \"%s\" in bsr at inappropriate place.\n"),
227 for (bv=bsr->volume; bv; bv=bv->next) {
228 bstrncpy(bv->device, lc->str, sizeof(bv->device));
233 static BSR *store_findex(LEX *lc, BSR *bsr)
239 token = lex_get_token(lc, T_PINT32_RANGE);
240 if (token == T_ERROR) {
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;
251 /* Add to end of chain */
252 BSR_FINDEX *bs = bsr->FileIndex;
253 for ( ;bs->next; bs=bs->next)
257 token = lex_get_token(lc, T_ALL);
258 if (token != T_COMMA) {
265 static BSR *store_fileregex(LEX *lc, BSR *bsr)
270 token = lex_get_token(lc, T_STRING);
271 if (token == T_ERROR) {
275 if (bsr->fileregex) free(bsr->fileregex);
276 bsr->fileregex = bstrdup(lc->str);
278 if (bsr->fileregex_re == NULL)
279 bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));
281 rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
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);
292 static BSR *store_jobid(LEX *lc, BSR *bsr)
298 token = lex_get_token(lc, T_PINT32_RANGE);
299 if (token == T_ERROR) {
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 */
310 /* Add to end of chain */
311 BSR_JOBID *bs = bsr->JobId;
312 for ( ;bs->next; bs=bs->next)
316 token = lex_get_token(lc, T_ALL);
317 if (token != T_COMMA) {
325 static BSR *store_jobtype(LEX *lc, BSR *bsr)
327 /* *****FIXME****** */
328 Pmsg0(-1, _("JobType not yet implemented\n"));
333 static BSR *store_joblevel(LEX *lc, BSR *bsr)
335 /* *****FIXME****** */
336 Pmsg0(-1, _("JobLevel not yet implemented\n"));
340 static BSR *store_job(LEX *lc, BSR *bsr)
346 token = lex_get_token(lc, T_NAME);
347 if (token == T_ERROR) {
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 */
357 /* Add to end of chain */
358 BSR_JOB *bc = bsr->job;
359 for ( ;bc->next; bc=bc->next)
363 token = lex_get_token(lc, T_ALL);
364 if (token != T_COMMA) {
371 /* Shove the MediaType in each Volume in the current bsr */
372 static BSR *store_mediatype(LEX *lc, BSR *bsr)
376 token = lex_get_token(lc, T_STRING);
377 if (token == T_ERROR) {
381 Emsg1(M_ERROR,0, _("MediaType %s in bsr at inappropriate place.\n"),
386 for (bv=bsr->volume; bv; bv=bv->next) {
387 bstrncpy(bv->MediaType, lc->str, sizeof(bv->MediaType));
392 static BSR *store_vol(LEX *lc, BSR *bsr)
398 token = lex_get_token(lc, T_STRING);
399 if (token == T_ERROR) {
403 bsr->next = new_bsr();
404 bsr->next->prev = bsr;
407 /* This may actually be more than one volume separated by a |
408 * If so, separate them.
410 for (p=lc->str; p && *p; ) {
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 */
420 bsr->volume = volume;
422 BSR_VOLUME *bc = bsr->volume;
423 for ( ;bc->next; bc=bc->next)
432 static bool is_positioning_ok(BSR *bsr)
435 * Every bsr should have a volfile entry and a volblock entry
437 * if we are going to use positioning
439 for ( ; bsr; bsr=bsr->next) {
440 if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
447 static bool is_fast_rejection_ok(BSR *bsr)
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.
454 for ( ; bsr; bsr=bsr->next) {
455 if (!(bsr->sesstime && bsr->sessid)) {
463 static BSR *store_nothing(LEX *lc, BSR *bsr)
467 token = lex_get_token(lc, T_STRING);
468 if (token == T_ERROR) {
477 * Routine to handle Volume start/end file
479 static BSR *store_volfile(LEX *lc, BSR *bsr)
482 BSR_VOLFILE *volfile;
485 token = lex_get_token(lc, T_PINT32_RANGE);
486 if (token == T_ERROR) {
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 */
495 bsr->volfile = volfile;
497 /* Add to end of chain */
498 BSR_VOLFILE *bs = bsr->volfile;
499 for ( ;bs->next; bs=bs->next)
503 token = lex_get_token(lc, T_ALL);
504 if (token != T_COMMA) {
513 * Routine to handle Volume start/end Block
515 static BSR *store_volblock(LEX *lc, BSR *bsr)
518 BSR_VOLBLOCK *volblock;
521 token = lex_get_token(lc, T_PINT32_RANGE);
522 if (token == T_ERROR) {
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;
533 /* Add to end of chain */
534 BSR_VOLBLOCK *bs = bsr->volblock;
535 for ( ;bs->next; bs=bs->next)
539 token = lex_get_token(lc, T_ALL);
540 if (token != T_COMMA) {
548 * Routine to handle Volume start/end address
550 static BSR *store_voladdr(LEX *lc, BSR *bsr)
553 BSR_VOLADDR *voladdr;
556 token = lex_get_token(lc, T_PINT64_RANGE);
557 if (token == T_ERROR) {
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 */
566 bsr->voladdr = voladdr;
568 /* Add to end of chain */
569 BSR_VOLADDR *bs = bsr->voladdr;
570 for ( ;bs->next; bs=bs->next)
574 token = lex_get_token(lc, T_ALL);
575 if (token != T_COMMA) {
582 static BSR *store_sessid(LEX *lc, BSR *bsr)
588 token = lex_get_token(lc, T_PINT32_RANGE);
589 if (token == T_ERROR) {
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 */
600 /* Add to end of chain */
601 BSR_SESSID *bs = bsr->sessid;
602 for ( ;bs->next; bs=bs->next)
606 token = lex_get_token(lc, T_ALL);
607 if (token != T_COMMA) {
614 static BSR *store_sesstime(LEX *lc, BSR *bsr)
620 token = lex_get_token(lc, T_PINT32);
621 if (token == T_ERROR) {
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;
631 /* Add to end of chain */
632 BSR_SESSTIME *bs = bsr->sesstime;
633 for ( ;bs->next; bs=bs->next)
637 token = lex_get_token(lc, T_ALL);
638 if (token != T_COMMA) {
646 static BSR *store_stream(LEX *lc, BSR *bsr)
652 token = lex_get_token(lc, T_INT32);
653 if (token == T_ERROR) {
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 */
661 bsr->stream = stream;
663 /* Add to end of chain */
664 BSR_STREAM *bs = bsr->stream;
665 for ( ;bs->next; bs=bs->next)
669 token = lex_get_token(lc, T_ALL);
670 if (token != T_COMMA) {
677 static BSR *store_slot(LEX *lc, BSR *bsr)
681 token = lex_get_token(lc, T_PINT32);
682 if (token == T_ERROR) {
686 Emsg1(M_ERROR,0, _("Slot %d in bsr at inappropriate place.\n"),
690 bsr->volume->Slot = lc->pint32_val;
695 static BSR *store_include(LEX *lc, BSR *bsr)
701 static BSR *store_exclude(LEX *lc, BSR *bsr)
707 void dump_volfile(BSR_VOLFILE *volfile)
710 Pmsg2(-1, _("VolFile : %u-%u\n"), volfile->sfile, volfile->efile);
711 dump_volfile(volfile->next);
715 void dump_volblock(BSR_VOLBLOCK *volblock)
718 Pmsg2(-1, _("VolBlock : %u-%u\n"), volblock->sblock, volblock->eblock);
719 dump_volblock(volblock->next);
723 void dump_voladdr(DEVICE *dev, BSR_VOLADDR *voladdr)
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));
732 Pmsg2(-1, _("VolAddr : %llu-%llu\n"), voladdr->saddr, voladdr->eaddr);
734 dump_voladdr(dev, voladdr->next);
738 void dump_findex(BSR_FINDEX *FileIndex)
741 if (FileIndex->findex == FileIndex->findex2) {
742 Pmsg1(-1, _("FileIndex : %u\n"), FileIndex->findex);
744 Pmsg2(-1, _("FileIndex : %u-%u\n"), FileIndex->findex, FileIndex->findex2);
746 dump_findex(FileIndex->next);
750 void dump_jobid(BSR_JOBID *jobid)
753 if (jobid->JobId == jobid->JobId2) {
754 Pmsg1(-1, _("JobId : %u\n"), jobid->JobId);
756 Pmsg2(-1, _("JobId : %u-%u\n"), jobid->JobId, jobid->JobId2);
758 dump_jobid(jobid->next);
762 void dump_sessid(BSR_SESSID *sessid)
765 if (sessid->sessid == sessid->sessid2) {
766 Pmsg1(-1, _("SessId : %u\n"), sessid->sessid);
768 Pmsg2(-1, _("SessId : %u-%u\n"), sessid->sessid, sessid->sessid2);
770 dump_sessid(sessid->next);
774 void dump_volume(BSR_VOLUME *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);
786 void dump_client(BSR_CLIENT *client)
789 Pmsg1(-1, _("Client : %s\n"), client->ClientName);
790 dump_client(client->next);
794 void dump_job(BSR_JOB *job)
797 Pmsg1(-1, _("Job : %s\n"), job->Job);
802 void dump_sesstime(BSR_SESSTIME *sesstime)
805 Pmsg1(-1, _("SessTime : %u\n"), sesstime->sesstime);
806 dump_sesstime(sesstime->next);
811 void dump_bsr(DEVICE *dev, BSR *bsr, bool recurse)
813 int64_t save_debug = debug_level;
816 Pmsg0(-1, _("BSR is NULL\n"));
817 debug_level = save_debug;
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);
831 dump_findex(bsr->FileIndex);
833 Pmsg1(-1, _("count : %u\n"), bsr->count);
834 Pmsg1(-1, _("found : %u\n"), bsr->found);
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) {
842 dump_bsr(dev, bsr->next, true);
844 debug_level = save_debug;
847 /*********************************************************************
852 static void free_bsr_item(BSR *bsr)
863 * Remove a single item from the bsr tree
865 void remove_bsr(BSR *bsr)
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);
882 if (bsr->fileregex_re) {
883 regfree(bsr->fileregex_re);
884 free(bsr->fileregex_re);
887 free_attr(bsr->attr);
890 bsr->next->prev = bsr->prev;
893 bsr->prev->next = bsr->next;
899 * Free all bsrs in chain
901 void free_bsr(BSR *bsr)
905 next_bsr = bsr->next;
906 /* Remove (free) current bsr */
908 /* Now get the next one */
913 /*****************************************************************
914 * Routines for handling volumes
916 static VOL_LIST *new_restore_volume()
919 vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
920 memset(vol, 0, sizeof(VOL_LIST));
925 * Create a list of Volumes (and Slots and Start positions) to be
926 * used in the current restore job.
928 void create_restore_volume_list(JCR *jcr, bool add_to_read_list)
934 * Build a list of volumes to be processed
936 jcr->NumReadVolumes = 0;
937 jcr->CurReadVolume = 0;
940 if (!bsr->volume || !bsr->volume->VolumeName[0]) {
943 for ( ; bsr; bsr=bsr->next) {
945 BSR_VOLFILE *volfile;
946 uint32_t sfile = UINT32_MAX;
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;
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,
967 Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
970 sfile = 0; /* start at beginning of second volume */
974 /* This is the old way -- deprecated */
975 for (p = jcr->dcr->VolumeName; p && *p; ) {
976 n = strchr(p, '|'); /* volume name separator */
978 *n++ = 0; /* Terminate name */
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++;
994 * Add current volume to end of list, only if the Volume
995 * is not already in the list.
997 * returns: 1 if volume added
998 * 0 if volume already in list
1000 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol, bool add_to_read_list)
1002 VOL_LIST *next = jcr->VolList;
1004 if (add_to_read_list) {
1005 /* Add volume to volume manager's read list */
1006 add_read_volume(jcr, vol->VolumeName);
1009 if (!next) { /* list empty ? */
1010 jcr->VolList = vol; /* yes, add volume */
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;
1019 return false; /* already in list */
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;
1027 return false; /* already in list */
1029 next->next = vol; /* add volume */
1034 void free_restore_volume_list(JCR *jcr)
1036 VOL_LIST *vol = jcr->VolList;
1041 remove_read_volume(jcr, vol->VolumeName);
1045 jcr->VolList = NULL;
1050 * Format a scanner error message
1052 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
1054 JCR *jcr = (JCR *)(lc->caller_ctx);
1056 char buf[MAXSTRING];
1058 va_start(arg_ptr, msg);
1059 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
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);
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);