@@ -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:: { NonZeroI16 , TryFromIntError } ;
1313use core:: str:: { self , Utf8Error } ;
1414
1515/// Generic integer kernel error.
@@ -21,44 +21,55 @@ 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 ( 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+ }
2536
2637impl Error {
2738 /// Invalid argument.
28- pub const EINVAL : Self = Error ( - ( bindings:: EINVAL as i32 ) ) ;
39+ pub const EINVAL : Self = kernel_const_to_error ! ( bindings:: EINVAL ) ;
2940
3041 /// Out of memory.
31- pub const ENOMEM : Self = Error ( - ( bindings:: ENOMEM as i32 ) ) ;
42+ pub const ENOMEM : Self = kernel_const_to_error ! ( bindings:: ENOMEM ) ;
3243
3344 /// Bad address.
34- pub const EFAULT : Self = Error ( - ( bindings:: EFAULT as i32 ) ) ;
45+ pub const EFAULT : Self = kernel_const_to_error ! ( bindings:: EFAULT ) ;
3546
3647 /// Illegal seek.
37- pub const ESPIPE : Self = Error ( - ( bindings:: ESPIPE as i32 ) ) ;
48+ pub const ESPIPE : Self = kernel_const_to_error ! ( bindings:: ESPIPE ) ;
3849
3950 /// Try again.
40- pub const EAGAIN : Self = Error ( - ( bindings:: EAGAIN as i32 ) ) ;
51+ pub const EAGAIN : Self = kernel_const_to_error ! ( bindings:: EAGAIN ) ;
4152
4253 /// 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 ) ;
4455
4556 /// 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 ) ;
4758
4859 /// Operation not permitted.
49- pub const EPERM : Self = Error ( - ( bindings:: EPERM as i32 ) ) ;
60+ pub const EPERM : Self = kernel_const_to_error ! ( bindings:: EPERM ) ;
5061
5162 /// No such process.
52- pub const ESRCH : Self = Error ( - ( bindings:: ESRCH as i32 ) ) ;
63+ pub const ESRCH : Self = kernel_const_to_error ! ( bindings:: ESRCH ) ;
5364
5465 /// 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 ) ;
5667
5768 /// Interrupted system call.
58- pub const EINTR : Self = Error ( - ( bindings:: EINTR as i32 ) ) ;
69+ pub const EINTR : Self = kernel_const_to_error ! ( bindings:: EINTR ) ;
5970
6071 /// Bad file number.
61- pub const EBADF : Self = Error ( - ( bindings:: EBADF as i32 ) ) ;
72+ pub const EBADF : Self = kernel_const_to_error ! ( bindings:: EBADF ) ;
6273
6374 /// Creates an [`Error`] from a kernel error code.
6475 ///
@@ -76,7 +87,8 @@ impl Error {
7687
7788 // INVARIANT: the check above ensures the type invariant
7889 // will hold.
79- Error ( errno)
90+ let nzi16_errno = NonZeroI16 :: new ( errno as i16 ) . unwrap ( ) ;
91+ Error ( nzi16_errno)
8092 }
8193
8294 /// Creates an [`Error`] from a kernel error code.
@@ -87,12 +99,15 @@ impl Error {
8799 pub ( crate ) unsafe fn from_kernel_errno_unchecked ( errno : c_types:: c_int ) -> Error {
88100 // INVARIANT: the contract ensures the type invariant
89101 // 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 ) } )
91106 }
92107
93108 /// Returns the kernel error code.
94109 pub fn to_kernel_errno ( self ) -> c_types:: c_int {
95- self . 0
110+ self . 0 . get ( ) . into ( )
96111 }
97112}
98113
@@ -102,11 +117,14 @@ impl fmt::Debug for Error {
102117 fn rust_helper_errname ( err : c_types:: c_int ) -> * const c_types:: c_char ;
103118 }
104119 // SAFETY: FFI call.
105- let name = unsafe { rust_helper_errname ( -self . 0 ) } ;
120+ let name = unsafe { rust_helper_errname ( -self . to_kernel_errno ( ) ) } ;
106121
107122 if name. is_null ( ) {
108123 // 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 ( ) ;
110128 }
111129
112130 // SAFETY: `'static` string from C, and is not NULL.
0 commit comments