1 use std::{ 2 ops::Deref, 3 os::unix::io::{ 4 AsFd, 5 AsRawFd, 6 BorrowedFd, 7 FromRawFd, 8 IntoRawFd, 9 RawFd, 10 }, 11 sync::atomic::{ 12 AtomicBool, 13 Ordering, 14 }, 15 }; 16 17 use inotify_sys as ffi; 18 19 20 /// A RAII guard around a `RawFd` that closes it automatically on drop. 21 #[derive(Debug)] 22 pub struct FdGuard { 23 pub(crate) fd : RawFd, 24 pub(crate) close_on_drop: AtomicBool, 25 } 26 27 impl FdGuard { 28 29 /// Indicate that the wrapped file descriptor should _not_ be closed 30 /// when the guard is dropped. 31 /// 32 /// This should be called in cases where ownership of the wrapped file 33 /// descriptor has been "moved" out of the guard. 34 /// 35 /// This is factored out into a separate function to ensure that it's 36 /// always used consistently. 37 #[inline] should_not_close(&self)38 pub fn should_not_close(&self) { 39 self.close_on_drop.store(false, Ordering::Release); 40 } 41 } 42 43 impl Deref for FdGuard { 44 type Target = RawFd; 45 46 #[inline] deref(&self) -> &Self::Target47 fn deref(&self) -> &Self::Target { 48 &self.fd 49 } 50 } 51 52 impl Drop for FdGuard { drop(&mut self)53 fn drop(&mut self) { 54 if self.close_on_drop.load(Ordering::Acquire) { 55 unsafe { ffi::close(self.fd); } 56 } 57 } 58 } 59 60 impl FromRawFd for FdGuard { from_raw_fd(fd: RawFd) -> Self61 unsafe fn from_raw_fd(fd: RawFd) -> Self { 62 FdGuard { 63 fd, 64 close_on_drop: AtomicBool::new(true), 65 } 66 } 67 } 68 69 impl IntoRawFd for FdGuard { into_raw_fd(self) -> RawFd70 fn into_raw_fd(self) -> RawFd { 71 self.should_not_close(); 72 self.fd 73 } 74 } 75 76 impl AsRawFd for FdGuard { as_raw_fd(&self) -> RawFd77 fn as_raw_fd(&self) -> RawFd { 78 self.fd 79 } 80 } 81 82 impl AsFd for FdGuard { 83 #[inline] as_fd(&self) -> BorrowedFd<'_>84 fn as_fd(&self) -> BorrowedFd<'_> { 85 unsafe { BorrowedFd::borrow_raw(self.fd) } 86 } 87 } 88 89 impl PartialEq for FdGuard { eq(&self, other: &FdGuard) -> bool90 fn eq(&self, other: &FdGuard) -> bool { 91 self.fd == other.fd 92 } 93 } 94