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:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user