pub type ErrnoLocation = libc::c_int;
cfg_if::cfg_if! {
if #[cfg(feature = "nightly")] {
pub type Errno = std::io::RawOsError;
} else {
pub type Errno = i32;
}
}
unsafe extern "C" {
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
#[cfg_attr(
any(
target_os = "linux",
target_os = "emscripten",
target_os = "fuchsia",
target_os = "l4re",
target_os = "hurd",
),
link_name = "__errno_location"
)]
#[cfg_attr(
any(
target_os = "netbsd",
target_os = "openbsd",
target_os = "android",
target_os = "redox",
target_os = "nuttx",
target_env = "newlib"
),
link_name = "__errno"
)]
#[cfg_attr(
any(target_os = "solaris", target_os = "illumos"),
link_name = "___errno"
)]
#[cfg_attr(target_os = "nto", link_name = "__get_errno_ptr")]
#[cfg_attr(
any(target_os = "freebsd", target_vendor = "apple"),
link_name = "__error"
)]
#[cfg_attr(target_os = "haiku", link_name = "_errnop")]
#[cfg_attr(target_os = "aix", link_name = "_Errno")]
fn errno_location() -> *mut ErrnoLocation;
}
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
pub fn errno() -> Errno { unsafe { (*errno_location()) as Errno } }
#[cfg(not(any(target_os = "dragonfly", target_os = "vxworks", target_os = "rtems")))]
#[allow(dead_code)] pub fn set_errno(e: Errno) { unsafe { *errno_location() = e as ErrnoLocation } }
#[cfg(target_os = "vxworks")]
pub fn errno() -> Errno { unsafe { libc::errnoGet() } }
#[cfg(target_os = "rtems")]
pub fn errno() -> Errno {
unsafe extern "C" {
#[thread_local]
static _tls_errno: ErrnoLocation;
}
unsafe { _tls_errno as Errno }
}
#[cfg(target_os = "dragonfly")]
pub fn errno() -> Errno {
unsafe extern "C" {
#[thread_local]
static errno: ErrnoLocation;
}
unsafe { errno as Errno }
}
#[cfg(target_os = "dragonfly")]
#[allow(dead_code)]
pub fn set_errno(e: Errno) {
unsafe extern "C" {
#[thread_local]
static mut errno: ErrnoLocation;
}
unsafe {
errno = e;
}
}
pub const UNSET_ERRNO: Errno = 0;
#[inline]
pub fn errno_is_unset() -> bool { errno() == UNSET_ERRNO }
#[inline]
pub fn maybe_errno(errno: Errno) -> Option<std::io::Error> {
debug_assert!(errno >= 0);
if errno == UNSET_ERRNO {
return None;
}
let err = std::io::Error::from_raw_os_error(errno);
Some(err)
}
#[inline]
pub fn with_cleared_errno<T>(f: impl FnOnce() -> T) -> Result<T, std::io::Error> {
set_errno(UNSET_ERRNO);
let ret = f();
if let Some(err) = maybe_errno(errno()) {
return Err(err);
}
Ok(ret)
}