nydus_api/
error.rs

1// Copyright 2020 Ant Group. All rights reserved.
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use std::fmt::Debug;
6
7/// Display error messages with line number, file path and optional backtrace.
8pub fn make_error(
9    err: std::io::Error,
10    _raw: impl Debug,
11    _file: &str,
12    _line: u32,
13) -> std::io::Error {
14    #[cfg(feature = "error-backtrace")]
15    {
16        if let Ok(val) = std::env::var("RUST_BACKTRACE") {
17            if val.trim() != "0" {
18                error!("Stack:\n{:?}", backtrace::Backtrace::new());
19                error!("Error:\n\t{:?}\n\tat {}:{}", _raw, _file, _line);
20                return err;
21            }
22        }
23        error!(
24            "Error:\n\t{:?}\n\tat {}:{}\n\tnote: enable `RUST_BACKTRACE=1` env to display a backtrace",
25            _raw, _file, _line
26        );
27    }
28    err
29}
30
31/// Define error macro like `x!()` or `x!(err)`.
32/// Note: The `x!()` macro will convert any origin error (Os, Simple, Custom) to Custom error.
33macro_rules! define_error_macro {
34    ($fn:ident, $err:expr) => {
35        #[macro_export]
36        macro_rules! $fn {
37            () => {
38                std::io::Error::new($err.kind(), format!("{}: {}:{}", $err, file!(), line!()))
39            };
40            ($raw:expr) => {
41                $crate::error::make_error($err, &$raw, file!(), line!())
42            };
43        }
44    };
45}
46
47/// Define error macro for libc error codes
48macro_rules! define_libc_error_macro {
49    ($fn:ident, $code:ident) => {
50        define_error_macro!($fn, std::io::Error::from_raw_os_error(libc::$code));
51    };
52}
53
54// TODO: Add format string support
55// Add more libc error macro here if necessary
56define_libc_error_macro!(einval, EINVAL);
57define_libc_error_macro!(enoent, ENOENT);
58define_libc_error_macro!(ebadf, EBADF);
59define_libc_error_macro!(eacces, EACCES);
60define_libc_error_macro!(enotdir, ENOTDIR);
61define_libc_error_macro!(eisdir, EISDIR);
62define_libc_error_macro!(ealready, EALREADY);
63define_libc_error_macro!(enosys, ENOSYS);
64define_libc_error_macro!(epipe, EPIPE);
65define_libc_error_macro!(eio, EIO);
66
67/// Return EINVAL error with formatted error message.
68#[macro_export]
69macro_rules! bail_einval {
70    ($($arg:tt)*) => {{
71        return Err(einval!(format!($($arg)*)))
72    }}
73}
74
75/// Return EIO error with formatted error message.
76#[macro_export]
77macro_rules! bail_eio {
78    ($($arg:tt)*) => {{
79        return Err(eio!(format!($($arg)*)))
80    }}
81}
82
83// Add more custom error macro here if necessary
84define_error_macro!(last_error, std::io::Error::last_os_error());
85define_error_macro!(eother, std::io::Error::new(std::io::ErrorKind::Other, ""));
86
87#[cfg(test)]
88mod tests {
89    fn check_size(size: usize) -> std::io::Result<()> {
90        if size > 0x1000 {
91            return Err(einval!());
92        }
93
94        Ok(())
95    }
96
97    #[test]
98    fn test_einval() {
99        assert_eq!(
100            check_size(0x2000).unwrap_err().kind(),
101            std::io::Error::from_raw_os_error(libc::EINVAL).kind()
102        );
103    }
104}