1use std::{io, str::Utf8Error};
4
5pub trait ErrorExt {
6 fn posix_errno(&self) -> i32;
7}
8
9impl ErrorExt for io::Error {
10 #[cfg(not(windows))]
11 fn posix_errno(&self) -> i32 {
12 self.raw_os_error().unwrap_or(0)
13 }
14 #[cfg(windows)]
15 fn posix_errno(&self) -> i32 {
16 let winerror = self.raw_os_error().unwrap_or(0);
17 winerror_to_errno(winerror)
18 }
19}
20
21#[cfg(windows)]
22pub fn last_os_error() -> io::Error {
23 let err = io::Error::last_os_error();
24 if err.raw_os_error() == Some(0) {
26 extern "C" {
27 fn _get_errno(pValue: *mut i32) -> i32;
28 }
29 let mut errno = 0;
30 unsafe { suppress_iph!(_get_errno(&mut errno)) };
31 let errno = errno_to_winerror(errno);
32 io::Error::from_raw_os_error(errno)
33 } else {
34 err
35 }
36}
37
38#[cfg(not(windows))]
39pub fn last_os_error() -> io::Error {
40 io::Error::last_os_error()
41}
42
43#[cfg(windows)]
44pub fn last_posix_errno() -> i32 {
45 let err = io::Error::last_os_error();
46 if err.raw_os_error() == Some(0) {
47 extern "C" {
48 fn _get_errno(pValue: *mut i32) -> i32;
49 }
50 let mut errno = 0;
51 unsafe { suppress_iph!(_get_errno(&mut errno)) };
52 errno
53 } else {
54 err.posix_errno()
55 }
56}
57
58#[cfg(not(windows))]
59pub fn last_posix_errno() -> i32 {
60 last_os_error().posix_errno()
61}
62
63#[cfg(unix)]
64pub fn bytes_as_osstr(b: &[u8]) -> Result<&std::ffi::OsStr, Utf8Error> {
65 use std::os::unix::ffi::OsStrExt;
66 Ok(std::ffi::OsStr::from_bytes(b))
67}
68
69#[cfg(not(unix))]
70pub fn bytes_as_osstr(b: &[u8]) -> Result<&std::ffi::OsStr, Utf8Error> {
71 Ok(std::str::from_utf8(b)?.as_ref())
72}
73
74#[cfg(unix)]
75pub use std::os::unix::ffi;
76#[cfg(target_os = "wasi")]
77pub use std::os::wasi::ffi;
78
79#[cfg(windows)]
80pub fn errno_to_winerror(errno: i32) -> i32 {
81 use libc::*;
82 use windows_sys::Win32::Foundation::*;
83 let winerror = match errno {
84 ENOENT => ERROR_FILE_NOT_FOUND,
85 E2BIG => ERROR_BAD_ENVIRONMENT,
86 ENOEXEC => ERROR_BAD_FORMAT,
87 EBADF => ERROR_INVALID_HANDLE,
88 ECHILD => ERROR_WAIT_NO_CHILDREN,
89 EAGAIN => ERROR_NO_PROC_SLOTS,
90 ENOMEM => ERROR_NOT_ENOUGH_MEMORY,
91 EACCES => ERROR_ACCESS_DENIED,
92 EEXIST => ERROR_FILE_EXISTS,
93 EXDEV => ERROR_NOT_SAME_DEVICE,
94 ENOTDIR => ERROR_DIRECTORY,
95 EMFILE => ERROR_TOO_MANY_OPEN_FILES,
96 ENOSPC => ERROR_DISK_FULL,
97 EPIPE => ERROR_BROKEN_PIPE,
98 ENOTEMPTY => ERROR_DIR_NOT_EMPTY,
99 EILSEQ => ERROR_NO_UNICODE_TRANSLATION,
100 EINVAL => ERROR_INVALID_FUNCTION,
101 _ => ERROR_INVALID_FUNCTION,
102 };
103 winerror as _
104}
105
106#[cfg(windows)]
109pub fn winerror_to_errno(winerror: i32) -> i32 {
110 use libc::*;
111 use windows_sys::Win32::{
112 Foundation::*,
113 Networking::WinSock::{WSAEACCES, WSAEBADF, WSAEFAULT, WSAEINTR, WSAEINVAL, WSAEMFILE},
114 };
115 if (10000..12000).contains(&winerror) {
122 match winerror {
123 WSAEINTR | WSAEBADF | WSAEACCES | WSAEFAULT | WSAEINVAL | WSAEMFILE => {
124 return winerror - 10000;
126 }
127 _ => return winerror as _,
128 }
129 }
130
131 #[allow(non_upper_case_globals)]
132 match winerror as u32 {
133 ERROR_FILE_NOT_FOUND
134 | ERROR_PATH_NOT_FOUND
135 | ERROR_INVALID_DRIVE
136 | ERROR_NO_MORE_FILES
137 | ERROR_BAD_NETPATH
138 | ERROR_BAD_NET_NAME
139 | ERROR_BAD_PATHNAME
140 | ERROR_FILENAME_EXCED_RANGE => ENOENT,
141 ERROR_BAD_ENVIRONMENT => E2BIG,
142 ERROR_BAD_FORMAT
143 | ERROR_INVALID_STARTING_CODESEG
144 | ERROR_INVALID_STACKSEG
145 | ERROR_INVALID_MODULETYPE
146 | ERROR_INVALID_EXE_SIGNATURE
147 | ERROR_EXE_MARKED_INVALID
148 | ERROR_BAD_EXE_FORMAT
149 | ERROR_ITERATED_DATA_EXCEEDS_64k
150 | ERROR_INVALID_MINALLOCSIZE
151 | ERROR_DYNLINK_FROM_INVALID_RING
152 | ERROR_IOPL_NOT_ENABLED
153 | ERROR_INVALID_SEGDPL
154 | ERROR_AUTODATASEG_EXCEEDS_64k
155 | ERROR_RING2SEG_MUST_BE_MOVABLE
156 | ERROR_RELOC_CHAIN_XEEDS_SEGLIM
157 | ERROR_INFLOOP_IN_RELOC_CHAIN => ENOEXEC,
158 ERROR_INVALID_HANDLE | ERROR_INVALID_TARGET_HANDLE | ERROR_DIRECT_ACCESS_HANDLE => EBADF,
159 ERROR_WAIT_NO_CHILDREN | ERROR_CHILD_NOT_COMPLETE => ECHILD,
160 ERROR_NO_PROC_SLOTS | ERROR_MAX_THRDS_REACHED | ERROR_NESTING_NOT_ALLOWED => EAGAIN,
161 ERROR_ARENA_TRASHED
162 | ERROR_NOT_ENOUGH_MEMORY
163 | ERROR_INVALID_BLOCK
164 | ERROR_NOT_ENOUGH_QUOTA => ENOMEM,
165 ERROR_ACCESS_DENIED
166 | ERROR_CURRENT_DIRECTORY
167 | ERROR_WRITE_PROTECT
168 | ERROR_BAD_UNIT
169 | ERROR_NOT_READY
170 | ERROR_BAD_COMMAND
171 | ERROR_CRC
172 | ERROR_BAD_LENGTH
173 | ERROR_SEEK
174 | ERROR_NOT_DOS_DISK
175 | ERROR_SECTOR_NOT_FOUND
176 | ERROR_OUT_OF_PAPER
177 | ERROR_WRITE_FAULT
178 | ERROR_READ_FAULT
179 | ERROR_GEN_FAILURE
180 | ERROR_SHARING_VIOLATION
181 | ERROR_LOCK_VIOLATION
182 | ERROR_WRONG_DISK
183 | ERROR_SHARING_BUFFER_EXCEEDED
184 | ERROR_NETWORK_ACCESS_DENIED
185 | ERROR_CANNOT_MAKE
186 | ERROR_FAIL_I24
187 | ERROR_DRIVE_LOCKED
188 | ERROR_SEEK_ON_DEVICE
189 | ERROR_NOT_LOCKED
190 | ERROR_LOCK_FAILED
191 | 35 => EACCES,
192 ERROR_FILE_EXISTS | ERROR_ALREADY_EXISTS => EEXIST,
193 ERROR_NOT_SAME_DEVICE => EXDEV,
194 ERROR_DIRECTORY => ENOTDIR,
195 ERROR_TOO_MANY_OPEN_FILES => EMFILE,
196 ERROR_DISK_FULL => ENOSPC,
197 ERROR_BROKEN_PIPE | ERROR_NO_DATA => EPIPE,
198 ERROR_DIR_NOT_EMPTY => ENOTEMPTY,
199 ERROR_NO_UNICODE_TRANSLATION => EILSEQ,
200 ERROR_INVALID_FUNCTION
201 | ERROR_INVALID_ACCESS
202 | ERROR_INVALID_DATA
203 | ERROR_INVALID_PARAMETER
204 | ERROR_NEGATIVE_SEEK => EINVAL,
205 _ => EINVAL,
206 }
207}