+
+/*****************************************************************
+ * Routines for handling volumes
+ */
+VOL_LIST *new_vol()
+{
+ VOL_LIST *vol;
+ vol = (VOL_LIST *)malloc(sizeof(VOL_LIST));
+ memset(vol, 0, sizeof(VOL_LIST));
+ return vol;
+}
+
+/*
+ * Add current volume to end of list, only if the Volume
+ * is not already in the list.
+ *
+ * returns: 1 if volume added
+ * 0 if volume already in list
+ */
+int add_vol(JCR *jcr, VOL_LIST *vol)
+{
+ VOL_LIST *next = jcr->VolList;
+
+ if (!next) { /* list empty ? */
+ jcr->VolList = vol; /* yes, add volume */
+ } else {
+ for ( ; next->next; next=next->next) {
+ if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
+ if (vol->start_file < next->start_file) {
+ next->start_file = vol->start_file;
+ }
+ return 0; /* already in list */
+ }
+ }
+ if (strcmp(vol->VolumeName, next->VolumeName) == 0) {
+ if (vol->start_file < next->start_file) {
+ next->start_file = vol->start_file;
+ }
+ return 0; /* already in list */
+ }
+ next->next = vol; /* add volume */
+ }
+ return 1;
+}
+
+void free_vol_list(JCR *jcr)
+{
+ VOL_LIST *next = jcr->VolList;
+ VOL_LIST *tmp;
+
+ for ( ; next; ) {
+ tmp = next->next;
+ free(next);
+ next = tmp;
+ }
+ jcr->VolList = NULL;
+}
+
+/*
+ * Create a list of Volumes (and Slots and Start positions) to be
+ * used in the current restore job.
+ */
+void create_vol_list(JCR *jcr)
+{
+ char *p, *n;
+ VOL_LIST *vol;
+
+ /*
+ * Build a list of volumes to be processed
+ */
+ jcr->NumVolumes = 0;
+ jcr->CurVolume = 0;
+ if (jcr->bsr) {
+ BSR *bsr = jcr->bsr;
+ if (!bsr->volume || !bsr->volume->VolumeName) {
+ return;
+ }
+ for ( ; bsr; bsr=bsr->next) {
+ BSR_VOLUME *bsrvol;
+ BSR_VOLFILE *volfile;
+ uint32_t sfile = UINT32_MAX;
+
+ /* Find minimum start file so that we can forward space to it */
+ for (volfile = bsr->volfile; volfile; volfile=volfile->next) {
+ if (volfile->sfile < sfile) {
+ sfile = volfile->sfile;
+ }
+ }
+ /* Now add volumes for this bsr */
+ for (bsrvol = bsr->volume; bsrvol; bsrvol=bsrvol->next) {
+ vol = new_vol();
+ bstrncpy(vol->VolumeName, bsrvol->VolumeName, sizeof(vol->VolumeName));
+ bstrncpy(vol->MediaType, bsrvol->MediaType, sizeof(vol->MediaType));
+ vol->start_file = sfile;
+ if (add_vol(jcr, vol)) {
+ jcr->NumVolumes++;
+ Dmsg2(400, "Added volume=%s mediatype=%s\n", vol->VolumeName,
+ vol->MediaType);
+ } else {
+ Dmsg1(400, "Duplicate volume %s\n", vol->VolumeName);
+ free((char *)vol);
+ }
+ sfile = 0; /* start at beginning of second volume */
+ }
+ }
+ } else {
+ /* This is the old way -- deprecated */
+ for (p = jcr->dcr->VolumeName; p && *p; ) {
+ n = strchr(p, '|'); /* volume name separator */
+ if (n) {
+ *n++ = 0; /* Terminate name */
+ }
+ vol = new_vol();
+ bstrncpy(vol->VolumeName, p, sizeof(vol->VolumeName));
+ bstrncpy(vol->MediaType, jcr->dcr->media_type, sizeof(vol->MediaType));
+ if (add_vol(jcr, vol)) {
+ jcr->NumVolumes++;
+ } else {
+ free((char *)vol);
+ }
+ p = n;
+ }
+ }
+}