2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2012 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 three of the GNU Affero 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 Affero 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
39 typedef BSR * (ITEM_HANDLER)(LEX *lc, BSR *bsr);
41 static BSR *store_vol(LEX *lc, BSR *bsr);
42 static BSR *store_mediatype(LEX *lc, BSR *bsr);
43 static BSR *store_device(LEX *lc, BSR *bsr);
44 static BSR *store_client(LEX *lc, BSR *bsr);
45 static BSR *store_job(LEX *lc, BSR *bsr);
46 static BSR *store_jobid(LEX *lc, BSR *bsr);
47 static BSR *store_count(LEX *lc, BSR *bsr);
48 static BSR *store_jobtype(LEX *lc, BSR *bsr);
49 static BSR *store_joblevel(LEX *lc, BSR *bsr);
50 static BSR *store_findex(LEX *lc, BSR *bsr);
51 static BSR *store_sessid(LEX *lc, BSR *bsr);
52 static BSR *store_volfile(LEX *lc, BSR *bsr);
53 static BSR *store_volblock(LEX *lc, BSR *bsr);
54 static BSR *store_voladdr(LEX *lc, BSR *bsr);
55 static BSR *store_sesstime(LEX *lc, BSR *bsr);
56 static BSR *store_include(LEX *lc, BSR *bsr);
57 static BSR *store_exclude(LEX *lc, BSR *bsr);
58 static BSR *store_stream(LEX *lc, BSR *bsr);
59 static BSR *store_slot(LEX *lc, BSR *bsr);
60 static BSR *store_fileregex(LEX *lc, BSR *bsr);
61 static BSR *store_nothing(LEX *lc, BSR *bsr);
62 static bool is_fast_rejection_ok(BSR *bsr);
63 static bool is_positioning_ok(BSR *bsr);
67 ITEM_HANDLER *handler;
71 * List of all keywords permitted in bsr files and their handlers
73 struct kw_items items[] = {
74 {"volume", store_vol},
75 {"mediatype", store_mediatype},
76 {"client", store_client},
78 {"jobid", store_jobid},
79 {"count", store_count},
80 {"fileindex", store_findex},
81 {"jobtype", store_jobtype},
82 {"joblevel", store_joblevel},
83 {"volsessionid", store_sessid},
84 {"volsessiontime", store_sesstime},
85 {"include", store_include},
86 {"exclude", store_exclude},
87 {"volfile", store_volfile},
88 {"volblock", store_volblock},
89 {"voladdr", store_voladdr},
90 {"stream", store_stream},
92 {"device", store_device},
93 {"fileregex", store_fileregex},
94 {"storage", store_nothing},
101 static BSR *new_bsr()
103 BSR *bsr = (BSR *)malloc(sizeof(BSR));
104 memset(bsr, 0, sizeof(BSR));
109 * Format a scanner error message
111 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
113 JCR *jcr = (JCR *)(lc->caller_ctx);
117 va_start(arg_ptr, msg);
118 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
122 Jmsg(jcr, M_FATAL, 0, _("Bootstrap file error: %s\n"
123 " : Line %d, col %d of file %s\n%s\n"),
124 buf, lc->line_no, lc->col_no, lc->fname, lc->line);
126 e_msg(file, line, M_FATAL, 0, _("Bootstrap file error: %s\n"
127 " : Line %d, col %d of file %s\n%s\n"),
128 buf, lc->line_no, lc->col_no, lc->fname, lc->line);
133 /*********************************************************************
135 * Parse Bootstrap file
138 BSR *parse_bsr(JCR *jcr, char *fname)
142 BSR *root_bsr = new_bsr();
145 Dmsg1(300, "Enter parse_bsf %s\n", fname);
146 if ((lc = lex_open_file(lc, fname, s_err)) == NULL) {
148 Emsg2(M_ERROR_TERM, 0, _("Cannot open bootstrap file %s: %s\n"),
149 fname, be.bstrerror());
151 lc->caller_ctx = (void *)jcr;
152 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
153 Dmsg1(300, "parse got token=%s\n", lex_tok_to_str(token));
154 if (token == T_EOL) {
157 for (i=0; items[i].name; i++) {
158 if (strcasecmp(items[i].name, lc->str) == 0) {
159 token = lex_get_token(lc, T_ALL);
160 Dmsg1 (300, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
161 if (token != T_EQUALS) {
162 scan_err1(lc, "expected an equals, got: %s", lc->str);
166 Dmsg1(300, "calling handler for %s\n", items[i].name);
167 /* Call item handler */
168 bsr = items[i].handler(lc, bsr);
174 Dmsg1(300, "Keyword = %s\n", lc->str);
175 scan_err1(lc, "Keyword %s not found", lc->str);
183 lc = lex_close_file(lc);
184 Dmsg0(300, "Leave parse_bsf()\n");
190 root_bsr->use_fast_rejection = is_fast_rejection_ok(root_bsr);
191 root_bsr->use_positioning = is_positioning_ok(root_bsr);
193 for (bsr=root_bsr; bsr; bsr=bsr->next) {
194 bsr->root = root_bsr;
199 static bool is_fast_rejection_ok(BSR *bsr)
202 * Although, this can be optimized, for the moment, require
203 * all bsrs to have both sesstime and sessid set before
204 * we do fast rejection.
206 for ( ; bsr; bsr=bsr->next) {
207 if (!(bsr->sesstime && bsr->sessid)) {
214 static bool is_positioning_ok(BSR *bsr)
217 * Every bsr should have a volfile entry and a volblock entry
219 * if we are going to use positioning
221 for ( ; bsr; bsr=bsr->next) {
222 if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
229 static BSR *store_vol(LEX *lc, BSR *bsr)
235 token = lex_get_token(lc, T_STRING);
236 if (token == T_ERROR) {
240 bsr->next = new_bsr();
241 bsr->next->prev = bsr;
244 /* This may actually be more than one volume separated by a |
245 * If so, separate them.
247 for (p=lc->str; p && *p; ) {
252 volume = (BSR_VOLUME *)malloc(sizeof(BSR_VOLUME));
253 memset(volume, 0, sizeof(BSR_VOLUME));
254 bstrncpy(volume->VolumeName, p, sizeof(volume->VolumeName));
255 /* Add it to the end of the volume chain */
257 bsr->volume = volume;
259 BSR_VOLUME *bc = bsr->volume;
260 for ( ;bc->next; bc=bc->next)
269 /* Shove the MediaType in each Volume in the current bsr */
270 static BSR *store_mediatype(LEX *lc, BSR *bsr)
274 token = lex_get_token(lc, T_STRING);
275 if (token == T_ERROR) {
279 Emsg1(M_ERROR,0, _("MediaType %s in bsr at inappropriate place.\n"),
284 for (bv=bsr->volume; bv; bv=bv->next) {
285 bstrncpy(bv->MediaType, lc->str, sizeof(bv->MediaType));
290 static BSR *store_nothing(LEX *lc, BSR *bsr)
294 token = lex_get_token(lc, T_STRING);
295 if (token == T_ERROR) {
301 /* Shove the Device name in each Volume in the current bsr */
302 static BSR *store_device(LEX *lc, BSR *bsr)
306 token = lex_get_token(lc, T_STRING);
307 if (token == T_ERROR) {
311 Emsg1(M_ERROR,0, _("Device \"%s\" in bsr at inappropriate place.\n"),
316 for (bv=bsr->volume; bv; bv=bv->next) {
317 bstrncpy(bv->device, lc->str, sizeof(bv->device));
324 static BSR *store_client(LEX *lc, BSR *bsr)
330 token = lex_get_token(lc, T_NAME);
331 if (token == T_ERROR) {
334 client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
335 memset(client, 0, sizeof(BSR_CLIENT));
336 bstrncpy(client->ClientName, lc->str, sizeof(client->ClientName));
337 /* Add it to the end of the client chain */
339 bsr->client = client;
341 BSR_CLIENT *bc = bsr->client;
342 for ( ;bc->next; bc=bc->next)
346 token = lex_get_token(lc, T_ALL);
347 if (token != T_COMMA) {
354 static BSR *store_job(LEX *lc, BSR *bsr)
360 token = lex_get_token(lc, T_NAME);
361 if (token == T_ERROR) {
364 job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
365 memset(job, 0, sizeof(BSR_JOB));
366 bstrncpy(job->Job, lc->str, sizeof(job->Job));
367 /* Add it to the end of the client chain */
371 /* Add to end of chain */
372 BSR_JOB *bc = bsr->job;
373 for ( ;bc->next; bc=bc->next)
377 token = lex_get_token(lc, T_ALL);
378 if (token != T_COMMA) {
385 static BSR *store_findex(LEX *lc, BSR *bsr)
391 token = lex_get_token(lc, T_PINT32_RANGE);
392 if (token == T_ERROR) {
395 findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
396 memset(findex, 0, sizeof(BSR_FINDEX));
397 findex->findex = lc->pint32_val;
398 findex->findex2 = lc->pint32_val2;
399 /* Add it to the end of the chain */
400 if (!bsr->FileIndex) {
401 bsr->FileIndex = findex;
403 /* Add to end of chain */
404 BSR_FINDEX *bs = bsr->FileIndex;
405 for ( ;bs->next; bs=bs->next)
409 token = lex_get_token(lc, T_ALL);
410 if (token != T_COMMA) {
418 static BSR *store_jobid(LEX *lc, BSR *bsr)
424 token = lex_get_token(lc, T_PINT32_RANGE);
425 if (token == T_ERROR) {
428 jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
429 memset(jobid, 0, sizeof(BSR_JOBID));
430 jobid->JobId = lc->pint32_val;
431 jobid->JobId2 = lc->pint32_val2;
432 /* Add it to the end of the chain */
436 /* Add to end of chain */
437 BSR_JOBID *bs = bsr->JobId;
438 for ( ;bs->next; bs=bs->next)
442 token = lex_get_token(lc, T_ALL);
443 if (token != T_COMMA) {
451 static BSR *store_count(LEX *lc, BSR *bsr)
455 token = lex_get_token(lc, T_PINT32);
456 if (token == T_ERROR) {
459 bsr->count = lc->pint32_val;
464 static BSR *store_fileregex(LEX *lc, BSR *bsr)
469 token = lex_get_token(lc, T_STRING);
470 if (token == T_ERROR) {
474 if (bsr->fileregex) free(bsr->fileregex);
475 bsr->fileregex = bstrdup(lc->str);
477 if (bsr->fileregex_re == NULL)
478 bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));
480 rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
483 regerror(rc, bsr->fileregex_re, prbuf, sizeof(prbuf));
484 Emsg2(M_ERROR, 0, _("REGEX '%s' compile error. ERR=%s\n"),
485 bsr->fileregex, prbuf);
491 static BSR *store_jobtype(LEX *lc, BSR *bsr)
493 /* *****FIXME****** */
494 Pmsg0(-1, _("JobType not yet implemented\n"));
499 static BSR *store_joblevel(LEX *lc, BSR *bsr)
501 /* *****FIXME****** */
502 Pmsg0(-1, _("JobLevel not yet implemented\n"));
510 * Routine to handle Volume start/end file
512 static BSR *store_volfile(LEX *lc, BSR *bsr)
515 BSR_VOLFILE *volfile;
518 token = lex_get_token(lc, T_PINT32_RANGE);
519 if (token == T_ERROR) {
522 volfile = (BSR_VOLFILE *)malloc(sizeof(BSR_VOLFILE));
523 memset(volfile, 0, sizeof(BSR_VOLFILE));
524 volfile->sfile = lc->pint32_val;
525 volfile->efile = lc->pint32_val2;
526 /* Add it to the end of the chain */
528 bsr->volfile = volfile;
530 /* Add to end of chain */
531 BSR_VOLFILE *bs = bsr->volfile;
532 for ( ;bs->next; bs=bs->next)
536 token = lex_get_token(lc, T_ALL);
537 if (token != T_COMMA) {
546 * Routine to handle Volume start/end Block
548 static BSR *store_volblock(LEX *lc, BSR *bsr)
551 BSR_VOLBLOCK *volblock;
554 token = lex_get_token(lc, T_PINT32_RANGE);
555 if (token == T_ERROR) {
558 volblock = (BSR_VOLBLOCK *)malloc(sizeof(BSR_VOLBLOCK));
559 memset(volblock, 0, sizeof(BSR_VOLBLOCK));
560 volblock->sblock = lc->pint32_val;
561 volblock->eblock = lc->pint32_val2;
562 /* Add it to the end of the chain */
563 if (!bsr->volblock) {
564 bsr->volblock = volblock;
566 /* Add to end of chain */
567 BSR_VOLBLOCK *bs = bsr->volblock;
568 for ( ;bs->next; bs=bs->next)
572 token = lex_get_token(lc, T_ALL);
573 if (token != T_COMMA) {
581 * Routine to handle Volume start/end address
583 static BSR *store_voladdr(LEX *lc, BSR *bsr)
586 BSR_VOLADDR *voladdr;
589 token = lex_get_token(lc, T_PINT64_RANGE);
590 if (token == T_ERROR) {
593 voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR));
594 memset(voladdr, 0, sizeof(BSR_VOLADDR));
595 voladdr->saddr = lc->pint64_val;
596 voladdr->eaddr = lc->pint64_val2;
597 /* Add it to the end of the chain */
599 bsr->voladdr = voladdr;
601 /* Add to end of chain */
602 BSR_VOLADDR *bs = bsr->voladdr;
603 for ( ;bs->next; bs=bs->next)
607 token = lex_get_token(lc, T_ALL);
608 if (token != T_COMMA) {
615 static BSR *store_sessid(LEX *lc, BSR *bsr)
621 token = lex_get_token(lc, T_PINT32_RANGE);
622 if (token == T_ERROR) {
625 sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
626 memset(sid, 0, sizeof(BSR_SESSID));
627 sid->sessid = lc->pint32_val;
628 sid->sessid2 = lc->pint32_val2;
629 /* Add it to the end of the chain */
633 /* Add to end of chain */
634 BSR_SESSID *bs = bsr->sessid;
635 for ( ;bs->next; bs=bs->next)
639 token = lex_get_token(lc, T_ALL);
640 if (token != T_COMMA) {
647 static BSR *store_sesstime(LEX *lc, BSR *bsr)
653 token = lex_get_token(lc, T_PINT32);
654 if (token == T_ERROR) {
657 stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
658 memset(stime, 0, sizeof(BSR_SESSTIME));
659 stime->sesstime = lc->pint32_val;
660 /* Add it to the end of the chain */
661 if (!bsr->sesstime) {
662 bsr->sesstime = stime;
664 /* Add to end of chain */
665 BSR_SESSTIME *bs = bsr->sesstime;
666 for ( ;bs->next; bs=bs->next)
670 token = lex_get_token(lc, T_ALL);
671 if (token != T_COMMA) {
679 static BSR *store_stream(LEX *lc, BSR *bsr)
685 token = lex_get_token(lc, T_INT32);
686 if (token == T_ERROR) {
689 stream = (BSR_STREAM *)malloc(sizeof(BSR_STREAM));
690 memset(stream, 0, sizeof(BSR_STREAM));
691 stream->stream = lc->int32_val;
692 /* Add it to the end of the chain */
694 bsr->stream = stream;
696 /* Add to end of chain */
697 BSR_STREAM *bs = bsr->stream;
698 for ( ;bs->next; bs=bs->next)
702 token = lex_get_token(lc, T_ALL);
703 if (token != T_COMMA) {
710 static BSR *store_slot(LEX *lc, BSR *bsr)
714 token = lex_get_token(lc, T_PINT32);
715 if (token == T_ERROR) {
719 Emsg1(M_ERROR,0, _("Slot %d in bsr at inappropriate place.\n"),
723 bsr->volume->Slot = lc->pint32_val;
728 static BSR *store_include(LEX *lc, BSR *bsr)
734 static BSR *store_exclude(LEX *lc, BSR *bsr)
740 void dump_volfile(BSR_VOLFILE *volfile)
743 Pmsg2(-1, _("VolFile : %u-%u\n"), volfile->sfile, volfile->efile);
744 dump_volfile(volfile->next);
748 void dump_volblock(BSR_VOLBLOCK *volblock)
751 Pmsg2(-1, _("VolBlock : %u-%u\n"), volblock->sblock, volblock->eblock);
752 dump_volblock(volblock->next);
756 void dump_voladdr(BSR_VOLADDR *voladdr)
759 Pmsg2(-1, _("VolAddr : %llu-%llu\n"), voladdr->saddr, voladdr->eaddr);
760 dump_voladdr(voladdr->next);
764 void dump_findex(BSR_FINDEX *FileIndex)
767 if (FileIndex->findex == FileIndex->findex2) {
768 Pmsg1(-1, _("FileIndex : %u\n"), FileIndex->findex);
770 Pmsg2(-1, _("FileIndex : %u-%u\n"), FileIndex->findex, FileIndex->findex2);
772 dump_findex(FileIndex->next);
776 void dump_jobid(BSR_JOBID *jobid)
779 if (jobid->JobId == jobid->JobId2) {
780 Pmsg1(-1, _("JobId : %u\n"), jobid->JobId);
782 Pmsg2(-1, _("JobId : %u-%u\n"), jobid->JobId, jobid->JobId2);
784 dump_jobid(jobid->next);
788 void dump_sessid(BSR_SESSID *sessid)
791 if (sessid->sessid == sessid->sessid2) {
792 Pmsg1(-1, _("SessId : %u\n"), sessid->sessid);
794 Pmsg2(-1, _("SessId : %u-%u\n"), sessid->sessid, sessid->sessid2);
796 dump_sessid(sessid->next);
800 void dump_volume(BSR_VOLUME *volume)
803 Pmsg1(-1, _("VolumeName : %s\n"), volume->VolumeName);
804 Pmsg1(-1, _(" MediaType : %s\n"), volume->MediaType);
805 Pmsg1(-1, _(" Device : %s\n"), volume->device);
806 Pmsg1(-1, _(" Slot : %d\n"), volume->Slot);
807 dump_volume(volume->next);
812 void dump_client(BSR_CLIENT *client)
815 Pmsg1(-1, _("Client : %s\n"), client->ClientName);
816 dump_client(client->next);
820 void dump_job(BSR_JOB *job)
823 Pmsg1(-1, _("Job : %s\n"), job->Job);
828 void dump_sesstime(BSR_SESSTIME *sesstime)
831 Pmsg1(-1, _("SessTime : %u\n"), sesstime->sesstime);
832 dump_sesstime(sesstime->next);
837 void dump_bsr(BSR *bsr, bool recurse)
839 int save_debug = debug_level;
842 Pmsg0(-1, _("BSR is NULL\n"));
843 debug_level = save_debug;
846 Pmsg1(-1, _("Next : 0x%x\n"), bsr->next);
847 Pmsg1(-1, _("Root bsr : 0x%x\n"), bsr->root);
848 dump_volume(bsr->volume);
849 dump_sessid(bsr->sessid);
850 dump_sesstime(bsr->sesstime);
851 dump_volfile(bsr->volfile);
852 dump_volblock(bsr->volblock);
853 dump_voladdr(bsr->voladdr);
854 dump_client(bsr->client);
855 dump_jobid(bsr->JobId);
857 dump_findex(bsr->FileIndex);
859 Pmsg1(-1, _("count : %u\n"), bsr->count);
860 Pmsg1(-1, _("found : %u\n"), bsr->found);
863 Pmsg1(-1, _("done : %s\n"), bsr->done?_("yes"):_("no"));
864 Pmsg1(-1, _("positioning : %d\n"), bsr->use_positioning);
865 Pmsg1(-1, _("fast_reject : %d\n"), bsr->use_fast_rejection);
866 if (recurse && bsr->next) {
868 dump_bsr(bsr->next, true);
870 debug_level = save_debug;
875 /*********************************************************************
880 static void free_bsr_item(BSR *bsr)
883 free_bsr_item(bsr->next);
889 * Remove a single item from the bsr tree
891 void remove_bsr(BSR *bsr)
893 free_bsr_item((BSR *)bsr->volume);
894 free_bsr_item((BSR *)bsr->client);
895 free_bsr_item((BSR *)bsr->sessid);
896 free_bsr_item((BSR *)bsr->sesstime);
897 free_bsr_item((BSR *)bsr->volfile);
898 free_bsr_item((BSR *)bsr->volblock);
899 free_bsr_item((BSR *)bsr->voladdr);
900 free_bsr_item((BSR *)bsr->JobId);
901 free_bsr_item((BSR *)bsr->job);
902 free_bsr_item((BSR *)bsr->FileIndex);
903 free_bsr_item((BSR *)bsr->JobType);
904 free_bsr_item((BSR *)bsr->JobLevel);
905 if (bsr->fileregex) {
906 bfree(bsr->fileregex);
908 if (bsr->fileregex_re) {
909 regfree(bsr->fileregex_re);
910 free(bsr->fileregex_re);
913 free_attr(bsr->attr);
916 bsr->next->prev = bsr->prev;
919 bsr->prev->next = bsr->next;
925 * Free all bsrs in chain
927 void free_bsr(BSR *bsr)
934 next_bsr = bsr->next;
935 /* Remove (free) current bsr */
937 /* Now get the next one */
941 /*****************************************************************
942 * Routines for handling volumes
944 static VOL_LIST *new_restore_volume()
947 vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
948 memset(vol, 0, sizeof(VOL_LIST));
953 * Add current volume to end of list, only if the Volume
954 * is not already in the list.
956 * returns: 1 if volume added
957 * 0 if volume already in list
959 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol)
961 VOL_LIST *next = jcr->VolList;
963 /* Add volume to volume manager's read list */
964 add_read_volume(jcr, vol->VolumeName);
966 if (!next) { /* list empty ? */
967 jcr->VolList = vol; /* yes, add volume */
969 /* Loop through all but last */
970 for ( ; next->next; next=next->next) {
971 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
972 /* Save smallest start file */
973 if (vol->start_file < next->start_file) {
974 next->start_file = vol->start_file;
976 return false; /* already in list */
979 /* Check last volume in list */
980 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
981 if (vol->start_file < next->start_file) {
982 next->start_file = vol->start_file;
984 return false; /* already in list */
986 next->next = vol; /* add volume */
991 void free_restore_volume_list(JCR *jcr)
993 VOL_LIST *vol = jcr->VolList;
998 remove_read_volume(jcr, vol->VolumeName);
1002 jcr->VolList = NULL;
1006 * Create a list of Volumes (and Slots and Start positions) to be
1007 * used in the current restore job.
1009 void create_restore_volume_list(JCR *jcr)
1015 * Build a list of volumes to be processed
1017 jcr->NumReadVolumes = 0;
1018 jcr->CurReadVolume = 0;
1020 BSR *bsr = jcr->bsr;
1021 if (!bsr->volume || !bsr->volume->VolumeName) {
1024 for ( ; bsr; bsr=bsr->next) {
1026 BSR_VOLFILE *volfile;
1027 uint32_t sfile = UINT32_MAX;
1029 /* Find minimum start file so that we can forward space to it */
1030 for (volfile = bsr->volfile; volfile; volfile=volfile->next) {
1031 if (volfile->sfile < sfile) {
1032 sfile = volfile->sfile;
1035 /* Now add volumes for this bsr */
1036 for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) {
1037 vol = new_restore_volume();
1038 bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
1039 bstrncpy(vol->MediaType, bsrvol->MediaType, sizeof(vol->MediaType));
1040 bstrncpy(vol->device, bsrvol->device, sizeof(vol->device));
1041 vol->Slot = bsrvol->Slot;
1042 vol->start_file = sfile;
1043 if (add_restore_volume(jcr, vol)) {
1044 jcr->NumReadVolumes++;
1045 Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName,
1048 Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
1051 sfile = 0; /* start at beginning of second volume */
1055 /* This is the old way -- deprecated */
1056 for (p = jcr->dcr->VolumeName; p && *p; ) {
1057 n = strchr(p, '|'); /* volume name separator */
1059 *n++ = 0; /* Terminate name */
1061 vol = new_restore_volume();
1062 bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
1063 bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType));
1064 if (add_restore_volume(jcr, vol)) {
1065 jcr->NumReadVolumes++;