| 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 ] |
| 38 | pub fn should_not_close(&self) { |
| 39 | self.close_on_drop.store(val:false, order:Ordering::Release); |
| 40 | } |
| 41 | } |
| 42 | |
| 43 | impl Deref for FdGuard { |
| 44 | type Target = RawFd; |
| 45 | |
| 46 | #[inline ] |
| 47 | fn deref(&self) -> &Self::Target { |
| 48 | &self.fd |
| 49 | } |
| 50 | } |
| 51 | |
| 52 | impl Drop for FdGuard { |
| 53 | fn drop(&mut self) { |
| 54 | if self.close_on_drop.load(order:Ordering::Acquire) { |
| 55 | unsafe { ffi::close(self.fd); } |
| 56 | } |
| 57 | } |
| 58 | } |
| 59 | |
| 60 | impl FromRawFd for FdGuard { |
| 61 | 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 { |
| 70 | fn into_raw_fd(self) -> RawFd { |
| 71 | self.should_not_close(); |
| 72 | self.fd |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | impl AsRawFd for FdGuard { |
| 77 | fn as_raw_fd(&self) -> RawFd { |
| 78 | self.fd |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | impl AsFd for FdGuard { |
| 83 | #[inline ] |
| 84 | fn as_fd(&self) -> BorrowedFd<'_> { |
| 85 | unsafe { BorrowedFd::borrow_raw(self.fd) } |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | impl PartialEq for FdGuard { |
| 90 | fn eq(&self, other: &FdGuard) -> bool { |
| 91 | self.fd == other.fd |
| 92 | } |
| 93 | } |
| 94 | |