Add lseek
This commit is contained in:
parent
f2ebc5c330
commit
10e3da87cc
@ -3,14 +3,13 @@ use {std};
|
|||||||
use std::{fmt};
|
use std::{fmt};
|
||||||
|
|
||||||
use std::sgxfs as fs_impl;
|
use std::sgxfs as fs_impl;
|
||||||
use std::io::{Read, Write, Seek, SeekFrom};
|
|
||||||
|
|
||||||
pub trait File : Debug + Sync + Send {
|
pub trait File : Debug + Sync + Send {
|
||||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error>;
|
fn read(&self, buf: &mut [u8]) -> Result<usize, Error>;
|
||||||
fn write(&self, buf: &[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 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>;
|
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>>;
|
pub type FileRef = Arc<Box<File>>;
|
||||||
@ -23,9 +22,14 @@ pub struct SgxFile {
|
|||||||
|
|
||||||
impl SgxFile {
|
impl SgxFile {
|
||||||
pub fn new(file: Arc<SgxMutex<fs_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 {
|
inner: SgxMutex::new(SgxFileInner {
|
||||||
pos: 0 as usize,
|
pos: 0 as usize,
|
||||||
file: file,
|
file: file,
|
||||||
@ -33,7 +37,7 @@ impl SgxFile {
|
|||||||
is_writable,
|
is_writable,
|
||||||
is_append,
|
is_append,
|
||||||
}),
|
}),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,6 +65,12 @@ impl File for SgxFile {
|
|||||||
let inner = inner_guard.borrow_mut();
|
let inner = inner_guard.borrow_mut();
|
||||||
inner.writev(bufs)
|
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)]
|
#[derive(Clone)]
|
||||||
@ -76,10 +86,18 @@ struct SgxFileInner {
|
|||||||
|
|
||||||
impl SgxFileInner {
|
impl SgxFileInner {
|
||||||
pub fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
|
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 mut file_guard = self.file.lock().unwrap();
|
||||||
let file = file_guard.borrow_mut();
|
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
|
// TODO: recover from error
|
||||||
file.seek(seek_pos).map_err(
|
file.seek(seek_pos).map_err(
|
||||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
|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"))?
|
|e| Error::new(Errno::EINVAL, "Failed to write"))?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if !self.is_append {
|
||||||
self.pos += write_len;
|
self.pos += write_len;
|
||||||
|
}
|
||||||
Ok(write_len)
|
Ok(write_len)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
|
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 mut file_guard = self.file.lock().unwrap();
|
||||||
let file = file_guard.borrow_mut();
|
let file = file_guard.borrow_mut();
|
||||||
|
|
||||||
@ -110,11 +134,50 @@ impl SgxFileInner {
|
|||||||
Ok(read_len)
|
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 mut file_guard = self.file.lock().unwrap();
|
||||||
let file = file_guard.borrow_mut();
|
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(
|
file.seek(seek_pos).map_err(
|
||||||
|e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?;
|
|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> {
|
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 mut file_guard = self.file.lock().unwrap();
|
||||||
let file = file_guard.borrow_mut();
|
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> {
|
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> {
|
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> {
|
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_TRUNC : u32 = 0x00000200;
|
||||||
pub const O_APPEND : u32 = 0x00000400;
|
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> {
|
pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||||
let open_options = {
|
let open_options = {
|
||||||
let mut open_options = fs_impl::OpenOptions::new();
|
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 mut sgx_file = {
|
||||||
let key : sgx_key_128bit_t = [0 as uint8_t; 16];
|
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)
|
let sgx_file = open_options.open_ex(path, &key)
|
||||||
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file") )?;
|
.map_err(|e| (Errno::ENOENT, "Failed to open the SGX-protected file") )?;
|
||||||
Arc::new(SgxMutex::new(sgx_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_writable = (flags & O_WRONLY != 0) || (flags & O_RDWR != 0);
|
||||||
let is_append = (flags & O_APPEND != 0);
|
let is_append = (flags & O_APPEND != 0);
|
||||||
let file_ref : Arc<Box<File>> = Arc::new(Box::new(
|
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 current_ref = process::get_current();
|
||||||
let mut current_process = current_ref.lock().unwrap();
|
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)
|
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> {
|
pub fn do_close(fd: FileDesc) -> Result<(), Error> {
|
||||||
let current_ref = process::get_current();
|
let current_ref = process::get_current();
|
||||||
let mut current_process = current_ref.lock().unwrap();
|
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::string::{String};
|
||||||
pub use std::collections::{HashMap, VecDeque};
|
pub use std::collections::{HashMap, VecDeque};
|
||||||
pub use std::fmt::{Debug, Display};
|
pub use std::fmt::{Debug, Display};
|
||||||
|
pub use std::io::{Read, Write, Seek, SeekFrom};
|
||||||
|
|
||||||
pub use errno::Error as Error;
|
pub use errno::Error as Error;
|
||||||
pub use errno::Errno;
|
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_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_readv(int fd, struct iovec* iov, int count);
|
||||||
extern ssize_t occlum_writev(int fd, const 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,
|
extern int occlum_spawn(int* child_pid, const char* path,
|
||||||
const char** argv,
|
const char** argv,
|
||||||
const char** envp);
|
const char** envp);
|
||||||
|
@ -11,7 +11,6 @@ pub struct iovec_t {
|
|||||||
len: size_t,
|
len: size_t,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<(), Error> {
|
fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<(), Error> {
|
||||||
Ok(())
|
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]
|
#[no_mangle]
|
||||||
pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
pub extern "C" fn occlum_open(path_buf: * const c_char, flags: c_int, mode: c_int) -> c_int {
|
||||||
let path = unsafe {
|
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]
|
#[no_mangle]
|
||||||
pub extern "C" fn occlum_getpid() -> c_uint
|
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);
|
ret = occlum_readv(fd, iov, count);
|
||||||
break;
|
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: {
|
case SYS_spawn: {
|
||||||
DECL_SYSCALL_ARG(int*, child_pid, arg0);
|
DECL_SYSCALL_ARG(int*, child_pid, arg0);
|
||||||
DECL_SYSCALL_ARG(const char*, path, arg1);
|
DECL_SYSCALL_ARG(const char*, path, arg1);
|
||||||
|
Loading…
Reference in New Issue
Block a user