Use ArrayString for Cwd

This commit is contained in:
Wildan M
2026-06-22 22:13:24 +07:00
parent 4e4ed8b8c7
commit c234ace91d
6 changed files with 57 additions and 40 deletions
+3 -3
View File
@@ -379,15 +379,15 @@ pub unsafe fn init_inner(auxvs: Box<[[usize; 2]]>) {
) {
let cwd_bytes: &'static [u8] =
unsafe { core::slice::from_raw_parts(cwd_ptr as *const u8, cwd_len) };
if let (Ok(cwd_path), Some(cwd_fd)) = (
core::str::from_utf8(cwd_bytes),
if let (Ok(Ok(cwd_path)), Some(cwd_fd)) = (
core::str::from_utf8(cwd_bytes).map(self::sys::path::CwdPath::from),
(cwd_fd != usize::MAX).then(|| {
FdGuard::new(cwd_fd)
.to_upper()
.expect("failed to move cwd fd to upper table")
}),
) {
self::sys::path::set_cwd_manual(cwd_path.into(), cwd_fd);
self::sys::path::set_cwd_manual(cwd_path, cwd_fd);
}
}
+2 -2
View File
@@ -118,7 +118,7 @@ pub fn execve(
return Err(Error::new(EPERM));
}
let cwd: Box<[u8]> = super::path::clone_cwd().unwrap_or_default().into();
let cwd = super::path::clone_cwd().unwrap_or_default();
// Path to interpreter binary and args if found
let (interpreter_path, interpreter_args) = { parse_interpreter(&mut image_file)? };
@@ -229,7 +229,7 @@ pub fn execve(
let sigprocmask = redox_rt::signal::get_sigmask().unwrap();
let extrainfo = ExtraInfo {
cwd: Some(&cwd),
cwd: Some(cwd.as_bytes()),
sigignmask: redox_rt::signal::get_sigignmask_to_inherit(),
sigprocmask,
umask: redox_rt::sys::get_umask(),
+22 -20
View File
@@ -59,7 +59,10 @@ use crate::{
out::Out,
platform::{
ERRNO, free,
sys::timer::{TIMERS, timer_routine, timer_update_wake_time},
sys::{
path::{CwdPath, to_cwd_path},
timer::{TIMERS, timer_routine, timer_update_wake_time},
},
},
sync::rwlock::RwLock,
};
@@ -1208,11 +1211,8 @@ impl Pal for Sys {
) -> Result<pid_t> {
use crate::header::spawn::Flags;
let child = redox_rt::proc::new_child_process(&redox_rt::proc::ForkArgs::Managed)?;
let mut cwd: Box<[u8]> = path::clone_cwd().unwrap_or_default().into();
let mut cwd_fd = {
let cwd_str = core::str::from_utf8(&cwd).map_err(|_| Errno(EINVAL))?;
FdGuard::open(cwd_str, syscall::O_STAT)?.to_upper()?
};
let mut cwd = path::clone_cwd().unwrap_or_default();
let mut cwd_fd = FdGuard::open(cwd.as_str(), syscall::O_STAT)?.to_upper()?;
let proc_fd = child.proc_fd.unwrap();
let curr_proc_fd = redox_rt::current_proc_fd();
let file_table = RtTcb::current()
@@ -1254,8 +1254,7 @@ impl Pal for Sys {
let dirfd = {
// TODO: Cannot use cwd_fd (being an upper fd), also
// cannot set cwd_fd as regular fd then call to_upper later
let cwd_str = core::str::from_utf8(&cwd).map_err(|_| Errno(EINVAL))?;
FdGuard::open(cwd_str, syscall::O_STAT)?
FdGuard::open(cwd.as_str(), syscall::O_STAT)?
};
let src_fd = Sys::openat(
dirfd.as_c_fd().ok_or(Errno(EMFILE))?,
@@ -1278,17 +1277,21 @@ impl Pal for Sys {
)?;
}
crate::header::spawn::Action::Chdir(path) => {
cwd = Box::from(path.as_bytes());
let cwd_str = core::str::from_utf8(&cwd).map_err(|_| Errno(EINVAL))?;
let fd = FdGuard::open(cwd_str, syscall::O_STAT)?.to_upper()?;
let cwd_str =
core::str::from_utf8(path.as_bytes()).map_err(|_| Errno(EINVAL))?;
cwd = to_cwd_path(cwd_str)?;
let fd = FdGuard::open(cwd.as_str(), syscall::O_STAT)?.to_upper()?;
cwd_fd = fd;
}
crate::header::spawn::Action::FChdir(fd) => {
let mut buf = [0_u8; limits::PATH_MAX];
let res = Sys::fpath(fd, &mut buf)?;
cwd = Box::from(&buf[..res]);
let cwd_str = core::str::from_utf8(&cwd).map_err(|_| Errno(EINVAL))?;
let fd = FdGuard::open(cwd_str, syscall::O_STAT)?.to_upper()?;
let mut buf = CwdPath::zero_filled();
unsafe {
// SAFETY: Sys::fpath is using str::from_utf8 already
let res = Sys::fpath(fd, buf.as_bytes_mut())?;
buf.set_len(res);
}
cwd = buf;
let fd = FdGuard::open(cwd.as_str(), syscall::O_STAT)?.to_upper()?;
cwd_fd = fd;
}
crate::header::spawn::Action::Dup2(old, new) => {
@@ -1309,8 +1312,7 @@ impl Pal for Sys {
let dirfd = {
// TODO: Cannot use cwd_fd (being an upper fd), also
// cannot set cwd_fd as regular fd then call to_upper later
let cwd_str = core::str::from_utf8(&cwd).map_err(|_| Errno(EINVAL))?;
FdGuard::open(cwd_str, syscall::O_STAT)?
FdGuard::open(cwd.as_str(), syscall::O_STAT)?
};
let executable = Sys::openat(
@@ -1330,7 +1332,7 @@ impl Pal for Sys {
// .map(|s| str::from_utf8(s).unwrap_or("???"))
// .collect::<Vec<_>>()
// .as_slice(),
// str::from_utf8(&cwd).unwrap_or("???")
// cwd.as_bytes()
// );
new_file_table.call_wo(
@@ -1340,7 +1342,7 @@ impl Pal for Sys {
)?;
let extra_info = redox_rt::proc::ExtraInfo {
cwd: Some(&cwd),
cwd: Some(cwd.as_bytes()),
// Signals set to be ignored by the calling process
// must also be ignored by the child process
sigignmask: redox_rt::signal::get_sigignmask_to_inherit(),
+23 -15
View File
@@ -1,11 +1,14 @@
use alloc::{
boxed::Box,
collections::btree_set::BTreeSet,
ffi::CString,
string::{String, ToString},
vec::Vec,
};
use core::{ffi::c_int, str};
use arrayvec::ArrayString;
use core::{
ffi::c_int,
str::{self, FromStr},
};
use redox_rt::{proc::FdGuardUpper, signal::tmp_disable_signals};
use syscall::{data::Stat, error::*, flag::*};
@@ -105,7 +108,7 @@ pub fn chdir(path: &str) -> Result<()> {
let canon = canonicalize_using_cwd(cwd_guard.as_ref().map(|c| c.path.as_ref()), &path)
.ok_or(Error::new(ENOENT))?;
*cwd_guard = Some(Cwd {
path: canon.into_boxed_str(),
path: to_cwd_path(&canon)?,
fd,
});
} else {
@@ -120,7 +123,7 @@ pub fn chdir(path: &str) -> Result<()> {
}
*cwd_guard = Some(Cwd {
path: path.into_boxed_str(),
path: to_cwd_path(&path)?,
fd,
});
}
@@ -129,12 +132,12 @@ pub fn chdir(path: &str) -> Result<()> {
}
pub fn fchdir(fd: c_int) -> Result<()> {
let mut buf = [0_u8; limits::PATH_MAX];
let res = Sys::fpath(fd, &mut buf)?;
let path = core::str::from_utf8(&buf[..res])
.map_err(|_| Errno(EINVAL))?
.to_string();
let mut buf = CwdPath::zero_filled();
unsafe {
// SAFETY: Sys::fpath is using str::from_utf8 already
let res = Sys::fpath(fd, buf.as_bytes_mut())?;
buf.set_len(res);
}
let fd = FdGuard::new(syscall::fcntl(
fd as usize,
syscall::F_DUPFD,
@@ -142,7 +145,7 @@ pub fn fchdir(fd: c_int) -> Result<()> {
)?)
.to_upper()
.unwrap();
set_cwd_manual(path.into_boxed_str(), fd);
set_cwd_manual(buf, fd);
Ok(())
}
@@ -209,20 +212,25 @@ pub fn canonicalize(path: &str) -> Result<String> {
canonicalize_with_cwd_internal(cwd_guard.as_ref().map(|c| c.path.as_ref()), path)
}
pub type CwdPath = ArrayString<{ limits::PATH_MAX }>;
pub struct Cwd {
pub path: Box<str>,
pub path: CwdPath,
pub fd: FdGuardUpper,
}
// TODO: arraystring?
static CWD: RwLock<Option<Cwd>> = RwLock::new(None);
pub fn set_cwd_manual(path: Box<str>, fd: FdGuardUpper) {
pub fn to_cwd_path(path: &str) -> Result<CwdPath> {
ArrayString::from_str(&path).or(Err(Error::new(ENAMETOOLONG)))
}
pub fn set_cwd_manual(path: CwdPath, fd: FdGuardUpper) {
let _siglock = tmp_disable_signals();
*CWD.write() = Some(Cwd { path, fd });
}
pub fn clone_cwd() -> Option<Box<str>> {
pub fn clone_cwd() -> Option<CwdPath> {
let _siglock = tmp_disable_signals();
CWD.read().as_ref().map(|cwd| cwd.path.clone())
}
+1
View File
@@ -0,0 +1 @@
getcwd: /usr
+6
View File
@@ -2,6 +2,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "test_helpers.h"
@@ -17,4 +18,9 @@ int main(void) {
int c = close(fd);
ERROR_IF(close, c, == -1);
UNEXP_IF(close, c, != 0);
char cwd[PATH_MAX];
char* cw = getcwd(cwd, sizeof(cwd));
ERROR_IF(getcwd, cw, == NULL);
printf("getcwd: %s\n", cwd);
}