diff --git a/src/platform/mod.rs b/src/platform/mod.rs index d9ec7cfee6..71a323993c 100644 --- a/src/platform/mod.rs +++ b/src/platform/mod.rs @@ -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); } } diff --git a/src/platform/redox/exec.rs b/src/platform/redox/exec.rs index 5235549f90..950be3c481 100644 --- a/src/platform/redox/exec.rs +++ b/src/platform/redox/exec.rs @@ -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(), diff --git a/src/platform/redox/mod.rs b/src/platform/redox/mod.rs index 80ed62c0c1..5655420c2b 100644 --- a/src/platform/redox/mod.rs +++ b/src/platform/redox/mod.rs @@ -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 { 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::>() // .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(), diff --git a/src/platform/redox/path.rs b/src/platform/redox/path.rs index 4151016eb0..2a149b308b 100644 --- a/src/platform/redox/path.rs +++ b/src/platform/redox/path.rs @@ -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 { 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, + pub path: CwdPath, pub fd: FdGuardUpper, } -// TODO: arraystring? static CWD: RwLock> = RwLock::new(None); -pub fn set_cwd_manual(path: Box, fd: FdGuardUpper) { +pub fn to_cwd_path(path: &str) -> Result { + 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> { +pub fn clone_cwd() -> Option { let _siglock = tmp_disable_signals(); CWD.read().as_ref().map(|cwd| cwd.path.clone()) } diff --git a/tests/expected/unistd/fchdir.stdout b/tests/expected/unistd/fchdir.stdout index e69de29bb2..a1c3331618 100644 --- a/tests/expected/unistd/fchdir.stdout +++ b/tests/expected/unistd/fchdir.stdout @@ -0,0 +1 @@ +getcwd: /usr diff --git a/tests/unistd/fchdir.c b/tests/unistd/fchdir.c index d80db6ea25..28f0b9150b 100644 --- a/tests/unistd/fchdir.c +++ b/tests/unistd/fchdir.c @@ -2,6 +2,7 @@ #include #include #include +#include #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); }