From 9ec700f2e98431e15988facd36daf74690e6f652 Mon Sep 17 00:00:00 2001 From: pjht Date: Sun, 10 Nov 2024 10:25:40 -0600 Subject: [PATCH] mikros: Add CWD support --- library/std/src/sys/pal/mikros/common.rs | 1 + library/std/src/sys/pal/mikros/fs.rs | 98 ++++++++++++++++++++++- library/std/src/sys/pal/mikros/os.rs | 49 +++++++++++- library/std/src/sys/pal/mikros/process.rs | 12 +++ 4 files changed, 154 insertions(+), 6 deletions(-) diff --git a/library/std/src/sys/pal/mikros/common.rs b/library/std/src/sys/pal/mikros/common.rs index 546cb0868ef..0ee0d498d41 100644 --- a/library/std/src/sys/pal/mikros/common.rs +++ b/library/std/src/sys/pal/mikros/common.rs @@ -8,6 +8,7 @@ pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) { rpc::init(); super::stdio::init(); super::args::init(); + super::os::init_cwd(); } // SAFETY: must be called only once during runtime cleanup. diff --git a/library/std/src/sys/pal/mikros/fs.rs b/library/std/src/sys/pal/mikros/fs.rs index 346133e96ca..d70a7c03a53 100644 --- a/library/std/src/sys/pal/mikros/fs.rs +++ b/library/std/src/sys/pal/mikros/fs.rs @@ -1,8 +1,8 @@ // use super::rmp_serde; -use serde::{Serialize, Serializer}; +use serde::de::{Unexpected, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use crate::ffi::OsString; -use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::os::mikros::ipc::rpc; @@ -10,6 +10,7 @@ use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::unsupported; +use crate::{fmt, str}; #[unstable(feature = "rmp", issue = "none")] impl Serialize for Path { @@ -34,6 +35,99 @@ fn serialize(&self, serializer: S) -> Result } } +#[unstable(feature = "rmp", issue = "none")] +struct PathVisitor; + +#[unstable(feature = "rmp", issue = "none")] +impl<'a> Visitor<'a> for PathVisitor { + type Value = &'a Path; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("a borrowed path") + } + + fn visit_borrowed_str(self, v: &'a str) -> Result + where + E: serde::de::Error, + { + Ok(v.as_ref()) + } + + fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result + where + E: serde::de::Error, + { + str::from_utf8(v) + .map(AsRef::as_ref) + .map_err(|_| serde::de::Error::invalid_value(Unexpected::Bytes(v), &self)) + } +} + +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +#[unstable(feature = "rmp", issue = "none")] +impl<'de: 'a, 'a> Deserialize<'de> for &'a Path { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_str(PathVisitor) + } +} + +#[unstable(feature = "rmp", issue = "none")] +struct PathBufVisitor; + +#[unstable(feature = "rmp", issue = "none")] +impl<'de> Visitor<'de> for PathBufVisitor { + type Value = PathBuf; + + fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + formatter.write_str("path string") + } + + fn visit_str(self, v: &str) -> Result + where + E: serde::de::Error, + { + Ok(From::from(v)) + } + + fn visit_string(self, v: String) -> Result + where + E: serde::de::Error, + { + Ok(From::from(v)) + } + + fn visit_bytes(self, v: &[u8]) -> Result + where + E: serde::de::Error, + { + str::from_utf8(v) + .map(From::from) + .map_err(|_| serde::de::Error::invalid_value(Unexpected::Bytes(v), &self)) + } + + fn visit_byte_buf(self, v: Vec) -> Result + where + E: serde::de::Error, + { + String::from_utf8(v) + .map(From::from) + .map_err(|e| serde::de::Error::invalid_value(Unexpected::Bytes(&e.into_bytes()), &self)) + } +} + +#[unstable(feature = "rmp", issue = "none")] +impl<'de> Deserialize<'de> for PathBuf { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + deserializer.deserialize_string(PathBufVisitor) + } +} + pub struct File { pub(crate) fs_pid: u64, pub(crate) fd: u64, diff --git a/library/std/src/sys/pal/mikros/os.rs b/library/std/src/sys/pal/mikros/os.rs index 39fcd337da5..84c8bd10e55 100644 --- a/library/std/src/sys/pal/mikros/os.rs +++ b/library/std/src/sys/pal/mikros/os.rs @@ -3,9 +3,13 @@ use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; use crate::os::mikros::Errno; -use crate::path::{self, PathBuf}; +use crate::os::mikros::ipc::rpc; +use crate::path::{self, Component, Path, PathBuf}; +use crate::sync::Mutex; use crate::{fmt, io}; +static CWD: Mutex> = Mutex::new(None); + pub fn errno() -> Errno { Errno::EIO } @@ -153,11 +157,48 @@ pub fn error_string(errno: Errno) -> String { } pub fn getcwd() -> io::Result { - unsupported() + Ok(CWD.lock().unwrap().clone().unwrap()) } -pub fn chdir(_: &path::Path) -> io::Result<()> { - unsupported() +fn canonicalize_path(path: &Path) -> PathBuf { + path.components().fold(PathBuf::from("/"), |mut buf, component| match component { + Component::Prefix(_) => unreachable!(), + Component::RootDir | Component::Normal(_) => { + buf.push(component); + buf + } + Component::CurDir => buf, + Component::ParentDir => { + buf.pop(); + buf + } + }) +} + +pub fn chdir(path: &path::Path) -> io::Result<()> { + let cwd = getcwd()?; + let abs_path = if path.is_relative() { + let mut abs_path = cwd.clone(); + abs_path.push(path); + canonicalize_path(&abs_path) + } else { + path.to_owned() + }; + // Try to open the given directory, if it fails it's not a valid directory. + // Use Metadata instead once it's implemented. + crate::fs::read_dir(&abs_path)?; + *CWD.lock().unwrap() = Some(abs_path); + Ok(()) +} + +pub fn init_cwd() { + let Some(proc_man_pid) = syscalls::try_get_registered(3) else { + *CWD.lock().unwrap() = Some(PathBuf::from("/")); + return; + }; + let cwd: PathBuf = + postcard::from_bytes(&rpc::send_call(proc_man_pid, 8, 10, &[]).get_return()).unwrap(); + *CWD.lock().unwrap() = Some(cwd); } pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); diff --git a/library/std/src/sys/pal/mikros/process.rs b/library/std/src/sys/pal/mikros/process.rs index d0e4c86868e..c9061058f74 100644 --- a/library/std/src/sys/pal/mikros/process.rs +++ b/library/std/src/sys/pal/mikros/process.rs @@ -1,3 +1,4 @@ +use super::os::getcwd; use super::stdio::{STDERR_FD, STDIN_FD, STDOUT_FD}; use super::syscalls; pub use crate::ffi::OsString as EnvKey; @@ -147,6 +148,17 @@ pub fn spawn( ) .unwrap(); res?; + let res: Result<(), Errno> = postcard::from_bytes( + &rpc::send_call( + proc_man_pid, + 8, + 9, + &postcard::to_allocvec(&(pid, getcwd()?)).unwrap(), + ) + .get_return(), + ) + .unwrap(); + res?; }; syscalls::wake_new(pid).unwrap(); Ok((Process { pid }, StdioPipes { stdin: None, stdout: None, stderr: None }))