Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Do media checks on getting next block encryption status #74

Merged
merged 2 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)};

Expand Down Expand Up @@ -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)};

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)};

Expand Down
33 changes: 23 additions & 10 deletions src/scsiencrypt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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[] {
Expand Down Expand Up @@ -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;
}
Expand Down
14 changes: 14 additions & 0 deletions src/scsiencrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down