use std::ffi::CStr;
use std::ffi::CString;
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
use syscalls::Errno;
pub fn to_cstring<S: AsRef<OsStr>>(s: S) -> CString {
CString::new(s.as_ref().as_bytes()).unwrap()
}
#[derive(Clone)]
pub struct CStringArray {
items: Vec<CString>,
ptrs: Vec<*const libc::c_char>,
}
impl CStringArray {
pub fn with_capacity(capacity: usize) -> Self {
let mut result = CStringArray {
items: Vec::with_capacity(capacity),
ptrs: Vec::with_capacity(capacity + 1),
};
result.ptrs.push(core::ptr::null());
result
}
pub fn push(&mut self, item: CString) {
let l = self.ptrs.len();
self.ptrs[l - 1] = item.as_ptr();
self.ptrs.push(core::ptr::null());
self.items.push(item);
}
pub fn as_ptr(&self) -> *const *const libc::c_char {
self.ptrs.as_ptr()
}
pub fn set(&mut self, i: usize, item: CString) {
self.ptrs[i] = item.as_ptr();
self.items[i] = item;
}
pub fn len(&self) -> usize {
self.items.len()
}
pub fn get(&self, i: usize) -> &CStr {
self.items[i].as_ref()
}
pub fn iter(&self) -> impl Iterator<Item = &CStr> {
self.items.iter().map(|x| x.as_ref())
}
}
impl IntoIterator for CStringArray {
type Item = CString;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.items.into_iter()
}
}
impl Extend<CString> for CStringArray {
fn extend<I>(&mut self, iter: I)
where
I: IntoIterator<Item = CString>,
{
for item in iter {
self.push(item);
}
}
}
pub unsafe fn reset_signal_handling() -> Result<(), Errno> {
unsafe {
use core::mem::MaybeUninit;
let mut set = MaybeUninit::<libc::sigset_t>::uninit();
Errno::result(libc::sigemptyset(set.as_mut_ptr()))?;
Errno::result(libc::pthread_sigmask(
libc::SIG_SETMASK,
set.as_ptr(),
core::ptr::null_mut(),
))?;
let ret = libc::signal(libc::SIGPIPE, libc::SIG_DFL);
if ret == libc::SIG_ERR {
return Err(Errno::last());
}
Ok(())
}
}
pub struct SharedValue<T> {
map: *mut T,
}
impl<T> SharedValue<T> {
pub fn new(value: T) -> Result<Self, Errno> {
let map = syscalls::Errno::result(unsafe {
libc::mmap(
core::ptr::null_mut(),
core::mem::size_of::<T>(),
libc::PROT_READ | libc::PROT_WRITE,
libc::MAP_SHARED | libc::MAP_ANONYMOUS,
-1,
0,
)
})? as *mut T;
let inner = unsafe { &mut *map };
*inner = value;
Ok(Self { map })
}
}
impl<T> Drop for SharedValue<T> {
fn drop(&mut self) {
unsafe { libc::munmap(self.map as *mut _, core::mem::size_of::<T>()) };
}
}
impl<T> core::ops::Deref for SharedValue<T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { &*self.map }
}
}
impl<T> core::ops::DerefMut for SharedValue<T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { &mut *self.map }
}
}
impl<T> AsRef<T> for SharedValue<T> {
fn as_ref(&self) -> &T {
unsafe { &*self.map }
}
}
impl<T> AsMut<T> for SharedValue<T> {
fn as_mut(&mut self) -> &mut T {
unsafe { &mut *self.map }
}
}