Rollup merge of #150723 - move_pal_error, r=@tgross35

std: move `errno` and related functions into `sys::io`

Part of rust-lang/rust#117276.

Currently, `errno` and related functions like `decode_error_kind` are split across `sys::pal` and `sys::pal::os`. This PR moves all of them into a new module inside `sys::io`.
This commit is contained in:
Jonathan Brouwer 2026-01-14 11:05:38 +01:00 committed by GitHub
commit 95ea4c5699
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 902 additions and 848 deletions

View file

@ -653,7 +653,7 @@ impl Error {
#[must_use]
#[inline]
pub fn last_os_error() -> Error {
Error::from_raw_os_error(sys::os::errno())
Error::from_raw_os_error(sys::io::errno())
}
/// Creates a new instance of an [`Error`] from a particular OS error code.
@ -1004,7 +1004,7 @@ impl Error {
#[inline]
pub fn kind(&self) -> ErrorKind {
match self.repr.data() {
ErrorData::Os(code) => sys::decode_error_kind(code),
ErrorData::Os(code) => sys::io::decode_error_kind(code),
ErrorData::Custom(c) => c.kind,
ErrorData::Simple(kind) => kind,
ErrorData::SimpleMessage(m) => m.kind,
@ -1014,7 +1014,7 @@ impl Error {
#[inline]
pub(crate) fn is_interrupted(&self) -> bool {
match self.repr.data() {
ErrorData::Os(code) => sys::is_interrupted(code),
ErrorData::Os(code) => sys::io::is_interrupted(code),
ErrorData::Custom(c) => c.kind == ErrorKind::Interrupted,
ErrorData::Simple(kind) => kind == ErrorKind::Interrupted,
ErrorData::SimpleMessage(m) => m.kind == ErrorKind::Interrupted,
@ -1028,8 +1028,8 @@ impl fmt::Debug for Repr {
ErrorData::Os(code) => fmt
.debug_struct("Os")
.field("code", &code)
.field("kind", &sys::decode_error_kind(code))
.field("message", &sys::os::error_string(code))
.field("kind", &sys::io::decode_error_kind(code))
.field("message", &sys::io::error_string(code))
.finish(),
ErrorData::Custom(c) => fmt::Debug::fmt(&c, fmt),
ErrorData::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
@ -1047,7 +1047,7 @@ impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.repr.data() {
ErrorData::Os(code) => {
let detail = sys::os::error_string(code);
let detail = sys::io::error_string(code);
write!(fmt, "{detail} (os error {code})")
}
ErrorData::Custom(ref c) => c.error.fmt(fmt),

View file

@ -1,7 +1,6 @@
use super::{Custom, Error, ErrorData, ErrorKind, Repr, SimpleMessage, const_error};
use crate::assert_matches::assert_matches;
use crate::sys::decode_error_kind;
use crate::sys::os::error_string;
use crate::sys::io::{decode_error_kind, error_string};
use crate::{error, fmt};
#[test]

View file

@ -34,7 +34,7 @@ cfg_select! {
// lifetime of the thread. Additionally, accesses to `errno` are
// async-signal-safe, so this function is available in all imaginable
// circumstances.
let this_thread_id = crate::sys::os::errno_location();
let this_thread_id = crate::sys::io::errno_location();
match EXITING_THREAD_ID.compare_exchange(ptr::null_mut(), this_thread_id, Acquire, Relaxed) {
Ok(_) => {
// This is the first thread to call `unique_thread_exit`,

View file

@ -850,7 +850,7 @@ impl Iterator for ReadDir {
target_os = "wasi",
))]
fn next(&mut self) -> Option<io::Result<DirEntry>> {
use crate::sys::os::{errno, set_errno};
use crate::sys::io::{errno, set_errno};
if self.end_of_stream {
return None;
@ -988,7 +988,7 @@ impl Iterator for ReadDir {
/// The downside is that it costs an extra syscall, so we only do it for debug.
#[inline]
pub(crate) fn debug_assert_fd_is_open(fd: RawFd) {
use crate::sys::os::errno;
use crate::sys::io::errno;
// this is similar to assert_unsafe_precondition!() but it doesn't require const
if core::ub_checks::check_library_ub() {

View file

@ -0,0 +1,15 @@
pub fn errno() -> i32 {
0
}
pub fn is_interrupted(_code: i32) -> bool {
false
}
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Uncategorized
}
pub fn error_string(_errno: i32) -> String {
"operation successful".to_string()
}

View file

@ -0,0 +1,35 @@
use crate::io;
pub fn errno() -> i32 {
unsafe { hermit_abi::get_errno() }
}
#[inline]
pub fn is_interrupted(errno: i32) -> bool {
errno == hermit_abi::errno::EINTR
}
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
match errno {
hermit_abi::errno::EACCES => io::ErrorKind::PermissionDenied,
hermit_abi::errno::EADDRINUSE => io::ErrorKind::AddrInUse,
hermit_abi::errno::EADDRNOTAVAIL => io::ErrorKind::AddrNotAvailable,
hermit_abi::errno::EAGAIN => io::ErrorKind::WouldBlock,
hermit_abi::errno::ECONNABORTED => io::ErrorKind::ConnectionAborted,
hermit_abi::errno::ECONNREFUSED => io::ErrorKind::ConnectionRefused,
hermit_abi::errno::ECONNRESET => io::ErrorKind::ConnectionReset,
hermit_abi::errno::EEXIST => io::ErrorKind::AlreadyExists,
hermit_abi::errno::EINTR => io::ErrorKind::Interrupted,
hermit_abi::errno::EINVAL => io::ErrorKind::InvalidInput,
hermit_abi::errno::ENOENT => io::ErrorKind::NotFound,
hermit_abi::errno::ENOTCONN => io::ErrorKind::NotConnected,
hermit_abi::errno::EPERM => io::ErrorKind::PermissionDenied,
hermit_abi::errno::EPIPE => io::ErrorKind::BrokenPipe,
hermit_abi::errno::ETIMEDOUT => io::ErrorKind::TimedOut,
_ => io::ErrorKind::Uncategorized,
}
}
pub fn error_string(errno: i32) -> String {
hermit_abi::error_string(errno).to_string()
}

View file

@ -0,0 +1,55 @@
cfg_select! {
target_os = "hermit" => {
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::*;
}
target_os = "solid_asp3" => {
mod solid;
pub use solid::*;
}
target_os = "teeos" => {
mod teeos;
pub use teeos::*;
}
target_os = "uefi" => {
mod uefi;
pub use uefi::*;
}
target_family = "unix" => {
mod unix;
pub use unix::*;
}
target_os = "wasi" => {
mod wasi;
pub use wasi::*;
}
target_os = "windows" => {
mod windows;
pub use windows::*;
}
target_os = "xous" => {
mod xous;
pub use xous::*;
}
any(
target_os = "vexos",
target_family = "wasm",
target_os = "zkvm",
) => {
mod generic;
pub use generic::*;
}
}
pub type RawOsError = cfg_select! {
target_os = "uefi" => usize,
_ => i32,
};

View file

@ -0,0 +1,67 @@
use crate::io;
use crate::sys::io::RawOsError;
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.
let error_code: moto_rt::ErrorCode = moto_rt::Error::Unknown.into();
error_code.into()
}
pub fn is_interrupted(_code: io::RawOsError) -> bool {
false // Motor OS doesn't have signals.
}
pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind {
if code < 0 || code > u16::MAX.into() {
return io::ErrorKind::Uncategorized;
}
let error = moto_rt::Error::from(code as moto_rt::ErrorCode);
match error {
moto_rt::Error::Unspecified => io::ErrorKind::Uncategorized,
moto_rt::Error::Unknown => io::ErrorKind::Uncategorized,
moto_rt::Error::NotReady => io::ErrorKind::WouldBlock,
moto_rt::Error::NotImplemented => io::ErrorKind::Unsupported,
moto_rt::Error::VersionTooHigh => io::ErrorKind::Unsupported,
moto_rt::Error::VersionTooLow => io::ErrorKind::Unsupported,
moto_rt::Error::InvalidArgument => io::ErrorKind::InvalidInput,
moto_rt::Error::OutOfMemory => io::ErrorKind::OutOfMemory,
moto_rt::Error::NotAllowed => io::ErrorKind::PermissionDenied,
moto_rt::Error::NotFound => io::ErrorKind::NotFound,
moto_rt::Error::InternalError => io::ErrorKind::Other,
moto_rt::Error::TimedOut => io::ErrorKind::TimedOut,
moto_rt::Error::AlreadyInUse => io::ErrorKind::AlreadyExists,
moto_rt::Error::UnexpectedEof => io::ErrorKind::UnexpectedEof,
moto_rt::Error::InvalidFilename => io::ErrorKind::InvalidFilename,
moto_rt::Error::NotADirectory => io::ErrorKind::NotADirectory,
moto_rt::Error::BadHandle => io::ErrorKind::InvalidInput,
moto_rt::Error::FileTooLarge => io::ErrorKind::FileTooLarge,
moto_rt::Error::NotConnected => io::ErrorKind::NotConnected,
moto_rt::Error::StorageFull => io::ErrorKind::StorageFull,
moto_rt::Error::InvalidData => io::ErrorKind::InvalidData,
_ => io::ErrorKind::Uncategorized,
}
}
pub fn error_string(errno: RawOsError) -> String {
let error: moto_rt::Error = match errno {
x if x < 0 => moto_rt::Error::Unknown,
x if x > u16::MAX.into() => moto_rt::Error::Unknown,
x => (x as moto_rt::ErrorCode).into(), /* u16 */
};
format!("{}", error)
}

View file

@ -0,0 +1,65 @@
use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
use crate::io;
pub fn errno() -> i32 {
RESULT_SUCCESS
}
#[inline]
pub fn is_interrupted(code: i32) -> bool {
code == fortanix_sgx_abi::Error::Interrupted as _
}
pub fn decode_error_kind(code: i32) -> io::ErrorKind {
// FIXME: not sure how to make sure all variants of Error are covered
if code == Error::NotFound as _ {
io::ErrorKind::NotFound
} else if code == Error::PermissionDenied as _ {
io::ErrorKind::PermissionDenied
} else if code == Error::ConnectionRefused as _ {
io::ErrorKind::ConnectionRefused
} else if code == Error::ConnectionReset as _ {
io::ErrorKind::ConnectionReset
} else if code == Error::ConnectionAborted as _ {
io::ErrorKind::ConnectionAborted
} else if code == Error::NotConnected as _ {
io::ErrorKind::NotConnected
} else if code == Error::AddrInUse as _ {
io::ErrorKind::AddrInUse
} else if code == Error::AddrNotAvailable as _ {
io::ErrorKind::AddrNotAvailable
} else if code == Error::BrokenPipe as _ {
io::ErrorKind::BrokenPipe
} else if code == Error::AlreadyExists as _ {
io::ErrorKind::AlreadyExists
} else if code == Error::WouldBlock as _ {
io::ErrorKind::WouldBlock
} else if code == Error::InvalidInput as _ {
io::ErrorKind::InvalidInput
} else if code == Error::InvalidData as _ {
io::ErrorKind::InvalidData
} else if code == Error::TimedOut as _ {
io::ErrorKind::TimedOut
} else if code == Error::WriteZero as _ {
io::ErrorKind::WriteZero
} else if code == Error::Interrupted as _ {
io::ErrorKind::Interrupted
} else if code == Error::Other as _ {
io::ErrorKind::Uncategorized
} else if code == Error::UnexpectedEof as _ {
io::ErrorKind::UnexpectedEof
} else {
io::ErrorKind::Uncategorized
}
}
pub fn error_string(errno: i32) -> String {
if errno == RESULT_SUCCESS {
"operation successful".into()
} else if ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&errno) {
format!("user-specified error {errno:08x}")
} else {
decode_error_kind(errno).as_str().into()
}
}

View file

@ -0,0 +1,19 @@
use crate::io;
use crate::sys::pal::error;
pub fn errno() -> i32 {
0
}
#[inline]
pub fn is_interrupted(code: i32) -> bool {
crate::sys::net::is_interrupted(code)
}
pub fn decode_error_kind(code: i32) -> io::ErrorKind {
error::decode_error_kind(code)
}
pub fn error_string(errno: i32) -> String {
if let Some(name) = error::error_name(errno) { name.to_owned() } else { format!("{errno}") }
}

View file

@ -0,0 +1,64 @@
use crate::io;
pub fn errno() -> i32 {
unsafe { (*libc::__errno_location()) as i32 }
}
#[inline]
pub fn is_interrupted(errno: i32) -> bool {
errno == libc::EINTR
}
// Note: code below is 1:1 copied from unix/mod.rs
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
use io::ErrorKind::*;
match errno as libc::c_int {
libc::E2BIG => ArgumentListTooLong,
libc::EADDRINUSE => AddrInUse,
libc::EADDRNOTAVAIL => AddrNotAvailable,
libc::EBUSY => ResourceBusy,
libc::ECONNABORTED => ConnectionAborted,
libc::ECONNREFUSED => ConnectionRefused,
libc::ECONNRESET => ConnectionReset,
libc::EDEADLK => Deadlock,
libc::EDQUOT => QuotaExceeded,
libc::EEXIST => AlreadyExists,
libc::EFBIG => FileTooLarge,
libc::EHOSTUNREACH => HostUnreachable,
libc::EINTR => Interrupted,
libc::EINVAL => InvalidInput,
libc::EISDIR => IsADirectory,
libc::ELOOP => FilesystemLoop,
libc::ENOENT => NotFound,
libc::ENOMEM => OutOfMemory,
libc::ENOSPC => StorageFull,
libc::ENOSYS => Unsupported,
libc::EMLINK => TooManyLinks,
libc::ENAMETOOLONG => InvalidFilename,
libc::ENETDOWN => NetworkDown,
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
libc::ENOTDIR => NotADirectory,
libc::ENOTEMPTY => DirectoryNotEmpty,
libc::EPIPE => BrokenPipe,
libc::EROFS => ReadOnlyFilesystem,
libc::ESPIPE => NotSeekable,
libc::ESTALE => StaleNetworkFileHandle,
libc::ETIMEDOUT => TimedOut,
libc::ETXTBSY => ExecutableFileBusy,
libc::EXDEV => CrossesDevices,
libc::EACCES | libc::EPERM => PermissionDenied,
// These two constants can have the same value on some systems,
// but different values on others, so we can't use a match
// clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
_ => Uncategorized,
}
}
pub fn error_string(_errno: i32) -> String {
"error string unimplemented".to_string()
}

View file

@ -0,0 +1,104 @@
use r_efi::efi::Status;
use crate::io;
pub fn errno() -> io::RawOsError {
0
}
pub fn is_interrupted(_code: io::RawOsError) -> bool {
false
}
pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind {
match Status::from_usize(code) {
Status::ALREADY_STARTED
| Status::COMPROMISED_DATA
| Status::CONNECTION_FIN
| Status::CRC_ERROR
| Status::DEVICE_ERROR
| Status::END_OF_MEDIA
| Status::HTTP_ERROR
| Status::ICMP_ERROR
| Status::INCOMPATIBLE_VERSION
| Status::LOAD_ERROR
| Status::MEDIA_CHANGED
| Status::NO_MAPPING
| Status::NO_MEDIA
| Status::NOT_STARTED
| Status::PROTOCOL_ERROR
| Status::PROTOCOL_UNREACHABLE
| Status::TFTP_ERROR
| Status::VOLUME_CORRUPTED => io::ErrorKind::Other,
Status::BAD_BUFFER_SIZE | Status::INVALID_LANGUAGE => io::ErrorKind::InvalidData,
Status::ABORTED => io::ErrorKind::ConnectionAborted,
Status::ACCESS_DENIED => io::ErrorKind::PermissionDenied,
Status::BUFFER_TOO_SMALL => io::ErrorKind::FileTooLarge,
Status::CONNECTION_REFUSED => io::ErrorKind::ConnectionRefused,
Status::CONNECTION_RESET => io::ErrorKind::ConnectionReset,
Status::END_OF_FILE => io::ErrorKind::UnexpectedEof,
Status::HOST_UNREACHABLE => io::ErrorKind::HostUnreachable,
Status::INVALID_PARAMETER => io::ErrorKind::InvalidInput,
Status::IP_ADDRESS_CONFLICT => io::ErrorKind::AddrInUse,
Status::NETWORK_UNREACHABLE => io::ErrorKind::NetworkUnreachable,
Status::NO_RESPONSE => io::ErrorKind::HostUnreachable,
Status::NOT_FOUND => io::ErrorKind::NotFound,
Status::NOT_READY => io::ErrorKind::ResourceBusy,
Status::OUT_OF_RESOURCES => io::ErrorKind::OutOfMemory,
Status::SECURITY_VIOLATION => io::ErrorKind::PermissionDenied,
Status::TIMEOUT => io::ErrorKind::TimedOut,
Status::UNSUPPORTED => io::ErrorKind::Unsupported,
Status::VOLUME_FULL => io::ErrorKind::StorageFull,
Status::WRITE_PROTECTED => io::ErrorKind::ReadOnlyFilesystem,
_ => io::ErrorKind::Uncategorized,
}
}
pub fn error_string(errno: io::RawOsError) -> String {
// Keep the List in Alphabetical Order
// The Messages are taken from UEFI Specification Appendix D - Status Codes
#[rustfmt::skip]
let msg = match Status::from_usize(errno) {
Status::ABORTED => "The operation was aborted.",
Status::ACCESS_DENIED => "Access was denied.",
Status::ALREADY_STARTED => "The protocol has already been started.",
Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.",
Status::BUFFER_TOO_SMALL => "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs.",
Status::COMPROMISED_DATA => "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.",
Status::CONNECTION_FIN => "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance.",
Status::CONNECTION_REFUSED => "The receiving or transmission operation fails because this connection is refused.",
Status::CONNECTION_RESET => "The connect fails because the connection is reset either by instance itself or the communication peer.",
Status::CRC_ERROR => "A CRC error was detected.",
Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.",
Status::END_OF_FILE => "The end of the file was reached.",
Status::END_OF_MEDIA => "Beginning or end of media was reached",
Status::HOST_UNREACHABLE => "The remote host is not reachable.",
Status::HTTP_ERROR => "A HTTP error occurred during the network operation.",
Status::ICMP_ERROR => "An ICMP error occurred during the network operation.",
Status::INCOMPATIBLE_VERSION => "The function encountered an internal version that was incompatible with a version requested by the caller.",
Status::INVALID_LANGUAGE => "The language specified was invalid.",
Status::INVALID_PARAMETER => "A parameter was incorrect.",
Status::IP_ADDRESS_CONFLICT => "There is an address conflict address allocation",
Status::LOAD_ERROR => "The image failed to load.",
Status::MEDIA_CHANGED => "The medium in the device has changed since the last access.",
Status::NETWORK_UNREACHABLE => "The network containing the remote host is not reachable.",
Status::NO_MAPPING => "A mapping to a device does not exist.",
Status::NO_MEDIA => "The device does not contain any medium to perform the operation.",
Status::NO_RESPONSE => "The server was not found or did not respond to the request.",
Status::NOT_FOUND => "The item was not found.",
Status::NOT_READY => "There is no data pending upon return.",
Status::NOT_STARTED => "The protocol has not been started.",
Status::OUT_OF_RESOURCES => "A resource has run out.",
Status::PROTOCOL_ERROR => "A protocol error occurred during the network operation.",
Status::PROTOCOL_UNREACHABLE => "An ICMP protocol unreachable error is received.",
Status::SECURITY_VIOLATION => "The function was not performed due to a security violation.",
Status::TFTP_ERROR => "A TFTP error occurred during the network operation.",
Status::TIMEOUT => "The timeout time expired.",
Status::UNSUPPORTED => "The operation is not supported.",
Status::VOLUME_FULL => "There is no more space on the file system.",
Status::VOLUME_CORRUPTED => "An inconstancy was detected on the file system causing the operating to fail.",
Status::WRITE_PROTECTED => "The device cannot be written to.",
_ => return format!("Status: {errno}"),
};
msg.to_owned()
}

View file

@ -0,0 +1,186 @@
use crate::ffi::{CStr, c_char, c_int};
use crate::io;
unsafe extern "C" {
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
#[cfg_attr(
any(
target_os = "linux",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "l4re",
target_os = "hurd",
),
link_name = "__errno_location"
)]
#[cfg_attr(
any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "android",
target_os = "redox",
target_os = "nuttx",
target_env = "newlib"
),
link_name = "__errno"
)]
#[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
#[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
#[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
#[cfg_attr(target_os = "aix", link_name = "_Errno")]
// SAFETY: this will always return the same pointer on a given thread.
#[unsafe(ffi_const)]
pub safe fn errno_location() -> *mut c_int;
}
/// Returns the platform-specific value of errno
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
#[inline]
pub fn errno() -> i32 {
unsafe { (*errno_location()) as i32 }
}
/// Sets the platform-specific value of errno
// needed for readdir and syscall!
#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))]
#[allow(dead_code)] // but not all target cfgs actually end up using it
#[inline]
pub fn set_errno(e: i32) {
unsafe { *errno_location() = e as c_int }
}
#[cfg(target_os = "vxworks")]
#[inline]
pub fn errno() -> i32 {
unsafe { libc::errnoGet() }
}
#[cfg(target_os = "rtems")]
#[inline]
pub fn errno() -> i32 {
unsafe extern "C" {
#[thread_local]
static _tls_errno: c_int;
}
unsafe { _tls_errno as i32 }
}
#[cfg(target_os = "dragonfly")]
#[inline]
pub fn errno() -> i32 {
unsafe extern "C" {
#[thread_local]
static errno: c_int;
}
unsafe { errno as i32 }
}
#[cfg(target_os = "dragonfly")]
#[allow(dead_code)]
#[inline]
pub fn set_errno(e: i32) {
unsafe extern "C" {
#[thread_local]
static mut errno: c_int;
}
unsafe {
errno = e;
}
}
#[inline]
pub fn is_interrupted(errno: i32) -> bool {
errno == libc::EINTR
}
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
use io::ErrorKind::*;
match errno as libc::c_int {
libc::E2BIG => ArgumentListTooLong,
libc::EADDRINUSE => AddrInUse,
libc::EADDRNOTAVAIL => AddrNotAvailable,
libc::EBUSY => ResourceBusy,
libc::ECONNABORTED => ConnectionAborted,
libc::ECONNREFUSED => ConnectionRefused,
libc::ECONNRESET => ConnectionReset,
libc::EDEADLK => Deadlock,
libc::EDQUOT => QuotaExceeded,
libc::EEXIST => AlreadyExists,
libc::EFBIG => FileTooLarge,
libc::EHOSTUNREACH => HostUnreachable,
libc::EINTR => Interrupted,
libc::EINVAL => InvalidInput,
libc::EISDIR => IsADirectory,
libc::ELOOP => FilesystemLoop,
libc::ENOENT => NotFound,
libc::ENOMEM => OutOfMemory,
libc::ENOSPC => StorageFull,
libc::ENOSYS => Unsupported,
libc::EMLINK => TooManyLinks,
libc::ENAMETOOLONG => InvalidFilename,
libc::ENETDOWN => NetworkDown,
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
libc::ENOTDIR => NotADirectory,
#[cfg(not(target_os = "aix"))]
libc::ENOTEMPTY => DirectoryNotEmpty,
libc::EPIPE => BrokenPipe,
libc::EROFS => ReadOnlyFilesystem,
libc::ESPIPE => NotSeekable,
libc::ESTALE => StaleNetworkFileHandle,
libc::ETIMEDOUT => TimedOut,
libc::ETXTBSY => ExecutableFileBusy,
libc::EXDEV => CrossesDevices,
libc::EINPROGRESS => InProgress,
libc::EOPNOTSUPP => Unsupported,
libc::EACCES | libc::EPERM => PermissionDenied,
// These two constants can have the same value on some systems,
// but different values on others, so we can't use a match
// clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
_ => Uncategorized,
}
}
/// Gets a detailed string description for the given error number.
pub fn error_string(errno: i32) -> String {
const TMPBUF_SZ: usize = 128;
unsafe extern "C" {
#[cfg_attr(
all(
any(
target_os = "linux",
target_os = "hurd",
target_env = "newlib",
target_os = "cygwin"
),
not(target_env = "ohos")
),
link_name = "__xpg_strerror_r"
)]
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int;
}
let mut buf = [0 as c_char; TMPBUF_SZ];
let p = buf.as_mut_ptr();
unsafe {
if strerror_r(errno as c_int, p, buf.len()) < 0 {
panic!("strerror_r failure");
}
let p = p as *const _;
// We can't always expect a UTF-8 environment. When we don't get that luxury,
// it's better to give a low-quality error message than none at all.
String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into()
}
}

View file

@ -0,0 +1,80 @@
use crate::ffi::CStr;
use crate::io as std_io;
unsafe extern "C" {
#[thread_local]
#[link_name = "errno"]
static mut libc_errno: libc::c_int;
}
pub fn errno() -> i32 {
unsafe { libc_errno as i32 }
}
pub fn set_errno(val: i32) {
unsafe {
libc_errno = val;
}
}
#[inline]
pub fn is_interrupted(errno: i32) -> bool {
errno == libc::EINTR
}
pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
use std_io::ErrorKind::*;
match errno as libc::c_int {
libc::E2BIG => ArgumentListTooLong,
libc::EADDRINUSE => AddrInUse,
libc::EADDRNOTAVAIL => AddrNotAvailable,
libc::EBUSY => ResourceBusy,
libc::ECONNABORTED => ConnectionAborted,
libc::ECONNREFUSED => ConnectionRefused,
libc::ECONNRESET => ConnectionReset,
libc::EDEADLK => Deadlock,
libc::EDQUOT => QuotaExceeded,
libc::EEXIST => AlreadyExists,
libc::EFBIG => FileTooLarge,
libc::EHOSTUNREACH => HostUnreachable,
libc::EINTR => Interrupted,
libc::EINVAL => InvalidInput,
libc::EISDIR => IsADirectory,
libc::ELOOP => FilesystemLoop,
libc::ENOENT => NotFound,
libc::ENOMEM => OutOfMemory,
libc::ENOSPC => StorageFull,
libc::ENOSYS => Unsupported,
libc::EMLINK => TooManyLinks,
libc::ENAMETOOLONG => InvalidFilename,
libc::ENETDOWN => NetworkDown,
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
libc::ENOTDIR => NotADirectory,
libc::EPIPE => BrokenPipe,
libc::EROFS => ReadOnlyFilesystem,
libc::ESPIPE => NotSeekable,
libc::ESTALE => StaleNetworkFileHandle,
libc::ETIMEDOUT => TimedOut,
libc::ETXTBSY => ExecutableFileBusy,
libc::EXDEV => CrossesDevices,
libc::EINPROGRESS => InProgress,
libc::EOPNOTSUPP => Unsupported,
libc::EACCES | libc::EPERM => PermissionDenied,
libc::EWOULDBLOCK => WouldBlock,
_ => Uncategorized,
}
}
pub fn error_string(errno: i32) -> String {
let mut buf = [0 as libc::c_char; 1024];
let p = buf.as_mut_ptr();
unsafe {
if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
panic!("strerror_r failure");
}
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
}
}

