+ switch (check_volume_label(ask, autochanger)) {
+ case check_next_vol:
+ Dmsg0(50, "set_unload\n");
+ dev->set_unload(); /* want a different Volume */
+ Dmsg0(150, "goto mount_next_vol\n");
+ goto mount_next_vol;
+ case check_read_vol:
+ goto read_volume;
+ case check_error:
+ goto bail_out;
+ case check_ok:
+ break;
+ }
+
+ /*
+ * See if we have a fresh tape or a tape with data.
+ *
+ * Note, if the LabelType is PRE_LABEL, it was labeled
+ * but never written. If so, rewrite the label but set as
+ * VOL_LABEL. We rewind and return the label (reconstructed)
+ * in the block so that in the case of a new tape, data can
+ * be appended just after the block label. If we are writing
+ * a second volume, the calling routine will write the label
+ * before writing the overflow block.
+ *
+ * If the tape is marked as Recycle, we rewrite the label.
+ */
+ recycle = strcmp(dev->VolCatInfo.VolCatStatus, "Recycle") == 0;
+ if (dev->VolHdr.LabelType == PRE_LABEL || recycle) {
+ if (!rewrite_volume_label(dcr, recycle)) {
+ mark_volume_in_error();
+ goto mount_next_vol;
+ }
+ } else {
+ /*
+ * OK, at this point, we have a valid Bacula label, but
+ * we need to position to the end of the volume, since we are
+ * just now putting it into append mode.
+ */
+ Dmsg0(200, "Device previously written, moving to end of data\n");
+ Jmsg(jcr, M_INFO, 0, _("Volume \"%s\" previously written, moving to end of data.\n"),
+ VolumeName);
+
+ if (!dev->eod(dcr)) {
+ Jmsg(jcr, M_ERROR, 0, _("Unable to position to end of data on device %s: ERR=%s\n"),
+ dev->print_name(), dev->bstrerror());
+ mark_volume_in_error();
+ goto mount_next_vol;
+ }
+ if (!is_eod_valid()) {
+ Dmsg0(150, "goto mount_next_vol\n");
+ goto mount_next_vol;
+ }
+
+ dev->VolCatInfo.VolCatMounts++; /* Update mounts */
+ Dmsg1(150, "update volinfo mounts=%d\n", dev->VolCatInfo.VolCatMounts);
+ if (!dir_update_volume_info(dcr, false, false)) {
+ goto bail_out;
+ }
+
+ /* Return an empty block */
+ empty_block(block); /* we used it for reading so set for write */
+ }
+ dev->set_append();
+ Dmsg1(150, "set APPEND, normal return from mount_next_write_volume. dev=%s\n",
+ dev->print_name());
+
+ unlock_volumes();
+ return true;
+
+bail_out:
+ unlock_volumes();
+
+no_lock_bail_out:
+ return false;
+}
+
+/*
+ * This routine is meant to be called once the first pass
+ * to ensure that we have a candidate volume to mount.
+ * Otherwise, we ask the sysop to created one.
+ */
+bool DCR::find_a_volume()
+{
+ DCR *dcr = this;
+ if (!is_suitable_volume_mounted()) {
+ bool have_vol = false;
+ /* Do we have a candidate volume? */
+ if (dev->vol) {
+ bstrncpy(VolumeName, dev->vol->vol_name, sizeof(VolumeName));
+ have_vol = dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE);
+ }
+ /*
+ * Get Director's idea of what tape we should have mounted.
+ * in dcr->VolCatInfo
+ */
+ if (!have_vol) {
+ Dmsg0(200, "Before dir_find_next_appendable_volume.\n");
+ while (!dir_find_next_appendable_volume(dcr)) {
+ Dmsg0(200, "not dir_find_next\n");
+ if (job_canceled(jcr)) {
+ unlock_volumes();
+ return false;
+ }
+ unlock_volumes();
+ if (!dir_ask_sysop_to_create_appendable_volume(dcr)) {
+ return false;
+ }
+ lock_volumes();
+ Dmsg0(150, "Again dir_find_next_append...\n");
+ }
+ }
+ }
+ return true;
+}
+
+int DCR::check_volume_label(bool &ask, bool &autochanger)
+{
+ int vol_label_status;