|
| 1 | +//! inotify support for working with inotifies |
| 2 | +
|
| 3 | +use super::super::c; |
| 4 | +use super::super::conv::{borrowed_fd, c_str, ret, ret_c_int, ret_owned_fd}; |
| 5 | +use crate::fd::{BorrowedFd, OwnedFd}; |
| 6 | +use crate::io; |
| 7 | +use bitflags::bitflags; |
| 8 | + |
| 9 | +bitflags! { |
| 10 | + /// `IN_*` for use with [`Inotify::new`]. |
| 11 | + pub struct CreateFlags: c::c_int { |
| 12 | + /// `IN_CLOEXEC` |
| 13 | + const CLOEXEC = c::IN_CLOEXEC; |
| 14 | + /// `IN_NONBLOCK` |
| 15 | + const NONBLOCK = c::IN_NONBLOCK; |
| 16 | + } |
| 17 | +} |
| 18 | + |
| 19 | +bitflags! { |
| 20 | + /// `IN*` for use with [`Inotify::add_watch`]. |
| 21 | + #[derive(Default)] |
| 22 | + pub struct WatchFlags: u32 { |
| 23 | + /// `IN_ACCESS` |
| 24 | + const ACCESS = c::IN_ACCESS; |
| 25 | + /// `IN_ATTRIB` |
| 26 | + const ATTRIB = c::IN_ATTRIB; |
| 27 | + /// `IN_CLOSE_NOWRITE` |
| 28 | + const CLOSE_NOWRITE = c::IN_CLOSE_NOWRITE; |
| 29 | + /// `IN_CLOSE_WRITE` |
| 30 | + const CLOSE_WRITE = c::IN_CLOSE_WRITE; |
| 31 | + /// `IN_CREATE ` |
| 32 | + const CREATE = c::IN_CREATE; |
| 33 | + /// `IN_DELETE` |
| 34 | + const DELETE = c::IN_DELETE; |
| 35 | + /// `IN_DELETE_SELF` |
| 36 | + const DELETE_SELF = c::IN_DELETE_SELF; |
| 37 | + /// `IN_MODIFY` |
| 38 | + const MODIFY = c::IN_MODIFY; |
| 39 | + /// `IN_MOVE_SELF` |
| 40 | + const MOVE_SELF = c::IN_MOVE_SELF; |
| 41 | + /// `IN_MOVED_FROM` |
| 42 | + const MOVED_FROM = c::IN_MOVED_FROM; |
| 43 | + /// `IN_MOVED_TO` |
| 44 | + const MOVED_TO = c::IN_MOVED_TO; |
| 45 | + /// `IN_OPEN` |
| 46 | + const OPEN = c::IN_OPEN; |
| 47 | + |
| 48 | + /// `IN_CLOSE` |
| 49 | + const CLOSE = c::IN_CLOSE; |
| 50 | + /// `IN_MOVE` |
| 51 | + const MOVE = c::IN_MOVE; |
| 52 | + /// `IN_ALL_EVENTS` |
| 53 | + const ALL_EVENTS = c::IN_ALL_EVENTS; |
| 54 | + |
| 55 | + /// `IN_DONT_FOLLOW` |
| 56 | + const DONT_FOLLOW = c::IN_DONT_FOLLOW; |
| 57 | + /// `IN_EXCL_UNLINK` |
| 58 | + const EXCL_UNLINK = 1; |
| 59 | + /// `IN_MASK_ADD` |
| 60 | + const MASK_ADD = 1; |
| 61 | + /// `IN_MASK_CREATE` |
| 62 | + const MASK_CREATE = 1; |
| 63 | + /// `IN_ONESHOT` |
| 64 | + const ONESHOT = c::IN_ONESHOT; |
| 65 | + /// `IN_ONLYDIR` |
| 66 | + const ONLYDIR = c::IN_ONLYDIR; |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +/// `inotify_init1(flags)`—Creates a new `Inotify`. |
| 71 | +/// |
| 72 | +/// Use the [`CreateFlags::CLOEXEC`] flag to prevent the resulting file |
| 73 | +/// descriptor from being implicitly passed across `exec` boundaries. |
| 74 | +#[doc(alias = "inotify_init1")] |
| 75 | +pub fn inotify_init(flags: CreateFlags) -> io::Result<OwnedFd> { |
| 76 | + // Safety: `inotify_init1` has no safety preconditions. |
| 77 | + unsafe { ret_owned_fd(c::inotify_init1(flags.bits())) } |
| 78 | +} |
| 79 | + |
| 80 | +/// `inotify_add_watch(self, path, flags)`-Adds a watch to inotify |
| 81 | +/// |
| 82 | +/// This registers or updates a watch for the filesystem path `path` |
| 83 | +/// and returns a watch descriptor corresponding to this watch. |
| 84 | +/// |
| 85 | +/// Note: Due to the existence of hardlinks, providing two |
| 86 | +/// different paths to this method may result in it returning |
| 87 | +/// the same watch descriptor. An application should keep track of this |
| 88 | +/// externally to avoid logic errors. |
| 89 | +pub fn inotify_add_watch<P: crate::path::Arg>( |
| 90 | + inot: BorrowedFd<'_>, |
| 91 | + path: P, |
| 92 | + flags: WatchFlags, |
| 93 | +) -> io::Result<i32> { |
| 94 | + let path = path.as_cow_c_str().unwrap(); |
| 95 | + // Safety: The fd and path we are passing is guranteed valid by the type system. |
| 96 | + unsafe { |
| 97 | + ret_c_int(c::inotify_add_watch( |
| 98 | + borrowed_fd(inot), |
| 99 | + c_str(&path), |
| 100 | + flags.bits(), |
| 101 | + )) |
| 102 | + } |
| 103 | +} |
| 104 | + |
| 105 | +/// `inotify_rm_watch(self, wd)`-Removes a watch from this inotify |
| 106 | +/// |
| 107 | +/// The watch descriptor provided should have previously been returned |
| 108 | +/// by [`Self::add_watch()`] and not previously have been removed. |
| 109 | +#[doc(alias = "inotify_rm_watch")] |
| 110 | +pub fn inotify_remove_watch<P: crate::path::Arg>(inot: BorrowedFd<'_>, wd: i32) -> io::Result<()> { |
| 111 | + // Android's `inotify_rm_watch` takes u32 despite `inotify_add_watch` is i32. |
| 112 | + #[cfg(target_os = "android")] |
| 113 | + let wd = wd as u32; |
| 114 | + // Safety: The fd is valid and closing an arbitrary wd is valid. |
| 115 | + unsafe { ret(c::inotify_rm_watch(borrowed_fd(inot), wd)) } |
| 116 | +} |
0 commit comments