dope-core 0.10.1

The manifold runtime
Documentation
pub(crate) static HOST: Host = Host;

pub(crate) struct Host;

#[cfg(target_os = "linux")]
mod linux {
    use std::fs;
    use std::io::{self, Error, ErrorKind};
    use std::mem::{MaybeUninit, size_of};

    use crate::io::file::RawMetadata;
    use crate::platform::raw::file::FileLimit;
    use crate::platform::snapshot::Snapshot;

    use super::Host;

    impl Host {
        pub(crate) fn entropy(&self) -> io::Result<[u64; 2]> {
            let mut words = MaybeUninit::<[u64; 2]>::uninit();
            let mut data = words.as_mut_ptr().cast::<u8>();
            let mut len = size_of::<[u64; 2]>();
            while len != 0 {
                let written = unsafe { libc::getrandom(data.cast(), len, 0) };
                if written < 0 {
                    let error = Error::last_os_error();
                    if error.kind() == ErrorKind::Interrupted {
                        continue;
                    }
                    return Err(error);
                }
                if written == 0 {
                    return Err(Error::new(
                        ErrorKind::UnexpectedEof,
                        "kernel entropy returned no bytes",
                    ));
                }
                let written = written as usize;
                data = unsafe { data.add(written) };
                len -= written;
            }
            Ok(unsafe { words.assume_init() })
        }

        pub(crate) fn parse_meta(&self, raw: &libc::statx) -> io::Result<RawMetadata> {
            if raw.stx_mtime.tv_nsec >= 1_000_000_000 {
                return Err(Error::new(
                    ErrorKind::InvalidData,
                    "statx returned an invalid modification nanosecond",
                ));
            }
            Ok(RawMetadata {
                len: raw.stx_size,
                modified: Some((raw.stx_mtime.tv_sec, raw.stx_mtime.tv_nsec)),
                regular: u32::from(raw.stx_mode) & libc::S_IFMT == libc::S_IFREG,
            })
        }

        pub(crate) fn snapshot(&self) -> io::Result<Snapshot> {
            Ok(Snapshot {
                syncookies: read_u32("/proc/sys/net/ipv4/tcp_syncookies")? != 0,
                max_syn_backlog: read_u32("/proc/sys/net/ipv4/tcp_max_syn_backlog")?,
                somaxconn: read_u32("/proc/sys/net/core/somaxconn")?,
                rlimit_nofile: FileLimit::get()?.soft(),
            })
        }
    }

    fn read_u32(path: &str) -> io::Result<u32> {
        let value = fs::read_to_string(path)?;
        value
            .trim()
            .parse::<u32>()
            .map_err(|error| Error::new(ErrorKind::InvalidData, format!("{path}: {error}")))
    }
}

#[cfg(not(target_os = "linux"))]
mod kqueue {
    use std::ffi::CStr;
    use std::io::{self, Error, ErrorKind};
    use std::mem::{MaybeUninit, size_of};
    use std::ptr::null_mut;

    use crate::io::file::RawMetadata;
    use crate::platform::raw::file::FileLimit;
    use crate::platform::snapshot::Snapshot;

    use super::Host;

    impl Host {
        pub(crate) fn entropy(&self) -> io::Result<[u64; 2]> {
            let mut words = MaybeUninit::<[u64; 2]>::uninit();
            loop {
                if unsafe { libc::getentropy(words.as_mut_ptr().cast(), size_of::<[u64; 2]>()) }
                    == 0
                {
                    return Ok(unsafe { words.assume_init() });
                }
                let error = Error::last_os_error();
                if error.kind() != ErrorKind::Interrupted {
                    return Err(error);
                }
            }
        }

        pub(crate) fn parse_meta(&self, raw: &libc::stat) -> io::Result<RawMetadata> {
            let len = u64::try_from(raw.st_size)
                .map_err(|_| Error::new(ErrorKind::InvalidData, "stat returned a negative size"))?;
            let nanos = u32::try_from(raw.st_mtime_nsec).map_err(|_| {
                Error::new(
                    ErrorKind::InvalidData,
                    "stat returned a negative modification nanosecond",
                )
            })?;
            if nanos >= 1_000_000_000 {
                return Err(Error::new(
                    ErrorKind::InvalidData,
                    "stat returned an invalid modification nanosecond",
                ));
            }
            Ok(RawMetadata {
                len,
                modified: Some((raw.st_mtime, nanos)),
                regular: (raw.st_mode as libc::mode_t) & libc::S_IFMT == libc::S_IFREG,
            })
        }

        pub(crate) fn snapshot(&self) -> io::Result<Snapshot> {
            let somaxconn = sysctl_u32(c"kern.ipc.somaxconn")?;
            Ok(Snapshot {
                syncookies: true,
                max_syn_backlog: somaxconn,
                somaxconn,
                rlimit_nofile: FileLimit::get()?.soft(),
            })
        }
    }

    fn sysctl_u32(name: &CStr) -> io::Result<u32> {
        let mut value: libc::c_int = 0;
        let mut len = size_of::<libc::c_int>();
        let rc = unsafe {
            libc::sysctlbyname(
                name.as_ptr(),
                (&mut value as *mut libc::c_int).cast(),
                &mut len,
                null_mut(),
                0,
            )
        };
        if rc != 0 {
            return Err(Error::last_os_error());
        }
        u32::try_from(value).map_err(|_| Error::new(ErrorKind::InvalidData, "negative sysctl"))
    }
}