@@ -9,7 +9,7 @@ use crate::{bindings, c_types};
9
9
use alloc:: { alloc:: AllocError , collections:: TryReserveError } ;
10
10
use core:: convert:: From ;
11
11
use core:: fmt;
12
- use core:: num:: TryFromIntError ;
12
+ use core:: num:: { NonZeroI16 , TryFromIntError } ;
13
13
use core:: str:: { self , Utf8Error } ;
14
14
15
15
/// Generic integer kernel error.
@@ -21,44 +21,55 @@ use core::str::{self, Utf8Error};
21
21
///
22
22
/// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`).
23
23
#[ derive( Clone , Copy , PartialEq , Eq ) ]
24
- pub struct Error ( c_types:: c_int ) ;
24
+ pub struct Error ( NonZeroI16 ) ;
25
+
26
+ /// DO NOT use this macro outside of Error const initializations.
27
+ ///
28
+ /// # Safety
29
+ ///
30
+ /// The parameter must be a valid kernel error number.
31
+ macro_rules! kernel_const_to_error {
32
+ ( $( $tt: tt) * ) => { {
33
+ Error ( unsafe { NonZeroI16 :: new_unchecked( -( $( $tt) * as i16 ) ) } )
34
+ } } ;
35
+ }
25
36
26
37
impl Error {
27
38
/// Invalid argument.
28
- pub const EINVAL : Self = Error ( - ( bindings:: EINVAL as i32 ) ) ;
39
+ pub const EINVAL : Self = kernel_const_to_error ! ( bindings:: EINVAL ) ;
29
40
30
41
/// Out of memory.
31
- pub const ENOMEM : Self = Error ( - ( bindings:: ENOMEM as i32 ) ) ;
42
+ pub const ENOMEM : Self = kernel_const_to_error ! ( bindings:: ENOMEM ) ;
32
43
33
44
/// Bad address.
34
- pub const EFAULT : Self = Error ( - ( bindings:: EFAULT as i32 ) ) ;
45
+ pub const EFAULT : Self = kernel_const_to_error ! ( bindings:: EFAULT ) ;
35
46
36
47
/// Illegal seek.
37
- pub const ESPIPE : Self = Error ( - ( bindings:: ESPIPE as i32 ) ) ;
48
+ pub const ESPIPE : Self = kernel_const_to_error ! ( bindings:: ESPIPE ) ;
38
49
39
50
/// Try again.
40
- pub const EAGAIN : Self = Error ( - ( bindings:: EAGAIN as i32 ) ) ;
51
+ pub const EAGAIN : Self = kernel_const_to_error ! ( bindings:: EAGAIN ) ;
41
52
42
53
/// Device or resource busy.
43
- pub const EBUSY : Self = Error ( - ( bindings:: EBUSY as i32 ) ) ;
54
+ pub const EBUSY : Self = kernel_const_to_error ! ( bindings:: EBUSY ) ;
44
55
45
56
/// Restart the system call.
46
- pub const ERESTARTSYS : Self = Error ( - ( bindings:: ERESTARTSYS as i32 ) ) ;
57
+ pub const ERESTARTSYS : Self = kernel_const_to_error ! ( bindings:: ERESTARTSYS ) ;
47
58
48
59
/// Operation not permitted.
49
- pub const EPERM : Self = Error ( - ( bindings:: EPERM as i32 ) ) ;
60
+ pub const EPERM : Self = kernel_const_to_error ! ( bindings:: EPERM ) ;
50
61
51
62
/// No such process.
52
- pub const ESRCH : Self = Error ( - ( bindings:: ESRCH as i32 ) ) ;
63
+ pub const ESRCH : Self = kernel_const_to_error ! ( bindings:: ESRCH ) ;
53
64
54
65
/// No such file or directory.
55
- pub const ENOENT : Self = Error ( - ( bindings:: ENOENT as i32 ) ) ;
66
+ pub const ENOENT : Self = kernel_const_to_error ! ( bindings:: ENOENT ) ;
56
67
57
68
/// Interrupted system call.
58
- pub const EINTR : Self = Error ( - ( bindings:: EINTR as i32 ) ) ;
69
+ pub const EINTR : Self = kernel_const_to_error ! ( bindings:: EINTR ) ;
59
70
60
71
/// Bad file number.
61
- pub const EBADF : Self = Error ( - ( bindings:: EBADF as i32 ) ) ;
72
+ pub const EBADF : Self = kernel_const_to_error ! ( bindings:: EBADF ) ;
62
73
63
74
/// Creates an [`Error`] from a kernel error code.
64
75
///
@@ -76,7 +87,8 @@ impl Error {
76
87
77
88
// INVARIANT: the check above ensures the type invariant
78
89
// will hold.
79
- Error ( errno)
90
+ let nzi16_errno = NonZeroI16 :: new ( errno as i16 ) . unwrap ( ) ;
91
+ Error ( nzi16_errno)
80
92
}
81
93
82
94
/// Creates an [`Error`] from a kernel error code.
@@ -87,12 +99,15 @@ impl Error {
87
99
pub ( crate ) unsafe fn from_kernel_errno_unchecked ( errno : c_types:: c_int ) -> Error {
88
100
// INVARIANT: the contract ensures the type invariant
89
101
// will hold.
90
- Error ( errno)
102
+ //
103
+ // Safety: `errno` must not be zero, which is guaranteed by the contract
104
+ // of this function.
105
+ Error ( unsafe { NonZeroI16 :: new_unchecked ( errno as i16 ) } )
91
106
}
92
107
93
108
/// Returns the kernel error code.
94
109
pub fn to_kernel_errno ( self ) -> c_types:: c_int {
95
- self . 0
110
+ self . 0 . get ( ) . into ( )
96
111
}
97
112
}
98
113
@@ -102,11 +117,14 @@ impl fmt::Debug for Error {
102
117
fn rust_helper_errname ( err : c_types:: c_int ) -> * const c_types:: c_char ;
103
118
}
104
119
// SAFETY: FFI call.
105
- let name = unsafe { rust_helper_errname ( -self . 0 ) } ;
120
+ let name = unsafe { rust_helper_errname ( -self . to_kernel_errno ( ) ) } ;
106
121
107
122
if name. is_null ( ) {
108
123
// Print out number if no name can be found.
109
- return f. debug_tuple ( "Error" ) . field ( & -self . 0 ) . finish ( ) ;
124
+ return f
125
+ . debug_tuple ( "Error" )
126
+ . field ( & -self . to_kernel_errno ( ) )
127
+ . finish ( ) ;
110
128
}
111
129
112
130
// SAFETY: `'static` string from C, and is not NULL.
0 commit comments