From d735b3134520e1bd9acd9fdd52d8e3e65ffab1e8 Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Sat, 5 Dec 2020 10:54:38 +0100 Subject: [PATCH] tape: add tape read trait --- src/tape/mod.rs | 3 +++ src/tape/tape_read.rs | 45 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/tape/tape_read.rs diff --git a/src/tape/mod.rs b/src/tape/mod.rs index 36e2efc5..cce4e553 100644 --- a/src/tape/mod.rs +++ b/src/tape/mod.rs @@ -2,3 +2,6 @@ pub mod file_formats; mod tape_write; pub use tape_write::*; + +mod tape_read; +pub use tape_read::*; diff --git a/src/tape/tape_read.rs b/src/tape/tape_read.rs new file mode 100644 index 00000000..c1ba52e6 --- /dev/null +++ b/src/tape/tape_read.rs @@ -0,0 +1,45 @@ +use std::io::Read; + +/// Read trait for tape devices +/// +/// Normal Read, but allows to query additional status flags. +pub trait TapeRead: Read { + /// Return true if there is an "INCOMPLETE" mark at EOF + /// + /// Raises an error if you query this flag before reaching EOF. + fn is_incomplete(&self) -> Result; + + /// Return true if there is a file end marker before EOF + /// + /// Raises an error if you query this flag before reaching EOF. + fn has_end_marker(&self) -> Result; +} + +/// Read a single block from a tape device +/// +/// Assumes that 'reader' is a linux tape device. +/// +/// Return true on success, false on EOD +pub fn tape_device_read_block( + reader: &mut R, + buffer: &mut [u8], +) -> Result { + + loop { + match reader.read(buffer) { + Ok(0) => { return Ok(false); /* EOD */ } + Ok(count) => { + if count == buffer.len() { + return Ok(true); + } + proxmox::io_bail!("short block read ({} < {}). Tape drive uses wrong block size.", + count, buffer.len()); + } + // handle interrupted system call + Err(err) if err.kind() == std::io::ErrorKind::Interrupted => { + continue; + } + Err(err) => return Err(err), + } + } +}