use std::ffi::CString;
use std::fs::File;
use std::io;
use std::os::unix::io::{AsRawFd, FromRawFd};
pub fn openat(dir_fd: &impl AsRawFd, path: &str, flags: libc::c_int) -> io::Result<File> {
let path_cstr =
CString::new(path).map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
let fd = unsafe { libc::openat(dir_fd.as_raw_fd(), path_cstr.as_ptr(), flags) };
if fd >= 0 {
Ok(unsafe { File::from_raw_fd(fd) })
} else {
Err(io::Error::last_os_error())
}
}
pub fn reopen_fd_through_proc(
fd: &impl AsRawFd,
flags: libc::c_int,
proc_self_fd: &File,
) -> io::Result<File> {
openat(
proc_self_fd,
format!("{}", fd.as_raw_fd()).as_str(),
flags & !libc::O_NOFOLLOW,
)
}
pub fn is_safe_inode(mode: u32) -> bool {
matches!(mode & libc::S_IFMT, libc::S_IFREG | libc::S_IFDIR)
}
pub fn ebadf() -> io::Error {
io::Error::from_raw_os_error(libc::EBADF)
}
pub fn einval() -> io::Error {
io::Error::from_raw_os_error(libc::EINVAL)
}