From 4de57e2c9883f1f9fe8ba9be5621ad6d86c46de2 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Tue, 26 Dec 2023 12:20:01 +0100 Subject: [PATCH] Allow disabling redox_syscall public APIs. --- Cargo.toml | 4 ++- src/lib.rs | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 104 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b169fc8e68..30a953c962 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,8 +11,10 @@ exclude = ["target"] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [features] -default = ["call"] +default = ["call", "std", "redox_syscall_exports"] call = [] +std = [] +redox_syscall_exports = [] [dependencies] bitflags = "2" diff --git a/src/lib.rs b/src/lib.rs index d29d1b7ac7..eb5febbb0c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,87 @@ //! Redox-specific system library. -#![no_std] +#![cfg_attr(not(feature = "std"), no_std)] -pub use syscall::error; -use syscall::error::{Error, Result}; +use self::error::{Error, Result}; + +pub mod error { + use super::*; + + #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] + // TODO: Define as enum? + pub struct Error { + // TODO: NonZeroU16? "success" is not an error. + errno: u16, + } + + impl Error { + pub fn new(errno: i32) -> Self { + Self { + errno: errno.try_into().unwrap_or(u16::MAX), + } + } + pub fn errno(self) -> i32 { + self.errno.into() + } + pub fn is_wouldblock(self) -> bool { + matches!(self.errno(), errno::EAGAIN | errno::EWOULDBLOCK) + } + pub fn is_interrupt(self) -> bool { + self.errno() == errno::EINTR + } + pub fn mux(res: Result) -> usize { + match res { + // TODO: Ensure success cannot overlap with error values. + Ok(success) => success, + Err(error) => usize::wrapping_neg(usize::from(error.errno)), + } + } + pub fn demux(res: usize) -> Result { + if res > usize::wrapping_neg(4096) { + Err(Self { + errno: res.wrapping_neg().try_into().expect("2^BITS - res < 4096"), + }) + } else { + Ok(res) + } + } + pub fn description(&self) -> &'static str { + syscall::error::STR_ERROR + .get(usize::from(self.errno)) + .copied() + .unwrap_or("Unknown") + } + } + + impl core::fmt::Display for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.description()) + } + } + impl core::fmt::Debug for Error { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Error `{}` {}", self.description(), self.errno) + } + } + #[cfg(feature = "redox_syscall_exports")] + impl From for Error { + fn from(value: syscall::Error) -> Self { + Self { + errno: value.errno.try_into().unwrap_or(u16::MAX), + } + } + } + #[cfg(feature = "std")] + impl From for std::io::Error { + fn from(value: Error) -> Self { + Self::from_raw_os_error(value.errno.into()) + } + } + + #[cfg(feature = "std")] + impl std::error::Error for Error {} + + pub type Result = core::result::Result; +} pub mod flag { pub use libc::{ @@ -83,6 +162,25 @@ pub mod data { pub use libc::statvfs as StatVfs; pub use libc::timespec as TimeSpec; + // TODO: Remove + pub fn timespec_from_mut_bytes(bytes: &mut [u8]) -> &mut TimeSpec { + assert!(bytes.len() >= core::mem::size_of::()); + assert_eq!( + bytes.as_ptr() as usize % core::mem::align_of::(), + 0 + ); + unsafe { &mut *bytes.as_mut_ptr().cast() } + } + // TODO: Remove + pub fn timespec_from_bytes(bytes: &[u8]) -> &TimeSpec { + assert!(bytes.len() >= core::mem::size_of::()); + assert_eq!( + bytes.as_ptr() as usize % core::mem::align_of::(), + 0 + ); + unsafe { &*bytes.as_ptr().cast() } + } + #[cfg(target_os = "redox")] pub use libc::sigset_t as SigSet;