tape: add helpers to emulate tape read/write behavior
This commit is contained in:
parent
ec00200411
commit
7c9835465e
|
@ -48,7 +48,7 @@ percent-encoding = "2.1"
|
||||||
pin-utils = "0.1.0"
|
pin-utils = "0.1.0"
|
||||||
pin-project = "0.4"
|
pin-project = "0.4"
|
||||||
pathpatterns = "0.1.2"
|
pathpatterns = "0.1.2"
|
||||||
proxmox = { version = "0.8.0", features = [ "sortable-macro", "api-macro", "websocket" ] }
|
proxmox = { version = "0.8.1", features = [ "sortable-macro", "api-macro", "websocket" ] }
|
||||||
#proxmox = { git = "git://git.proxmox.com/git/proxmox", version = "0.1.2", features = [ "sortable-macro", "api-macro" ] }
|
#proxmox = { git = "git://git.proxmox.com/git/proxmox", version = "0.1.2", features = [ "sortable-macro", "api-macro" ] }
|
||||||
#proxmox = { path = "../proxmox/proxmox", features = [ "sortable-macro", "api-macro", "websocket" ] }
|
#proxmox = { path = "../proxmox/proxmox", features = [ "sortable-macro", "api-macro", "websocket" ] }
|
||||||
proxmox-fuse = "0.1.0"
|
proxmox-fuse = "0.1.0"
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
use std::io::{self, Read};
|
||||||
|
|
||||||
|
use crate::tape::file_formats::PROXMOX_TAPE_BLOCK_SIZE;
|
||||||
|
|
||||||
|
/// Emulate tape read behavior on a normal Reader
|
||||||
|
///
|
||||||
|
/// Tapes reads are always return one whole block PROXMOX_TAPE_BLOCK_SIZE.
|
||||||
|
pub struct EmulateTapeReader<R> {
|
||||||
|
reader: R,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <R: Read> EmulateTapeReader<R> {
|
||||||
|
|
||||||
|
pub fn new(reader: R) -> Self {
|
||||||
|
Self { reader }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <R: Read> Read for EmulateTapeReader<R> {
|
||||||
|
|
||||||
|
fn read(&mut self, mut buffer: &mut [u8]) -> Result<usize, io::Error> {
|
||||||
|
|
||||||
|
let initial_buffer_len = buffer.len(); // store, check later
|
||||||
|
|
||||||
|
let mut bytes = 0;
|
||||||
|
|
||||||
|
while !buffer.is_empty() {
|
||||||
|
match self.reader.read(buffer) {
|
||||||
|
Ok(0) => break,
|
||||||
|
Ok(n) => {
|
||||||
|
bytes += n;
|
||||||
|
let tmp = buffer;
|
||||||
|
buffer = &mut tmp[n..];
|
||||||
|
}
|
||||||
|
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
|
||||||
|
Err(e) => return Err(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if bytes == 0 {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test buffer len after EOF test (to allow EOF test with small buffers in BufferedReader)
|
||||||
|
if initial_buffer_len != PROXMOX_TAPE_BLOCK_SIZE {
|
||||||
|
proxmox::io_bail!("EmulateTapeReader: got read with wrong block size ({} != {})",
|
||||||
|
buffer.len(), PROXMOX_TAPE_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !buffer.is_empty() {
|
||||||
|
Err(io::Error::new(io::ErrorKind::UnexpectedEof, "failed to fill whole buffer"))
|
||||||
|
} else {
|
||||||
|
Ok(bytes)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
use std::io::{self, Write};
|
||||||
|
|
||||||
|
use crate::tape::file_formats::PROXMOX_TAPE_BLOCK_SIZE;
|
||||||
|
|
||||||
|
/// Emulate tape write behavior on a normal Writer
|
||||||
|
///
|
||||||
|
/// Data need to be written in blocks of size PROXMOX_TAPE_BLOCK_SIZE.
|
||||||
|
/// Before reaching the EOT, the writer returns ENOSPC (like a linux
|
||||||
|
/// tape device).
|
||||||
|
pub struct EmulateTapeWriter<W> {
|
||||||
|
block_nr: usize,
|
||||||
|
max_blocks: usize,
|
||||||
|
writer: W,
|
||||||
|
leom_sent: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <W: Write> EmulateTapeWriter<W> {
|
||||||
|
|
||||||
|
/// Create a new instance allowing to write about max_size bytes
|
||||||
|
pub fn new(writer: W, max_size: usize) -> Self {
|
||||||
|
|
||||||
|
let mut max_blocks = max_size/PROXMOX_TAPE_BLOCK_SIZE;
|
||||||
|
|
||||||
|
if max_blocks < 2 {
|
||||||
|
max_blocks = 2; // at least 2 blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
Self {
|
||||||
|
block_nr: 0,
|
||||||
|
leom_sent: false,
|
||||||
|
writer,
|
||||||
|
max_blocks,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl <W: Write> Write for EmulateTapeWriter<W> {
|
||||||
|
|
||||||
|
fn write(&mut self, buffer: &[u8]) -> Result<usize, io::Error> {
|
||||||
|
|
||||||
|
if buffer.len() != PROXMOX_TAPE_BLOCK_SIZE {
|
||||||
|
proxmox::io_bail!("EmulateTapeWriter: got write with wrong block size ({} != {}",
|
||||||
|
buffer.len(), PROXMOX_TAPE_BLOCK_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.block_nr >= self.max_blocks + 2 {
|
||||||
|
return Err(io::Error::from_raw_os_error(nix::errno::Errno::ENOSPC as i32));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.block_nr >= self.max_blocks {
|
||||||
|
if !self.leom_sent {
|
||||||
|
self.leom_sent = true;
|
||||||
|
return Err(io::Error::from_raw_os_error(nix::errno::Errno::ENOSPC as i32));
|
||||||
|
} else {
|
||||||
|
self.leom_sent = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.writer.write_all(buffer)?;
|
||||||
|
self.block_nr += 1;
|
||||||
|
|
||||||
|
Ok(buffer.len())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> Result<(), io::Error> {
|
||||||
|
proxmox::io_bail!("EmulateTapeWriter does not support flush");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
mod emulate_tape_writer;
|
||||||
|
pub use emulate_tape_writer::*;
|
||||||
|
|
||||||
|
mod emulate_tape_reader;
|
||||||
|
pub use emulate_tape_reader::*;
|
|
@ -6,6 +6,9 @@ pub use tape_write::*;
|
||||||
mod tape_read;
|
mod tape_read;
|
||||||
pub use tape_read::*;
|
pub use tape_read::*;
|
||||||
|
|
||||||
|
mod helpers;
|
||||||
|
pub use helpers::*;
|
||||||
|
|
||||||
mod inventory;
|
mod inventory;
|
||||||
pub use inventory::*;
|
pub use inventory::*;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue