1use crate::ffi::c_int;
2#[cfg(not(target_os = "teeos"))]
3use crate::ffi::{CStr, c_char};
4use crate::{fmt, 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::EMLINK => TooManyLinks,
161 libc::ENAMETOOLONG => InvalidFilename,
162 libc::ENETDOWN => NetworkDown,
163 libc::ENETUNREACH => NetworkUnreachable,
164 libc::ENOTCONN => NotConnected,
165 libc::ENOTDIR => NotADirectory,
166 #[cfg(not(target_os = "aix"))]
167 libc::ENOTEMPTY => DirectoryNotEmpty,
168 libc::EPIPE => BrokenPipe,
169 libc::EROFS => ReadOnlyFilesystem,
170 libc::ESPIPE => NotSeekable,
171 libc::ESTALE => StaleNetworkFileHandle,
172 libc::ETIMEDOUT => TimedOut,
173 libc::ETXTBSY => ExecutableFileBusy,
174 libc::EXDEV => CrossesDevices,
175 libc::EINPROGRESS => InProgress,
176 libc::EMFILE | libc::ENFILE => TooManyOpenFiles,
177 libc::EIO => InputOutputError,
178
179 libc::EACCES | libc::EPERM => PermissionDenied,
180
181 libc::ENOSYS => Unsupported,
182 x if x == libc::EOPNOTSUPP || x == libc::ENOTSUP => Unsupported,
186
187 x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
191
192 _ => Uncategorized,
193 }
194}
195
196#[cfg(any(target_family = "unix", target_os = "wasi"))]
198pub fn format_error(errno: i32, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199 const TMPBUF_SZ: usize = if falsecfg!(target_os = "wasi") { 1024 } else { 128 };
200
201 unsafe extern "C" {
202 #[cfg_attr(
203 all(
204 any(
205 target_os = "linux",
206 target_os = "hurd",
207 target_env = "newlib",
208 target_os = "cygwin",
209 target_env = "uclibc",
210 ),
211 not(target_env = "ohos")
212 ),
213 link_name = "__xpg_strerror_r"
214 )]
215 fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: libc::size_t) -> c_int;
216 }
217
218 let mut buf = [0 as c_char; TMPBUF_SZ];
219
220 let p = buf.as_mut_ptr();
221 unsafe {
222 if strerror_r(errno as c_int, p, buf.len()) < 0 {
223 { ::core::panicking::panic_fmt(format_args!("strerror_r failure")); };panic!("strerror_r failure");
224 }
225
226 let p = p as *const _;
227 f.write_fmt(format_args!("{0}", CStr::from_ptr(p).display()))write!(f, "{}", CStr::from_ptr(p).display())
230 }
231}
232
233#[cfg(target_os = "teeos")]
234pub fn format_error(_errno: i32, f: &mut fmt::Formatter<'_>) -> fmt::Result {
235 f.write_str("error string unimplemented")
236}