1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
#![cfg_attr(not(feature = "std"), no_std)]
use core::ffi::c_int as RawFd;
extern crate alloc;
pub mod op;
mod listenfd;
pub use listenfd::ListenFd;
/// A raw file descriptor, opened for us by the environment.
///
/// The code does assume to own it, but it won't close the file descriptor.
pub struct SharedFd {
fd: RawFd,
}
impl SharedFd {
/// Import a shared file descriptor based on environment variable `SHM_SHARED_FDS`.
///
/// # Safety
/// Caller asserts that the environment variable has been set to a file descriptor that is not
/// owned by any other resource.
#[cfg(all(feature = "std", feature = "libc"))]
pub unsafe fn from_env() -> Option<Self> {
let listen = ListenFd::new()?.ok()?;
Self::from_listen(&listen)
}
/// Import a shared file descriptor based on the contents that would be in the environment variable `SHM_SHARED_FDS`.
#[cfg(all(feature = "libc"))]
unsafe fn from_listen(var: &ListenFd) -> Option<Self> {
let num = var.names.iter().position(|v|v == "SHM_SHARED_FD")?;
let fd: RawFd = var.fd_base + num as RawFd;
let mut statbuf = unsafe { core::mem::zeroed::<libc::stat>() };
if -1 == unsafe { libc::fstat(fd, &mut statbuf) } {
// FIXME: Report that error?
return None;
}
Some(SharedFd { fd })
}
/// Open the file descriptor.
///
/// This can fail if for some reason the file descriptor does not refer to an anonymous memory
/// file.
#[cfg(all(feature = "memfile", feature = "std"))]
pub fn into_file(self) -> Result<memfile::MemFile, std::io::Error> {
let fd = self.into_raw_fd();
// It's not necessary to preserve the file descriptor here.
// It can be restored in any case.
memfile::MemFile::from_file(fd).map_err(|err| err.into_error())
}
pub fn as_raw_fd(&self) -> RawFd {
self.fd
}
pub fn into_raw_fd(self) -> RawFd {
let _this = core::mem::ManuallyDrop::new(self);
_this.fd
}
}
#[cfg(feature = "std")]
impl std::os::unix::io::AsRawFd for SharedFd {
fn as_raw_fd(&self) -> RawFd {
self.fd
}
}