#![forbid(unsafe_op_in_unsafe_fn)] use std::{ os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, OwnedFd, RawFd}, path::PathBuf, sync::Arc, }; /// Ref-counted file descriptor of an open device node #[derive(Debug, Clone)] pub struct DeviceFd(Arc); impl PartialEq for DeviceFd { #[inline] fn eq(&self, other: &Self) -> bool { self.0.as_raw_fd() == other.0.as_raw_fd() } } impl AsFd for DeviceFd { #[inline] fn as_fd(&self) -> BorrowedFd<'_> { self.0.as_fd() } } // TODO: drop impl once not needed anymore by smithay or dependencies impl AsRawFd for DeviceFd { #[inline] fn as_raw_fd(&self) -> RawFd { self.0.as_raw_fd() } } impl FromRawFd for DeviceFd { /// SAFETY: /// Make sure that `fd` is a valid value! #[inline] unsafe fn from_raw_fd(fd: RawFd) -> Self { DeviceFd(Arc::new(unsafe { OwnedFd::from_raw_fd(fd) })) } } impl From for DeviceFd { #[inline] fn from(fd: OwnedFd) -> Self { DeviceFd(Arc::new(fd)) } } impl TryInto for DeviceFd { type Error = DeviceFd; #[inline] fn try_into(self) -> Result { Arc::try_unwrap(self.0).map_err(DeviceFd) } } /// Trait representing open devices that *may* return a `Path` pub trait DevPath { /// Returns the path of the open device if possible fn dev_path(&self) -> Option; } impl DevPath for A { fn dev_path(&self) -> Option { use std::fs; fs::read_link(format!("/proc/self/fd/{:?}", self.as_fd().as_raw_fd())).ok() } }