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
+102 -3
View File
@@ -2,14 +2,18 @@
//!
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/fcntl.h.html>.
use core::num::NonZeroU64;
use core::{num::NonZeroU64, slice};
use crate::{
c_str::CStr,
error::ResultExt,
error::{Errno, ResultExt},
header::errno::ENAMETOOLONG,
platform::{
Pal, Sys,
types::{c_char, c_int, c_short, c_ulonglong, mode_t, off_t, pid_t},
types::{
c_char, c_int, c_short, c_ulonglong, gid_t, mode_t, off_t, pid_t, size_t, ssize_t,
uid_t,
},
},
};
@@ -122,3 +126,98 @@ pub unsafe extern "C" fn posix_fallocate(fd: c_int, offset: off_t, length: off_t
.map(|e| e.0)
.unwrap_or_default()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/readlinkat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn readlinkat(
dirfd: c_int,
pathname: *const c_char,
buf: *mut c_char,
len: size_t,
) -> ssize_t {
let pathname = unsafe { CStr::from_ptr(pathname) };
let buf = unsafe { slice::from_raw_parts_mut(buf.cast(), len) };
Sys::readlinkat(dirfd, pathname, buf)
.map(|read| {
read.try_into()
.map_err(|_| Errno(ENAMETOOLONG))
.or_minus_one_errno()
})
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/linkat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn linkat(
fd1: c_int,
path1: *const c_char,
fd2: c_int,
path2: *const c_char,
flags: c_int,
) -> c_int {
let path1 = unsafe { CStr::from_ptr(path1) };
let path2 = unsafe { CStr::from_ptr(path2) };
Sys::linkat(fd1, path1, fd2, path2, flags)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/symlinkat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn symlinkat(path1: *const c_char, fd: c_int, path2: *const c_char) -> c_int {
let path1 = unsafe { CStr::from_ptr(path1) };
let path2 = unsafe { CStr::from_ptr(path2) };
Sys::symlinkat(path1, fd, path2)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/unlinkat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn unlinkat(fd: c_int, path: *const c_char, flags: c_int) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::unlinkat(fd, path, flags)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/fexecve.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn fexecve(
fd: c_int,
argv: *const *mut c_char,
envp: *const *mut c_char,
) -> c_int {
unsafe { Sys::fexecve(fd, argv, envp) }
.map(|()| unreachable!())
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/faccessat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn faccessat(
fd: c_int,
path: *const c_char,
mode: c_int,
flags: c_int,
) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::faccessat(fd, path, mode, flags)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/faccessat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn fchownat(
fd: c_int,
path: *const c_char,
owner: uid_t,
group: gid_t,
flags: c_int,
) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::fchownat(fd, path, owner, group, flags)
.map(|()| 0)
.or_minus_one_errno()
}
+7 -3
View File
@@ -30,7 +30,11 @@ pub const O_NDELAY: c_int = O_NONBLOCK;
// Flags for capability based "at" functions
pub const AT_FDCWD: c_int = -100;
pub const AT_SYMLINK_NOFOLLOW: c_int = 0x0200;
pub const AT_SYMLINK_FOLLOW: c_int = 0x2000;
pub const AT_EMPTY_PATH: c_int = 0x4000;
pub const AT_SYMLINK_NOFOLLOW: c_int = 0x200;
pub const AT_REMOVEDIR: c_int = 0x200;
// Used by linkat()
pub const AT_SYMLINK_FOLLOW: c_int = 0x2000;
// nonstandard extension, but likely to be in a future standard
pub const AT_EMPTY_PATH: c_int = 0x4000;
// only used for faccessat()
pub const AT_EACCESS: c_int = 0x400;
+5 -71
View File
@@ -17,8 +17,7 @@ use crate::{
header::{
bits_timespec::timespec,
crypt::{crypt_data, crypt_r},
errno::{self, ENAMETOOLONG},
fcntl, limits,
errno, fcntl, limits,
stdlib::getenv,
sys_ioctl, sys_resource,
sys_select::timeval,
@@ -45,13 +44,14 @@ pub use crate::header::stdio::ctermid;
#[allow(deprecated)]
pub use crate::header::stdio::cuserid;
// TODO: implement and reexport fcntl functions:
//pub use crate::header::fcntl::{faccessat, fchownat, fexecve, linkat, readlinkat, symlinkat, unlinkat};
use super::{
errno::{E2BIG, EINVAL, ENOMEM},
stdio::snprintf,
};
// Export *at functions because unistd.h includes them.
pub use crate::header::fcntl::{
faccessat, fchownat, fexecve, linkat, readlinkat, symlinkat, unlinkat,
};
use crate::header::signal::{sigprocmask, sigset_t, sigsuspend};
@@ -337,18 +337,6 @@ pub unsafe extern "C" fn execve(
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/exec.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn fexecve(
fd: c_int,
argv: *const *mut c_char,
envp: *const *mut c_char,
) -> c_int {
unsafe { Sys::fexecve(fd, argv, envp) }
.map(|()| unreachable!())
.or_minus_one_errno()
}
const PATH_SEPARATOR: u8 = b':';
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/exec.html>.
@@ -712,22 +700,6 @@ pub unsafe extern "C" fn link(path1: *const c_char, path2: *const c_char) -> c_i
Sys::link(path1, path2).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/linkat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn linkat(
fd1: c_int,
path1: *const c_char,
fd2: c_int,
path2: *const c_char,
flags: c_int,
) -> c_int {
let path1 = unsafe { CStr::from_ptr(path1) };
let path2 = unsafe { CStr::from_ptr(path2) };
Sys::linkat(fd1, path1, fd2, path2, flags)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/lockf.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn lockf(fildes: c_int, function: c_int, size: off_t) -> c_int {
@@ -876,25 +848,6 @@ pub unsafe extern "C" fn readlink(
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/readlink.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn readlinkat(
dirfd: c_int,
pathname: *const c_char,
buf: *mut c_char,
len: size_t,
) -> ssize_t {
let pathname = unsafe { CStr::from_ptr(pathname) };
let buf = unsafe { slice::from_raw_parts_mut(buf.cast(), len) };
Sys::readlinkat(dirfd, pathname, buf)
.map(|read| {
read.try_into()
.map_err(|_| Errno(ENAMETOOLONG))
.or_minus_one_errno()
})
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/rmdir.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
@@ -1031,16 +984,6 @@ pub unsafe extern "C" fn symlink(path1: *const c_char, path2: *const c_char) ->
Sys::symlink(path1, path2).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/symlinkat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn symlinkat(path1: *const c_char, fd: c_int, path2: *const c_char) -> c_int {
let path1 = unsafe { CStr::from_ptr(path1) };
let path2 = unsafe { CStr::from_ptr(path2) };
Sys::symlinkat(path1, fd, path2)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/sync.html>.
#[unsafe(no_mangle)]
pub extern "C" fn sync() {
@@ -1155,15 +1098,6 @@ pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
Sys::unlink(path).map(|()| 0).or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/unlinkat.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn unlinkat(fd: c_int, path: *const c_char, flags: c_int) -> c_int {
let path = unsafe { CStr::from_ptr(path) };
Sys::unlinkat(fd, path, flags)
.map(|()| 0)
.or_minus_one_errno()
}
/// See <https://pubs.opengroup.org/onlinepubs/009695399/functions/usleep.html>.
///
/// # Deprecation