@@ -14,6 +14,7 @@ use crate::errno::Errno;
14
14
use crate :: fcntl:: OFlag ;
15
15
use crate :: unistd:: { close, read, write} ;
16
16
use crate :: { NixPath , Result } ;
17
+ use std:: ffi:: CStr ;
17
18
use std:: marker:: PhantomData ;
18
19
use std:: mem:: { size_of, MaybeUninit } ;
19
20
use std:: os:: unix:: io:: { AsFd , AsRawFd , BorrowedFd , FromRawFd , OwnedFd , RawFd } ;
@@ -272,6 +273,7 @@ pub struct LibcFanotifyFidRecord(libc::fanotify_event_info_fid);
272
273
pub struct FanotifyFidRecord {
273
274
record : LibcFanotifyFidRecord ,
274
275
file_handle_bytes : [ u8 ; MAX_HANDLE_SZ ] ,
276
+ name : Option < String > ,
275
277
}
276
278
277
279
impl FanotifyFidRecord {
@@ -293,10 +295,20 @@ impl FanotifyFidRecord {
293
295
294
296
/// The specific info_type for this Fid Record. Fanotify can return an Fid Record
295
297
/// 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)
297
299
pub fn info_type ( & self ) -> FanotifyFidEventInfoType {
298
300
FanotifyFidEventInfoType :: try_from ( self . record . 0 . hdr . info_type ) . unwrap ( )
299
301
}
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
+ }
300
312
}
301
313
302
314
/// Abstract over [`libc::fanotify_event_info_error`], which represents an
@@ -599,7 +611,7 @@ impl Fanotify {
599
611
/// In particular, `EAGAIN` is returned when no event is available on a
600
612
/// group that has been initialized with the flag `InitFlags::FAN_NONBLOCK`,
601
613
/// thus making this method nonblocking.
602
- #[ allow( clippy:: cast_ptr_alignment) ] // False positive
614
+ #[ allow( clippy:: cast_ptr_alignment) ] // False positive
603
615
pub fn read_events_with_info_records (
604
616
& self ,
605
617
) -> Result < Vec < ( FanotifyEvent , Vec < FanotifyInfoRecord > ) > > {
@@ -628,9 +640,12 @@ impl Fanotify {
628
640
let mut current_event_offset = offset + metadata_size;
629
641
630
642
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 ( ) } ;
632
645
// 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
+ } ;
634
649
635
650
let info_record = match header_info_type {
636
651
// FanotifyFidRecord can be returned for any of the following info_type.
@@ -647,18 +662,24 @@ impl Fanotify {
647
662
current_event_offset,
648
663
) ;
649
664
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
653
677
} ;
654
678
655
679
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 ( ) ;
658
682
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
683
std:: ptr:: copy_nonoverlapping (
663
684
file_handle_ptr,
664
685
file_handle. as_mut_ptr ( ) . cast ( ) ,
@@ -667,9 +688,32 @@ impl Fanotify {
667
688
file_handle. assume_init ( )
668
689
} ;
669
690
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
+
670
713
Some ( FanotifyInfoRecord :: Fid ( FanotifyFidRecord {
671
714
record : LibcFanotifyFidRecord ( record) ,
672
715
file_handle_bytes : file_handle,
716
+ name,
673
717
} ) )
674
718
}
675
719
#[ cfg( target_env = "gnu" ) ]
@@ -752,8 +796,7 @@ impl AsFd for Fanotify {
752
796
}
753
797
754
798
impl AsRawFd for Fanotify {
755
- fn as_raw_fd ( & self ) -> RawFd
756
- {
799
+ fn as_raw_fd ( & self ) -> RawFd {
757
800
self . fd . as_raw_fd ( )
758
801
}
759
802
}
@@ -771,8 +814,6 @@ impl Fanotify {
771
814
///
772
815
/// `OwnedFd` is a valid `Fanotify`.
773
816
pub unsafe fn from_owned_fd ( fd : OwnedFd ) -> Self {
774
- Self {
775
- fd
776
- }
817
+ Self { fd }
777
818
}
778
819
}
0 commit comments