inotify/util.rs
1use std::{io, mem, os::unix::io::RawFd, path::Path};
2
3use inotify_sys as ffi;
4use libc::{c_void, size_t};
5
6const INOTIFY_EVENT_SIZE: usize = mem::size_of::<ffi::inotify_event>() + 257;
7
8pub fn read_into_buffer(fd: RawFd, buffer: &mut [u8]) -> isize {
9 unsafe {
10 ffi::read(
11 fd,
12 buffer.as_mut_ptr() as *mut c_void,
13 buffer.len() as size_t,
14 )
15 }
16}
17
18/// Get the inotify event buffer size
19///
20/// The maximum size of an inotify event and thus the buffer size to hold it
21/// can be calculated using this formula:
22/// `sizeof(struct inotify_event) + NAME_MAX + 1`
23///
24/// See: <https://man7.org/linux/man-pages/man7/inotify.7.html>
25///
26/// The NAME_MAX size formula is:
27/// `ABSOLUTE_PARENT_PATH_LEN + 1 + 255`
28///
29/// - `ABSOLUTE_PARENT_PATH_LEN` will be calculated at runtime.
30/// - Add 1 to account for a `/`, either in between the parent path and a filename or for the root directory.
31/// - Add the maximum number of chars in a filename, 255.
32///
33/// See: <https://github.com/torvalds/linux/blob/master/include/uapi/linux/limits.h>
34///
35/// Unfortunately, we can't just do the same with max path length itself.
36///
37/// See: <https://eklitzke.org/path-max-is-tricky>
38///
39/// This function is really just a fallible wrapper around `get_absolute_path_buffer_size()`.
40///
41/// path: A relative or absolute path for the inotify events.
42pub fn get_buffer_size(path: &Path) -> io::Result<usize> {
43 Ok(get_absolute_path_buffer_size(&path.canonicalize()?))
44}
45
46/// Get the inotify event buffer size for an absolute path
47///
48/// For relative paths, consider using `get_buffer_size()` which provides a fallible wrapper
49/// for this function.
50///
51/// path: An absolute path for the inotify events.
52pub fn get_absolute_path_buffer_size(path: &Path) -> usize {
53 // Get the length of the absolute parent path, if the path is not the root directory.
54 // Because we canonicalize the path, we do not need to worry about prefixes.
55 let parent_path_len = path
56 .parent()
57 .map(|parent_path| parent_path.as_os_str().len())
58 .unwrap_or(0);
59
60 INOTIFY_EVENT_SIZE + parent_path_len
61}