mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-22 08:53:29 +00:00
Add dup3 syscall and fix EventFile
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
e0c6c29481
commit
8e1aeaf578
@ -312,7 +312,7 @@ provided by Linux on x86-64 architecture.
|
|||||||
| 289 | signalfd4 | ❌ |
|
| 289 | signalfd4 | ❌ |
|
||||||
| 290 | eventfd2 | ✅ |
|
| 290 | eventfd2 | ✅ |
|
||||||
| 291 | epoll_create1 | ✅ |
|
| 291 | epoll_create1 | ✅ |
|
||||||
| 292 | dup3 | ❌ |
|
| 292 | dup3 | ✅ |
|
||||||
| 293 | pipe2 | ✅ |
|
| 293 | pipe2 | ✅ |
|
||||||
| 294 | inotify_init1 | ❌ |
|
| 294 | inotify_init1 | ❌ |
|
||||||
| 295 | preadv | ❌ |
|
| 295 | preadv | ❌ |
|
||||||
|
@ -99,7 +99,7 @@ impl FileTable {
|
|||||||
item: Arc<dyn FileLike>,
|
item: Arc<dyn FileLike>,
|
||||||
flags: FdFlags,
|
flags: FdFlags,
|
||||||
) -> Option<Arc<dyn FileLike>> {
|
) -> Option<Arc<dyn FileLike>> {
|
||||||
let entry = FileTableEntry::new(item, FdFlags::empty());
|
let entry = FileTableEntry::new(item, flags);
|
||||||
let entry = self.table.put_at(fd as usize, entry);
|
let entry = self.table.put_at(fd as usize, entry);
|
||||||
if entry.is_some() {
|
if entry.is_some() {
|
||||||
let events = FdEvents::Close(fd);
|
let events = FdEvents::Close(fd);
|
||||||
|
@ -15,7 +15,7 @@ use crate::syscall::{
|
|||||||
clone::{sys_clone, sys_clone3},
|
clone::{sys_clone, sys_clone3},
|
||||||
close::sys_close,
|
close::sys_close,
|
||||||
connect::sys_connect,
|
connect::sys_connect,
|
||||||
dup::{sys_dup, sys_dup2},
|
dup::{sys_dup, sys_dup2, sys_dup3},
|
||||||
epoll::{sys_epoll_create, sys_epoll_create1, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait},
|
epoll::{sys_epoll_create, sys_epoll_create1, sys_epoll_ctl, sys_epoll_pwait, sys_epoll_wait},
|
||||||
eventfd::{sys_eventfd, sys_eventfd2},
|
eventfd::{sys_eventfd, sys_eventfd2},
|
||||||
execve::{sys_execve, sys_execveat},
|
execve::{sys_execve, sys_execveat},
|
||||||
@ -264,6 +264,7 @@ impl_syscall_nums_and_dispatch_fn! {
|
|||||||
SYS_ACCEPT4 = 288 => sys_accept4(args[..4]);
|
SYS_ACCEPT4 = 288 => sys_accept4(args[..4]);
|
||||||
SYS_EVENTFD2 = 290 => sys_eventfd2(args[..2]);
|
SYS_EVENTFD2 = 290 => sys_eventfd2(args[..2]);
|
||||||
SYS_EPOLL_CREATE1 = 291 => sys_epoll_create1(args[..1]);
|
SYS_EPOLL_CREATE1 = 291 => sys_epoll_create1(args[..1]);
|
||||||
|
SYS_DUP3 = 292 => sys_dup3(args[..3]);
|
||||||
SYS_PIPE2 = 293 => sys_pipe2(args[..2]);
|
SYS_PIPE2 = 293 => sys_pipe2(args[..2]);
|
||||||
SYS_PRLIMIT64 = 302 => sys_prlimit64(args[..4]);
|
SYS_PRLIMIT64 = 302 => sys_prlimit64(args[..4]);
|
||||||
SYS_GETRANDOM = 318 => sys_getrandom(args[..3]);
|
SYS_GETRANDOM = 318 => sys_getrandom(args[..3]);
|
||||||
|
@ -4,6 +4,7 @@ use super::SyscallReturn;
|
|||||||
use crate::{
|
use crate::{
|
||||||
fs::file_table::{FdFlags, FileDesc},
|
fs::file_table::{FdFlags, FileDesc},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
process::ResourceType,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn sys_dup(old_fd: FileDesc) -> Result<SyscallReturn> {
|
pub fn sys_dup(old_fd: FileDesc) -> Result<SyscallReturn> {
|
||||||
@ -11,24 +12,55 @@ pub fn sys_dup(old_fd: FileDesc) -> Result<SyscallReturn> {
|
|||||||
|
|
||||||
let current = current!();
|
let current = current!();
|
||||||
let mut file_table = current.file_table().lock();
|
let mut file_table = current.file_table().lock();
|
||||||
let file = file_table.get_file(old_fd)?.clone();
|
let new_fd = file_table.dup(old_fd, 0, FdFlags::empty())?;
|
||||||
// The two file descriptors do not share the close-on-exec flag.
|
|
||||||
let new_fd = file_table.insert(file, FdFlags::empty());
|
|
||||||
Ok(SyscallReturn::Return(new_fd as _))
|
Ok(SyscallReturn::Return(new_fd as _))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sys_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<SyscallReturn> {
|
pub fn sys_dup2(old_fd: FileDesc, new_fd: FileDesc) -> Result<SyscallReturn> {
|
||||||
debug!("old_fd = {}, new_fd = {}", old_fd, new_fd);
|
debug!("old_fd = {}, new_fd = {}", old_fd, new_fd);
|
||||||
|
|
||||||
|
if old_fd == new_fd {
|
||||||
let current = current!();
|
let current = current!();
|
||||||
|
let file_table = current.file_table().lock();
|
||||||
|
let _ = file_table.get_file(old_fd)?;
|
||||||
|
return Ok(SyscallReturn::Return(new_fd as _));
|
||||||
|
}
|
||||||
|
|
||||||
|
do_dup3(old_fd, new_fd, FdFlags::empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sys_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: u32) -> Result<SyscallReturn> {
|
||||||
|
debug!("old_fd = {}, new_fd = {}", old_fd, new_fd);
|
||||||
|
|
||||||
|
let fdflag = match flags {
|
||||||
|
0x0 => FdFlags::empty(),
|
||||||
|
0x80000 => FdFlags::CLOEXEC,
|
||||||
|
_ => return_errno_with_message!(Errno::EINVAL, "flags must be O_CLOEXEC or 0"),
|
||||||
|
};
|
||||||
|
|
||||||
|
do_dup3(old_fd, new_fd, fdflag)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn do_dup3(old_fd: FileDesc, new_fd: FileDesc, flags: FdFlags) -> Result<SyscallReturn> {
|
||||||
|
if old_fd == new_fd {
|
||||||
|
return_errno!(Errno::EINVAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
let current = current!();
|
||||||
|
if new_fd
|
||||||
|
>= current
|
||||||
|
.resource_limits()
|
||||||
|
.lock()
|
||||||
|
.get_rlimit(ResourceType::RLIMIT_NOFILE)
|
||||||
|
.get_cur() as FileDesc
|
||||||
|
{
|
||||||
|
return_errno!(Errno::EBADF);
|
||||||
|
}
|
||||||
|
|
||||||
let mut file_table = current.file_table().lock();
|
let mut file_table = current.file_table().lock();
|
||||||
let file = file_table.get_file(old_fd)?.clone();
|
let _ = file_table.close_file(new_fd);
|
||||||
if old_fd != new_fd {
|
let new_fd = file_table.dup(old_fd, new_fd, flags)?;
|
||||||
// The two file descriptors do not share the close-on-exec flag.
|
|
||||||
if let Some(old_file) = file_table.insert_at(new_fd, file, FdFlags::empty()) {
|
|
||||||
// If the file descriptor `new_fd` was previously open, close it silently.
|
|
||||||
let _ = old_file.clean_for_close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(SyscallReturn::Return(new_fd as _))
|
Ok(SyscallReturn::Return(new_fd as _))
|
||||||
}
|
}
|
||||||
|
@ -20,10 +20,14 @@ use crate::{
|
|||||||
fs::{
|
fs::{
|
||||||
file_handle::FileLike,
|
file_handle::FileLike,
|
||||||
file_table::{FdFlags, FileDesc},
|
file_table::{FdFlags, FileDesc},
|
||||||
utils::{CreationFlags, StatusFlags},
|
utils::{CreationFlags, InodeMode, InodeType, Metadata, StatusFlags},
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
process::signal::{Pauser, Pollee, Poller},
|
process::{
|
||||||
|
signal::{Pauser, Pollee, Poller},
|
||||||
|
Gid, Uid,
|
||||||
|
},
|
||||||
|
time::clocks::RealTimeClock,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn sys_eventfd(init_val: u64) -> Result<SyscallReturn> {
|
pub fn sys_eventfd(init_val: u64) -> Result<SyscallReturn> {
|
||||||
@ -253,4 +257,24 @@ impl FileLike for EventFile {
|
|||||||
) -> Option<Weak<dyn Observer<IoEvents>>> {
|
) -> Option<Weak<dyn Observer<IoEvents>>> {
|
||||||
self.pollee.unregister_observer(observer)
|
self.pollee.unregister_observer(observer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn metadata(&self) -> Metadata {
|
||||||
|
let now = RealTimeClock::get().read_time();
|
||||||
|
Metadata {
|
||||||
|
dev: 0,
|
||||||
|
ino: 0,
|
||||||
|
size: 0,
|
||||||
|
blk_size: 0,
|
||||||
|
blocks: 0,
|
||||||
|
atime: now,
|
||||||
|
mtime: now,
|
||||||
|
ctime: now,
|
||||||
|
type_: InodeType::NamedPipe,
|
||||||
|
mode: InodeMode::from_bits_truncate(0o200),
|
||||||
|
nlinks: 1,
|
||||||
|
uid: Uid::new_root(),
|
||||||
|
gid: Gid::new_root(),
|
||||||
|
rdev: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ TESTS ?= \
|
|||||||
chown_test \
|
chown_test \
|
||||||
chroot_test \
|
chroot_test \
|
||||||
creat_test \
|
creat_test \
|
||||||
|
dup_test \
|
||||||
epoll_test \
|
epoll_test \
|
||||||
eventfd_test \
|
eventfd_test \
|
||||||
fsync_test \
|
fsync_test \
|
||||||
|
Reference in New Issue
Block a user