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