Clean way to patch the std

This commit is contained in:
2026-03-18 17:19:08 +01:00
parent 51780b3a78
commit a087bdd523
35 changed files with 6302 additions and 1430 deletions

8
crates/std/build.rs Normal file
View File

@@ -0,0 +1,8 @@
use std::env;
pub fn main() {
println!(
"cargo:rustc-env=STD_ENV_ARCH={}",
env::var("CARGO_CFG_TARGET_ARCH").unwrap()
);
}

179
crates/std/justfile Normal file
View File

@@ -0,0 +1,179 @@
SRC_DIR := "src"
PATCH_DIR := "patches"
RUST_SRC := `rustc --print sysroot` / "lib/rustlib/src/rust/library/std/src"
patch-std:
@echo "Start patching the std..."
@find {{ PATCH_DIR }} -type f | while read -r patch_file; do \
relative_path="${patch_file#{{ PATCH_DIR }}/}"; \
case "$patch_file" in \
*.rs) \
echo "📄 [COPY] $relative_path"; \
mkdir -p "{{ SRC_DIR }}/$(dirname "$relative_path")"; \
cp "$patch_file" "{{ SRC_DIR }}/$relative_path"; \
;; \
*.sed) \
target_file="${relative_path%.sed}.rs"; \
if [ -f "{{ SRC_DIR }}/$target_file" ]; then \
echo " [SED] $target_file"; \
sed -i -f "$patch_file" "{{ SRC_DIR }}/$target_file"; \
else \
echo "⚠️[WARN] target doesn't exist: $target_file"; \
fi \
;; \
*) \
echo "❓ [SKIP] Unknown file : $relative_path"; \
;; \
esac; \
done
@echo "✅ Patching done."
update-std:
@just setup-std
@just patch-std
cp_std path:
@echo "Copying {{ path }}"
@mkdir {{ "src" / parent_directory(path) }} -p
@cp {{ RUST_SRC / path }} {{ "src" / path }}
@sed -i -f patches.sed {{ "src" / path }}
setup-std:
@# Not copied : sys/mod.rs, io.rs, error.rs, thread.rs, sync.rs
# @just cp_std "process.rs"
# @just cp_std "fs.rs"
# @just cp_std "collections/mod.rs"
@just cp_std "env.rs"
@just cp_std "time.rs"
@just cp_std "os/mod.rs"
@just cp_std "os/raw/mod.rs"
@just cp_std "os/raw/tests.rs"
@just cp_std "bstr.rs"
@just cp_std "panicking.rs"
@just cp_std "panic.rs"
@just cp_std "collections/hash/map.rs"
@just cp_std "collections/hash/set.rs"
@just cp_std "collections/hash/mod.rs"
@just cp_std "io/error.rs"
@just cp_std "io/error/repr_bitpacked.rs"
@just cp_std "io/error/repr_unpacked.rs"
@just cp_std "io/error/tests.rs"
@just cp_std "io/cursor.rs"
@just cp_std "io/cursor/tests.rs"
@just cp_std "io/prelude.rs"
@just cp_std "io/impls.rs"
@just cp_std "io/impls/tests.rs"
@just cp_std "io/tests.rs"
@just cp_std "io/util.rs"
@just cp_std "io/util/tests.rs"
@just cp_std "io/copy.rs"
@just cp_std "io/copy/tests.rs"
@just cp_std "io/pipe.rs"
@just cp_std "io/pipe/tests.rs"
@just cp_std "io/stdio.rs"
@just cp_std "io/buffered/mod.rs"
@just cp_std "io/buffered/bufreader.rs"
@just cp_std "io/buffered/bufreader/buffer.rs"
@just cp_std "io/buffered/bufwriter.rs"
@just cp_std "io/buffered/linewriter.rs"
@just cp_std "io/buffered/linewritershim.rs"
@just cp_std "sync/once.rs"
@just cp_std "sync/once_lock.rs"
@just cp_std "sync/lazy_lock.rs"
@just cp_std "sync/nonpoison.rs"
@just cp_std "sync/nonpoison/condvar.rs"
@just cp_std "sync/nonpoison/mutex.rs"
@just cp_std "sync/nonpoison/rwlock.rs"
@just cp_std "sync/poison.rs"
@just cp_std "sync/poison/condvar.rs"
@just cp_std "sync/poison/mutex.rs"
@just cp_std "sync/poison/rwlock.rs"
@just cp_std "sync/barrier.rs"
@just cp_std "sync/reentrant_lock.rs"
@just cp_std "sync/mpsc.rs"
@just cp_std "sync/mpmc/mod.rs"
@just cp_std "sync/mpmc/array.rs"
@just cp_std "sync/mpmc/context.rs"
@just cp_std "sync/mpmc/counter.rs"
@just cp_std "sync/mpmc/error.rs"
@just cp_std "sync/mpmc/list.rs"
@just cp_std "sync/mpmc/select.rs"
@just cp_std "sync/mpmc/tests.rs"
@just cp_std "sync/mpmc/utils.rs"
@just cp_std "sync/mpmc/waker.rs"
@just cp_std "sync/mpmc/zero.rs"
@just cp_std "hash/mod.rs"
@just cp_std "hash/random.rs"
@just cp_std "num/mod.rs"
@just cp_std "ffi/c_str.rs"
@just cp_std "ffi/mod.rs"
@just cp_std "ffi/os_str.rs"
@just cp_std "ffi/os_str/tests.rs"
@just cp_std "thread/local.rs"
@just cp_std "thread/thread.rs"
@just cp_std "thread/id.rs"
@just cp_std "thread/main_thread.rs"
@just cp_std "thread/current.rs"
@just cp_std "thread/join_handle.rs"
@just cp_std "thread/functions.rs"
@just cp_std "thread/lifecycle.rs"
@just cp_std "thread/builder.rs"
@just cp_std "thread/scoped.rs"
@just cp_std "thread/spawnhook.rs"
@just cp_std "sys/exit.rs"
@just cp_std "sys/env_consts.rs"
@just cp_std "sys/configure_builtins.rs"
@just cp_std "sys/cmath.rs"
@just cp_std "sys/process/mod.rs"
@just cp_std "sys/process/env.rs"
@just cp_std "sys/args/mod.rs"
@just cp_std "sys/args/unsupported.rs"
@just cp_std "sys/pal/mod.rs"
@just cp_std "sys/pal/unsupported/mod.rs"
@just cp_std "sys/pal/unsupported/common.rs"
@just cp_std "sys/pal/unsupported/os.rs"
@just cp_std "sys/sync/condvar/mod.rs"
@just cp_std "sys/sync/condvar/no_threads.rs"
@just cp_std "sys/sync/mutex/mod.rs"
@just cp_std "sys/sync/mutex/no_threads.rs"
@just cp_std "sys/sync/once/mod.rs"
@just cp_std "sys/sync/once/no_threads.rs"
@just cp_std "sys/sync/rwlock/mod.rs"
@just cp_std "sys/sync/rwlock/no_threads.rs"
@just cp_std "sys/sync/thread_parking/mod.rs"
@just cp_std "sys/sync/thread_parking/unsupported.rs"
@just cp_std "sys/thread/mod.rs"
@just cp_std "sys/thread/unsupported.rs"
@just cp_std "sys/thread_local/no_threads.rs"
@just cp_std "sys/thread_local/os.rs"
@just cp_std "sys/thread_local/mod.rs"
@just cp_std "sys/time/mod.rs"
@just cp_std "sys/time/unsupported.rs"
@just cp_std "sys/random/mod.rs"
@just cp_std "sys/random/unsupported.rs"
@just cp_std "sys/env/mod.rs"
@just cp_std "sys/env/common.rs"
@just cp_std "sys/env/unsupported.rs"
@just cp_std "sys/os_str/mod.rs"
@just cp_std "sys/os_str/bytes.rs"
@just cp_std "sys/os_str/bytes/tests.rs"
@just cp_std "sys/path/mod.rs"
@just cp_std "sys/path/unix.rs"
@just cp_std "sys/fs/mod.rs"
@just cp_std "sys/fs/common.rs"
@just cp_std "sys/fs/unsupported.rs"
@just cp_std "sys/io/error/generic.rs"
@just cp_std "sys/io/io_slice/unsupported.rs"
@just cp_std "sys/io/is_terminal/unsupported.rs"
@just cp_std "sys/io/kernel_copy/mod.rs"
@just cp_std "sys/io/mod.rs"
@just cp_std "sys/pipe/mod.rs"
@just cp_std "sys/pipe/unsupported.rs"
@just cp_std "sys/stdio/mod.rs"
@just cp_std "sys/stdio/unsupported.rs"
@just cp_std "sys/alloc/mod.rs"
@# Copied but edited for the moment
# @just cp_std "sys/process/unsupported.rs"
@just cp_std "sys/io/error/mod.rs"
# @just cp_std "alloc.rs"
# @just cp_std "path.rs"

