summaryrefslogtreecommitdiffstats
path: root/vendor/rustix/src/backend/libc/fs/inotify.rs
blob: fea2fad0625e05e38e6f9ce9d13b99fe50b0cda1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//! inotify support for working with inotifies

use crate::backend::c;
use crate::backend::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_owned_fd};
use crate::fd::{BorrowedFd, OwnedFd};
use crate::io;
use bitflags::bitflags;

bitflags! {
    /// `IN_*` for use with [`inotify_init`].
    ///
    /// [`inotify_init`]: crate::fs::inotify::inotify_init
    #[repr(transparent)]
    #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
    pub struct CreateFlags: u32 {
        /// `IN_CLOEXEC`
        const CLOEXEC = bitcast!(c::IN_CLOEXEC);
        /// `IN_NONBLOCK`
        const NONBLOCK = bitcast!(c::IN_NONBLOCK);

        /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
        const _ = !0;
    }
}

bitflags! {
    /// `IN*` for use with [`inotify_add_watch`].
    ///
    /// [`inotify_add_watch`]: crate::fs::inotify::inotify_add_watch
    #[repr(transparent)]
    #[derive(Default, Copy, Clone, Eq, PartialEq, Hash, Debug)]
    pub struct WatchFlags: u32 {
        /// `IN_ACCESS`
        const ACCESS = c::IN_ACCESS;
        /// `IN_ATTRIB`
        const ATTRIB = c::IN_ATTRIB;
        /// `IN_CLOSE_NOWRITE`
        const CLOSE_NOWRITE = c::IN_CLOSE_NOWRITE;
        /// `IN_CLOSE_WRITE`
        const CLOSE_WRITE = c::IN_CLOSE_WRITE;
        /// `IN_CREATE `
        const CREATE = c::IN_CREATE;
        /// `IN_DELETE`
        const DELETE = c::IN_DELETE;
        /// `IN_DELETE_SELF`
        const DELETE_SELF = c::IN_DELETE_SELF;
        /// `IN_MODIFY`
        const MODIFY = c::IN_MODIFY;
        /// `IN_MOVE_SELF`
        const MOVE_SELF = c::IN_MOVE_SELF;
        /// `IN_MOVED_FROM`
        const MOVED_FROM = c::IN_MOVED_FROM;
        /// `IN_MOVED_TO`
        const MOVED_TO = c::IN_MOVED_TO;
        /// `IN_OPEN`
        const OPEN = c::IN_OPEN;

        /// `IN_CLOSE`
        const CLOSE = c::IN_CLOSE;
        /// `IN_MOVE`
        const MOVE = c::IN_MOVE;
        /// `IN_ALL_EVENTS`
        const ALL_EVENTS = c::IN_ALL_EVENTS;

        /// `IN_DONT_FOLLOW`
        const DONT_FOLLOW = c::IN_DONT_FOLLOW;
        /// `IN_EXCL_UNLINK`
        const EXCL_UNLINK = 1;
        /// `IN_MASK_ADD`
        const MASK_ADD = 1;
        /// `IN_MASK_CREATE`
        const MASK_CREATE = 1;
        /// `IN_ONESHOT`
        const ONESHOT = c::IN_ONESHOT;
        /// `IN_ONLYDIR`
        const ONLYDIR = c::IN_ONLYDIR;

        /// <https://docs.rs/bitflags/latest/bitflags/#externally-defined-flags>
        const _ = !0;
    }
}

/// `inotify_init1(flags)`—Creates a new inotify object.
///
/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file
/// descriptor from being implicitly passed across `exec` boundaries.
#[doc(alias = "inotify_init1")]
pub fn inotify_init(flags: CreateFlags) -> io::Result<OwnedFd> {
    // SAFETY: `inotify_init1` has no safety preconditions.
    unsafe { ret_owned_fd(c::inotify_init1(bitflags_bits!(flags))) }
}

/// `inotify_add_watch(self, path, flags)`—Adds a watch to inotify
///
/// This registers or updates a watch for the filesystem path `path`
/// and returns a watch descriptor corresponding to this watch.
///
/// Note: Due to the existence of hardlinks, providing two
/// different paths to this method may result in it returning
/// the same watch descriptor. An application should keep track of this
/// externally to avoid logic errors.
pub fn inotify_add_watch<P: crate::path::Arg>(
    inot: BorrowedFd<'_>,
    path: P,
    flags: WatchFlags,
) -> io::Result<i32> {
    path.into_with_c_str(|path| {
        // SAFETY: The fd and path we are passing is guaranteed valid by the type
        // system.
        unsafe {
            ret_c_int(c::inotify_add_watch(
                borrowed_fd(inot),
                c_str(path),
                flags.bits(),
            ))
        }
    })
}

/// `inotify_rm_watch(self, wd)`—Removes a watch from this inotify
///
/// The watch descriptor provided should have previously been returned by
/// [`inotify_add_watch`] and not previously have been removed.
#[doc(alias = "inotify_rm_watch")]
pub fn inotify_remove_watch(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> {
    // Android's `inotify_rm_watch` takes `u32` despite that
    // `inotify_add_watch` expects a `i32`.
    #[cfg(target_os = "android")]
    let wd = wd as u32;
    // SAFETY: The fd is valid and closing an arbitrary wd is valid.
    unsafe { ret(c::inotify_rm_watch(borrowed_fd(inot), wd)) }
}