Add dup, dup2, and dup3
This commit is contained in:
parent
d40af94aaf
commit
77a18bbc4d
@ -13,13 +13,18 @@ extern "C" {
|
||||
extern int occlum_open(const char* path, int flags, int mode);
|
||||
extern int occlum_close(int fd);
|
||||
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_write(int fd, const void* buf, size_t size);
|
||||
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_pipe(int fds[2]);
|
||||
extern int occlum_pipe2(int fds[2], int flags);
|
||||
|
||||
extern int occlum_dup(int old_fd);
|
||||
extern int occlum_dup2(int old_fd, int new_fd);
|
||||
extern int occlum_dup3(int old_fd, int new_fd, int flags);
|
||||
|
||||
extern int occlum_spawn(int* child_pid, const char* path,
|
||||
const char** argv,
|
||||
const char** envp);
|
||||
|
@ -44,25 +44,45 @@ impl FileTable {
|
||||
min_free_fd as FileDesc
|
||||
}
|
||||
|
||||
pub fn get(&self, fd: FileDesc) -> Option<FileRef> {
|
||||
pub fn put_at(&mut self, fd: FileDesc, file: FileRef, close_on_spawn: bool) {
|
||||
let mut table = &mut self.table;
|
||||
let mut table_entry = Some(FileTableEntry::new(file, close_on_spawn));
|
||||
if fd as usize >= table.len() {
|
||||
table.resize(fd as usize + 1, None);
|
||||
}
|
||||
std::mem::swap(&mut table_entry, &mut table[fd as usize]);
|
||||
if table_entry.is_none() {
|
||||
self.num_fds += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, fd: FileDesc) -> Result<FileRef, Error> {
|
||||
if fd as usize >= self.table.len() {
|
||||
return None;
|
||||
return errno!(EBADF, "Invalid file descriptor");
|
||||
}
|
||||
|
||||
let table = &self.table;
|
||||
table[fd as usize].as_ref().map(|entry| entry.file.clone())
|
||||
match table[fd as usize].as_ref() {
|
||||
Some(table_entry) => Ok(table_entry.file.clone()),
|
||||
None => errno!(EBADF, "Invalid file descriptor"),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn del(&mut self, fd: FileDesc) -> Option<FileRef> {
|
||||
pub fn del(&mut self, fd: FileDesc) -> Result<FileRef, Error> {
|
||||
if fd as usize >= self.table.len() {
|
||||
return None;
|
||||
return errno!(EBADF, "Invalid file descriptor");
|
||||
}
|
||||
|
||||
let mut del_entry = None;
|
||||
let mut del_table_entry = None;
|
||||
let table = &mut self.table;
|
||||
std::mem::swap(&mut del_entry, &mut table[fd as usize]);
|
||||
self.num_fds -= 1;
|
||||
del_entry.map(|entry| entry.file)
|
||||
std::mem::swap(&mut del_table_entry, &mut table[fd as usize]);
|
||||
match del_table_entry {
|
||||
Some(del_table_entry) => {
|
||||
self.num_fds -= 1;
|
||||
Ok(del_table_entry.file)
|
||||
},
|
||||
None => errno!(EBADF, "Invalid file descriptor"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,40 +67,35 @@ pub fn do_open(path: &str, flags: u32, mode: u32) -> Result<FileDesc, Error> {
|
||||
pub fn do_write(fd: FileDesc, buf: &[u8]) -> Result<usize, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)
|
||||
.ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor [do_write]"))?;
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
file_ref.write(buf)
|
||||
}
|
||||
|
||||
pub fn do_read(fd: FileDesc, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)
|
||||
.ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor [do_read]"))?;
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
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.get_files().get(fd)
|
||||
.ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor [do_write]"))?;
|
||||
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<usize, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let current_process = current_ref.lock().unwrap();
|
||||
let file_ref = current_process.get_files().get(fd)
|
||||
.ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor [do_read]"))?;
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
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.get_files().get(fd)
|
||||
.ok_or_else(|| Error::new(Errno::EBADF, "Invalid file descriptor [do_lseek]"))?;
|
||||
let file_ref = current_process.get_files().get(fd)?;
|
||||
file_ref.seek(offset)
|
||||
}
|
||||
|
||||
@ -108,10 +103,8 @@ pub fn do_close(fd: FileDesc) -> Result<(), Error> {
|
||||
let current_ref = process::get_current();
|
||||
let mut current_process = current_ref.lock().unwrap();
|
||||
let file_table = current_process.get_files_mut();
|
||||
match file_table.del(fd) {
|
||||
Some(_) => Ok(()),
|
||||
None => Err(Error::new(Errno::EBADF, "Invalid file descriptor [do_close]")),
|
||||
}
|
||||
file_table.del(fd)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> {
|
||||
@ -127,3 +120,36 @@ pub fn do_pipe2(flags: u32) -> Result<[FileDesc; 2], Error> {
|
||||
close_on_spawn);
|
||||
Ok([reader_fd, writer_fd])
|
||||
}
|
||||
|
||||
pub fn do_dup(old_fd: FileDesc) -> Result<FileDesc, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
let file_table = current.get_files_mut();
|
||||
let file = file_table.get(old_fd)?;
|
||||
let new_fd = file_table.put(file, false);
|
||||
Ok(new_fd)
|
||||
}
|
||||
|
||||
pub fn do_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<FileDesc, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
let file_table = current.get_files_mut();
|
||||
let file = file_table.get(old_fd)?;
|
||||
if old_fd != new_fd {
|
||||
file_table.put_at(new_fd, file, false);
|
||||
}
|
||||
Ok(new_fd)
|
||||
}
|
||||
|
||||
pub fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<FileDesc, Error> {
|
||||
let current_ref = process::get_current();
|
||||
let mut current = current_ref.lock().unwrap();
|
||||
let file_table = current.get_files_mut();
|
||||
let file = file_table.get(old_fd)?;
|
||||
if old_fd == new_fd {
|
||||
return errno!(EINVAL, "old_fd must not be equal to new_fd");
|
||||
}
|
||||
let close_on_spawn = flags & O_CLOEXEC != 0;
|
||||
file_table.put_at(new_fd, file, close_on_spawn);
|
||||
Ok(new_fd)
|
||||
}
|
||||
|
@ -195,6 +195,43 @@ fn do_brk(new_brk_addr: *const c_void) -> Result<*const c_void, Error> {
|
||||
vm::do_brk(new_brk_addr).map(|ret_brk_addr| ret_brk_addr as *const c_void)
|
||||
}
|
||||
|
||||
fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> {
|
||||
if _exit_status != 0 as *mut c_int {
|
||||
check_mut_ptr_from_user(_exit_status)?;
|
||||
}
|
||||
|
||||
let child_process_filter = match pid {
|
||||
pid if pid < -1 => {
|
||||
process::ChildProcessFilter::WithPGID((-pid) as pid_t)
|
||||
},
|
||||
-1 => {
|
||||
process::ChildProcessFilter::WithAnyPID
|
||||
},
|
||||
0 => {
|
||||
let gpid = process::do_getgpid();
|
||||
process::ChildProcessFilter::WithPGID(gpid)
|
||||
},
|
||||
pid if pid > 0 => {
|
||||
process::ChildProcessFilter::WithPID(pid as pid_t)
|
||||
},
|
||||
_ => {
|
||||
panic!("THIS SHOULD NEVER HAPPEN!");
|
||||
}
|
||||
};
|
||||
let mut exit_status = 0;
|
||||
match process::do_wait4(&child_process_filter, &mut exit_status) {
|
||||
Ok(pid) => {
|
||||
if _exit_status != 0 as *mut c_int {
|
||||
unsafe { *_exit_status = exit_status; }
|
||||
}
|
||||
Ok(pid)
|
||||
}
|
||||
Err(e) => {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn do_pipe2(fds_u: *mut c_int, flags: c_int) -> Result<(), Error> {
|
||||
check_mut_array_from_user(fds_u, 2)?;
|
||||
// TODO: how to deal with open flags???
|
||||
@ -405,43 +442,6 @@ pub extern "C" fn occlum_spawn(
|
||||
}
|
||||
}
|
||||
|
||||
fn do_wait4(pid: c_int, _exit_status: *mut c_int) -> Result<pid_t, Error> {
|
||||
if _exit_status != 0 as *mut c_int {
|
||||
check_mut_ptr_from_user(_exit_status)?;
|
||||
}
|
||||
|
||||
let child_process_filter = match pid {
|
||||
pid if pid < -1 => {
|
||||
process::ChildProcessFilter::WithPGID((-pid) as pid_t)
|
||||
},
|
||||
-1 => {
|
||||
process::ChildProcessFilter::WithAnyPID
|
||||
},
|
||||
0 => {
|
||||
let gpid = process::do_getgpid();
|
||||
process::ChildProcessFilter::WithPGID(gpid)
|
||||
},
|
||||
pid if pid > 0 => {
|
||||
process::ChildProcessFilter::WithPID(pid as pid_t)
|
||||
},
|
||||
_ => {
|
||||
panic!("THIS SHOULD NEVER HAPPEN!");
|
||||
}
|
||||
};
|
||||
let mut exit_status = 0;
|
||||
match process::do_wait4(&child_process_filter, &mut exit_status) {
|
||||
Ok(pid) => {
|
||||
if _exit_status != 0 as *mut c_int {
|
||||
unsafe { *_exit_status = exit_status; }
|
||||
}
|
||||
Ok(pid)
|
||||
}
|
||||
Err(e) => {
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_wait4(child_pid: c_int, exit_status: *mut c_int,
|
||||
options: c_int/*, rusage: *mut Rusage*/) -> c_int
|
||||
@ -455,3 +455,50 @@ pub extern "C" fn occlum_wait4(child_pid: c_int, exit_status: *mut c_int,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_dup(old_fd: c_int) -> c_int
|
||||
{
|
||||
let old_fd = old_fd as FileDesc;
|
||||
match fs::do_dup(old_fd) {
|
||||
Ok(new_fd) => {
|
||||
new_fd as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_dup2(old_fd: c_int, new_fd: c_int)
|
||||
-> c_int
|
||||
{
|
||||
let old_fd = old_fd as FileDesc;
|
||||
let new_fd = new_fd as FileDesc;
|
||||
match fs::do_dup2(old_fd, new_fd) {
|
||||
Ok(new_fd) => {
|
||||
new_fd as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn occlum_dup3(old_fd: c_int, new_fd: c_int, flags: c_int)
|
||||
-> c_int
|
||||
{
|
||||
let old_fd = old_fd as FileDesc;
|
||||
let new_fd = new_fd as FileDesc;
|
||||
let flags = flags as u32;
|
||||
match fs::do_dup3(old_fd, new_fd, flags) {
|
||||
Ok(new_fd) => {
|
||||
new_fd as c_int
|
||||
}
|
||||
Err(e) => {
|
||||
e.errno.as_retval()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -125,6 +125,24 @@ long dispatch_syscall(int num, long arg0, long arg1, long arg2, long arg3, long
|
||||
ret = (long) occlum_pipe2(fds, flags);
|
||||
break;
|
||||
}
|
||||
case SYS_dup: {
|
||||
DECL_SYSCALL_ARG(int, old_fd, arg0);
|
||||
ret = (long) occlum_dup(old_fd);
|
||||
break;
|
||||
}
|
||||
case SYS_dup2: {
|
||||
DECL_SYSCALL_ARG(int, old_fd, arg0);
|
||||
DECL_SYSCALL_ARG(int, new_fd, arg1);
|
||||
ret = (long) occlum_dup2(old_fd, new_fd);
|
||||
break;
|
||||
}
|
||||
case SYS_dup3: {
|
||||
DECL_SYSCALL_ARG(int, old_fd, arg0);
|
||||
DECL_SYSCALL_ARG(int, new_fd, arg1);
|
||||
DECL_SYSCALL_ARG(int, flags, arg2);
|
||||
ret = (long) occlum_dup3(old_fd, new_fd, flags);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ret = occlum_unknown(num);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user