platform/redox: migrate more functions to use their *at variants
Additionally, this adds the `SYMLOOP_MAX` constant in `limits.h` to replace the `MAX_LEVEL` magic number used during symlink resolution. `fstat` was kept because it is more difficult than the others to do a drop-in replacement in terms of `fstatat` for since a naive approach would cause mutual recursion.
This commit is contained in:
@@ -129,3 +129,4 @@ pub const PTHREAD_DESTRUCTOR_ITERATIONS: c_long = _POSIX_THREAD_DESTRUCTOR_ITERA
|
||||
// TODO: What should this limit be? Both glibc and musl have it as 1024
|
||||
pub const PTHREAD_KEYS_MAX: c_long = 4096 * 32;
|
||||
pub const PTHREAD_STACK_MIN: c_long = 65536;
|
||||
pub const SYMLOOP_MAX: c_long = 64;
|
||||
|
||||
@@ -5,7 +5,7 @@ use crate::{
|
||||
c_str::CStr,
|
||||
error::{Errno, Result},
|
||||
header::{
|
||||
fcntl::{AT_EMPTY_PATH, AT_FDCWD},
|
||||
fcntl::{AT_EMPTY_PATH, AT_FDCWD, F_DUPFD},
|
||||
signal::sigevent,
|
||||
sys_resource::{rlimit, rusage},
|
||||
sys_select::timeval,
|
||||
@@ -72,7 +72,9 @@ pub trait Pal {
|
||||
fn close(fildes: c_int) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`dup()`](crate::header::unistd::dup) from [`unistd.h`](crate::header::unistd).
|
||||
fn dup(fildes: c_int) -> Result<c_int>;
|
||||
fn dup(fildes: c_int) -> Result<c_int> {
|
||||
Self::fcntl(fildes, F_DUPFD, 0)
|
||||
}
|
||||
|
||||
/// Platform implementation of [`dup2()`](crate::header::unistd::dup2) from [`unistd.h`](crate::header::unistd).
|
||||
fn dup2(fildes: c_int, fildes2: c_int) -> Result<c_int>;
|
||||
@@ -322,7 +324,9 @@ pub trait Pal {
|
||||
unsafe fn nanosleep(rqtp: *const timespec, rmtp: *mut timespec) -> Result<()>;
|
||||
|
||||
/// Platform implementation of [`open()`](crate::header::fcntl::open) from [`fcntl.h`](crate::header::fcntl).
|
||||
fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int>;
|
||||
fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int> {
|
||||
Self::openat(AT_FDCWD, path, oflag, mode)
|
||||
}
|
||||
|
||||
/// Platform implementation of `openat()` (TODO) from [`fcntl.h`](crate::header::fcntl).
|
||||
fn openat(dirfd: c_int, path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int>;
|
||||
|
||||
@@ -2,7 +2,7 @@ use core::mem::size_of;
|
||||
|
||||
use crate::header::{
|
||||
bits_sigset_t::sigset_t,
|
||||
fcntl::{O_CLOEXEC, O_CREAT, O_RDWR},
|
||||
fcntl::{AT_FDCWD, O_CLOEXEC, O_CREAT, O_RDWR},
|
||||
time::timespec,
|
||||
};
|
||||
|
||||
@@ -16,7 +16,12 @@ pub unsafe extern "C" fn redox_event_queue_create_v1(flags: u32) -> RawResult {
|
||||
if flags != 0 {
|
||||
return Err(Error::new(EINVAL));
|
||||
}
|
||||
Ok(super::libredox::open("/scheme/event", O_CLOEXEC | O_CREAT | O_RDWR, 0o700)? as usize)
|
||||
Ok(super::libredox::openat(
|
||||
AT_FDCWD,
|
||||
"/scheme/event",
|
||||
O_CLOEXEC | O_CREAT | O_RDWR,
|
||||
0o700,
|
||||
)? as usize)
|
||||
})())
|
||||
}
|
||||
#[unsafe(no_mangle)]
|
||||
|
||||
@@ -12,7 +12,8 @@ use syscall::{
|
||||
|
||||
use crate::{
|
||||
header::{
|
||||
bits_iovec::iovec, errno::EINVAL, signal::sigaction, sys_stat::UTIME_NOW, time::timespec,
|
||||
bits_iovec::iovec, errno::EINVAL, fcntl::AT_FDCWD, signal::sigaction, sys_stat::UTIME_NOW,
|
||||
time::timespec,
|
||||
},
|
||||
out::Out,
|
||||
platform::{PalSignal, pal::Pal, types::*},
|
||||
@@ -22,20 +23,6 @@ use super::Sys;
|
||||
|
||||
pub type RawResult = usize;
|
||||
|
||||
pub fn open(path: &str, oflag: c_int, mode: mode_t) -> Result<usize> {
|
||||
let usize_fd = super::path::open(
|
||||
path,
|
||||
((oflag as usize) & 0xFFFF_0000) | ((mode as usize) & 0xFFFF),
|
||||
)?;
|
||||
|
||||
c_int::try_from(usize_fd)
|
||||
.map_err(|_| {
|
||||
let _ = syscall::close(usize_fd);
|
||||
Error::new(EMFILE)
|
||||
})
|
||||
.map(|f| f as usize)
|
||||
}
|
||||
|
||||
pub fn openat(dirfd: c_int, path: &str, oflag: c_int, mode: mode_t) -> Result<usize> {
|
||||
let usize_fd = super::path::openat(
|
||||
dirfd,
|
||||
@@ -239,7 +226,8 @@ pub unsafe extern "C" fn redox_open_v1(
|
||||
flags: u32,
|
||||
mode: u16,
|
||||
) -> RawResult {
|
||||
Error::mux(open(
|
||||
Error::mux(openat(
|
||||
AT_FDCWD,
|
||||
unsafe { str::from_utf8_unchecked(slice::from_raw_parts(path_base, path_len)) },
|
||||
flags as c_int,
|
||||
mode as mode_t,
|
||||
|
||||
+16
-37
@@ -107,10 +107,6 @@ static CLONE_LOCK: RwLock<()> = RwLock::new(());
|
||||
pub struct Sys;
|
||||
|
||||
impl Pal for Sys {
|
||||
fn access(path: CStr, mode: c_int) -> Result<()> {
|
||||
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);
|
||||
|
||||
@@ -247,10 +243,6 @@ impl Pal for Sys {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dup(fd: c_int) -> Result<c_int> {
|
||||
Ok(syscall::dup(fd as usize, &[])? as c_int)
|
||||
}
|
||||
|
||||
fn dup2(fd1: c_int, fd2: c_int) -> Result<c_int> {
|
||||
Ok(syscall::dup2(fd1 as usize, fd2 as usize, &[])? as c_int)
|
||||
}
|
||||
@@ -289,11 +281,6 @@ impl Pal for Sys {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fchmod(fd: c_int, mode: mode_t) -> Result<()> {
|
||||
libredox::fchmod(fd as usize, mode as u16)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -308,7 +295,7 @@ impl Pal for Sys {
|
||||
if dirfd == AT_FDCWD {
|
||||
path = ".";
|
||||
} else {
|
||||
return Sys::fchmod(dirfd, mode);
|
||||
return Ok(libredox::fchmod(dirfd as usize, mode as u16)?);
|
||||
}
|
||||
} else {
|
||||
// If the path is empty but `AT_EMPTY_PATH` is **not** set, bail out.
|
||||
@@ -321,17 +308,24 @@ impl Pal for Sys {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn fchown(fd: c_int, owner: uid_t, group: gid_t) -> Result<()> {
|
||||
libredox::fchown(fd as usize, owner as u32, group as u32)?;
|
||||
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 mut path = path.to_str().map_err(|_| Errno(ENOENT))?;
|
||||
if path.is_empty() {
|
||||
if flags & AT_EMPTY_PATH == AT_EMPTY_PATH {
|
||||
if fildes == AT_FDCWD {
|
||||
path = ".";
|
||||
} else {
|
||||
return Ok(libredox::fchown(fildes as usize, owner as _, group as _)?);
|
||||
}
|
||||
} else {
|
||||
// If the path is empty but `AT_EMPTY_PATH` is **not** set, bail out.
|
||||
return Err(Errno(ENOENT));
|
||||
}
|
||||
}
|
||||
let file = openat2(fildes, path, flags, 0)?;
|
||||
libredox::fchown(*file as usize, owner as _, group as _)?;
|
||||
Ok(())
|
||||
@@ -486,7 +480,7 @@ impl Pal for Sys {
|
||||
if dirfd == AT_FDCWD {
|
||||
path = ".";
|
||||
} else {
|
||||
return Sys::fstat(dirfd, buf);
|
||||
return Ok(Sys::fstat(dirfd, buf)?);
|
||||
}
|
||||
} else {
|
||||
// If the path is empty but `AT_EMPTY_PATH` is **not** set, bail out.
|
||||
@@ -513,7 +507,7 @@ impl Pal for Sys {
|
||||
let file = openat2(dirfd, path, 0, open_flags)?;
|
||||
// Close the file descriptor after fstat(2) regardless of success or failure.
|
||||
let fstat_res = Sys::fstat(*file, buf);
|
||||
let close_res = syscall::close(file.fd as usize);
|
||||
let close_res = syscall::close(*file as usize);
|
||||
if let Err(err) = fstat_res {
|
||||
return Err(err);
|
||||
}
|
||||
@@ -977,21 +971,6 @@ impl Pal for Sys {
|
||||
}
|
||||
}
|
||||
|
||||
fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int> {
|
||||
let path = path.to_str().map_err(|_| Errno(EINVAL))?;
|
||||
|
||||
// POSIX states that umask should affect the following:
|
||||
//
|
||||
// open, openat, creat, mkdir, mkdirat,
|
||||
// mkfifo, mkfifoat, mknod, mknodat,
|
||||
// mq_open, and sem_open,
|
||||
//
|
||||
// all of which (the ones that exist thus far) currently call this function.
|
||||
let effective_mode = mode & !(redox_rt::sys::get_umask() as mode_t);
|
||||
|
||||
Ok(libredox::open(path, oflag, effective_mode)? as c_int)
|
||||
}
|
||||
|
||||
fn openat(dirfd: c_int, path: CStr, oflag: c_int, mode: mode_t) -> Result<c_int> {
|
||||
let path = path.to_str().map_err(|_| Errno(EINVAL))?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user