Commit | Line | Data |
---|---|---|
247b365d WAF |
1 | // SPDX-License-Identifier: GPL-2.0 |
2 | ||
3 | //! Kernel errors. | |
4 | //! | |
5 | //! C header: [`include/uapi/asm-generic/errno-base.h`](../../../include/uapi/asm-generic/errno-base.h) | |
6 | ||
76e2c2d9 WAF |
7 | use alloc::{ |
8 | alloc::{AllocError, LayoutError}, | |
9 | collections::TryReserveError, | |
10 | }; | |
11 | ||
12 | use core::convert::From; | |
13 | use core::num::TryFromIntError; | |
14 | use core::str::Utf8Error; | |
247b365d WAF |
15 | |
16 | /// Contains the C-compatible error codes. | |
17 | pub mod code { | |
4b0c68bd FB |
18 | macro_rules! declare_err { |
19 | ($err:tt $(,)? $($doc:expr),+) => { | |
20 | $( | |
21 | #[doc = $doc] | |
22 | )* | |
23 | pub const $err: super::Error = super::Error(-(crate::bindings::$err as i32)); | |
24 | }; | |
25 | } | |
26 | ||
266def2a VG |
27 | declare_err!(EPERM, "Operation not permitted."); |
28 | declare_err!(ENOENT, "No such file or directory."); | |
29 | declare_err!(ESRCH, "No such process."); | |
30 | declare_err!(EINTR, "Interrupted system call."); | |
31 | declare_err!(EIO, "I/O error."); | |
32 | declare_err!(ENXIO, "No such device or address."); | |
33 | declare_err!(E2BIG, "Argument list too long."); | |
34 | declare_err!(ENOEXEC, "Exec format error."); | |
35 | declare_err!(EBADF, "Bad file number."); | |
36 | declare_err!(ECHILD, "Exec format error."); | |
37 | declare_err!(EAGAIN, "Try again."); | |
4b0c68bd | 38 | declare_err!(ENOMEM, "Out of memory."); |
266def2a VG |
39 | declare_err!(EACCES, "Permission denied."); |
40 | declare_err!(EFAULT, "Bad address."); | |
41 | declare_err!(ENOTBLK, "Block device required."); | |
42 | declare_err!(EBUSY, "Device or resource busy."); | |
43 | declare_err!(EEXIST, "File exists."); | |
44 | declare_err!(EXDEV, "Cross-device link."); | |
45 | declare_err!(ENODEV, "No such device."); | |
46 | declare_err!(ENOTDIR, "Not a directory."); | |
47 | declare_err!(EISDIR, "Is a directory."); | |
48 | declare_err!(EINVAL, "Invalid argument."); | |
49 | declare_err!(ENFILE, "File table overflow."); | |
50 | declare_err!(EMFILE, "Too many open files."); | |
51 | declare_err!(ENOTTY, "Not a typewriter."); | |
52 | declare_err!(ETXTBSY, "Text file busy."); | |
53 | declare_err!(EFBIG, "File too large."); | |
54 | declare_err!(ENOSPC, "No space left on device."); | |
55 | declare_err!(ESPIPE, "Illegal seek."); | |
56 | declare_err!(EROFS, "Read-only file system."); | |
57 | declare_err!(EMLINK, "Too many links."); | |
58 | declare_err!(EPIPE, "Broken pipe."); | |
59 | declare_err!(EDOM, "Math argument out of domain of func."); | |
60 | declare_err!(ERANGE, "Math result not representable."); | |
247b365d WAF |
61 | } |
62 | ||
63 | /// Generic integer kernel error. | |
64 | /// | |
65 | /// The kernel defines a set of integer generic error codes based on C and | |
66 | /// POSIX ones. These codes may have a more specific meaning in some contexts. | |
67 | /// | |
68 | /// # Invariants | |
69 | /// | |
70 | /// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`). | |
71 | #[derive(Clone, Copy, PartialEq, Eq)] | |
72 | pub struct Error(core::ffi::c_int); | |
73 | ||
74 | impl Error { | |
75 | /// Returns the kernel error code. | |
76 | pub fn to_kernel_errno(self) -> core::ffi::c_int { | |
77 | self.0 | |
78 | } | |
79 | } | |
80 | ||
76e2c2d9 WAF |
81 | impl From<AllocError> for Error { |
82 | fn from(_: AllocError) -> Error { | |
83 | code::ENOMEM | |
84 | } | |
85 | } | |
86 | ||
87 | impl From<TryFromIntError> for Error { | |
88 | fn from(_: TryFromIntError) -> Error { | |
89 | code::EINVAL | |
90 | } | |
91 | } | |
92 | ||
93 | impl From<Utf8Error> for Error { | |
94 | fn from(_: Utf8Error) -> Error { | |
95 | code::EINVAL | |
96 | } | |
97 | } | |
98 | ||
247b365d WAF |
99 | impl From<TryReserveError> for Error { |
100 | fn from(_: TryReserveError) -> Error { | |
101 | code::ENOMEM | |
102 | } | |
103 | } | |
104 | ||
76e2c2d9 WAF |
105 | impl From<LayoutError> for Error { |
106 | fn from(_: LayoutError) -> Error { | |
107 | code::ENOMEM | |
108 | } | |
109 | } | |
110 | ||
111 | impl From<core::fmt::Error> for Error { | |
112 | fn from(_: core::fmt::Error) -> Error { | |
113 | code::EINVAL | |
114 | } | |
115 | } | |
116 | ||
117 | impl From<core::convert::Infallible> for Error { | |
118 | fn from(e: core::convert::Infallible) -> Error { | |
119 | match e {} | |
120 | } | |
121 | } | |
122 | ||
247b365d WAF |
123 | /// A [`Result`] with an [`Error`] error type. |
124 | /// | |
125 | /// To be used as the return type for functions that may fail. | |
126 | /// | |
127 | /// # Error codes in C and Rust | |
128 | /// | |
129 | /// In C, it is common that functions indicate success or failure through | |
130 | /// their return value; modifying or returning extra data through non-`const` | |
131 | /// pointer parameters. In particular, in the kernel, functions that may fail | |
132 | /// typically return an `int` that represents a generic error code. We model | |
133 | /// those as [`Error`]. | |
134 | /// | |
135 | /// In Rust, it is idiomatic to model functions that may fail as returning | |
136 | /// a [`Result`]. Since in the kernel many functions return an error code, | |
137 | /// [`Result`] is a type alias for a [`core::result::Result`] that uses | |
138 | /// [`Error`] as its error type. | |
139 | /// | |
140 | /// Note that even if a function does not return anything when it succeeds, | |
141 | /// it should still be modeled as returning a `Result` rather than | |
142 | /// just an [`Error`]. | |
143 | pub type Result<T = ()> = core::result::Result<T, Error>; |