static void get_session_record(DEVICE *dev, DEV_RECORD *rec, SESSION_LABEL *sessrec) { const char *rtype; memset(sessrec, 0, sizeof(sessrec)); switch (rec->FileIndex) { case PRE_LABEL: rtype = _("Fresh Volume Label"); break; case VOL_LABEL: rtype = _("Volume Label"); unser_volume_label(dev, rec); break; case SOS_LABEL: rtype = _("Begin Job Session"); unser_session_label(sessrec, rec); break; case EOS_LABEL: rtype = _("End Job Session"); break; case 0: case EOM_LABEL: rtype = _("End of Medium"); break; default: rtype = _("Unknown"); break; } Dmsg5(10, "%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n", rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); if (verbose) { Pmsg5(-1, _("%s Record: VolSessionId=%d VolSessionTime=%d JobId=%d DataLen=%d\n"), rtype, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); } }
/* * 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; }
void dump_label_record(DEVICE *dev, DEV_RECORD *rec, bool verbose) { const char *type; int dbl; if (rec->FileIndex == 0 && rec->VolSessionId == 0 && rec->VolSessionTime == 0) { return; } dbl = debug_level; debug_level = 1; switch (rec->FileIndex) { case PRE_LABEL: type = _("Fresh Volume"); break; case VOL_LABEL: type = _("Volume"); break; case SOS_LABEL: type = _("Begin Job Session"); break; case EOS_LABEL: type = _("End Job Session"); break; case EOM_LABEL: type = _("End of Media"); break; case EOT_LABEL: type = _("End of Tape"); break; default: type = _("Unknown"); break; } if (verbose) { switch (rec->FileIndex) { case PRE_LABEL: case VOL_LABEL: unser_volume_label(dev, rec); dump_volume_label(dev); break; case SOS_LABEL: dump_session_label(rec, type); break; case EOS_LABEL: dump_session_label(rec, type); break; case EOM_LABEL: Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"), type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); break; case EOT_LABEL: Pmsg0(-1, _("End of physical tape.\n")); break; default: Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"), type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); break; } } else { SESSION_LABEL label; char dt[50]; switch (rec->FileIndex) { case SOS_LABEL: unser_session_label(&label, rec); bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime)); Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"), type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId); Pmsg4(-1, _(" Job=%s Date=%s Level=%c Type=%c\n"), label.Job, dt, label.JobLevel, label.JobType); break; case EOS_LABEL: char ed1[30], ed2[30]; unser_session_label(&label, rec); bstrftimes(dt, sizeof(dt), btime_to_utime(label.write_btime)); Pmsg6(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d\n"), type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, label.JobId); Pmsg7(-1, _(" Date=%s Level=%c Type=%c Files=%s Bytes=%s Errors=%d Status=%c\n"), dt, label.JobLevel, label.JobType, edit_uint64_with_commas(label.JobFiles, ed1), edit_uint64_with_commas(label.JobBytes, ed2), label.JobErrors, (char)label.JobStatus); break; case EOM_LABEL: case PRE_LABEL: case VOL_LABEL: default: Pmsg7(-1, _("%s Record: File:blk=%u:%u SessId=%d SessTime=%d JobId=%d DataLen=%d\n"), type, dev->file, dev->block_num, rec->VolSessionId, rec->VolSessionTime, rec->Stream, rec->data_len); break; case EOT_LABEL: break; } } debug_level = dbl; }