pub mod fifo_file;
pub mod signal;
#[cfg(any(
target_os = "linux",
target_os = "android",
target_os = "emscripten",
target_os = "solaris",
target_os = "illumos",
target_os = "hermit",
target_os = "redox",
// For some unknown reason, Newlib only declares sockaddr_un on Xtensa, which is why we don't
// support Ud-sockets on ARM
all(target_env = "newlib", target_arch = "xtensa"),
target_env = "uclibc",
target_os = "freebsd",
target_os = "openbsd",
target_os = "netbsd",
target_os = "dragonfly",
target_os = "macos",
target_os = "ios",
doc,
))]
pub mod udsocket;
#[cfg(unix)]
pub(crate) mod unnamed_pipe;
#[cfg(unix)]
pub(crate) mod local_socket;
#[cfg(unix)]
use libc::{
c_int, size_t,
};
#[cfg(unix)]
use std::{
io,
os::unix::io::{AsRawFd, IntoRawFd, FromRawFd},
mem,
};
#[cfg(unix)]
pub(crate) struct FdOps (pub(crate) c_int);
#[cfg(unix)]
impl FdOps {
#[inline]
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
let (success, num_bytes_read) = unsafe {
let length_to_read = buf.len() as size_t;
let size_or_err = libc::read(
self.as_raw_fd(),
buf.as_mut_ptr() as *mut _,
length_to_read,
);
if size_or_err >= 0 {
(true, size_or_err as usize)
} else {
(false, 0)
}
};
if success {
Ok(num_bytes_read)
} else {
Err(io::Error::last_os_error())
}
}
#[inline]
pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
let (success, num_bytes_written) = unsafe {
let length_to_write = buf.len() as size_t;
let size_or_err = libc::write(
self.as_raw_fd(),
buf.as_ptr() as *const _,
length_to_write,
);
if size_or_err >= 0 {
(true, size_or_err as usize)
} else {
(false, 0)
}
};
if success {
Ok(num_bytes_written)
} else {
Err(io::Error::last_os_error())
}
}
#[inline]
pub fn flush(&self) -> io::Result<()> {
let success = unsafe {
libc::fsync(self.as_raw_fd()) >= 0
};
if success {
Ok(())
} else {
Err(io::Error::last_os_error())
}
}
}
#[cfg(unix)]
impl AsRawFd for FdOps {
#[inline(always)]
fn as_raw_fd(&self) -> c_int {
self.0
}
}
#[cfg(unix)]
impl IntoRawFd for FdOps {
#[inline(always)]
fn into_raw_fd(self) -> c_int {
let fd = self.as_raw_fd();
mem::forget(self);
fd
}
}
#[cfg(unix)]
impl FromRawFd for FdOps {
#[inline(always)]
unsafe fn from_raw_fd(fd: c_int) -> Self {
Self(fd)
}
}
#[cfg(unix)]
impl Drop for FdOps {
#[inline]
fn drop(&mut self) {
debug_assert!(unsafe {
let mut success = true;
while libc::close(self.0) != 0 {
if io::Error::last_os_error().kind() != io::ErrorKind::Interrupted {
success = false;
break;
}
}
success
});
}
}