@@ -114,15 +114,15 @@ libc_bitflags! {
114
114
/// requires the `CAP_SYS_ADMIN` capability.
115
115
FAN_UNLIMITED_MARKS ;
116
116
117
- /// Make `FanotifyEvent::pid` return pidfd. Since Linux 5.15.
117
+ /// Make [ `FanotifyEvent::pid()`] return pidfd. Since Linux 5.15.
118
118
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.
120
120
FAN_REPORT_TID ;
121
121
122
122
/// Allows the receipt of events which contain additional information
123
123
/// about the underlying filesystem object correlated to an event.
124
124
///
125
- /// This will make `FanotifyEvent::fd` return `FAN_NOFD `.
125
+ /// This will make [ `FanotifyEvent::fd()`] return `None `.
126
126
/// This should be used with `Fanotify::read_events_with_info_records` to
127
127
/// recieve `FanotifyInfoRecord::Fid` info records.
128
128
/// Since Linux 5.1
@@ -131,7 +131,7 @@ libc_bitflags! {
131
131
/// Allows the receipt of events which contain additional information
132
132
/// about the underlying filesystem object correlated to an event.
133
133
///
134
- /// This will make `FanotifyEvent::fd` return `FAN_NOFD `.
134
+ /// This will make [ `FanotifyEvent::fd()`] return `None `.
135
135
/// This should be used with `Fanotify::read_events_with_info_records` to
136
136
/// recieve `FanotifyInfoRecord::Fid` info records.
137
137
///
@@ -235,9 +235,26 @@ libc_bitflags! {
235
235
}
236
236
}
237
237
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
+
238
252
/// Compile version number of fanotify API.
239
253
pub const FANOTIFY_METADATA_VERSION : u8 = libc:: FANOTIFY_METADATA_VERSION ;
240
254
255
+ /// Maximum file_handle size
256
+ pub const MAX_HANDLE_SZ : usize = 128 ;
257
+
241
258
/// Abstract over [`libc::fanotify_event_info_fid`], which represents an
242
259
/// information record received via [`Fanotify::read_events_with_info_records`].
243
260
#[ derive( Debug , Eq , Hash , PartialEq ) ]
@@ -254,7 +271,7 @@ pub struct LibcFanotifyFidRecord(libc::fanotify_event_info_fid);
254
271
#[ allow( missing_copy_implementations) ]
255
272
pub struct FanotifyFidRecord {
256
273
record : LibcFanotifyFidRecord ,
257
- handle_bytes : * const u8 ,
274
+ file_handle_bytes : [ u8 ; MAX_HANDLE_SZ ] ,
258
275
}
259
276
260
277
impl FanotifyFidRecord {
@@ -270,15 +287,15 @@ impl FanotifyFidRecord {
270
287
/// represented as a 0-length u8 array, but it actually points to variable-length
271
288
/// file_handle struct.For more information:
272
289
/// <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
275
292
}
276
293
277
294
/// The specific info_type for this Fid Record. Fanotify can return an Fid Record
278
295
/// with many different possible info_types. The info_type is not always necessary
279
296
/// 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 ( )
282
299
}
283
300
}
284
301
@@ -348,10 +365,9 @@ impl Drop for FanotifyPidfdRecord {
348
365
/// After a [`libc::fanotify_event_metadata`], there can be 0 or more event_info
349
366
/// structs depending on which InitFlags were used in [`Fanotify::init`].
350
367
// 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.
353
368
#[ derive( Debug , Eq , Hash , PartialEq ) ]
354
369
#[ allow( missing_copy_implementations) ]
370
+ #[ non_exhaustive]
355
371
pub enum FanotifyInfoRecord {
356
372
/// A [`libc::fanotify_event_info_fid`] event was recieved, usually as
357
373
/// a result of passing [`InitFlags::FAN_REPORT_FID`] or [`InitFlags::FAN_REPORT_DIR_FID`]
@@ -612,13 +628,11 @@ impl Fanotify {
612
628
let mut current_event_offset = offset + metadata_size;
613
629
614
630
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 ( ) } ;
620
634
621
- let info_record = match header . info_type {
635
+ let info_record = match header_info_type {
622
636
// FanotifyFidRecord can be returned for any of the following info_type.
623
637
// This isn't found in the fanotify(7) documentation, but the fanotify_init(2) documentation
624
638
// https://man7.org/linux/man-pages/man2/fanotify_init.2.html
@@ -638,11 +652,24 @@ impl Fanotify {
638
652
as * const libc:: fanotify_event_info_fid
639
653
} ;
640
654
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
+ } ;
642
669
643
670
Some ( FanotifyInfoRecord :: Fid ( FanotifyFidRecord {
644
671
record : LibcFanotifyFidRecord ( record) ,
645
- handle_bytes : file_handle_ptr ,
672
+ file_handle_bytes : file_handle ,
646
673
} ) )
647
674
}
648
675
#[ cfg( target_env = "gnu" ) ]
@@ -676,12 +703,10 @@ impl Fanotify {
676
703
info_records. push ( record) ;
677
704
}
678
705
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 ;
681
708
}
682
709
683
- // libc::fanotify_event_info_header
684
-
685
710
events. push ( ( FanotifyEvent ( metadata) , info_records) ) ;
686
711
offset += metadata. event_len as usize ;
687
712
}
0 commit comments