mikros: Add CWD support

This commit is contained in:
pjht 2024-11-10 10:25:40 -06:00
parent ead8f274c6
commit 9ec700f2e9
Signed by: pjht
GPG Key ID: 7B5F6AFBEC7EE78E
4 changed files with 154 additions and 6 deletions

View File

@ -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.

View File

@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
}
}
#[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<E>(self, v: &'a str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(v.as_ref())
}
fn visit_borrowed_bytes<E>(self, v: &'a [u8]) -> Result<Self::Value, E>
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<D>(deserializer: D) -> Result<Self, D::Error>
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<E>(self, v: &str) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(From::from(v))
}
fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
where
E: serde::de::Error,
{
Ok(From::from(v))
}
fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
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<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
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<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_string(PathBufVisitor)
}
}
pub struct File {
pub(crate) fs_pid: u64,
pub(crate) fd: u64,

View File

@ -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<Option<PathBuf>> = 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<PathBuf> {
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 ()>);

View File

@ -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 }))