/** * Get info on the next appendable volume in the Director's database * * Returns: true on success dcr->VolumeName is volume * reserve_volume() called on Volume name * false on failure dcr->VolumeName[0] == 0 * also sets dcr->found_in_use if at least one * in use volume was found. * * Volume information returned in dcr * */ bool dir_find_next_appendable_volume(DCR *dcr) { JCR *jcr = dcr->jcr; BSOCK *dir = jcr->dir_bsock; bool rtn; char lastVolume[MAX_NAME_LENGTH]; Dmsg2(dbglvl, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n", dcr->is_reserved(), dcr->VolumeName); /* * Try the twenty oldest or most available volumes. Note, * the most available could already be mounted on another * drive, so we continue looking for a not in use Volume. */ lock_volumes(); P(vol_info_mutex); dcr->clear_found_in_use(); lastVolume[0] = 0; for (int vol_index=1; vol_index < 20; vol_index++) { bash_spaces(dcr->media_type); bash_spaces(dcr->pool_name); dir->fsend(Find_media, jcr->Job, vol_index, dcr->pool_name, dcr->media_type); unbash_spaces(dcr->media_type); unbash_spaces(dcr->pool_name); Dmsg1(dbglvl, ">dird %s", dir->msg); if (do_get_volume_info(dcr)) { /* Give up if we get the same volume name twice */ if (lastVolume[0] && bstrcmp(lastVolume, dcr->VolumeName)) { Dmsg1(dbglvl, "Got same vol = %s\n", lastVolume); break; } bstrncpy(lastVolume, dcr->VolumeName, sizeof(lastVolume)); if (dcr->can_i_write_volume()) { Dmsg1(dbglvl, "Call reserve_volume for write. Vol=%s\n", dcr->VolumeName); if (reserve_volume(dcr, dcr->VolumeName) == NULL) { Dmsg2(dbglvl, "Could not reserve volume %s on %s\n", dcr->VolumeName, dcr->dev->print_name()); continue; } Dmsg1(dbglvl, "dir_find_next_appendable_volume return true. vol=%s\n", dcr->VolumeName); rtn = true; goto get_out; } else { Dmsg1(dbglvl, "Volume %s is in use.\n", dcr->VolumeName); /* If volume is not usable, it is in use by someone else */ dcr->set_found_in_use(); continue; } } Dmsg2(dbglvl, "No vol. index %d return false. dev=%s\n", vol_index, dcr->dev->print_name()); break; } rtn = false; dcr->VolumeName[0] = 0; get_out: V(vol_info_mutex); unlock_volumes(); return rtn; }
/* * We read an ANSI label and compare the Volume name. We require * a VOL1 record of 80 characters followed by a HDR1 record containing * BACULA.DATA in the filename field. We then read up to 3 more * header records (they are not required) and an EOF, at which * point, all is good. * * Returns: * VOL_OK Volume name OK * VOL_NO_LABEL No ANSI label on Volume * VOL_IO_ERROR I/O error on read * VOL_NAME_ERROR Wrong name in VOL1 record * VOL_LABEL_ERROR Probably an ANSI label, but something wrong * */ int read_ansi_ibm_label(DCR *dcr) { DEVICE * volatile dev = dcr->dev; JCR *jcr = dcr->jcr; char label[80]; /* tape label */ int stat, i; char *VolName = dcr->VolumeName; bool ok = false; /* * Read VOL1, HDR1, HDR2 labels, but ignore the data * If tape read the following EOF mark, on disk do * not read. */ Dmsg0(100, "Read ansi label.\n"); if (!dev->is_tape()) { return VOL_OK; } dev->label_type = B_BACULA_LABEL; /* assume Bacula label */ /* Read a maximum of 5 records VOL1, HDR1, ... HDR4 */ for (i=0; i < 6; i++) { do { stat = dev->read(label, sizeof(label)); } while (stat == -1 && errno == EINTR); if (stat < 0) { berrno be; dev->clrerror(-1); Dmsg1(100, "Read device got: ERR=%s\n", be.bstrerror()); Mmsg2(jcr->errmsg, _("Read error on device %s in ANSI label. ERR=%s\n"), dev->dev_name, be.bstrerror()); Jmsg(jcr, M_ERROR, 0, "%s", dev->errmsg); dev->VolCatInfo.VolCatErrors++; return VOL_IO_ERROR; } if (stat == 0) { if (dev->at_eof()) { dev->set_eot(); /* second eof, set eot bit */ Dmsg0(100, "EOM on ANSI label\n"); Mmsg0(jcr->errmsg, _("Insane! End of tape while reading ANSI label.\n")); return VOL_LABEL_ERROR; /* at EOM this shouldn't happen */ } else { dev->set_ateof(); /* set eof state */ } } switch (i) { case 0: /* Want VOL1 label */ if (stat == 80) { if (strncmp("VOL1", label, 4) == 0) { ok = true; dev->label_type = B_ANSI_LABEL; Dmsg0(100, "Got ANSI VOL1 label\n"); } else { /* Try EBCDIC */ ebcdic_to_ascii(label, label, sizeof(label)); if (strncmp("VOL1", label, 4) == 0) { ok = true;; dev->label_type = B_IBM_LABEL; Dmsg0(100, "Found IBM label.\n"); Dmsg0(100, "Got IBM VOL1 label\n"); } } } if (!ok) { Dmsg0(100, "No VOL1 label\n"); Mmsg0(jcr->errmsg, _("No VOL1 label while reading ANSI/IBM label.\n")); return VOL_NO_LABEL; /* No ANSI label */ } /* Compare Volume Names allow special wild card */ if (VolName && *VolName && *VolName != '*') { if (!same_label_names(VolName, &label[4])) { char *p = &label[4]; char *q; free_volume(dev); /* Store new Volume name */ q = dev->VolHdr.VolumeName; for (int i=0; *p != ' ' && i < 6; i++) { *q++ = *p++; } *q = 0; Dmsg0(100, "Call reserve_volume\n"); /* ***FIXME*** why is this reserve_volume() needed???? KES */ reserve_volume(dcr, dev->VolHdr.VolumeName); dev = dcr->dev; /* may have changed in reserve_volume */ Dmsg2(100, "Wanted ANSI Vol %s got %6s\n", VolName, dev->VolHdr.VolumeName); Mmsg2(jcr->errmsg, _("Wanted ANSI Volume \"%s\" got \"%s\"\n"), VolName, dev->VolHdr.VolumeName); return VOL_NAME_ERROR; } } break; case 1: if (dev->label_type == B_IBM_LABEL) { ebcdic_to_ascii(label, label, sizeof(label)); } if (stat != 80 || strncmp("HDR1", label, 4) != 0) { Dmsg0(100, "No HDR1 label\n"); Mmsg0(jcr->errmsg, _("No HDR1 label while reading ANSI label.\n")); return VOL_LABEL_ERROR; } if (strncmp("BACULA.DATA", &label[4], 11) != 0) { Dmsg1(100, "HD1 not Bacula label. Wanted BACULA.DATA got %11s\n", &label[4]); Mmsg1(jcr->errmsg, _("ANSI/IBM Volume \"%s\" does not belong to Bacula.\n"), dev->VolHdr.VolumeName); return VOL_NAME_ERROR; /* Not a Bacula label */ } Dmsg0(100, "Got HDR1 label\n"); break; case 2: if (dev->label_type == B_IBM_LABEL) { ebcdic_to_ascii(label, label, sizeof(label)); } if (stat != 80 || strncmp("HDR2", label, 4) != 0) { Dmsg0(100, "No HDR2 label\n"); Mmsg0(jcr->errmsg, _("No HDR2 label while reading ANSI/IBM label.\n")); return VOL_LABEL_ERROR; } Dmsg0(100, "Got ANSI HDR2 label\n"); break; default: if (stat == 0) { Dmsg0(100, "ANSI label OK\n"); return VOL_OK; } if (dev->label_type == B_IBM_LABEL) { ebcdic_to_ascii(label, label, sizeof(label)); } if (stat != 80 || strncmp("HDR", label, 3) != 0) { Dmsg0(100, "Unknown or bad ANSI/IBM label record.\n"); Mmsg0(jcr->errmsg, _("Unknown or bad ANSI/IBM label record.\n")); return VOL_LABEL_ERROR; } Dmsg0(100, "Got HDR label\n"); break; } } Dmsg0(100, "Too many records in ANSI/IBM label.\n"); Mmsg0(jcr->errmsg, _("Too many records in while reading ANSI/IBM label.\n")); return VOL_LABEL_ERROR; }
int DCR::check_volume_label(bool &ask, bool &autochanger) { int vol_label_status; /* * If we are writing to a stream device, ASSUME the volume label * is correct. */ if (dev->has_cap(CAP_STREAM)) { vol_label_status = VOL_OK; create_volume_label(dev, VolumeName, "Default", false /* not DVD */); dev->VolHdr.LabelType = PRE_LABEL; } else { vol_label_status = read_dev_volume_label(this); } if (job_canceled(jcr)) { goto check_bail_out; } Dmsg2(150, "Want dirVol=%s dirStat=%s\n", VolumeName, VolCatInfo.VolCatStatus); /* * At this point, dev->VolCatInfo has what is in the drive, if anything, * and dcr->VolCatInfo has what the Director wants. */ switch (vol_label_status) { case VOL_OK: Dmsg1(150, "Vol OK name=%s\n", dev->VolHdr.VolumeName); dev->VolCatInfo = VolCatInfo; /* structure assignment */ break; /* got a Volume */ case VOL_NAME_ERROR: VOLUME_CAT_INFO dcrVolCatInfo, devVolCatInfo; char saveVolumeName[MAX_NAME_LENGTH]; Dmsg2(150, "Vol NAME Error Have=%s, want=%s\n", dev->VolHdr.VolumeName, VolumeName); if (dev->is_volume_to_unload()) { ask = true; goto check_next_volume; } /* If not removable, Volume is broken */ if (!dev->is_removable()) { Jmsg(jcr, M_WARNING, 0, _("Volume \"%s\" not on device %s.\n"), VolumeName, dev->print_name()); mark_volume_in_error(); goto check_next_volume; } /* * OK, we got a different volume mounted. First save the * requested Volume info (dcr) structure, then query if * this volume is really OK. If not, put back the desired * volume name, mark it not in changer and continue. */ dcrVolCatInfo = VolCatInfo; /* structure assignment */ devVolCatInfo = dev->VolCatInfo; /* structure assignment */ /* Check if this is a valid Volume in the pool */ bstrncpy(saveVolumeName, VolumeName, sizeof(saveVolumeName)); bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName)); if (!dir_get_volume_info(this, GET_VOL_INFO_FOR_WRITE)) { POOL_MEM vol_info_msg; pm_strcpy(vol_info_msg, jcr->dir_bsock->msg); /* save error message */ /* Restore desired volume name, note device info out of sync */ /* This gets the info regardless of the Pool */ bstrncpy(VolumeName, dev->VolHdr.VolumeName, sizeof(VolumeName)); if (autochanger && !dir_get_volume_info(this, GET_VOL_INFO_FOR_READ)) { /* * If we get here, we know we cannot write on the Volume, * and we know that we cannot read it either, so it * is not in the autochanger. */ mark_volume_not_inchanger(); } dev->VolCatInfo = devVolCatInfo; /* structure assignment */ dev->set_unload(); /* unload this volume */ Jmsg(jcr, M_WARNING, 0, _("Director wanted Volume \"%s\".\n" " Current Volume \"%s\" not acceptable because:\n" " %s"), dcrVolCatInfo.VolCatName, dev->VolHdr.VolumeName, vol_info_msg.c_str()); ask = true; /* Restore saved DCR before continuing */ bstrncpy(VolumeName, saveVolumeName, sizeof(VolumeName)); VolCatInfo = dcrVolCatInfo; /* structure assignment */ goto check_next_volume; } /* * This was not the volume we expected, but it is OK with * the Director, so use it. */ Dmsg1(150, "Got new Volume name=%s\n", VolumeName); dev->VolCatInfo = VolCatInfo; /* structure assignment */ Dmsg1(100, "Call reserve_volume=%s\n", dev->VolHdr.VolumeName); if (reserve_volume(this, dev->VolHdr.VolumeName) == NULL) { Jmsg2(jcr, M_WARNING, 0, _("Could not reserve volume %s on %s\n"), dev->VolHdr.VolumeName, dev->print_name()); ask = true; goto check_next_volume; } break; /* got a Volume */ /* * At this point, we assume we have a blank tape mounted. */ case VOL_IO_ERROR: if (dev->is_dvd()) { Jmsg(jcr, M_FATAL, 0, "%s", jcr->errmsg); mark_volume_in_error(); goto check_bail_out; /* we could not write on DVD */ } /* Fall through wanted */ case VOL_NO_LABEL: switch (try_autolabel(true)) { case try_next_vol: goto check_next_volume; case try_read_vol: goto check_read_volume; case try_error: goto check_bail_out; case try_default: break; } /* NOTE! Fall-through wanted. */ case VOL_NO_MEDIA: default: Dmsg0(200, "VOL_NO_MEDIA or default.\n"); /* Send error message */ if (!dev->poll) { } else { Dmsg1(200, "Msg suppressed by poll: %s\n", jcr->errmsg); } ask = true; /* Needed, so the medium can be changed */ if (dev->requires_mount()) { dev->close(); } goto check_next_volume; } return check_ok; check_next_volume: return check_next_vol; check_bail_out: return check_error; check_read_volume: return check_read_vol; }
/** * Get info on the next appendable volume in the Director's database * * Returns: true on success dcr->VolumeName is volume * reserve_volume() called on Volume name * false on failure dcr->VolumeName[0] == 0 * also sets dcr->found_in_use if at least one * in use volume was found. * * Volume information returned in dcr */ bool SD_DCR::dir_find_next_appendable_volume() { bool retval; BSOCK *dir = jcr->dir_bsock; POOL_MEM unwanted_volumes(PM_MESSAGE); Dmsg2(dbglvl, "dir_find_next_appendable_volume: reserved=%d Vol=%s\n", is_reserved(), VolumeName); /* * Try the twenty oldest or most available volumes. Note, * the most available could already be mounted on another * drive, so we continue looking for a not in use Volume. */ lock_volumes(); P(vol_info_mutex); clear_found_in_use(); pm_strcpy(unwanted_volumes, ""); for (int vol_index = 1; vol_index < 20; vol_index++) { bash_spaces(media_type); bash_spaces(pool_name); bash_spaces(unwanted_volumes.c_str()); dir->fsend(Find_media, jcr->Job, vol_index, pool_name, media_type, unwanted_volumes.c_str()); unbash_spaces(media_type); unbash_spaces(pool_name); unbash_spaces(unwanted_volumes.c_str()); Dmsg1(dbglvl, ">dird %s", dir->msg); if (do_get_volume_info(this)) { if (vol_index == 1) { pm_strcpy(unwanted_volumes, VolumeName); } else { pm_strcat(unwanted_volumes, ","); pm_strcat(unwanted_volumes, VolumeName); } if (can_i_write_volume()) { Dmsg1(dbglvl, "Call reserve_volume for write. Vol=%s\n", VolumeName); if (reserve_volume(this, VolumeName) == NULL) { Dmsg2(dbglvl, "Could not reserve volume %s on %s\n", VolumeName, dev->print_name()); continue; } Dmsg1(dbglvl, "dir_find_next_appendable_volume return true. vol=%s\n", VolumeName); retval = true; goto get_out; } else { Dmsg1(dbglvl, "Volume %s is in use.\n", VolumeName); /* * If volume is not usable, it is in use by someone else */ set_found_in_use(); continue; } } Dmsg2(dbglvl, "No vol. index %d return false. dev=%s\n", vol_index, dev->print_name()); break; } retval = false; VolumeName[0] = 0; get_out: V(vol_info_mutex); unlock_volumes(); return retval; }
/* * 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; }
/* * Write a Volume Label * !!! Note, this is ONLY used for writing * a fresh volume label. Any data * after the label will be destroyed, * in fact, we write the label 5 times !!!! * * This routine should be used only when labeling a blank tape. */ bool write_new_volume_label_to_dev(DCR *dcr, const char *VolName, const char *PoolName, bool relabel) { JCR *jcr = dcr->jcr; DEVICE *dev = dcr->dev; DEV_BLOCK *block = dcr->block; Dmsg0(150, "write_volume_label()\n"); if (*VolName == 0) { Pmsg0(0, "=== ERROR: write_new_volume_label_to_dev called with NULL VolName\n"); goto bail_out; } if (relabel) { volume_unused(dcr); /* mark current volume unused */ /* Truncate device */ if (!dev->truncate(dcr)) { goto bail_out; } if (!dev->is_tape()) { dev->close(dcr); /* make sure file closed for rename */ } } /* Set the new filename for open, ... */ dev->setVolCatName(VolName); dcr->setVolCatName(VolName); Dmsg1(150, "New VolName=%s\n", VolName); if (!dev->open(dcr, OPEN_READ_WRITE)) { /* If device is not tape, attempt to create it */ if (dev->is_tape() || !dev->open(dcr, CREATE_READ_WRITE)) { Jmsg3(jcr, M_WARNING, 0, _("Open device %s Volume \"%s\" failed: ERR=%s\n"), dev->print_name(), dcr->VolumeName, dev->bstrerror()); goto bail_out; } } Dmsg1(150, "Label type=%d\n", dev->label_type); /* * Let any stored plugin know that we are about to write a new label to the volume. */ if (generate_plugin_event(jcr, bsdEventLabelWrite, dcr) != bRC_OK) { Dmsg0(200, "Error from bsdEventLabelWrite plugin event.\n"); goto bail_out; } for ( ;; ) { empty_block(block); if (!dev->rewind(dcr)) { Dmsg2(130, "Bad status on %s from rewind: ERR=%s\n", dev->print_name(), dev->print_errmsg()); if (!forge_on) { goto bail_out; } } /* Temporarily mark in append state to enable writing */ dev->set_append(); /* Create PRE_LABEL */ create_volume_label(dev, VolName, PoolName); /* * If we have already detected an ANSI label, re-read it * to skip past it. Otherwise, we write a new one if * so requested. */ if (dev->label_type != B_BAREOS_LABEL) { if (read_ansi_ibm_label(dcr) != VOL_OK) { dev->rewind(dcr); goto bail_out; } } else if (!write_ansi_ibm_labels(dcr, ANSI_VOL_LABEL, VolName)) { goto bail_out; } create_volume_label_record(dcr, dev, dcr->rec); dcr->rec->Stream = 0; dcr->rec->maskedStream = 0; if (!write_record_to_block(dcr, dcr->rec)) { Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg()); goto bail_out; } else { Dmsg2(130, "Wrote label of %d bytes to %s\n", dcr->rec->data_len, dev->print_name()); } Dmsg0(130, "Call write_block_to_dev()\n"); if (!dcr->write_block_to_dev()) { Dmsg2(130, "Bad Label write on %s: ERR=%s\n", dev->print_name(), dev->print_errmsg()); goto bail_out; } break; } dev = dcr->dev; Dmsg0(130, " Wrote block to device\n"); if (dev->weof(1)) { dev->set_labeled(); write_ansi_ibm_labels(dcr, ANSI_EOF_LABEL, dev->VolHdr.VolumeName); } if (debug_level >= 20) { dump_volume_label(dev); } Dmsg0(100, "Call reserve_volume\n"); if (reserve_volume(dcr, VolName) == NULL) { Mmsg2(jcr->errmsg, _("Could not reserve volume %s on %s\n"), dev->VolHdr.VolumeName, dev->print_name()); Dmsg1(100, "%s", jcr->errmsg); goto bail_out; } dev = dcr->dev; /* may have changed in reserve_volume */ dev->clear_append(); /* remove append since this is PRE_LABEL */ return true; bail_out: volume_unused(dcr); dev->clear_volhdr(); dev->clear_append(); /* remove append since this is PRE_LABEL */ return false; }