1#![cfg(unix)]
5#![expect(unsafe_code)]
7
8pub mod affinity;
9pub mod pipe;
10pub mod process;
11pub mod pthread;
12
13use std::fs::File;
14use std::io;
15use std::io::Error;
16use std::os::unix::prelude::*;
17
18#[derive(Copy, Clone, PartialEq, Eq)]
20pub struct Errno(pub i32);
21
22impl std::fmt::Debug for Errno {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 std::fmt::Debug::fmt(&Error::from(*self), f)
25 }
26}
27
28impl From<Errno> for Error {
29 fn from(code: Errno) -> Self {
30 Self::from_raw_os_error(code.0)
31 }
32}
33
34pub trait TryAsErrno {
36 fn try_as_errno(&self) -> Option<Errno>;
38}
39
40impl TryAsErrno for Errno {
41 fn try_as_errno(&self) -> Option<Errno> {
42 Some(*self)
43 }
44}
45
46impl TryAsErrno for Error {
47 fn try_as_errno(&self) -> Option<Errno> {
48 self.raw_os_error().map(Errno)
49 }
50}
51
52pub(crate) fn errno() -> Errno {
54 Errno(Error::last_os_error().raw_os_error().unwrap())
55}
56
57pub trait SyscallResult: Sized {
59 fn syscall_result(self) -> Result<Self, Errno>;
61}
62
63impl SyscallResult for i32 {
64 fn syscall_result(self) -> Result<Self, Errno> {
65 if self >= 0 { Ok(self) } else { Err(errno()) }
66 }
67}
68
69impl SyscallResult for isize {
70 fn syscall_result(self) -> Result<Self, Errno> {
71 if self >= 0 { Ok(self) } else { Err(errno()) }
72 }
73}
74
75pub fn while_eintr<F, R, E>(mut f: F) -> Result<R, E>
77where
78 F: FnMut() -> Result<R, E>,
79 E: TryAsErrno,
80{
81 loop {
82 match f() {
83 Err(err) if err.try_as_errno() == Some(Errno(libc::EINTR)) => {}
84 r => break r,
85 }
86 }
87}
88
89pub fn close_stdout() -> io::Result<()> {
91 let new_stdout = File::open("/dev/null")?;
92 unsafe { libc::dup2(new_stdout.as_raw_fd(), 1) }.syscall_result()?;
94 Ok(())
95}