1use crate::ffi::c_int;
2#[cfg(not(target_os = "teeos"))]
3use crate::ffi::{CStr, c_char};
4use crate::io;
5
6unsafe extern "C" {
7 #[cfg(not(any(
8 target_os = "dragonfly",
9 target_os = "vxworks",
10 target_os = "rtems",
11 target_os = "wasi"
12 )))]
13 #[cfg_attr(
14 any(
15 target_os = "linux",
16 target_os = "emscripten",
17 target_os = "fuchsia",
18 target_os = "l4re",
19 target_os = "hurd",
20 target_os = "teeos",
21 ),
22 link_name = "__errno_location"
23 )]
24 #[cfg_attr(
25 any(
26 target_os = "netbsd",
27 target_os = "openbsd",
28 target_os = "cygwin",
29 target_os = "android",
30 target_os = "redox",
31 target_os = "nuttx",
32 target_env = "newlib"
33 ),
34 link_name = "__errno"
35 )]
36 #[cfg_attr(any(target_os = "solaris", target_os = "illumos"), link_name = "___errno")]
37 #[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
38 #[cfg_attr(target_os = "qnx", link_name = "__get_errno_ptr")]
39 #[cfg_attr(any(target_os = "freebsd", target_vendor = "apple"), link_name = "__error")]
40 #[cfg_attr(target_os = "haiku", link_name = "_errnop")]
41 #[cfg_attr(target_os = "aix", link_name = "_Errno")]
42 #[unsafe(ffi_const)]
44 pub safe fn errno_location() -> *mut c_int;
45}
46
47#[cfg(not(any(
49 target_os = "dragonfly",
50 target_os = "vxworks",
51 target_os = "rtems",
52 target_os = "wasi"
53)))]
54#[inline]
55pub fn errno() -> i32 {
56 unsafe { (*errno_location()) as i32 }
57}
58
59#[cfg(not(any(
62 target_os = "dragonfly",
63 target_os = "espidf",
64 target_os = "lynxos178",
65 target_os = "qurt",
66 target_os = "rtems",
67 target_os = "vxworks",
68 target_os = "wasi",
69)))]
70#[inline]
71pub fn set_errno(e: i32) {
72 unsafe { *errno_location() = e as c_int }
73}
74
75#[cfg(target_os = "vxworks")]
76#[inline]
77pub fn errno() -> i32 {
78 unsafe { libc::errnoGet() }
79}
80
81#[cfg(target_os = "rtems")]
82#[inline]
83pub fn errno() -> i32 {
84 unsafe extern "C" {
85 #[thread_local]
86 static _tls_errno: c_int;
87 }
88
89 unsafe { _tls_errno as i32 }
90}
91
92#[cfg(target_os = "dragonfly")]
93#[inline]
94pub fn errno() -> i32 {
95 unsafe extern "C" {
96 #[thread_local]
97 static mut errno: c_int;
98 }
99
100 unsafe { errno as i32 }
101}
102
103#[cfg(target_os = "dragonfly")]
104#[inline]
105pub fn set_errno(e: i32) {
106 unsafe extern "C" {
107 #[thread_local]
108 static mut errno: c_int;
109 }
110
111 unsafe { errno = e };
112}
113
114#[cfg(target_os = "wasi")]
115unsafe extern "C" {
116 #[thread_local]
117 #[link_name = "errno"]
118 static mut libc_errno: libc::c_int;
119}
120
121#[cfg(target_os = "wasi")]
122pub fn errno() -> i32 {
123 unsafe { libc_errno as i32 }
124}
125
126#[cfg(target_os = "wasi")]
127pub fn set_errno(val: i32) {
128 unsafe {
129 libc_errno = val;
130 }
131}
132
133#[inline]
134pub fn is_interrupted(errno: i32) -> bool {
135 errno == libc::EINTR
136}
137
138pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
139 use io::ErrorKind::*;
140 match errno as libc::c_int {
141 libc::E2BIG => ArgumentListTooLong,
142 libc::EADDRINUSE => AddrInUse,
143 libc::EADDRNOTAVAIL => AddrNotAvailable,
144 libc::EBUSY => ResourceBusy,
145 libc::ECONNABORTED => ConnectionAborted,
146 libc::ECONNREFUSED => ConnectionRefused,
147 libc::ECONNRESET => ConnectionReset,
148 libc::EDEADLK => Deadlock,
149 libc::EDQUOT => QuotaExceeded,
150 libc::EEXIST => AlreadyExists,
151 libc::EFBIG => FileTooLarge,
152 libc::EHOSTUNREACH => HostUnreachable,
153 libc::EINTR => Interrupted,
154 libc::EINVAL => InvalidInput,
155 libc::EISDIR => IsADirectory,
156 libc::ELOOP => FilesystemLoop,
157 libc::ENOENT => NotFound,
158 libc::ENOMEM => OutOfMemory,
159 libc::ENOSPC => StorageFull,
160 libc::ENOSYS => Unsupported,
161 libc::EMLINK => TooManyLinks,
162 libc::ENAMETOOLONG => InvalidFilename,
163 libc::ENETDOWN => NetworkDown,
164 libc::ENETUNREACH => NetworkUnreachable,
165 libc::ENOTCONN => NotConnected,
166 libc::ENOTDIR => NotADirectory,
167 #[cfg(not(target_os = "aix"))]
168 libc::ENOTEMPTY => DirectoryNotEmpty,
169 libc::EPIPE => BrokenPipe,
170 libc::EROFS => ReadOnlyFilesystem,
171 libc::ESPIPE => NotSeekable,
172 libc::ESTALE => StaleNetworkFileHandle,
173 libc::ETIMEDOUT => TimedOut,
174 libc::ETXTBSY => ExecutableFileBusy,
175 libc::EXDEV => CrossesDevices,
176 libc::EINPROGRESS => InProgress,
177 libc::EMFILE | libc::ENFILE => TooManyOpenFiles,
178 libc::EOPNOTSUPP => Unsupported,
179 libc::EIO => InputOutputError,
180
181 libc::EACCES | libc::EPERM => PermissionDenied,
182
183 x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
187
188 _ => Uncategorized,
189 }
190}
191
192#[cfg(any(target_family = "unix", target_os = "wasi"))]
194pub fn error_string(errno: i32) -> String {
195 const TMPBUF_SZ: usize = if cfg!(target_os = "wasi") { 1024 } else { 128 };
196
197 unsafe extern "C" {
198 #[cfg_attr(
199 all(
200 any(
201 target_os = "linux",
202 target_os = "hurd",
203 target_env = "newlib",
204 target_os = "cygwin",
205 target_env = "uclibc",
206 ),
207 not(target_env = "ohos")
208 ),
209 link_name = "__xpg_strerror_r"
210 )]
211 fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int;
212 }
213
214 let mut buf = [0 as c_char; TMPBUF_SZ];
215
216 let p = buf.as_mut_ptr();
217 unsafe {
218 if strerror_r(errno as c_int, p, buf.len()) < 0 {
219 panic!("strerror_r failure");
220 }
221
222 let p = p as *const _;
223 String::from_utf8_lossy(CStr::from_ptr(p).to_bytes()).into()
226 }
227}
228
229#[cfg(target_os = "teeos")]
230pub fn error_string(_errno: i32) -> String {
231 "error string unimplemented".to_string()
232}