2 Bacula® - The Network Backup Solution
4 Copyright (C) 2002-2008 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 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},
100 static BSR *new_bsr()
102 BSR *bsr = (BSR *)malloc(sizeof(BSR));
103 memset(bsr, 0, sizeof(BSR));
108 * Format a scanner error message
110 static void s_err(const char *file, int line, LEX *lc, const char *msg, ...)
112 JCR *jcr = (JCR *)(lc->caller_ctx);
116 va_start(arg_ptr, msg);
117 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
121 Jmsg(jcr, M_FATAL, 0, _("Bootstrap file error: %s\n"
122 " : Line %d, col %d of file %s\n%s\n"),
123 buf, lc->line_no, lc->col_no, lc->fname, lc->line);
125 e_msg(file, line, M_FATAL, 0, _("Bootstrap file error: %s\n"
126 " : Line %d, col %d of file %s\n%s\n"),
127 buf, lc->line_no, lc->col_no, lc->fname, lc->line);
132 /*********************************************************************
134 * Parse Bootstrap file
137 BSR *parse_bsr(JCR *jcr, char *fname)
141 BSR *root_bsr = new_bsr();
144 Dmsg1(300, "Enter parse_bsf %s\n", fname);
145 if ((lc = lex_open_file(lc, fname, s_err)) == NULL) {
147 Emsg2(M_ERROR_TERM, 0, _("Cannot open bootstrap file %s: %s\n"),
148 fname, be.bstrerror());
150 lc->caller_ctx = (void *)jcr;
151 while ((token=lex_get_token(lc, T_ALL)) != T_EOF) {
152 Dmsg1(300, "parse got token=%s\n", lex_tok_to_str(token));
153 if (token == T_EOL) {
156 for (i=0; items[i].name; i++) {
157 if (strcasecmp(items[i].name, lc->str) == 0) {
158 token = lex_get_token(lc, T_ALL);
159 Dmsg1 (300, "in T_IDENT got token=%s\n", lex_tok_to_str(token));
160 if (token != T_EQUALS) {
161 scan_err1(lc, "expected an equals, got: %s", lc->str);
165 Dmsg1(300, "calling handler for %s\n", items[i].name);
166 /* Call item handler */
167 bsr = items[i].handler(lc, bsr);
173 Dmsg1(300, "Keyword = %s\n", lc->str);
174 scan_err1(lc, "Keyword %s not found", lc->str);
182 lc = lex_close_file(lc);
183 Dmsg0(300, "Leave parse_bsf()\n");
189 root_bsr->use_fast_rejection = is_fast_rejection_ok(root_bsr);
190 root_bsr->use_positioning = is_positioning_ok(root_bsr);
192 for (bsr=root_bsr; bsr; bsr=bsr->next) {
193 bsr->root = root_bsr;
198 static bool is_fast_rejection_ok(BSR *bsr)
201 * Although, this can be optimized, for the moment, require
202 * all bsrs to have both sesstime and sessid set before
203 * we do fast rejection.
205 for ( ; bsr; bsr=bsr->next) {
206 if (!(bsr->sesstime && bsr->sessid)) {
213 static bool is_positioning_ok(BSR *bsr)
216 * Every bsr should have a volfile entry and a volblock entry
218 * if we are going to use positioning
220 for ( ; bsr; bsr=bsr->next) {
221 if (!((bsr->volfile && bsr->volblock) || bsr->voladdr)) {
228 static BSR *store_vol(LEX *lc, BSR *bsr)
234 token = lex_get_token(lc, T_STRING);
235 if (token == T_ERROR) {
239 bsr->next = new_bsr();
240 bsr->next->prev = bsr;
243 /* This may actually be more than one volume separated by a |
244 * If so, separate them.
246 for (p=lc->str; p && *p; ) {
251 volume = (BSR_VOLUME *)malloc(sizeof(BSR_VOLUME));
252 memset(volume, 0, sizeof(BSR_VOLUME));
253 bstrncpy(volume->VolumeName, p, sizeof(volume->VolumeName));
254 /* Add it to the end of the volume chain */
256 bsr->volume = volume;
258 BSR_VOLUME *bc = bsr->volume;
259 for ( ;bc->next; bc=bc->next)
268 /* Shove the MediaType in each Volume in the current bsr */
269 static BSR *store_mediatype(LEX *lc, BSR *bsr)
273 token = lex_get_token(lc, T_STRING);
274 if (token == T_ERROR) {
278 Emsg1(M_ERROR,0, _("MediaType %s in bsr at inappropriate place.\n"),
283 for (bv=bsr->volume; bv; bv=bv->next) {
284 bstrncpy(bv->MediaType, lc->str, sizeof(bv->MediaType));
289 /* Shove the Device name in each Volume in the current bsr */
290 static BSR *store_device(LEX *lc, BSR *bsr)
294 token = lex_get_token(lc, T_STRING);
295 if (token == T_ERROR) {
299 Emsg1(M_ERROR,0, _("Device \"%s\" in bsr at inappropriate place.\n"),
304 for (bv=bsr->volume; bv; bv=bv->next) {
305 bstrncpy(bv->device, lc->str, sizeof(bv->device));
312 static BSR *store_client(LEX *lc, BSR *bsr)
318 token = lex_get_token(lc, T_NAME);
319 if (token == T_ERROR) {
322 client = (BSR_CLIENT *)malloc(sizeof(BSR_CLIENT));
323 memset(client, 0, sizeof(BSR_CLIENT));
324 bstrncpy(client->ClientName, lc->str, sizeof(client->ClientName));
325 /* Add it to the end of the client chain */
327 bsr->client = client;
329 BSR_CLIENT *bc = bsr->client;
330 for ( ;bc->next; bc=bc->next)
334 token = lex_get_token(lc, T_ALL);
335 if (token != T_COMMA) {
342 static BSR *store_job(LEX *lc, BSR *bsr)
348 token = lex_get_token(lc, T_NAME);
349 if (token == T_ERROR) {
352 job = (BSR_JOB *)malloc(sizeof(BSR_JOB));
353 memset(job, 0, sizeof(BSR_JOB));
354 bstrncpy(job->Job, lc->str, sizeof(job->Job));
355 /* Add it to the end of the client chain */
359 /* Add to end of chain */
360 BSR_JOB *bc = bsr->job;
361 for ( ;bc->next; bc=bc->next)
365 token = lex_get_token(lc, T_ALL);
366 if (token != T_COMMA) {
373 static BSR *store_findex(LEX *lc, BSR *bsr)
379 token = lex_get_token(lc, T_PINT32_RANGE);
380 if (token == T_ERROR) {
383 findex = (BSR_FINDEX *)malloc(sizeof(BSR_FINDEX));
384 memset(findex, 0, sizeof(BSR_FINDEX));
385 findex->findex = lc->pint32_val;
386 findex->findex2 = lc->pint32_val2;
387 /* Add it to the end of the chain */
388 if (!bsr->FileIndex) {
389 bsr->FileIndex = findex;
391 /* Add to end of chain */
392 BSR_FINDEX *bs = bsr->FileIndex;
393 for ( ;bs->next; bs=bs->next)
397 token = lex_get_token(lc, T_ALL);
398 if (token != T_COMMA) {
406 static BSR *store_jobid(LEX *lc, BSR *bsr)
412 token = lex_get_token(lc, T_PINT32_RANGE);
413 if (token == T_ERROR) {
416 jobid = (BSR_JOBID *)malloc(sizeof(BSR_JOBID));
417 memset(jobid, 0, sizeof(BSR_JOBID));
418 jobid->JobId = lc->pint32_val;
419 jobid->JobId2 = lc->pint32_val2;
420 /* Add it to the end of the chain */
424 /* Add to end of chain */
425 BSR_JOBID *bs = bsr->JobId;
426 for ( ;bs->next; bs=bs->next)
430 token = lex_get_token(lc, T_ALL);
431 if (token != T_COMMA) {
439 static BSR *store_count(LEX *lc, BSR *bsr)
443 token = lex_get_token(lc, T_PINT32);
444 if (token == T_ERROR) {
447 bsr->count = lc->pint32_val;
452 static BSR *store_fileregex(LEX *lc, BSR *bsr)
457 token = lex_get_token(lc, T_STRING);
458 if (token == T_ERROR) {
462 if (bsr->fileregex) free(bsr->fileregex);
463 bsr->fileregex = bstrdup(lc->str);
465 if (bsr->fileregex_re == NULL)
466 bsr->fileregex_re = (regex_t *)bmalloc(sizeof(regex_t));
468 rc = regcomp(bsr->fileregex_re, bsr->fileregex, REG_EXTENDED|REG_NOSUB);
471 regerror(rc, bsr->fileregex_re, prbuf, sizeof(prbuf));
472 Emsg2(M_ERROR, 0, _("REGEX '%s' compile error. ERR=%s\n"),
473 bsr->fileregex, prbuf);
479 static BSR *store_jobtype(LEX *lc, BSR *bsr)
481 /* *****FIXME****** */
482 Pmsg0(-1, _("JobType not yet implemented\n"));
487 static BSR *store_joblevel(LEX *lc, BSR *bsr)
489 /* *****FIXME****** */
490 Pmsg0(-1, _("JobLevel not yet implemented\n"));
498 * Routine to handle Volume start/end file
500 static BSR *store_volfile(LEX *lc, BSR *bsr)
503 BSR_VOLFILE *volfile;
506 token = lex_get_token(lc, T_PINT32_RANGE);
507 if (token == T_ERROR) {
510 volfile = (BSR_VOLFILE *)malloc(sizeof(BSR_VOLFILE));
511 memset(volfile, 0, sizeof(BSR_VOLFILE));
512 volfile->sfile = lc->pint32_val;
513 volfile->efile = lc->pint32_val2;
514 /* Add it to the end of the chain */
516 bsr->volfile = volfile;
518 /* Add to end of chain */
519 BSR_VOLFILE *bs = bsr->volfile;
520 for ( ;bs->next; bs=bs->next)
524 token = lex_get_token(lc, T_ALL);
525 if (token != T_COMMA) {
534 * Routine to handle Volume start/end Block
536 static BSR *store_volblock(LEX *lc, BSR *bsr)
539 BSR_VOLBLOCK *volblock;
542 token = lex_get_token(lc, T_PINT32_RANGE);
543 if (token == T_ERROR) {
546 volblock = (BSR_VOLBLOCK *)malloc(sizeof(BSR_VOLBLOCK));
547 memset(volblock, 0, sizeof(BSR_VOLBLOCK));
548 volblock->sblock = lc->pint32_val;
549 volblock->eblock = lc->pint32_val2;
550 /* Add it to the end of the chain */
551 if (!bsr->volblock) {
552 bsr->volblock = volblock;
554 /* Add to end of chain */
555 BSR_VOLBLOCK *bs = bsr->volblock;
556 for ( ;bs->next; bs=bs->next)
560 token = lex_get_token(lc, T_ALL);
561 if (token != T_COMMA) {
569 * Routine to handle Volume start/end address
571 static BSR *store_voladdr(LEX *lc, BSR *bsr)
574 BSR_VOLADDR *voladdr;
577 token = lex_get_token(lc, T_PINT64_RANGE);
578 if (token == T_ERROR) {
581 voladdr = (BSR_VOLADDR *)malloc(sizeof(BSR_VOLADDR));
582 memset(voladdr, 0, sizeof(BSR_VOLADDR));
583 voladdr->saddr = lc->pint64_val;
584 voladdr->eaddr = lc->pint64_val2;
585 /* Add it to the end of the chain */
587 bsr->voladdr = voladdr;
589 /* Add to end of chain */
590 BSR_VOLADDR *bs = bsr->voladdr;
591 for ( ;bs->next; bs=bs->next)
595 token = lex_get_token(lc, T_ALL);
596 if (token != T_COMMA) {
603 static BSR *store_sessid(LEX *lc, BSR *bsr)
609 token = lex_get_token(lc, T_PINT32_RANGE);
610 if (token == T_ERROR) {
613 sid = (BSR_SESSID *)malloc(sizeof(BSR_SESSID));
614 memset(sid, 0, sizeof(BSR_SESSID));
615 sid->sessid = lc->pint32_val;
616 sid->sessid2 = lc->pint32_val2;
617 /* Add it to the end of the chain */
621 /* Add to end of chain */
622 BSR_SESSID *bs = bsr->sessid;
623 for ( ;bs->next; bs=bs->next)
627 token = lex_get_token(lc, T_ALL);
628 if (token != T_COMMA) {
635 static BSR *store_sesstime(LEX *lc, BSR *bsr)
641 token = lex_get_token(lc, T_PINT32);
642 if (token == T_ERROR) {
645 stime = (BSR_SESSTIME *)malloc(sizeof(BSR_SESSTIME));
646 memset(stime, 0, sizeof(BSR_SESSTIME));
647 stime->sesstime = lc->pint32_val;
648 /* Add it to the end of the chain */
649 if (!bsr->sesstime) {
650 bsr->sesstime = stime;
652 /* Add to end of chain */
653 BSR_SESSTIME *bs = bsr->sesstime;
654 for ( ;bs->next; bs=bs->next)
658 token = lex_get_token(lc, T_ALL);
659 if (token != T_COMMA) {
667 static BSR *store_stream(LEX *lc, BSR *bsr)
673 token = lex_get_token(lc, T_INT32);
674 if (token == T_ERROR) {
677 stream = (BSR_STREAM *)malloc(sizeof(BSR_STREAM));
678 memset(stream, 0, sizeof(BSR_STREAM));
679 stream->stream = lc->int32_val;
680 /* Add it to the end of the chain */
682 bsr->stream = stream;
684 /* Add to end of chain */
685 BSR_STREAM *bs = bsr->stream;
686 for ( ;bs->next; bs=bs->next)
690 token = lex_get_token(lc, T_ALL);
691 if (token != T_COMMA) {
698 static BSR *store_slot(LEX *lc, BSR *bsr)
702 token = lex_get_token(lc, T_PINT32);
703 if (token == T_ERROR) {
707 Emsg1(M_ERROR,0, _("Slot %d in bsr at inappropriate place.\n"),
711 bsr->volume->Slot = lc->pint32_val;
716 static BSR *store_include(LEX *lc, BSR *bsr)
722 static BSR *store_exclude(LEX *lc, BSR *bsr)
728 void dump_volfile(BSR_VOLFILE *volfile)
731 Pmsg2(-1, _("VolFile : %u-%u\n"), volfile->sfile, volfile->efile);
732 dump_volfile(volfile->next);
736 void dump_volblock(BSR_VOLBLOCK *volblock)
739 Pmsg2(-1, _("VolBlock : %u-%u\n"), volblock->sblock, volblock->eblock);
740 dump_volblock(volblock->next);
744 void dump_voladdr(BSR_VOLADDR *voladdr)
747 Pmsg2(-1, _("VolAddr : %llu-%llu\n"), voladdr->saddr, voladdr->eaddr);
748 dump_voladdr(voladdr->next);
752 void dump_findex(BSR_FINDEX *FileIndex)
755 if (FileIndex->findex == FileIndex->findex2) {
756 Pmsg1(-1, _("FileIndex : %u\n"), FileIndex->findex);
758 Pmsg2(-1, _("FileIndex : %u-%u\n"), FileIndex->findex, FileIndex->findex2);
760 dump_findex(FileIndex->next);
764 void dump_jobid(BSR_JOBID *jobid)
767 if (jobid->JobId == jobid->JobId2) {
768 Pmsg1(-1, _("JobId : %u\n"), jobid->JobId);
770 Pmsg2(-1, _("JobId : %u-%u\n"), jobid->JobId, jobid->JobId2);
772 dump_jobid(jobid->next);
776 void dump_sessid(BSR_SESSID *sessid)
779 if (sessid->sessid == sessid->sessid2) {
780 Pmsg1(-1, _("SessId : %u\n"), sessid->sessid);
782 Pmsg2(-1, _("SessId : %u-%u\n"), sessid->sessid, sessid->sessid2);
784 dump_sessid(sessid->next);
788 void dump_volume(BSR_VOLUME *volume)
791 Pmsg1(-1, _("VolumeName : %s\n"), volume->VolumeName);
792 Pmsg1(-1, _(" MediaType : %s\n"), volume->MediaType);
793 Pmsg1(-1, _(" Device : %s\n"), volume->device);
794 Pmsg1(-1, _(" Slot : %d\n"), volume->Slot);
795 dump_volume(volume->next);
800 void dump_client(BSR_CLIENT *client)
803 Pmsg1(-1, _("Client : %s\n"), client->ClientName);
804 dump_client(client->next);
808 void dump_job(BSR_JOB *job)
811 Pmsg1(-1, _("Job : %s\n"), job->Job);
816 void dump_sesstime(BSR_SESSTIME *sesstime)
819 Pmsg1(-1, _("SessTime : %u\n"), sesstime->sesstime);
820 dump_sesstime(sesstime->next);
825 void dump_bsr(BSR *bsr, bool recurse)
827 int save_debug = debug_level;
830 Pmsg0(-1, _("BSR is NULL\n"));
831 debug_level = save_debug;
834 Pmsg1(-1, _("Next : 0x%x\n"), bsr->next);
835 Pmsg1(-1, _("Root bsr : 0x%x\n"), bsr->root);
836 dump_volume(bsr->volume);
837 dump_sessid(bsr->sessid);
838 dump_sesstime(bsr->sesstime);
839 dump_volfile(bsr->volfile);
840 dump_volblock(bsr->volblock);
841 dump_voladdr(bsr->voladdr);
842 dump_client(bsr->client);
843 dump_jobid(bsr->JobId);
845 dump_findex(bsr->FileIndex);
847 Pmsg1(-1, _("count : %u\n"), bsr->count);
848 Pmsg1(-1, _("found : %u\n"), bsr->found);
851 Pmsg1(-1, _("done : %s\n"), bsr->done?_("yes"):_("no"));
852 Pmsg1(-1, _("positioning : %d\n"), bsr->use_positioning);
853 Pmsg1(-1, _("fast_reject : %d\n"), bsr->use_fast_rejection);
854 if (recurse && bsr->next) {
856 dump_bsr(bsr->next, true);
858 debug_level = save_debug;
863 /*********************************************************************
868 static void free_bsr_item(BSR *bsr)
871 free_bsr_item(bsr->next);
877 * Remove a single item from the bsr tree
879 void remove_bsr(BSR *bsr)
881 free_bsr_item((BSR *)bsr->volume);
882 free_bsr_item((BSR *)bsr->client);
883 free_bsr_item((BSR *)bsr->sessid);
884 free_bsr_item((BSR *)bsr->sesstime);
885 free_bsr_item((BSR *)bsr->volfile);
886 free_bsr_item((BSR *)bsr->volblock);
887 free_bsr_item((BSR *)bsr->voladdr);
888 free_bsr_item((BSR *)bsr->JobId);
889 free_bsr_item((BSR *)bsr->job);
890 free_bsr_item((BSR *)bsr->FileIndex);
891 free_bsr_item((BSR *)bsr->JobType);
892 free_bsr_item((BSR *)bsr->JobLevel);
893 if (bsr->fileregex) {
894 bfree(bsr->fileregex);
896 if (bsr->fileregex_re) {
897 regfree(bsr->fileregex_re);
898 free(bsr->fileregex_re);
901 free_attr(bsr->attr);
904 bsr->next->prev = bsr->prev;
907 bsr->prev->next = bsr->next;
913 * Free all bsrs in chain
915 void free_bsr(BSR *bsr)
922 next_bsr = bsr->next;
923 /* Remove (free) current bsr */
925 /* Now get the next one */
929 /*****************************************************************
930 * Routines for handling volumes
932 static VOL_LIST *new_restore_volume()
935 vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
936 memset(vol, 0, sizeof(VOL_LIST));
941 * Add current volume to end of list, only if the Volume
942 * is not already in the list.
944 * returns: 1 if volume added
945 * 0 if volume already in list
947 static bool add_restore_volume(JCR *jcr, VOL_LIST *vol)
949 VOL_LIST *next = jcr->VolList;
951 /* Add volume to volume manager's read list */
952 add_read_volume(jcr, vol->VolumeName);
954 if (!next) { /* list empty ? */
955 jcr->VolList = vol; /* yes, add volume */
957 /* Loop through all but last */
958 for ( ; next->next; next=next->next) {
959 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
960 /* Save smallest start file */
961 if (vol->start_file < next->start_file) {
962 next->start_file = vol->start_file;
964 return false; /* already in list */
967 /* Check last volume in list */
968 if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
969 if (vol->start_file < next->start_file) {
970 next->start_file = vol->start_file;
972 return false; /* already in list */
974 next->next = vol; /* add volume */
979 void free_restore_volume_list(JCR *jcr)
981 VOL_LIST *vol = jcr->VolList;
986 remove_read_volume(jcr, vol->VolumeName);
994 * Create a list of Volumes (and Slots and Start positions) to be
995 * used in the current restore job.
997 void create_restore_volume_list(JCR *jcr)
1003 * Build a list of volumes to be processed
1005 jcr->NumReadVolumes = 0;
1006 jcr->CurReadVolume = 0;
1008 BSR *bsr = jcr->bsr;
1009 if (!bsr->volume || !bsr->volume->VolumeName) {
1012 for ( ; bsr; bsr=bsr->next) {
1014 BSR_VOLFILE *volfile;
1015 uint32_t sfile = UINT32_MAX;
1017 /* Find minimum start file so that we can forward space to it */
1018 for (volfile = bsr->volfile; volfile; volfile=volfile->next) {
1019 if (volfile->sfile < sfile) {
1020 sfile = volfile->sfile;
1023 /* Now add volumes for this bsr */
1024 for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) {
1025 vol = new_restore_volume();
1026 bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
1027 bstrncpy(vol->MediaType, bsrvol->MediaType, sizeof(vol->MediaType));
1028 bstrncpy(vol->device, bsrvol->device, sizeof(vol->device));
1029 vol->Slot = bsrvol->Slot;
1030 vol->start_file = sfile;
1031 if (add_restore_volume(jcr, vol)) {
1032 jcr->NumReadVolumes++;
1033 Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName,
1036 Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
1039 sfile = 0; /* start at beginning of second volume */
1043 /* This is the old way -- deprecated */
1044 for (p = jcr->dcr->VolumeName; p && *p; ) {
1045 n = strchr(p, '|'); /* volume name separator */
1047 *n++ = 0; /* Terminate name */
1049 vol = new_restore_volume();
1050 bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
1051 bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType));
1052 if (add_restore_volume(jcr, vol)) {
1053 jcr->NumReadVolumes++;