@@ -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.
239253pub 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) ]
255272pub struct FanotifyFidRecord {
256273 record : LibcFanotifyFidRecord ,
257- handle_bytes : * const u8 ,
274+ file_handle_bytes : [ u8 ; MAX_HANDLE_SZ ] ,
258275}
259276
260277impl 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]
355371pub 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