@@ -14,6 +14,7 @@ use crate::errno::Errno;
1414use crate :: fcntl:: OFlag ;
1515use crate :: unistd:: { close, read, write} ;
1616use crate :: { NixPath , Result } ;
17+ use std:: ffi:: CStr ;
1718use std:: marker:: PhantomData ;
1819use std:: mem:: { size_of, MaybeUninit } ;
1920use std:: os:: unix:: io:: { AsFd , AsRawFd , BorrowedFd , FromRawFd , OwnedFd , RawFd } ;
@@ -272,6 +273,7 @@ pub struct LibcFanotifyFidRecord(libc::fanotify_event_info_fid);
272273pub struct FanotifyFidRecord {
273274 record : LibcFanotifyFidRecord ,
274275 file_handle_bytes : [ u8 ; MAX_HANDLE_SZ ] ,
276+ name : Option < String > ,
275277}
276278
277279impl FanotifyFidRecord {
@@ -293,10 +295,20 @@ impl FanotifyFidRecord {
293295
294296 /// The specific info_type for this Fid Record. Fanotify can return an Fid Record
295297 /// with many different possible info_types. The info_type is not always necessary
296- /// but can be useful for connecting similar events together (like a FAN_RENAME)
298+ /// but can be useful for connecting similar events together (like a FAN_RENAME)
297299 pub fn info_type ( & self ) -> FanotifyFidEventInfoType {
298300 FanotifyFidEventInfoType :: try_from ( self . record . 0 . hdr . info_type ) . unwrap ( )
299301 }
302+
303+ /// The name attached to the end of this Fid Record. This will only contain a value
304+ /// if the info_type is expected to return a name (like `FanotifyFidEventInfoType::FAN_EVENT_INFO_TYPE_DFID_NAME`)
305+ pub fn name ( & self ) -> Option < & str > {
306+ if let Some ( name) = self . name . as_ref ( ) {
307+ Some ( name)
308+ } else {
309+ None
310+ }
311+ }
300312}
301313
302314/// Abstract over [`libc::fanotify_event_info_error`], which represents an
@@ -599,7 +611,7 @@ impl Fanotify {
599611 /// In particular, `EAGAIN` is returned when no event is available on a
600612 /// group that has been initialized with the flag `InitFlags::FAN_NONBLOCK`,
601613 /// thus making this method nonblocking.
602- #[ allow( clippy:: cast_ptr_alignment) ] // False positive
614+ #[ allow( clippy:: cast_ptr_alignment) ] // False positive
603615 pub fn read_events_with_info_records (
604616 & self ,
605617 ) -> Result < Vec < ( FanotifyEvent , Vec < FanotifyInfoRecord > ) > > {
@@ -628,9 +640,12 @@ impl Fanotify {
628640 let mut current_event_offset = offset + metadata_size;
629641
630642 while remaining_len > 0 {
631- let header_info_type = unsafe { buffer. as_ptr ( ) . add ( current_event_offset) . read ( ) } ;
643+ let header_info_type =
644+ unsafe { buffer. as_ptr ( ) . add ( current_event_offset) . read ( ) } ;
632645 // 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 ( ) } ;
646+ let info_type_length = unsafe {
647+ buffer. as_ptr ( ) . add ( current_event_offset + 2 ) . read ( )
648+ } ;
634649
635650 let info_record = match header_info_type {
636651 // FanotifyFidRecord can be returned for any of the following info_type.
@@ -647,18 +662,24 @@ impl Fanotify {
647662 current_event_offset,
648663 ) ;
649664
650- let record_ptr: * const libc:: fanotify_event_info_fid = unsafe {
651- buffer. as_ptr ( ) . add ( current_event_offset)
652- as * const libc:: fanotify_event_info_fid
665+ let file_handle_ptr = unsafe {
666+ ( buffer. as_ptr ( ) . add ( current_event_offset)
667+ as * const libc:: fanotify_event_info_fid )
668+ . add ( 1 ) as * const u8
669+ } ;
670+
671+ // Read the entire file_handle. The struct can be found here:
672+ // https://man7.org/linux/man-pages/man2/open_by_handle_at.2.html
673+ let file_handle_length = unsafe {
674+ size_of :: < u32 > ( )
675+ + size_of :: < i32 > ( )
676+ + file_handle_ptr. cast :: < u32 > ( ) . read ( ) as usize
653677 } ;
654678
655679 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 ( ) ;
680+ let mut file_handle =
681+ MaybeUninit :: < [ u8 ; MAX_HANDLE_SZ ] > :: uninit ( ) ;
658682
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 ;
662683 std:: ptr:: copy_nonoverlapping (
663684 file_handle_ptr,
664685 file_handle. as_mut_ptr ( ) . cast ( ) ,
@@ -667,9 +688,32 @@ impl Fanotify {
667688 file_handle. assume_init ( )
668689 } ;
669690
691+ let name: Option < String > = match header_info_type {
692+ libc:: FAN_EVENT_INFO_TYPE_DFID_NAME
693+ | libc:: FAN_EVENT_INFO_TYPE_NEW_DFID_NAME
694+ | libc:: FAN_EVENT_INFO_TYPE_OLD_DFID_NAME => unsafe {
695+ let name_ptr =
696+ file_handle_ptr. add ( file_handle_length) ;
697+ if !name_ptr. is_null ( ) {
698+ let name_as_c_str =
699+ CStr :: from_ptr ( name_ptr. cast ( ) )
700+ . to_str ( ) ;
701+ if let Ok ( name) = name_as_c_str {
702+ Some ( name. to_owned ( ) )
703+ } else {
704+ None
705+ }
706+ } else {
707+ None
708+ }
709+ } ,
710+ _ => None ,
711+ } ;
712+
670713 Some ( FanotifyInfoRecord :: Fid ( FanotifyFidRecord {
671714 record : LibcFanotifyFidRecord ( record) ,
672715 file_handle_bytes : file_handle,
716+ name,
673717 } ) )
674718 }
675719 #[ cfg( target_env = "gnu" ) ]
@@ -752,8 +796,7 @@ impl AsFd for Fanotify {
752796}
753797
754798impl AsRawFd for Fanotify {
755- fn as_raw_fd ( & self ) -> RawFd
756- {
799+ fn as_raw_fd ( & self ) -> RawFd {
757800 self . fd . as_raw_fd ( )
758801 }
759802}
@@ -771,8 +814,6 @@ impl Fanotify {
771814 ///
772815 /// `OwnedFd` is a valid `Fanotify`.
773816 pub unsafe fn from_owned_fd ( fd : OwnedFd ) -> Self {
774- Self {
775- fd
776- }
817+ Self { fd }
777818 }
778819}
0 commit comments