View file

@ -0,0 +1,140 @@
use crate::sys::pal::{api, c};
use crate::{io, ptr};
pub fn errno() -> i32 {
api::get_last_error().code as i32
}
#[inline]
pub fn is_interrupted(_errno: i32) -> bool {
false
}
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
use io::ErrorKind::*;
match errno as u32 {
c::ERROR_ACCESS_DENIED => return PermissionDenied,
c::ERROR_ALREADY_EXISTS => return AlreadyExists,
c::ERROR_FILE_EXISTS => return AlreadyExists,
c::ERROR_BROKEN_PIPE => return BrokenPipe,
c::ERROR_FILE_NOT_FOUND
| c::ERROR_PATH_NOT_FOUND
| c::ERROR_INVALID_DRIVE
| c::ERROR_BAD_NETPATH
| c::ERROR_BAD_NET_NAME => return NotFound,
c::ERROR_NO_DATA => return BrokenPipe,
c::ERROR_INVALID_NAME | c::ERROR_BAD_PATHNAME => return InvalidFilename,
c::ERROR_INVALID_PARAMETER => return InvalidInput,
c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory,
c::ERROR_SEM_TIMEOUT
| c::WAIT_TIMEOUT
| c::ERROR_DRIVER_CANCEL_TIMEOUT
| c::ERROR_OPERATION_ABORTED
| c::ERROR_SERVICE_REQUEST_TIMEOUT
| c::ERROR_COUNTER_TIMEOUT
| c::ERROR_TIMEOUT
| c::ERROR_RESOURCE_CALL_TIMED_OUT
| c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT
| c::ERROR_CTX_CLIENT_QUERY_TIMEOUT
| c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT
| c::ERROR_DS_TIMELIMIT_EXCEEDED
| c::DNS_ERROR_RECORD_TIMED_OUT
| c::ERROR_IPSEC_IKE_TIMED_OUT
| c::ERROR_RUNLEVEL_SWITCH_TIMEOUT
| c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return TimedOut,
c::ERROR_CALL_NOT_IMPLEMENTED => return Unsupported,
c::ERROR_HOST_UNREACHABLE => return HostUnreachable,
c::ERROR_NETWORK_UNREACHABLE => return NetworkUnreachable,
c::ERROR_DIRECTORY => return NotADirectory,
c::ERROR_DIRECTORY_NOT_SUPPORTED => return IsADirectory,
c::ERROR_DIR_NOT_EMPTY => return DirectoryNotEmpty,
c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem,
c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull,
c::ERROR_SEEK_ON_DEVICE => return NotSeekable,
c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded,
c::ERROR_FILE_TOO_LARGE => return FileTooLarge,
c::ERROR_BUSY => return ResourceBusy,
c::ERROR_POSSIBLE_DEADLOCK => return Deadlock,
c::ERROR_NOT_SAME_DEVICE => return CrossesDevices,
c::ERROR_TOO_MANY_LINKS => return TooManyLinks,
c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename,
c::ERROR_CANT_RESOLVE_FILENAME => return FilesystemLoop,
_ => {}
}
match errno {
c::WSAEACCES => PermissionDenied,
c::WSAEADDRINUSE => AddrInUse,
c::WSAEADDRNOTAVAIL => AddrNotAvailable,
c::WSAECONNABORTED => ConnectionAborted,
c::WSAECONNREFUSED => ConnectionRefused,
c::WSAECONNRESET => ConnectionReset,
c::WSAEINVAL => InvalidInput,
c::WSAENOTCONN => NotConnected,
c::WSAEWOULDBLOCK => WouldBlock,
c::WSAETIMEDOUT => TimedOut,
c::WSAEHOSTUNREACH => HostUnreachable,
c::WSAENETDOWN => NetworkDown,
c::WSAENETUNREACH => NetworkUnreachable,
c::WSAEDQUOT => QuotaExceeded,
_ => Uncategorized,
}
}
/// Gets a detailed string description for the given error number.
pub fn error_string(mut errnum: i32) -> String {
let mut buf = [0 as c::WCHAR; 2048];
unsafe {
let mut module = ptr::null_mut();
let mut flags = 0;
// NTSTATUS errors may be encoded as HRESULT, which may returned from
// GetLastError. For more information about Windows error codes, see
// `[MS-ERREF]`: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a
if (errnum & c::FACILITY_NT_BIT as i32) != 0 {
// format according to https://support.microsoft.com/en-us/help/259693
const NTDLL_DLL: &[u16] = &[
'N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _, '.' as _, 'D' as _, 'L' as _,
'L' as _, 0,
];
module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
if !module.is_null() {
errnum ^= c::FACILITY_NT_BIT as i32;
flags = c::FORMAT_MESSAGE_FROM_HMODULE;
}
}
let res = c::FormatMessageW(
flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS,
module,
errnum as u32,
0,
buf.as_mut_ptr(),
buf.len() as u32,
ptr::null(),
) as usize;
if res == 0 {
// Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId,
let fm_err = errno();
return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})");
}
match String::from_utf16(&buf[..res]) {
Ok(mut msg) => {
// Trim trailing CRLF inserted by FormatMessageW
let len = msg.trim_end().len();
msg.truncate(len);
msg
}
Err(..) => format!(
"OS Error {} (FormatMessageW() returned \
invalid UTF-16)",
errnum
),
}
}
}

