@@ -352,23 +352,41 @@ impl Error {
352352 pub fn to_kernel_errno ( self ) -> c_types:: c_int {
353353 self . 0
354354 }
355+
356+ /// Returns a string representing the error, if one exists.
357+ #[ cfg( not( testlib) ) ]
358+ pub fn name ( & self ) -> Option < & ' static CStr > {
359+ // SAFETY: Just an FFI call, there are no extra safety requirements.
360+ let ptr = unsafe { bindings:: errname ( -self . 0 ) } ;
361+ if ptr. is_null ( ) {
362+ None
363+ } else {
364+ // SAFETY: The string returned by `errname` is static and `NUL`-terminated.
365+ Some ( unsafe { CStr :: from_char_ptr ( ptr) } )
366+ }
367+ }
368+
369+ /// Returns a string representing the error, if one exists.
370+ ///
371+ /// When `testlib` is configured, this always returns `None` to avoid the dependency on a
372+ /// kernel function so that tests that use this (e.g., by calling [`Result::unwrap`]) can still
373+ /// run in userspace.
374+ #[ cfg( testlib) ]
375+ pub fn name ( & self ) -> Option < & ' static CStr > {
376+ None
377+ }
355378}
356379
357380impl fmt:: Debug for Error {
358381 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
359- // SAFETY: FFI call.
360- let name = unsafe { bindings:: errname ( -self . 0 ) } ;
361-
362- if name. is_null ( ) {
382+ match self . name ( ) {
363383 // Print out number if no name can be found.
364- return f. debug_tuple ( "Error" ) . field ( & -self . 0 ) . finish ( ) ;
384+ None => f. debug_tuple ( "Error" ) . field ( & -self . 0 ) . finish ( ) ,
385+ // SAFETY: These strings are ASCII-only.
386+ Some ( name) => f
387+ . debug_tuple ( unsafe { str:: from_utf8_unchecked ( name) } )
388+ . finish ( ) ,
365389 }
366-
367- // SAFETY: `'static` string from C, and is not NULL.
368- let cstr = unsafe { CStr :: from_char_ptr ( name) } ;
369- // SAFETY: These strings are ASCII-only.
370- let str = unsafe { str:: from_utf8_unchecked ( cstr) } ;
371- f. debug_tuple ( str) . finish ( )
372390 }
373391}
374392
0 commit comments