From 5b704984e3d81cdecbcde703601dc884a0463a84 Mon Sep 17 00:00:00 2001 From: ClawSeven Date: Thu, 29 Feb 2024 11:19:56 +0800 Subject: [PATCH] [crates] Seperate error module into errno crate --- src/libos/Cargo.toml | 1 + src/libos/crates/errno/Cargo.lock | 265 ++++++++++++++++++ src/libos/crates/errno/Cargo.toml | 19 ++ .../error => crates/errno/src}/backtrace.rs | 24 +- .../{src/error => crates/errno/src}/errno.rs | 6 +- .../{src/error => crates/errno/src}/error.rs | 48 ++-- src/libos/crates/errno/src/lib.rs | 204 ++++++++++++++ src/libos/crates/errno/src/prelude.rs | 3 + src/libos/crates/errno/src/result.rs | 34 +++ src/libos/crates/errno/src/to_errno.rs | 138 +++++++++ src/libos/src/error/mod.rs | 68 +---- src/libos/src/error/to_errno.rs | 116 -------- src/libos/src/fs/sefs/sgx_storage.rs | 7 - 13 files changed, 704 insertions(+), 229 deletions(-) create mode 100644 src/libos/crates/errno/Cargo.lock create mode 100644 src/libos/crates/errno/Cargo.toml rename src/libos/{src/error => crates/errno/src}/backtrace.rs (74%) rename src/libos/{src/error => crates/errno/src}/errno.rs (95%) rename src/libos/{src/error => crates/errno/src}/error.rs (73%) create mode 100644 src/libos/crates/errno/src/lib.rs create mode 100644 src/libos/crates/errno/src/prelude.rs create mode 100644 src/libos/crates/errno/src/result.rs create mode 100644 src/libos/crates/errno/src/to_errno.rs delete mode 100644 src/libos/src/error/to_errno.rs diff --git a/src/libos/Cargo.toml b/src/libos/Cargo.toml index fa7954b2..c4488c42 100644 --- a/src/libos/Cargo.toml +++ b/src/libos/Cargo.toml @@ -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"] } diff --git a/src/libos/crates/errno/Cargo.lock b/src/libos/crates/errno/Cargo.lock new file mode 100644 index 00000000..95399643 --- /dev/null +++ b/src/libos/crates/errno/Cargo.lock @@ -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" diff --git a/src/libos/crates/errno/Cargo.toml b/src/libos/crates/errno/Cargo.toml new file mode 100644 index 00000000..490109c9 --- /dev/null +++ b/src/libos/crates/errno/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "errno" +version = "0.1.0" +authors = ["Tate, Hongliang Tian "] +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 } diff --git a/src/libos/src/error/backtrace.rs b/src/libos/crates/errno/src/backtrace.rs similarity index 74% rename from src/libos/src/error/backtrace.rs rename to src/libos/crates/errno/src/backtrace.rs index c45a3875..1c8310b6 100644 --- a/src/libos/src/error/backtrace.rs +++ b/src/libos/crates/errno/src/backtrace.rs @@ -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 = self.clone().map(|e| e.to_string()).collect(); + let error_strings: Vec = 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 { - fn cause_err(self, f: F) -> Result - where - F: FnOnce(&Error) -> Error; -} - -impl ResultExt for Result { - fn cause_err(self, f: F) -> Result - where - F: FnOnce(&Error) -> Error, - { - self.map_err(|old_e| old_e.cause_err(f)) - } -} diff --git a/src/libos/src/error/errno.rs b/src/libos/crates/errno/src/errno.rs similarity index 95% rename from src/libos/src/error/errno.rs rename to src/libos/crates/errno/src/errno.rs index f7879789..03985ed5 100644 --- a/src/libos/src/error/errno.rs +++ b/src/libos/crates/errno/src/errno.rs @@ -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 { diff --git a/src/libos/src/error/error.rs b/src/libos/crates/errno/src/error.rs similarity index 73% rename from src/libos/src/error/error.rs rename to src/libos/crates/errno/src/error.rs index e3d62bd7..06bbceba 100644 --- a/src/libos/src/error/error.rs +++ b/src/libos/crates/errno/src/error.rs @@ -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), + Boxed(Box), } #[derive(Debug, Clone, Copy)] @@ -30,7 +33,7 @@ impl Error { pub fn boxed(inner: T, location: Option) -> 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)) + } + */ + } +} diff --git a/src/libos/crates/errno/src/lib.rs b/src/libos/crates/errno/src/lib.rs new file mode 100644 index 00000000..16f4ef9c --- /dev/null +++ b/src/libos/crates/errno/src/lib.rs @@ -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::::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(()) + } +} diff --git a/src/libos/crates/errno/src/prelude.rs b/src/libos/crates/errno/src/prelude.rs new file mode 100644 index 00000000..418bfece --- /dev/null +++ b/src/libos/crates/errno/src/prelude.rs @@ -0,0 +1,3 @@ +pub use crate::{ + errno, return_errno, Errno, Errno::*, Error, ErrorLocation, Result, ResultExt, ToErrno, +}; diff --git a/src/libos/crates/errno/src/result.rs b/src/libos/crates/errno/src/result.rs new file mode 100644 index 00000000..b9607456 --- /dev/null +++ b/src/libos/crates/errno/src/result.rs @@ -0,0 +1,34 @@ +use super::{Errno, Error}; + +pub type Result = core::result::Result; + +/// Extending `Result` with extra functionalities. +pub trait ResultExt { + fn cause_err(self, f: F) -> Result + where + F: FnOnce(&Error) -> Error; + + fn errno(&self) -> Option; + + fn has_errno(&self, errno: Errno) -> bool; +} + +impl ResultExt for Result { + fn cause_err(self, f: F) -> Result + where + F: FnOnce(&Error) -> Error, + { + self.map_err(|old_e| old_e.cause_err(f)) + } + + fn errno(&self) -> Option { + match self { + Ok(_) => None, + Err(e) => Some(e.errno()), + } + } + + fn has_errno(&self, errno: Errno) -> bool { + self.errno() == Some(errno) + } +} diff --git a/src/libos/crates/errno/src/to_errno.rs b/src/libos/crates/errno/src/to_errno.rs new file mode 100644 index 00000000..784dc342 --- /dev/null +++ b/src/libos/crates/errno/src/to_errno.rs @@ -0,0 +1,138 @@ +use core::fmt; + +use super::{Errno, Error}; + +pub trait ToErrno: fmt::Display + fmt::Debug { + fn errno(&self) -> Errno; +} + +impl From 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 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 for DevError { + fn from(e: Error) -> Self { + DevError(e.errno() as i32) + } + } +} diff --git a/src/libos/src/error/mod.rs b/src/libos/src/error/mod.rs index cb0c08b0..5be585f1 100644 --- a/src/libos/src/error/mod.rs +++ b/src/libos/src/error/mod.rs @@ -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 = std::result::Result; - -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::*, *}; diff --git a/src/libos/src/error/to_errno.rs b/src/libos/src/error/to_errno.rs deleted file mode 100644 index 9b68eb1a..00000000 --- a/src/libos/src/error/to_errno.rs +++ /dev/null @@ -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 From for Error -where - T: ToErrno + 'static, -{ - fn from(t: T) -> Error { - Error::boxed(t, None) - } -} - -impl From 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 - } -} diff --git a/src/libos/src/fs/sefs/sgx_storage.rs b/src/libos/src/fs/sefs/sgx_storage.rs index 2e86d874..3f5e7511 100644 --- a/src/libos/src/fs/sefs/sgx_storage.rs +++ b/src/libos/src/fs/sefs/sgx_storage.rs @@ -321,10 +321,3 @@ impl File for LockedFile { Ok(SefsMac(file.get_mac().unwrap())) } } - -impl From for DevError { - fn from(e: Error) -> Self { - error!("SGX protected file I/O error: {}", e.backtrace()); - DevError(e.errno() as i32) - } -}