@@ -9,7 +9,7 @@ use crate::{bindings, c_types};
99use alloc:: { alloc:: AllocError , collections:: TryReserveError } ;
1010use core:: convert:: From ;
1111use core:: fmt;
12- use core:: num:: TryFromIntError ;
12+ use core:: num:: { NonZeroI32 , TryFromIntError } ;
1313use core:: str:: { self , Utf8Error } ;
1414
1515/// Generic integer kernel error.
@@ -21,44 +21,49 @@ use core::str::{self, Utf8Error};
2121///
2222/// The value is a valid `errno` (i.e. `>= -MAX_ERRNO && < 0`).
2323#[ 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+ }
2530
2631impl Error {
2732 /// Invalid argument.
28- pub const EINVAL : Self = Error ( - ( bindings:: EINVAL as i32 ) ) ;
33+ pub const EINVAL : Self = kernel_const_to_error ( bindings:: EINVAL ) ;
2934
3035 /// Out of memory.
31- pub const ENOMEM : Self = Error ( - ( bindings:: ENOMEM as i32 ) ) ;
36+ pub const ENOMEM : Self = kernel_const_to_error ( bindings:: ENOMEM ) ;
3237
3338 /// Bad address.
34- pub const EFAULT : Self = Error ( - ( bindings:: EFAULT as i32 ) ) ;
39+ pub const EFAULT : Self = kernel_const_to_error ( bindings:: EFAULT ) ;
3540
3641 /// Illegal seek.
37- pub const ESPIPE : Self = Error ( - ( bindings:: ESPIPE as i32 ) ) ;
42+ pub const ESPIPE : Self = kernel_const_to_error ( bindings:: ESPIPE ) ;
3843
3944 /// Try again.
40- pub const EAGAIN : Self = Error ( - ( bindings:: EAGAIN as i32 ) ) ;
45+ pub const EAGAIN : Self = kernel_const_to_error ( bindings:: EAGAIN ) ;
4146
4247 /// 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 ) ;
4449
4550 /// 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 ) ;
4752
4853 /// Operation not permitted.
49- pub const EPERM : Self = Error ( - ( bindings:: EPERM as i32 ) ) ;
54+ pub const EPERM : Self = kernel_const_to_error ( bindings:: EPERM ) ;
5055
5156 /// No such process.
52- pub const ESRCH : Self = Error ( - ( bindings:: ESRCH as i32 ) ) ;
57+ pub const ESRCH : Self = kernel_const_to_error ( bindings:: ESRCH ) ;
5358
5459 /// 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 ) ;
5661
5762 /// Interrupted system call.
58- pub const EINTR : Self = Error ( - ( bindings:: EINTR as i32 ) ) ;
63+ pub const EINTR : Self = kernel_const_to_error ( bindings:: EINTR ) ;
5964
6065 /// Bad file number.
61- pub const EBADF : Self = Error ( - ( bindings:: EBADF as i32 ) ) ;
66+ pub const EBADF : Self = kernel_const_to_error ( bindings:: EBADF ) ;
6267
6368 /// Creates an [`Error`] from a kernel error code.
6469 ///
@@ -76,7 +81,11 @@ impl Error {
7681
7782 // INVARIANT: the check above ensures the type invariant
7883 // 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)
8089 }
8190
8291 /// Creates an [`Error`] from a kernel error code.
@@ -87,12 +96,15 @@ impl Error {
8796 pub ( crate ) unsafe fn from_kernel_errno_unchecked ( errno : c_types:: c_int ) -> Error {
8897 // INVARIANT: the contract ensures the type invariant
8998 // 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) } )
91103 }
92104
93105 /// Returns the kernel error code.
94106 pub fn to_kernel_errno ( self ) -> c_types:: c_int {
95- self . 0
107+ self . 0 . get ( )
96108 }
97109}
98110
@@ -102,11 +114,14 @@ impl fmt::Debug for Error {
102114 fn rust_helper_errname ( err : c_types:: c_int ) -> * const c_types:: c_char ;
103115 }
104116 // SAFETY: FFI call.
105- let name = unsafe { rust_helper_errname ( -self . 0 ) } ;
117+ let name = unsafe { rust_helper_errname ( -self . to_kernel_errno ( ) ) } ;
106118
107119 if name. is_null ( ) {
108120 // 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 ( ) ;
110125 }
111126
112127 // SAFETY: `'static` string from C, and is not NULL.
0 commit comments