Merge branch 'faccessat-fchownat' into 'master'

add faccessat(2) and fchownat(2)

See merge request redox-os/relibc!1213
This commit is contained in:
Jeremy Soller
2026-04-20 16:33:30 -06:00
6 changed files with 170 additions and 91 deletions
+8 -7
View File
@@ -81,14 +81,12 @@ impl Sys {
}
impl Pal for Sys {
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
fn access(path: CStr, mode: c_int) -> Result<()> {
e_raw(unsafe { syscall!(ACCESS, path.as_ptr(), mode) }).map(|_| ())
Sys::faccessat(AT_FDCWD, path, mode, 0)
}
#[cfg(target_arch = "aarch64")]
fn access(path: CStr, mode: c_int) -> Result<()> {
e_raw(unsafe { syscall!(FACCESSAT, AT_FDCWD, path.as_ptr(), mode, 0) }).map(|_| ())
fn faccessat(fd: c_int, path: CStr, amode: c_int, flags: c_int) -> Result<()> {
e_raw(unsafe { syscall!(FACCESSAT, fd, path.as_ptr(), amode, flags) }).map(|_| ())
}
unsafe fn brk(addr: *mut c_void) -> Result<*mut c_void> {
@@ -104,11 +102,14 @@ impl Pal for Sys {
}
fn chown(path: CStr, owner: uid_t, group: gid_t) -> Result<()> {
let flags: c_int = 0;
Sys::fchownat(AT_FDCWD, path, owner, group, 0)
}
fn fchownat(fildes: c_int, path: CStr, owner: uid_t, group: gid_t, flags: c_int) -> Result<()> {
e_raw(unsafe {
syscall!(
FCHOWNAT,
AT_FDCWD,
fildes,
path.as_ptr(),
owner as u32,
group as u32,
+6
View File
@@ -37,6 +37,9 @@ pub trait Pal {
/// Platform implementation of [`access()`](crate::header::unistd::access) from [`unistd.h`](crate::header::unistd).
fn access(path: CStr, mode: c_int) -> Result<()>;
/// Platform implementation of [`faccessat()`](crate::header::unistd::faccessat) from [`unistd.h`](crate::header::unistd).
fn faccessat(fd: c_int, path: CStr, amode: c_int, flags: c_int) -> Result<()>;
/// Platform implementation of [`brk()`](crate::header::unistd::brk) from [`unistd.h`](crate::header::unistd).
unsafe fn brk(addr: *mut c_void) -> Result<*mut c_void>;
@@ -95,6 +98,9 @@ pub trait Pal {
/// Platform implementation of [`fchown()`](crate::header::unistd::fchown) from [`unistd.h`](crate::header::unistd).
fn fchown(fildes: c_int, owner: uid_t, group: gid_t) -> Result<()>;
/// Platform implementation of [`fchownat()`](crate::header::unistd::fchownat) from [`unistd.h`](crate::header::unistd).
fn fchownat(fildes: c_int, path: CStr, owner: uid_t, group: gid_t, flags: c_int) -> Result<()>;
/// Platform implementation of [`fdatasync()`](crate::header::unistd::fdatasync) from [`unistd.h`](crate::header::unistd).
fn fdatasync(fildes: c_int) -> Result<()>;
+42 -7
View File
@@ -32,8 +32,9 @@ use crate::{
ENOSYS, EOPNOTSUPP, EPERM,
},
fcntl::{
self, AT_EMPTY_PATH, AT_FDCWD, AT_REMOVEDIR, AT_SYMLINK_FOLLOW, AT_SYMLINK_NOFOLLOW,
F_GETLK, F_OFD_GETLK, F_OFD_SETLK, F_RDLCK, F_SETLK, F_SETLKW, F_UNLCK, F_WRLCK, flock,
self, AT_EACCESS, AT_EMPTY_PATH, AT_FDCWD, AT_REMOVEDIR, AT_SYMLINK_FOLLOW,
AT_SYMLINK_NOFOLLOW, F_GETLK, F_OFD_GETLK, F_OFD_SETLK, F_RDLCK, F_SETLK, F_SETLKW,
F_UNLCK, F_WRLCK, flock,
},
limits,
pthread::{pthread_cancel, pthread_create},
@@ -107,7 +108,15 @@ pub struct Sys;
impl Pal for Sys {
fn access(path: CStr, mode: c_int) -> Result<()> {
let fd = FdGuard::new(Sys::open(path, fcntl::O_PATH | fcntl::O_CLOEXEC, 0)? as usize);
Sys::faccessat(AT_FDCWD, path, mode, 0)
}
fn faccessat(fd: c_int, path: CStr, mode: c_int, flags: c_int) -> Result<()> {
let fd = FdGuard::new(Sys::openat(fd, path, fcntl::O_PATH | fcntl::O_CLOEXEC, 0)? as usize);
if (flags & !(AT_EACCESS)) != 0 {
return Err(Errno(EINVAL));
}
if mode == F_OK {
return Ok(());
@@ -117,11 +126,22 @@ impl Pal for Sys {
fd.fstat(&mut stat)?;
let Resugid { ruid, rgid, .. } = redox_rt::sys::posix_getresugid();
let Resugid {
ruid,
rgid,
euid,
egid,
..
} = redox_rt::sys::posix_getresugid();
let (uid, gid) = if (flags & AT_EACCESS) == AT_EACCESS {
(euid, egid)
} else {
(ruid, rgid)
};
let perms = (if stat.st_uid == ruid {
let perms = (if stat.st_uid == uid {
stat.st_mode >> (3 * 2)
} else if stat.st_gid == rgid {
} else if stat.st_gid == gid {
stat.st_mode >> (3 * 1)
} else {
stat.st_mode
@@ -277,7 +297,7 @@ impl Pal for Sys {
fn fchmodat(dirfd: c_int, path: Option<CStr>, mode: mode_t, flags: c_int) -> Result<()> {
const MASK: c_int = !(fcntl::AT_SYMLINK_NOFOLLOW | fcntl::AT_EMPTY_PATH);
if MASK & flags != 0 {
return Err(Errno(EOPNOTSUPP));
return Err(Errno(EINVAL));
}
let mut path = path
.and_then(|cs| str::from_utf8(cs.to_bytes()).ok())
@@ -306,6 +326,21 @@ impl Pal for Sys {
Ok(())
}
fn fchownat(fildes: c_int, path: CStr, owner: uid_t, group: gid_t, flags: c_int) -> Result<()> {
const MASK: c_int = !(fcntl::AT_SYMLINK_NOFOLLOW | fcntl::AT_EMPTY_PATH);
if MASK & flags != 0 {
return Err(Errno(EINVAL));
}
let path = path.to_str().map_err(|_| Errno(EINVAL))?;
let file = openat2(fildes, path, flags, 0)?;
libredox::fchown(
*file as usize,
owner.try_into().map_err(|_| Errno(EINVAL))?,
group.try_into().map_err(|_| Errno(EINVAL))?,
)?;
Ok(())
}
fn fcntl(fd: c_int, cmd: c_int, args: c_ulonglong) -> Result<c_int> {
match cmd {
F_SETLK | F_OFD_SETLK => {