View File

@@ -7,6 +7,8 @@ s|alloc::collections::TryReserveError|alloc_crate::collections::TryReserveError|
s|crate::collections::VecDeque|alloc_crate::collections::VecDeque|g
# s|collections::HashMap|hashbrown::HashMap|g
/crate::backtrace_rs/c \ todo!()
/crate::sys::os::getpid/c \ todo!()
/\[doc = include_str!/c \ // todo retreive docs
# /target_os = "xous",/a \ target_os = "survos",
# Ajouter d'autres modifications facilement ici :

View File

@@ -0,0 +1,3 @@
109a \ target_os = "survos" => { \
mod survos; \
}

View File

@@ -0,0 +1,4 @@
# 55a \ target_os = "survos" => { \
# mod survos; \
# pub use survos::*; \
# }

View File

@@ -0,0 +1 @@
45a \ target_os = "survos",

View File

@@ -0,0 +1,2 @@
108a \target_os = "survos",
124a \target_os = "survos",

View File

@@ -0,0 +1,6 @@
32a \ target_os = "survos",
129a \ target_os = "survos" => { \
// todo \
pub(crate) fn enable() {} \
}

View File

@@ -3,4 +3,5 @@ use core::marker::PhantomData;
pub struct HashMap<K, V, T> {
_phantom: PhantomData<(K, V, T)>,
}
pub use alloc_crate::collections;
pub use alloc_crate::collections::BTreeMap;
pub use alloc_crate::collections::btree_map;

File diff suppressed because it is too large Load Diff

View File

@@ -9,8 +9,8 @@ pub mod copy;
pub mod cursor;
pub mod impls;
pub mod pipe;
pub mod stdio;
pub mod prelude;
pub mod stdio;
pub mod util;
use crate::mem::{MaybeUninit, take};
@@ -18,9 +18,15 @@ use crate::ops::{Deref, DerefMut};
use crate::{cmp, fmt, slice, str, sys};
#[unstable(feature = "read_buf", issue = "78485")]
pub use core::io::{BorrowedBuf, BorrowedCursor};
pub use cursor::Cursor;
use core::slice::memchr;
pub use cursor::Cursor;
pub use self::stdio::{
Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, stderr, stdin, stdout,
};
pub use self::pipe::{PipeReader, PipeWriter};
pub use stdio::try_set_output_capture;
pub(crate) use stdio::attempt_print_to_stderr;
use crate::fs::File;
use io::IoBase;
@@ -29,7 +35,7 @@ use io::IoBase;
// pub use io::SeekFrom;
// pub use io::Write;
pub struct Stdin;
// pub struct Stdin;
impl IoBase for Stdin {
type Error = ();
@@ -41,9 +47,9 @@ impl io::Read for Stdin {
}
}
pub fn stdin() -> Stdin {
Stdin
}
// pub fn stdin() -> Stdin {
// Stdin
// }
// Part took from the real std

File diff suppressed because it is too large Load Diff

View File

@@ -187,7 +187,8 @@
stable_features,
incomplete_features,
unexpected_cfgs,
unfulfilled_lint_expectations
unfulfilled_lint_expectations,
private_interfaces
)]
#![allow(unused)]
@@ -287,6 +288,7 @@ pub mod alloc;
pub mod bstr;
pub mod collections;
pub mod env;
pub mod os;
pub mod panic;
pub mod panicking;
pub mod sync;

