#![cfg(unix)]
#![allow(unsafe_code)]
pub mod affinity;
pub mod pipe;
pub mod process;
pub mod pthread;
use std::fs::File;
use std::io;
use std::io::Error;
use std::os::unix::prelude::*;
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Errno(pub i32);
impl std::fmt::Debug for Errno {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(&Error::from(*self), f)
}
}
impl From<Errno> for Error {
fn from(code: Errno) -> Self {
Self::from_raw_os_error(code.0)
}
}
pub trait TryAsErrno {
fn try_as_errno(&self) -> Option<Errno>;
}
impl TryAsErrno for Errno {
fn try_as_errno(&self) -> Option<Errno> {
Some(*self)
}
}
impl TryAsErrno for Error {
fn try_as_errno(&self) -> Option<Errno> {
self.raw_os_error().map(Errno)
}
}
pub(crate) fn errno() -> Errno {
Errno(Error::last_os_error().raw_os_error().unwrap())
}
pub trait SyscallResult: Sized {
fn syscall_result(self) -> Result<Self, Errno>;
}
impl SyscallResult for i32 {
fn syscall_result(self) -> Result<Self, Errno> {
if self >= 0 {
Ok(self)
} else {
Err(errno())
}
}
}
impl SyscallResult for isize {
fn syscall_result(self) -> Result<Self, Errno> {
if self >= 0 {
Ok(self)
} else {
Err(errno())
}
}
}
pub fn while_eintr<F, R, E>(mut f: F) -> Result<R, E>
where
F: FnMut() -> Result<R, E>,
E: TryAsErrno,
{
loop {
match f() {
Err(err) if err.try_as_errno() == Some(Errno(libc::EINTR)) => {}
r => break r,
}
}
}
pub fn close_stdout() -> io::Result<()> {
let new_stdout = File::open("/dev/null")?;
unsafe { libc::dup2(new_stdout.as_raw_fd(), 1) }.syscall_result()?;
Ok(())
}