/* List just block information */ static void do_blocks(char *infname) { DEV_BLOCK *block = dcr->block; char buf1[100], buf2[100]; for ( ;; ) { if (!dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK)) { Dmsg1(100, "!read_block(): ERR=%s\n", dev->bstrerror()); if (dev->at_eot()) { if (!mount_next_read_volume(dcr)) { Jmsg(jcr, M_INFO, 0, _("Got EOM at file %u on device %s, Volume \"%s\"\n"), dev->file, dev->print_name(), dcr->VolumeName); break; } /* Read and discard Volume label */ DEV_RECORD *record; record = new_record(); dcr->read_block_from_device(NO_BLOCK_NUMBER_CHECK); read_record_from_block(dcr, record); get_session_record(dev, record, &sessrec); free_record(record); Jmsg(jcr, M_INFO, 0, _("Mounted Volume \"%s\".\n"), dcr->VolumeName); } else if (dev->at_eof()) { Jmsg(jcr, M_INFO, 0, _("End of file %u on device %s, Volume \"%s\"\n"), dev->file, dev->print_name(), dcr->VolumeName); Dmsg0(20, "read_record got eof. try again\n"); continue; } else if (dev->is_short_block()) { Jmsg(jcr, M_INFO, 0, "%s", dev->errmsg); continue; } else { /* I/O error */ display_tape_error_status(jcr, dev); break; } } if (!match_bsr_block(bsr, block)) { Dmsg5(100, "reject Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n", block->BlockNumber, block->block_len, block->BlockVer, block->VolSessionId, block->VolSessionTime); continue; } Dmsg5(100, "Blk=%u blen=%u bVer=%d SessId=%u SessTim=%u\n", block->BlockNumber, block->block_len, block->BlockVer, block->VolSessionId, block->VolSessionTime); if (verbose == 1) { read_record_from_block(dcr, rec); Pmsg9(-1, _("File:blk=%u:%u blk_num=%u blen=%u First rec FI=%s SessId=%u SessTim=%u Strm=%s rlen=%d\n"), dev->file, dev->block_num, block->BlockNumber, block->block_len, FI_to_ascii(buf1, rec->FileIndex), rec->VolSessionId, rec->VolSessionTime, stream_to_ascii(buf2, rec->Stream, rec->FileIndex), rec->data_len); rec->remainder = 0; } else if (verbose > 1) { dump_block(block, ""); } else { printf(_("Block: %d size=%d\n"), block->BlockNumber, block->block_len); } } return; }
/* * Read the volume label * * If dcr->VolumeName == NULL, we accept any Bareos Volume * If dcr->VolumeName[0] == 0, we accept any Bareos Volume * otherwise dcr->VolumeName must match the Volume. * * If VolName given, ensure that it matches * * Returns VOL_ code as defined in record.h * VOL_NOT_READ * VOL_OK good label found * VOL_NO_LABEL volume not labeled * VOL_IO_ERROR I/O error reading tape * VOL_NAME_ERROR label has wrong name * VOL_CREATE_ERROR Error creating label * VOL_VERSION_ERROR label has wrong version * VOL_LABEL_ERROR bad label type * VOL_NO_MEDIA no media in drive * * The dcr block is emptied on return, and the Volume is * rewound. */ int read_dev_volume_label(DCR *dcr) { JCR *jcr = dcr->jcr; DEVICE * volatile dev = dcr->dev; char *VolName = dcr->VolumeName; DEV_RECORD *record; bool ok = false; DEV_BLOCK *block = dcr->block; int status; bool want_ansi_label; bool have_ansi_label = false; Dmsg4(100, "Enter read_volume_label res=%d device=%s vol=%s dev_Vol=%s\n", dev->num_reserved(), dev->print_name(), VolName, dev->VolHdr.VolumeName[0]?dev->VolHdr.VolumeName:"*NULL*"); if (!dev->is_open()) { if (!dev->open(dcr, OPEN_READ_ONLY)) { return VOL_IO_ERROR; } } dev->clear_labeled(); dev->clear_append(); dev->clear_read(); dev->label_type = B_BAREOS_LABEL; if (!dev->rewind(dcr)) { Mmsg(jcr->errmsg, _("Couldn't rewind device %s: ERR=%s\n"), dev->print_name(), dev->print_errmsg()); Dmsg1(130, "return VOL_NO_MEDIA: %s", jcr->errmsg); return VOL_NO_MEDIA; } bstrncpy(dev->VolHdr.Id, "**error**", sizeof(dev->VolHdr.Id)); /* * The stored plugin handling the bsdEventLabelRead event can abort * the reading of the label by returning a non bRC_OK. */ if (generate_plugin_event(jcr, bsdEventLabelRead, dcr) != bRC_OK) { Dmsg0(200, "Error from bsdEventLabelRead plugin event.\n"); return VOL_NO_MEDIA; } /* * Read ANSI/IBM label if so requested */ want_ansi_label = dcr->VolCatInfo.LabelType != B_BAREOS_LABEL || dcr->device->label_type != B_BAREOS_LABEL; if (want_ansi_label || dev->has_cap(CAP_CHECKLABELS)) { status = read_ansi_ibm_label(dcr); /* * If we want a label and didn't find it, return error */ if (want_ansi_label && status != VOL_OK) { goto bail_out; } if (status == VOL_NAME_ERROR || status == VOL_LABEL_ERROR) { Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), dev->print_name(), VolName, dev->VolHdr.VolumeName); if (!dev->poll && jcr->label_errors++ > 100) { Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg); } goto bail_out; } if (status != VOL_OK) { /* Not an ANSI/IBM label, so re-read */ dev->rewind(dcr); } else { have_ansi_label = true; } } /* * Read the Bareos Volume label block */ record = new_record(); empty_block(block); Dmsg0(130, "Big if statement in read_volume_label\n"); if (!dcr->read_block_from_dev(NO_BLOCK_NUMBER_CHECK)) { Mmsg(jcr->errmsg, _("Requested Volume \"%s\" on %s is not a Bareos " "labeled Volume, because: ERR=%s"), NPRT(VolName), dev->print_name(), dev->print_errmsg()); Dmsg1(130, "%s", jcr->errmsg); } else if (!read_record_from_block(dcr, record)) { Mmsg(jcr->errmsg, _("Could not read Volume label from block.\n")); Dmsg1(130, "%s", jcr->errmsg); } else if (!unser_volume_label(dev, record)) { Mmsg(jcr->errmsg, _("Could not unserialize Volume label: ERR=%s\n"), dev->print_errmsg()); Dmsg1(130, "%s", jcr->errmsg); } else if (!bstrcmp(dev->VolHdr.Id, BareosId) && !bstrcmp(dev->VolHdr.Id, OldBaculaId) && !bstrcmp(dev->VolHdr.Id, OlderBaculaId)) { Mmsg(jcr->errmsg, _("Volume Header Id bad: %s\n"), dev->VolHdr.Id); Dmsg1(130, "%s", jcr->errmsg); } else { ok = true; } free_record(record); /* finished reading Volume record */ if (!dev->is_volume_to_unload()) { dev->clear_unload(); } if (!ok) { if (forge_on || jcr->ignore_label_errors) { dev->set_labeled(); /* set has Bareos label */ Jmsg(jcr, M_ERROR, 0, "%s", jcr->errmsg); goto ok_out; } Dmsg0(100, "No volume label - bailing out\n"); status = VOL_NO_LABEL; goto bail_out; } /* * At this point, we have read the first Bareos block, and * then read the Bareos Volume label. Now we need to * make sure we have the right Volume. */ if (dev->VolHdr.VerNum != BareosTapeVersion && dev->VolHdr.VerNum != OldCompatibleBareosTapeVersion1 && dev->VolHdr.VerNum != OldCompatibleBareosTapeVersion2 && dev->VolHdr.VerNum != OldCompatibleBareosTapeVersion3) { Mmsg(jcr->errmsg, _("Volume on %s has wrong Bareos version. Wanted %d got %d\n"), dev->print_name(), BareosTapeVersion, dev->VolHdr.VerNum); Dmsg1(130, "VOL_VERSION_ERROR: %s", jcr->errmsg); status = VOL_VERSION_ERROR; goto bail_out; } /* * We are looking for either an unused Bareos tape (PRE_LABEL) or * a Bareos volume label (VOL_LABEL) */ if (dev->VolHdr.LabelType != PRE_LABEL && dev->VolHdr.LabelType != VOL_LABEL) { Mmsg(jcr->errmsg, _("Volume on %s has bad Bareos label type: %x\n"), dev->print_name(), dev->VolHdr.LabelType); Dmsg1(130, "%s", jcr->errmsg); if (!dev->poll && jcr->label_errors++ > 100) { Jmsg(jcr, M_FATAL, 0, _("Too many tries: %s"), jcr->errmsg); } Dmsg0(150, "return VOL_LABEL_ERROR\n"); status = VOL_LABEL_ERROR; goto bail_out; } dev->set_labeled(); /* set has Bareos label */ /* Compare Volume Names */ Dmsg2(130, "Compare Vol names: VolName=%s hdr=%s\n", VolName?VolName:"*", dev->VolHdr.VolumeName); if (VolName && *VolName && *VolName != '*' && !bstrcmp(dev->VolHdr.VolumeName, VolName)) { Mmsg(jcr->errmsg, _("Wrong Volume mounted on device %s: Wanted %s have %s\n"), dev->print_name(), VolName, dev->VolHdr.VolumeName); Dmsg1(130, "%s", jcr->errmsg); /* * Cancel Job if too many label errors * => we are in a loop */ if (!dev->poll && jcr->label_errors++ > 100) { Jmsg(jcr, M_FATAL, 0, "Too many tries: %s", jcr->errmsg); } Dmsg0(150, "return VOL_NAME_ERROR\n"); status = VOL_NAME_ERROR; goto bail_out; } if (debug_level >= 200) { dump_volume_label(dev); } Dmsg0(130, "Leave read_volume_label() VOL_OK\n"); /* * If we are a streaming device, we only get one chance to read */ if (!dev->has_cap(CAP_STREAM)) { dev->rewind(dcr); if (have_ansi_label) { status = read_ansi_ibm_label(dcr); /* * If we want a label and didn't find it, return error */ if (status != VOL_OK) { goto bail_out; } } } Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName); if (reserve_volume(dcr, dev->VolHdr.VolumeName) == NULL) { Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"), dev->VolHdr.VolumeName, dev->print_name()); Dmsg2(150, "Could not reserve volume %s on %s\n", dev->VolHdr.VolumeName, dev->print_name()); status = VOL_NAME_ERROR; goto bail_out; } ok_out: /* * The stored plugin handling the bsdEventLabelVerified event can override * the return value e.g. although we think the volume label is ok the plugin * has reasons to override that. So when the plugin returns something else * then bRC_OK it want to tell us the volume is not OK to use and as * such we return VOL_NAME_ERROR as error although it might not be te * best error it should be sufficient. */ if (generate_plugin_event(jcr, bsdEventLabelVerified, dcr) != bRC_OK) { Dmsg0(200, "Error from bsdEventLabelVerified plugin event.\n"); status = VOL_NAME_ERROR; goto bail_out; } empty_block(block); return VOL_OK; bail_out: empty_block(block); dev->rewind(dcr); Dmsg1(150, "return %d\n", status); return status; }