Add Motor OS std library port
Motor OS was added as a no-std Tier-3 target in https://github.com/rust-lang/rust/pull/146848 as x86_64-unknown-motor. This patch/PR adds the std library for Motor OS. While the patch may seem large, all it does is proxy std pal calls to moto-rt. When there is some non-trivial code (e.g. thread::spawn), it is quite similar, and often identical, to what other platforms do.
This commit is contained in:
@@ -166,6 +166,16 @@ dependencies = [
|
|||||||
"rustc-std-workspace-core",
|
"rustc-std-workspace-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "moto-rt"
|
||||||
|
version = "0.15.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "058a2807a30527bee4c30df7ababe971cdde94372d4dbd1ff145bb403381436c"
|
||||||
|
dependencies = [
|
||||||
|
"rustc-std-workspace-alloc",
|
||||||
|
"rustc-std-workspace-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.37.3"
|
version = "0.37.3"
|
||||||
@@ -316,6 +326,7 @@ dependencies = [
|
|||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
|
"moto-rt",
|
||||||
"object",
|
"object",
|
||||||
"panic_abort",
|
"panic_abort",
|
||||||
"panic_unwind",
|
"panic_unwind",
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ fortanix-sgx-abi = { version = "0.6.1", features = [
|
|||||||
'rustc-dep-of-std',
|
'rustc-dep-of-std',
|
||||||
], public = true }
|
], public = true }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "motor")'.dependencies]
|
||||||
|
moto-rt = { version = "0.15", features = ['rustc-dep-of-std'], public = true }
|
||||||
|
|
||||||
[target.'cfg(target_os = "hermit")'.dependencies]
|
[target.'cfg(target_os = "hermit")'.dependencies]
|
||||||
hermit-abi = { version = "0.5.0", features = [
|
hermit-abi = { version = "0.5.0", features = [
|
||||||
'rustc-dep-of-std',
|
'rustc-dep-of-std',
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ fn main() {
|
|||||||
|| target_os == "windows"
|
|| target_os == "windows"
|
||||||
|| target_os == "fuchsia"
|
|| target_os == "fuchsia"
|
||||||
|| (target_vendor == "fortanix" && target_env == "sgx")
|
|| (target_vendor == "fortanix" && target_env == "sgx")
|
||||||
|
|| target_os == "motor"
|
||||||
|| target_os == "hermit"
|
|| target_os == "hermit"
|
||||||
|| target_os == "trusty"
|
|| target_os == "trusty"
|
||||||
|| target_os == "l4re"
|
|| target_os == "l4re"
|
||||||
|
|||||||
@@ -3,6 +3,9 @@
|
|||||||
#![stable(feature = "io_safety", since = "1.63.0")]
|
#![stable(feature = "io_safety", since = "1.63.0")]
|
||||||
#![deny(unsafe_op_in_unsafe_fn)]
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
|
#[cfg(target_os = "motor")]
|
||||||
|
use moto_rt::libc;
|
||||||
|
|
||||||
use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||||
#[cfg(not(target_os = "trusty"))]
|
#[cfg(not(target_os = "trusty"))]
|
||||||
use crate::fs;
|
use crate::fs;
|
||||||
@@ -12,7 +15,8 @@ use crate::mem::ManuallyDrop;
|
|||||||
target_arch = "wasm32",
|
target_arch = "wasm32",
|
||||||
target_env = "sgx",
|
target_env = "sgx",
|
||||||
target_os = "hermit",
|
target_os = "hermit",
|
||||||
target_os = "trusty"
|
target_os = "trusty",
|
||||||
|
target_os = "motor"
|
||||||
)))]
|
)))]
|
||||||
use crate::sys::cvt;
|
use crate::sys::cvt;
|
||||||
#[cfg(not(target_os = "trusty"))]
|
#[cfg(not(target_os = "trusty"))]
|
||||||
@@ -95,7 +99,12 @@ impl OwnedFd {
|
|||||||
impl BorrowedFd<'_> {
|
impl BorrowedFd<'_> {
|
||||||
/// Creates a new `OwnedFd` instance that shares the same underlying file
|
/// Creates a new `OwnedFd` instance that shares the same underlying file
|
||||||
/// description as the existing `BorrowedFd` instance.
|
/// description as the existing `BorrowedFd` instance.
|
||||||
#[cfg(not(any(target_arch = "wasm32", target_os = "hermit", target_os = "trusty")))]
|
#[cfg(not(any(
|
||||||
|
target_arch = "wasm32",
|
||||||
|
target_os = "hermit",
|
||||||
|
target_os = "trusty",
|
||||||
|
target_os = "motor"
|
||||||
|
)))]
|
||||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
|
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
|
||||||
// We want to atomically duplicate this file descriptor and set the
|
// We want to atomically duplicate this file descriptor and set the
|
||||||
@@ -123,6 +132,15 @@ impl BorrowedFd<'_> {
|
|||||||
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
|
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
|
||||||
Err(crate::io::Error::UNSUPPORTED_PLATFORM)
|
Err(crate::io::Error::UNSUPPORTED_PLATFORM)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a new `OwnedFd` instance that shares the same underlying file
|
||||||
|
/// description as the existing `BorrowedFd` instance.
|
||||||
|
#[cfg(target_os = "motor")]
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
|
||||||
|
let fd = moto_rt::fs::duplicate(self.as_raw_fd()).map_err(crate::sys::map_motor_error)?;
|
||||||
|
Ok(unsafe { OwnedFd::from_raw_fd(fd) })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
|||||||
@@ -4,13 +4,17 @@
|
|||||||
|
|
||||||
#[cfg(target_os = "hermit")]
|
#[cfg(target_os = "hermit")]
|
||||||
use hermit_abi as libc;
|
use hermit_abi as libc;
|
||||||
|
#[cfg(target_os = "motor")]
|
||||||
|
use moto_rt::libc;
|
||||||
|
|
||||||
|
#[cfg(target_os = "motor")]
|
||||||
|
use super::owned::OwnedFd;
|
||||||
#[cfg(not(target_os = "trusty"))]
|
#[cfg(not(target_os = "trusty"))]
|
||||||
use crate::fs;
|
use crate::fs;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
#[cfg(target_os = "hermit")]
|
#[cfg(target_os = "hermit")]
|
||||||
use crate::os::hermit::io::OwnedFd;
|
use crate::os::hermit::io::OwnedFd;
|
||||||
#[cfg(not(target_os = "hermit"))]
|
#[cfg(all(not(target_os = "hermit"), not(target_os = "motor")))]
|
||||||
use crate::os::raw;
|
use crate::os::raw;
|
||||||
#[cfg(all(doc, not(target_arch = "wasm32")))]
|
#[cfg(all(doc, not(target_arch = "wasm32")))]
|
||||||
use crate::os::unix::io::AsFd;
|
use crate::os::unix::io::AsFd;
|
||||||
@@ -23,10 +27,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
|
|||||||
|
|
||||||
/// Raw file descriptors.
|
/// Raw file descriptors.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(not(target_os = "hermit"))]
|
#[cfg(all(not(target_os = "hermit"), not(target_os = "motor")))]
|
||||||
pub type RawFd = raw::c_int;
|
pub type RawFd = raw::c_int;
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(target_os = "hermit")]
|
#[cfg(any(target_os = "hermit", target_os = "motor"))]
|
||||||
pub type RawFd = i32;
|
pub type RawFd = i32;
|
||||||
|
|
||||||
/// A trait to extract the raw file descriptor from an underlying object.
|
/// A trait to extract the raw file descriptor from an underlying object.
|
||||||
|
|||||||
@@ -155,6 +155,8 @@ pub mod ios;
|
|||||||
pub mod l4re;
|
pub mod l4re;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
pub mod macos;
|
pub mod macos;
|
||||||
|
#[cfg(target_os = "motor")]
|
||||||
|
pub mod motor;
|
||||||
#[cfg(target_os = "netbsd")]
|
#[cfg(target_os = "netbsd")]
|
||||||
pub mod netbsd;
|
pub mod netbsd;
|
||||||
#[cfg(target_os = "nto")]
|
#[cfg(target_os = "nto")]
|
||||||
@@ -182,7 +184,14 @@ pub mod vxworks;
|
|||||||
#[cfg(target_os = "xous")]
|
#[cfg(target_os = "xous")]
|
||||||
pub mod xous;
|
pub mod xous;
|
||||||
|
|
||||||
#[cfg(any(unix, target_os = "hermit", target_os = "trusty", target_os = "wasi", doc))]
|
#[cfg(any(
|
||||||
|
unix,
|
||||||
|
target_os = "hermit",
|
||||||
|
target_os = "trusty",
|
||||||
|
target_os = "wasi",
|
||||||
|
target_os = "motor",
|
||||||
|
doc
|
||||||
|
))]
|
||||||
pub mod fd;
|
pub mod fd;
|
||||||
|
|
||||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin", doc))]
|
#[cfg(any(target_os = "linux", target_os = "android", target_os = "cygwin", doc))]
|
||||||
|
|||||||
37
library/std/src/os/motor/ffi.rs
Normal file
37
library/std/src/os/motor/ffi.rs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
//! Motor OS-specific extensions to primitives in the [`std::ffi`] module.
|
||||||
|
#![unstable(feature = "motor_ext", issue = "147456")]
|
||||||
|
|
||||||
|
use crate::ffi::{OsStr, OsString};
|
||||||
|
use crate::sealed::Sealed;
|
||||||
|
|
||||||
|
/// Motor OS-specific extensions to [`OsString`].
|
||||||
|
///
|
||||||
|
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||||
|
/// This is so that future additional methods are not breaking changes.
|
||||||
|
pub trait OsStringExt: Sealed {
|
||||||
|
/// Motor OS strings are utf-8, and thus just strings.
|
||||||
|
fn as_str(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsStringExt for OsString {
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> &str {
|
||||||
|
self.to_str().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Motor OS-specific extensions to [`OsString`].
|
||||||
|
///
|
||||||
|
/// This trait is sealed: it cannot be implemented outside the standard library.
|
||||||
|
/// This is so that future additional methods are not breaking changes.
|
||||||
|
pub trait OsStrExt: Sealed {
|
||||||
|
/// Motor OS strings are utf-8, and thus just strings.
|
||||||
|
fn as_str(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OsStrExt for OsStr {
|
||||||
|
#[inline]
|
||||||
|
fn as_str(&self) -> &str {
|
||||||
|
self.to_str().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
4
library/std/src/os/motor/mod.rs
Normal file
4
library/std/src/os/motor/mod.rs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#![unstable(feature = "motor_ext", issue = "147456")]
|
||||||
|
|
||||||
|
pub mod ffi;
|
||||||
|
pub mod process;
|
||||||
15
library/std/src/os/motor/process.rs
Normal file
15
library/std/src/os/motor/process.rs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#![unstable(feature = "motor_ext", issue = "147456")]
|
||||||
|
|
||||||
|
use crate::sealed::Sealed;
|
||||||
|
use crate::sys_common::AsInner;
|
||||||
|
|
||||||
|
pub trait ChildExt: Sealed {
|
||||||
|
/// Extracts the main thread raw handle, without taking ownership
|
||||||
|
fn sys_handle(&self) -> u64;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ChildExt for crate::process::Child {
|
||||||
|
fn sys_handle(&self) -> u64 {
|
||||||
|
self.as_inner().handle()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -83,6 +83,9 @@ cfg_select! {
|
|||||||
target_os = "hermit" => {
|
target_os = "hermit" => {
|
||||||
mod hermit;
|
mod hermit;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
}
|
||||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||||
mod sgx;
|
mod sgx;
|
||||||
}
|
}
|
||||||
|
|||||||
28
library/std/src/sys/alloc/motor.rs
Normal file
28
library/std/src/sys/alloc/motor.rs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
use crate::alloc::{GlobalAlloc, Layout, System};
|
||||||
|
|
||||||
|
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||||
|
unsafe impl GlobalAlloc for System {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
// SAFETY: same requirements as in GlobalAlloc::alloc.
|
||||||
|
moto_rt::alloc::alloc(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||||
|
// SAFETY: same requirements as in GlobalAlloc::alloc_zeroed.
|
||||||
|
moto_rt::alloc::alloc_zeroed(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
// SAFETY: same requirements as in GlobalAlloc::dealloc.
|
||||||
|
unsafe { moto_rt::alloc::dealloc(ptr, layout) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||||
|
// SAFETY: same requirements as in GlobalAlloc::realloc.
|
||||||
|
unsafe { moto_rt::alloc::realloc(ptr, layout, new_size) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,10 @@ cfg_select! {
|
|||||||
mod windows;
|
mod windows;
|
||||||
pub use windows::{AnonPipe, pipe};
|
pub use windows::{AnonPipe, pipe};
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::{AnonPipe, pipe};
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
mod unsupported;
|
mod unsupported;
|
||||||
pub use unsupported::{AnonPipe, pipe};
|
pub use unsupported::{AnonPipe, pipe};
|
||||||
|
|||||||
11
library/std/src/sys/anonymous_pipe/motor.rs
Normal file
11
library/std/src/sys/anonymous_pipe/motor.rs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
use crate::io;
|
||||||
|
use crate::sys::fd::FileDesc;
|
||||||
|
use crate::sys::pipe::anon_pipe;
|
||||||
|
use crate::sys_common::IntoInner;
|
||||||
|
|
||||||
|
pub type AnonPipe = FileDesc;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||||
|
anon_pipe().map(|(rx, wx)| (rx.into_inner(), wx.into_inner()))
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
|
all(target_family = "unix", not(any(target_os = "espidf", target_os = "vita"))),
|
||||||
target_family = "windows",
|
target_family = "windows",
|
||||||
target_os = "hermit",
|
target_os = "hermit",
|
||||||
|
target_os = "motor",
|
||||||
target_os = "uefi",
|
target_os = "uefi",
|
||||||
target_os = "wasi",
|
target_os = "wasi",
|
||||||
target_os = "xous",
|
target_os = "xous",
|
||||||
@@ -28,6 +29,10 @@ cfg_select! {
|
|||||||
mod sgx;
|
mod sgx;
|
||||||
pub use sgx::*;
|
pub use sgx::*;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::*;
|
||||||
|
}
|
||||||
target_os = "uefi" => {
|
target_os = "uefi" => {
|
||||||
mod uefi;
|
mod uefi;
|
||||||
pub use uefi::*;
|
pub use uefi::*;
|
||||||
|
|||||||
13
library/std/src/sys/args/motor.rs
Normal file
13
library/std/src/sys/args/motor.rs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
pub use super::common::Args;
|
||||||
|
use crate::ffi::OsString;
|
||||||
|
|
||||||
|
pub fn args() -> Args {
|
||||||
|
let motor_args: Vec<String> = moto_rt::process::args();
|
||||||
|
let mut rust_args = Vec::new();
|
||||||
|
|
||||||
|
for arg in motor_args {
|
||||||
|
rust_args.push(OsString::from(arg));
|
||||||
|
}
|
||||||
|
|
||||||
|
Args::new(rust_args)
|
||||||
|
}
|
||||||
5
library/std/src/sys/env/mod.rs
vendored
5
library/std/src/sys/env/mod.rs
vendored
@@ -5,6 +5,7 @@
|
|||||||
#[cfg(any(
|
#[cfg(any(
|
||||||
target_family = "unix",
|
target_family = "unix",
|
||||||
target_os = "hermit",
|
target_os = "hermit",
|
||||||
|
target_os = "motor",
|
||||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||||
target_os = "solid_asp3",
|
target_os = "solid_asp3",
|
||||||
target_os = "uefi",
|
target_os = "uefi",
|
||||||
@@ -26,6 +27,10 @@ cfg_select! {
|
|||||||
mod hermit;
|
mod hermit;
|
||||||
pub use hermit::*;
|
pub use hermit::*;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::*;
|
||||||
|
}
|
||||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||||
mod sgx;
|
mod sgx;
|
||||||
pub use sgx::*;
|
pub use sgx::*;
|
||||||
|
|||||||
27
library/std/src/sys/env/motor.rs
vendored
Normal file
27
library/std/src/sys/env/motor.rs
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
pub use super::common::Env;
|
||||||
|
use crate::ffi::{OsStr, OsString};
|
||||||
|
use crate::io;
|
||||||
|
use crate::os::motor::ffi::OsStrExt;
|
||||||
|
|
||||||
|
pub fn env() -> Env {
|
||||||
|
let motor_env: Vec<(String, String)> = moto_rt::process::env();
|
||||||
|
let mut rust_env = vec![];
|
||||||
|
|
||||||
|
for (k, v) in motor_env {
|
||||||
|
rust_env.push((OsString::from(k), OsString::from(v)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Env::new(rust_env)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getenv(key: &OsStr) -> Option<OsString> {
|
||||||
|
moto_rt::process::getenv(key.as_str()).map(|s| OsString::from(s))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn setenv(key: &OsStr, val: &OsStr) -> io::Result<()> {
|
||||||
|
Ok(moto_rt::process::setenv(key.as_str(), val.as_str()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn unsetenv(key: &OsStr) -> io::Result<()> {
|
||||||
|
Ok(moto_rt::process::unsetenv(key.as_str()))
|
||||||
|
}
|
||||||
@@ -11,6 +11,10 @@ cfg_select! {
|
|||||||
mod hermit;
|
mod hermit;
|
||||||
pub use hermit::*;
|
pub use hermit::*;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::*;
|
||||||
|
}
|
||||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||||
mod sgx;
|
mod sgx;
|
||||||
pub use sgx::*;
|
pub use sgx::*;
|
||||||
|
|||||||
124
library/std/src/sys/fd/motor.rs
Normal file
124
library/std/src/sys/fd/motor.rs
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
#![unstable(reason = "not public", issue = "none", feature = "fd")]
|
||||||
|
|
||||||
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read};
|
||||||
|
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||||
|
use crate::sys::map_motor_error;
|
||||||
|
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct FileDesc(OwnedFd);
|
||||||
|
|
||||||
|
impl FileDesc {
|
||||||
|
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::read(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
|
crate::io::default_read_buf(|buf| self.read(buf), cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
|
io::default_read_vectored(|b| self.read(b), bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
|
let mut me = self;
|
||||||
|
(&mut me).read_to_end(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::write(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
|
crate::io::default_write_vectored(|b| self.write(b), bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_write_vectored(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_read_vectored(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_nonblocking(self.as_raw_fd(), nonblocking).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn duplicate(&self) -> io::Result<FileDesc> {
|
||||||
|
let fd = moto_rt::fs::duplicate(self.as_raw_fd()).map_err(map_motor_error)?;
|
||||||
|
// SAFETY: safe because we just got it from the OS runtime.
|
||||||
|
unsafe { Ok(Self::from_raw_fd(fd)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn try_clone(&self) -> io::Result<Self> {
|
||||||
|
self.duplicate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Read for &'a FileDesc {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
(**self).read(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
|
(**self).read_buf(cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
|
(**self).read_vectored(bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn is_read_vectored(&self) -> bool {
|
||||||
|
(**self).is_read_vectored()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInner<OwnedFd> for FileDesc {
|
||||||
|
#[inline]
|
||||||
|
fn as_inner(&self) -> &OwnedFd {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoInner<OwnedFd> for FileDesc {
|
||||||
|
fn into_inner(self) -> OwnedFd {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<OwnedFd> for FileDesc {
|
||||||
|
fn from_inner(owned_fd: OwnedFd) -> Self {
|
||||||
|
Self(owned_fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsFd for FileDesc {
|
||||||
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||||
|
self.0.as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for FileDesc {
|
||||||
|
#[inline]
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoRawFd for FileDesc {
|
||||||
|
fn into_raw_fd(self) -> RawFd {
|
||||||
|
self.0.into_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawFd for FileDesc {
|
||||||
|
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||||
|
unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,10 @@ cfg_select! {
|
|||||||
mod hermit;
|
mod hermit;
|
||||||
use hermit as imp;
|
use hermit as imp;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
use motor as imp;
|
||||||
|
}
|
||||||
target_os = "solid_asp3" => {
|
target_os = "solid_asp3" => {
|
||||||
mod solid;
|
mod solid;
|
||||||
use solid as imp;
|
use solid as imp;
|
||||||
|
|||||||
478
library/std/src/sys/fs/motor.rs
Normal file
478
library/std/src/sys/fs/motor.rs
Normal file
@@ -0,0 +1,478 @@
|
|||||||
|
use crate::ffi::OsString;
|
||||||
|
use crate::hash::Hash;
|
||||||
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
|
||||||
|
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||||
|
use crate::path::{Path, PathBuf};
|
||||||
|
use crate::sys::fd::FileDesc;
|
||||||
|
pub use crate::sys::fs::common::exists;
|
||||||
|
use crate::sys::time::SystemTime;
|
||||||
|
use crate::sys::{map_motor_error, unsupported};
|
||||||
|
use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct FileType {
|
||||||
|
rt_filetype: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileType {
|
||||||
|
pub fn is_dir(&self) -> bool {
|
||||||
|
self.rt_filetype == moto_rt::fs::FILETYPE_DIRECTORY
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_file(&self) -> bool {
|
||||||
|
self.rt_filetype == moto_rt::fs::FILETYPE_FILE
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_symlink(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||||
|
pub struct FilePermissions {
|
||||||
|
rt_perm: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FilePermissions {
|
||||||
|
pub fn readonly(&self) -> bool {
|
||||||
|
(self.rt_perm & moto_rt::fs::PERM_WRITE == 0)
|
||||||
|
&& (self.rt_perm & moto_rt::fs::PERM_READ != 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_readonly(&mut self, readonly: bool) {
|
||||||
|
if readonly {
|
||||||
|
self.rt_perm = moto_rt::fs::PERM_READ;
|
||||||
|
} else {
|
||||||
|
self.rt_perm = moto_rt::fs::PERM_READ | moto_rt::fs::PERM_WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, Default)]
|
||||||
|
pub struct FileTimes {
|
||||||
|
modified: u128,
|
||||||
|
accessed: u128,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileTimes {
|
||||||
|
pub fn set_accessed(&mut self, t: SystemTime) {
|
||||||
|
self.accessed = t.as_u128();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_modified(&mut self, t: SystemTime) {
|
||||||
|
self.modified = t.as_u128();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub struct FileAttr {
|
||||||
|
inner: moto_rt::fs::FileAttr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileAttr {
|
||||||
|
pub fn size(&self) -> u64 {
|
||||||
|
self.inner.size
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn perm(&self) -> FilePermissions {
|
||||||
|
FilePermissions { rt_perm: self.inner.perm }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_type(&self) -> FileType {
|
||||||
|
FileType { rt_filetype: self.inner.file_type }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||||
|
match self.inner.modified {
|
||||||
|
0 => Err(crate::io::Error::from(crate::io::ErrorKind::Other)),
|
||||||
|
x => Ok(SystemTime::from_u128(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||||
|
match self.inner.accessed {
|
||||||
|
0 => Err(crate::io::Error::from(crate::io::ErrorKind::Other)),
|
||||||
|
x => Ok(SystemTime::from_u128(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn created(&self) -> io::Result<SystemTime> {
|
||||||
|
match self.inner.created {
|
||||||
|
0 => Err(crate::io::Error::from(crate::io::ErrorKind::Other)),
|
||||||
|
x => Ok(SystemTime::from_u128(x)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct OpenOptions {
|
||||||
|
rt_open_options: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OpenOptions {
|
||||||
|
pub fn new() -> OpenOptions {
|
||||||
|
OpenOptions { rt_open_options: 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&mut self, read: bool) {
|
||||||
|
if read {
|
||||||
|
self.rt_open_options |= moto_rt::fs::O_READ;
|
||||||
|
} else {
|
||||||
|
self.rt_open_options &= !moto_rt::fs::O_READ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&mut self, write: bool) {
|
||||||
|
if write {
|
||||||
|
self.rt_open_options |= moto_rt::fs::O_WRITE;
|
||||||
|
} else {
|
||||||
|
self.rt_open_options &= !moto_rt::fs::O_WRITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn append(&mut self, append: bool) {
|
||||||
|
if append {
|
||||||
|
self.rt_open_options |= moto_rt::fs::O_APPEND;
|
||||||
|
} else {
|
||||||
|
self.rt_open_options &= !moto_rt::fs::O_APPEND;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn truncate(&mut self, truncate: bool) {
|
||||||
|
if truncate {
|
||||||
|
self.rt_open_options |= moto_rt::fs::O_TRUNCATE;
|
||||||
|
} else {
|
||||||
|
self.rt_open_options &= !moto_rt::fs::O_TRUNCATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(&mut self, create: bool) {
|
||||||
|
if create {
|
||||||
|
self.rt_open_options |= moto_rt::fs::O_CREATE;
|
||||||
|
} else {
|
||||||
|
self.rt_open_options &= !moto_rt::fs::O_CREATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_new(&mut self, create_new: bool) {
|
||||||
|
if create_new {
|
||||||
|
self.rt_open_options |= moto_rt::fs::O_CREATE_NEW;
|
||||||
|
} else {
|
||||||
|
self.rt_open_options &= !moto_rt::fs::O_CREATE_NEW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct File(FileDesc);
|
||||||
|
|
||||||
|
impl File {
|
||||||
|
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::open(path, opts.rt_open_options)
|
||||||
|
.map(|fd| unsafe { Self::from_raw_fd(fd) })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||||
|
moto_rt::fs::get_file_attr(self.as_raw_fd())
|
||||||
|
.map(|inner| -> FileAttr { FileAttr { inner } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn fsync(&self) -> io::Result<()> {
|
||||||
|
moto_rt::fs::fsync(self.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn datasync(&self) -> io::Result<()> {
|
||||||
|
moto_rt::fs::datasync(self.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn truncate(&self, size: u64) -> io::Result<()> {
|
||||||
|
moto_rt::fs::truncate(self.as_raw_fd(), size).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::read(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
|
crate::io::default_read_vectored(|b| self.read(b), bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_read_vectored(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
|
crate::io::default_read_buf(|buf| self.read(buf), cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::write(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
|
crate::io::default_write_vectored(|b| self.write(b), bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_write_vectored(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flush(&self) -> io::Result<()> {
|
||||||
|
moto_rt::fs::flush(self.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
|
||||||
|
match pos {
|
||||||
|
SeekFrom::Start(offset) => {
|
||||||
|
moto_rt::fs::seek(self.as_raw_fd(), offset as i64, moto_rt::fs::SEEK_SET)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
SeekFrom::End(offset) => {
|
||||||
|
moto_rt::fs::seek(self.as_raw_fd(), offset, moto_rt::fs::SEEK_END)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
SeekFrom::Current(offset) => {
|
||||||
|
moto_rt::fs::seek(self.as_raw_fd(), offset, moto_rt::fs::SEEK_CUR)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tell(&self) -> io::Result<u64> {
|
||||||
|
self.seek(SeekFrom::Current(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duplicate(&self) -> io::Result<File> {
|
||||||
|
moto_rt::fs::duplicate(self.as_raw_fd())
|
||||||
|
.map(|fd| unsafe { Self::from_raw_fd(fd) })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_permissions(&self, perm: FilePermissions) -> io::Result<()> {
|
||||||
|
moto_rt::fs::set_file_perm(self.as_raw_fd(), perm.rt_perm).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
|
||||||
|
unsupported() // Let's not do that.
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lock(&self) -> io::Result<()> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lock_shared(&self) -> io::Result<()> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_lock(&self) -> Result<(), crate::fs::TryLockError> {
|
||||||
|
Err(crate::fs::TryLockError::Error(io::Error::from(io::ErrorKind::Unsupported)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_lock_shared(&self) -> Result<(), crate::fs::TryLockError> {
|
||||||
|
Err(crate::fs::TryLockError::Error(io::Error::from(io::ErrorKind::Unsupported)))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlock(&self) -> io::Result<()> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> Option<io::Result<u64>> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct DirBuilder {}
|
||||||
|
|
||||||
|
impl DirBuilder {
|
||||||
|
pub fn new() -> DirBuilder {
|
||||||
|
DirBuilder {}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mkdir(&self, path: &Path) -> io::Result<()> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::mkdir(path).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unlink(path: &Path) -> io::Result<()> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::unlink(path).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||||
|
let old = old.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
let new = new.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::rename(old, new).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rmdir(path: &Path) -> io::Result<()> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::rmdir(path).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::rmdir_all(path).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_perm(path: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::set_perm(path, perm.rt_perm).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||||
|
unsupported()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn stat(path: &Path) -> io::Result<FileAttr> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
let inner = moto_rt::fs::stat(path).map_err(map_motor_error)?;
|
||||||
|
Ok(FileAttr { inner })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lstat(path: &Path) -> io::Result<FileAttr> {
|
||||||
|
stat(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn canonicalize(path: &Path) -> io::Result<PathBuf> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
let path = moto_rt::fs::canonicalize(path).map_err(map_motor_error)?;
|
||||||
|
Ok(path.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
|
||||||
|
let from = from.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
let to = to.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
moto_rt::fs::copy(from, to).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct ReadDir {
|
||||||
|
rt_fd: moto_rt::RtFd,
|
||||||
|
path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for ReadDir {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
moto_rt::fs::closedir(self.rt_fd).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn readdir(path: &Path) -> io::Result<ReadDir> {
|
||||||
|
let path = path.to_str().ok_or(io::Error::from(io::ErrorKind::InvalidFilename))?;
|
||||||
|
Ok(ReadDir {
|
||||||
|
rt_fd: moto_rt::fs::opendir(path).map_err(map_motor_error)?,
|
||||||
|
path: path.to_owned(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for ReadDir {
|
||||||
|
type Item = io::Result<DirEntry>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||||
|
match moto_rt::fs::readdir(self.rt_fd).map_err(map_motor_error) {
|
||||||
|
Ok(maybe_item) => match maybe_item {
|
||||||
|
Some(inner) => Some(Ok(DirEntry { inner, parent_path: self.path.clone() })),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
Err(err) => Some(Err(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DirEntry {
|
||||||
|
parent_path: String,
|
||||||
|
inner: moto_rt::fs::DirEntry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DirEntry {
|
||||||
|
fn filename(&self) -> &str {
|
||||||
|
core::str::from_utf8(unsafe {
|
||||||
|
core::slice::from_raw_parts(self.inner.fname.as_ptr(), self.inner.fname_size as usize)
|
||||||
|
})
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> PathBuf {
|
||||||
|
let mut path = self.parent_path.clone();
|
||||||
|
path.push_str("/");
|
||||||
|
path.push_str(self.filename());
|
||||||
|
path.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_name(&self) -> OsString {
|
||||||
|
self.filename().to_owned().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||||
|
Ok(FileAttr { inner: self.inner.attr })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn file_type(&self) -> io::Result<FileType> {
|
||||||
|
Ok(FileType { rt_filetype: self.inner.attr.file_type })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInner<FileDesc> for File {
|
||||||
|
#[inline]
|
||||||
|
fn as_inner(&self) -> &FileDesc {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInnerMut<FileDesc> for File {
|
||||||
|
#[inline]
|
||||||
|
fn as_inner_mut(&mut self) -> &mut FileDesc {
|
||||||
|
&mut self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoInner<FileDesc> for File {
|
||||||
|
fn into_inner(self) -> FileDesc {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<FileDesc> for File {
|
||||||
|
fn from_inner(file_desc: FileDesc) -> Self {
|
||||||
|
Self(file_desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsFd for File {
|
||||||
|
#[inline]
|
||||||
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||||
|
self.0.as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for File {
|
||||||
|
#[inline]
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoRawFd for File {
|
||||||
|
fn into_raw_fd(self) -> RawFd {
|
||||||
|
self.0.into_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawFd for File {
|
||||||
|
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||||
|
unsafe { Self(FromRawFd::from_raw_fd(raw_fd)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
6
library/std/src/sys/io/is_terminal/motor.rs
Normal file
6
library/std/src/sys/io/is_terminal/motor.rs
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
use crate::os::fd::{AsFd, AsRawFd};
|
||||||
|
|
||||||
|
pub fn is_terminal(fd: &impl AsFd) -> bool {
|
||||||
|
let fd = fd.as_fd();
|
||||||
|
moto_rt::fs::is_terminal(fd.as_raw_fd())
|
||||||
|
}
|
||||||
@@ -39,6 +39,10 @@ mod is_terminal {
|
|||||||
mod hermit;
|
mod hermit;
|
||||||
pub use hermit::*;
|
pub use hermit::*;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::*;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
mod unsupported;
|
mod unsupported;
|
||||||
pub use unsupported::*;
|
pub use unsupported::*;
|
||||||
|
|||||||
@@ -17,6 +17,10 @@ cfg_select! {
|
|||||||
mod wasip1;
|
mod wasip1;
|
||||||
pub use wasip1::*;
|
pub use wasip1::*;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::*;
|
||||||
|
}
|
||||||
target_os = "xous" => {
|
target_os = "xous" => {
|
||||||
mod xous;
|
mod xous;
|
||||||
pub use xous::*;
|
pub use xous::*;
|
||||||
|
|||||||
521
library/std/src/sys/net/connection/motor.rs
Normal file
521
library/std/src/sys/net/connection/motor.rs
Normal file
@@ -0,0 +1,521 @@
|
|||||||
|
pub use moto_rt::netc;
|
||||||
|
|
||||||
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
|
use crate::net::SocketAddr::{V4, V6};
|
||||||
|
use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, ToSocketAddrs};
|
||||||
|
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||||
|
use crate::sys::fd::FileDesc;
|
||||||
|
use crate::sys::map_motor_error;
|
||||||
|
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||||
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
// We want to re-use as much of Rust's stdlib code as possible,
|
||||||
|
// and most of it is unixy, but with a lot of nesting.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct Socket(FileDesc);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TcpStream {
|
||||||
|
inner: Socket,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TcpStream {
|
||||||
|
pub fn socket(&self) -> &Socket {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_socket(self) -> Socket {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
|
||||||
|
let addr = into_netc(&addr.to_socket_addrs()?.next().unwrap());
|
||||||
|
moto_rt::net::tcp_connect(&addr, Duration::MAX, false)
|
||||||
|
.map(|fd| Self { inner: unsafe { Socket::from_raw_fd(fd) } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
|
||||||
|
let addr = into_netc(addr);
|
||||||
|
moto_rt::net::tcp_connect(&addr, timeout, false)
|
||||||
|
.map(|fd| Self { inner: unsafe { Socket::from_raw_fd(fd) } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_read_timeout(self.inner.as_raw_fd(), timeout).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_write_timeout(self.inner.as_raw_fd(), timeout).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||||
|
moto_rt::net::read_timeout(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||||
|
moto_rt::net::write_timeout(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::net::peek(self.inner.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::read(self.inner.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
|
crate::io::default_read_buf(|buf| self.read(buf), cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
|
let bufs: &mut [&mut [u8]] = unsafe { core::mem::transmute(bufs) };
|
||||||
|
moto_rt::fs::read_vectored(self.inner.as_raw_fd(), bufs).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_read_vectored(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::write(self.inner.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
|
let bufs: &[&[u8]] = unsafe { core::mem::transmute(bufs) };
|
||||||
|
moto_rt::fs::write_vectored(self.inner.as_raw_fd(), bufs).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_write_vectored(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||||
|
moto_rt::net::peer_addr(self.inner.as_raw_fd())
|
||||||
|
.map(|addr| from_netc(&addr))
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||||
|
moto_rt::net::socket_addr(self.inner.as_raw_fd())
|
||||||
|
.map(|addr| from_netc(&addr))
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shutdown(&self, shutdown: Shutdown) -> io::Result<()> {
|
||||||
|
let shutdown = match shutdown {
|
||||||
|
Shutdown::Read => moto_rt::net::SHUTDOWN_READ,
|
||||||
|
Shutdown::Write => moto_rt::net::SHUTDOWN_WRITE,
|
||||||
|
Shutdown::Both => moto_rt::net::SHUTDOWN_READ | moto_rt::net::SHUTDOWN_WRITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
moto_rt::net::shutdown(self.inner.as_raw_fd(), shutdown).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duplicate(&self) -> io::Result<TcpStream> {
|
||||||
|
moto_rt::fs::duplicate(self.inner.as_raw_fd())
|
||||||
|
.map(|fd| Self { inner: unsafe { Socket::from_raw_fd(fd) } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_linger(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_linger(self.inner.as_raw_fd(), timeout).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linger(&self) -> io::Result<Option<Duration>> {
|
||||||
|
moto_rt::net::linger(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_nodelay(self.inner.as_raw_fd(), nodelay).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn nodelay(&self) -> io::Result<bool> {
|
||||||
|
moto_rt::net::nodelay(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_ttl(self.inner.as_raw_fd(), ttl).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ttl(&self) -> io::Result<u32> {
|
||||||
|
moto_rt::net::ttl(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||||
|
let e = moto_rt::net::take_error(self.inner.as_raw_fd()).map_err(map_motor_error)?;
|
||||||
|
if e == moto_rt::E_OK { Ok(None) } else { Ok(Some(map_motor_error(e))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_nonblocking(self.inner.as_raw_fd(), nonblocking).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct TcpListener {
|
||||||
|
inner: Socket,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TcpListener {
|
||||||
|
#[inline]
|
||||||
|
pub fn socket(&self) -> &Socket {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_socket(self) -> Socket {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
|
||||||
|
let addr = into_netc(&addr.to_socket_addrs()?.next().unwrap());
|
||||||
|
moto_rt::net::bind(moto_rt::net::PROTO_TCP, &addr)
|
||||||
|
.map(|fd| Self { inner: unsafe { Socket::from_raw_fd(fd) } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||||
|
moto_rt::net::socket_addr(self.inner.as_raw_fd())
|
||||||
|
.map(|addr| from_netc(&addr))
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
|
||||||
|
moto_rt::net::accept(self.inner.as_raw_fd())
|
||||||
|
.map(|(fd, addr)| {
|
||||||
|
(TcpStream { inner: unsafe { Socket::from_raw_fd(fd) } }, from_netc(&addr))
|
||||||
|
})
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duplicate(&self) -> io::Result<TcpListener> {
|
||||||
|
moto_rt::fs::duplicate(self.inner.as_raw_fd())
|
||||||
|
.map(|fd| Self { inner: unsafe { Socket::from_raw_fd(fd) } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_ttl(self.inner.as_raw_fd(), ttl).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ttl(&self) -> io::Result<u32> {
|
||||||
|
moto_rt::net::ttl(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_only_v6(self.inner.as_raw_fd(), only_v6).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn only_v6(&self) -> io::Result<bool> {
|
||||||
|
moto_rt::net::only_v6(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||||
|
let e = moto_rt::net::take_error(self.inner.as_raw_fd()).map_err(map_motor_error)?;
|
||||||
|
if e == moto_rt::E_OK { Ok(None) } else { Ok(Some(map_motor_error(e))) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_nonblocking(self.inner.as_raw_fd(), nonblocking).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct UdpSocket {
|
||||||
|
inner: Socket,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UdpSocket {
|
||||||
|
pub fn socket(&self) -> &Socket {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn into_socket(self) -> Socket {
|
||||||
|
self.inner
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
|
||||||
|
let addr = into_netc(&addr.to_socket_addrs()?.next().unwrap());
|
||||||
|
moto_rt::net::bind(moto_rt::net::PROTO_UDP, &addr)
|
||||||
|
.map(|fd| Self { inner: unsafe { Socket::from_raw_fd(fd) } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||||
|
moto_rt::net::peer_addr(self.inner.as_raw_fd())
|
||||||
|
.map(|addr| from_netc(&addr))
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn socket_addr(&self) -> io::Result<SocketAddr> {
|
||||||
|
moto_rt::net::socket_addr(self.inner.as_raw_fd())
|
||||||
|
.map(|addr| from_netc(&addr))
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||||
|
moto_rt::net::udp_recv_from(self.inner.as_raw_fd(), buf)
|
||||||
|
.map(|(sz, addr)| (sz, from_netc(&addr)))
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||||
|
moto_rt::net::udp_peek_from(self.inner.as_raw_fd(), buf)
|
||||||
|
.map(|(sz, addr)| (sz, from_netc(&addr)))
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_to(&self, buf: &[u8], addr: &SocketAddr) -> io::Result<usize> {
|
||||||
|
let addr = into_netc(addr);
|
||||||
|
moto_rt::net::udp_send_to(self.inner.as_raw_fd(), buf, &addr).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duplicate(&self) -> io::Result<UdpSocket> {
|
||||||
|
moto_rt::fs::duplicate(self.inner.as_raw_fd())
|
||||||
|
.map(|fd| Self { inner: unsafe { Socket::from_raw_fd(fd) } })
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_read_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_read_timeout(self.inner.as_raw_fd(), timeout).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_write_timeout(&self, timeout: Option<Duration>) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_write_timeout(self.inner.as_raw_fd(), timeout).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
|
||||||
|
moto_rt::net::read_timeout(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
|
||||||
|
moto_rt::net::write_timeout(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_udp_broadcast(self.inner.as_raw_fd(), broadcast).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn broadcast(&self) -> io::Result<bool> {
|
||||||
|
moto_rt::net::udp_broadcast(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_multicast_loop_v4(&self, val: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_udp_multicast_loop_v4(self.inner.as_raw_fd(), val)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn multicast_loop_v4(&self) -> io::Result<bool> {
|
||||||
|
moto_rt::net::udp_multicast_loop_v4(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_multicast_ttl_v4(&self, val: u32) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_udp_multicast_ttl_v4(self.inner.as_raw_fd(), val).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
|
||||||
|
moto_rt::net::udp_multicast_ttl_v4(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_multicast_loop_v6(&self, val: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_udp_multicast_loop_v6(self.inner.as_raw_fd(), val)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn multicast_loop_v6(&self) -> io::Result<bool> {
|
||||||
|
moto_rt::net::udp_multicast_loop_v6(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join_multicast_v4(&self, addr: &Ipv4Addr, iface: &Ipv4Addr) -> io::Result<()> {
|
||||||
|
let addr = (*addr).into();
|
||||||
|
let iface = (*iface).into();
|
||||||
|
moto_rt::net::join_udp_multicast_v4(self.inner.as_raw_fd(), &addr, &iface)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join_multicast_v6(&self, addr: &Ipv6Addr, iface: u32) -> io::Result<()> {
|
||||||
|
let addr = (*addr).into();
|
||||||
|
moto_rt::net::join_udp_multicast_v6(self.inner.as_raw_fd(), &addr, iface)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn leave_multicast_v4(&self, addr: &Ipv4Addr, iface: &Ipv4Addr) -> io::Result<()> {
|
||||||
|
let addr = (*addr).into();
|
||||||
|
let iface = (*iface).into();
|
||||||
|
moto_rt::net::leave_udp_multicast_v4(self.inner.as_raw_fd(), &addr, &iface)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn leave_multicast_v6(&self, addr: &Ipv6Addr, iface: u32) -> io::Result<()> {
|
||||||
|
let addr = (*addr).into();
|
||||||
|
moto_rt::net::leave_udp_multicast_v6(self.inner.as_raw_fd(), &addr, iface)
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_ttl(self.inner.as_raw_fd(), ttl).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn ttl(&self) -> io::Result<u32> {
|
||||||
|
moto_rt::net::ttl(self.inner.as_raw_fd()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_error(&self) -> io::Result<Option<io::Error>> {
|
||||||
|
moto_rt::net::take_error(self.inner.as_raw_fd())
|
||||||
|
.map(|e| match e {
|
||||||
|
moto_rt::E_OK => None,
|
||||||
|
e => Some(map_motor_error(e)),
|
||||||
|
})
|
||||||
|
.map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
|
||||||
|
moto_rt::net::set_nonblocking(self.inner.as_raw_fd(), nonblocking).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::read(self.inner.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::net::peek(self.inner.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::write(self.inner.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
|
||||||
|
let addr = into_netc(&addr.to_socket_addrs()?.next().unwrap());
|
||||||
|
moto_rt::net::udp_connect(self.inner.as_raw_fd(), &addr).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct LookupHost {
|
||||||
|
addresses: alloc::collections::VecDeque<netc::sockaddr>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
|
||||||
|
let (_port, addresses) = moto_rt::net::lookup_host(host, port).map_err(map_motor_error)?;
|
||||||
|
Ok(LookupHost { addresses })
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for LookupHost {
|
||||||
|
type Item = SocketAddr;
|
||||||
|
fn next(&mut self) -> Option<SocketAddr> {
|
||||||
|
self.addresses.pop_front().map(|addr| from_netc(&addr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&str> for LookupHost {
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn try_from(host_port: &str) -> io::Result<LookupHost> {
|
||||||
|
let (host, port_str) = host_port
|
||||||
|
.rsplit_once(':')
|
||||||
|
.ok_or(moto_rt::E_INVALID_ARGUMENT)
|
||||||
|
.map_err(map_motor_error)?;
|
||||||
|
let port: u16 =
|
||||||
|
port_str.parse().map_err(|_| moto_rt::E_INVALID_ARGUMENT).map_err(map_motor_error)?;
|
||||||
|
(host, port).try_into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
|
||||||
|
type Error = io::Error;
|
||||||
|
|
||||||
|
fn try_from(host_port: (&'a str, u16)) -> io::Result<LookupHost> {
|
||||||
|
let (host, port) = host_port;
|
||||||
|
|
||||||
|
let (_port, addresses) = moto_rt::net::lookup_host(host, port).map_err(map_motor_error)?;
|
||||||
|
Ok(LookupHost { addresses })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_netc(addr: &SocketAddr) -> netc::sockaddr {
|
||||||
|
match addr {
|
||||||
|
V4(addr4) => netc::sockaddr { v4: (*addr4).into() },
|
||||||
|
V6(addr6) => netc::sockaddr { v6: (*addr6).into() },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_netc(addr: &netc::sockaddr) -> SocketAddr {
|
||||||
|
// SAFETY: all variants of union netc::sockaddr have `sin_family` at the same offset.
|
||||||
|
let family = unsafe { addr.v4.sin_family };
|
||||||
|
match family {
|
||||||
|
netc::AF_INET => SocketAddr::V4(crate::net::SocketAddrV4::from(unsafe { addr.v4 })),
|
||||||
|
netc::AF_INET6 => SocketAddr::V6(crate::net::SocketAddrV6::from(unsafe { addr.v6 })),
|
||||||
|
_ => panic!("bad sin_family {family}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInner<FileDesc> for Socket {
|
||||||
|
#[inline]
|
||||||
|
fn as_inner(&self) -> &FileDesc {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoInner<FileDesc> for Socket {
|
||||||
|
fn into_inner(self) -> FileDesc {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<FileDesc> for Socket {
|
||||||
|
fn from_inner(file_desc: FileDesc) -> Self {
|
||||||
|
Self(file_desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsFd for Socket {
|
||||||
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||||
|
self.0.as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for Socket {
|
||||||
|
#[inline]
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoRawFd for Socket {
|
||||||
|
fn into_raw_fd(self) -> RawFd {
|
||||||
|
self.0.into_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawFd for Socket {
|
||||||
|
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
|
||||||
|
Self(FromRawFd::from_raw_fd(raw_fd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsInner<Socket> for TcpStream {
|
||||||
|
#[inline]
|
||||||
|
fn as_inner(&self) -> &Socket {
|
||||||
|
&self.inner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<Socket> for TcpStream {
|
||||||
|
fn from_inner(socket: Socket) -> TcpStream {
|
||||||
|
TcpStream { inner: socket }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<Socket> for TcpListener {
|
||||||
|
fn from_inner(socket: Socket) -> TcpListener {
|
||||||
|
TcpListener { inner: socket }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<Socket> for UdpSocket {
|
||||||
|
fn from_inner(socket: Socket) -> UdpSocket {
|
||||||
|
UdpSocket { inner: socket }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,6 +41,10 @@ cfg_select! {
|
|||||||
mod hermit;
|
mod hermit;
|
||||||
pub use self::hermit::*;
|
pub use self::hermit::*;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use self::motor::*;
|
||||||
|
}
|
||||||
target_os = "trusty" => {
|
target_os = "trusty" => {
|
||||||
mod trusty;
|
mod trusty;
|
||||||
pub use self::trusty::*;
|
pub use self::trusty::*;
|
||||||
|
|||||||
77
library/std/src/sys/pal/motor/mod.rs
Normal file
77
library/std/src/sys/pal/motor/mod.rs
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#![allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
|
pub mod os;
|
||||||
|
pub mod pipe;
|
||||||
|
pub mod time;
|
||||||
|
|
||||||
|
pub use moto_rt::futex;
|
||||||
|
|
||||||
|
use crate::io as std_io;
|
||||||
|
use crate::sys::RawOsError;
|
||||||
|
|
||||||
|
pub(crate) fn map_motor_error(err: moto_rt::ErrorCode) -> crate::io::Error {
|
||||||
|
crate::io::Error::from_raw_os_error(err.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(test))]
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn motor_start() -> ! {
|
||||||
|
// Initialize the runtime.
|
||||||
|
moto_rt::start();
|
||||||
|
|
||||||
|
// Call main.
|
||||||
|
unsafe extern "C" {
|
||||||
|
fn main(_: isize, _: *const *const u8, _: u8) -> i32;
|
||||||
|
}
|
||||||
|
let result = unsafe { main(0, core::ptr::null(), 0) };
|
||||||
|
|
||||||
|
// Terminate the process.
|
||||||
|
moto_rt::process::exit(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAFETY: must be called only once during runtime initialization.
|
||||||
|
// NOTE: Motor OS uses moto_rt::start() to initialize runtime (see above).
|
||||||
|
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 is_interrupted(_code: RawOsError) -> bool {
|
||||||
|
false // Motor OS doesn't have signals.
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn decode_error_kind(code: RawOsError) -> crate::io::ErrorKind {
|
||||||
|
use moto_rt::error::*;
|
||||||
|
use std_io::ErrorKind;
|
||||||
|
|
||||||
|
if code < 0 || code > u16::MAX.into() {
|
||||||
|
return std_io::ErrorKind::Uncategorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
match code as moto_rt::ErrorCode /* u16 */ {
|
||||||
|
E_ALREADY_IN_USE => ErrorKind::AlreadyExists,
|
||||||
|
E_INVALID_FILENAME => ErrorKind::InvalidFilename,
|
||||||
|
E_NOT_FOUND => ErrorKind::NotFound,
|
||||||
|
E_TIMED_OUT => ErrorKind::TimedOut,
|
||||||
|
E_NOT_IMPLEMENTED => ErrorKind::Unsupported,
|
||||||
|
E_FILE_TOO_LARGE => ErrorKind::FileTooLarge,
|
||||||
|
E_UNEXPECTED_EOF => ErrorKind::UnexpectedEof,
|
||||||
|
E_INVALID_ARGUMENT => ErrorKind::InvalidInput,
|
||||||
|
E_NOT_READY => ErrorKind::WouldBlock,
|
||||||
|
E_NOT_CONNECTED => ErrorKind::NotConnected,
|
||||||
|
_ => crate::io::ErrorKind::Uncategorized,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn abort_internal() -> ! {
|
||||||
|
core::intrinsics::abort();
|
||||||
|
}
|
||||||
100
library/std/src/sys/pal/motor/os.rs
Normal file
100
library/std/src/sys/pal/motor/os.rs
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
use super::map_motor_error;
|
||||||
|
use crate::error::Error as StdError;
|
||||||
|
use crate::ffi::{OsStr, OsString};
|
||||||
|
use crate::marker::PhantomData;
|
||||||
|
use crate::os::motor::ffi::OsStrExt;
|
||||||
|
use crate::path::{self, PathBuf};
|
||||||
|
use crate::sys::RawOsError;
|
||||||
|
use crate::{fmt, io};
|
||||||
|
|
||||||
|
pub fn errno() -> RawOsError {
|
||||||
|
// Not used in Motor OS because it is ambiguous: Motor OS
|
||||||
|
// is micro-kernel-based, and I/O happens via a shared-memory
|
||||||
|
// ring buffer, so an I/O operation that on a unix is a syscall
|
||||||
|
// may involve no sycalls on Motor OS at all, or a syscall
|
||||||
|
// that e.g. waits for a notification from the I/O driver
|
||||||
|
// (sys-io); and the wait syscall may succeed, but the
|
||||||
|
// driver may report an I/O error; or a bunch of results
|
||||||
|
// for several I/O operations, some successful and some
|
||||||
|
// not.
|
||||||
|
//
|
||||||
|
// Also I/O operations in a Motor OS process are handled by a
|
||||||
|
// separate runtime background/I/O thread, so it is really hard
|
||||||
|
// to define what "last system error in the current thread"
|
||||||
|
// actually means.
|
||||||
|
moto_rt::E_UNKNOWN.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn error_string(errno: RawOsError) -> String {
|
||||||
|
let error_code: moto_rt::ErrorCode = match errno {
|
||||||
|
x if x < 0 => moto_rt::E_UNKNOWN,
|
||||||
|
x if x > u16::MAX.into() => moto_rt::E_UNKNOWN,
|
||||||
|
x => x as moto_rt::ErrorCode, /* u16 */
|
||||||
|
};
|
||||||
|
format!("{}", moto_rt::Error::from(error_code))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getcwd() -> io::Result<PathBuf> {
|
||||||
|
moto_rt::fs::getcwd().map(PathBuf::from).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn chdir(path: &path::Path) -> io::Result<()> {
|
||||||
|
moto_rt::fs::chdir(path.as_os_str().as_str()).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 StdError for JoinPathsError {
|
||||||
|
#[allow(deprecated)]
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
"not supported on this platform yet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_exe() -> io::Result<PathBuf> {
|
||||||
|
moto_rt::process::current_exe().map(PathBuf::from).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn temp_dir() -> PathBuf {
|
||||||
|
PathBuf::from(moto_rt::fs::TEMP_DIR)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn home_dir() -> Option<PathBuf> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn exit(code: i32) -> ! {
|
||||||
|
moto_rt::process::exit(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn getpid() -> u32 {
|
||||||
|
panic!("Pids on Motor OS are u64.")
|
||||||
|
}
|
||||||
121
library/std/src/sys/pal/motor/pipe.rs
Normal file
121
library/std/src/sys/pal/motor/pipe.rs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut};
|
||||||
|
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||||
|
use crate::sys::fd::FileDesc;
|
||||||
|
use crate::sys::map_motor_error;
|
||||||
|
use crate::sys_common::{FromInner, IntoInner};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct AnonPipe(FileDesc);
|
||||||
|
|
||||||
|
impl From<moto_rt::RtFd> for AnonPipe {
|
||||||
|
fn from(rt_fd: moto_rt::RtFd) -> AnonPipe {
|
||||||
|
unsafe { AnonPipe::from_raw_fd(rt_fd) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AnonPipe {
|
||||||
|
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::read(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||||
|
crate::io::default_read_buf(|buf| self.read(buf), cursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
|
crate::io::default_read_vectored(|b| self.read(b), bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_read_vectored(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::write(self.as_raw_fd(), buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
|
crate::io::default_write_vectored(|b| self.write(b), bufs)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_write_vectored(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_to_end(&self, buf: &mut Vec<u8>) -> io::Result<usize> {
|
||||||
|
let mut temp_vec = Vec::new();
|
||||||
|
let mut size = 0_usize;
|
||||||
|
loop {
|
||||||
|
temp_vec.resize(256, 0_u8);
|
||||||
|
match self.read(&mut temp_vec[..]) {
|
||||||
|
Ok(sz) => {
|
||||||
|
if sz == 0 {
|
||||||
|
return Ok(size);
|
||||||
|
}
|
||||||
|
size += sz;
|
||||||
|
temp_vec.truncate(sz);
|
||||||
|
buf.append(&mut temp_vec);
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
if size != 0 {
|
||||||
|
return Ok(size);
|
||||||
|
} else {
|
||||||
|
return Err(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsRawFd for AnonPipe {
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.0.as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromRawFd for AnonPipe {
|
||||||
|
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||||
|
let desc = FileDesc::from_raw_fd(fd);
|
||||||
|
Self(desc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoRawFd for AnonPipe {
|
||||||
|
fn into_raw_fd(self) -> RawFd {
|
||||||
|
self.0.into_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AsFd for AnonPipe {
|
||||||
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||||
|
self.0.as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoInner<OwnedFd> for AnonPipe {
|
||||||
|
fn into_inner(self) -> OwnedFd {
|
||||||
|
self.0.into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoInner<FileDesc> for AnonPipe {
|
||||||
|
fn into_inner(self) -> FileDesc {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromInner<OwnedFd> for AnonPipe {
|
||||||
|
fn from_inner(owned_fd: OwnedFd) -> Self {
|
||||||
|
Self(FileDesc::from_inner(owned_fd))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read2(_p1: AnonPipe, _v1: &mut Vec<u8>, _p2: AnonPipe, _v2: &mut Vec<u8>) -> io::Result<()> {
|
||||||
|
Err(io::Error::from_raw_os_error(moto_rt::E_NOT_IMPLEMENTED.into()))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
|
||||||
|
Err(io::Error::UNSUPPORTED_PLATFORM)
|
||||||
|
}
|
||||||
1
library/std/src/sys/pal/motor/time.rs
Normal file
1
library/std/src/sys/pal/motor/time.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub use moto_rt::time::{Instant, SystemTime, UNIX_EPOCH};
|
||||||
@@ -62,7 +62,7 @@ pub(crate) fn absolute(path: &Path) -> io::Result<PathBuf> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn is_absolute(path: &Path) -> bool {
|
pub(crate) fn is_absolute(path: &Path) -> bool {
|
||||||
if cfg!(any(unix, target_os = "hermit", target_os = "wasi")) {
|
if cfg!(any(unix, target_os = "hermit", target_os = "wasi", target_os = "motor")) {
|
||||||
path.has_root()
|
path.has_root()
|
||||||
} else {
|
} else {
|
||||||
path.has_root() && path.prefix().is_some()
|
path.has_root() && path.prefix().is_some()
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ cfg_select! {
|
|||||||
target_os = "emscripten" => {
|
target_os = "emscripten" => {
|
||||||
mod emcc;
|
mod emcc;
|
||||||
}
|
}
|
||||||
any(target_env = "msvc", target_family = "wasm") => {
|
any(target_env = "msvc", target_family = "wasm", target_os = "motor") => {
|
||||||
// This is required by the compiler to exist (e.g., it's a lang item),
|
// This is required by the compiler to exist (e.g., it's a lang item),
|
||||||
// but it's never actually called by the compiler because
|
// but it's never actually called by the compiler because
|
||||||
// __CxxFrameHandler3 (msvc) / __gxx_wasm_personality_v0 (wasm) is the
|
// __CxxFrameHandler3 (msvc) / __gxx_wasm_personality_v0 (wasm) is the
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ cfg_select! {
|
|||||||
mod uefi;
|
mod uefi;
|
||||||
use uefi as imp;
|
use uefi as imp;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
use motor as imp;
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
mod unsupported;
|
mod unsupported;
|
||||||
use unsupported as imp;
|
use unsupported as imp;
|
||||||
@@ -38,6 +42,7 @@ pub use imp::{
|
|||||||
))
|
))
|
||||||
),
|
),
|
||||||
target_os = "windows",
|
target_os = "windows",
|
||||||
|
target_os = "motor"
|
||||||
))]
|
))]
|
||||||
pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||||
use crate::sys::pipe::read2;
|
use crate::sys::pipe::read2;
|
||||||
@@ -77,5 +82,6 @@ pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<
|
|||||||
))
|
))
|
||||||
),
|
),
|
||||||
target_os = "windows",
|
target_os = "windows",
|
||||||
|
target_os = "motor"
|
||||||
)))]
|
)))]
|
||||||
pub use imp::output;
|
pub use imp::output;
|
||||||
|
|||||||
313
library/std/src/sys/process/motor.rs
Normal file
313
library/std/src/sys/process/motor.rs
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
use super::CommandEnvs;
|
||||||
|
use super::env::CommandEnv;
|
||||||
|
use crate::ffi::OsStr;
|
||||||
|
pub use crate::ffi::OsString as EnvKey;
|
||||||
|
use crate::num::NonZeroI32;
|
||||||
|
use crate::os::fd::{FromRawFd, IntoRawFd};
|
||||||
|
use crate::os::motor::ffi::OsStrExt;
|
||||||
|
use crate::path::Path;
|
||||||
|
use crate::process::StdioPipes;
|
||||||
|
use crate::sys::fs::File;
|
||||||
|
use crate::sys::map_motor_error;
|
||||||
|
use crate::sys::pipe::AnonPipe;
|
||||||
|
use crate::sys_common::{AsInner, FromInner};
|
||||||
|
use crate::{fmt, io};
|
||||||
|
|
||||||
|
pub enum Stdio {
|
||||||
|
Inherit,
|
||||||
|
Null,
|
||||||
|
MakePipe,
|
||||||
|
Fd(crate::sys::fd::FileDesc),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Stdio {
|
||||||
|
fn into_rt(self) -> moto_rt::RtFd {
|
||||||
|
match self {
|
||||||
|
Stdio::Inherit => moto_rt::process::STDIO_INHERIT,
|
||||||
|
Stdio::Null => moto_rt::process::STDIO_NULL,
|
||||||
|
Stdio::MakePipe => moto_rt::process::STDIO_MAKE_PIPE,
|
||||||
|
Stdio::Fd(fd) => fd.into_raw_fd(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_clone(&self) -> io::Result<Self> {
|
||||||
|
match self {
|
||||||
|
Self::Fd(fd) => {
|
||||||
|
Ok(Self::Fd(crate::sys::fd::FileDesc::from_inner(fd.as_inner().try_clone()?)))
|
||||||
|
}
|
||||||
|
Self::Inherit => Ok(Self::Inherit),
|
||||||
|
Self::Null => Ok(Self::Null),
|
||||||
|
Self::MakePipe => Ok(Self::MakePipe),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Command {
|
||||||
|
program: String,
|
||||||
|
args: Vec<String>,
|
||||||
|
cwd: Option<String>,
|
||||||
|
stdin: Option<Stdio>,
|
||||||
|
stdout: Option<Stdio>,
|
||||||
|
stderr: Option<Stdio>,
|
||||||
|
env: CommandEnv,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Command {
|
||||||
|
pub fn new(program: &OsStr) -> Command {
|
||||||
|
let mut env = CommandEnv::default();
|
||||||
|
env.remove(OsStr::new(moto_rt::process::STDIO_IS_TERMINAL_ENV_KEY));
|
||||||
|
|
||||||
|
Command { program: program.as_str().to_owned(), env, ..Default::default() }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn arg(&mut self, arg: &OsStr) {
|
||||||
|
self.args.push(arg.as_str().to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn env_mut(&mut self) -> &mut CommandEnv {
|
||||||
|
&mut self.env
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cwd(&mut self, dir: &OsStr) {
|
||||||
|
self.cwd = Some(dir.as_str().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 {
|
||||||
|
OsStr::new(self.program.as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_args(&self) -> CommandArgs<'_> {
|
||||||
|
let iter = self.args.iter();
|
||||||
|
CommandArgs { iter }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_envs(&self) -> CommandEnvs<'_> {
|
||||||
|
self.env.iter()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_current_dir(&self) -> Option<&Path> {
|
||||||
|
self.cwd.as_ref().map(Path::new)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn(
|
||||||
|
&mut self,
|
||||||
|
default: Stdio,
|
||||||
|
needs_stdin: bool,
|
||||||
|
) -> io::Result<(Process, StdioPipes)> {
|
||||||
|
let stdin = if let Some(stdin) = self.stdin.as_ref() {
|
||||||
|
stdin.try_clone()?.into_rt()
|
||||||
|
} else if needs_stdin {
|
||||||
|
default.try_clone()?.into_rt()
|
||||||
|
} else {
|
||||||
|
Stdio::Null.into_rt()
|
||||||
|
};
|
||||||
|
let stdout = if let Some(stdout) = self.stdout.as_ref() {
|
||||||
|
stdout.try_clone()?.into_rt()
|
||||||
|
} else {
|
||||||
|
default.try_clone()?.into_rt()
|
||||||
|
};
|
||||||
|
let stderr = if let Some(stderr) = self.stdout.as_ref() {
|
||||||
|
stderr.try_clone()?.into_rt()
|
||||||
|
} else {
|
||||||
|
default.try_clone()?.into_rt()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut env = Vec::<(String, String)>::new();
|
||||||
|
for (k, v) in self.env.capture() {
|
||||||
|
env.push((k.as_str().to_owned(), v.as_str().to_owned()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let args = moto_rt::process::SpawnArgs {
|
||||||
|
program: self.program.clone(),
|
||||||
|
args: self.args.clone(),
|
||||||
|
env,
|
||||||
|
cwd: self.cwd.clone(),
|
||||||
|
stdin,
|
||||||
|
stdout,
|
||||||
|
stderr,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (handle, stdin, stdout, stderr) =
|
||||||
|
moto_rt::process::spawn(args).map_err(map_motor_error)?;
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
Process { handle },
|
||||||
|
StdioPipes {
|
||||||
|
stdin: if stdin >= 0 { Some(stdin.into()) } else { None },
|
||||||
|
stdout: if stdout >= 0 { Some(stdout.into()) } else { None },
|
||||||
|
stderr: if stderr >= 0 { Some(stderr.into()) } else { None },
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<AnonPipe> for Stdio {
|
||||||
|
fn from(pipe: AnonPipe) -> Stdio {
|
||||||
|
unsafe { Stdio::Fd(crate::sys::fd::FileDesc::from_raw_fd(pipe.into_raw_fd())) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<crate::sys::fd::FileDesc> for Stdio {
|
||||||
|
fn from(fd: crate::sys::fd::FileDesc) -> Stdio {
|
||||||
|
Stdio::Fd(fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<File> for Stdio {
|
||||||
|
fn from(_file: File) -> Stdio {
|
||||||
|
panic!("Not implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Stdout> for Stdio {
|
||||||
|
fn from(_: io::Stdout) -> Stdio {
|
||||||
|
panic!("Not implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Stderr> for Stdio {
|
||||||
|
fn from(_: io::Stderr) -> Stdio {
|
||||||
|
panic!("Not implemented")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for Command {
|
||||||
|
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
|
||||||
|
pub struct ExitStatus(i32);
|
||||||
|
|
||||||
|
impl ExitStatus {
|
||||||
|
pub fn exit_ok(&self) -> Result<(), ExitStatusError> {
|
||||||
|
if self.0 == 0 { Ok(()) } else { Err(ExitStatusError(*self)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn code(&self) -> Option<i32> {
|
||||||
|
Some(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for ExitStatus {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "exit code: {}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
|
pub struct ExitStatusError(ExitStatus);
|
||||||
|
|
||||||
|
impl Into<ExitStatus> for ExitStatusError {
|
||||||
|
fn into(self) -> ExitStatus {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExitStatusError {
|
||||||
|
pub fn code(self) -> Option<NonZeroI32> {
|
||||||
|
NonZeroI32::new(self.0.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||||
|
pub struct ExitCode(i32);
|
||||||
|
|
||||||
|
impl ExitCode {
|
||||||
|
pub const SUCCESS: ExitCode = ExitCode(0);
|
||||||
|
pub const FAILURE: ExitCode = ExitCode(1);
|
||||||
|
|
||||||
|
pub fn as_i32(&self) -> i32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<u8> for ExitCode {
|
||||||
|
fn from(code: u8) -> Self {
|
||||||
|
Self(code as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Process {
|
||||||
|
handle: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Process {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
moto_rt::alloc::release_handle(self.handle).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Process {
|
||||||
|
pub fn id(&self) -> u32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn kill(&mut self) -> io::Result<()> {
|
||||||
|
match moto_rt::process::kill(self.handle) {
|
||||||
|
moto_rt::E_OK => Ok(()),
|
||||||
|
err => Err(map_motor_error(err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait(&mut self) -> io::Result<ExitStatus> {
|
||||||
|
moto_rt::process::wait(self.handle).map(|c| ExitStatus(c)).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_wait(&mut self) -> io::Result<Option<ExitStatus>> {
|
||||||
|
match moto_rt::process::try_wait(self.handle) {
|
||||||
|
Ok(s) => Ok(Some(ExitStatus(s))),
|
||||||
|
Err(err) => match err {
|
||||||
|
moto_rt::E_NOT_READY => Ok(None),
|
||||||
|
err => Err(map_motor_error(err)),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn handle(&self) -> u64 {
|
||||||
|
self.handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CommandArgs<'a> {
|
||||||
|
iter: crate::slice::Iter<'a, String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for CommandArgs<'a> {
|
||||||
|
type Item = &'a OsStr;
|
||||||
|
fn next(&mut self) -> Option<&'a OsStr> {
|
||||||
|
self.iter.next().map(|arg| OsStr::new(arg))
|
||||||
|
}
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,6 +62,10 @@ cfg_select! {
|
|||||||
mod redox;
|
mod redox;
|
||||||
pub use redox::fill_bytes;
|
pub use redox::fill_bytes;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::fill_bytes;
|
||||||
|
}
|
||||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||||
mod sgx;
|
mod sgx;
|
||||||
pub use sgx::fill_bytes;
|
pub use sgx::fill_bytes;
|
||||||
|
|||||||
3
library/std/src/sys/random/motor.rs
Normal file
3
library/std/src/sys/random/motor.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
pub fn fill_bytes(bytes: &mut [u8]) {
|
||||||
|
moto_rt::fill_random_bytes(bytes)
|
||||||
|
}
|
||||||
@@ -13,6 +13,10 @@ cfg_select! {
|
|||||||
mod sgx;
|
mod sgx;
|
||||||
pub use sgx::*;
|
pub use sgx::*;
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::*;
|
||||||
|
}
|
||||||
target_os = "solid_asp3" => {
|
target_os = "solid_asp3" => {
|
||||||
mod solid;
|
mod solid;
|
||||||
pub use solid::*;
|
pub use solid::*;
|
||||||
|
|||||||
232
library/std/src/sys/stdio/motor.rs
Normal file
232
library/std/src/sys/stdio/motor.rs
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
|
||||||
|
use crate::sys::map_motor_error;
|
||||||
|
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||||
|
use crate::{io, process, sys};
|
||||||
|
|
||||||
|
pub const STDIN_BUF_SIZE: usize = crate::sys::io::DEFAULT_BUF_SIZE;
|
||||||
|
|
||||||
|
pub struct Stdin {}
|
||||||
|
|
||||||
|
impl Stdin {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stdout {}
|
||||||
|
|
||||||
|
impl Stdout {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Stderr {}
|
||||||
|
|
||||||
|
impl Stderr {
|
||||||
|
pub const fn new() -> Self {
|
||||||
|
Self {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl crate::sealed::Sealed for Stdin {}
|
||||||
|
|
||||||
|
impl crate::io::IsTerminal for Stdin {
|
||||||
|
fn is_terminal(&self) -> bool {
|
||||||
|
moto_rt::fs::is_terminal(moto_rt::FD_STDIN)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Read for Stdin {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::read(moto_rt::FD_STDIN, buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Write for Stdout {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::write(moto_rt::FD_STDOUT, buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
moto_rt::fs::flush(moto_rt::FD_STDOUT).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl io::Write for Stderr {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
moto_rt::fs::write(moto_rt::FD_STDERR, buf).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
moto_rt::fs::flush(moto_rt::FD_STDERR).map_err(map_motor_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn panic_output() -> Option<impl io::Write> {
|
||||||
|
Some(Stderr::new())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_ebadf(_err: &io::Error) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||||
|
impl FromRawFd for process::Stdio {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn from_raw_fd(fd: RawFd) -> process::Stdio {
|
||||||
|
let fd = unsafe { sys::fd::FileDesc::from_raw_fd(fd) };
|
||||||
|
let io = sys::process::Stdio::Fd(fd);
|
||||||
|
process::Stdio::from_inner(io)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
impl From<OwnedFd> for process::Stdio {
|
||||||
|
/// Takes ownership of a file descriptor and returns a [`Stdio`](process::Stdio)
|
||||||
|
/// that can attach a stream to it.
|
||||||
|
#[inline]
|
||||||
|
fn from(fd: OwnedFd) -> process::Stdio {
|
||||||
|
let fd = sys::fd::FileDesc::from_inner(fd);
|
||||||
|
let io = sys::process::Stdio::Fd(fd);
|
||||||
|
process::Stdio::from_inner(io)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||||
|
impl AsRawFd for process::ChildStdin {
|
||||||
|
#[inline]
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.as_inner().as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||||
|
impl AsRawFd for process::ChildStdout {
|
||||||
|
#[inline]
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.as_inner().as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "process_extensions", since = "1.2.0")]
|
||||||
|
impl AsRawFd for process::ChildStderr {
|
||||||
|
#[inline]
|
||||||
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
|
self.as_inner().as_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||||
|
impl IntoRawFd for process::ChildStdin {
|
||||||
|
#[inline]
|
||||||
|
fn into_raw_fd(self) -> RawFd {
|
||||||
|
self.into_inner().into_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||||
|
impl IntoRawFd for process::ChildStdout {
|
||||||
|
#[inline]
|
||||||
|
fn into_raw_fd(self) -> RawFd {
|
||||||
|
self.into_inner().into_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "into_raw_os", since = "1.4.0")]
|
||||||
|
impl IntoRawFd for process::ChildStderr {
|
||||||
|
#[inline]
|
||||||
|
fn into_raw_fd(self) -> RawFd {
|
||||||
|
self.into_inner().into_raw_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
impl AsFd for crate::process::ChildStdin {
|
||||||
|
#[inline]
|
||||||
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||||
|
self.as_inner().as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
impl From<crate::process::ChildStdin> for OwnedFd {
|
||||||
|
/// Takes ownership of a [`ChildStdin`](crate::process::ChildStdin)'s file descriptor.
|
||||||
|
#[inline]
|
||||||
|
fn from(child_stdin: crate::process::ChildStdin) -> OwnedFd {
|
||||||
|
child_stdin.into_inner().into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a `ChildStdin` from the provided `OwnedFd`.
|
||||||
|
///
|
||||||
|
/// The provided file descriptor must point to a pipe
|
||||||
|
/// with the `CLOEXEC` flag set.
|
||||||
|
#[stable(feature = "child_stream_from_fd", since = "1.74.0")]
|
||||||
|
impl From<OwnedFd> for process::ChildStdin {
|
||||||
|
#[inline]
|
||||||
|
fn from(fd: OwnedFd) -> process::ChildStdin {
|
||||||
|
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||||
|
process::ChildStdin::from_inner(pipe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
impl AsFd for crate::process::ChildStdout {
|
||||||
|
#[inline]
|
||||||
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||||
|
self.as_inner().as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
impl From<crate::process::ChildStdout> for OwnedFd {
|
||||||
|
/// Takes ownership of a [`ChildStdout`](crate::process::ChildStdout)'s file descriptor.
|
||||||
|
#[inline]
|
||||||
|
fn from(child_stdout: crate::process::ChildStdout) -> OwnedFd {
|
||||||
|
child_stdout.into_inner().into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a `ChildStdout` from the provided `OwnedFd`.
|
||||||
|
///
|
||||||
|
/// The provided file descriptor must point to a pipe
|
||||||
|
/// with the `CLOEXEC` flag set.
|
||||||
|
#[stable(feature = "child_stream_from_fd", since = "1.74.0")]
|
||||||
|
impl From<OwnedFd> for process::ChildStdout {
|
||||||
|
#[inline]
|
||||||
|
fn from(fd: OwnedFd) -> process::ChildStdout {
|
||||||
|
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||||
|
process::ChildStdout::from_inner(pipe)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
impl AsFd for crate::process::ChildStderr {
|
||||||
|
#[inline]
|
||||||
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||||
|
self.as_inner().as_fd()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||||
|
impl From<crate::process::ChildStderr> for OwnedFd {
|
||||||
|
/// Takes ownership of a [`ChildStderr`](crate::process::ChildStderr)'s file descriptor.
|
||||||
|
#[inline]
|
||||||
|
fn from(child_stderr: crate::process::ChildStderr) -> OwnedFd {
|
||||||
|
child_stderr.into_inner().into_inner()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a `ChildStderr` from the provided `OwnedFd`.
|
||||||
|
///
|
||||||
|
/// The provided file descriptor must point to a pipe
|
||||||
|
/// with the `CLOEXEC` flag set.
|
||||||
|
#[stable(feature = "child_stream_from_fd", since = "1.74.0")]
|
||||||
|
impl From<OwnedFd> for process::ChildStderr {
|
||||||
|
#[inline]
|
||||||
|
fn from(fd: OwnedFd) -> process::ChildStderr {
|
||||||
|
let pipe = sys::pipe::AnonPipe::from_inner(fd);
|
||||||
|
process::ChildStderr::from_inner(pipe)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,6 +6,7 @@ cfg_select! {
|
|||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
|
target_os = "motor",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
all(target_family = "wasm", target_feature = "atomics"),
|
all(target_family = "wasm", target_feature = "atomics"),
|
||||||
target_os = "hermit",
|
target_os = "hermit",
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ cfg_select! {
|
|||||||
target_os = "android",
|
target_os = "android",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
|
target_os = "motor",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
all(target_family = "wasm", target_feature = "atomics"),
|
all(target_family = "wasm", target_feature = "atomics"),
|
||||||
target_os = "hermit",
|
target_os = "hermit",
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ cfg_select! {
|
|||||||
target_os = "android",
|
target_os = "android",
|
||||||
all(target_arch = "wasm32", target_feature = "atomics"),
|
all(target_arch = "wasm32", target_feature = "atomics"),
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
|
target_os = "motor",
|
||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ cfg_select! {
|
|||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
all(target_family = "wasm", target_feature = "atomics"),
|
all(target_family = "wasm", target_feature = "atomics"),
|
||||||
target_os = "hermit",
|
target_os = "hermit",
|
||||||
|
target_os = "motor",
|
||||||
) => {
|
) => {
|
||||||
mod futex;
|
mod futex;
|
||||||
pub use futex::RwLock;
|
pub use futex::RwLock;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ cfg_select! {
|
|||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
target_os = "dragonfly",
|
target_os = "dragonfly",
|
||||||
target_os = "fuchsia",
|
target_os = "fuchsia",
|
||||||
|
target_os = "motor",
|
||||||
target_os = "hermit",
|
target_os = "hermit",
|
||||||
) => {
|
) => {
|
||||||
mod futex;
|
mod futex;
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ cfg_select! {
|
|||||||
mod unsupported;
|
mod unsupported;
|
||||||
pub use unsupported::{current_os_id, set_name};
|
pub use unsupported::{current_os_id, set_name};
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod motor;
|
||||||
|
pub use motor::*;
|
||||||
|
}
|
||||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||||
mod sgx;
|
mod sgx;
|
||||||
pub use sgx::{Thread, current_os_id, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
pub use sgx::{Thread, current_os_id, sleep, yield_now, DEFAULT_MIN_STACK_SIZE};
|
||||||
|
|||||||
63
library/std/src/sys/thread/motor.rs
Normal file
63
library/std/src/sys/thread/motor.rs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
use crate::ffi::CStr;
|
||||||
|
use crate::io;
|
||||||
|
use crate::num::NonZeroUsize;
|
||||||
|
use crate::sys::map_motor_error;
|
||||||
|
use crate::time::Duration;
|
||||||
|
|
||||||
|
pub const DEFAULT_MIN_STACK_SIZE: usize = 1024 * 256;
|
||||||
|
|
||||||
|
pub struct Thread {
|
||||||
|
sys_thread: moto_rt::thread::ThreadHandle,
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for Thread {}
|
||||||
|
unsafe impl Sync for Thread {}
|
||||||
|
|
||||||
|
impl Thread {
|
||||||
|
pub unsafe fn new(
|
||||||
|
stack: usize,
|
||||||
|
_name: Option<&str>,
|
||||||
|
p: Box<dyn FnOnce()>,
|
||||||
|
) -> io::Result<Thread> {
|
||||||
|
extern "C" fn __moto_rt_thread_fn(thread_arg: u64) {
|
||||||
|
unsafe {
|
||||||
|
Box::from_raw(
|
||||||
|
core::ptr::with_exposed_provenance::<Box<dyn FnOnce()>>(thread_arg as usize)
|
||||||
|
.cast_mut(),
|
||||||
|
)();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let thread_arg = Box::into_raw(Box::new(p)).expose_provenance() as u64;
|
||||||
|
let sys_thread = moto_rt::thread::spawn(__moto_rt_thread_fn, stack, thread_arg)
|
||||||
|
.map_err(map_motor_error)?;
|
||||||
|
Ok(Self { sys_thread })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn join(self) {
|
||||||
|
assert!(moto_rt::thread::join(self.sys_thread) == moto_rt::E_OK)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_name(name: &CStr) {
|
||||||
|
let bytes = name.to_bytes();
|
||||||
|
if let Ok(s) = core::str::from_utf8(bytes) {
|
||||||
|
let _ = moto_rt::thread::set_name(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn current_os_id() -> Option<u64> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn available_parallelism() -> io::Result<NonZeroUsize> {
|
||||||
|
Ok(unsafe { NonZeroUsize::new_unchecked(moto_rt::num_cpus()) })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn yield_now() {
|
||||||
|
moto_rt::thread::yield_now()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sleep(dur: Duration) {
|
||||||
|
moto_rt::thread::sleep_until(moto_rt::time::Instant::now() + dur)
|
||||||
|
}
|
||||||
@@ -187,6 +187,14 @@ pub(crate) mod key {
|
|||||||
pub(super) use xous::{Key, get, set};
|
pub(super) use xous::{Key, get, set};
|
||||||
use xous::{create, destroy};
|
use xous::{create, destroy};
|
||||||
}
|
}
|
||||||
|
target_os = "motor" => {
|
||||||
|
mod racy;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
|
pub(super) use racy::LazyKey;
|
||||||
|
pub(super) use moto_rt::tls::{Key, get, set};
|
||||||
|
use moto_rt::tls::{create, destroy};
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user