From 940f3f1e305c62e73a76677afcde1b9630e27453 Mon Sep 17 00:00:00 2001 From: Graham MacDonald <grahamamacdonald@gmail.com> Date: Fri, 19 Jun 2020 23:53:05 +0100 Subject: [PATCH] move calc_seek_offset* to syscall --- src/scheme/mod.rs | 2 ++ src/scheme/seek.rs | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/scheme/seek.rs diff --git a/src/scheme/mod.rs b/src/scheme/mod.rs index 66f8fc7..be548bd 100644 --- a/src/scheme/mod.rs +++ b/src/scheme/mod.rs @@ -2,8 +2,10 @@ pub use self::scheme::Scheme; pub use self::scheme_mut::SchemeMut; pub use self::scheme_block::SchemeBlock; pub use self::scheme_block_mut::SchemeBlockMut; +pub use self::seek::*; mod scheme; mod scheme_mut; mod scheme_block; mod scheme_block_mut; +mod seek; diff --git a/src/scheme/seek.rs b/src/scheme/seek.rs new file mode 100644 index 0000000..09a4518 --- /dev/null +++ b/src/scheme/seek.rs @@ -0,0 +1,33 @@ +use core::cmp; +use core::convert::TryFrom; +use crate::error::*; +use crate::flag::*; + +/// Helper for seek calls +/// In most cases it's easier to use a usize to track the offset and buffer size internally, +/// but the seek interface uses isize. This wrapper ensures EOVERFLOW errors are returned +/// as appropriate if the value in the usize can't fit in the isize. +pub fn calc_seek_offset_usize(cur_offset: usize, pos: isize, whence: usize, buf_len: usize) -> Result<isize> { + let cur_offset = isize::try_from(cur_offset).or_else(|_| Err(Error::new(EOVERFLOW)))?; + let buf_len = isize::try_from(buf_len).or_else(|_| Err(Error::new(EOVERFLOW)))?; + calc_seek_offset_isize(cur_offset, pos, whence, buf_len) +} + +/// Helper for seek calls +/// Result is guaranteed to be positive. +/// EOVERFLOW returned if the arguments would cause an overflow. +/// EINVAL returned if the new offset is out of bounds. +pub fn calc_seek_offset_isize(cur_offset: isize, pos: isize, whence: usize, buf_len: isize) -> Result<isize> { + let new_offset = match whence { + SEEK_CUR => pos.checked_add(cur_offset), + SEEK_END => pos.checked_add(buf_len), + SEEK_SET => Some(pos), + _ => None, + }; + + match new_offset { + Some(new_offset) if new_offset < 0 => Err(Error::new(EINVAL)), + Some(new_offset) => Ok(cmp::min(new_offset, buf_len)), + None => Err(Error::new(EOVERFLOW)) + } +} \ No newline at end of file -- GitLab