Add lseek
This commit is contained in:
parent
f2ebc5c330
commit
10e3da87cc
@ -3,14 +3,13 @@ use {std};
|
||||
use std::{fmt};
|
||||
|
||||
use std::sgxfs as fs_impl;
|
||||
use std::io::{Read, Write, Seek, SeekFrom};
|
||||
|
||||
pub trait File : Debug + Sync + Send {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error>;
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error>;
|
||||
fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error>;
|
||||
fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error>;
|
||||
//pub seek(&mut self, ) -> Result<usize, Error>;
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error>;
|
||||
}
|
||||
|
||||
pub type FileRef = Arc<Box<File>>;
|
||||
@ -23,9 +22,14 @@ pub struct SgxFile {
|
||||
|
||||
impl SgxFile {
|
||||
pub fn new(file: Arc<SgxMutex<fs_impl::SgxFile>>,
|
||||
is_readable: bool, is_writable: bool, is_append: bool) -> SgxFile
|
||||
is_readable: bool, is_writable: bool, is_append: bool)
|
||||
-> Result<SgxFile, Error>
|
||||
{
|
||||
SgxFile {
|
||||
if !is_readable && !is_writable {
|
||||
return Err(Error::new(Errno::EINVAL, "Invalid permissions"));
|
||||
}
|
||||
|
||||
Ok(SgxFile {
|
||||
inner: SgxMutex::new(SgxFileInner {
|
||||
pos: 0 as usize,
|
||||
file: file,
|
||||
@ -33,7 +37,7 @@ impl SgxFile {
|
||||
is_writable,
|
||||
is_append,
|
||||
}),
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,6 +65,12 @@ impl File for SgxFile {
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.writev(bufs)
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
let mut inner_guard = self.inner.lock().unwrap();
|
||||
let inner = inner_guard.borrow_mut();
|
||||
inner.seek(pos)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -76,10 +86,18 @@ struct SgxFileInner {
|
||||
|
||||
impl SgxFileInner {
|
||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
||||
if !self.is_writable {
|
||||
return Err(Error::new(Errno::EINVAL, "File not writable"));
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let seek_pos = SeekFrom::Start(self.pos as u64);
|
||||
let seek_pos = if !self.is_append {
|
||||
SeekFrom::Start(self.pos as u64)
|
||||
} else {
|
||||
SeekFrom::End(0)
|
||||
};
|
||||
// TODO: recover from error
|
||||
file.seek(seek_pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
@ -89,11 +107,17 @@ impl SgxFileInner {
|
||||
|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||
};
|
||||
|
||||
self.pos += write_len;
|
||||
if !self.is_append {
|
||||
self.pos += write_len;
|
||||
}
|
||||
Ok(write_len)
|
||||
}
|
||||
|
||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
if !self.is_readable {
|
||||
return Err(Error::new(Errno::EINVAL, "File not readable"));
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
@ -110,11 +134,50 @@ impl SgxFileInner {
|
||||
Ok(read_len)
|
||||
}
|
||||
|
||||
pub fn writev<'a, 'b>(&mut self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> {
|
||||
pub fn seek(&mut self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let seek_pos = SeekFrom::Start(self.pos as u64);
|
||||
let pos = match pos {
|
||||
SeekFrom::Start(absolute_offset) => {
|
||||
pos
|
||||
}
|
||||
SeekFrom::End(relative_offset) => {
|
||||
pos
|
||||
}
|
||||
SeekFrom::Current(relative_offset) => {
|
||||
if relative_offset >= 0 {
|
||||
SeekFrom::Start((self.pos + relative_offset as usize) as u64)
|
||||
}
|
||||
else {
|
||||
let backward_offset = (-relative_offset) as usize;
|
||||
if self.pos < backward_offset { // underflow
|
||||
return Err(Error::new(Errno::EINVAL,
|
||||
"Invalid seek position"));
|
||||
}
|
||||
SeekFrom::Start((self.pos - backward_offset) as u64)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
self.pos = file.seek(pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))? as usize;
|
||||
Ok(self.pos as off_t)
|
||||
}
|
||||
|
||||
pub fn writev<'a, 'b>(&mut self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> {
|
||||
if !self.is_writable {
|
||||
return Err(Error::new(Errno::EINVAL, "File not writable"));
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
let seek_pos = if !self.is_append {
|
||||
SeekFrom::Start(self.pos as u64)
|
||||
} else {
|
||||
SeekFrom::End(0)
|
||||
};
|
||||
file.seek(seek_pos).map_err(
|
||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
||||
|
||||
@ -143,6 +206,10 @@ impl SgxFileInner {
|
||||
}
|
||||
|
||||
fn readv<'a, 'b>(&mut self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error> {
|
||||
if !self.is_readable {
|
||||
return Err(Error::new(Errno::EINVAL, "File not readable"));
|
||||
}
|
||||
|
||||
let mut file_guard = self.file.lock().unwrap();
|
||||
let file = file_guard.borrow_mut();
|
||||
|
||||
@ -233,7 +300,11 @@ impl File for StdoutFile {
|
||||
}
|
||||
|
||||
fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error> {
|
||||
Err(Error::new(Errno::EBADF, "Stdout does not support reading"))
|
||||
Err(Error::new(Errno::EBADF, "Stdout does not support read"))
|
||||
}
|
||||
|
||||
fn seek(&self, seek_pos: SeekFrom) -> Result<off_t, Error> {
|
||||
Err(Error::new(Errno::ESPIPE, "Stdout does not support seek"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -268,7 +339,11 @@ impl File for StdinFile {
|
||||
}
|
||||
|
||||
fn write(&self, buf: &[u8]) -> Result<usize, Error> {
|
||||
Err(Error::new(Errno::EBADF, "Stdin does not support reading"))
|
||||
Err(Error::new(Errno::EBADF, "Stdin does not support write"))
|
||||
}
|
||||
|
||||
fn seek(&self, pos: SeekFrom) -> Result<off_t, Error> {
|
||||
Err(Error::new(Errno::ESPIPE, "Stdin does not support seek"))
|
||||
}
|
||||
|
||||
fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error> {
|
||||
|
@ -12,6 +12,13 @@ pub const O_CREAT : u32 = 0x00000040;
|
||||
pub const O_TRUNC : u32 = 0x00000200;
|
||||
pub const O_APPEND : u32 = 0x00000400;
|
||||
|
||||
// TODO: use the type defined in Rust libc.
|
||||
//
|
||||
// However, off_t is defined as i64 in the current Rust SGX SDK, which is
|
||||
// wrong (see issue https://github.com/baidu/rust-sgx-sdk/issues/46)
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type off_t = i64;
|
||||
|
||||
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
let open_options = {
|
||||
let mut open_options = fs_impl::OpenOptions::new();
|
||||
@ -29,6 +36,7 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
|
||||
let mut sgx_file = {
|
||||
let key : sgx_key_128bit_t = [0 as uint8_t; 16];
|
||||
// TODO: what if two processes open the same underlying SGX file?
|
||||
let sgx_file = open_options.open_ex(path, &key)
|
||||
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file") )?;
|
||||
Arc::new(SgxMutex::new(sgx_file))
|
||||
@ -38,7 +46,7 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
let is_writable = (flags & O_WRONLY != 0) || (flags & O_RDWR != 0);
|
||||
let is_append = (flags & O_APPEND != 0);
|
||||
let file_ref : Arc<Box<File>> = Arc::new(Box::new(
|
||||
SgxFile::new(sgx_file, is_readable, is_writable, is_append)));
|
||||
SgxFile::new(sgx_file, is_readable, is_writable, is_append)?));
|
||||
|
||||
let current_ref = process::get_current();
|
||||
let mut current_process = current_ref.lock().unwrap();
|
||||
@ -79,6 +87,14 @@ pub fn do_readv<'a, 'b>(fd: FileDesc, bufs: &'a mut [&'b mut [u8]]) -> Result<us
|
||||
file_ref.readv(bufs)
|
||||
}
|
||||
|
||||
pub fn do_lseek<'a, 'b>(fd: FileDesc, offset: SeekFrom) -> Result<off_t, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.file_table.get(fd)
|
||||
.ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor [do_lseek]"))?;
|
||||
file_ref.seek(offset)
|
||||
}
|
||||
|
||||
pub fn do_close(fd: FileDesc) -> Result<(), Error> {
|
||||
let current_ref = process::get_current();
|
||||
let mut current_process = current_ref.lock().unwrap();
|
||||
|
@ -15,6 +15,9 @@ pub use std::vec::Vec;
|
||||
pub use std::string::{String};
|
||||
pub use std::collections::{HashMap, VecDeque};
|
||||
pub use std::fmt::{Debug, Display};
|
||||
pub use std::io::{Read, Write, Seek, SeekFrom};
|
||||
|
||||
pub use errno::Error as Error;
|
||||
pub use errno::Errno;
|
||||
|
||||
pub use fs::off_t;
|
||||
|
@ -16,6 +16,7 @@ extern ssize_t occlum_read(int fd, void* buf, size_t size);
|
||||
extern ssize_t occlum_write(int fd, const void* buf, size_t size);
|
||||
extern ssize_t occlum_readv(int fd, struct iovec* iov, int count);
|
||||
extern ssize_t occlum_writev(int fd, const struct iovec* iov, int count);
|
||||
extern off_t occlum_lseek(int fd, off_t offset, int whence);
|
||||
extern int occlum_spawn(int* child_pid, const char* path,
|
||||
const char** argv,
|
||||
const char** envp);
|
||||
|
@ -11,7 +11,6 @@ pub struct iovec_t {
|
||||
len: size_t,
|
||||
}
|
||||
|
||||
|
||||
fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<(), Error> {
|
||||
Ok(())
|
||||
}
|
||||
@ -133,6 +132,33 @@ fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int)
|
||||
}
|
||||
|
||||
|
||||
pub fn do_lseek(fd: c_int, offset: off_t, whence: c_int) -> Result<off_t, Error>
|
||||
{
|
||||
|
||||
let fd = fd as file_table::FileDesc;
|
||||
|
||||
let seek_from = match whence {
|
||||
0 => { // SEEK_SET
|
||||
if offset < 0 {
|
||||
return Err(Error::new(Errno::EINVAL, "Invalid offset"));
|
||||
}
|
||||
SeekFrom::Start(offset as u64)
|
||||
}
|
||||
1 => { // SEEK_CUR
|
||||
SeekFrom::Current(offset)
|
||||
}
|
||||
2 => { // SEEK_END
|
||||
SeekFrom::End(offset)
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::new(Errno::EINVAL, "Invalid whence"));
|
||||
}
|
||||
};
|
||||
|
||||
fs::do_lseek(fd, seek_from)
|
||||
}
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
||||
let path = unsafe {
|
||||
@ -208,6 +234,17 @@ pub extern "C" fn occlum_writev(fd: c_int, iov: * const iovec_t, count: c_int) -
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
|
||||
match do_lseek(fd, offset, whence) {
|
||||
Ok(ret) => {
|
||||
ret
|
||||
},
|
||||
Err(e) => {
|
||||
-1 as off_t // this special value indicates error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_getpid() -> c_uint
|
||||
|
@ -54,6 +54,13 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long
|
||||
ret = occlum_readv(fd, iov, count);
|
||||
break;
|
||||
}
|
||||
case SYS_lseek: {
|
||||
DECL_SYSCALL_ARG(int, fd, arg0);
|
||||
DECL_SYSCALL_ARG(off_t, offset, arg1);
|
||||
DECL_SYSCALL_ARG(int, whence, arg2);
|
||||
ret = occlum_lseek(fd, offset, whence);
|
||||
break;
|
||||
}
|
||||
case SYS_spawn: {
|
||||
DECL_SYSCALL_ARG(int*, child_pid, arg0);
|
||||
DECL_SYSCALL_ARG(const char*, path, arg1);
|
||||
|
Loading…
Reference in New Issue
Block a user