198
crates/std/src/os/mod.rs Normal file
View File

@@ -0,0 +1,198 @@
//! OS-specific functionality.
#![stable(feature = "os", since = "1.0.0")]
#![allow(missing_docs, nonstandard_style, missing_debug_implementations)]
#![allow(unsafe_op_in_unsafe_fn)]
pub mod raw;
// The code below could be written clearer using `cfg_if!`. However, the items below are
// publicly exported by `std` and external tools can have trouble analysing them because of the use
// of a macro that is not vendored by Rust and included in the toolchain.
// See https://github.com/rust-analyzer/rust-analyzer/issues/6038.
// On certain platforms right now the "main modules" modules that are
// documented don't compile (missing things in `libc` which is empty),
// so just omit them with an empty module and add the "unstable" attribute.
// darwin, unix, linux, wasi and windows are handled a bit differently.
#[cfg(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
))]
#[unstable(issue = "none", feature = "std_internals")]
pub mod darwin {}
#[cfg(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
))]
#[unstable(issue = "none", feature = "std_internals")]
pub mod unix {}
#[cfg(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
))]
#[unstable(issue = "none", feature = "std_internals")]
pub mod linux {}
#[cfg(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
))]
#[unstable(issue = "none", feature = "std_internals")]
pub mod wasi {}
#[cfg(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
))]
#[unstable(issue = "none", feature = "std_internals")]
pub mod windows {}
// darwin
#[cfg(not(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
)))]
#[cfg(any(target_vendor = "apple", doc))]
pub mod darwin;
// unix
#[cfg(not(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
)))]
#[cfg(all(not(target_os = "hermit"), any(unix, doc)))]
pub mod unix;
// linux
#[cfg(not(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
)))]
#[cfg(any(target_os = "linux", doc))]
pub mod linux;
// wasi
#[cfg(not(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
)))]
#[cfg(any(target_os = "wasi", any(target_env = "p1", target_env = "p2"), doc))]
pub mod wasi;
#[cfg(any(all(target_os = "wasi", target_env = "p2"), doc))]
pub mod wasip2;
// windows
#[cfg(not(all(
doc,
any(
all(target_arch = "wasm32", not(target_os = "wasi")),
all(target_vendor = "fortanix", target_env = "sgx")
)
)))]
#[cfg(any(windows, doc))]
pub mod windows;
// Others.
#[cfg(target_os = "aix")]
pub mod aix;
#[cfg(target_os = "android")]
pub mod android;
#[cfg(target_os = "cygwin")]
pub mod cygwin;
#[cfg(target_os = "dragonfly")]
pub mod dragonfly;
#[cfg(target_os = "emscripten")]
pub mod emscripten;
#[cfg(target_os = "espidf")]
pub mod espidf;
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
pub mod fortanix_sgx;
#[cfg(target_os = "freebsd")]
pub mod freebsd;
#[cfg(target_os = "fuchsia")]
pub mod fuchsia;
#[cfg(target_os = "haiku")]
pub mod haiku;
#[cfg(target_os = "hermit")]
pub mod hermit;
#[cfg(target_os = "horizon")]
pub mod horizon;
#[cfg(target_os = "hurd")]
pub mod hurd;
#[cfg(target_os = "illumos")]
pub mod illumos;
#[cfg(target_os = "ios")]
pub mod ios;
#[cfg(target_os = "l4re")]
pub mod l4re;
#[cfg(target_os = "macos")]
pub mod macos;
#[cfg(target_os = "motor")]
pub mod motor;
#[cfg(target_os = "netbsd")]
pub mod netbsd;
#[cfg(target_os = "nto")]
pub mod nto;
#[cfg(target_os = "nuttx")]
pub mod nuttx;
#[cfg(target_os = "openbsd")]
pub mod openbsd;
#[cfg(target_os = "redox")]
pub mod redox;
#[cfg(target_os = "rtems")]
pub mod rtems;
#[cfg(target_os = "solaris")]
pub mod solaris;
#[cfg(target_os = "solid_asp3")]
pub mod solid;
#[cfg(target_os = "trusty")]
pub mod trusty;
#[cfg(target_os = "uefi")]
pub mod uefi;
#[cfg(target_os = "vita")]
pub mod vita;
#[cfg(target_os = "vxworks")]
pub mod vxworks;
#[cfg(target_os = "xous")]
pub mod xous;
#[cfg(any(
unix,
target_os = "hermit",
target_os = "trusty",
target_os = "wasi",
target_os = "motor",
doc
))]
pub mod fd;
#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin", doc))]
mod net;

View File