View file

@ -0,0 +1,17 @@
use crate::os::xous::ffi::Error as XousError;
pub fn errno() -> i32 {
0
}
pub fn is_interrupted(_code: i32) -> bool {
false
}
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Uncategorized
}
pub fn error_string(errno: i32) -> String {
Into::<XousError>::into(errno).to_string()
}

View file

@ -1,5 +1,7 @@
#![forbid(unsafe_op_in_unsafe_fn)]
mod error;
mod io_slice {
cfg_select! {
any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty", target_os = "wasi") => {
@ -48,6 +50,19 @@ mod is_terminal {
mod kernel_copy;
#[cfg_attr(not(target_os = "linux"), allow(unused_imports))]
#[cfg(all(
target_family = "unix",
not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems"))
))]
pub use error::errno_location;
#[cfg_attr(not(target_os = "linux"), allow(unused_imports))]
#[cfg(any(
all(target_family = "unix", not(any(target_os = "vxworks", target_os = "rtems"))),
target_os = "wasi",
))]
pub use error::set_errno;
pub use error::{RawOsError, decode_error_kind, errno, error_string, is_interrupted};
pub use io_slice::{IoSlice, IoSliceMut};
pub use is_terminal::is_terminal;
pub use kernel_copy::{CopyState, kernel_copy};
@ -55,8 +70,3 @@ pub use kernel_copy::{CopyState, kernel_copy};
// Bare metal platforms usually have very small amounts of RAM
// (in the order of hundreds of KB)
pub const DEFAULT_BUF_SIZE: usize = if cfg!(target_os = "espidf") { 512 } else { 8 * 1024 };
pub type RawOsError = cfg_select! {
target_os = "uefi" => usize,
_ => i32,
};

View file

@ -151,7 +151,7 @@ impl Socket {
loop {
let result = unsafe { libc::connect(self.as_raw_fd(), addr.as_ptr(), len) };
if result.is_minus_one() {
let err = crate::sys::os::errno();
let err = crate::sys::io::errno();
match err {
libc::EINTR => continue,
libc::EISCONN => return Ok(()),

View file

@ -1,7 +1,7 @@
use crate::ffi::OsString;
use crate::io;
use crate::os::unix::ffi::OsStringExt;
use crate::sys::pal::os::errno;
use crate::sys::io::errno;
pub fn hostname() -> io::Result<OsString> {
// Query the system for the maximum host name length.

View file

@ -75,32 +75,6 @@ pub unsafe extern "C" fn runtime_entry(
}
}
#[inline]
pub(crate) fn is_interrupted(errno: i32) -> bool {
errno == hermit_abi::errno::EINTR
}
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
match errno {
hermit_abi::errno::EACCES => io::ErrorKind::PermissionDenied,
hermit_abi::errno::EADDRINUSE => io::ErrorKind::AddrInUse,
hermit_abi::errno::EADDRNOTAVAIL => io::ErrorKind::AddrNotAvailable,
hermit_abi::errno::EAGAIN => io::ErrorKind::WouldBlock,
hermit_abi::errno::ECONNABORTED => io::ErrorKind::ConnectionAborted,
hermit_abi::errno::ECONNREFUSED => io::ErrorKind::ConnectionRefused,
hermit_abi::errno::ECONNRESET => io::ErrorKind::ConnectionReset,
hermit_abi::errno::EEXIST => io::ErrorKind::AlreadyExists,
hermit_abi::errno::EINTR => io::ErrorKind::Interrupted,
hermit_abi::errno::EINVAL => io::ErrorKind::InvalidInput,
hermit_abi::errno::ENOENT => io::ErrorKind::NotFound,
hermit_abi::errno::ENOTCONN => io::ErrorKind::NotConnected,
hermit_abi::errno::EPERM => io::ErrorKind::PermissionDenied,
hermit_abi::errno::EPIPE => io::ErrorKind::BrokenPipe,
hermit_abi::errno::ETIMEDOUT => io::ErrorKind::TimedOut,
_ => io::ErrorKind::Uncategorized,
}
}
#[doc(hidden)]
pub trait IsNegative {
fn is_negative(&self) -> bool;
@ -131,12 +105,7 @@ impl IsNegative for i32 {
impl_is_negative! { i8 i16 i64 isize }
pub fn cvt<T: IsNegative>(t: T) -> io::Result<T> {
if t.is_negative() {
let e = decode_error_kind(t.negate());
Err(io::Error::from(e))
} else {
Ok(t)
}
if t.is_negative() { Err(io::Error::from_raw_os_error(t.negate())) } else { Ok(t) }
}
pub fn cvt_r<T, F>(mut f: F) -> io::Result<T>

View file

@ -5,14 +5,6 @@ use crate::path::{self, PathBuf};
use crate::sys::unsupported;
use crate::{fmt, io};
pub fn errno() -> i32 {
unsafe { hermit_abi::get_errno() }
}
pub fn error_string(errno: i32) -> String {
hermit_abi::error_string(errno).to_string()
}
pub fn getcwd() -> io::Result<PathBuf> {
Ok(PathBuf::from("/"))
}

View file

@ -44,45 +44,6 @@ pub fn unsupported_err() -> io::Error {
io::Error::UNSUPPORTED_PLATFORM
}
pub fn is_interrupted(_code: io::RawOsError) -> bool {
false // Motor OS doesn't have signals.
}
pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind {
use moto_rt::error::*;
if code < 0 || code > u16::MAX.into() {
return io::ErrorKind::Uncategorized;
}
let error = moto_rt::Error::from(code as moto_rt::ErrorCode);
match error {
moto_rt::Error::Unspecified => io::ErrorKind::Uncategorized,
moto_rt::Error::Unknown => io::ErrorKind::Uncategorized,
moto_rt::Error::NotReady => io::ErrorKind::WouldBlock,
moto_rt::Error::NotImplemented => io::ErrorKind::Unsupported,
moto_rt::Error::VersionTooHigh => io::ErrorKind::Unsupported,
moto_rt::Error::VersionTooLow => io::ErrorKind::Unsupported,
moto_rt::Error::InvalidArgument => io::ErrorKind::InvalidInput,
moto_rt::Error::OutOfMemory => io::ErrorKind::OutOfMemory,
moto_rt::Error::NotAllowed => io::ErrorKind::PermissionDenied,
moto_rt::Error::NotFound => io::ErrorKind::NotFound,
moto_rt::Error::InternalError => io::ErrorKind::Other,
moto_rt::Error::TimedOut => io::ErrorKind::TimedOut,
moto_rt::Error::AlreadyInUse => io::ErrorKind::AlreadyExists,
moto_rt::Error::UnexpectedEof => io::ErrorKind::UnexpectedEof,
moto_rt::Error::InvalidFilename => io::ErrorKind::InvalidFilename,
moto_rt::Error::NotADirectory => io::ErrorKind::NotADirectory,
moto_rt::Error::BadHandle => io::ErrorKind::InvalidInput,
moto_rt::Error::FileTooLarge => io::ErrorKind::FileTooLarge,
moto_rt::Error::NotConnected => io::ErrorKind::NotConnected,
moto_rt::Error::StorageFull => io::ErrorKind::StorageFull,
moto_rt::Error::InvalidData => io::ErrorKind::InvalidData,
_ => io::ErrorKind::Uncategorized,
}
}
pub fn abort_internal() -> ! {
core::intrinsics::abort();
}

View file

@ -4,37 +4,8 @@ use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::motor::ffi::OsStrExt;
use crate::path::{self, PathBuf};
use crate::sys::io::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.
let error_code: moto_rt::ErrorCode = moto_rt::Error::Unknown.into();
error_code.into()
}
pub fn error_string(errno: RawOsError) -> String {
let error: moto_rt::Error = match errno {
x if x < 0 => moto_rt::Error::Unknown,
x if x > u16::MAX.into() => moto_rt::Error::Unknown,
x => (x as moto_rt::ErrorCode).into(), /* u16 */
};
format!("{}", error)
}
pub fn getcwd() -> io::Result<PathBuf> {
moto_rt::fs::getcwd().map(PathBuf::from).map_err(map_motor_error)
}

View file

@ -54,56 +54,6 @@ pub fn sgx_ineffective<T>(v: T) -> io::Result<T> {
}
}
#[inline]
pub fn is_interrupted(code: i32) -> bool {
code == fortanix_sgx_abi::Error::Interrupted as _
}
pub fn decode_error_kind(code: i32) -> io::ErrorKind {
use fortanix_sgx_abi::Error;
// FIXME: not sure how to make sure all variants of Error are covered
if code == Error::NotFound as _ {
io::ErrorKind::NotFound
} else if code == Error::PermissionDenied as _ {
io::ErrorKind::PermissionDenied
} else if code == Error::ConnectionRefused as _ {
io::ErrorKind::ConnectionRefused
} else if code == Error::ConnectionReset as _ {
io::ErrorKind::ConnectionReset
} else if code == Error::ConnectionAborted as _ {
io::ErrorKind::ConnectionAborted
} else if code == Error::NotConnected as _ {
io::ErrorKind::NotConnected
} else if code == Error::AddrInUse as _ {
io::ErrorKind::AddrInUse
} else if code == Error::AddrNotAvailable as _ {
io::ErrorKind::AddrNotAvailable
} else if code == Error::BrokenPipe as _ {
io::ErrorKind::BrokenPipe
} else if code == Error::AlreadyExists as _ {
io::ErrorKind::AlreadyExists
} else if code == Error::WouldBlock as _ {
io::ErrorKind::WouldBlock
} else if code == Error::InvalidInput as _ {
io::ErrorKind::InvalidInput
} else if code == Error::InvalidData as _ {
io::ErrorKind::InvalidData
} else if code == Error::TimedOut as _ {
io::ErrorKind::TimedOut
} else if code == Error::WriteZero as _ {
io::ErrorKind::WriteZero
} else if code == Error::Interrupted as _ {
io::ErrorKind::Interrupted
} else if code == Error::Other as _ {
io::ErrorKind::Uncategorized
} else if code == Error::UnexpectedEof as _ {
io::ErrorKind::UnexpectedEof
} else {
io::ErrorKind::Uncategorized
}
}
pub fn abort_internal() -> ! {
abi::usercalls::exit(true)
}

View file

@ -1,25 +1,9 @@
use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
use crate::sys::{sgx_ineffective, unsupported};
use crate::{fmt, io};
pub fn errno() -> i32 {
RESULT_SUCCESS
}
pub fn error_string(errno: i32) -> String {
if errno == RESULT_SUCCESS {
"operation successful".into()
} else if ((Error::UserRangeStart as _)..=(Error::UserRangeEnd as _)).contains(&errno) {
format!("user-specified error {errno:08x}")
} else {
decode_error_kind(errno).as_str().into()
}
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}

View file

@ -38,15 +38,6 @@ pub fn unsupported_err() -> io::Error {
io::Error::UNSUPPORTED_PLATFORM
}
#[inline]
pub fn is_interrupted(code: i32) -> bool {
crate::sys::net::is_interrupted(code)
}
pub fn decode_error_kind(code: i32) -> io::ErrorKind {
error::decode_error_kind(code)
}
#[inline]
pub fn abort_internal() -> ! {
unsafe { libc::abort() }

View file

@ -1,4 +1,4 @@
use super::{error, itron, unsupported};
use super::{itron, unsupported};
use crate::ffi::{OsStr, OsString};
use crate::path::{self, PathBuf};
use crate::{fmt, io};
@ -11,14 +11,6 @@ impl itron::error::ItronError {
}
}
pub fn errno() -> i32 {
0
}
pub fn error_string(errno: i32) -> String {
if let Some(name) = error::error_name(errno) { name.to_owned() } else { format!("{errno}") }
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}

View file

@ -38,61 +38,6 @@ pub unsafe fn cleanup() {
// stack_overflow::cleanup();
}
#[inline]
pub(crate) fn is_interrupted(errno: i32) -> bool {
errno == libc::EINTR
}
// Note: code below is 1:1 copied from unix/mod.rs
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
use io::ErrorKind::*;
match errno as libc::c_int {
libc::E2BIG => ArgumentListTooLong,
libc::EADDRINUSE => AddrInUse,
libc::EADDRNOTAVAIL => AddrNotAvailable,
libc::EBUSY => ResourceBusy,
libc::ECONNABORTED => ConnectionAborted,
libc::ECONNREFUSED => ConnectionRefused,
libc::ECONNRESET => ConnectionReset,
libc::EDEADLK => Deadlock,
libc::EDQUOT => QuotaExceeded,
libc::EEXIST => AlreadyExists,
libc::EFBIG => FileTooLarge,
libc::EHOSTUNREACH => HostUnreachable,
libc::EINTR => Interrupted,
libc::EINVAL => InvalidInput,
libc::EISDIR => IsADirectory,
libc::ELOOP => FilesystemLoop,
libc::ENOENT => NotFound,
libc::ENOMEM => OutOfMemory,
libc::ENOSPC => StorageFull,
libc::ENOSYS => Unsupported,
libc::EMLINK => TooManyLinks,
libc::ENAMETOOLONG => InvalidFilename,
libc::ENETDOWN => NetworkDown,
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
libc::ENOTDIR => NotADirectory,
libc::ENOTEMPTY => DirectoryNotEmpty,
libc::EPIPE => BrokenPipe,
libc::EROFS => ReadOnlyFilesystem,
libc::ESPIPE => NotSeekable,
libc::ESTALE => StaleNetworkFileHandle,
libc::ETIMEDOUT => TimedOut,
libc::ETXTBSY => ExecutableFileBusy,
libc::EXDEV => CrossesDevices,
libc::EACCES | libc::EPERM => PermissionDenied,
// These two constants can have the same value on some systems,
// but different values on others, so we can't use a match
// clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
_ => Uncategorized,
}
}
#[doc(hidden)]
pub trait IsMinusOne {
fn is_minus_one(&self) -> bool;

View file

@ -7,10 +7,6 @@ use crate::ffi::{OsStr, OsString};
use crate::path::PathBuf;
use crate::{fmt, io, path};
pub fn errno() -> i32 {
unsafe { (*libc::__errno_location()) as i32 }
}
// Hardcoded to return 4096, since `sysconf` is only implemented as a stub.
pub fn page_size() -> usize {
// unsafe { libc::sysconf(libc::_SC_PAGESIZE) as usize };
@ -19,10 +15,6 @@ pub fn page_size() -> usize {
// Everything below are stubs and copied from unsupported.rs
pub fn error_string(_errno: i32) -> String {
"error string unimplemented".to_string()
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}

View file

@ -83,52 +83,6 @@ pub const fn unsupported_err() -> io::Error {
io::const_error!(io::ErrorKind::Unsupported, "operation not supported on UEFI")
}
pub fn decode_error_kind(code: io::RawOsError) -> io::ErrorKind {
use r_efi::efi::Status;
match r_efi::efi::Status::from_usize(code) {
Status::ALREADY_STARTED
| Status::COMPROMISED_DATA
| Status::CONNECTION_FIN
| Status::CRC_ERROR
| Status::DEVICE_ERROR
| Status::END_OF_MEDIA
| Status::HTTP_ERROR
| Status::ICMP_ERROR
| Status::INCOMPATIBLE_VERSION
| Status::LOAD_ERROR
| Status::MEDIA_CHANGED
| Status::NO_MAPPING
| Status::NO_MEDIA
| Status::NOT_STARTED
| Status::PROTOCOL_ERROR
| Status::PROTOCOL_UNREACHABLE
| Status::TFTP_ERROR
| Status::VOLUME_CORRUPTED => io::ErrorKind::Other,
Status::BAD_BUFFER_SIZE | Status::INVALID_LANGUAGE => io::ErrorKind::InvalidData,
Status::ABORTED => io::ErrorKind::ConnectionAborted,
Status::ACCESS_DENIED => io::ErrorKind::PermissionDenied,
Status::BUFFER_TOO_SMALL => io::ErrorKind::FileTooLarge,
Status::CONNECTION_REFUSED => io::ErrorKind::ConnectionRefused,
Status::CONNECTION_RESET => io::ErrorKind::ConnectionReset,
Status::END_OF_FILE => io::ErrorKind::UnexpectedEof,
Status::HOST_UNREACHABLE => io::ErrorKind::HostUnreachable,
Status::INVALID_PARAMETER => io::ErrorKind::InvalidInput,
Status::IP_ADDRESS_CONFLICT => io::ErrorKind::AddrInUse,
Status::NETWORK_UNREACHABLE => io::ErrorKind::NetworkUnreachable,
Status::NO_RESPONSE => io::ErrorKind::HostUnreachable,
Status::NOT_FOUND => io::ErrorKind::NotFound,
Status::NOT_READY => io::ErrorKind::ResourceBusy,
Status::OUT_OF_RESOURCES => io::ErrorKind::OutOfMemory,
Status::SECURITY_VIOLATION => io::ErrorKind::PermissionDenied,
Status::TIMEOUT => io::ErrorKind::TimedOut,
Status::UNSUPPORTED => io::ErrorKind::Unsupported,
Status::VOLUME_FULL => io::ErrorKind::StorageFull,
Status::WRITE_PROTECTED => io::ErrorKind::ReadOnlyFilesystem,
_ => io::ErrorKind::Uncategorized,
}
}
pub fn abort_internal() -> ! {
if let Some(exit_boot_service_event) =
NonNull::new(EXIT_BOOT_SERVICE_EVENT.load(Ordering::Acquire))
@ -158,7 +112,3 @@ pub fn abort_internal() -> ! {
extern "efiapi" fn exit_boot_service_handler(_e: r_efi::efi::Event, _ctx: *mut crate::ffi::c_void) {
uefi::env::disable_boot_services();
}
pub fn is_interrupted(_code: io::RawOsError) -> bool {
false
}

View file

@ -9,59 +9,6 @@ use crate::path::{self, PathBuf};
use crate::ptr::NonNull;
use crate::{fmt, io};
pub fn errno() -> io::RawOsError {
0
}
pub fn error_string(errno: io::RawOsError) -> String {
// Keep the List in Alphabetical Order
// The Messages are taken from UEFI Specification Appendix D - Status Codes
#[rustfmt::skip]
let msg = match r_efi::efi::Status::from_usize(errno) {
Status::ABORTED => "The operation was aborted.",
Status::ACCESS_DENIED => "Access was denied.",
Status::ALREADY_STARTED => "The protocol has already been started.",
Status::BAD_BUFFER_SIZE => "The buffer was not the proper size for the request.",
Status::BUFFER_TOO_SMALL => "The buffer is not large enough to hold the requested data. The required buffer size is returned in the appropriate parameter when this error occurs.",
Status::COMPROMISED_DATA => "The security status of the data is unknown or compromised and the data must be updated or replaced to restore a valid security status.",
Status::CONNECTION_FIN => "The receiving operation fails because the communication peer has closed the connection and there is no more data in the receive buffer of the instance.",
Status::CONNECTION_REFUSED => "The receiving or transmission operation fails because this connection is refused.",
Status::CONNECTION_RESET => "The connect fails because the connection is reset either by instance itself or the communication peer.",
Status::CRC_ERROR => "A CRC error was detected.",
Status::DEVICE_ERROR => "The physical device reported an error while attempting the operation.",
Status::END_OF_FILE => "The end of the file was reached.",
Status::END_OF_MEDIA => "Beginning or end of media was reached",
Status::HOST_UNREACHABLE => "The remote host is not reachable.",
Status::HTTP_ERROR => "A HTTP error occurred during the network operation.",
Status::ICMP_ERROR => "An ICMP error occurred during the network operation.",
Status::INCOMPATIBLE_VERSION => "The function encountered an internal version that was incompatible with a version requested by the caller.",
Status::INVALID_LANGUAGE => "The language specified was invalid.",
Status::INVALID_PARAMETER => "A parameter was incorrect.",
Status::IP_ADDRESS_CONFLICT => "There is an address conflict address allocation",
Status::LOAD_ERROR => "The image failed to load.",
Status::MEDIA_CHANGED => "The medium in the device has changed since the last access.",
Status::NETWORK_UNREACHABLE => "The network containing the remote host is not reachable.",
Status::NO_MAPPING => "A mapping to a device does not exist.",
Status::NO_MEDIA => "The device does not contain any medium to perform the operation.",
Status::NO_RESPONSE => "The server was not found or did not respond to the request.",
Status::NOT_FOUND => "The item was not found.",
Status::NOT_READY => "There is no data pending upon return.",
Status::NOT_STARTED => "The protocol has not been started.",
Status::OUT_OF_RESOURCES => "A resource has run out.",
Status::PROTOCOL_ERROR => "A protocol error occurred during the network operation.",
Status::PROTOCOL_UNREACHABLE => "An ICMP protocol unreachable error is received.",
Status::SECURITY_VIOLATION => "The function was not performed due to a security violation.",
Status::TFTP_ERROR => "A TFTP error occurred during the network operation.",
Status::TIMEOUT => "The timeout time expired.",
Status::UNSUPPORTED => "The operation is not supported.",
Status::VOLUME_FULL => "There is no more space on the file system.",
Status::VOLUME_CORRUPTED => "An inconstancy was detected on the file system causing the operating to fail.",
Status::WRITE_PROTECTED => "The device cannot be written to.",
_ => return format!("Status: {errno}"),
};
msg.to_owned()
}
pub fn getcwd() -> io::Result<PathBuf> {
match helpers::open_shell() {
Some(shell) => {

View file

@ -86,7 +86,7 @@ pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>)
}
};
match (r < 0).then(super::os::errno) {
match (r < 0).then(crate::sys::io::errno) {
Some(libc::ETIMEDOUT) => return false,
Some(libc::EINTR) => continue,
_ => return true,
@ -167,7 +167,7 @@ pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>)
)
};
r == 0 || super::os::errno() != libc::ETIMEDOUT
r == 0 || crate::sys::io::errno() != libc::ETIMEDOUT
}
#[cfg(target_os = "openbsd")]
@ -210,7 +210,7 @@ pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>)
libc::umtx_sleep(futex as *const Atomic<u32> as *const i32, expected as i32, timeout_ms)
};
r == 0 || super::os::errno() != libc::ETIMEDOUT
r == 0 || crate::sys::io::errno() != libc::ETIMEDOUT
}
// DragonflyBSD doesn't tell us how many threads are woken up, so this always returns false.

View file

@ -91,7 +91,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
target_vendor = "apple",
)))]
'poll: {
use crate::sys::os::errno;
use crate::sys::io::errno;
let pfds: &mut [_] = &mut [
libc::pollfd { fd: 0, events: 0, revents: 0 },
libc::pollfd { fd: 1, events: 0, revents: 0 },
@ -135,7 +135,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
target_os = "vita",
)))]
{
use crate::sys::os::errno;
use crate::sys::io::errno;
for fd in 0..3 {
if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
open_devnull();
@ -224,63 +224,6 @@ pub unsafe fn cleanup() {
#[allow(unused_imports)]
pub use libc::signal;
#[inline]
pub(crate) fn is_interrupted(errno: i32) -> bool {
errno == libc::EINTR
}
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
use io::ErrorKind::*;
match errno as libc::c_int {
libc::E2BIG => ArgumentListTooLong,
libc::EADDRINUSE => AddrInUse,
libc::EADDRNOTAVAIL => AddrNotAvailable,
libc::EBUSY => ResourceBusy,
libc::ECONNABORTED => ConnectionAborted,
libc::ECONNREFUSED => ConnectionRefused,
libc::ECONNRESET => ConnectionReset,
libc::EDEADLK => Deadlock,
libc::EDQUOT => QuotaExceeded,
libc::EEXIST => AlreadyExists,
libc::EFBIG => FileTooLarge,
libc::EHOSTUNREACH => HostUnreachable,
libc::EINTR => Interrupted,
libc::EINVAL => InvalidInput,
libc::EISDIR => IsADirectory,
libc::ELOOP => FilesystemLoop,
libc::ENOENT => NotFound,
libc::ENOMEM => OutOfMemory,
libc::ENOSPC => StorageFull,
libc::ENOSYS => Unsupported,
libc::EMLINK => TooManyLinks,
libc::ENAMETOOLONG => InvalidFilename,
libc::ENETDOWN => NetworkDown,
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
libc::ENOTDIR => NotADirectory,
#[cfg(not(target_os = "aix"))]
libc::ENOTEMPTY => DirectoryNotEmpty,
libc::EPIPE => BrokenPipe,
libc::EROFS => ReadOnlyFilesystem,
libc::ESPIPE => NotSeekable,
libc::ESTALE => StaleNetworkFileHandle,
libc::ETIMEDOUT => TimedOut,
libc::ETXTBSY => ExecutableFileBusy,
libc::EXDEV => CrossesDevices,
libc::EINPROGRESS => InProgress,
libc::EOPNOTSUPP => Unsupported,
libc::EACCES | libc::EPERM => PermissionDenied,
// These two constants can have the same value on some systems,
// but different values on others, so we can't use a match
// clause
x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
_ => Uncategorized,
}
}
#[doc(hidden)]
pub trait IsMinusOne {
fn is_minus_one(&self) -> bool;

View file

@ -14,135 +14,8 @@ use crate::sys::cvt;
use crate::sys::helpers::run_path_with_cstr;
use crate::{fmt, io, iter, mem, ptr, slice, str};
const TMPBUF_SZ: usize = 128;
const PATH_SEPARATOR: u8 = b':';
unsafe extern "C" {
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
#[cfg_attr(
any(
target_os = "linux",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "l4re",
target_os = "hurd",
),
link_name = "__errno_location"
)]
#[cfg_attr(
any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "cygwin",
target_os = "android",
target_os = "redox",
target_os = "nuttx",
target_env = "newlib"
),
link_name = "__errno"
)]
#[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
#[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
#[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
#[cfg_attr(target_os = "aix", link_name = "_Errno")]
// SAFETY: this will always return the same pointer on a given thread.
#[unsafe(ffi_const)]
pub safe fn errno_location() -> *mut c_int;
}
/// Returns the platform-specific value of errno
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
#[inline]
pub fn errno() -> i32 {
unsafe { (*errno_location()) as i32 }
}
/// Sets the platform-specific value of errno
// needed for readdir and syscall!
#[cfg(all(not(target_os = "dragonfly"), not(target_os = "vxworks"), not(target_os = "rtems")))]
#[allow(dead_code)] // but not all target cfgs actually end up using it
#[inline]
pub fn set_errno(e: i32) {
unsafe { *errno_location() = e as c_int }
}
#[cfg(target_os = "vxworks")]
#[inline]
pub fn errno() -> i32 {
unsafe { libc::errnoGet() }
}
#[cfg(target_os = "rtems")]
#[inline]
pub fn errno() -> i32 {
unsafe extern "C" {
#[thread_local]
static _tls_errno: c_int;
}
unsafe { _tls_errno as i32 }
}
#[cfg(target_os = "dragonfly")]
#[inline]
pub fn errno() -> i32 {
unsafe extern "C" {
#[thread_local]
static errno: c_int;
}
unsafe { errno as i32 }
}
#[cfg(target_os = "dragonfly")]
#[allow(dead_code)]
#[inline]
pub fn set_errno(e: i32) {
unsafe extern "C" {
#[thread_local]
static mut errno: c_int;
}
unsafe {
errno = e;
}
}
/// Gets a detailed string description for the given error number.
pub fn error_string(errno: i32) -> String {
unsafe extern "C" {
#[cfg_attr(
all(
any(
target_os = "linux",
target_os = "hurd",
target_env = "newlib",
target_os = "cygwin"
),
not(target_env = "ohos")
),
link_name = "__xpg_strerror_r"
)]
fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int;
}
let mut buf = [0 as c_char; TMPBUF_SZ];
let p = buf.as_mut_ptr();
unsafe {
if strerror_r(errno as c_int, p, buf.len()) < 0 {
panic!("strerror_r failure");
}
let p = p as *const _;
// We can't always expect a UTF-8 environment. When we don't get that luxury,
// it's better to give a low-quality error message than none at all.
String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into()
}
}
#[cfg(target_os = "espidf")]
pub fn getcwd() -> io::Result<PathBuf> {
Ok(PathBuf::from("/"))

View file

@ -29,7 +29,7 @@ use crate::hint::spin_loop;
use crate::ops::Range;
use crate::sync::Mutex;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::os::errno_location;
use crate::sys::io::errno_location;
pub struct ThreadInfo {
pub tid: u64,

View file

@ -16,14 +16,6 @@ pub fn unsupported_err() -> std_io::Error {
std_io::Error::UNSUPPORTED_PLATFORM
}
pub fn is_interrupted(_code: i32) -> bool {
false
}
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Uncategorized
}
pub fn abort_internal() -> ! {
core::intrinsics::abort();
}

View file

@ -4,14 +4,6 @@ use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::{fmt, io};
pub fn errno() -> i32 {
0
}
pub fn error_string(_errno: i32) -> String {
"operation successful".to_string()
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}

View file

@ -5,9 +5,7 @@ pub mod time;
#[path = "../unsupported/common.rs"]
mod unsupported_common;
pub use unsupported_common::{
decode_error_kind, init, is_interrupted, unsupported, unsupported_err,
};
pub use unsupported_common::{init, unsupported, unsupported_err};
use crate::arch::global_asm;
use crate::ptr;

View file

@ -2,8 +2,8 @@
#[path = "../unsupported/os.rs"]
mod unsupported_os;
pub use unsupported_os::{
JoinPathsError, SplitPaths, chdir, current_exe, errno, error_string, getcwd, getpid, home_dir,
join_paths, split_paths, temp_dir,
JoinPathsError, SplitPaths, chdir, current_exe, getcwd, getpid, home_dir, join_paths,
split_paths, temp_dir,
};
pub use super::unsupported;

View file

@ -1,63 +1,11 @@
#![forbid(unsafe_op_in_unsafe_fn)]
use crate::io as std_io;
#[inline]
pub fn is_interrupted(errno: i32) -> bool {
errno == libc::EINTR
}
pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
use std_io::ErrorKind::*;
match errno as libc::c_int {
libc::E2BIG => ArgumentListTooLong,
libc::EADDRINUSE => AddrInUse,
libc::EADDRNOTAVAIL => AddrNotAvailable,
libc::EBUSY => ResourceBusy,
libc::ECONNABORTED => ConnectionAborted,
libc::ECONNREFUSED => ConnectionRefused,
libc::ECONNRESET => ConnectionReset,
libc::EDEADLK => Deadlock,
libc::EDQUOT => QuotaExceeded,
libc::EEXIST => AlreadyExists,
libc::EFBIG => FileTooLarge,
libc::EHOSTUNREACH => HostUnreachable,
libc::EINTR => Interrupted,
libc::EINVAL => InvalidInput,
libc::EISDIR => IsADirectory,
libc::ELOOP => FilesystemLoop,
libc::ENOENT => NotFound,
libc::ENOMEM => OutOfMemory,
libc::ENOSPC => StorageFull,
libc::ENOSYS => Unsupported,
libc::EMLINK => TooManyLinks,
libc::ENAMETOOLONG => InvalidFilename,
libc::ENETDOWN => NetworkDown,
libc::ENETUNREACH => NetworkUnreachable,
libc::ENOTCONN => NotConnected,
libc::ENOTDIR => NotADirectory,
libc::EPIPE => BrokenPipe,
libc::EROFS => ReadOnlyFilesystem,
libc::ESPIPE => NotSeekable,
libc::ESTALE => StaleNetworkFileHandle,
libc::ETIMEDOUT => TimedOut,
libc::ETXTBSY => ExecutableFileBusy,
libc::EXDEV => CrossesDevices,
libc::EINPROGRESS => InProgress,
libc::EOPNOTSUPP => Unsupported,
libc::EACCES | libc::EPERM => PermissionDenied,
libc::EWOULDBLOCK => WouldBlock,
_ => Uncategorized,
}
}
pub fn abort_internal() -> ! {
unsafe { libc::abort() }
}
#[inline]
#[cfg(target_env = "p1")]
pub(crate) fn err2io(err: wasi::Errno) -> std_io::Error {
std_io::Error::from_raw_os_error(err.raw().into())
pub(crate) fn err2io(err: wasi::Errno) -> crate::io::Error {
crate::io::Error::from_raw_os_error(err.raw().into())
}

View file

@ -26,9 +26,9 @@ mod helpers;
// import conflict rules. If we glob export `helpers` and `common` together,
// then the compiler complains about conflicts.
pub(crate) use helpers::abort_internal;
#[cfg(target_env = "p1")]
pub(crate) use helpers::err2io;
pub(crate) use helpers::{abort_internal, decode_error_kind, is_interrupted};
#[cfg(not(target_env = "p1"))]
pub use os::IsMinusOne;
pub use os::{cvt, cvt_r};

View file

@ -6,7 +6,7 @@ use crate::os::wasi::prelude::*;
use crate::path::{self, PathBuf};
use crate::sys::helpers::run_path_with_cstr;
use crate::sys::unsupported;
use crate::{fmt, io, str};
use crate::{fmt, io};
// Add a few symbols not in upstream `libc` just yet.
pub mod libc {
@ -19,34 +19,6 @@ pub mod libc {
}
}
unsafe extern "C" {
#[thread_local]
#[link_name = "errno"]
static mut libc_errno: libc::c_int;
}
pub fn errno() -> i32 {
unsafe { libc_errno as i32 }
}
pub fn set_errno(val: i32) {
unsafe {
libc_errno = val;
}
}
pub fn error_string(errno: i32) -> String {
let mut buf = [0 as libc::c_char; 1024];
let p = buf.as_mut_ptr();
unsafe {
if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
panic!("strerror_r failure");
}
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
}
}
pub fn getcwd() -> io::Result<PathBuf> {
let mut buf = Vec::with_capacity(512);
loop {

View file

@ -60,84 +60,6 @@ pub unsafe fn cleanup() {
winsock::cleanup();
}
#[inline]
pub fn is_interrupted(_errno: i32) -> bool {
false
}
pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
use io::ErrorKind::*;
match errno as u32 {
c::ERROR_ACCESS_DENIED => return PermissionDenied,
c::ERROR_ALREADY_EXISTS => return AlreadyExists,
c::ERROR_FILE_EXISTS => return AlreadyExists,
c::ERROR_BROKEN_PIPE => return BrokenPipe,
c::ERROR_FILE_NOT_FOUND
| c::ERROR_PATH_NOT_FOUND
| c::ERROR_INVALID_DRIVE
| c::ERROR_BAD_NETPATH
| c::ERROR_BAD_NET_NAME => return NotFound,
c::ERROR_NO_DATA => return BrokenPipe,
c::ERROR_INVALID_NAME | c::ERROR_BAD_PATHNAME => return InvalidFilename,
c::ERROR_INVALID_PARAMETER => return InvalidInput,
c::ERROR_NOT_ENOUGH_MEMORY | c::ERROR_OUTOFMEMORY => return OutOfMemory,
c::ERROR_SEM_TIMEOUT
| c::WAIT_TIMEOUT
| c::ERROR_DRIVER_CANCEL_TIMEOUT
| c::ERROR_OPERATION_ABORTED
| c::ERROR_SERVICE_REQUEST_TIMEOUT
| c::ERROR_COUNTER_TIMEOUT
| c::ERROR_TIMEOUT
| c::ERROR_RESOURCE_CALL_TIMED_OUT
| c::ERROR_CTX_MODEM_RESPONSE_TIMEOUT
| c::ERROR_CTX_CLIENT_QUERY_TIMEOUT
| c::FRS_ERR_SYSVOL_POPULATE_TIMEOUT
| c::ERROR_DS_TIMELIMIT_EXCEEDED
| c::DNS_ERROR_RECORD_TIMED_OUT
| c::ERROR_IPSEC_IKE_TIMED_OUT
| c::ERROR_RUNLEVEL_SWITCH_TIMEOUT
| c::ERROR_RUNLEVEL_SWITCH_AGENT_TIMEOUT => return TimedOut,
c::ERROR_CALL_NOT_IMPLEMENTED => return Unsupported,
c::ERROR_HOST_UNREACHABLE => return HostUnreachable,
c::ERROR_NETWORK_UNREACHABLE => return NetworkUnreachable,
c::ERROR_DIRECTORY => return NotADirectory,
c::ERROR_DIRECTORY_NOT_SUPPORTED => return IsADirectory,
c::ERROR_DIR_NOT_EMPTY => return DirectoryNotEmpty,
c::ERROR_WRITE_PROTECT => return ReadOnlyFilesystem,
c::ERROR_DISK_FULL | c::ERROR_HANDLE_DISK_FULL => return StorageFull,
c::ERROR_SEEK_ON_DEVICE => return NotSeekable,
c::ERROR_DISK_QUOTA_EXCEEDED => return QuotaExceeded,
c::ERROR_FILE_TOO_LARGE => return FileTooLarge,
c::ERROR_BUSY => return ResourceBusy,
c::ERROR_POSSIBLE_DEADLOCK => return Deadlock,
c::ERROR_NOT_SAME_DEVICE => return CrossesDevices,
c::ERROR_TOO_MANY_LINKS => return TooManyLinks,
c::ERROR_FILENAME_EXCED_RANGE => return InvalidFilename,
c::ERROR_CANT_RESOLVE_FILENAME => return FilesystemLoop,
_ => {}
}
match errno {
c::WSAEACCES => PermissionDenied,
c::WSAEADDRINUSE => AddrInUse,
c::WSAEADDRNOTAVAIL => AddrNotAvailable,
c::WSAECONNABORTED => ConnectionAborted,
c::WSAECONNREFUSED => ConnectionRefused,
c::WSAECONNRESET => ConnectionReset,
c::WSAEINVAL => InvalidInput,
c::WSAENOTCONN => NotConnected,
c::WSAEWOULDBLOCK => WouldBlock,
c::WSAETIMEDOUT => TimedOut,
c::WSAEHOSTUNREACH => HostUnreachable,
c::WSAENETDOWN => NetworkDown,
c::WSAENETUNREACH => NetworkUnreachable,
c::WSAEDQUOT => QuotaExceeded,
_ => Uncategorized,
}
}
pub fn unrolled_find_u16s(needle: u16, haystack: &[u16]) -> Option<usize> {
let ptr = haystack.as_ptr();
let mut start = haystack;

View file

@ -15,66 +15,6 @@ use crate::path::{self, PathBuf};
use crate::sys::pal::{c, cvt};
use crate::{fmt, io, ptr};
pub fn errno() -> i32 {
api::get_last_error().code as i32
}
/// Gets a detailed string description for the given error number.
pub fn error_string(mut errnum: i32) -> String {
let mut buf = [0 as c::WCHAR; 2048];
unsafe {
let mut module = ptr::null_mut();
let mut flags = 0;
// NTSTATUS errors may be encoded as HRESULT, which may returned from
// GetLastError. For more information about Windows error codes, see
// `[MS-ERREF]`: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/0642cb2f-2075-4469-918c-4441e69c548a
if (errnum & c::FACILITY_NT_BIT as i32) != 0 {
// format according to https://support.microsoft.com/en-us/help/259693
const NTDLL_DLL: &[u16] = &[
'N' as _, 'T' as _, 'D' as _, 'L' as _, 'L' as _, '.' as _, 'D' as _, 'L' as _,
'L' as _, 0,
];
module = c::GetModuleHandleW(NTDLL_DLL.as_ptr());
if !module.is_null() {
errnum ^= c::FACILITY_NT_BIT as i32;
flags = c::FORMAT_MESSAGE_FROM_HMODULE;
}
}
let res = c::FormatMessageW(
flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS,
module,
errnum as u32,
0,
buf.as_mut_ptr(),
buf.len() as u32,
ptr::null(),
) as usize;
if res == 0 {
// Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId,
let fm_err = errno();
return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})");
}
match String::from_utf16(&buf[..res]) {
Ok(mut msg) => {
// Trim trailing CRLF inserted by FormatMessageW
let len = msg.trim_end().len();
msg.truncate(len);
msg
}
Err(..) => format!(
"OS Error {} (FormatMessageW() returned \
invalid UTF-16)",
errnum
),
}
}
}
pub struct SplitPaths<'a> {
data: EncodeWide<'a>,
must_yield: bool,

