Skip to content

Commit 380e319

Browse files
committed
Added enum for FanotifyFidRecord event types, fixed comments, header now reads instead of copys, file_handle no longer returns pointer but returns [u8; 128]
1 parent 077234d commit 380e319

File tree

1 file changed

+48
-23
lines changed

1 file changed

+48
-23
lines changed

src/sys/fanotify.rs

Lines changed: 48 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -114,15 +114,15 @@ libc_bitflags! {
114114
/// requires the `CAP_SYS_ADMIN` capability.
115115
FAN_UNLIMITED_MARKS;
116116

117-
/// Make `FanotifyEvent::pid` return pidfd. Since Linux 5.15.
117+
/// Make [`FanotifyEvent::pid()`] return pidfd. Since Linux 5.15.
118118
FAN_REPORT_PIDFD;
119-
/// Make `FanotifyEvent::pid` return thread id. Since Linux 4.20.
119+
/// Make [`FanotifyEvent::pid()`] return thread id. Since Linux 4.20.
120120
FAN_REPORT_TID;
121121

122122
/// Allows the receipt of events which contain additional information
123123
/// about the underlying filesystem object correlated to an event.
124124
///
125-
/// This will make `FanotifyEvent::fd` return `FAN_NOFD`.
125+
/// This will make [`FanotifyEvent::fd()`] return `None`.
126126
/// This should be used with `Fanotify::read_events_with_info_records` to
127127
/// recieve `FanotifyInfoRecord::Fid` info records.
128128
/// Since Linux 5.1
@@ -131,7 +131,7 @@ libc_bitflags! {
131131
/// Allows the receipt of events which contain additional information
132132
/// about the underlying filesystem object correlated to an event.
133133
///
134-
/// This will make `FanotifyEvent::fd` return `FAN_NOFD`.
134+
/// This will make [`FanotifyEvent::fd()`] return `None`.
135135
/// This should be used with `Fanotify::read_events_with_info_records` to
136136
/// recieve `FanotifyInfoRecord::Fid` info records.
137137
///
@@ -235,9 +235,26 @@ libc_bitflags! {
235235
}
236236
}
237237

238+
libc_enum! {
239+
/// All possible Fanotify event types that result in a FanotifyFidRecord
240+
#[repr(u8)]
241+
#[non_exhaustive]
242+
pub enum FanotifyFidEventInfoType {
243+
FAN_EVENT_INFO_TYPE_FID,
244+
FAN_EVENT_INFO_TYPE_DFID,
245+
FAN_EVENT_INFO_TYPE_DFID_NAME,
246+
FAN_EVENT_INFO_TYPE_OLD_DFID_NAME,
247+
FAN_EVENT_INFO_TYPE_NEW_DFID_NAME,
248+
}
249+
impl TryFrom<u8>
250+
}
251+
238252
/// Compile version number of fanotify API.
239253
pub const FANOTIFY_METADATA_VERSION: u8 = libc::FANOTIFY_METADATA_VERSION;
240254

255+
/// Maximum file_handle size
256+
pub const MAX_HANDLE_SZ: usize = 128;
257+
241258
/// Abstract over [`libc::fanotify_event_info_fid`], which represents an
242259
/// information record received via [`Fanotify::read_events_with_info_records`].
243260
#[derive(Debug, Eq, Hash, PartialEq)]
@@ -254,7 +271,7 @@ pub struct LibcFanotifyFidRecord(libc::fanotify_event_info_fid);
254271
#[allow(missing_copy_implementations)]
255272
pub struct FanotifyFidRecord {
256273
record: LibcFanotifyFidRecord,
257-
handle_bytes: *const u8,
274+
file_handle_bytes: [u8; MAX_HANDLE_SZ],
258275
}
259276

260277
impl FanotifyFidRecord {
@@ -270,15 +287,15 @@ impl FanotifyFidRecord {
270287
/// represented as a 0-length u8 array, but it actually points to variable-length
271288
/// file_handle struct.For more information:
272289
/// <https://man7.org/linux/man-pages/man2/open_by_handle_at.2.html>
273-
pub fn handle(&self) -> *const u8 {
274-
self.handle_bytes
290+
pub fn handle(&self) -> [u8; MAX_HANDLE_SZ] {
291+
self.file_handle_bytes
275292
}
276293

277294
/// The specific info_type for this Fid Record. Fanotify can return an Fid Record
278295
/// with many different possible info_types. The info_type is not always necessary
279296
/// but can be useful for connecting similar events together (like a FAN_RENAME)
280-
pub fn info_type(&self) -> u8 {
281-
self.record.0.hdr.info_type
297+
pub fn info_type(&self) -> FanotifyFidEventInfoType {
298+
FanotifyFidEventInfoType::try_from(self.record.0.hdr.info_type).unwrap()
282299
}
283300
}
284301

@@ -348,10 +365,9 @@ impl Drop for FanotifyPidfdRecord {
348365
/// After a [`libc::fanotify_event_metadata`], there can be 0 or more event_info
349366
/// structs depending on which InitFlags were used in [`Fanotify::init`].
350367
// Is not Clone due to pidfd in `libc::fanotify_event_info_pidfd`
351-
// Other fanotify_event_info records are not implemented as they don't exist in
352-
// the libc crate yet.
353368
#[derive(Debug, Eq, Hash, PartialEq)]
354369
#[allow(missing_copy_implementations)]
370+
#[non_exhaustive]
355371
pub enum FanotifyInfoRecord {
356372
/// A [`libc::fanotify_event_info_fid`] event was recieved, usually as
357373
/// a result of passing [`InitFlags::FAN_REPORT_FID`] or [`InitFlags::FAN_REPORT_DIR_FID`]
@@ -612,13 +628,11 @@ impl Fanotify {
612628
let mut current_event_offset = offset + metadata_size;
613629

614630
while remaining_len > 0 {
615-
let header = self
616-
.get_struct::<libc::fanotify_event_info_header>(
617-
&buffer,
618-
current_event_offset,
619-
);
631+
let header_info_type = unsafe { buffer.as_ptr().add(current_event_offset).read() };
632+
// The +2 here represents the offset between the info_type and the length (which is 2 u8s apart)
633+
let info_type_length = unsafe { buffer.as_ptr().add(current_event_offset + 2).read() };
620634

621-
let info_record = match header.info_type {
635+
let info_record = match header_info_type {
622636
// FanotifyFidRecord can be returned for any of the following info_type.
623637
// This isn't found in the fanotify(7) documentation, but the fanotify_init(2) documentation
624638
// https://man7.org/linux/man-pages/man2/fanotify_init.2.html
@@ -638,11 +652,24 @@ impl Fanotify {
638652
as *const libc::fanotify_event_info_fid
639653
};
640654

641-
let file_handle_ptr = unsafe { record_ptr.add(1) as *const u8 };
655+
let file_handle = unsafe {
656+
let file_handle_ptr = record_ptr.add(1) as *const u8;
657+
let mut file_handle = MaybeUninit::<[u8; MAX_HANDLE_SZ]>::uninit();
658+
659+
// Read the entire file_handle. The struct can be found here:
660+
// https://man7.org/linux/man-pages/man2/open_by_handle_at.2.html
661+
let file_handle_length = size_of::<u32>() + size_of::<i32>() + file_handle_ptr.cast::<u32>().read() as usize;
662+
std::ptr::copy_nonoverlapping(
663+
file_handle_ptr,
664+
file_handle.as_mut_ptr().cast(),
665+
(file_handle_length).min(MAX_HANDLE_SZ),
666+
);
667+
file_handle.assume_init()
668+
};
642669

643670
Some(FanotifyInfoRecord::Fid(FanotifyFidRecord {
644671
record: LibcFanotifyFidRecord(record),
645-
handle_bytes: file_handle_ptr,
672+
file_handle_bytes: file_handle,
646673
}))
647674
}
648675
#[cfg(target_env = "gnu")]
@@ -676,12 +703,10 @@ impl Fanotify {
676703
info_records.push(record);
677704
}
678705

679-
remaining_len -= header.len as u32;
680-
current_event_offset += header.len as usize;
706+
remaining_len -= info_type_length as u32;
707+
current_event_offset += info_type_length as usize;
681708
}
682709

683-
// libc::fanotify_event_info_header
684-
685710
events.push((FanotifyEvent(metadata), info_records));
686711
offset += metadata.event_len as usize;
687712
}

0 commit comments

Comments
 (0)