@@ -7,7 +7,7 @@ use crate::hash::Hash;
77use crate :: io:: { self , BorrowedCursor , IoSlice , IoSliceMut , SeekFrom } ;
88use crate :: path:: { Path , PathBuf } ;
99use crate :: sys:: time:: SystemTime ;
10- use crate :: sys:: unsupported;
10+ use crate :: sys:: { helpers , unsupported} ;
1111
1212#[ expect( dead_code) ]
1313const FILE_PERMISSIONS_MASK : u64 = r_efi:: protocols:: file:: READ_ONLY ;
@@ -76,6 +76,18 @@ impl FileAttr {
7676 pub fn created ( & self ) -> io:: Result < SystemTime > {
7777 Ok ( self . created )
7878 }
79+
80+ fn from_uefi ( info : helpers:: UefiBox < file:: Info > ) -> Self {
81+ unsafe {
82+ Self {
83+ attr : ( * info. as_ptr ( ) ) . attribute ,
84+ size : ( * info. as_ptr ( ) ) . size ,
85+ modified : uefi_fs:: uefi_to_systemtime ( ( * info. as_ptr ( ) ) . modification_time ) ,
86+ accessed : uefi_fs:: uefi_to_systemtime ( ( * info. as_ptr ( ) ) . last_access_time ) ,
87+ created : uefi_fs:: uefi_to_systemtime ( ( * info. as_ptr ( ) ) . create_time ) ,
88+ }
89+ }
90+ }
7991}
8092
8193impl FilePermissions {
@@ -381,8 +393,10 @@ pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
381393 unsupported ( )
382394}
383395
384- pub fn stat ( _p : & Path ) -> io:: Result < FileAttr > {
385- unsupported ( )
396+ pub fn stat ( p : & Path ) -> io:: Result < FileAttr > {
397+ let f = uefi_fs:: File :: from_path ( p, r_efi:: protocols:: file:: MODE_READ , 0 ) ?;
398+ let inf = f. file_info ( ) ?;
399+ Ok ( FileAttr :: from_uefi ( inf) )
386400}
387401
388402pub fn lstat ( p : & Path ) -> io:: Result < FileAttr > {
@@ -404,7 +418,7 @@ mod uefi_fs {
404418 use crate :: io;
405419 use crate :: path:: Path ;
406420 use crate :: ptr:: NonNull ;
407- use crate :: sys:: helpers;
421+ use crate :: sys:: helpers:: { self , UefiBox } ;
408422 use crate :: sys:: time:: { self , SystemTime } ;
409423
410424 pub ( crate ) struct File ( NonNull < file:: Protocol > ) ;
@@ -492,6 +506,37 @@ mod uefi_fs {
492506 let p = NonNull :: new ( file_opened) . unwrap ( ) ;
493507 Ok ( File ( p) )
494508 }
509+
510+ pub ( crate ) fn file_info ( & self ) -> io:: Result < UefiBox < file:: Info > > {
511+ let file_ptr = self . 0 . as_ptr ( ) ;
512+ let mut info_id = file:: INFO_ID ;
513+ let mut buf_size = 0 ;
514+
515+ let r = unsafe {
516+ ( ( * file_ptr) . get_info ) (
517+ file_ptr,
518+ & mut info_id,
519+ & mut buf_size,
520+ crate :: ptr:: null_mut ( ) ,
521+ )
522+ } ;
523+ assert ! ( r. is_error( ) ) ;
524+ if r != r_efi:: efi:: Status :: BUFFER_TOO_SMALL {
525+ return Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) ;
526+ }
527+
528+ let mut info: UefiBox < file:: Info > = UefiBox :: new ( buf_size) ?;
529+ let r = unsafe {
530+ ( ( * file_ptr) . get_info ) (
531+ file_ptr,
532+ & mut info_id,
533+ & mut buf_size,
534+ info. as_mut_ptr ( ) . cast ( ) ,
535+ )
536+ } ;
537+
538+ if r. is_error ( ) { Err ( io:: Error :: from_raw_os_error ( r. as_usize ( ) ) ) } else { Ok ( info) }
539+ }
495540 }
496541
497542 impl Drop for File {
@@ -556,8 +601,7 @@ mod uefi_fs {
556601
557602 /// EDK2 FAT driver uses EFI_UNSPECIFIED_TIMEZONE to represent localtime. So for proper
558603 /// conversion to SystemTime, we use the current time to get the timezone in such cases.
559- #[ expect( dead_code) ]
560- fn uefi_to_systemtime ( mut time : r_efi:: efi:: Time ) -> SystemTime {
604+ pub ( crate ) fn uefi_to_systemtime ( mut time : r_efi:: efi:: Time ) -> SystemTime {
561605 time. timezone = if time. timezone == r_efi:: efi:: UNSPECIFIED_TIMEZONE {
562606 time:: system_time_internal:: now ( ) . unwrap ( ) . timezone
563607 } else {
0 commit comments