[crates] Seperate error module into errno crate

This commit is contained in:
ClawSeven 2024-02-29 11:19:56 +08:00 committed by volcano
parent 4027258ec5
commit 5b704984e3
13 changed files with 704 additions and 229 deletions

@ -25,6 +25,7 @@ rcore-fs-devfs = { path = "../../deps/sefs/rcore-fs-devfs" }
resolv-conf = { path = "../../deps/resolv-conf" }
serde = { path = "../../deps/serde-sgx/serde", features = ["derive"] }
serde_json = { path = "../../deps/serde-json-sgx" }
errno = { path = "./crates/errno", features = ["occlum"] }
memoffset = "0.6.1"
scroll = { version = "0.11.0", default-features = false }
itertools = { version = "0.10.0", default-features = false, features = ["use_alloc"] }

265
src/libos/crates/errno/Cargo.lock generated Normal file

@ -0,0 +1,265 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "cc"
version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [
"libc",
]
[[package]]
name = "errno"
version = "0.1.0"
dependencies = [
"log",
"rcore-fs",
"serde_json",
"sgx_tstd 1.1.6",
]
[[package]]
name = "hashbrown_tstd"
version = "0.12.0"
[[package]]
name = "itoa"
version = "0.4.5"
dependencies = [
"sgx_tstd 1.1.0",
]
[[package]]
name = "libc"
version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]]
name = "log"
version = "0.4.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]]
name = "rcore-fs"
version = "0.1.0"
dependencies = [
"bitflags",
"spin",
]
[[package]]
name = "ryu"
version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]]
name = "serde"
version = "1.0.104"
dependencies = [
"sgx_tstd 1.1.0",
]
[[package]]
name = "serde_json"
version = "1.0.40"
dependencies = [
"itoa",
"ryu",
"serde",
"sgx_tstd 1.1.0",
]
[[package]]
name = "sgx_alloc"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
[[package]]
name = "sgx_alloc"
version = "1.1.6"
[[package]]
name = "sgx_backtrace_sys"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"cc",
"sgx_build_helper 0.1.0",
"sgx_libc 1.1.0",
]
[[package]]
name = "sgx_backtrace_sys"
version = "1.1.6"
dependencies = [
"cc",
"sgx_build_helper 1.1.6",
"sgx_libc 1.1.6",
]
[[package]]
name = "sgx_build_helper"
version = "0.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
[[package]]
name = "sgx_build_helper"
version = "1.1.6"
[[package]]
name = "sgx_demangle"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
[[package]]
name = "sgx_demangle"
version = "1.1.6"
[[package]]
name = "sgx_libc"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_types 1.1.0",
]
[[package]]
name = "sgx_libc"
version = "1.1.6"
dependencies = [
"sgx_types 1.1.6",
]
[[package]]
name = "sgx_tcrypto"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_types 1.1.0",
]
[[package]]
name = "sgx_tprotected_fs"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_trts 1.1.0",
"sgx_types 1.1.0",
]
[[package]]
name = "sgx_tprotected_fs"
version = "1.1.6"
dependencies = [
"sgx_trts 1.1.6",
"sgx_types 1.1.6",
]
[[package]]
name = "sgx_trts"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_libc 1.1.0",
"sgx_types 1.1.0",
]
[[package]]
name = "sgx_trts"
version = "1.1.6"
dependencies = [
"sgx_libc 1.1.6",
"sgx_types 1.1.6",
]
[[package]]
name = "sgx_tse"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_types 1.1.0",
]
[[package]]
name = "sgx_tseal"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_tcrypto",
"sgx_trts 1.1.0",
"sgx_tse",
"sgx_types 1.1.0",
]
[[package]]
name = "sgx_tstd"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_alloc 1.1.0",
"sgx_backtrace_sys 1.1.0",
"sgx_demangle 1.1.0",
"sgx_libc 1.1.0",
"sgx_tprotected_fs 1.1.0",
"sgx_trts 1.1.0",
"sgx_tseal",
"sgx_types 1.1.0",
"sgx_unwind 0.1.0",
]
[[package]]
name = "sgx_tstd"
version = "1.1.6"
dependencies = [
"hashbrown_tstd",
"sgx_alloc 1.1.6",
"sgx_backtrace_sys 1.1.6",
"sgx_demangle 1.1.6",
"sgx_libc 1.1.6",
"sgx_tprotected_fs 1.1.6",
"sgx_trts 1.1.6",
"sgx_types 1.1.6",
"sgx_unwind 1.1.6",
]
[[package]]
name = "sgx_types"
version = "1.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
[[package]]
name = "sgx_types"
version = "1.1.6"
[[package]]
name = "sgx_unwind"
version = "0.1.0"
source = "git+https://github.com/apache/teaclave-sgx-sdk.git?rev=v1.1.0#71a88b647bb76a16cbc5c3e29403e2afb67f82fd"
dependencies = [
"sgx_build_helper 0.1.0",
]
[[package]]
name = "sgx_unwind"
version = "1.1.6"
dependencies = [
"sgx_build_helper 1.1.6",
]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"

@ -0,0 +1,19 @@
[package]
name = "errno"
version = "0.1.0"
authors = ["Tate, Hongliang Tian <tate.thl@antgroup.com>"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = []
std = []
occlum = ["sgx", "serde_json", "rcore-fs"]
sgx = ["sgx_tstd"]
[dependencies]
log = "0.4"
serde_json = { path = "../../../../deps/serde-json-sgx", optional = true }
sgx_tstd = { path = "../../../../deps/rust-sgx-sdk/sgx_tstd", optional = true }
rcore-fs = { path = "../../../../deps/sefs/rcore-fs", optional = true }

@ -1,4 +1,9 @@
use super::*;
use alloc::boxed::Box;
use alloc::string::String;
use alloc::vec::Vec;
use core::fmt;
use super::Error;
#[derive(Debug, Clone)]
pub struct ErrorBacktrace<'a> {
@ -15,7 +20,7 @@ impl<'a> ErrorBacktrace<'a> {
impl<'a> fmt::Display for ErrorBacktrace<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let error_strings: Vec<String> = self.clone().map(|e| e.to_string()).collect();
let error_strings: Vec<String> = self.clone().map(|e| alloc::format!("{}", e)).collect();
let error_backtrace = error_strings.join("\n Caused by ");
write!(f, "{}", error_backtrace)
}
@ -48,18 +53,3 @@ impl Error {
ErrorBacktrace::new(self)
}
}
pub trait ResultExt<T> {
fn cause_err<F>(self, f: F) -> Result<T>
where
F: FnOnce(&Error) -> Error;
}
impl<T> ResultExt<T> for Result<T> {
fn cause_err<F>(self, f: F) -> Result<T>
where
F: FnOnce(&Error) -> Error,
{
self.map_err(|old_e| old_e.cause_err(f))
}
}

