@@ -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:: { NonZeroI32 , TryFromIntError } ;
13
13
use core:: str:: { self , Utf8Error } ;
14
14
15
15
/// Generic integer kernel error.
@@ -21,44 +21,49 @@ 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 ( NonZeroI32 ) ;
25
+
26
+ /// DO NOT use this function outside of Error const initializations.
27
+ const fn kernel_const_to_error ( val : u32 ) -> Error {
28
+ Error ( unsafe { NonZeroI32 :: new_unchecked ( -( val as i32 ) ) } )
29
+ }
25
30
26
31
impl Error {
27
32
/// Invalid argument.
28
- pub const EINVAL : Self = Error ( - ( bindings:: EINVAL as i32 ) ) ;
33
+ pub const EINVAL : Self = kernel_const_to_error ( bindings:: EINVAL ) ;
29
34
30
35
/// Out of memory.
31
- pub const ENOMEM : Self = Error ( - ( bindings:: ENOMEM as i32 ) ) ;
36
+ pub const ENOMEM : Self = kernel_const_to_error ( bindings:: ENOMEM ) ;
32
37
33
38
/// Bad address.
34
- pub const EFAULT : Self = Error ( - ( bindings:: EFAULT as i32 ) ) ;
39
+ pub const EFAULT : Self = kernel_const_to_error ( bindings:: EFAULT ) ;
35
40
36
41
/// Illegal seek.
37
- pub const ESPIPE : Self = Error ( - ( bindings:: ESPIPE as i32 ) ) ;
42
+ pub const ESPIPE : Self = kernel_const_to_error ( bindings:: ESPIPE ) ;
38
43
39
44
/// Try again.
40
- pub const EAGAIN : Self = Error ( - ( bindings:: EAGAIN as i32 ) ) ;
45
+ pub const EAGAIN : Self = kernel_const_to_error ( bindings:: EAGAIN ) ;
41
46
42
47
/// Device or resource busy.
43
- pub const EBUSY : Self = Error ( - ( bindings:: EBUSY as i32 ) ) ;
48
+ pub const EBUSY : Self = kernel_const_to_error ( bindings:: EBUSY ) ;
44
49
45
50
/// Restart the system call.
46
- pub const ERESTARTSYS : Self = Error ( - ( bindings:: ERESTARTSYS as i32 ) ) ;
51
+ pub const ERESTARTSYS : Self = kernel_const_to_error ( bindings:: ERESTARTSYS ) ;
47
52
48
53
/// Operation not permitted.
49
- pub const EPERM : Self = Error ( - ( bindings:: EPERM as i32 ) ) ;
54
+ pub const EPERM : Self = kernel_const_to_error ( bindings:: EPERM ) ;
50
55
51
56
/// No such process.
52
- pub const ESRCH : Self = Error ( - ( bindings:: ESRCH as i32 ) ) ;
57
+ pub const ESRCH : Self = kernel_const_to_error ( bindings:: ESRCH ) ;
53
58
54
59
/// No such file or directory.
55
- pub const ENOENT : Self = Error ( - ( bindings:: ENOENT as i32 ) ) ;
60
+ pub const ENOENT : Self = kernel_const_to_error ( bindings:: ENOENT ) ;
56
61
57
62
/// Interrupted system call.
58
- pub const EINTR : Self = Error ( - ( bindings:: EINTR as i32 ) ) ;
63
+ pub const EINTR : Self = kernel_const_to_error ( bindings:: EINTR ) ;
59
64
60
65
/// Bad file number.
61
- pub const EBADF : Self = Error ( - ( bindings:: EBADF as i32 ) ) ;
66
+ pub const EBADF : Self = kernel_const_to_error ( bindings:: EBADF ) ;
62
67
63
68
/// Creates an [`Error`] from a kernel error code.
64
69
///
@@ -76,7 +81,11 @@ impl Error {
76
81
77
82
// INVARIANT: the check above ensures the type invariant
78
83
// will hold.
79
- Error ( errno)
84
+ //
85
+ // Safety: `errno` must be non zero, which is guaranteed by the check
86
+ // above.
87
+ let nz_errno = unsafe { NonZeroI32 :: new_unchecked ( errno) } ;
88
+ Error ( nz_errno)
80
89
}
81
90
82
91
/// Creates an [`Error`] from a kernel error code.
@@ -87,12 +96,15 @@ impl Error {
87
96
pub ( crate ) unsafe fn from_kernel_errno_unchecked ( errno : c_types:: c_int ) -> Error {
88
97
// INVARIANT: the contract ensures the type invariant
89
98
// will hold.
90
- Error ( errno)
99
+ //
100
+ // Safety: `errno` must not be zero, which is guaranteed by the contract
101
+ // of this function.
102
+ Error ( unsafe { NonZeroI32 :: new_unchecked ( errno) } )
91
103
}
92
104
93
105
/// Returns the kernel error code.
94
106
pub fn to_kernel_errno ( self ) -> c_types:: c_int {
95
- self . 0
107
+ self . 0 . get ( )
96
108
}
97
109
}
98
110
@@ -102,11 +114,14 @@ impl fmt::Debug for Error {
102
114
fn rust_helper_errname ( err : c_types:: c_int ) -> * const c_types:: c_char ;
103
115
}
104
116
// SAFETY: FFI call.
105
- let name = unsafe { rust_helper_errname ( -self . 0 ) } ;
117
+ let name = unsafe { rust_helper_errname ( -self . to_kernel_errno ( ) ) } ;
106
118
107
119
if name. is_null ( ) {
108
120
// Print out number if no name can be found.
109
- return f. debug_tuple ( "Error" ) . field ( & -self . 0 ) . finish ( ) ;
121
+ return f
122
+ . debug_tuple ( "Error" )
123
+ . field ( & -self . to_kernel_errno ( ) )
124
+ . finish ( ) ;
110
125
}
111
126
112
127
// SAFETY: `'static` string from C, and is not NULL.
0 commit comments