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",
|
||||
]
|
||||
|
||||
[[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]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
@@ -316,6 +326,7 @@ dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"moto-rt",
|
||||
"object",
|
||||
"panic_abort",
|
||||
"panic_unwind",
|
||||
|
||||
@@ -70,6 +70,9 @@ fortanix-sgx-abi = { version = "0.6.1", features = [
|
||||
'rustc-dep-of-std',
|
||||
], 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]
|
||||
hermit-abi = { version = "0.5.0", features = [
|
||||
'rustc-dep-of-std',
|
||||
|
||||
@@ -30,6 +30,7 @@ fn main() {
|
||||
|| target_os == "windows"
|
||||
|| target_os == "fuchsia"
|
||||
|| (target_vendor == "fortanix" && target_env == "sgx")
|
||||
|| target_os == "motor"
|
||||
|| target_os == "hermit"
|
||||
|| target_os == "trusty"
|
||||
|| target_os == "l4re"
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
#![stable(feature = "io_safety", since = "1.63.0")]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[cfg(target_os = "motor")]
|
||||
use moto_rt::libc;
|
||||
|
||||
use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(not(target_os = "trusty"))]
|
||||
use crate::fs;
|
||||
@@ -12,7 +15,8 @@ use crate::mem::ManuallyDrop;
|
||||
target_arch = "wasm32",
|
||||
target_env = "sgx",
|
||||
target_os = "hermit",
|
||||
target_os = "trusty"
|
||||
target_os = "trusty",
|
||||
target_os = "motor"
|
||||
)))]
|
||||
use crate::sys::cvt;
|
||||
#[cfg(not(target_os = "trusty"))]
|
||||
@@ -95,7 +99,12 @@ impl OwnedFd {
|
||||
impl BorrowedFd<'_> {
|
||||
/// Creates a new `OwnedFd` instance that shares the same underlying file
|
||||
/// 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")]
|
||||
pub fn try_clone_to_owned(&self) -> crate::io::Result<OwnedFd> {
|
||||
// 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> {
|
||||
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")]
|
||||
|
||||
@@ -4,13 +4,17 @@
|
||||
|
||||
#[cfg(target_os = "hermit")]
|
||||
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"))]
|
||||
use crate::fs;
|
||||
use crate::io;
|
||||
#[cfg(target_os = "hermit")]
|
||||
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;
|
||||
#[cfg(all(doc, not(target_arch = "wasm32")))]
|
||||
use crate::os::unix::io::AsFd;
|
||||
@@ -23,10 +27,10 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
/// Raw file descriptors.
|
||||
#[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;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(target_os = "hermit")]
|
||||
#[cfg(any(target_os = "hermit", target_os = "motor"))]
|
||||
pub type RawFd = i32;
|
||||
|
||||
/// A trait to extract the raw file descriptor from an underlying object.
|
||||
|
||||
@@ -155,6 +155,8 @@ pub mod ios;
|
||||
pub mod l4re;
|
||||
#[cfg(target_os = "macos")]
|
||||
pub mod macos;
|
||||
#[cfg(target_os = "motor")]
|
||||
pub mod motor;
|
||||
#[cfg(target_os = "netbsd")]
|
||||
pub mod netbsd;
|
||||
#[cfg(target_os = "nto")]
|
||||
@@ -182,7 +184,14 @@ pub mod vxworks;
|
||||
#[cfg(target_os = "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;
|
||||
|
||||
#[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" => {
|
||||
mod hermit;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "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;
|
||||
pub use windows::{AnonPipe, pipe};
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::{AnonPipe, pipe};
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
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"))),
|
||||
target_family = "windows",
|
||||
target_os = "hermit",
|
||||
target_os = "motor",
|
||||
target_os = "uefi",
|
||||
target_os = "wasi",
|
||||
target_os = "xous",
|
||||
@@ -28,6 +29,10 @@ cfg_select! {
|
||||
mod sgx;
|
||||
pub use sgx::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
target_os = "uefi" => {
|
||||
mod 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(
|
||||
target_family = "unix",
|
||||
target_os = "hermit",
|
||||
target_os = "motor",
|
||||
all(target_vendor = "fortanix", target_env = "sgx"),
|
||||
target_os = "solid_asp3",
|
||||
target_os = "uefi",
|
||||
@@ -26,6 +27,10 @@ cfg_select! {
|
||||
mod hermit;
|
||||
pub use hermit::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod 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;
|
||||
pub use hermit::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod 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;
|
||||
use hermit as imp;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
use motor as imp;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod solid;
|
||||
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;
|
||||
pub use hermit::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
pub use unsupported::*;
|
||||
|
||||
@@ -17,6 +17,10 @@ cfg_select! {
|
||||
mod wasip1;
|
||||
pub use wasip1::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
target_os = "xous" => {
|
||||
mod 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;
|
||||
pub use self::hermit::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use self::motor::*;
|
||||
}
|
||||
target_os = "trusty" => {
|
||||
mod 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 {
|
||||
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()
|
||||
} else {
|
||||
path.has_root() && path.prefix().is_some()
|
||||
|
||||
@@ -17,7 +17,7 @@ cfg_select! {
|
||||
target_os = "emscripten" => {
|
||||
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),
|
||||
// but it's never actually called by the compiler because
|
||||
// __CxxFrameHandler3 (msvc) / __gxx_wasm_personality_v0 (wasm) is the
|
||||
|
||||
@@ -11,6 +11,10 @@ cfg_select! {
|
||||
mod uefi;
|
||||
use uefi as imp;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
use motor as imp;
|
||||
}
|
||||
_ => {
|
||||
mod unsupported;
|
||||
use unsupported as imp;
|
||||
@@ -38,6 +42,7 @@ pub use imp::{
|
||||
))
|
||||
),
|
||||
target_os = "windows",
|
||||
target_os = "motor"
|
||||
))]
|
||||
pub fn output(cmd: &mut Command) -> crate::io::Result<(ExitStatus, Vec<u8>, Vec<u8>)> {
|
||||
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 = "motor"
|
||||
)))]
|
||||
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;
|
||||
pub use redox::fill_bytes;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::fill_bytes;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
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;
|
||||
pub use sgx::*;
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
target_os = "solid_asp3" => {
|
||||
mod 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 = "openbsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "motor",
|
||||
target_os = "fuchsia",
|
||||
all(target_family = "wasm", target_feature = "atomics"),
|
||||
target_os = "hermit",
|
||||
|
||||
@@ -5,6 +5,7 @@ cfg_select! {
|
||||
target_os = "android",
|
||||
target_os = "freebsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "motor",
|
||||
target_os = "dragonfly",
|
||||
all(target_family = "wasm", target_feature = "atomics"),
|
||||
target_os = "hermit",
|
||||
|
||||
@@ -14,6 +14,7 @@ cfg_select! {
|
||||
target_os = "android",
|
||||
all(target_arch = "wasm32", target_feature = "atomics"),
|
||||
target_os = "freebsd",
|
||||
target_os = "motor",
|
||||
target_os = "openbsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
|
||||
@@ -9,6 +9,7 @@ cfg_select! {
|
||||
target_os = "fuchsia",
|
||||
all(target_family = "wasm", target_feature = "atomics"),
|
||||
target_os = "hermit",
|
||||
target_os = "motor",
|
||||
) => {
|
||||
mod futex;
|
||||
pub use futex::RwLock;
|
||||
|
||||
@@ -8,6 +8,7 @@ cfg_select! {
|
||||
target_os = "openbsd",
|
||||
target_os = "dragonfly",
|
||||
target_os = "fuchsia",
|
||||
target_os = "motor",
|
||||
target_os = "hermit",
|
||||
) => {
|
||||
mod futex;
|
||||
|
||||
@@ -6,6 +6,10 @@ cfg_select! {
|
||||
mod unsupported;
|
||||
pub use unsupported::{current_os_id, set_name};
|
||||
}
|
||||
target_os = "motor" => {
|
||||
mod motor;
|
||||
pub use motor::*;
|
||||
}
|
||||
all(target_vendor = "fortanix", target_env = "sgx") => {
|
||||
mod sgx;
|
||||
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};
|
||||
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