@@ -0,0 +1,26 @@
//! Compatibility module for C platform-specific types. Use [`core::ffi`] instead.
#![stable(feature = "raw_os", since = "1.1.0")]
#[cfg(test)]
mod tests;
macro_rules! alias_core_ffi {
($($t:ident)*) => {$(
#[stable(feature = "raw_os", since = "1.1.0")]
// todo retreive docs
#[doc(cfg(all()))]
pub type $t = core::ffi::$t;
)*}
}
alias_core_ffi! {
c_char c_schar c_uchar
c_short c_ushort
c_int c_uint
c_long c_ulong
c_longlong c_ulonglong
c_float
c_double
c_void
}

View File

@@ -0,0 +1,17 @@
#![cfg(not(all(windows, target_env = "msvc")))]
use crate::any::TypeId;
macro_rules! ok {
($($t:ident)*) => {$(
assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
"{} is wrong", stringify!($t));
)*}
}
#[test]
fn same() {
use crate::os::raw;
ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
c_longlong c_ulonglong c_float c_double);
}

View File

@@ -176,6 +176,6 @@ pub mod rust_2024 {
) -> isize {
println!("{}", argc);
println!("{:?}", argv);
main().report().to_isize()
main().report().to_i32() as isize
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
macro_rules! rtabort {
($($t:tt)*) => {{
loop {}
}};
($($t:tt)*) => {{ loop {} }};
}
macro_rules! rtprintpanic {
($($t:tt)*) => {{}};
}
pub fn cleanup() {}

View File

@@ -0,0 +1,60 @@
//! Platform-dependent command line arguments abstraction.
#![forbid(unsafe_op_in_unsafe_fn)]
#[cfg(any(
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
target_family = "windows",
target_os = "hermit",
target_os = "motor",
target_os = "uefi",
target_os = "wasi",
target_os = "xous",
))]
mod common;
cfg_select! {
any(
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
target_os = "hermit",
) => {
mod unix;
pub use unix::*;
}
target_family = "windows" => {
mod windows;
pub use windows::*;
}
all(target_vendor = "fortanix", target_env = "sgx") => {
mod sgx;
pub use sgx::*;
}
target_os = "motor" => {
mod motor;
pub use motor::*;
}
target_os = "uefi" => {
mod uefi;
pub use uefi::*;
}
all(target_os = "wasi", target_env = "p1") => {
mod wasip1;
pub use wasip1::*;
}
all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
mod wasip2;
pub use wasip2::*;
}
target_os = "xous" => {
mod xous;
pub use xous::*;
}
target_os = "zkvm" => {
mod zkvm;
pub use zkvm::*;
}
_ => {
mod unsupported;
pub use unsupported::*;
}
}

View File

@@ -0,0 +1,42 @@
use crate::ffi::OsString;
use crate::fmt;
pub struct Args {}
pub fn args() -> Args {
Args {}
}
impl fmt::Debug for Args {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().finish()
}
}
impl Iterator for Args {
type Item = OsString;
#[inline]
fn next(&mut self) -> Option<OsString> {
None
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(0, Some(0))
}
}
impl DoubleEndedIterator for Args {
#[inline]
fn next_back(&mut self) -> Option<OsString> {
None
}
}
impl ExactSizeIterator for Args {
#[inline]
fn len(&self) -> usize {
0
}
}

View File

@@ -1,20 +1,24 @@
pub mod alloc;
pub mod args;
pub mod backtrace;
pub mod cmath;
pub mod configure_builtins;
pub mod env;
pub mod env_consts;
pub mod exit;
pub mod io;
pub mod os_str;
pub mod pal;
pub mod path;
pub mod pipe;
pub mod process;
pub mod random;
pub mod stdio;
pub mod sync;
pub mod thread;
pub mod time;
pub mod random;
pub mod thread_local;
pub mod alloc;
pub mod io;
pub mod pipe;
pub mod stdio;
pub mod backtrace;
pub mod time;
pub use pal::*;
// pub mod fs;
/// A trait for viewing representations from std types.
@@ -38,3 +42,25 @@ pub(crate) trait IntoInner<Inner> {
pub(crate) trait FromInner<Inner> {
fn from_inner(inner: Inner) -> Self;
}
use crate::io as std_io;
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
pub unsafe fn cleanup() {}
pub fn unsupported<T>() -> std_io::Result<T> {
Err(unsupported_err())
}
pub fn unsupported_err() -> std_io::Error {
std_io::Error::UNSUPPORTED_PLATFORM
}
pub fn abort_internal() -> ! {
core::intrinsics::abort();
}

View File

@@ -0,0 +1,67 @@
//! The PAL (platform abstraction layer) contains platform-specific abstractions
//! for implementing the features in the other submodules, such as e.g. bindings.
#![allow(missing_debug_implementations)]
cfg_select! {
unix => {
mod unix;
pub use self::unix::*;
}
windows => {
mod windows;
pub use self::windows::*;
}
target_os = "solid_asp3" => {
mod solid;
pub use self::solid::*;
}
target_os = "hermit" => {
mod hermit;
pub use self::hermit::*;
}
target_os = "motor" => {
mod motor;
pub use self::motor::*;
}
target_os = "trusty" => {
mod trusty;
pub use self::trusty::*;
}
target_os = "vexos" => {
mod vexos;
pub use self::vexos::*;
}
target_os = "wasi" => {
mod wasi;
pub use self::wasi::*;
}
target_family = "wasm" => {
mod wasm;
pub use self::wasm::*;
}
target_os = "xous" => {
mod xous;
pub use self::xous::*;
}
target_os = "uefi" => {
mod uefi;
pub use self::uefi::*;
}
all(target_vendor = "fortanix", target_env = "sgx") => {
mod sgx;
pub use self::sgx::*;
}
target_os = "teeos" => {
mod teeos;
pub use self::teeos::*;
}
target_os = "zkvm" => {
mod zkvm;
pub use self::zkvm::*;
}
_ => {
mod unsupported;
pub use self::unsupported::*;
}
}

View File

@@ -0,0 +1,21 @@
use crate::io as std_io;
// SAFETY: must be called only once during runtime initialization.
// NOTE: this is not guaranteed to run, for example when Rust code is called externally.
pub unsafe fn init(_argc: isize, _argv: *const *const u8, _sigpipe: u8) {}
// SAFETY: must be called only once during runtime cleanup.
// NOTE: this is not guaranteed to run, for example when the program aborts.
pub unsafe fn cleanup() {}
pub fn unsupported<T>() -> std_io::Result<T> {
Err(unsupported_err())
}
pub fn unsupported_err() -> std_io::Error {
std_io::Error::UNSUPPORTED_PLATFORM
}
pub fn abort_internal() -> ! {
core::intrinsics::abort();
}

View File

@@ -0,0 +1,6 @@
#![deny(unsafe_op_in_unsafe_fn)]
pub mod os;
mod common;
pub use common::*;

View File

@@ -0,0 +1,61 @@
use super::unsupported;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::{fmt, io};
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}
pub fn chdir(_: &path::Path) -> io::Result<()> {
unsupported()
}
pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> {
panic!("unsupported")
}
impl<'a> Iterator for SplitPaths<'a> {
type Item = PathBuf;
fn next(&mut self) -> Option<PathBuf> {
self.0
}
}
#[derive(Debug)]
pub struct JoinPathsError;
pub fn join_paths<I, T>(_paths: I) -> Result<OsString, JoinPathsError>
where
I: Iterator<Item = T>,
T: AsRef<OsStr>,
{
Err(JoinPathsError)
}
impl fmt::Display for JoinPathsError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
"not supported on this platform yet".fmt(f)
}
}
impl crate::error::Error for JoinPathsError {}
pub fn current_exe() -> io::Result<PathBuf> {
unsupported()
}
pub fn temp_dir() -> PathBuf {
panic!("no filesystem on this platform")
}
pub fn home_dir() -> Option<PathBuf> {
None
}
pub fn getpid() -> u32 {
panic!("no pids on this platform")
}

