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