use crate::*;
use cfg_if::cfg_if;
use std::{convert::TryInto, ffi::CStr, mem::MaybeUninit, ops::Deref, ptr};
cfg_if! {
if #[cfg(target_os = "linux")] {
mod linux;
pub use linux::*;
}
}
#[man(umask(2))]
pub fn umask(mask: c::mode_t) -> c::mode_t {
unsafe { c::umask(mask) }
}
#[man(pipe(2))]
pub fn pipe() -> Result<(OwnedFd, OwnedFd)> {
let mut buf = [0; 2];
let res = unsafe { c::pipe(buf.as_mut_ptr()) };
map_err!(res).map(|_| (OwnedFd::new(buf[0]), OwnedFd::new(buf[1])))
}
pub struct UtsName {
buf: c::utsname,
}
impl UtsName {
pub fn sysname(&self) -> &CStr {
unsafe { CStr::from_ptr(self.buf.sysname.as_ptr()) }
}
pub fn nodename(&self) -> &CStr {
unsafe { CStr::from_ptr(self.buf.nodename.as_ptr()) }
}
pub fn release(&self) -> &CStr {
unsafe { CStr::from_ptr(self.buf.release.as_ptr()) }
}
pub fn version(&self) -> &CStr {
unsafe { CStr::from_ptr(self.buf.version.as_ptr()) }
}
pub fn machine(&self) -> &CStr {
unsafe { CStr::from_ptr(self.buf.machine.as_ptr()) }
}
}
impl Deref for UtsName {
type Target = c::utsname;
fn deref(&self) -> &Self::Target {
&self.buf
}
}
#[man(uname(2))]
pub fn uname() -> Result<UtsName> {
let mut uname = MaybeUninit::uninit();
let res = unsafe { c::uname(uname.as_mut_ptr()) };
map_err!(res).map(|_| UtsName {
buf: unsafe { uname.assume_init() },
})
}
#[man(daemon(3))]
pub fn daemon(nochdir: bool, noclose: bool) -> Result<()> {
let res = unsafe { c::daemon(nochdir as _, noclose as _) };
map_err!(res).map(drop)
}
#[man(sethostname(2))]
pub fn sethostname(buf: &[u8]) -> Result<()> {
let res = unsafe {
c::sethostname(buf.as_ptr() as *const _, buf.len().try_into().or(einval())?)
};
map_err!(res).map(drop)
}
#[man(gethostname(2))]
pub fn gethostname<T: Pod + ?Sized>(buf: &mut T) -> Result<&CStr> {
unsafe {
let buf = as_maybe_uninit_bytes_mut2(buf);
const SIZE: usize = 257;
let mut inner = MaybeUninit::<[u8; SIZE]>::uninit();
let res = c::gethostname(inner.as_mut_ptr() as *mut _, SIZE);
map_err!(res)?;
*(inner.as_mut_ptr() as *mut u8).add(SIZE - 1) = 0;
let cstr = CStr::from_ptr(inner.as_ptr() as *mut c::c_char);
let bytes = cstr.to_bytes_with_nul();
if bytes.len() < SIZE && bytes.len() <= buf.len() {
ptr::copy_nonoverlapping(
bytes.as_ptr(),
buf.as_mut_ptr() as *mut _,
bytes.len(),
);
Ok(CStr::from_bytes_with_nul_unchecked(
buf[..bytes.len()].slice_assume_init_ref(),
))
} else {
Err(Errno(c::ENAMETOOLONG))
}
}
}
#[man(sync(2))]
pub fn sync() {
unsafe { libc::sync() }
}
#[man(sysconf(3))]
pub fn sysconf(name: c::c_int) -> Result<c::c_long> {
set_errno(0);
let res = unsafe { c::sysconf(name) };
map_err!(res)
}