Add readv and writev
This commit is contained in:
		
							parent
							
								
									4c3f556c7d
								
							
						
					
					
						commit
						f2ebc5c330
					
				| @ -8,8 +8,9 @@ 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 writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error>; | ||||||
|     //pub seek(&mut self, ) -> Result<usize, Error>;
 |     //pub seek(&mut self, ) -> Result<usize, Error>;
 | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| pub type FileRef = Arc<Box<File>>; | pub type FileRef = Arc<Box<File>>; | ||||||
| @ -48,6 +49,18 @@ impl File for SgxFile { | |||||||
|         let inner = inner_guard.borrow_mut(); |         let inner = inner_guard.borrow_mut(); | ||||||
|         inner.write(buf) |         inner.write(buf) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error> { | ||||||
|  |         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<usize, Error> { | ||||||
|  |         let mut inner_guard = self.inner.lock().unwrap(); | ||||||
|  |         let inner = inner_guard.borrow_mut(); | ||||||
|  |         inner.writev(bufs) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #[derive(Clone)] | #[derive(Clone)] | ||||||
| @ -67,6 +80,7 @@ impl SgxFileInner { | |||||||
|         let file = file_guard.borrow_mut(); |         let file = file_guard.borrow_mut(); | ||||||
| 
 | 
 | ||||||
|         let seek_pos = SeekFrom::Start(self.pos as u64); |         let seek_pos = SeekFrom::Start(self.pos as u64); | ||||||
|  |         // 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"))?; | ||||||
| 
 | 
 | ||||||
| @ -95,6 +109,70 @@ impl SgxFileInner { | |||||||
|         self.pos += read_len; |         self.pos += read_len; | ||||||
|         Ok(read_len) |         Ok(read_len) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     pub fn writev<'a, 'b>(&mut self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> { | ||||||
|  |         let mut file_guard = self.file.lock().unwrap(); | ||||||
|  |         let file = file_guard.borrow_mut(); | ||||||
|  | 
 | ||||||
|  |         let seek_pos = SeekFrom::Start(self.pos as u64); | ||||||
|  |         file.seek(seek_pos).map_err( | ||||||
|  |             |e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; | ||||||
|  | 
 | ||||||
|  |         let mut total_bytes = 0; | ||||||
|  |         for buf in bufs { | ||||||
|  |             match file.write(buf) { | ||||||
|  |                 Ok(this_bytes) => { | ||||||
|  |                     if this_bytes == 0 { break; } | ||||||
|  | 
 | ||||||
|  |                     total_bytes += this_bytes; | ||||||
|  |                     if this_bytes < buf.len() { break; } | ||||||
|  |                 } | ||||||
|  |                 Err(e) => { | ||||||
|  |                     match total_bytes { | ||||||
|  |                         // a complete failure
 | ||||||
|  |                         0 => return Err(Error::new(Errno::EINVAL, "Failed to write")), | ||||||
|  |                         // a partially failure
 | ||||||
|  |                         _ => break, | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         self.pos += total_bytes; | ||||||
|  |         Ok(total_bytes) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn readv<'a, 'b>(&mut self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error> { | ||||||
|  |         let mut file_guard = self.file.lock().unwrap(); | ||||||
|  |         let file = file_guard.borrow_mut(); | ||||||
|  | 
 | ||||||
|  |         let seek_pos = SeekFrom::Start(self.pos as u64); | ||||||
|  |         file.seek(seek_pos).map_err( | ||||||
|  |             |e| Error::new(Errno::EINVAL, "Failed to seek to a position"))?; | ||||||
|  | 
 | ||||||
|  |         let mut total_bytes = 0; | ||||||
|  |         for buf in bufs { | ||||||
|  |             match file.read(buf) { | ||||||
|  |                 Ok(this_bytes) => { | ||||||
|  |                     if this_bytes == 0 { break; } | ||||||
|  | 
 | ||||||
|  |                     total_bytes += this_bytes; | ||||||
|  |                     if this_bytes < buf.len() { break; } | ||||||
|  |                 } | ||||||
|  |                 Err(e) => { | ||||||
|  |                     match total_bytes { | ||||||
|  |                         // a complete failure
 | ||||||
|  |                         0 => return Err(Error::new(Errno::EINVAL, "Failed to write")), | ||||||
|  |                         // a partially failure
 | ||||||
|  |                         _ => break, | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         self.pos += total_bytes; | ||||||
|  |         Ok(total_bytes) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| unsafe impl Send for SgxFileInner {} | unsafe impl Send for SgxFileInner {} | ||||||
| @ -130,6 +208,33 @@ impl File for StdoutFile { | |||||||
|     fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { |     fn read(&self, buf: &mut [u8]) -> Result<usize, Error> { | ||||||
|         Err(Error::new(Errno::EBADF, "Stdout does not support reading")) |         Err(Error::new(Errno::EBADF, "Stdout does not support reading")) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> { | ||||||
|  |         let mut guard = self.inner.lock(); | ||||||
|  |         let mut total_bytes = 0; | ||||||
|  |         for buf in bufs { | ||||||
|  |             match guard.write(buf) { | ||||||
|  |                 Ok(this_len) => { | ||||||
|  |                     if this_len == 0 { break; } | ||||||
|  |                     total_bytes += this_len; | ||||||
|  |                     if this_len < buf.len() { break; } | ||||||
|  |                 } | ||||||
|  |                 Err(e) => { | ||||||
|  |                     match total_bytes { | ||||||
|  |                         // a complete failure
 | ||||||
|  |                         0 => return Err(Error::new(Errno::EINVAL, "Failed to write")), | ||||||
|  |                         // a partially failure
 | ||||||
|  |                         _ => break, | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Ok(total_bytes) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error> { | ||||||
|  |         Err(Error::new(Errno::EBADF, "Stdout does not support reading")) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Debug for StdoutFile { | impl Debug for StdoutFile { | ||||||
| @ -165,6 +270,33 @@ 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 reading")) | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     fn readv<'a, 'b>(&self, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, Error> { | ||||||
|  |         let mut guard = self.inner.lock(); | ||||||
|  |         let mut total_bytes = 0; | ||||||
|  |         for buf in bufs { | ||||||
|  |             match guard.read(buf) { | ||||||
|  |                 Ok(this_len) => { | ||||||
|  |                     if this_len == 0 { break; } | ||||||
|  |                     total_bytes += this_len; | ||||||
|  |                     if this_len < buf.len() { break; } | ||||||
|  |                 } | ||||||
|  |                 Err(e) => { | ||||||
|  |                     match total_bytes { | ||||||
|  |                         // a complete failure
 | ||||||
|  |                         0 => return Err(Error::new(Errno::EINVAL, "Failed to write")), | ||||||
|  |                         // a partially failure
 | ||||||
|  |                         _ => break, | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |         Ok(total_bytes) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     fn writev<'a, 'b>(&self, bufs: &'a [&'b [u8]]) -> Result<usize, Error> { | ||||||
|  |         Err(Error::new(Errno::EBADF, "Stdin does not support reading")) | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| impl Debug for StdinFile { | impl Debug for StdinFile { | ||||||
|  | |||||||
| @ -63,6 +63,22 @@ pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> { | |||||||
|     file_ref.read(buf) |     file_ref.read(buf) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | pub fn do_writev<'a, 'b>(fd: FileDesc, bufs: &'a [&'b [u8]]) -> Result<usize, 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_write]"))?; | ||||||
|  |     file_ref.writev(bufs) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | pub fn do_readv<'a, 'b>(fd: FileDesc, bufs: &'a mut [&'b mut [u8]]) -> Result<usize, 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_read]"))?; | ||||||
|  |     file_ref.readv(bufs) | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 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(); | ||||||
|  | |||||||
| @ -77,6 +77,7 @@ pub fn do_spawn<P: AsRef<Path>>(elf_path: &P, argv: &[CString], envp: &[CString] | |||||||
|             //let stdin = Arc::new(SgxMutex::new(Box::new(StdinFile::new())));
 |             //let stdin = Arc::new(SgxMutex::new(Box::new(StdinFile::new())));
 | ||||||
|             let stdin : Arc<Box<File>> = Arc::new(Box::new(StdinFile::new())); |             let stdin : Arc<Box<File>> = Arc::new(Box::new(StdinFile::new())); | ||||||
|             let stdout : Arc<Box<File>> = Arc::new(Box::new(StdoutFile::new())); |             let stdout : Arc<Box<File>> = Arc::new(Box::new(StdoutFile::new())); | ||||||
|  |             // TODO: implement and use a real stderr
 | ||||||
|             let stderr = stdout.clone(); |             let stderr = stdout.clone(); | ||||||
|             file_table.put(stdin); |             file_table.put(stdin); | ||||||
|             file_table.put(stdout); |             file_table.put(stdout); | ||||||
|  | |||||||
| @ -4,6 +4,8 @@ | |||||||
| #include <sys/types.h> | #include <sys/types.h> | ||||||
| #include "syscall_nr.h" | #include "syscall_nr.h" | ||||||
| 
 | 
 | ||||||
|  | struct iovec; | ||||||
|  | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| extern "C" { | extern "C" { | ||||||
| #endif | #endif | ||||||
| @ -12,6 +14,8 @@ extern int occlum_open(const char* path, int flags, int mode); | |||||||
| extern int occlum_close(int fd); | extern int occlum_close(int fd); | ||||||
| extern ssize_t occlum_read(int fd, void* buf, size_t size); | 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_writev(int fd, const struct iovec* iov, int count); | ||||||
| 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); | ||||||
|  | |||||||
| @ -5,18 +5,33 @@ use std::ffi::{CStr, CString}; | |||||||
| //use std::libc_fs as fs;
 | //use std::libc_fs as fs;
 | ||||||
| //use std::libc_io as io;
 | //use std::libc_io as io;
 | ||||||
| 
 | 
 | ||||||
| fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<*const T, Error> { | #[allow(non_camel_case_types)] | ||||||
|     Ok(user_ptr) | pub struct iovec_t { | ||||||
|  |     base: *const c_void, | ||||||
|  |     len: size_t, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn check_mut_ptr_from_user<T>(user_ptr: *mut T) -> Result<*mut T, Error> { | 
 | ||||||
|     Ok(user_ptr) | fn check_ptr_from_user<T>(user_ptr: *const T) -> Result<(), Error> { | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn check_mut_ptr_from_user<T>(user_ptr: *mut T) -> Result<(), Error> { | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn check_array_from_user<T>(user_buf: *const T, count: usize) -> Result<(), Error> { | ||||||
|  |     Ok(()) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn check_mut_array_from_user<T>(user_buf: *mut T, count: usize) -> Result<(), Error> { | ||||||
|  |     Ok(()) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| fn clone_string_from_user_safely(user_ptr: *const c_char) | fn clone_string_from_user_safely(user_ptr: *const c_char) | ||||||
|     -> Result<String, Error> |     -> Result<String, Error> | ||||||
| { | { | ||||||
|     let user_ptr = check_ptr_from_user(user_ptr)?; |     check_ptr_from_user(user_ptr)?; | ||||||
|     let string = unsafe { |     let string = unsafe { | ||||||
|         CStr::from_ptr(user_ptr).to_string_lossy().into_owned() |         CStr::from_ptr(user_ptr).to_string_lossy().into_owned() | ||||||
|     }; |     }; | ||||||
| @ -31,6 +46,93 @@ fn clone_cstrings_from_user_safely(user_ptr: *const *const c_char) | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | fn do_read(fd: c_int, buf: *mut c_void, size: size_t) | ||||||
|  |     -> Result<size_t, Error> | ||||||
|  | { | ||||||
|  |     let fd = fd as file_table::FileDesc; | ||||||
|  |     let safe_buf = { | ||||||
|  |         let buf = buf as *mut u8; | ||||||
|  |         let size = size as usize; | ||||||
|  |         check_mut_array_from_user(buf, size)?; | ||||||
|  |         unsafe { std::slice::from_raw_parts_mut(buf, size) } | ||||||
|  |     }; | ||||||
|  |     fs::do_read(fd, safe_buf) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn do_write(fd: c_int, buf: *const c_void, size: size_t) | ||||||
|  |     -> Result<size_t, Error> | ||||||
|  | { | ||||||
|  |     let fd = fd as file_table::FileDesc; | ||||||
|  |     let safe_buf = { | ||||||
|  |         let buf = buf as *mut u8; | ||||||
|  |         let size = size as usize; | ||||||
|  |         check_array_from_user(buf, size)?; | ||||||
|  |         unsafe { std::slice::from_raw_parts(buf, size) } | ||||||
|  |     }; | ||||||
|  |     fs::do_write(fd, safe_buf) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn do_writev(fd: c_int, iov: *const iovec_t, count: c_int) | ||||||
|  |     -> Result<size_t, Error> | ||||||
|  | { | ||||||
|  |     let fd = fd as file_table::FileDesc; | ||||||
|  | 
 | ||||||
|  |     let count = { | ||||||
|  |         if count < 0 { | ||||||
|  |             return Err(Error::new(Errno::EINVAL, "Invalid count of iovec")); | ||||||
|  |         } | ||||||
|  |         count as usize | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     check_array_from_user(iov, count); | ||||||
|  |     let bufs_vec = { | ||||||
|  |         let mut bufs_vec = Vec::with_capacity(count); | ||||||
|  |         for iov_i in 0..count { | ||||||
|  |             let iov_ptr = unsafe { iov.offset(iov_i as isize) }; | ||||||
|  |             let iov = unsafe { &*iov_ptr }; | ||||||
|  |             let buf = unsafe { | ||||||
|  |                 std::slice::from_raw_parts(iov.base as * const u8, iov.len) | ||||||
|  |             }; | ||||||
|  |             bufs_vec[iov_i] = buf; | ||||||
|  |         } | ||||||
|  |         bufs_vec | ||||||
|  |     }; | ||||||
|  |     let bufs = &bufs_vec[..]; | ||||||
|  | 
 | ||||||
|  |     fs::do_writev(fd, bufs) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn do_readv(fd: c_int, iov: *mut iovec_t, count: c_int) | ||||||
|  |     -> Result<size_t, Error> | ||||||
|  | { | ||||||
|  |     let fd = fd as file_table::FileDesc; | ||||||
|  | 
 | ||||||
|  |     let count = { | ||||||
|  |         if count < 0 { | ||||||
|  |             return Err(Error::new(Errno::EINVAL, "Invalid count of iovec")); | ||||||
|  |         } | ||||||
|  |         count as usize | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     check_array_from_user(iov, count); | ||||||
|  |     let mut bufs_vec = { | ||||||
|  |         let mut bufs_vec = Vec::with_capacity(count); | ||||||
|  |         for iov_i in 0..count { | ||||||
|  |             let iov_ptr = unsafe { iov.offset(iov_i as isize) }; | ||||||
|  |             let iov = unsafe { &*iov_ptr }; | ||||||
|  |             let buf = unsafe { | ||||||
|  |                 std::slice::from_raw_parts_mut(iov.base as * mut u8, iov.len) | ||||||
|  |             }; | ||||||
|  |             bufs_vec[iov_i] = buf; | ||||||
|  |         } | ||||||
|  |         bufs_vec | ||||||
|  |     }; | ||||||
|  |     let bufs = &mut bufs_vec[..]; | ||||||
|  | 
 | ||||||
|  |     fs::do_readv(fd, bufs) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #[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 { | ||||||
| @ -60,10 +162,7 @@ pub extern "C" fn occlum_close(fd: c_int) -> c_int { | |||||||
| 
 | 
 | ||||||
| #[no_mangle] | #[no_mangle] | ||||||
| pub extern "C" fn occlum_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t { | pub extern "C" fn occlum_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssize_t { | ||||||
|     let buf = unsafe { |     match do_read(fd, buf, size) { | ||||||
|         std::slice::from_raw_parts_mut(buf as *mut u8, size as usize) |  | ||||||
|     }; |  | ||||||
|     match fs::do_read(fd as file_table::FileDesc, buf) { |  | ||||||
|         Ok(read_len) => { |         Ok(read_len) => { | ||||||
|             read_len as ssize_t |             read_len as ssize_t | ||||||
|         }, |         }, | ||||||
| @ -75,16 +174,7 @@ pub extern "C" fn occlum_read(fd: c_int, buf: * mut c_void, size: size_t) -> ssi | |||||||
| 
 | 
 | ||||||
| #[no_mangle] | #[no_mangle] | ||||||
| pub extern "C" fn occlum_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t { | pub extern "C" fn occlum_write(fd: c_int, buf: * const c_void, size: size_t) -> ssize_t { | ||||||
| /*    let str_from_c = unsafe {
 |     match do_write(fd, buf, size) { | ||||||
|         CStr::from_ptr(buf as * const i8).to_string_lossy().into_owned() |  | ||||||
|     }; |  | ||||||
|     println!("occlum_write: {}", str_from_c); |  | ||||||
|     size as ssize_t |  | ||||||
| */ |  | ||||||
|     let buf = unsafe { |  | ||||||
|         std::slice::from_raw_parts(buf as *const u8, size as usize) |  | ||||||
|     }; |  | ||||||
|     match fs::do_write(fd as file_table::FileDesc, buf) { |  | ||||||
|         Ok(write_len) => { |         Ok(write_len) => { | ||||||
|             write_len as ssize_t |             write_len as ssize_t | ||||||
|         }, |         }, | ||||||
| @ -94,6 +184,31 @@ pub extern "C" fn occlum_write(fd: c_int, buf: * const c_void, size: size_t) -> | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[no_mangle] | ||||||
|  | pub extern "C" fn occlum_readv(fd: c_int, iov: * mut iovec_t, count: c_int) -> ssize_t { | ||||||
|  |     match do_readv(fd, iov, count) { | ||||||
|  |         Ok(read_len) => { | ||||||
|  |             read_len as ssize_t | ||||||
|  |         }, | ||||||
|  |         Err(e) => { | ||||||
|  |             e.errno.as_retval() as ssize_t | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #[no_mangle] | ||||||
|  | pub extern "C" fn occlum_writev(fd: c_int, iov: * const iovec_t, count: c_int) -> ssize_t { | ||||||
|  |     match do_writev(fd, iov, count) { | ||||||
|  |         Ok(write_len) => { | ||||||
|  |             write_len as ssize_t | ||||||
|  |         }, | ||||||
|  |         Err(e) => { | ||||||
|  |             e.errno.as_retval() as ssize_t | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| #[no_mangle] | #[no_mangle] | ||||||
| pub extern "C" fn occlum_getpid() -> c_uint | pub extern "C" fn occlum_getpid() -> c_uint | ||||||
| { | { | ||||||
| @ -118,7 +233,7 @@ fn do_spawn(child_pid_ptr: *mut c_uint, | |||||||
|             envp: *const *const c_char) |             envp: *const *const c_char) | ||||||
|     -> Result<(), Error> |     -> Result<(), Error> | ||||||
| { | { | ||||||
|     let child_pid_ptr = check_mut_ptr_from_user(child_pid_ptr)?; |     check_mut_ptr_from_user(child_pid_ptr)?; | ||||||
|     let path = clone_string_from_user_safely(path)?; |     let path = clone_string_from_user_safely(path)?; | ||||||
|     let argv = clone_cstrings_from_user_safely(argv)?; |     let argv = clone_cstrings_from_user_safely(argv)?; | ||||||
|     let envp = clone_cstrings_from_user_safely(envp)?; |     let envp = clone_cstrings_from_user_safely(envp)?; | ||||||
|  | |||||||
| @ -40,6 +40,20 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long | |||||||
|         ret = occlum_read(fd, buf, buf_size); |         ret = occlum_read(fd, buf, buf_size); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  |     case SYS_writev: { | ||||||
|  |         DECL_SYSCALL_ARG(int, fd, arg0); | ||||||
|  |         DECL_SYSCALL_ARG(const struct iovec*, iov, arg1); | ||||||
|  |         DECL_SYSCALL_ARG(int, count, arg2); | ||||||
|  |         ret = occlum_writev(fd, iov, count); | ||||||
|  |         break; | ||||||
|  |     } | ||||||
|  |     case SYS_readv: { | ||||||
|  |         DECL_SYSCALL_ARG(int, fd, arg0); | ||||||
|  |         DECL_SYSCALL_ARG(struct iovec*, iov, arg1); | ||||||
|  |         DECL_SYSCALL_ARG(int, count, arg2); | ||||||
|  |         ret = occlum_readv(fd, iov, count); | ||||||
|  |         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