@ -1,4 +1,4 @@
use super::*;
use core::fmt;
/// POSIX errno
#[derive(Clone, Copy, Debug, PartialEq)]
@ -46,7 +46,6 @@ pub enum Errno {
ENOSYS = 38,
ENOTEMPTY = 39,
ELOOP = 40,
EWOULDBLOCK = 41,
ENOMSG = 42,
EIDRM = 43,
ECHRNG = 44,
@ -145,6 +144,9 @@ const ERRNO_MIN: u32 = Errno::EPERM as u32;
const ERRNO_MAX: u32 = Errno::EHWPOISON as u32;
impl Errno {
// EWOULDBLOCK was used on BSD/Sun variants of Unix, and EAGAIN was the AT&T System V error code.
// Here we keep same with linux, define EWOULDBLOCK with EAGAIN.
pub const EWOULDBLOCK: Errno = Errno::EAGAIN;
pub(crate) fn as_str(&self) -> &'static str {
use self::Errno::*;
match *self {

@ -1,4 +1,7 @@
use super::*;
use alloc::boxed::Box;
use core::fmt;
use super::{Errno, ToErrno};
#[derive(Debug)]
pub struct Error {
@ -10,7 +13,7 @@ pub struct Error {
#[derive(Debug)]
enum Error__ {
Embedded((Errno, &'static str)),
Boxed(Box<dyn ToErrno + 'static>),
Boxed(Box<dyn ToErrno + Send + 'static>),
}
#[derive(Debug, Clone, Copy)]
@ -30,7 +33,7 @@ impl Error {
pub fn boxed<T>(inner: T, location: Option<ErrorLocation>) -> Error
where
T: ToErrno + 'static,
T: ToErrno + Send + 'static,
{
Error {
inner: Error__::Boxed(Box::new(inner)),
@ -64,23 +67,6 @@ impl ErrorLocation {
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
self.errno().as_str()
}
fn cause(&self) -> Option<&dyn std::error::Error> {
self.cause.as_ref().map(|e| e as &dyn std::error::Error)
}
/*
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause
.as_ref()
.map(|e| e as &(dyn std::error::Error + 'static))
}
*/
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.inner)?;
@ -105,3 +91,25 @@ impl fmt::Display for ErrorLocation {
write!(f, "[line = {}, file = {}]", self.line, self.file)
}
}
#[cfg(any(feature = "std", feature = "sgx", test, doctest))]
mod if_std {
use super::*;
impl std::error::Error for Error {
fn description(&self) -> &str {
self.errno().as_str()
}
fn cause(&self) -> Option<&dyn std::error::Error> {
self.cause.as_ref().map(|e| e as &dyn std::error::Error)
}
/*
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.cause
.as_ref()
.map(|e| e as &(dyn std::error::Error + 'static))
}
*/
}
}

@ -0,0 +1,204 @@
//! User-friendly error handling with build-in support for POSIX errno.
//!
//! This crate extends Rust's standard error handling with the abilities of
//! reporting error locations, providing backtrace information, and unifying
//! all types of errors with POSIX errno.
//!
//! # Motivation
//!
//! While the built-in error handling mechanism of Rust is undoubtedly superior
//! than that of a traditional system programming language (e.g., C/C++), it
//! is _not perfect_.
//!
//! First, trait `std::error::Error` does not provide any means to
//! record the location of the source code that triggers an error, leading to
//! a slow process of diagnosing errors or bugs.
//!
//! Second, while the `Error` trait (which has a `cause` method)
//! supports backtrace in theory, it is inconvenient---in practice---to implement
//! backtrace. This is because the users still need to manually write the concrete
//! implementation that stores the cause for every error struct.
//!
//! Third, one challenging aspect of error handling in Rust is
//! dealing with the various types of errors. The standard library
//! defines errors like `std::io::Error`, `std::fmt::Error`, `std::str::Utf8Error`, etc.
//! Not to mention the error types defined by third-party libraries.
//! To make it even worse, we, as OS writers, have to convert all these errors
//! into POSIX errno eventually.
//!
//! To cope with the issues above, this crate extends Rust's standard error
//! handling mechanism. Specifically, it aims at the following design goals:
//!
//! * **Fast diagnose** (e.g., reporting the backtrace and the code location of an error).
//! * **First-class POSIX errno** (e.g., every error has an errno).
//! * **Zero-overhead abstraction** (e.g., no heap allocation unless absolutely necesary).
//! * **Ergonomic grammar** (e.g., use macros to avoid writing code manually).
//! * **Compatibility with `no_std`**.
//!
//! # How to Use
//!
//! ## Basic Usage
//!
//! The simplest usage involves just one macro---`errno!`.
//! See the sample code below:
//! ```rust
//! use errno::prelude::*;
//!
//! fn return_err() -> Result<()> {
//! Err(errno!(EINVAL, "the root error"))
//! }
//!
//! # fn main() {
//! if let Err(e) = return_err() {
//! println!("{}", e);
//! }
//! # }
//! ```
//! which prints something like
//! ```text
//! EINVAL (#22, Invalid argument): the root error [line = 45, file = src/lib.rs]
//! ```
//! Note that the specific line and file of source code that generates the error
//! is printed. This facilitates diagnosing errors.
//!
//! ## Backtrace
//!
//! A more interesting usage is to print the backtrace of an error. To create
//! the chains of errors, `std::result::Result` is extended with a new method
//! named `cause_err`. If the result is `Ok`, the method does nothing; otherwise,
//! this method executes a user-given closure to output a new error whose cause
//! is the error contained in the result. The method consumes the current result
//! and generates a new result that contains the new error. The two errors are
//! chained. More calls to `cause_err` form deeper backtraces.
//!
//! See the sample code below:
//! ```rust
//! use errno::prelude::*;
//!
//! fn return_err() -> Result<()> {
//! Err(errno!(EINVAL, "the root error"))
//! }
//!
//! fn cause_err() -> Result<()> {
//! return_err()
//! .cause_err(|_e| errno!(EIO, "another error"))
//! }
//!
//! # fn main() {
//! if let Err(e) = cause_err() {
//! println!("{}", e.backtrace());
//! }
//! # }
//! ```
//! which prints something like
//! ```text
//! EIO (#5, I/O error): another error [line = 71, file = src/lib.rs]
//! Caused by EINVAL (#22, Invalid argument): the root error [line = 68, file = src/lib.rs]
//! ```
//!
#![feature(allocator_api)]
// Use no_std and alloc crate except when given std feature or during test.
#![cfg_attr(not(any(feature = "std", test, doctest)), no_std)]
extern crate alloc;
// Use Rust SGX SDK's std when given SGX feature.
#[cfg(feature = "sgx")]
extern crate sgx_tstd as std;
#[macro_use]
extern crate log;
mod backtrace;
mod errno;
mod error;
pub mod prelude;
mod result;
mod to_errno;
pub use self::backtrace::ErrorBacktrace;
pub use self::errno::*;
pub use self::errno::Errno::*;
pub use self::error::{Error, ErrorLocation};
pub use self::result::{Result, ResultExt};
pub use self::to_errno::ToErrno;
#[macro_export]
macro_rules! errno {
($errno_expr: expr, $error_msg: expr) => {{
let inner_error = {
let errno: Errno = $errno_expr;
let msg: &'static str = $error_msg;
(errno, msg)
};
let error =
$crate::Error::embedded(inner_error, Some($crate::ErrorLocation::new(file!(), line!())));
error
}};
($error_expr: expr) => {{
let inner_error = $error_expr;
let error = $crate::Error::boxed(inner_error, Some($crate::ErrorLocation::new(file!(), line!())));
error
}};
}
#[macro_export]
macro_rules! return_errno {
($errno_expr: expr, $error_msg: expr) => {{
return Err(errno!($errno_expr, $error_msg));
}};
($error_expr: expr) => {{
return Err(errno!($error_expr));
}};
}
// return Err(errno) if libc return -1
#[macro_export]
macro_rules! try_libc {
($ret: expr) => {{
let ret = unsafe { $ret };
if ret < 0 {
let errno = unsafe { libc::errno() };
return_errno!(Errno::from(errno as u32), "libc error");
}
ret
}};
}
// return Err(errno) if libc return -1
// raise SIGPIPE if errno == EPIPE
#[macro_export]
macro_rules! try_libc_may_epipe {
($ret: expr) => {{
let ret = unsafe { $ret };
if ret < 0 {
let errno = unsafe { libc::errno() };
if errno == Errno::EPIPE as i32 {
crate::signal::do_tkill(current!().tid(), crate::signal::SIGPIPE.as_u8() as i32);
}
return_errno!(Errno::from(errno as u32), "libc error");
}
ret
}};
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
#[test]
fn convert_std_io_error() -> Result<()> {
use std::io::{BufWriter, Write};
let mut buf_writer = BufWriter::new(Vec::<u8>::new());
// std::io::Error can be converted crate::Error implicitly
buf_writer.write("foo".as_bytes())?;
Ok(())
}
#[test]
fn convert_std_ffi_nul_error() -> Result<()> {
use std::ffi::CString;
// std::ffi::NulError can be converted crate::Error implicitly
let _ = CString::new(b"foo".to_vec())?;
Ok(())
}
}

@ -0,0 +1,3 @@
pub use crate::{
errno, return_errno, Errno, Errno::*, Error, ErrorLocation, Result, ResultExt, ToErrno,
};

@ -0,0 +1,34 @@
use super::{Errno, Error};
pub type Result<T> = core::result::Result<T, Error>;
/// Extending `Result` with extra functionalities.
pub trait ResultExt<T> {
fn cause_err<F>(self, f: F) -> Result<T>
where
F: FnOnce(&Error) -> Error;
fn errno(&self) -> Option<Errno>;
fn has_errno(&self, errno: Errno) -> bool;
}
impl<T> ResultExt<T> for Result<T> {
fn cause_err<F>(self, f: F) -> Result<T>
where
F: FnOnce(&Error) -> Error,
{
self.map_err(|old_e| old_e.cause_err(f))
}
fn errno(&self) -> Option<Errno> {
match self {
Ok(_) => None,
Err(e) => Some(e.errno()),
}
}
fn has_errno(&self, errno: Errno) -> bool {
self.errno() == Some(errno)
}
}

@ -0,0 +1,138 @@
use core::fmt;
use super::{Errno, Error};
pub trait ToErrno: fmt::Display + fmt::Debug {
fn errno(&self) -> Errno;
}
impl<T> From<T> for Error
where
T: ToErrno + Send + 'static,
{
fn from(t: T) -> Error {
Error::boxed(t, None)
}
}
impl ToErrno for Errno {
fn errno(&self) -> Errno {
*self
}
}
impl ToErrno for core::alloc::AllocError {
fn errno(&self) -> Errno {
Errno::ENOMEM
}
}
impl ToErrno for core::alloc::LayoutError {
fn errno(&self) -> Errno {
Errno::EINVAL
}
}
impl ToErrno for core::num::ParseIntError {
fn errno(&self) -> Errno {
Errno::EINVAL
}
}
#[cfg(any(feature = "std", feature = "sgx", test, doctest))]
mod if_std {
use super::*;
impl From<std::io::ErrorKind> for Errno {
fn from(kind: std::io::ErrorKind) -> Errno {
use std::io::ErrorKind::*;
use Errno::*;
match kind {
NotFound => ENOENT,
PermissionDenied => EPERM,
ConnectionRefused => ECONNREFUSED,
ConnectionReset => ECONNRESET,
ConnectionAborted => ECONNABORTED,
NotConnected => ENOTCONN,
AddrInUse => EADDRINUSE,
AddrNotAvailable => EADDRNOTAVAIL,
BrokenPipe => EPIPE,
AlreadyExists => EEXIST,
WouldBlock => Errno::EWOULDBLOCK,
InvalidInput => EINVAL,
InvalidData => EBADMSG, /* TODO: correct? */
TimedOut => ETIMEDOUT,
Interrupted => EINTR,
WriteZero => EINVAL,
UnexpectedEof => EIO,
Other => EIO,
_ => EIO,
}
}
}
impl ToErrno for std::io::Error {
fn errno(&self) -> Errno {
Errno::from(self.kind())
}
}
impl ToErrno for std::ffi::NulError {
fn errno(&self) -> Errno {
Errno::EINVAL
}
}
}
#[cfg(feature = "occlum")]
mod if_occlum {
use rcore_fs::dev::DevError;
use rcore_fs::vfs::FsError;
use super::*;
impl ToErrno for serde_json::Error {
fn errno(&self) -> Errno {
Errno::EINVAL
}
}
impl ToErrno for FsError {
fn errno(&self) -> Errno {
use Errno::*;
match *self {
FsError::NotSupported => ENOSYS,
FsError::NotFile => EISDIR,
FsError::IsDir => EISDIR,
FsError::NotDir => ENOTDIR,
FsError::EntryNotFound => ENOENT,
FsError::EntryExist => EEXIST,
FsError::NotSameFs => EXDEV,
FsError::InvalidParam => EINVAL,
FsError::NoDeviceSpace => ENOMEM,
FsError::DirRemoved => ENOENT,
FsError::DirNotEmpty => ENOTEMPTY,
FsError::WrongFs => EINVAL,
FsError::DeviceError(_err) => EIO,
FsError::SymLoop => ELOOP,
FsError::NoDevice => ENXIO,
FsError::IOCTLError => EINVAL,
FsError::Again => EAGAIN,
FsError::Busy => EBUSY,
FsError::WrProtected => EROFS,
FsError::NoIntegrity => EIO,
FsError::PermError => EPERM,
FsError::NameTooLong => ENAMETOOLONG,
FsError::FileTooBig => EFBIG,
FsError::OpNotSupported => EOPNOTSUPP,
FsError::NotMountPoint => EINVAL,
}
}
}
impl From<Error> for DevError {
fn from(e: Error) -> Self {
DevError(e.errno() as i32)
}
}
}

@ -1,69 +1,3 @@
use super::*;
use std::fmt;
mod backtrace;
mod errno;
mod error;
mod to_errno;
pub use self::backtrace::{ErrorBacktrace, ResultExt};
pub use self::errno::Errno;
pub use self::errno::Errno::*;
pub use self::error::{Error, ErrorLocation};
pub use self::to_errno::ToErrno;
pub type Result<T> = std::result::Result<T, Error>;
macro_rules! errno {
($errno_expr: expr, $error_msg: expr) => {{
let inner_error = {
let errno: Errno = $errno_expr;
let msg: &'static str = $error_msg;
(errno, msg)
};
let error = Error::embedded(inner_error, Some(ErrorLocation::new(file!(), line!())));
error
}};
($error_expr: expr) => {{
let inner_error = $error_expr;
let error = Error::boxed(inner_error, Some(ErrorLocation::new(file!(), line!())));
error
}};
}
macro_rules! return_errno {
($errno_expr: expr, $error_msg: expr) => {{
return Err(errno!($errno_expr, $error_msg));
}};
($error_expr: expr) => {{
return Err(errno!($error_expr));
}};
}
// return Err(errno) if libc return -1
macro_rules! try_libc {
($ret: expr) => {{
let ret = unsafe { $ret };
if ret < 0 {
let errno = unsafe { libc::errno() };
return_errno!(Errno::from(errno as u32), "libc error");
}
ret
}};
}
// return Err(errno) if libc return -1
// raise SIGPIPE if errno == EPIPE
macro_rules! try_libc_may_epipe {
($ret: expr) => {{
let ret = unsafe { $ret };
if ret < 0 {
let errno = unsafe { libc::errno() };
if errno == Errno::EPIPE as i32 {
crate::signal::do_tkill(current!().tid(), crate::signal::SIGPIPE.as_u8() as i32);
}
return_errno!(Errno::from(errno as u32), "libc error");
}
ret
}};
}
pub use errno::{Errno::*, *};

@ -1,116 +0,0 @@
use super::*;
pub trait ToErrno: fmt::Display + fmt::Debug {
fn errno(&self) -> Errno;
}
impl ToErrno for Errno {
fn errno(&self) -> Errno {
*self
}
}
impl<T> From<T> for Error
where
T: ToErrno + 'static,
{
fn from(t: T) -> Error {
Error::boxed(t, None)
}
}
impl From<std::io::ErrorKind> for Errno {
fn from(kind: std::io::ErrorKind) -> Errno {
use std::io::ErrorKind::*;
match kind {
NotFound => ENOENT,
PermissionDenied => EPERM,
ConnectionRefused => ECONNREFUSED,
ConnectionReset => ECONNRESET,
ConnectionAborted => ECONNABORTED,
NotConnected => ENOTCONN,
AddrInUse => EADDRINUSE,
AddrNotAvailable => EADDRNOTAVAIL,
BrokenPipe => EPIPE,
AlreadyExists => EEXIST,
WouldBlock => EWOULDBLOCK,
InvalidInput => EINVAL,
InvalidData => EBADMSG, /* TODO: correct? */
TimedOut => ETIMEDOUT,
Interrupted => EINTR,
WriteZero => EINVAL,
UnexpectedEof => EIO,
Other => EIO,
_ => EIO,
}
}
}
impl ToErrno for std::io::Error {
fn errno(&self) -> Errno {
Errno::from(self.kind())
}
}
impl ToErrno for std::ffi::NulError {
fn errno(&self) -> Errno {
EINVAL
}
}
impl ToErrno for std::num::ParseIntError {
fn errno(&self) -> Errno {
EINVAL
}
}
impl ToErrno for serde_json::Error {
fn errno(&self) -> Errno {
EINVAL
}
}
impl ToErrno for rcore_fs::vfs::FsError {
fn errno(&self) -> Errno {
use rcore_fs::vfs::FsError;
match *self {
FsError::NotSupported => ENOSYS,
FsError::NotFile => EISDIR,
FsError::IsDir => EISDIR,
FsError::NotDir => ENOTDIR,
FsError::EntryNotFound => ENOENT,
FsError::EntryExist => EEXIST,
FsError::NotSameFs => EXDEV,
FsError::InvalidParam => EINVAL,
FsError::NoDeviceSpace => ENOMEM,
FsError::DirRemoved => ENOENT,
FsError::DirNotEmpty => ENOTEMPTY,
FsError::WrongFs => EINVAL,
FsError::DeviceError(err) => EIO,
FsError::SymLoop => ELOOP,
FsError::NoDevice => ENXIO,
FsError::IOCTLError => EINVAL,
FsError::Again => EAGAIN,
FsError::Busy => EBUSY,
FsError::WrProtected => EROFS,
FsError::NoIntegrity => EIO,
FsError::PermError => EPERM,
FsError::NameTooLong => ENAMETOOLONG,
FsError::FileTooBig => EFBIG,
FsError::OpNotSupported => EOPNOTSUPP,
FsError::NotMountPoint => EINVAL,
}
}
}
impl ToErrno for std::alloc::AllocError {
fn errno(&self) -> Errno {
ENOMEM
}
}
impl ToErrno for std::alloc::LayoutError {
fn errno(&self) -> Errno {
EINVAL
}
}

@ -321,10 +321,3 @@ impl File for LockedFile {
Ok(SefsMac(file.get_mac().unwrap()))
}
}
impl From<Error> for DevError {
fn from(e: Error) -> Self {
error!("SGX protected file I/O error: {}", e.backtrace());
DevError(e.errno() as i32)
}
}