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:
commit
95ea4c5699
55 changed files with 902 additions and 848 deletions
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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`,
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
15
library/std/src/sys/io/error/generic.rs
Normal file
15
library/std/src/sys/io/error/generic.rs
Normal 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()
|
||||
}
|
||||
35
library/std/src/sys/io/error/hermit.rs
Normal file
35
library/std/src/sys/io/error/hermit.rs
Normal 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()
|
||||
}
|
||||
55
library/std/src/sys/io/error/mod.rs
Normal file
55
library/std/src/sys/io/error/mod.rs
Normal 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,
|
||||
};
|
||||
67
library/std/src/sys/io/error/motor.rs
Normal file
67
library/std/src/sys/io/error/motor.rs
Normal 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)
|
||||
}
|
||||
65
library/std/src/sys/io/error/sgx.rs
Normal file
65
library/std/src/sys/io/error/sgx.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
19
library/std/src/sys/io/error/solid.rs
Normal file
19
library/std/src/sys/io/error/solid.rs
Normal 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}") }
|
||||
}
|
||||
64
library/std/src/sys/io/error/teeos.rs
Normal file
64
library/std/src/sys/io/error/teeos.rs
Normal 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()
|
||||
}
|
||||
104
library/std/src/sys/io/error/uefi.rs
Normal file
104
library/std/src/sys/io/error/uefi.rs
Normal 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()
|
||||
}
|
||||
186
library/std/src/sys/io/error/unix.rs
Normal file
186
library/std/src/sys/io/error/unix.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
80
library/std/src/sys/io/error/wasi.rs
Normal file
80
library/std/src/sys/io/error/wasi.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
140
library/std/src/sys/io/error/windows.rs
Normal file
140
library/std/src/sys/io/error/windows.rs
Normal 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
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
17
library/std/src/sys/io/error/xous.rs
Normal file
17
library/std/src/sys/io/error/xous.rs
Normal 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()
|
||||
}
|
||||
|
|
@ -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,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(()),
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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("/"))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() }
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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("/"))
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
fn main() {
|
||||
let _ = std::sys::os::errno();
|
||||
let _ = std::sys::io::errno();
|
||||
//~^ERROR module `sys` is private
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue