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