diff --git a/src/header/limits/mod.rs b/src/header/limits/mod.rs index 45c37f06ca..192a82eafb 100644 --- a/src/header/limits/mod.rs +++ b/src/header/limits/mod.rs @@ -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; diff --git a/src/platform/pal/mod.rs b/src/platform/pal/mod.rs index 25d7351fbe..57363f0a8e 100644 --- a/src/platform/pal/mod.rs +++ b/src/platform/pal/mod.rs @@ -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; + fn dup(fildes: c_int) -> Result { + 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; @@ -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; + fn open(path: CStr, oflag: c_int, mode: mode_t) -> Result { + 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; diff --git a/src/platform/redox/event.rs b/src/platform/redox/event.rs index a3fe2254ff..9458aeeb16 100644 --- a/src/platform/redox/event.rs +++ b/src/platform/redox/event.rs @@ -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)] diff --git a/src/platform/redox/libredox.rs b/src/platform/redox/libredox.rs index dd9f5c1490..d6d5c77cce 100644 --- a/src/platform/redox/libredox.rs +++ b/src/platform/redox/libredox.rs @@ -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 { - 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 { 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, diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 8b5560e70b..dbd89ee5a1 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -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 { - Ok(syscall::dup(fd as usize, &[])? as c_int) - } - fn dup2(fd1: c_int, fd2: c_int) -> Result { 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, 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 { - 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 { let path = path.to_str().map_err(|_| Errno(EINVAL))?;