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 = "vxworks",
64 target_os = "rtems",
65 target_os = "wasi",
66)))]
67#[allow(dead_code)] #[inline]
69pub fn set_errno(e: i32) {
70 unsafe { *errno_location() = e as c_int }
71}
72
73#[cfg(target_os = "vxworks")]
74#[inline]
75pub fn errno() -> i32 {
76 unsafe { libc::errnoGet() }
77}
78
79#[cfg(target_os = "rtems")]
80#[inline]
81pub fn errno() -> i32 {
82 unsafe extern "C" {
83 #[thread_local]
84 static _tls_errno: c_int;
85 }
86
87 unsafe { _tls_errno as i32 }
88}
89
90#[cfg(target_os = "dragonfly")]
91#[inline]
92pub fn errno() -> i32 {
93 unsafe extern "C" {
94 #[thread_local]
95 static errno: c_int;
96 }
97
98 unsafe { errno as i32 }
99}
100
101#[cfg(target_os = "dragonfly")]
102#[allow(dead_code)]
103#[inline]
104pub fn set_errno(e: i32) {
105 unsafe extern "C" {
106 #[thread_local]
107 static mut errno: c_int;
108 }
109
110 unsafe {
111 errno = e;
112 }
113}
114
115#[cfg(target_os = "wasi")]
116unsafe extern "C" {
117 #[thread_local]
118 #[link_name = "errno"]
119 static mut libc_errno: libc::c_int;
120}
121
122#[cfg(target_os = "wasi")]
123pub fn errno() -> i32 {
124 unsafe { libc_errno as i32 }
125}
126
127#[cfg(target_os = "wasi")]
128pub fn set_errno(val: i32) {
129 unsafe {
130 libc_errno = val;
131 }
132}
133
134#[inline]
135pub fn is_interrupted(errno: i32) -> bool {
136 errno == libc::EINTR
137}
138
139pub fn decode_error_kind(errno: i32) -> io::ErrorKind {
140 use io::ErrorKind::*;
141 match errno as libc::c_int {
142 libc::E2BIG => ArgumentListTooLong,
143 libc::EADDRINUSE => AddrInUse,
144 libc::EADDRNOTAVAIL => AddrNotAvailable,
145 libc::EBUSY => ResourceBusy,
146 libc::ECONNABORTED => ConnectionAborted,
147 libc::ECONNREFUSED => ConnectionRefused,
148 libc::ECONNRESET => ConnectionReset,
149 libc::EDEADLK => Deadlock,
150 libc::EDQUOT => QuotaExceeded,
151 libc::EEXIST => AlreadyExists,
152 libc::EFBIG => FileTooLarge,
153 libc::EHOSTUNREACH => HostUnreachable,
154 libc::EINTR => Interrupted,
155 libc::EINVAL => InvalidInput,
156 libc::EISDIR => IsADirectory,
157 libc::ELOOP => FilesystemLoop,
158 libc::ENOENT => NotFound,
159 libc::ENOMEM => OutOfMemory,
160 libc::ENOSPC => StorageFull,
161 libc::ENOSYS => Unsupported,
162 libc::EMLINK => TooManyLinks,
163 libc::ENAMETOOLONG => InvalidFilename,
164 libc::ENETDOWN => NetworkDown,
165 libc::ENETUNREACH => NetworkUnreachable,
166 libc::ENOTCONN => NotConnected,
167 libc::ENOTDIR => NotADirectory,
168 #[cfg(not(target_os = "aix"))]
169 libc::ENOTEMPTY => DirectoryNotEmpty,
170 libc::EPIPE => BrokenPipe,
171 libc::EROFS => ReadOnlyFilesystem,
172 libc::ESPIPE => NotSeekable,
173 libc::ESTALE => StaleNetworkFileHandle,
174 libc::ETIMEDOUT => TimedOut,
175 libc::ETXTBSY => ExecutableFileBusy,
176 libc::EXDEV => CrossesDevices,
177 libc::EINPROGRESS => InProgress,
178 libc::EMFILE | libc::ENFILE => TooManyOpenFiles,
179 libc::EOPNOTSUPP => Unsupported,
180 libc::EIO => InputOutputError,
181
182 libc::EACCES | libc::EPERM => PermissionDenied,
183
184 x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
188
189 _ => Uncategorized,
190 }
191}
192
193#[cfg(any(target_family = "unix", target_os = "wasi"))]
195pub fn error_string(errno: i32) -> String {
196 const TMPBUF_SZ: usize = if falsecfg!(target_os = "wasi") { 1024 } else { 128 };
197
198 unsafe extern "C" {
199 #[cfg_attr(
200 all(
201 any(
202 target_os = "linux",
203 target_os = "hurd",
204 target_env = "newlib",
205 target_os = "cygwin"
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 { ::core::panicking::panic_fmt(format_args!("strerror_r failure")); };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}