diff --git a/Cargo.toml b/Cargo.toml index 820d5709..856e1abf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ percent-encoding = "2.1" pin-utils = "0.1.0" pin-project = "0.4" 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 = { path = "../proxmox/proxmox", features = [ "sortable-macro", "api-macro", "websocket" ] } proxmox-fuse = "0.1.0" diff --git a/src/tape/helpers/emulate_tape_reader.rs b/src/tape/helpers/emulate_tape_reader.rs new file mode 100644 index 00000000..1b6d4c5e --- /dev/null +++ b/src/tape/helpers/emulate_tape_reader.rs @@ -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 { + reader: R, +} + +impl EmulateTapeReader { + + pub fn new(reader: R) -> Self { + Self { reader } + } +} + +impl Read for EmulateTapeReader { + + fn read(&mut self, mut buffer: &mut [u8]) -> Result { + + 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) + } + } +} diff --git a/src/tape/helpers/emulate_tape_writer.rs b/src/tape/helpers/emulate_tape_writer.rs new file mode 100644 index 00000000..b385d6b3 --- /dev/null +++ b/src/tape/helpers/emulate_tape_writer.rs @@ -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 { + block_nr: usize, + max_blocks: usize, + writer: W, + leom_sent: bool, +} + +impl EmulateTapeWriter { + + /// 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 Write for EmulateTapeWriter { + + fn write(&mut self, buffer: &[u8]) -> Result { + + 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"); + } +} diff --git a/src/tape/helpers/mod.rs b/src/tape/helpers/mod.rs new file mode 100644 index 00000000..66c8fea9 --- /dev/null +++ b/src/tape/helpers/mod.rs @@ -0,0 +1,5 @@ +mod emulate_tape_writer; +pub use emulate_tape_writer::*; + +mod emulate_tape_reader; +pub use emulate_tape_reader::*; diff --git a/src/tape/mod.rs b/src/tape/mod.rs index 9e11ea4e..85de1328 100644 --- a/src/tape/mod.rs +++ b/src/tape/mod.rs @@ -6,6 +6,9 @@ pub use tape_write::*; mod tape_read; pub use tape_read::*; +mod helpers; +pub use helpers::*; + mod inventory; pub use inventory::*;