use crate::FdIterBuilder;
mod cloexec;
mod close;
#[derive(Clone, Debug)]
pub struct CloseFdsBuilder<'a> {
keep_fds: KeepFds<'a>,
it: FdIterBuilder,
}
impl<'a> CloseFdsBuilder<'a> {
#[inline]
pub fn new() -> Self {
Self {
keep_fds: KeepFds::empty(),
it: FdIterBuilder::new(),
}
}
#[inline]
pub fn keep_fds(&mut self, keep_fds: &'a [libc::c_int]) -> &mut Self {
self.keep_fds = KeepFds::new(keep_fds);
self
}
#[inline]
pub unsafe fn keep_fds_sorted(&mut self, keep_fds: &'a [libc::c_int]) -> &mut Self {
self.keep_fds = KeepFds::new_sorted(keep_fds);
self
}
#[inline]
pub fn threadsafe(&mut self, threadsafe: bool) -> &mut Self {
self.it.threadsafe(threadsafe);
self
}
#[inline]
pub fn allow_filesystem(&mut self, fs: bool) -> &mut Self {
self.it.allow_filesystem(fs);
self
}
pub fn cloexecfrom(&self, minfd: libc::c_int) {
cloexec::set_fds_cloexec(
core::cmp::max(minfd, 0),
self.keep_fds.clone(),
self.it.clone(),
);
}
pub unsafe fn closefrom(&self, minfd: libc::c_int) {
close::close_fds(
core::cmp::max(minfd, 0),
self.keep_fds.clone(),
self.it.clone(),
);
}
}
impl<'a> Default for CloseFdsBuilder<'a> {
#[inline]
fn default() -> Self {
Self::new()
}
}
#[derive(Clone, Debug)]
pub(crate) struct KeepFds<'a> {
fds: &'a [libc::c_int],
max: libc::c_int,
sorted: bool,
}
impl<'a> KeepFds<'a> {
#[inline]
pub fn empty() -> Self {
Self {
fds: &[],
max: -1,
sorted: true,
}
}
#[inline]
pub fn new(fds: &'a [libc::c_int]) -> Self {
let (max, sorted) = crate::util::inspect_keep_fds(fds);
Self { fds, max, sorted }
}
#[inline]
pub unsafe fn new_sorted(fds: &'a [libc::c_int]) -> Self {
Self {
fds,
max: fds.last().copied().unwrap_or(-1),
sorted: true,
}
}
}
#[inline]
pub fn set_fds_cloexec(minfd: libc::c_int, keep_fds: &[libc::c_int]) {
CloseFdsBuilder::new().keep_fds(keep_fds).cloexecfrom(minfd)
}
#[inline]
pub fn set_fds_cloexec_threadsafe(minfd: libc::c_int, keep_fds: &[libc::c_int]) {
CloseFdsBuilder::new()
.keep_fds(keep_fds)
.threadsafe(true)
.cloexecfrom(minfd)
}
pub unsafe fn close_open_fds(minfd: libc::c_int, keep_fds: &[libc::c_int]) {
CloseFdsBuilder::new().keep_fds(keep_fds).closefrom(minfd)
}