mirror of
https://github.com/scsitape/stenc.git
synced 2026-09-13 11:04:14 +00:00
Do media checks on getting next block encryption status (#74)
* Do media check before getting NBES and allow getting status without media * Supress error from BLANK CHECK sense when querying next block encryption status
This commit is contained in:
+16
-5
@@ -200,7 +200,7 @@ static void print_device_status(std::ostream& os, const scsi::page_des& opt, boo
|
||||
}
|
||||
|
||||
static void showDriveStatus(const std::string& tapeDrive, bool detail) {
|
||||
alignas(4) scsi::page_buffer buffer;
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};
|
||||
|
||||
@@ -281,7 +281,7 @@ static void print_volume_status(std::ostream& os, const scsi::page_nbes& opt)
|
||||
}
|
||||
|
||||
static void showVolumeStatus(const std::string& tapeDrive) {
|
||||
alignas(4) scsi::page_buffer buffer;
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
scsi::get_nbes(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& opt {reinterpret_cast<const scsi::page_nbes&>(buffer)};
|
||||
|
||||
@@ -420,8 +420,19 @@ int main(int argc, const char **argv) {
|
||||
inquiryDrive(tapeDrive);
|
||||
}
|
||||
showDriveStatus(tapeDrive, detail);
|
||||
if (detail) {
|
||||
showVolumeStatus(tapeDrive);
|
||||
if (detail && scsi::is_device_ready(tapeDrive)) {
|
||||
try {
|
||||
showVolumeStatus(tapeDrive);
|
||||
} catch (const scsi::scsi_error& err) {
|
||||
// #71: ignore BLANK CHECK sense key that some drives may return
|
||||
// during media access check in getting NBES
|
||||
auto sense_key {
|
||||
err.get_sense().flags & scsi::sense_data::flags_sense_key_mask
|
||||
};
|
||||
if (sense_key != scsi::sense_data::blank_check) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
exit(EXIT_SUCCESS);
|
||||
} catch (const scsi::scsi_error& err) {
|
||||
@@ -495,7 +506,7 @@ int main(int argc, const char **argv) {
|
||||
key, key_name, rdmc, ckod)};
|
||||
scsi::write_sde(tapeDrive, sde_buffer.get());
|
||||
|
||||
alignas(4) scsi::page_buffer buffer;
|
||||
alignas(4) scsi::page_buffer buffer {};
|
||||
scsi::get_des(tapeDrive, buffer, sizeof(buffer));
|
||||
auto& opt {reinterpret_cast<const scsi::page_des&>(buffer)};
|
||||
|
||||
|
||||
+23
-10
@@ -83,7 +83,7 @@ static void scsi_execute(const std::string& device, const std::uint8_t *cmd_p,
|
||||
std::size_t dxfer_len, scsi_direction direction)
|
||||
{
|
||||
#if defined(OS_LINUX)
|
||||
unique_fd fd {open(device.c_str(), O_RDONLY)};
|
||||
unique_fd fd {open(device.c_str(), O_RDONLY | O_NDELAY)};
|
||||
if (!fd) {
|
||||
std::ostringstream oss;
|
||||
oss << "Cannot open device " << device;
|
||||
@@ -146,6 +146,19 @@ static void scsi_execute(const std::string& device, const std::uint8_t *cmd_p,
|
||||
|
||||
namespace scsi {
|
||||
|
||||
bool is_device_ready(const std::string& device)
|
||||
{
|
||||
const std::uint8_t test_unit_ready_cmd[6] {};
|
||||
|
||||
try {
|
||||
scsi_execute(device, test_unit_ready_cmd, sizeof(test_unit_ready_cmd),
|
||||
nullptr, 0u, scsi_direction::from_device);
|
||||
return true;
|
||||
} catch (const scsi::scsi_error& err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void get_des(const std::string& device, std::uint8_t *buffer, std::size_t length)
|
||||
{
|
||||
const std::uint8_t spin_des_command[] {
|
||||
@@ -266,31 +279,31 @@ void write_sde(const std::string& device, const std::uint8_t *sde_buffer)
|
||||
void print_sense_data(std::ostream& os, const sense_data& sd) {
|
||||
os << std::left << std::setw(25) << "Sense Code: ";
|
||||
|
||||
auto sense_key {static_cast<unsigned int>(sd.flags & sense_data::flags_sense_key_mask)};
|
||||
auto sense_key {sd.flags & sense_data::flags_sense_key_mask};
|
||||
|
||||
switch (sense_key) {
|
||||
case 0u:
|
||||
case sense_data::no_sense:
|
||||
os << "No specific error";
|
||||
break;
|
||||
case 2u:
|
||||
case sense_data::not_ready:
|
||||
os << "Device not ready";
|
||||
break;
|
||||
case 3u:
|
||||
case sense_data::medium_error:
|
||||
os << "Medium Error";
|
||||
break;
|
||||
case 4u:
|
||||
case sense_data::hardware_error:
|
||||
os << "Hardware Error";
|
||||
break;
|
||||
case 5u:
|
||||
case sense_data::illegal_request:
|
||||
os << "Illegal Request";
|
||||
break;
|
||||
case 6u:
|
||||
case sense_data::unit_attention:
|
||||
os << "Unit Attention";
|
||||
break;
|
||||
case 7u:
|
||||
case sense_data::data_protect:
|
||||
os << "Data protect";
|
||||
break;
|
||||
case 8u:
|
||||
case sense_data::blank_check:
|
||||
os << "Blank tape";
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -285,6 +285,17 @@ struct __attribute__((packed)) sense_data {
|
||||
std::uint8_t field_replaceable_unit_code;
|
||||
std::uint8_t sense_key_specific[3];
|
||||
std::uint8_t additional_sense_bytes[];
|
||||
|
||||
static constexpr std::byte no_sense {0u};
|
||||
static constexpr std::byte recovered_error {1u};
|
||||
static constexpr std::byte not_ready {2u};
|
||||
static constexpr std::byte medium_error {3u};
|
||||
static constexpr std::byte hardware_error {4u};
|
||||
static constexpr std::byte illegal_request {5u};
|
||||
static constexpr std::byte unit_attention {6u};
|
||||
static constexpr std::byte data_protect {7u};
|
||||
static constexpr std::byte blank_check {8u};
|
||||
|
||||
static constexpr auto maximum_size {252u}; // per SPC-5
|
||||
};
|
||||
static_assert(sizeof(sense_data) == 18u);
|
||||
@@ -321,6 +332,9 @@ std::vector<const kad *> read_page_kads(const Page& page)
|
||||
return v;
|
||||
}
|
||||
|
||||
// Check if a tape is loaded
|
||||
bool is_device_ready(const std::string& device);
|
||||
// Get SCSI inquiry data from device
|
||||
inquiry_data get_inquiry(const std::string& device);
|
||||
// Get data encryption status page
|
||||
void get_des(const std::string& device, std::uint8_t *buffer, std::size_t length);
|
||||
|
||||
Reference in New Issue
Block a user