Implement fstatat

Linux's variant uses the syscall as intended. Redox's variant uses fpath
to build a path to pass to fstat from the file descriptor plus the file
name. Unlike the syscall, this isn't atomic so the liminal space between
fpath/getcwd and fstat is subject to TOCTOU.

Beyond fstatat, I moved the stat test to its correct location and added
an assert since the output of the test is unchecked.

I also added AT_FDCWD which seems to be -100 across Unixes. The other
AT_* constants are unimplemented for now.
This commit is contained in:
Josh Megnauth
2025-08-24 02:49:21 -04:00
committed by Josh Megnauth
parent 92bc01247a
commit c899feb774
14 changed files with 384 additions and 9 deletions
+10 -4
View File
@@ -7,6 +7,7 @@ use crate::{
header::{
dirent::dirent,
errno::EINVAL,
fcntl::{AT_EMPTY_PATH, AT_FDCWD, AT_REMOVEDIR, AT_SYMLINK_NOFOLLOW},
signal::SIGCHLD,
sys_resource::{rlimit, rusage},
sys_stat::{stat, S_IFIFO},
@@ -26,10 +27,6 @@ mod ptrace;
mod signal;
mod socket;
const AT_FDCWD: c_int = -100;
const AT_EMPTY_PATH: c_int = 0x1000;
const AT_REMOVEDIR: c_int = 0x200;
const SYS_CLONE: usize = 56;
const CLONE_VM: usize = 0x0100;
const CLONE_FS: usize = 0x0200;
@@ -185,6 +182,15 @@ impl Pal for Sys {
e_raw(unsafe { syscall!(NEWFSTATAT, fildes, empty_ptr, buf, AT_EMPTY_PATH) }).map(|_| ())
}
unsafe fn fstatat(
fildes: c_int,
path: *const c_char,
buf: *mut stat,
flags: c_int,
) -> Result<()> {
e_raw(unsafe { syscall!(NEWFSTATAT, fildes, path, buf, flags) }).map(|_| ())
}
unsafe fn fstatvfs(fildes: c_int, buf: *mut statvfs) -> Result<()> {
let mut kbuf = linux_statfs::default();
let kbuf_ptr = &mut kbuf as *mut linux_statfs;