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