inotify/
fd_guard.rs

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