View file

@ -1,7 +1,6 @@
use super::unsupported;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
use crate::os::xous::ffi::Error as XousError;
use crate::path::{self, PathBuf};
use crate::sync::atomic::{Atomic, AtomicPtr, Ordering};
use crate::{fmt, io};
@ -63,14 +62,6 @@ mod c_compat {
}
}
pub fn errno() -> i32 {
0
}
pub fn error_string(errno: i32) -> String {
Into::<XousError>::into(errno).to_string()
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}

View file

@ -33,14 +33,6 @@ pub fn unsupported_err() -> std_io::Error {
std_io::Error::UNSUPPORTED_PLATFORM
}
pub fn is_interrupted(_code: i32) -> bool {
false
}
pub fn decode_error_kind(_code: i32) -> crate::io::ErrorKind {
crate::io::ErrorKind::Uncategorized
}
pub fn abort_internal() -> ! {
core::intrinsics::abort();
}

View file

@ -4,14 +4,6 @@ use crate::marker::PhantomData;
use crate::path::{self, PathBuf};
use crate::{fmt, io};
pub fn errno() -> i32 {
0
}
pub fn error_string(_errno: i32) -> String {
"operation successful".to_string()
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
}

View file

@ -8,8 +8,8 @@ use crate::num::{NonZero, NonZeroI32};
use crate::path::Path;
use crate::process::StdioPipes;
use crate::sys::fs::File;
use crate::sys::io::error_string;
use crate::sys::pal::helpers;
use crate::sys::pal::os::error_string;
use crate::sys::unsupported;
use crate::{fmt, io};