View File

@@ -45,8 +45,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
PathBuf::new()
}
} else {
// env::current_dir()?
todo!()
env::current_dir()?
};
normalized.extend(components);

View File

@@ -0,0 +1,115 @@
use crate::collections::BTreeMap;
use crate::ffi::{OsStr, OsString};
use crate::sys::process::EnvKey;
use crate::{env, fmt};
/// Stores a set of changes to an environment
#[derive(Clone, Default)]
pub struct CommandEnv {
clear: bool,
saw_path: bool,
vars: BTreeMap<EnvKey, Option<OsString>>,
}
impl fmt::Debug for CommandEnv {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut debug_command_env = f.debug_struct("CommandEnv");
debug_command_env.field("clear", &self.clear).field("vars", &self.vars);
debug_command_env.finish()
}
}
impl CommandEnv {
// Capture the current environment with these changes applied
pub fn capture(&self) -> BTreeMap<EnvKey, OsString> {
let mut result = BTreeMap::<EnvKey, OsString>::new();
if !self.clear {
for (k, v) in env::vars_os() {
result.insert(k.into(), v);
}
}
for (k, maybe_v) in &self.vars {
if let &Some(ref v) = maybe_v {
result.insert(k.clone(), v.clone());
} else {
result.remove(k);
}
}
result
}
pub fn is_unchanged(&self) -> bool {
!self.clear && self.vars.is_empty()
}
pub fn capture_if_changed(&self) -> Option<BTreeMap<EnvKey, OsString>> {
if self.is_unchanged() { None } else { Some(self.capture()) }
}
// The following functions build up changes
pub fn set(&mut self, key: &OsStr, value: &OsStr) {
let key = EnvKey::from(key);
self.maybe_saw_path(&key);
self.vars.insert(key, Some(value.to_owned()));
}
pub fn remove(&mut self, key: &OsStr) {
let key = EnvKey::from(key);
self.maybe_saw_path(&key);
if self.clear {
self.vars.remove(&key);
} else {
self.vars.insert(key, None);
}
}
pub fn clear(&mut self) {
self.clear = true;
self.vars.clear();
}
pub fn does_clear(&self) -> bool {
self.clear
}
pub fn have_changed_path(&self) -> bool {
self.saw_path || self.clear
}
fn maybe_saw_path(&mut self, key: &EnvKey) {
if !self.saw_path && key == "PATH" {
self.saw_path = true;
}
}
pub fn iter(&self) -> CommandEnvs<'_> {
let iter = self.vars.iter();
CommandEnvs { iter }
}
}
#[derive(Debug)]
pub struct CommandEnvs<'a> {
iter: crate::collections::btree_map::Iter<'a, EnvKey, Option<OsString>>,
}
impl<'a> Iterator for CommandEnvs<'a> {
type Item = (&'a OsStr, Option<&'a OsStr>);
fn next(&mut self) -> Option<Self::Item> {
self.iter.next().map(|(key, value)| (key.as_ref(), value.as_deref()))
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for CommandEnvs<'a> {
fn len(&self) -> usize {
self.iter.len()
}
fn is_empty(&self) -> bool {
self.iter.is_empty()
}
}

View File

@@ -0,0 +1,86 @@
cfg_select! {
target_family = "unix" => {
mod unix;
use unix as imp;
}
target_os = "windows" => {
mod windows;
use windows as imp;
}
target_os = "uefi" => {
mod uefi;
use uefi as imp;
}
target_os = "motor" => {
mod motor;
use motor as imp;
}
_ => {
mod unsupported;
use unsupported as imp;
}
}
// This module is shared by all platforms, but nearly all platforms except for
// the "normal" UNIX ones leave some of this code unused.
#[cfg_attr(not(target_os = "linux"), allow(dead_code))]
mod env;
pub use env::CommandEnvs;
pub use imp::{
ChildPipe, Command, CommandArgs, EnvKey, ExitCode, ExitStatus, ExitStatusError, Process, Stdio,
read_output,
};
#[cfg(any(
all(
target_family = "unix",
not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
))
),
target_os = "windows",
target_os = "motor"
))]
pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
let (mut process, mut pipes) = cmd.spawn(Stdio::MakePipe, false)?;
drop(pipes.stdin.take());
let (mut stdout, mut stderr) = (Vec::new(), Vec::new());
match (pipes.stdout.take(), pipes.stderr.take()) {
(None, None) => {}
(Some(out), None) => {
let res = out.read_to_end(&mut stdout);
res.unwrap();
}
(None, Some(err)) => {
let res = err.read_to_end(&mut stderr);
res.unwrap();
}
(Some(out), Some(err)) => {
let res = read_output(out, &mut stdout, err, &mut stderr);
res.unwrap();
}
}
let status = process.wait()?;
Ok((status, stdout, stderr))
}
#[cfg(not(any(
all(
target_family = "unix",
not(any(
target_os = "espidf",
target_os = "horizon",
target_os = "vita",
target_os = "nuttx"
))
),
target_os = "windows",
target_os = "motor"
)))]
pub use imp::output;

