1#![no_std]
19
20use core::fmt;
21use core::slice;
22use core::str;
23
24#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
25#[repr(transparent)]
26pub struct Error {
27 pub errno: i32,
28}
29
30impl Error {
31 pub const fn new(errno: i32) -> Self {
32 Self { errno }
33 }
34 pub fn last_error() -> Self {
35 Self { errno: errno() }
36 }
37}
38
39impl Default for Error {
40 fn default() -> Self {
41 Error::new(-1)
42 }
43}
44
45impl From<i32> for Error {
46 fn from(i32: i32) -> Self {
47 Self::new(i32)
48 }
49}
50
51impl From<Error> for Result<(), Error> {
52 fn from(err: Error) -> Self {
53 if err.errno == 0 {
54 Ok(())
55 } else {
56 Err(err)
57 }
58 }
59}
60
61impl fmt::Display for Error {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
63 write!(f, "{}, {}", self.errno, unsafe { errmsg(self.errno) })
64 }
65}
66
67impl fmt::Debug for Error {
68 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
69 write!(f, "{}, {}", self.errno, unsafe { errmsg(self.errno) })
70 }
71}
72
73cfg_if::cfg_if! {
74 if #[cfg(unix)] {
75 #[link(name = "c")]
76 extern "C" {
77 #[cfg(any(
78 target_os = "linux",
79 target_os = "redox",
80 target_os = "dragonfly",
81 target_os = "fuchsia"
82 ))]
83 #[link_name = "__errno_location"]
84 fn errno_location() -> *mut i32;
85
86 #[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))]
87 #[link_name = "__errno"]
88 fn errno_location() -> *mut i32;
89
90 #[cfg(any(target_os = "ios", target_os = "macos", target_os = "freebsd"))]
91 #[link_name = "__error"]
92 fn errno_location() -> *mut i32;
93
94 #[cfg(any(target_os = "illumos", target_os = "solaris"))]
95 #[link_name = "___errno"]
96 fn errno_location() -> *mut i32;
97
98 #[cfg(any(target_os = "haiku"))]
99 #[link_name = "_errnop"]
100 fn errno_location() -> *mut i32;
101
102 fn strerror(errno: i32) -> *const u8;
103 fn strlen(s: *const u8) -> usize;
104 }
105
106 pub fn errno() -> i32 {
107 unsafe { *errno_location() }
110 }
111
112 pub fn set_errno(errno: i32) {
113 unsafe { *errno_location() = errno };
116 }
117
118 pub unsafe fn errmsg<'a>(errno: i32) -> &'a str {
121 let s = strerror(errno);
122 let len = strlen(s);
123 str::from_utf8_unchecked(slice::from_raw_parts(s, len))
124 }
125 } else if #[cfg(windows)] {
126 pub fn errmsg<'a>(errno: i32) -> &'a str {
127 "unknown"
128 }
129
130 #[link(name = "Kernel32")]
131 extern "C" {
132 #[link_name = "GetLastError"]
133 pub fn errno() -> i32;
134 #[link_name = "SetLastError"]
135 pub fn set_errno(errno: i32);
136 }
137 }
138}