Add dup3 syscall and fix EventFile

This commit is contained in:
Fabing Li
2024-05-31 20:53:54 +08:00
committed by Tate, Hongliang Tian
parent e0c6c29481
commit 8e1aeaf578
6 changed files with 75 additions and 17 deletions

View File

@ -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 | ❌ |

View File

@ -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);

View File

@ -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]);

View File

@ -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 _))
} }

View File

@ -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,
}
}
} }

View File

@ -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 \