@@ -238,13 +238,89 @@ libc_bitflags! {
238
238
/// Compile version number of fanotify API.
239
239
pub const FANOTIFY_METADATA_VERSION : u8 = libc:: FANOTIFY_METADATA_VERSION ;
240
240
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 `].
243
243
// Is not Clone due to fd field, to avoid use-after-close scenarios.
244
244
#[ derive( Debug , Eq , Hash , PartialEq ) ]
245
245
#[ repr( transparent) ]
246
246
#[ 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
+ }
248
324
249
325
/// After a [`libc::fanotify_event_metadata`], there can be 0 or more event_info
250
326
/// structs depending on which InitFlags were used in [`Fanotify::init`].
@@ -258,21 +334,28 @@ pub enum FanotifyInfoRecord {
258
334
/// a result of passing [`InitFlags::FAN_REPORT_FID`] or [`InitFlags::FAN_REPORT_DIR_FID`]
259
335
/// into [`Fanotify::init`]. The containing struct includes a `file_handle` for
260
336
/// use with `open_by_handle_at(2)`.
261
- Fid ( libc :: fanotify_event_info_fid ) ,
337
+ Fid ( FanotifyFidRecord ) ,
262
338
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 ) ,
268
343
269
344
/// A [`libc::fanotify_event_info_pidfd`] event was recieved, usually as
270
345
/// a result of passing [`InitFlags::FAN_REPORT_PIDFD`] into [`Fanotify::init`].
271
346
/// The containing struct includes a `pidfd` for reliably determining
272
347
/// whether the process responsible for generating an event has been recycled or terminated
273
- Pidfd ( libc :: fanotify_event_info_pidfd ) ,
348
+ Pidfd ( FanotifyPidfdRecord ) ,
274
349
}
275
350
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
+
276
359
impl FanotifyEvent {
277
360
/// Version number for the structure. It must be compared to
278
361
/// `FANOTIFY_METADATA_VERSION` to verify compile version and runtime
@@ -513,28 +596,33 @@ impl Fanotify {
513
596
514
597
let info_record = match header. info_type {
515
598
libc:: FAN_EVENT_INFO_TYPE_FID => {
516
- let event_fid = self
599
+ let record = self
517
600
. get_struct :: < libc:: fanotify_event_info_fid > (
518
601
& buffer,
519
602
current_event_offset,
520
603
) ;
521
- Some ( FanotifyInfoRecord :: Fid ( event_fid ) )
604
+ Some ( FanotifyInfoRecord :: Fid ( FanotifyFidRecord ( record ) ) )
522
605
}
523
606
libc:: FAN_EVENT_INFO_TYPE_ERROR => {
524
- let error_fid = self
607
+ let record = self
525
608
. get_struct :: < libc:: fanotify_event_info_error > (
526
609
& buffer,
527
610
current_event_offset,
528
611
) ;
529
- Some ( FanotifyInfoRecord :: Error ( error_fid) )
612
+
613
+ Some ( FanotifyInfoRecord :: Error ( FanotifyErrorRecord (
614
+ record,
615
+ ) ) )
530
616
}
531
617
libc:: FAN_EVENT_INFO_TYPE_PIDFD => {
532
- let error_fid = self
618
+ let record = self
533
619
. get_struct :: < libc:: fanotify_event_info_pidfd > (
534
620
& buffer,
535
621
current_event_offset,
536
622
) ;
537
- Some ( FanotifyInfoRecord :: Pidfd ( error_fid) )
623
+ Some ( FanotifyInfoRecord :: Pidfd ( FanotifyPidfdRecord (
624
+ record,
625
+ ) ) )
538
626
}
539
627
// Ignore unsupported events
540
628
_ => None ,
0 commit comments