View file

@ -61,7 +61,7 @@ cfg_select! {
let bit = (signum - 1) as usize;
if set.is_null() || bit >= (8 * size_of::<sigset_t>()) {
crate::sys::pal::os::set_errno(libc::EINVAL);
crate::sys::io::set_errno(libc::EINVAL);
return -1;
}
let raw = slice::from_raw_parts_mut(

View file

@ -194,7 +194,7 @@ impl Command {
// See also https://www.qnx.com/developers/docs/7.1/#com.qnx.doc.neutrino.lib_ref/topic/f/fork.html
#[cfg(target_os = "nto")]
unsafe fn do_fork(&mut self) -> Result<pid_t, io::Error> {
use crate::sys::os::errno;
use crate::sys::io::errno;
let mut delay = MIN_FORKSPAWN_SLEEP;

View file

@ -66,7 +66,7 @@ use crate::os::fd::AsRawFd;
use crate::sync::OnceLock;
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sync::atomic::{Atomic, AtomicBool};
use crate::sys::pal::os::errno;
use crate::sys::io::errno;
use crate::sys::pal::weak::syscall;
fn getrandom(mut bytes: &mut [u8], insecure: bool) {

View file

@ -1,6 +1,6 @@
use crate::cell::UnsafeCell;
use crate::sys::c;
use crate::sys::sync::{Mutex, mutex};
use crate::sys::{c, os};
use crate::time::Duration;
pub struct Condvar {
@ -30,7 +30,7 @@ impl Condvar {
0,
);
if r == 0 {
debug_assert_eq!(os::errno() as usize, c::ERROR_TIMEOUT as usize);
debug_assert_eq!(crate::sys::io::errno() as usize, c::ERROR_TIMEOUT as usize);
false
} else {
true

View file

@ -14,10 +14,9 @@ use crate::num::NonZero;
use crate::sys::weak::dlsym;
#[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto",))]
use crate::sys::weak::weak;
use crate::sys::{os, stack_overflow};
use crate::thread::ThreadInit;
use crate::time::Duration;
use crate::{cmp, io, ptr};
use crate::{cmp, io, ptr, sys};
#[cfg(not(any(
target_os = "l4re",
target_os = "vxworks",
@ -77,7 +76,7 @@ impl Thread {
// multiple of the system page size. Because it's definitely
// >= PTHREAD_STACK_MIN, it must be an alignment issue.
// Round up to the nearest page and try again.
let page_size = os::page_size();
let page_size = sys::os::page_size();
let stack_size =
(stack_size + page_size - 1) & (-(page_size as isize - 1) as usize - 1);
@ -114,7 +113,7 @@ impl Thread {
// Now that the thread information is set, set up our stack
// overflow handler.
let _handler = stack_overflow::Handler::new();
let _handler = sys::stack_overflow::Handler::new();
rust_start();
}
@ -536,7 +535,7 @@ pub fn sleep(dur: Duration) {
secs -= ts.tv_sec as u64;
let ts_ptr = &raw mut ts;
if libc::nanosleep(ts_ptr, ts_ptr) == -1 {
assert_eq!(os::errno(), libc::EINTR);
assert_eq!(sys::io::errno(), libc::EINTR);
secs += ts.tv_sec as u64;
nsecs = ts.tv_nsec;
} else {

View file

@ -1,4 +1,4 @@
fn main() {
let _ = std::sys::os::errno();
let _ = std::sys::io::errno();
//~^ERROR module `sys` is private
}

View file

@ -1,7 +1,7 @@
error[E0603]: module `sys` is private
--> $DIR/stability-in-private-module.rs:2:18
|
LL | let _ = std::sys::os::errno();
LL | let _ = std::sys::io::errno();
| ^^^ ----- function `errno` is not publicly re-exported
| |
| private module