change seek sig to match posix - signed pos and result

This commit is contained in:
Graham MacDonald
2020-06-10 23:22:02 +01:00
parent fcea6e06dd
commit 01f95b644d
9 changed files with 74 additions and 68 deletions

View File

@@ -11,13 +11,14 @@ use syscall::error::{EACCES, EBADF, EBADFD, EINVAL, EIO, EISDIR, ENOENT, ENOTDIR
use syscall::flag::{O_ACCMODE, O_DIRECTORY, O_RDWR, O_STAT, O_WRONLY};
use syscall::scheme::Scheme;
use syscall::{Error, Result};
use syscall::{MODE_DIR, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET};
use syscall::{MODE_DIR, MODE_FILE};
use spin::{Mutex, RwLock};
use crate::acpi::sdt::Sdt;
use crate::acpi::SdtSignature;
use crate::paging::ActivePageTable;
use crate::scheme::calc_seek_offset_usize;
#[derive(Clone, Copy)]
struct PhysSlice {
@@ -336,13 +337,13 @@ impl Scheme for AcpiScheme {
}
Ok(0)
}
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
let handles_guard = self.handles.read();
let mut handle = handles_guard.get(&id).ok_or(Error::new(EBADF))?.lock();
let (cur_offset, length) = match &*handle {
&Handle::TopLevel(offset) => (offset, TOPLEVEL_DIR_CONTENTS.len()),
&Handle::Tables(offset) => (offset, self.tables.len() * 35),
&Handle::Tables(offset) => (offset, (self.tables.len() * 35)),
&Handle::Table {
name,
oem_id,
@@ -355,16 +356,11 @@ impl Scheme for AcpiScheme {
.len,
),
};
let new_offset = match whence {
SEEK_CUR => core::cmp::min(cur_offset + pos, length),
SEEK_END => core::cmp::min(length + pos, length),
SEEK_SET => core::cmp::min(length, pos),
_ => return Err(Error::new(EINVAL)),
};
let new_offset = calc_seek_offset_usize(cur_offset, pos, whence, length)?;
match &mut *handle {
&mut Handle::Table { ref mut offset, .. }
| &mut Handle::Tables(ref mut offset)
| &mut Handle::TopLevel(ref mut offset) => *offset = new_offset,
| &mut Handle::TopLevel(ref mut offset) => *offset = new_offset as usize,
}
Ok(new_offset)
}

View File

@@ -1,11 +1,12 @@
use alloc::collections::BTreeMap;
use core::{cmp, str};
use core::str;
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::RwLock;
use crate::scheme::calc_seek_offset_usize;
use crate::syscall::data::Stat;
use crate::syscall::error::*;
use crate::syscall::flag::{MODE_DIR, MODE_FILE, SEEK_SET, SEEK_CUR, SEEK_END};
use crate::syscall::flag::{MODE_DIR, MODE_FILE};
use crate::syscall::scheme::Scheme;
#[cfg(test)]
@@ -77,18 +78,12 @@ impl Scheme for InitFsScheme {
Ok(i)
}
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
let mut handles = self.handles.write();
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
handle.seek = match whence {
SEEK_SET => cmp::min(handle.data.len(), pos),
SEEK_CUR => cmp::max(0, cmp::min(handle.data.len() as isize, handle.seek as isize + pos as isize)) as usize,
SEEK_END => cmp::max(0, cmp::min(handle.data.len() as isize, handle.data.len() as isize + pos as isize)) as usize,
_ => return Err(Error::new(EINVAL))
};
Ok(handle.seek)
let new_offset = calc_seek_offset_usize(handle.seek, pos, whence, handle.data.len())?;
handle.seek = new_offset as usize;
Ok(new_offset)
}
fn fcntl(&self, id: usize, _cmd: usize, _arg: usize) -> Result<usize> {

View File

@@ -12,9 +12,9 @@ use crate::arch::interrupt::{available_irqs_iter, bsp_apic_id, is_reserved, set_
use crate::event;
use crate::interrupt::irq::acknowledge;
use crate::scheme::{AtomicSchemeId, SchemeId};
use crate::scheme::{AtomicSchemeId, SchemeId, calc_seek_offset_usize};
use crate::syscall::error::*;
use crate::syscall::flag::{EventFlags, EVENT_READ, O_DIRECTORY, O_CREAT, O_STAT, MODE_CHR, MODE_DIR, SEEK_CUR, SEEK_END, SEEK_SET};
use crate::syscall::flag::{EventFlags, EVENT_READ, O_DIRECTORY, O_CREAT, O_STAT, MODE_CHR, MODE_DIR};
use crate::syscall::scheme::Scheme;
pub static IRQ_SCHEME_ID: AtomicSchemeId = AtomicSchemeId::default();
@@ -252,20 +252,15 @@ impl Scheme for IrqScheme {
}
}
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
let handles_guard = HANDLES.read();
let handle = handles_guard.as_ref().unwrap().get(&id).ok_or(Error::new(EBADF))?;
match handle {
&Handle::Avail(_, ref buf, ref offset) | &Handle::TopLevel(ref buf, ref offset) => {
let cur_offset = offset.load(Ordering::SeqCst);
let new_offset = match whence {
SEEK_CUR => core::cmp::min(cur_offset + pos, buf.len()),
SEEK_END => core::cmp::min(buf.len() + pos, buf.len()),
SEEK_SET => core::cmp::min(buf.len(), pos),
_ => return Err(Error::new(EINVAL)),
};
offset.store(new_offset, Ordering::SeqCst);
let new_offset = calc_seek_offset_usize(cur_offset, pos, whence, buf.len())?;
offset.store(new_offset as usize, Ordering::SeqCst);
Ok(new_offset)
}
_ => return Err(Error::new(ESPIPE)),

View File

@@ -10,11 +10,14 @@ use alloc::sync::Arc;
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use core::cmp;
use core::sync::atomic::AtomicUsize;
use core::convert::TryFrom;
use spin::{Once, RwLock, RwLockReadGuard, RwLockWriteGuard};
use crate::syscall::error::*;
use crate::syscall::scheme::Scheme;
use crate::syscall::flag::{SEEK_CUR, SEEK_END, SEEK_SET};
#[cfg(feature = "acpi")]
use self::acpi::AcpiScheme;
@@ -283,3 +286,32 @@ pub fn schemes() -> RwLockReadGuard<'static, SchemeList> {
pub fn schemes_mut() -> RwLockWriteGuard<'static, SchemeList> {
SCHEMES.call_once(init_schemes).write()
}
/// 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))
}
}

