2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2009 Free Software Foundation Europe e.V.
6 The main author of Bacula is Kern Sibbald, with contributions from
7 many others, a complete list can be found in the file AUTHORS.
8 This program is Free Software; you can redistribute it and/or
9 modify it under the terms of version two of the GNU General Public
10 License as published by the Free Software Foundation and included
13 This program is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23 Bacula® is a registered trademark of Kern Sibbald.
24 The licensor of Bacula is the Free Software Foundation Europe
25 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26 Switzerland, email:ftf@fsfeurope.org.
29 * Parse a Bootstrap Records (used for restores)
31 * Kern Sibbald, June MMII
40 typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
42 static BSR *store_vol(LEX *lc, BSR *bsr);
43 static BSR *store_mediatype(LEX *lc, BSR *bsr);
44 static BSR *store_device(LEX *lc, BSR *bsr);
45 static BSR *store_client(LEX *lc, BSR *bsr);
46 static BSR *store_job(LEX *lc, BSR *bsr);
47 static BSR *store_jobid(LEX *lc, BSR *bsr);
48 static BSR *store_count(LEX *lc, BSR *bsr);
49 static BSR *store_jobtype(LEX *lc, BSR *bsr);
50 static BSR *store_joblevel(LEX *lc, BSR *bsr);
51 static BSR *store_findex(LEX *lc, BSR *bsr);
52 static BSR *store_sessid(LEX *lc, BSR *bsr);
53 static BSR *store_volfile(LEX *lc, BSR *bsr);
54 static BSR *store_volblock(LEX *lc, BSR *bsr);
55 static BSR *store_voladdr(LEX *lc, BSR *bsr);
56 static BSR *store_sesstime(LEX *lc, BSR *bsr);
57 static BSR *store_include(LEX *lc, BSR *bsr);
58 static BSR *store_exclude(LEX *lc, BSR *bsr);
59 static BSR *store_stream(LEX *lc, BSR *bsr);
60 static BSR *store_slot(LEX *lc, BSR *bsr);
61 static BSR *store_fileregex(LEX *lc, BSR *bsr);
62 static BSR *store_nothing(LEX *lc, BSR *bsr);
63 static bool is_fast_rejection_ok(BSR *bsr);
64 static bool is_positioning_ok(BSR *bsr);
68 ITEM_HANDLER *handler;
72 * List of all keywords permitted in bsr files and their handlers
74 struct kw_items items[] = {
75 {"volume", store_vol},
76 {"mediatype", store_mediatype},
77 {"client", store_client},
79 {"jobid", store_jobid},
80 {"count", store_count},
81 {"fileindex", store_findex},
82 {"jobtype", store_jobtype},
83 {"joblevel", store_joblevel},
84 {"volsessionid", store_sessid},
85 {"volsessiontime", store_sesstime},
86 {"include", store_include},
87 {"exclude", store_exclude},
88 {"volfile", store_volfile},
89 {"volblock", store_volblock},
90 {"voladdr", store_voladdr},
91 {"stream", store_stream},
93 {"device", store_device},
94 {"fileregex", store_fileregex},
95 {"storage", store_nothing},
100 * Create a BSR record
102 static BSR *new_bsr()
104 BSR *bsr = (BSR *)malloc(sizeof(BSR));
105 memset(bsr, 0, sizeof(BSR));
110 * Format a scanner error message
112 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
114 JCR *jcr = (JCR *)(lc->caller_ctx);
118 va_start(arg_ptr, msg);
119 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
123 Jmsg(jcr, M_FATAL, 0, _("Bootstrap file error: %s\n"
124 " : Line %d, col %d of file %s\n%s\n"),
125 buf, lc->line_no, lc->col_no, lc->fname, lc->line);
127 e_msg(file, line, M_FATAL, 0, _("Bootstrap file error: %s\n"
128 " : Line %d, col %d of file %s\n%s\n"),
129 buf, lc->line_no, lc->col_no, lc->fname, lc->line);
134 /*********************************************************************
136 * Parse Bootstrap file
139 BSR *parse_bsr(JCR *jcr, char *fname)
143 BSR *root_bsr = new_bsr();
146 Dmsg1(300, "Enter parse_bsf %s\n", fname);
147 if ((lc = lex_open_file(lc, fname, s_err)) == NULL) {
149 Emsg2(M_ERROR_TERM, 0, _("Cannot open bootstrap file %s: %s\n"),
150 fname, be.bstrerror());
152 lc->caller_ctx = (void *)jcr;
153 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
154 Dmsg1(300, "parse got token=%s\n", lex_tok_to_str(token));
155 if (token == T_EOL) {
158 for (i=0; items[i].name; i++) {
159 if (strcasecmp(items[i].name, lc->str) == 0) {
160 token = lex_get_token(lc, T_ALL);
161 Dmsg1 (300, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
162 if (token != T_EQUALS) {
163 scan_err1(lc, "expected an equals, got: %s", lc->str);
167 Dmsg1(300, "calling handler for %s\n", items[i].name);
168 /* Call item handler */
169 bsr = items[i].handler(lc, bsr);
175 Dmsg1(300, "Keyword = %s\n", lc->str);
176 scan_err1(lc, "Keyword %s not found", lc->str);
184 lc = lex_close_file(lc);
185 Dmsg0(300, "Leave parse_bsf()\n");
191 root_bsr->use_fast_rejection = is_fast_rejection_ok(root_bsr);
192 root_bsr->use_positioning = is_positioning_ok(root_bsr);
194 for (bsr=root_bsr; bsr; bsr=bsr->next) {
195 bsr->root = root_bsr;
200 static bool is_fast_rejection_ok(BSR *bsr)
203 * Although, this can be optimized, for the moment, require
204 * all bsrs to have both sesstime and sessid set before
205 * we do fast rejection.
207 for ( ; bsr; bsr=bsr->next) {
208 if (!(bsr->sesstime && bsr->sessid)) {
215 static bool is_positioning_ok(BSR *bsr)
218 * Every bsr should have a volfile entry and a volblock entry
220 * if we are going to use positioning
222 for ( ; bsr; bsr=bsr->next) {
223 if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
230 static BSR *store_vol(LEX *lc, BSR *bsr)
236 token = lex_get_token(lc, T_STRING);
237 if (token == T_ERROR) {
241 bsr->next = new_bsr();
242 bsr->next->prev = bsr;
245 /* This may actually be more than one volume separated by a |
246 * If so, separate them.
248 for (p=lc->str; p && *p; ) {
253 volume = (BSR_VOLUME *)malloc(sizeof(BSR_VOLUME));
254 memset(volume, 0, sizeof(BSR_VOLUME));
255 bstrncpy(volume->VolumeName, p, sizeof(volume->VolumeName));
256 /* Add it to the end of the volume chain */
258 bsr->volume = volume;
260 BSR_VOLUME *bc = bsr->volume;
261 for ( ;bc->next; bc=bc->next)
270 /* Shove the MediaType in each Volume in the current bsr */
271 static BSR *store_mediatype(LEX *lc, BSR *bsr)
275 token = lex_get_token(lc, T_STRING);
276 if (token == T_ERROR) {
280 Emsg1(M_ERROR,0, _("MediaType %s in bsr at inappropriate place.\n"),
285 for (bv=bsr->volume; bv; bv=bv->next) {
286 bstrncpy(bv->MediaType, lc->str, sizeof(bv->MediaType));
291 static BSR *store_nothing(LEX *lc, BSR *bsr)
295 token = lex_get_token(lc, T_STRING);
296 if (token == T_ERROR) {
302 /* Shove the Device name in each Volume in the current bsr */
303 static BSR *store_device(LEX *lc, BSR *bsr)
307 token = lex_get_token(lc, T_STRING);
308 if (token == T_ERROR) {
312 Emsg1(M_ERROR,0, _("Device \"%s\" in bsr at inappropriate place.\n"),
317 for (bv=bsr->volume; bv; bv=bv->next) {
318 bstrncpy(bv->device, lc->str, sizeof(bv->device));
325 static BSR *store_client(LEX *lc, BSR *bsr)
331 token = lex_get_token(lc, T_NAME);
332 if (token == T_ERROR) {
335 client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
336 memset(client, 0, sizeof(BSR_CLIENT));
337 bstrncpy(client->ClientName, lc->str, sizeof(client->ClientName));
338 /* Add it to the end of the client chain */
340 bsr->client = client;
342 BSR_CLIENT *bc = bsr->client;
343 for ( ;bc->next; bc=bc->next)
347 token = lex_get_token(lc, T_ALL);
348 if (token != T_COMMA) {
355 static BSR *store_job(LEX *lc, BSR *bsr)
361 token = lex_get_token(lc, T_NAME);
362 if (token == T_ERROR) {
365 job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
366 memset(job, 0, sizeof(BSR_JOB));
367 bstrncpy(job->Job, lc->str, sizeof(job->Job));
368 /* Add it to the end of the client chain */
372 /* Add to end of chain */
373 BSR_JOB *bc = bsr->job;
374 for ( ;bc->next; bc=bc->next)
378 token = lex_get_token(lc, T_ALL);
379 if (token != T_COMMA) {
386 static BSR *store_findex(LEX *lc, BSR *bsr)
392 token = lex_get_token(lc, T_PINT32_RANGE);
393 if (token == T_ERROR) {
396 findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
397 memset(findex, 0, sizeof(BSR_FINDEX));
398 findex->findex = lc->pint32_val;
399 findex->findex2 = lc->pint32_val2;
400 /* Add it to the end of the chain */
401 if (!bsr->FileIndex) {
402 bsr->FileIndex = findex;
404 /* Add to end of chain */
405 BSR_FINDEX *bs = bsr->FileIndex;
406 for ( ;bs->next; bs=bs->next)
410 token = lex_get_token(lc, T_ALL);
411 if (token != T_COMMA) {
419 static BSR *store_jobid(LEX *lc, BSR *bsr)
425 token = lex_get_token(lc, T_PINT32_RANGE);
426 if (token == T_ERROR) {
429 jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
430 memset(jobid, 0, sizeof(BSR_JOBID));
431 jobid->JobId = lc->pint32_val;
432 jobid->JobId2 = lc->pint32_val2;
433 /* Add it to the end of the chain */
437 /* Add to end of chain */
438 BSR_JOBID *bs = bsr->JobId;
439 for ( ;bs->next; bs=bs->next)
443 token = lex_get_token(lc, T_ALL);
444 if (token != T_COMMA) {
452 static BSR *store_count(LEX *lc, BSR *bsr)
456 token = lex_get_token(lc, T_PINT32);
457 if (token == T_ERROR) {
460 bsr->count = lc->pint32_val;
465 static BSR *store_fileregex(LEX *lc, BSR *bsr)
470 token = lex_get_token(lc, T_STRING);
471 if (token == T_ERROR) {
475 if (bsr->fileregex) free(bsr->fileregex);
476 bsr->fileregex = bstrdup(lc->str);
478 if (bsr->fileregex_re == NULL)
479 bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));
481 rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
484 regerror(rc, bsr->fileregex_re, prbuf, sizeof(prbuf));
485 Emsg2(M_ERROR, 0, _("REGEX '%s' compile error. ERR=%s\n"),
486 bsr->fileregex, prbuf);
492 static BSR *store_jobtype(LEX *lc, BSR *bsr)
494 /* *****FIXME****** */
495 Pmsg0(-1, _("JobType not yet implemented\n"));
500 static BSR *store_joblevel(LEX *lc, BSR *bsr)
502 /* *****FIXME****** */
503 Pmsg0(-1, _("JobLevel not yet implemented\n"));
511 * Routine to handle Volume start/end file
513 static BSR *store_volfile(LEX *lc, BSR *bsr)
516 BSR_VOLFILE *volfile;
519 token = lex_get_token(lc, T_PINT32_RANGE);
520 if (token == T_ERROR) {
523 volfile = (BSR_VOLFILE *)malloc(sizeof(BSR_VOLFILE));
524 memset(volfile, 0, sizeof(BSR_VOLFILE));
525 volfile->sfile = lc->pint32_val;
526 volfile->efile = lc->pint32_val2;
527 /* Add it to the end of the chain */
529 bsr->volfile = volfile;
531 /* Add to end of chain */
532 BSR_VOLFILE *bs = bsr->volfile;
533 for ( ;bs->next; bs=bs->next)
537 token = lex_get_token(lc, T_ALL);
538 if (token != T_COMMA) {
547 * Routine to handle Volume start/end Block
549 static BSR *store_volblock(LEX *lc, BSR *bsr)
552 BSR_VOLBLOCK *volblock;
555 token = lex_get_token(lc, T_PINT32_RANGE);
556 if (token == T_ERROR) {
559 volblock = (BSR_VOLBLOCK *)malloc(sizeof(BSR_VOLBLOCK));
560 memset(volblock, 0, sizeof(BSR_VOLBLOCK));
561 volblock->sblock = lc->pint32_val;
562 volblock->eblock = lc->pint32_val2;
563 /* Add it to the end of the chain */
564 if (!bsr->volblock) {
565 bsr->volblock = volblock;
567 /* Add to end of chain */
568 BSR_VOLBLOCK *bs = bsr->volblock;
569 for ( ;bs->next; bs=bs->next)
573 token = lex_get_token(lc, T_ALL);
574 if (token != T_COMMA) {
582 * Routine to handle Volume start/end address
584 static BSR *store_voladdr(LEX *lc, BSR *bsr)
587 BSR_VOLADDR *voladdr;
590 token = lex_get_token(lc, T_PINT64_RANGE);
591 if (token == T_ERROR) {
594 voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR));
595 memset(voladdr, 0, sizeof(BSR_VOLADDR));
596 voladdr->saddr = lc->pint64_val;
597 voladdr->eaddr = lc->pint64_val2;
598 /* Add it to the end of the chain */
600 bsr->voladdr = voladdr;
602 /* Add to end of chain */
603 BSR_VOLADDR *bs = bsr->voladdr;
604 for ( ;bs->next; bs=bs->next)
608 token = lex_get_token(lc, T_ALL);
609 if (token != T_COMMA) {
616 static BSR *store_sessid(LEX *lc, BSR *bsr)
622 token = lex_get_token(lc, T_PINT32_RANGE);
623 if (token == T_ERROR) {
626 sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
627 memset(sid, 0, sizeof(BSR_SESSID));
628 sid->sessid = lc->pint32_val;
629 sid->sessid2 = lc->pint32_val2;
630 /* Add it to the end of the chain */
634 /* Add to end of chain */
635 BSR_SESSID *bs = bsr->sessid;
636 for ( ;bs->next; bs=bs->next)
640 token = lex_get_token(lc, T_ALL);
641 if (token != T_COMMA) {
648 static BSR *store_sesstime(LEX *lc, BSR *bsr)
654 token = lex_get_token(lc, T_PINT32);
655 if (token == T_ERROR) {
658 stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
659 memset(stime, 0, sizeof(BSR_SESSTIME));
660 stime->sesstime = lc->pint32_val;
661 /* Add it to the end of the chain */
662 if (!bsr->sesstime) {
663 bsr->sesstime = stime;
665 /* Add to end of chain */
666 BSR_SESSTIME *bs = bsr->sesstime;
667 for ( ;bs->next; bs=bs->next)
671 token = lex_get_token(lc, T_ALL);
672 if (token != T_COMMA) {
680 static BSR *store_stream(LEX *lc, BSR *bsr)
686 token = lex_get_token(lc, T_INT32);
687 if (token == T_ERROR) {
690 stream = (BSR_STREAM *)malloc(sizeof(BSR_STREAM));
691 memset(stream, 0, sizeof(BSR_STREAM));
692 stream->stream = lc->int32_val;
693 /* Add it to the end of the chain */
695 bsr->stream = stream;
697 /* Add to end of chain */
698 BSR_STREAM *bs = bsr->stream;
699 for ( ;bs->next; bs=bs->next)
703 token = lex_get_token(lc, T_ALL);
704 if (token != T_COMMA) {
711 static BSR *store_slot(LEX *lc, BSR *bsr)
715 token = lex_get_token(lc, T_PINT32);
716 if (token == T_ERROR) {
720 Emsg1(M_ERROR,0, _("Slot %d in bsr at inappropriate place.\n"),
724 bsr->volume->Slot = lc->pint32_val;
729 static BSR *store_include(LEX *lc, BSR *bsr)
735 static BSR *store_exclude(LEX *lc, BSR *bsr)
741 void dump_volfile(BSR_VOLFILE *volfile)
744 Pmsg2(-1, _("VolFile : %u-%u\n"), volfile->sfile, volfile->efile);
745 dump_volfile(volfile->next);
749 void dump_volblock(BSR_VOLBLOCK *volblock)
752 Pmsg2(-1, _("VolBlock : %u-%u\n"), volblock->sblock, volblock->eblock);
753 dump_volblock(volblock->next);
757 void dump_voladdr(BSR_VOLADDR *voladdr)
760 Pmsg2(-1, _("VolAddr : %llu-%llu\n"), voladdr->saddr, voladdr->eaddr);
761 dump_voladdr(voladdr->next);
765 void dump_findex(BSR_FINDEX *FileIndex)
768 if (FileIndex->findex == FileIndex->findex2) {
769 Pmsg1(-1, _("FileIndex : %u\n"), FileIndex->findex);
771 Pmsg2(-1, _("FileIndex : %u-%u\n"), FileIndex->findex, FileIndex->findex2);
773 dump_findex(FileIndex->next);
777 void dump_jobid(BSR_JOBID *jobid)
780 if (jobid->JobId == jobid->JobId2) {
781 Pmsg1(-1, _("JobId : %u\n"), jobid->JobId);
783 Pmsg2(-1, _("JobId : %u-%u\n"), jobid->JobId, jobid->JobId2);
785 dump_jobid(jobid->next);
789 void dump_sessid(BSR_SESSID *sessid)
792 if (sessid->sessid == sessid->sessid2) {
793 Pmsg1(-1, _("SessId : %u\n"), sessid->sessid);
795 Pmsg2(-1, _("SessId : %u-%u\n"), sessid->sessid, sessid->sessid2);
797 dump_sessid(sessid->next);
801 void dump_volume(BSR_VOLUME *volume)
804 Pmsg1(-1, _("VolumeName : %s\n"), volume->VolumeName);
805 Pmsg1(-1, _(" MediaType : %s\n"), volume->MediaType);
806 Pmsg1(-1, _(" Device : %s\n"), volume->device);
807 Pmsg1(-1, _(" Slot : %d\n"), volume->Slot);
808 dump_volume(volume->next);
813 void dump_client(BSR_CLIENT *client)
816 Pmsg1(-1, _("Client : %s\n"), client->ClientName);
817 dump_client(client->next);
821 void dump_job(BSR_JOB *job)
824 Pmsg1(-1, _("Job : %s\n"), job->Job);
829 void dump_sesstime(BSR_SESSTIME *sesstime)
832 Pmsg1(-1, _("SessTime : %u\n"), sesstime->sesstime);
833 dump_sesstime(sesstime->next);
838 void dump_bsr(BSR *bsr, bool recurse)
840 int save_debug = debug_level;
843 Pmsg0(-1, _("BSR is NULL\n"));
844 debug_level = save_debug;
847 Pmsg1(-1, _("Next : 0x%x\n"), bsr->next);
848 Pmsg1(-1, _("Root bsr : 0x%x\n"), bsr->root);
849 dump_volume(bsr->volume);
850 dump_sessid(bsr->sessid);
851 dump_sesstime(bsr->sesstime);
852 dump_volfile(bsr->volfile);
853 dump_volblock(bsr->volblock);
854 dump_voladdr(bsr->voladdr);
855 dump_client(bsr->client);
856 dump_jobid(bsr->JobId);
858 dump_findex(bsr->FileIndex);
860 Pmsg1(-1, _("count : %u\n"), bsr->count);
861 Pmsg1(-1, _("found : %u\n"), bsr->found);
864 Pmsg1(-1, _("done : %s\n"), bsr->done?_("yes"):_("no"));
865 Pmsg1(-1, _("positioning : %d\n"), bsr->use_positioning);
866 Pmsg1(-1, _("fast_reject : %d\n"), bsr->use_fast_rejection);
867 if (recurse && bsr->next) {
869 dump_bsr(bsr->next, true);
871 debug_level = save_debug;
876 /*********************************************************************
881 static void free_bsr_item(BSR *bsr)
884 free_bsr_item(bsr->next);
890 * Remove a single item from the bsr tree
892 void remove_bsr(BSR *bsr)
894 free_bsr_item((BSR *)bsr->volume);
895 free_bsr_item((BSR *)bsr->client);
896 free_bsr_item((BSR *)bsr->sessid);
897 free_bsr_item((BSR *)bsr->sesstime);
898 free_bsr_item((BSR *)bsr->volfile);
899 free_bsr_item((BSR *)bsr->volblock);
900 free_bsr_item((BSR *)bsr->voladdr);
901 free_bsr_item((BSR *)bsr->JobId);
902 free_bsr_item((BSR *)bsr->job);
903 free_bsr_item((BSR *)bsr->FileIndex);
904 free_bsr_item((BSR *)bsr->JobType);
905 free_bsr_item((BSR *)bsr->JobLevel);
906 if (bsr->fileregex) {
907 bfree(bsr->fileregex);
909 if (bsr->fileregex_re) {
910 regfree(bsr->fileregex_re);
911 free(bsr->fileregex_re);
914 free_attr(bsr->attr);
917 bsr->next->prev = bsr->prev;
920 bsr->prev->next = bsr->next;
926 * Free all bsrs in chain
928 void free_bsr(BSR *bsr)
935 next_bsr = bsr->next;
936 /* Remove (free) current bsr */
938 /* Now get the next one */
942 /*****************************************************************
943 * Routines for handling volumes
945 static VOL_LIST *new_restore_volume()
948 vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
949 memset(vol, 0, sizeof(VOL_LIST));
954 * Add current volume to end of list, only if the Volume
955 * is not already in the list.
957 * returns: 1 if volume added
958 * 0 if volume already in list
960 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol)
962 VOL_LIST *next = jcr->VolList;
964 /* Add volume to volume manager's read list */
965 add_read_volume(jcr, vol->VolumeName);
967 if (!next) { /* list empty ? */
968 jcr->VolList = vol; /* yes, add volume */
970 /* Loop through all but last */
971 for ( ; next->next; next=next->next) {
972 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
973 /* Save smallest start file */
974 if (vol->start_file < next->start_file) {
975 next->start_file = vol->start_file;
977 return false; /* already in list */
980 /* Check last volume in list */
981 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
982 if (vol->start_file < next->start_file) {
983 next->start_file = vol->start_file;
985 return false; /* already in list */
987 next->next = vol; /* add volume */
992 void free_restore_volume_list(JCR *jcr)
994 VOL_LIST *vol = jcr->VolList;
999 remove_read_volume(jcr, vol->VolumeName);
1003 jcr->VolList = NULL;
1007 * Create a list of Volumes (and Slots and Start positions) to be
1008 * used in the current restore job.
1010 void create_restore_volume_list(JCR *jcr)
1016 * Build a list of volumes to be processed
1018 jcr->NumReadVolumes = 0;
1019 jcr->CurReadVolume = 0;
1021 BSR *bsr = jcr->bsr;
1022 if (!bsr->volume || !bsr->volume->VolumeName) {
1025 for ( ; bsr; bsr=bsr->next) {
1027 BSR_VOLFILE *volfile;
1028 uint32_t sfile = UINT32_MAX;
1030 /* Find minimum start file so that we can forward space to it */
1031 for (volfile = bsr->volfile; volfile; volfile=volfile->next) {
1032 if (volfile->sfile < sfile) {
1033 sfile = volfile->sfile;
1036 /* Now add volumes for this bsr */
1037 for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) {
1038 vol = new_restore_volume();
1039 bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
1040 bstrncpy(vol->MediaType, bsrvol->MediaType, sizeof(vol->MediaType));
1041 bstrncpy(vol->device, bsrvol->device, sizeof(vol->device));
1042 vol->Slot = bsrvol->Slot;
1043 vol->start_file = sfile;
1044 if (add_restore_volume(jcr, vol)) {
1045 jcr->NumReadVolumes++;
1046 Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName,
1049 Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
1052 sfile = 0; /* start at beginning of second volume */
1056 /* This is the old way -- deprecated */
1057 for (p = jcr->dcr->VolumeName; p && *p; ) {
1058 n = strchr(p, '|'); /* volume name separator */
1060 *n++ = 0; /* Terminate name */
1062 vol = new_restore_volume();
1063 bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
1064 bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType));
1065 if (add_restore_volume(jcr, vol)) {
1066 jcr->NumReadVolumes++;