2020-12-06 08:41:16 +00:00
|
|
|
use std::io::{self, Write};
|
|
|
|
|
2021-09-13 09:54:24 +00:00
|
|
|
use crate::{BlockWrite, PROXMOX_TAPE_BLOCK_SIZE};
|
2020-12-06 08:41:16 +00:00
|
|
|
|
|
|
|
/// 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,
|
2021-03-29 10:52:26 +00:00
|
|
|
wrote_eof: bool,
|
2020-12-06 08:41:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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,
|
2021-03-29 10:52:26 +00:00
|
|
|
wrote_eof: false,
|
2020-12-06 08:41:16 +00:00
|
|
|
writer,
|
|
|
|
max_blocks,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-29 10:52:26 +00:00
|
|
|
impl <W: Write> BlockWrite for EmulateTapeWriter<W> {
|
2020-12-06 08:41:16 +00:00
|
|
|
|
2021-03-29 10:52:26 +00:00
|
|
|
fn write_block(&mut self, buffer: &[u8]) -> Result<bool, io::Error> {
|
2020-12-06 08:41:16 +00:00
|
|
|
|
|
|
|
if buffer.len() != PROXMOX_TAPE_BLOCK_SIZE {
|
2021-11-23 16:57:00 +00:00
|
|
|
proxmox_sys::io_bail!("EmulateTapeWriter: got write with wrong block size ({} != {}",
|
2020-12-06 08:41:16 +00:00
|
|
|
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));
|
|
|
|
}
|
|
|
|
|
|
|
|
self.writer.write_all(buffer)?;
|
|
|
|
self.block_nr += 1;
|
|
|
|
|
2021-03-29 10:52:26 +00:00
|
|
|
if self.block_nr > self.max_blocks {
|
|
|
|
Ok(true)
|
|
|
|
} else {
|
|
|
|
Ok(false)
|
|
|
|
}
|
2020-12-06 08:41:16 +00:00
|
|
|
}
|
|
|
|
|
2021-03-29 10:52:26 +00:00
|
|
|
fn write_filemark(&mut self) -> Result<(), std::io::Error> {
|
|
|
|
if self.wrote_eof {
|
2021-11-23 16:57:00 +00:00
|
|
|
proxmox_sys::io_bail!("EmulateTapeWriter: detected multiple EOF writes");
|
2021-03-29 10:52:26 +00:00
|
|
|
}
|
|
|
|
// do nothing, just record the call
|
|
|
|
self.wrote_eof = true;
|
|
|
|
Ok(())
|
2020-12-06 08:41:16 +00:00
|
|
|
}
|
|
|
|
}
|