diff --git a/src/libos/src/fs/file.rs b/src/libos/src/fs/file.rs index 18259bc2..a237d330 100644 --- a/src/libos/src/fs/file.rs +++ b/src/libos/src/fs/file.rs @@ -2,12 +2,15 @@ use super::*; use std; use std::borrow::BorrowMut; use std::fmt; +use std::io::SeekFrom; pub trait File: Debug + Sync + Send { fn read(&self, buf: &mut [u8]) -> Result; fn write(&self, buf: &[u8]) -> Result; - fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result; - fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result; + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result; + fn write_at(&self, offset: usize, buf: &[u8]) -> Result; + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result; + fn writev(&self, bufs: &[&[u8]]) -> Result; fn seek(&self, pos: SeekFrom) -> Result; fn metadata(&self) -> Result; fn set_len(&self, len: u64) -> Result<(), Error>; @@ -60,13 +63,27 @@ impl File for SgxFile { inner.write(buf) } - fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + let mut inner_guard = self.inner.lock().unwrap(); + let inner = inner_guard.borrow_mut(); + inner.seek(SeekFrom::Start(offset as u64))?; + inner.read(buf) + } + + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + let mut inner_guard = self.inner.lock().unwrap(); + let inner = inner_guard.borrow_mut(); + inner.seek(SeekFrom::Start(offset as u64))?; + inner.write(buf) + } + + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.readv(bufs) } - fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { let mut inner_guard = self.inner.lock().unwrap(); let inner = inner_guard.borrow_mut(); inner.writev(bufs) @@ -287,6 +304,10 @@ impl StdoutFile { } impl File for StdoutFile { + fn read(&self, buf: &mut [u8]) -> Result { + Err(Error::new(Errno::EBADF, "Stdout does not support read")) + } + fn write(&self, buf: &[u8]) -> Result { let write_len = { self.inner @@ -297,11 +318,19 @@ impl File for StdoutFile { Ok(write_len) } - fn read(&self, buf: &mut [u8]) -> Result { + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + unimplemented!() + } + + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + unimplemented!() + } + + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { Err(Error::new(Errno::EBADF, "Stdout does not support read")) } - fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { let mut guard = self.inner.lock(); let mut total_bytes = 0; for buf in bufs { @@ -325,10 +354,6 @@ impl File for StdoutFile { Ok(total_bytes) } - fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result { - Err(Error::new(Errno::EBADF, "Stdout does not support read")) - } - fn seek(&self, seek_pos: SeekFrom) -> Result { Err(Error::new(Errno::ESPIPE, "Stdout does not support seek")) } @@ -390,11 +415,15 @@ impl File for StdinFile { Err(Error::new(Errno::EBADF, "Stdin does not support write")) } - fn seek(&self, pos: SeekFrom) -> Result { - Err(Error::new(Errno::ESPIPE, "Stdin does not support seek")) + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + unimplemented!() } - fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + unimplemented!() + } + + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut guard = self.inner.lock(); let mut total_bytes = 0; for buf in bufs { @@ -418,10 +447,14 @@ impl File for StdinFile { Ok(total_bytes) } - fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { Err(Error::new(Errno::EBADF, "Stdin does not support write")) } + fn seek(&self, pos: SeekFrom) -> Result { + Err(Error::new(Errno::ESPIPE, "Stdin does not support seek")) + } + fn metadata(&self) -> Result { unimplemented!() } diff --git a/src/libos/src/fs/inode_file.rs b/src/libos/src/fs/inode_file.rs index 416a6ead..0dac3a1f 100644 --- a/src/libos/src/fs/inode_file.rs +++ b/src/libos/src/fs/inode_file.rs @@ -53,6 +53,23 @@ impl File for INodeFile { Ok(len) } + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + if !self.options.read { + return Err(Error::new(Errno::EBADF, "File not readable")); + } + let len = self.inode.read_at(offset, buf)?; + Ok(len) + } + + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + if !self.options.write { + return Err(Error::new(Errno::EBADF, "File not writable")); + } + let len = self.inode.write_at(offset, buf)?; + Ok(len) + } + + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { Err(Error::new(Errno::ENOSYS, "Not implemented")) } diff --git a/src/libos/src/fs/mod.rs b/src/libos/src/fs/mod.rs index ced1aa9d..d1450bda 100644 --- a/src/libos/src/fs/mod.rs +++ b/src/libos/src/fs/mod.rs @@ -75,20 +75,34 @@ pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result { file_ref.read(buf) } -pub fn do_writev<'a, 'b>(fd: FileDesc, bufs: &'a [&'b [u8]]) -> Result { +pub fn do_writev(fd: FileDesc, bufs: &[&[u8]]) -> Result { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); let file_ref = current_process.get_files().get(fd)?; file_ref.writev(bufs) } -pub fn do_readv<'a, 'b>(fd: FileDesc, bufs: &'a mut [&'b mut [u8]]) -> Result { +pub fn do_readv(fd: FileDesc, bufs: &mut [&mut [u8]]) -> Result { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); let file_ref = current_process.get_files().get(fd)?; file_ref.readv(bufs) } +pub fn do_pwrite(fd: FileDesc, buf: &[u8], offset: usize) -> Result { + let current_ref = process::get_current(); + let current_process = current_ref.lock().unwrap(); + let file_ref = current_process.get_files().get(fd)?; + file_ref.write_at(offset, buf) +} + +pub fn do_pread(fd: FileDesc, buf: &mut [u8], offset: usize) -> Result { + let current_ref = process::get_current(); + let current_process = current_ref.lock().unwrap(); + let file_ref = current_process.get_files().get(fd)?; + file_ref.read_at(offset, buf) +} + pub fn do_stat(path: &str) -> Result { warn!("stat is partial implemented as lstat"); do_lstat(path) @@ -114,7 +128,7 @@ pub fn do_lstat(path: &str) -> Result { Ok(stat) } -pub fn do_lseek<'a, 'b>(fd: FileDesc, offset: SeekFrom) -> Result { +pub fn do_lseek(fd: FileDesc, offset: SeekFrom) -> Result { let current_ref = process::get_current(); let current_process = current_ref.lock().unwrap(); let file_ref = current_process.get_files().get(fd)?; diff --git a/src/libos/src/fs/pipe.rs b/src/libos/src/fs/pipe.rs index 75325e67..75cb77d9 100644 --- a/src/libos/src/fs/pipe.rs +++ b/src/libos/src/fs/pipe.rs @@ -36,7 +36,22 @@ impl File for PipeReader { ringbuf.read(buf) } - fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result { + fn write(&self, buf: &[u8]) -> Result { + Err(Error::new( + Errno::EBADF, + "PipeReader does not support write", + )) + } + + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + unimplemented!() + } + + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + unimplemented!() + } + + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { let mut ringbuf = self.inner.lock().unwrap(); let mut total_bytes = 0; for buf in bufs { @@ -60,14 +75,7 @@ impl File for PipeReader { Ok(total_bytes) } - fn write(&self, buf: &[u8]) -> Result { - Err(Error::new( - Errno::EBADF, - "PipeReader does not support write", - )) - } - - fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result { + fn writev(&self, bufs: &[&[u8]]) -> Result { Err(Error::new( Errno::EBADF, "PipeReader does not support write", @@ -108,12 +116,27 @@ pub struct PipeWriter { } impl File for PipeWriter { + fn read(&self, buf: &mut [u8]) -> Result { + Err(Error::new(Errno::EBADF, "PipeWriter does not support read")) + } + fn write(&self, buf: &[u8]) -> Result { let ringbuf = self.inner.lock().unwrap(); ringbuf.write(buf) } + fn read_at(&self, offset: usize, buf: &mut [u8]) -> Result { + unimplemented!() + } - fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result { + fn write_at(&self, offset: usize, buf: &[u8]) -> Result { + unimplemented!() + } + + fn readv(&self, bufs: &mut [&mut [u8]]) -> Result { + Err(Error::new(Errno::EBADF, "PipeWriter does not support read")) + } + + fn writev(&self, bufs: &[&[u8]]) -> Result { let ringbuf = self.inner.lock().unwrap(); let mut total_bytes = 0; for buf in bufs { @@ -137,14 +160,6 @@ impl File for PipeWriter { Ok(total_bytes) } - fn read(&self, buf: &mut [u8]) -> Result { - Err(Error::new(Errno::EBADF, "PipeWriter does not support read")) - } - - fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result { - Err(Error::new(Errno::EBADF, "PipeWriter does not support read")) - } - fn seek(&self, seek_pos: SeekFrom) -> Result { Err(Error::new(Errno::ESPIPE, "Pipe does not support seek")) } diff --git a/src/libos/src/syscall/mod.rs b/src/libos/src/syscall/mod.rs index 27d2431c..1de70a19 100644 --- a/src/libos/src/syscall/mod.rs +++ b/src/libos/src/syscall/mod.rs @@ -34,6 +34,8 @@ pub extern "C" fn dispatch_syscall( SYS_CLOSE => do_close(arg0 as FileDesc), SYS_READ => do_read(arg0 as FileDesc, arg1 as *mut u8, arg2 as usize), SYS_WRITE => do_write(arg0 as FileDesc, arg1 as *const u8, arg2 as usize), + SYS_PREAD64 => do_pread(arg0 as FileDesc, arg1 as *mut u8, arg2 as usize, arg3 as usize), + SYS_PWRITE64 => do_pwrite(arg0 as FileDesc, arg1 as *const u8, arg2 as usize, arg3 as usize), SYS_READV => do_readv(arg0 as FileDesc, arg1 as *mut iovec_t, arg2 as i32), SYS_WRITEV => do_writev(arg0 as FileDesc, arg1 as *mut iovec_t, arg2 as i32), SYS_STAT => do_stat(arg0 as *const i8, arg1 as *mut fs::Stat), @@ -250,6 +252,24 @@ fn do_readv(fd: FileDesc, iov: *mut iovec_t, count: i32) -> Result Ok(len as isize) } +fn do_pread(fd: FileDesc, buf: *mut u8, size: usize, offset: usize) -> Result { + let safe_buf = { + check_mut_array(buf, size)?; + unsafe { std::slice::from_raw_parts_mut(buf, size) } + }; + let len = fs::do_pread(fd, safe_buf, offset)?; + Ok(len as isize) +} + +fn do_pwrite(fd: FileDesc, buf: *const u8, size: usize, offset: usize) -> Result { + let safe_buf = { + check_array(buf, size)?; + unsafe { std::slice::from_raw_parts(buf, size) } + }; + let len = fs::do_pwrite(fd, safe_buf, offset)?; + Ok(len as isize) +} + fn do_stat(path: *const i8, stat_buf: *mut fs::Stat) -> Result { let path = clone_cstring_safely(path)?.to_string_lossy().into_owned(); check_mut_ptr(stat_buf)?;