Skip to main content

coreshift_core/
error.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/
4
5//! Shared low-level error types.
6//!
7//! [`CoreError`] is the crate-wide error for Linux and Android primitive
8//! operations. It intentionally stays small: low-level modules surface the
9//! syscall that failed and the raw OS error code, while callers decide how
10//! much policy or recovery to layer on top.
11
12use std::fmt;
13
14/// Error type for low-level system operations.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum CoreError {
17    /// A syscall or libc-style operation failed with the specified OS error.
18    Syscall {
19        /// The raw OS error code.
20        code: i32,
21        /// The name of the failed operation.
22        op: &'static str,
23    },
24}
25
26impl CoreError {
27    /// Construct a new syscall error.
28    pub fn sys(code: i32, op: &'static str) -> Self {
29        Self::Syscall { code, op }
30    }
31
32    /// Return the raw OS error code if applicable.
33    pub fn raw_os_error(&self) -> Option<i32> {
34        match self {
35            Self::Syscall { code, .. } => Some(*code),
36        }
37    }
38
39    /// Convert this low-level error into a standard I/O error.
40    pub fn to_io_error(&self) -> std::io::Error {
41        std::io::Error::from_raw_os_error(self.raw_os_error().unwrap_or(libc::EIO))
42    }
43}
44
45impl fmt::Display for CoreError {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        match self {
48            Self::Syscall { code, op } => write!(f, "{op} failed (code={code})"),
49        }
50    }
51}
52
53impl std::error::Error for CoreError {}
54
55#[inline(always)]
56pub(crate) fn syscall_ret(ret: i32, op: &'static str) -> Result<(), CoreError> {
57    if ret == -1 {
58        let code = std::io::Error::last_os_error().raw_os_error().unwrap_or(0);
59        Err(CoreError::sys(code, op))
60    } else {
61        Ok(())
62    }
63}
64
65#[inline(always)]
66pub(crate) fn posix_ret(ret: i32, op: &'static str) -> Result<(), CoreError> {
67    if ret != 0 {
68        Err(CoreError::sys(ret, op))
69    } else {
70        Ok(())
71    }
72}