sys_stat: implement utimensat() POSIX function

libstdc++ requires utimensat for file timestamp operations. Implemented
using openat(O_PATH) + futimens, with AT_SYMLINK_NOFOLLOW support.
This commit is contained in:
Red Bear OS
2026-07-10 12:14:55 +03:00
parent ef55c3cbb0
commit ee3107d873
+33
View File
@@ -142,6 +142,39 @@ pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/utimensat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn utimensat(
dirfd: c_int,
path: *const c_char,
times: *const timespec,
flags: c_int,
) -> c_int {
// If path is NULL, behave like futimens.
if path.is_null() {
return unsafe { futimens(dirfd, times) };
}
let path = unsafe { CStr::from_ptr(path) };
let mut oflag = O_PATH;
if flags & crate::header::fcntl::AT_SYMLINK_NOFOLLOW != 0 {
oflag |= O_NOFOLLOW;
}
let fd = Sys::openat(dirfd, path, oflag, 0).or_minus_one_errno();
if fd < 0 {
return -1;
}
let res = unsafe { Sys::futimens(fd, times) }
.map(|()| 0)
.or_minus_one_errno();
let _ = Sys::close(fd);
res
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/lstat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lstat(path: *const c_char, buf: *mut stat) -> c_int {