View File

@@ -0,0 +1,331 @@
use super::env::{CommandEnv, CommandEnvs};
pub use crate::ffi::OsString as EnvKey;
use crate::ffi::{OsStr, OsString};
use crate::num::NonZero;
use crate::path::Path;
use crate::process::StdioPipes;
// use crate::sys::fs::File;
use crate::sys::unsupported;
use crate::{fmt, io};
////////////////////////////////////////////////////////////////////////////////
// Command
////////////////////////////////////////////////////////////////////////////////
pub struct Command {
program: OsString,
args: Vec<OsString>,
env: CommandEnv,
cwd: Option<OsString>,
stdin: Option<Stdio>,
stdout: Option<Stdio>,
stderr: Option<Stdio>,
}
#[derive(Debug)]
pub enum Stdio {
Inherit,
Null,
MakePipe,
ParentStdout,
ParentStderr,
// #[allow(dead_code)] // This variant exists only for the Debug impl
// InheritFile(File),
}
impl Command {
pub fn new(program: &OsStr) -> Command {
Command {
program: program.to_owned(),
args: vec![program.to_owned()],
env: Default::default(),
cwd: None,
stdin: None,
stdout: None,
stderr: None,
}
}
pub fn arg(&mut self, arg: &OsStr) {
self.args.push(arg.to_owned());
}
pub fn env_mut(&mut self) -> &mut CommandEnv {
&mut self.env
}
pub fn cwd(&mut self, dir: &OsStr) {
self.cwd = Some(dir.to_owned());
}
pub fn stdin(&mut self, stdin: Stdio) {
self.stdin = Some(stdin);
}
pub fn stdout(&mut self, stdout: Stdio) {
self.stdout = Some(stdout);
}
pub fn stderr(&mut self, stderr: Stdio) {
self.stderr = Some(stderr);
}
pub fn get_program(&self) -> &OsStr {
&self.program
}
pub fn get_args(&self) -> CommandArgs<'_> {
let mut iter = self.args.iter();
iter.next();
CommandArgs { iter }
}
pub fn get_envs(&self) -> CommandEnvs<'_> {
self.env.iter()
}
pub fn get_env_clear(&self) -> bool {
self.env.does_clear()
}
pub fn get_current_dir(&self) -> Option<&Path> {
self.cwd.as_ref().map(|cs| Path::new(cs))
}
pub fn spawn(
&mut self,
_default: Stdio,
_needs_stdin: bool,
) -> io::Result<(Process, StdioPipes)> {
unsupported()
}
}
pub fn output(_cmd: &mut Command) -> io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
unsupported()
}
impl From<ChildPipe> for Stdio {
fn from(pipe: ChildPipe) -> Stdio {
pipe.diverge()
}
}
impl From<io::Stdout> for Stdio {
fn from(_: io::Stdout) -> Stdio {
Stdio::ParentStdout
}
}
impl From<io::Stderr> for Stdio {
fn from(_: io::Stderr) -> Stdio {
Stdio::ParentStderr
}
}
// impl From<File> for Stdio {
// fn from(file: File) -> Stdio {
// Stdio::InheritFile(file)
// }
// }
impl fmt::Debug for Command {
// show all attributes
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
let mut debug_command = f.debug_struct("Command");
debug_command
.field("program", &self.program)
.field("args", &self.args);
if !self.env.is_unchanged() {
debug_command.field("env", &self.env);
}
if self.cwd.is_some() {
debug_command.field("cwd", &self.cwd);
}
if self.stdin.is_some() {
debug_command.field("stdin", &self.stdin);
}
if self.stdout.is_some() {
debug_command.field("stdout", &self.stdout);
}
if self.stderr.is_some() {
debug_command.field("stderr", &self.stderr);
}
debug_command.finish()
} else {
if let Some(ref cwd) = self.cwd {
write!(f, "cd {cwd:?} && ")?;
}
if self.env.does_clear() {
write!(f, "env -i ")?;
// Altered env vars will be printed next, that should exactly work as expected.
} else {
// Removed env vars need the command to be wrapped in `env`.
let mut any_removed = false;
for (key, value_opt) in self.get_envs() {
if value_opt.is_none() {
if !any_removed {
write!(f, "env ")?;
any_removed = true;
}
write!(f, "-u {} ", key.to_string_lossy())?;
}
}
}
// Altered env vars can just be added in front of the program.
for (key, value_opt) in self.get_envs() {
if let Some(value) = value_opt {
write!(f, "{}={value:?} ", key.to_string_lossy())?;
}
}
if self.program != self.args[0] {
write!(f, "[{:?}] ", self.program)?;
}
write!(f, "{:?}", self.args[0])?;
for arg in &self.args[1..] {
write!(f, " {:?}", arg)?;
}
Ok(())
}
}
}
#[derive(PartialEq, Eq, Clone, Copy, Debug, Default)]
#[non_exhaustive]
pub struct ExitStatus();
impl ExitStatus {
pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
Ok(())
}
pub fn code(&self) -> Option<i32> {
Some(0)
}
}
impl fmt::Display for ExitStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<dummy exit status>")
}
}
pub struct ExitStatusError(!);
impl Clone for ExitStatusError {
fn clone(&self) -> ExitStatusError {
self.0
}
}
impl Copy for ExitStatusError {}
impl PartialEq for ExitStatusError {
fn eq(&self, _other: &ExitStatusError) -> bool {
self.0
}
}
impl Eq for ExitStatusError {}
impl fmt::Debug for ExitStatusError {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
}
}
impl Into<ExitStatus> for ExitStatusError {
fn into(self) -> ExitStatus {
self.0
}
}
impl ExitStatusError {
pub fn code(self) -> Option<NonZero<i32>> {
self.0
}
}
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
pub struct ExitCode(u8);
impl ExitCode {
pub const SUCCESS: ExitCode = ExitCode(0);
pub const FAILURE: ExitCode = ExitCode(1);
pub fn as_i32(&self) -> i32 {
self.0 as i32
}
}
impl From<u8> for ExitCode {
fn from(code: u8) -> Self {
Self(code)
}
}
pub struct Process(!);
impl Process {
pub fn id(&self) -> u32 {
self.0
}
pub fn kill(&mut self) -> io::Result<()> {
self.0
}
pub fn wait(&mut self) -> io::Result<ExitStatus> {
self.0
}
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
self.0
}
}
pub struct CommandArgs<'a> {
iter: crate::slice::Iter<'a, OsString>,
}
impl<'a> Iterator for CommandArgs<'a> {
type Item = &'a OsStr;
fn next(&mut self) -> Option<&'a OsStr> {
self.iter.next().map(|os| &**os)
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.iter.size_hint()
}
}
impl<'a> ExactSizeIterator for CommandArgs<'a> {
fn len(&self) -> usize {
self.iter.len()
}
fn is_empty(&self) -> bool {
self.iter.is_empty()
}
}
impl<'a> fmt::Debug for CommandArgs<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter.clone()).finish()
}
}
pub type ChildPipe = crate::sys::pipe::Pipe;
pub fn read_output(
out: ChildPipe,
_stdout: &mut Vec<u8>,
_err: ChildPipe,
_stderr: &mut Vec<u8>,
) -> io::Result<()> {
match out.diverge() {}
}

