Skip to content
Snippets Groups Projects
Commit e2ec6fd2 authored by Jeremy Soller's avatar Jeremy Soller
Browse files

Implement more system calls

parent 4ee9a6b4
No related branches found
No related tags found
No related merge requests found
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)
}
......
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))
}
}
......@@ -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)
......
......@@ -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 = {
......
......@@ -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),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment