use libc::{syscall, SYS_pidfd_getfd};
use pidfd::PidFd;
use std::{
fs::File,
io::{self, Result as IoResult},
os::unix::prelude::{AsRawFd, FromRawFd, RawFd},
};
#[cfg(feature = "nightly")]
use std::os::linux::process::PidFd as StdPidFd;
#[derive(Clone, Copy)]
#[non_exhaustive]
pub struct GetFdFlags;
impl GetFdFlags {
pub const fn empty() -> Self {
Self
}
pub const fn bits(&self) -> u32 {
0
}
}
pub trait PidFdExt {
fn get_file(&self, target_fd: RawFd, flags: GetFdFlags) -> IoResult<File>;
}
impl PidFdExt for PidFd {
fn get_file(&self, target_fd: RawFd, flags: GetFdFlags) -> IoResult<File> {
get_file_from_pidfd(self.as_raw_fd(), target_fd, flags)
}
}
#[cfg(feature = "nightly")]
impl PidFdExt for StdPidFd {
fn get_file(&self, target_fd: RawFd, flags: GetFdFlags) -> IoResult<File> {
get_file_from_pidfd(self.as_raw_fd(), target_fd, flags)
}
}
pub fn get_file_from_pidfd(pidfd: RawFd, target_fd: RawFd, flags: GetFdFlags) -> IoResult<File> {
let res = unsafe { pidfd_getfd(pidfd, target_fd, flags.bits()) };
if res == -1 {
Err(io::Error::last_os_error())
} else {
Ok(unsafe { File::from_raw_fd(res) })
}
}
pub unsafe fn pidfd_getfd(
pidfd: libc::c_int,
targetfd: libc::c_int,
flags: libc::c_uint,
) -> libc::c_int {
unsafe { syscall(SYS_pidfd_getfd, pidfd, targetfd, flags) as libc::c_int }
}