140
justfile
View File

@@ -2,7 +2,6 @@ release := ""
qemu_flags := ""
cargo_flags := "" + if release != "" { "--release" } else { "" }
bin_path := if release != "" { "target/riscv64/release" } else { "target/riscv64/debug" }
rust_src := `rustc --print sysroot` / "lib/rustlib/src/rust/library/std/src"
default: run
@@ -13,143 +12,8 @@ mount_filesystem:
sync_filesystem:
sync
cp_std path:
@echo "Copying {{ path }}"
@mkdir {{ "crates/std/src" / parent_directory(path) }} -p
@cp {{ rust_src / path }} {{ "crates/std/src" / path }}
@sed -i -f patches.sed {{ "crates/std/src" / path }}
insert_target line path:
@sed -i '{{ line }}a \target_os = "survos",' {{ "crates/std/src" / path }}
update_std:
@# Not copied : sys/mod.rs, io.rs, error.rs, thread.rs, sync.rs
# @just cp_std "process.rs"
# @just cp_std "fs.rs"
@just cp_std "time.rs"
@just cp_std "bstr.rs"
@just cp_std "panicking.rs"
@just cp_std "panic.rs"
@just cp_std "collections/hash/map.rs"
@just cp_std "collections/hash/set.rs"
@just cp_std "collections/hash/mod.rs"
@just cp_std "collections/mod.rs"
@just cp_std "io/error.rs"
@just cp_std "io/error/repr_bitpacked.rs"
@just cp_std "io/error/repr_unpacked.rs"
@just cp_std "io/error/tests.rs"
@just cp_std "io/cursor.rs"
@just cp_std "io/cursor/tests.rs"
@just cp_std "io/prelude.rs"
@just cp_std "io/impls.rs"
@just cp_std "io/impls/tests.rs"
@just cp_std "io/tests.rs"
@just cp_std "io/util.rs"
@just cp_std "io/util/tests.rs"
@just cp_std "io/copy.rs"
@just cp_std "io/copy/tests.rs"
@just cp_std "io/pipe.rs"
@just cp_std "io/pipe/tests.rs"
# @just cp_std "io/stdio.rs"
@just cp_std "io/buffered/mod.rs"
@just cp_std "io/buffered/bufreader.rs"
@just cp_std "io/buffered/bufreader/buffer.rs"
@just cp_std "io/buffered/bufwriter.rs"
@just cp_std "io/buffered/linewriter.rs"
@just cp_std "io/buffered/linewritershim.rs"
@just cp_std "sync/once.rs"
@just cp_std "sync/once_lock.rs"
@just cp_std "sync/lazy_lock.rs"
@just cp_std "sync/nonpoison.rs"
@just cp_std "sync/nonpoison/condvar.rs"
@just cp_std "sync/nonpoison/mutex.rs"
@just cp_std "sync/nonpoison/rwlock.rs"
@just cp_std "sync/poison.rs"
@just cp_std "sync/poison/condvar.rs"
@just cp_std "sync/poison/mutex.rs"
@just cp_std "sync/poison/rwlock.rs"
@just cp_std "sync/barrier.rs"
@just cp_std "sync/reentrant_lock.rs"
@just cp_std "sync/mpsc.rs"
@just cp_std "sync/mpmc/mod.rs"
@just cp_std "sync/mpmc/array.rs"
@just cp_std "sync/mpmc/context.rs"
@just cp_std "sync/mpmc/counter.rs"
@just cp_std "sync/mpmc/error.rs"
@just cp_std "sync/mpmc/list.rs"
@just cp_std "sync/mpmc/select.rs"
@just cp_std "sync/mpmc/tests.rs"
@just cp_std "sync/mpmc/utils.rs"
@just cp_std "sync/mpmc/waker.rs"
@just cp_std "sync/mpmc/zero.rs"
@just cp_std "hash/mod.rs"
@just cp_std "hash/random.rs"
@just cp_std "num/mod.rs"
@just cp_std "ffi/c_str.rs"
@just cp_std "ffi/mod.rs"
@just cp_std "ffi/os_str.rs"
@just cp_std "ffi/os_str/tests.rs"
@just cp_std "thread/local.rs"
@just cp_std "thread/thread.rs"
@just cp_std "thread/id.rs"
@just cp_std "thread/main_thread.rs"
@just cp_std "thread/current.rs"
@just cp_std "thread/join_handle.rs"
@just cp_std "thread/functions.rs"
@just cp_std "thread/lifecycle.rs"
@just cp_std "thread/builder.rs"
@just cp_std "thread/scoped.rs"
@just cp_std "thread/spawnhook.rs"
@just cp_std "sys/exit.rs"
@just cp_std "sys/env_consts.rs"
@just cp_std "sys/configure_builtins.rs"
@just cp_std "sys/cmath.rs"
@just cp_std "sys/sync/condvar/mod.rs"
@just cp_std "sys/sync/condvar/no_threads.rs"
@just cp_std "sys/sync/mutex/mod.rs"
@just cp_std "sys/sync/mutex/no_threads.rs"
@just cp_std "sys/sync/once/mod.rs"
@just cp_std "sys/sync/once/no_threads.rs"
@just cp_std "sys/sync/rwlock/mod.rs"
@just cp_std "sys/sync/rwlock/no_threads.rs"
@just cp_std "sys/sync/thread_parking/mod.rs"
@just cp_std "sys/sync/thread_parking/unsupported.rs"
@just cp_std "sys/thread/mod.rs"
@just cp_std "sys/thread/unsupported.rs"
@just cp_std "sys/thread_local/no_threads.rs"
@just cp_std "sys/thread_local/os.rs"
@just cp_std "sys/time/mod.rs"
@just cp_std "sys/time/unsupported.rs"
@just cp_std "sys/random/mod.rs"
@just cp_std "sys/random/unsupported.rs"
@just cp_std "sys/env/mod.rs"
@just cp_std "sys/env/common.rs"
@just cp_std "sys/env/unsupported.rs"
@just cp_std "sys/os_str/mod.rs"
@just cp_std "sys/os_str/bytes.rs"
@just cp_std "sys/os_str/bytes/tests.rs"
@just cp_std "sys/path/mod.rs"
@just cp_std "sys/fs/mod.rs"
@just cp_std "sys/fs/common.rs"
@just cp_std "sys/fs/unsupported.rs"
@just cp_std "sys/io/error/generic.rs"
@just cp_std "sys/io/io_slice/unsupported.rs"
@just cp_std "sys/io/is_terminal/unsupported.rs"
@just cp_std "sys/io/kernel_copy/mod.rs"
@just cp_std "sys/io/mod.rs"
@just cp_std "sys/pipe/mod.rs"
@just cp_std "sys/pipe/unsupported.rs"
@just cp_std "sys/stdio/mod.rs"
@just cp_std "sys/stdio/unsupported.rs"
@just insert_target 108 "sys/random/mod.rs"
@just insert_target 125 "sys/random/mod.rs"
@# Copied but edited for the moment
# @just cp_std "sys/thread_local/mod.rs"
# @just cp_std "sys/alloc/mod.rs"
# @just cp_std "sys/io/error/mod.rs"
# @just cp_std "alloc.rs"
# @just cp_std "path.rs"
# @just cp_std "sys/path/unix.rs"
update-std:
@cd crates/std && just update-std
build_user_prog prog:
RUSTFLAGS="-C relocation-model=pic -C link-arg=-Tuser.ld -C link-arg=-pie" cargo b {{ cargo_flags }} --package {{ prog }}

View File

@@ -1,8 +1,11 @@
#![feature(custom_std)]
fn main() -> isize {
fn main() {
let a = std::env::args();
for a in a {
println!("Argument: {}", a);
}
println!(
"Hello from PIC program loaded dynamically with custom std and a better justfile, and syscalls ! "
);
0
}

View File

@@ -2,7 +2,7 @@
#![allow(unused)]
use io::{Read, Write};
use std::{io::stdin, syscall};
use std::{io::{Stdin, stdin}, syscall};
fn main() {
// let mut input = String::new();
@@ -15,8 +15,8 @@ fn main() {
syscall::spawn("/usr/bin/shell");
loop {
let mut test = [0; 2];
let len = stdin().read(&mut test).unwrap();
let len = tty.read(&mut test).unwrap();
tty.write(str::from_utf8(&test[..len as usize]).unwrap().as_bytes())
.unwrap();
.unwrap();
}
}