proxmox-backup/pbs-tape/src/sg_tape/report_density.rs
2021-09-13 12:54:59 +02:00

70 lines
2.0 KiB
Rust

use anyhow::{bail, format_err, Error};
use std::io::Read;
use endian_trait::Endian;
use std::os::unix::io::AsRawFd;
use proxmox::tools::io::ReadExt;
use crate::sgutils2::SgRaw;
#[repr(C, packed)]
#[derive(Endian)]
struct DesnityDescriptorBlock {
primary_density_code: u8,
secondary_density_code: u8,
flags2: u8,
reserved: [u8; 2],
bits_per_mm: [u8; 3],
media_width: u16,
tracks: u16,
capacity: u32,
organizazion: [u8; 8],
density_name: [u8; 8],
description: [u8; 20],
}
// Returns the maximum supported drive density code
pub fn report_density<F: AsRawFd>(file: &mut F) -> Result<u8, Error> {
let alloc_len: u16 = 8192;
let mut sg_raw = SgRaw::new(file, alloc_len as usize)?;
let mut cmd = Vec::new();
cmd.extend(&[0x44, 0, 0, 0, 0, 0, 0]); // REPORT DENSITY SUPPORT (MEDIA=0)
cmd.extend(&alloc_len.to_be_bytes()); // alloc len
cmd.push(0u8); // control byte
let data = sg_raw.do_command(&cmd)
.map_err(|err| format_err!("report density failed - {}", err))?;
let mut max_density = 0u8;
proxmox::try_block!({
let mut reader = &data[..];
let page_len: u16 = unsafe { reader.read_be_value()? };
let page_len = page_len as usize;
if (page_len + 2) > data.len() {
bail!("invalid page length {} {}", page_len + 2, data.len());
} else {
// Note: Quantum hh7 returns the allocation_length instead of real data_len
reader = &data[2..page_len+2];
}
let mut reserved = [0u8; 2];
reader.read_exact(&mut reserved)?;
loop {
if reader.is_empty() { break; }
let block: DesnityDescriptorBlock = unsafe { reader.read_be_value()? };
if block.primary_density_code > max_density {
max_density = block.primary_density_code;
}
}
Ok(())
}).map_err(|err| format_err!("decode report density failed - {}", err))?;
Ok(max_density)
}