View File

@@ -142,7 +142,7 @@ impl Scheme for PipeScheme {
Ok(0)
}
fn seek(&self, _id: usize, _pos: usize, _whence: usize) -> Result<usize> {
fn seek(&self, _id: usize, _pos: isize, _whence: usize) -> Result<isize> {
Err(Error::new(ESPIPE))
}
}

View File

@@ -2,7 +2,7 @@ use crate::{
arch::paging::VirtualAddress,
context::{self, Context, ContextId, Status},
ptrace,
scheme::{AtomicSchemeId, SchemeId},
scheme::{AtomicSchemeId, SchemeId, calc_seek_offset_usize},
syscall::{
data::{FloatRegisters, IntRegisters, PtraceEvent},
error::*,
@@ -285,18 +285,13 @@ impl Scheme for ProcScheme {
self.open(&path, info.flags, uid, gid)
}
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
let mut handles = self.handles.write();
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
let mut memory = handle.data.mem_data().ok_or(Error::new(EBADF))?;
let value = match whence {
SEEK_SET => pos,
SEEK_CUR => cmp::max(0, memory.offset.get() as isize + pos as isize) as usize,
SEEK_END => cmp::max(0, isize::max_value() + pos as isize) as usize,
_ => return Err(Error::new(EBADF))
};
memory.offset = VirtualAddress::new(value);
let value = calc_seek_offset_usize(memory.offset.get(), pos, whence, isize::max_value() as usize)?;
memory.offset = VirtualAddress::new(value as usize);
Ok(value)
}

View File

@@ -2,7 +2,7 @@ use alloc::sync::Arc;
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use core::{cmp, str};
use core::str;
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::{Mutex, RwLock};
@@ -11,7 +11,7 @@ use crate::syscall::data::Stat;
use crate::syscall::error::*;
use crate::syscall::flag::{EventFlags, O_CREAT, MODE_FILE, MODE_DIR, SEEK_SET, SEEK_CUR, SEEK_END};
use crate::syscall::scheme::Scheme;
use crate::scheme::{self, SchemeNamespace, SchemeId};
use crate::scheme::{self, SchemeNamespace, SchemeId, calc_seek_offset_usize};
use crate::scheme::user::{UserInner, UserScheme};
struct FolderInner {
@@ -33,16 +33,11 @@ impl FolderInner {
Ok(i)
}
fn seek(&self, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, pos: isize, whence: usize) -> Result<isize> {
let mut seek = self.pos.lock();
*seek = match whence {
SEEK_SET => cmp::min(self.data.len(), pos),
SEEK_CUR => cmp::max(0, cmp::min(self.data.len() as isize, *seek as isize + pos as isize)) as usize,
SEEK_END => cmp::max(0, cmp::min(self.data.len() as isize, self.data.len() as isize + pos as isize)) as usize,
_ => return Err(Error::new(EINVAL))
};
Ok(*seek)
let new_offset = calc_seek_offset_usize(*seek, pos, whence, self.data.len())?;
*seek = new_offset as usize;
Ok(new_offset)
}
}
@@ -206,7 +201,7 @@ impl Scheme for RootScheme {
}
}
fn seek(&self, file: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, file: usize, pos: isize, whence: usize) -> Result<isize> {
let handle = {
let handles = self.handles.read();
let handle = handles.get(&file).ok_or(Error::new(EBADF))?;

View File

@@ -1,13 +1,14 @@
use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use alloc::vec::Vec;
use core::{cmp, str};
use core::str;
use core::sync::atomic::{AtomicUsize, Ordering};
use spin::RwLock;
use crate::scheme::calc_seek_offset_usize;
use crate::syscall::data::Stat;
use crate::syscall::error::{Error, EBADF, EINVAL, ENOENT, Result};
use crate::syscall::flag::{MODE_DIR, MODE_FILE, SEEK_CUR, SEEK_END, SEEK_SET};
use crate::syscall::error::{Error, EBADF, ENOENT, Result};
use crate::syscall::flag::{MODE_DIR, MODE_FILE};
use crate::syscall::scheme::Scheme;
use crate::arch::interrupt::irq;
@@ -118,18 +119,13 @@ impl Scheme for SysScheme {
Ok(i)
}
fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> {
fn seek(&self, id: usize, pos: isize, whence: usize) -> Result<isize> {
let mut handles = self.handles.write();
let handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?;
handle.seek = match whence {
SEEK_SET => cmp::min(handle.data.len(), pos),
SEEK_CUR => cmp::max(0, cmp::min(handle.data.len() as isize, handle.seek as isize + pos as isize)) as usize,
SEEK_END => cmp::max(0, cmp::min(handle.data.len() as isize, handle.data.len() as isize + pos as isize)) as usize,
_ => return Err(Error::new(EINVAL))
};
Ok(handle.seek)
let new_offset = calc_seek_offset_usize(handle.seek, pos, whence, handle.data.len())?;
handle.seek = new_offset as usize;
Ok(new_offset)
}
fn fpath(&self, id: usize, buf: &mut [u8]) -> Result<usize> {

View File

@@ -3,6 +3,7 @@ use alloc::boxed::Box;
use alloc::collections::BTreeMap;
use core::sync::atomic::{AtomicBool, AtomicU64, Ordering};
use core::{mem, slice, usize};
use core::convert::TryFrom;
use spin::{Mutex, RwLock};
use crate::context::{self, Context};
@@ -334,9 +335,10 @@ impl Scheme for UserScheme {
result
}
fn seek(&self, file: usize, position: usize, whence: usize) -> Result<usize> {
fn seek(&self, file: usize, position: isize, whence: usize) -> Result<isize> {
let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?;
inner.call(SYS_LSEEK, file, position, whence)
let new_offset = inner.call(SYS_LSEEK, file, position as usize, whence)?;
isize::try_from(new_offset).or_else(|_| Err(Error::new(EOVERFLOW)))
}
fn fchmod(&self, file: usize, mode: u16) -> Result<usize> {