From e2ec6fd2201dc0d9e193a38c6d360d345f217f9e Mon Sep 17 00:00:00 2001 From: Jeremy Soller <jackpot51@gmail.com> Date: Tue, 20 Sep 2016 16:57:45 -0600 Subject: [PATCH] Implement more system calls --- scheme/env.rs | 16 ++++++++++++++++ scheme/initfs.rs | 40 ++++++++++++++++++++++++++++------------ scheme/user.rs | 31 ++++++++++++++++++++----------- syscall/fs.rs | 37 +++++++++++++++++++++++++++++++++++++ syscall/mod.rs | 10 +++++++--- 5 files changed, 108 insertions(+), 26 deletions(-) diff --git a/scheme/env.rs b/scheme/env.rs index 8448cfe4..3f3f1f56 100644 --- a/scheme/env.rs +++ b/scheme/env.rs @@ -1,8 +1,10 @@ use collections::BTreeMap; +use core::cmp; use core::sync::atomic::{AtomicUsize, Ordering}; use spin::RwLock; use syscall::error::*; +use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END}; use syscall::scheme::Scheme; struct Handle { @@ -76,6 +78,20 @@ impl Scheme for EnvScheme { Ok(i) } + fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> { + let mut handles = self.handles.write(); + let mut 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) + } + fn fsync(&self, _file: usize) -> Result<usize> { Ok(0) } diff --git a/scheme/initfs.rs b/scheme/initfs.rs index 1380c6ea..84df203d 100644 --- a/scheme/initfs.rs +++ b/scheme/initfs.rs @@ -1,8 +1,10 @@ use collections::BTreeMap; +use core::cmp; use core::sync::atomic::{AtomicUsize, Ordering}; use spin::RwLock; use syscall::error::*; +use syscall::flag::{SEEK_SET, SEEK_CUR, SEEK_END}; use syscall::scheme::Scheme; struct Handle { @@ -48,29 +50,29 @@ impl Scheme for InitFsScheme { Ok(id) } - fn dup(&self, file: usize) -> Result<usize> { + fn dup(&self, id: usize) -> Result<usize> { let (data, seek) = { let handles = self.handles.read(); - let handle = handles.get(&file).ok_or(Error::new(EBADF))?; + let handle = handles.get(&id).ok_or(Error::new(EBADF))?; (handle.data, handle.seek) }; - let id = self.next_id.fetch_add(1, Ordering::SeqCst); - self.handles.write().insert(id, Handle { + let new_id = self.next_id.fetch_add(1, Ordering::SeqCst); + self.handles.write().insert(new_id, Handle { data: data, seek: seek }); - Ok(id) + Ok(new_id) } - fn read(&self, file: usize, buffer: &mut [u8]) -> Result<usize> { + fn read(&self, id: usize, buf: &mut [u8]) -> Result<usize> { let mut handles = self.handles.write(); - let mut handle = handles.get_mut(&file).ok_or(Error::new(EBADF))?; + let mut handle = handles.get_mut(&id).ok_or(Error::new(EBADF))?; let mut i = 0; - while i < buffer.len() && handle.seek < handle.data.len() { - buffer[i] = handle.data[handle.seek]; + while i < buf.len() && handle.seek < handle.data.len() { + buf[i] = handle.data[handle.seek]; i += 1; handle.seek += 1; } @@ -78,11 +80,25 @@ impl Scheme for InitFsScheme { Ok(i) } - fn fsync(&self, _file: usize) -> Result<usize> { + fn seek(&self, id: usize, pos: usize, whence: usize) -> Result<usize> { + let mut handles = self.handles.write(); + let mut 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) + } + + fn fsync(&self, _id: usize) -> Result<usize> { Ok(0) } - fn close(&self, file: usize) -> Result<usize> { - self.handles.write().remove(&file).ok_or(Error::new(EBADF)).and(Ok(0)) + fn close(&self, id: usize) -> Result<usize> { + self.handles.write().remove(&id).ok_or(Error::new(EBADF)).and(Ok(0)) } } diff --git a/scheme/user.rs b/scheme/user.rs index 9d9ae7e9..e5a01675 100644 --- a/scheme/user.rs +++ b/scheme/user.rs @@ -9,20 +9,11 @@ use arch::paging::{InactivePageTable, Page, VirtualAddress, entry}; use arch::paging::temporary_page::TemporaryPage; use context::{self, Context}; use context::memory::Grant; +use syscall::data::{Packet, Stat}; use syscall::error::*; use syscall::number::*; use syscall::scheme::Scheme; -#[derive(Copy, Clone, Debug, Default)] -#[repr(packed)] -pub struct Packet { - pub id: usize, - pub a: usize, - pub b: usize, - pub c: usize, - pub d: usize -} - pub struct UserInner { next_id: AtomicUsize, context: Weak<RwLock<Context>>, @@ -224,7 +215,20 @@ impl Scheme for UserScheme { fn write(&self, file: usize, buf: &[u8]) -> Result<usize> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; let address = inner.capture(buf)?; - let result = inner.call(SYS_WRITE, file, buf.as_ptr() as usize, buf.len()); + let result = inner.call(SYS_WRITE, file, address, buf.len()); + let _ = inner.release(address); + result + } + + fn seek(&self, file: usize, position: usize, whence: usize) -> Result<usize> { + let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; + inner.call(SYS_FSYNC, file, position, whence) + } + + fn fstat(&self, file: usize, stat: &mut Stat) -> Result<usize> { + let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; + let address = inner.capture_mut(stat)?; + let result = inner.call(SYS_FSTAT, file, address, 0); let _ = inner.release(address); result } @@ -234,6 +238,11 @@ impl Scheme for UserScheme { inner.call(SYS_FSYNC, file, 0, 0) } + fn ftruncate(&self, file: usize, len: usize) -> Result<usize> { + let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; + inner.call(SYS_FTRUNCATE, file, len, 0) + } + fn close(&self, file: usize) -> Result<usize> { let inner = self.inner.upgrade().ok_or(Error::new(ENODEV))?; inner.call(SYS_CLOSE, file, 0, 0) diff --git a/syscall/fs.rs b/syscall/fs.rs index a487019b..029222b7 100644 --- a/syscall/fs.rs +++ b/syscall/fs.rs @@ -2,6 +2,7 @@ use context; use scheme; +use syscall::data::Stat; use syscall::error::*; /// Change the current working directory @@ -97,6 +98,24 @@ pub fn dup(fd: usize) -> Result<usize> { scheme.dup(file.number) } +/// Get information about the file +pub fn fstat(fd: usize, stat: &mut Stat) -> Result<usize> { + let file = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + let file = context.get_file(fd).ok_or(Error::new(EBADF))?; + file + }; + + let scheme = { + let schemes = scheme::schemes(); + let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; + scheme.clone() + }; + scheme.fstat(file.number, stat) +} + /// Sync the file descriptor pub fn fsync(fd: usize) -> Result<usize> { let file = { @@ -115,6 +134,24 @@ pub fn fsync(fd: usize) -> Result<usize> { scheme.fsync(file.number) } +/// Seek to an offset +pub fn lseek(fd: usize, pos: usize, whence: usize) -> Result<usize> { + let file = { + let contexts = context::contexts(); + let context_lock = contexts.current().ok_or(Error::new(ESRCH))?; + let context = context_lock.read(); + let file = context.get_file(fd).ok_or(Error::new(EBADF))?; + file + }; + + let scheme = { + let schemes = scheme::schemes(); + let scheme = schemes.get(file.scheme).ok_or(Error::new(EBADF))?; + scheme.clone() + }; + scheme.seek(file.number, pos, whence) +} + /// Read syscall pub fn read(fd: usize, buf: &mut [u8]) -> Result<usize> { let file = { diff --git a/syscall/mod.rs b/syscall/mod.rs index 70400e79..b37a056b 100644 --- a/syscall/mod.rs +++ b/syscall/mod.rs @@ -2,14 +2,16 @@ extern crate syscall; -pub use self::syscall::{error, number, scheme}; +pub use self::syscall::{data, error, flag, number, scheme}; -use self::error::{Error, Result, ENOSYS}; -use self::number::*; pub use self::fs::*; pub use self::process::*; pub use self::validate::*; +use self::data::Stat; +use self::error::{Error, Result, ENOSYS}; +use self::number::*; + /// Filesystem syscalls pub mod fs; @@ -32,7 +34,9 @@ pub extern fn syscall(a: usize, b: usize, c: usize, d: usize, e: usize, f: usize SYS_WAITPID => waitpid(b, c, d), SYS_EXECVE => exec(validate_slice(b as *const u8, c)?, validate_slice(d as *const [usize; 2], e)?), SYS_CHDIR => chdir(validate_slice(b as *const u8, c)?), + SYS_LSEEK => lseek(b, c, d), SYS_GETPID => getpid(), + SYS_FSTAT => fstat(b, &mut validate_slice_mut(b as *mut Stat, 1)?[0]), SYS_DUP => dup(b), SYS_BRK => brk(b), SYS_IOPL => iopl(b), -- GitLab