Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add sys_dup2 and sys_dup3 #53

Merged
merged 1 commit into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions api/arceos_posix_api/src/imp/fd_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,39 @@ pub fn sys_dup2(old_fd: c_int, new_fd: c_int) -> c_int {
})
}

/// Duplicate a file descriptor.
pub fn sys_dup3(old_fd: c_int, new_fd: c_int, flags: c_int) -> c_int {
debug!(
"sys_dup3 <= old_fd: {}, new_fd: {}, flags: {}",
old_fd, new_fd, flags
);
syscall_body!(sys_dup3, {
if old_fd == new_fd {
let r = sys_fcntl(old_fd, ctypes::F_GETFD as _, 0);
if r >= 0 {
return Ok(old_fd);
} else {
return Ok(r);
}
}
if new_fd as usize >= AX_FILE_LIMIT {
return Err(LinuxError::EBADF);
}

let f = get_file_like(old_fd)?;
FD_TABLE
.write()
.add_at(new_fd as usize, f)
.ok_or(LinuxError::EMFILE)?;

if (flags & (ctypes::O_CLOEXEC as c_int)) != 0 {
let res = sys_fcntl(new_fd, ctypes::F_SETFD as _, ctypes::FD_CLOEXEC as _);
}

Ok(new_fd)
})
}

/// Manipulate file descriptor.
///
/// TODO: `SET/GET` command is ignored, hard-code stdin/stdout
Expand Down
2 changes: 1 addition & 1 deletion api/arceos_posix_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub use imp::task::{sys_exit, sys_getpid, sys_sched_yield};
pub use imp::time::{sys_clock_gettime, sys_nanosleep};

#[cfg(feature = "fd")]
pub use imp::fd_ops::{sys_close, sys_dup, sys_dup2, sys_fcntl};
pub use imp::fd_ops::{sys_close, sys_dup, sys_dup2, sys_dup3, sys_fcntl};
#[cfg(feature = "fs")]
pub use imp::fs::{sys_fstat, sys_getcwd, sys_lseek, sys_lstat, sys_open, sys_rename, sys_stat};
#[cfg(feature = "select")]
Expand Down
2 changes: 1 addition & 1 deletion ulib/axlibc/src/fd_ops.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::{ctypes, utils::e};
use arceos_posix_api::{sys_close, sys_dup, sys_dup2, sys_fcntl};
use arceos_posix_api::{sys_close, sys_dup, sys_dup2, sys_dup3, sys_fcntl};
use axerrno::LinuxError;
use core::ffi::c_int;

Expand Down
2 changes: 2 additions & 0 deletions ulib/axstarry/src/ctypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use axhal::{
};
use bitflags::*;
use core::panic;
/// a flag used in sys_dup3

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can wrap the flags as a full type for dup3 syscall in the next commit

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

pub const O_CLOEXEC: u32 = 524288;
/// The nano seconds number per second
pub const NSEC_PER_SEC: usize = 1_000_000_000;
bitflags! {
Expand Down
47 changes: 40 additions & 7 deletions ulib/axstarry/src/syscall_fs/imp/io.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! 负责与 IO 相关的系统调用
extern crate alloc;
use crate::ctypes;
use crate::syscall_net::Socket;
use crate::{IoVec, SyscallError, SyscallResult};
use alloc::string::ToString;
Expand Down Expand Up @@ -299,17 +300,47 @@ pub fn syscall_dup(args: [usize; 6]) -> SyscallResult {
/// 返回值:成功执行,返回新的文件描述符。失败,返回-1。
#[cfg(target_arch = "x86_64")]
pub fn syscall_dup2(args: [usize; 6]) -> SyscallResult {
syscall_dup3(args)
let fd = args[0];
let new_fd = args[1];
let process = current_process();
let mut fd_table = process.fd_manager.fd_table.lock();
if fd >= fd_table.len() {
debug!("fd {} is out of range", fd);
return Err(SyscallError::EPERM);
}
if fd_table[fd].is_none() {
debug!("fd {} is not opened", fd);
return Err(SyscallError::EPERM);
}
if new_fd >= fd_table.len() {
if new_fd >= (process.fd_manager.get_limit() as usize) {
// 超出了资源限制
return Err(SyscallError::EBADF);
}
for _i in fd_table.len()..new_fd + 1 {
fd_table.push(None);
}
}
// if process_inner.fd_manager.fd_table[new_fd].is_some() {
// debug!("new_fd {} is already opened", new_fd);
// return ErrorNo::EINVAL as isize;
// }
info!("dup2 fd {} to new fd {}", fd, new_fd);
// 就算new_fd已经被打开了,也可以被重新替代掉
fd_table[new_fd] = fd_table[fd].clone();
Ok(new_fd as isize)
}

/// 功能:复制文件描述符,并指定了新的文件描述符;
/// # Arguments
/// * fd: usize, 原文件所在的文件描述符
/// * new_fd: usize, 新的文件描述符
/// * flags: usize, 文件描述符标志
/// 返回值:成功执行,返回新的文件描述符。失败,返回-1。
pub fn syscall_dup3(args: [usize; 6]) -> SyscallResult {
let fd = args[0];
let new_fd = args[1];
let flags = args[2];
let process = current_process();
let mut fd_table = process.fd_manager.fd_table.lock();
if fd >= fd_table.len() {
Expand All @@ -320,6 +351,10 @@ pub fn syscall_dup3(args: [usize; 6]) -> SyscallResult {
debug!("fd {} is not opened", fd);
return Err(SyscallError::EPERM);
}
if fd == new_fd {
debug!("oldfd is equal to newfd");
return Err(SyscallError::EINVAL);
}
if new_fd >= fd_table.len() {
if new_fd >= (process.fd_manager.get_limit() as usize) {
// 超出了资源限制
Expand All @@ -329,13 +364,11 @@ pub fn syscall_dup3(args: [usize; 6]) -> SyscallResult {
fd_table.push(None);
}
}
// if process_inner.fd_manager.fd_table[new_fd].is_some() {
// debug!("new_fd {} is already opened", new_fd);
// return ErrorNo::EINVAL as isize;
// }
info!("dup3 fd {} to new fd {}", fd, new_fd);
// 就算new_fd已经被打开了,也可以被重新替代掉
info!("dup3 fd {} to new fd {} with flags {}", fd, new_fd, flags);
fd_table[new_fd] = fd_table[fd].clone();
if flags as u32 & ctypes::O_CLOEXEC != 0 {
fd_table[new_fd].as_mut().unwrap().set_close_on_exec(true);
}
Ok(new_fd as isize)
}

Expand Down
Loading