@@ -238,13 +238,89 @@ libc_bitflags! {
238238/// Compile version number of fanotify API.
239239pub const FANOTIFY_METADATA_VERSION : u8 = libc:: FANOTIFY_METADATA_VERSION ;
240240
241- /// Abstract over [`libc::fanotify_event_metadata `], which represents an event
242- /// received via [`Fanotify::read_events `].
241+ /// Abstract over [`libc::fanotify_event_info_fid `], which represents an
242+ /// information record received via [`Fanotify::read_events_with_info_records `].
243243// Is not Clone due to fd field, to avoid use-after-close scenarios.
244244#[ derive( Debug , Eq , Hash , PartialEq ) ]
245245#[ repr( transparent) ]
246246#[ allow( missing_copy_implementations) ]
247- pub struct FanotifyEvent ( libc:: fanotify_event_metadata ) ;
247+ pub struct FanotifyFidRecord ( libc:: fanotify_event_info_fid ) ;
248+
249+ impl FanotifyFidRecord {
250+ /// The filesystem id where this event occurred. The value this method returns
251+ /// differs depending on the host system. Please read the statfs(2) documentation
252+ /// for more information:
253+ /// https://man7.org/linux/man-pages/man2/statfs.2.html#VERSIONS
254+ pub fn fsid ( & self ) -> libc:: __kernel_fsid_t {
255+ self . 0 . fsid
256+ }
257+
258+ /// The file handle for the filesystem object where the event occurred. The handle is
259+ /// represented as a 0-length u8 array, but it actually points to variable-length
260+ /// file_handle struct.For more information:
261+ /// https://man7.org/linux/man-pages/man2/open_by_handle_at.2.html
262+ pub fn handle ( & self ) -> [ u8 ; 0 ] {
263+ self . 0 . handle
264+ }
265+ }
266+
267+ /// Abstract over [`libc::fanotify_event_info_error`], which represents an
268+ /// information record received via [`Fanotify::read_events_with_info_records`].
269+ // Is not Clone due to fd field, to avoid use-after-close scenarios.
270+ #[ derive( Debug , Eq , Hash , PartialEq ) ]
271+ #[ repr( transparent) ]
272+ #[ allow( missing_copy_implementations) ]
273+ pub struct FanotifyErrorRecord ( libc:: fanotify_event_info_error ) ;
274+
275+ impl FanotifyErrorRecord {
276+ /// Errno of the FAN_FS_ERROR that occurred.
277+ pub fn err ( & self ) -> Errno {
278+ Errno :: from_raw ( self . 0 . error )
279+ }
280+
281+ /// Number of errors that occurred in the filesystem Fanotify in watching.
282+ /// Only a single FAN_FS_ERROR is stored per filesystem at once. As such, Fanotify
283+ /// suppresses subsequent error messages and only increments the `err_count` value.
284+ pub fn err_count ( & self ) -> u32 {
285+ self . 0 . error_count
286+ }
287+ }
288+
289+ /// Abstract over [`libc::fanotify_event_info_pidfd`], which represents an
290+ /// information record received via [`Fanotify::read_events_with_info_records`].
291+ // Is not Clone due to fd field, to avoid use-after-close scenarios.
292+ #[ derive( Debug , Eq , Hash , PartialEq ) ]
293+ #[ repr( transparent) ]
294+ #[ allow( missing_copy_implementations) ]
295+ pub struct FanotifyPidfdRecord ( libc:: fanotify_event_info_pidfd ) ;
296+
297+ impl FanotifyPidfdRecord {
298+ /// The process file descriptor that refers to the process responsible for
299+ /// generating this event. If the underlying pidfd_create fails, `None` is returned.
300+ pub fn pidfd ( & self ) -> Option < BorrowedFd > {
301+ if self . 0 . pidfd == libc:: FAN_NOPIDFD || self . 0 . pidfd == libc:: FAN_EPIDFD
302+ {
303+ None
304+ } else {
305+ // SAFETY: self.0.pidfd will be opened for the lifetime of `Self`,
306+ // which is longer than the lifetime of the returned BorrowedFd, so
307+ // it is safe.
308+ Some ( unsafe { BorrowedFd :: borrow_raw ( self . 0 . pidfd ) } )
309+ }
310+ }
311+ }
312+
313+ impl Drop for FanotifyPidfdRecord {
314+ fn drop ( & mut self ) {
315+ if self . 0 . pidfd == libc:: FAN_NOFD {
316+ return ;
317+ }
318+ let e = close ( self . 0 . pidfd ) ;
319+ if !std:: thread:: panicking ( ) && e == Err ( Errno :: EBADF ) {
320+ panic ! ( "Closing an invalid file descriptor!" ) ;
321+ } ;
322+ }
323+ }
248324
249325/// After a [`libc::fanotify_event_metadata`], there can be 0 or more event_info
250326/// structs depending on which InitFlags were used in [`Fanotify::init`].
@@ -258,21 +334,28 @@ pub enum FanotifyInfoRecord {
258334 /// a result of passing [`InitFlags::FAN_REPORT_FID`] or [`InitFlags::FAN_REPORT_DIR_FID`]
259335 /// into [`Fanotify::init`]. The containing struct includes a `file_handle` for
260336 /// use with `open_by_handle_at(2)`.
261- Fid ( libc :: fanotify_event_info_fid ) ,
337+ Fid ( FanotifyFidRecord ) ,
262338
263- /// A [`libc::FAN_FS_ERROR`] event was received. This event occurs when
264- /// a filesystem event is detected. Only a single [`libc::FAN_FS_ERROR`] is
265- /// stored per filesystem at once, extra error messages are suppressed and
266- /// accounted for in the error_count field.
267- Error ( libc:: fanotify_event_info_error ) ,
339+ /// A [`libc::fanotify_event_info_error`] event was recieved.
340+ /// This occurs when a FAN_FS_ERROR occurs, indicating an error with
341+ /// the watch filesystem object. (such as a bad file or bad link lookup)
342+ Error ( FanotifyErrorRecord ) ,
268343
269344 /// A [`libc::fanotify_event_info_pidfd`] event was recieved, usually as
270345 /// a result of passing [`InitFlags::FAN_REPORT_PIDFD`] into [`Fanotify::init`].
271346 /// The containing struct includes a `pidfd` for reliably determining
272347 /// whether the process responsible for generating an event has been recycled or terminated
273- Pidfd ( libc :: fanotify_event_info_pidfd ) ,
348+ Pidfd ( FanotifyPidfdRecord ) ,
274349}
275350
351+ /// Abstract over [`libc::fanotify_event_metadata`], which represents an event
352+ /// received via [`Fanotify::read_events`].
353+ // Is not Clone due to fd field, to avoid use-after-close scenarios.
354+ #[ derive( Debug , Eq , Hash , PartialEq ) ]
355+ #[ repr( transparent) ]
356+ #[ allow( missing_copy_implementations) ]
357+ pub struct FanotifyEvent ( libc:: fanotify_event_metadata ) ;
358+
276359impl FanotifyEvent {
277360 /// Version number for the structure. It must be compared to
278361 /// `FANOTIFY_METADATA_VERSION` to verify compile version and runtime
@@ -513,28 +596,33 @@ impl Fanotify {
513596
514597 let info_record = match header. info_type {
515598 libc:: FAN_EVENT_INFO_TYPE_FID => {
516- let event_fid = self
599+ let record = self
517600 . get_struct :: < libc:: fanotify_event_info_fid > (
518601 & buffer,
519602 current_event_offset,
520603 ) ;
521- Some ( FanotifyInfoRecord :: Fid ( event_fid ) )
604+ Some ( FanotifyInfoRecord :: Fid ( FanotifyFidRecord ( record ) ) )
522605 }
523606 libc:: FAN_EVENT_INFO_TYPE_ERROR => {
524- let error_fid = self
607+ let record = self
525608 . get_struct :: < libc:: fanotify_event_info_error > (
526609 & buffer,
527610 current_event_offset,
528611 ) ;
529- Some ( FanotifyInfoRecord :: Error ( error_fid) )
612+
613+ Some ( FanotifyInfoRecord :: Error ( FanotifyErrorRecord (
614+ record,
615+ ) ) )
530616 }
531617 libc:: FAN_EVENT_INFO_TYPE_PIDFD => {
532- let error_fid = self
618+ let record = self
533619 . get_struct :: < libc:: fanotify_event_info_pidfd > (
534620 & buffer,
535621 current_event_offset,
536622 ) ;
537- Some ( FanotifyInfoRecord :: Pidfd ( error_fid) )
623+ Some ( FanotifyInfoRecord :: Pidfd ( FanotifyPidfdRecord (
624+ record,
625+ ) ) )
538626 }
539627 // Ignore unsupported events
540628 _ => None ,
0 commit comments