@@ -59,7 +59,8 @@ struct StatxExtraFields {
5959 stx_btime : libc:: statx_timestamp ,
6060}
6161
62- // We prefer `statx` if available, which contains file creation time.
62+ // We prefer `statx` on Linux if available, which contains file creation time.
63+ // Default `stat64` contains no creation time.
6364#[ cfg( target_os = "linux" ) ]
6465unsafe fn try_statx (
6566 fd : c_int ,
@@ -178,6 +179,14 @@ pub struct FileType { mode: mode_t }
178179pub struct DirBuilder { mode : mode_t }
179180
180181impl FileAttr {
182+ fn from_stat64 ( stat : stat64 ) -> Self {
183+ Self {
184+ stat,
185+ #[ cfg( target_os = "linux" ) ]
186+ statx_extra_fields : None ,
187+ }
188+ }
189+
181190 pub fn size ( & self ) -> u64 { self . stat . st_size as u64 }
182191 pub fn perm ( & self ) -> FilePermissions {
183192 FilePermissions { mode : ( self . stat . st_mode as mode_t ) }
@@ -228,26 +237,6 @@ impl FileAttr {
228237 } ) )
229238 }
230239
231- #[ cfg( target_os = "linux" ) ]
232- pub fn created ( & self ) -> io:: Result < SystemTime > {
233- match & self . statx_extra_fields {
234- Some ( ext) if ( ext. stx_mask & libc:: STATX_BTIME ) != 0 => {
235- Ok ( SystemTime :: from ( libc:: timespec {
236- tv_sec : ext. stx_btime . tv_sec as libc:: time_t ,
237- tv_nsec : ext. stx_btime . tv_nsec as libc:: c_long ,
238- } ) )
239- }
240- Some ( _) => Err ( io:: Error :: new (
241- io:: ErrorKind :: Other ,
242- "creation time is not available for the filesystam" ,
243- ) ) ,
244- None => Err ( io:: Error :: new (
245- io:: ErrorKind :: Other ,
246- "creation time is not available on this platform currently" ,
247- ) ) ,
248- }
249- }
250-
251240 #[ cfg( any( target_os = "freebsd" ,
252241 target_os = "openbsd" ,
253242 target_os = "macos" ,
@@ -259,12 +248,28 @@ impl FileAttr {
259248 } ) )
260249 }
261250
262- #[ cfg( not( any( target_os = "linux" ,
263- target_os = "freebsd" ,
251+ #[ cfg( not( any( target_os = "freebsd" ,
264252 target_os = "openbsd" ,
265253 target_os = "macos" ,
266254 target_os = "ios" ) ) ) ]
267255 pub fn created ( & self ) -> io:: Result < SystemTime > {
256+ #[ cfg( target_os = "linux" ) ]
257+ {
258+ if let Some ( ext) = & self . statx_extra_fields {
259+ return if ( ext. stx_mask & libc:: STATX_BTIME ) != 0 {
260+ Ok ( SystemTime :: from ( libc:: timespec {
261+ tv_sec : ext. stx_btime . tv_sec as libc:: time_t ,
262+ tv_nsec : ext. stx_btime . tv_nsec as libc:: c_long ,
263+ } ) )
264+ } else {
265+ Err ( io:: Error :: new (
266+ io:: ErrorKind :: Other ,
267+ "creation time is not available for the filesystam" ,
268+ ) )
269+ } ;
270+ }
271+ }
272+
268273 Err ( io:: Error :: new ( io:: ErrorKind :: Other ,
269274 "creation time is not available on this platform \
270275 currently") )
@@ -405,30 +410,28 @@ impl DirEntry {
405410 OsStr :: from_bytes ( self . name_bytes ( ) ) . to_os_string ( )
406411 }
407412
408- #[ cfg( target_os = "linux" ) ]
413+ #[ cfg( any ( target_os = "linux" , target_os = "emscripten" , target_os = "android" ) ) ]
409414 pub fn metadata ( & self ) -> io:: Result < FileAttr > {
410- let dir_fd = cvt ( unsafe { dirfd ( self . dir . inner . dirp . 0 ) } ) ?;
411- let pathname = self . entry . d_name . as_ptr ( ) ;
412- unsafe { try_statx (
413- dir_fd,
414- pathname,
415- libc:: AT_SYMLINK_NOFOLLOW | libc:: AT_STATX_SYNC_AS_STAT ,
416- libc:: STATX_ALL ,
417- ) } . unwrap_or_else ( || {
418- let mut stat = unsafe { mem:: zeroed ( ) } ;
419- cvt ( unsafe { fstatat64 ( dir_fd, pathname, & mut stat, libc:: AT_SYMLINK_NOFOLLOW ) } ) ?;
420- Ok ( FileAttr { stat, statx_extra_fields : None } )
421- } )
422- }
415+ let fd = cvt ( unsafe { dirfd ( self . dir . inner . dirp . 0 ) } ) ?;
416+ let name = self . entry . d_name . as_ptr ( ) ;
417+
418+ #[ cfg( target_os = "linux" ) ]
419+ {
420+ if let Some ( ret) = unsafe { try_statx (
421+ fd,
422+ name,
423+ libc:: AT_SYMLINK_NOFOLLOW | libc:: AT_STATX_SYNC_AS_STAT ,
424+ libc:: STATX_ALL ,
425+ ) } {
426+ return ret;
427+ }
428+ }
423429
424- #[ cfg( any( target_os = "emscripten" , target_os = "android" ) ) ]
425- pub fn metadata ( & self ) -> io:: Result < FileAttr > {
426- let fd = cvt ( unsafe { dirfd ( self . dir . inner . dirp . 0 ) } ) ?;
427430 let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
428431 cvt ( unsafe {
429- fstatat64 ( fd, self . entry . d_name . as_ptr ( ) , & mut stat, libc:: AT_SYMLINK_NOFOLLOW )
432+ fstatat64 ( fd, name , & mut stat, libc:: AT_SYMLINK_NOFOLLOW )
430433 } ) ?;
431- Ok ( FileAttr { stat } )
434+ Ok ( FileAttr :: from_stat64 ( stat) )
432435 }
433436
434437 #[ cfg( not( any( target_os = "linux" , target_os = "emscripten" , target_os = "android" ) ) ) ]
@@ -633,28 +636,26 @@ impl File {
633636 Ok ( File ( fd) )
634637 }
635638
636- #[ cfg( target_os = "linux" ) ]
637639 pub fn file_attr ( & self ) -> io:: Result < FileAttr > {
638640 let fd = self . 0 . raw ( ) ;
639- unsafe { try_statx (
640- fd,
641- b"\0 " as * const _ as * const libc:: c_char ,
642- libc:: AT_EMPTY_PATH | libc:: AT_STATX_SYNC_AS_STAT ,
643- libc:: STATX_ALL ,
644- ) } . unwrap_or_else ( || {
645- let mut stat = unsafe { mem:: zeroed ( ) } ;
646- cvt ( unsafe { fstat64 ( fd, & mut stat) } ) ?;
647- Ok ( FileAttr { stat, statx_extra_fields : None } )
648- } )
649- }
650641
651- #[ cfg( not( target_os = "linux" ) ) ]
652- pub fn file_attr ( & self ) -> io:: Result < FileAttr > {
642+ #[ cfg( target_os = "linux" ) ]
643+ {
644+ if let Some ( ret) = unsafe { try_statx (
645+ fd,
646+ b"\0 " as * const _ as * const libc:: c_char ,
647+ libc:: AT_EMPTY_PATH | libc:: AT_STATX_SYNC_AS_STAT ,
648+ libc:: STATX_ALL ,
649+ ) } {
650+ return ret;
651+ }
652+ }
653+
653654 let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
654655 cvt ( unsafe {
655- fstat64 ( self . 0 . raw ( ) , & mut stat)
656+ fstat64 ( fd , & mut stat)
656657 } ) ?;
657- Ok ( FileAttr { stat } )
658+ Ok ( FileAttr :: from_stat64 ( stat) )
658659 }
659660
660661 pub fn fsync ( & self ) -> io:: Result < ( ) > {
@@ -929,56 +930,48 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
929930 Ok ( ( ) )
930931}
931932
932- #[ cfg( target_os = "linux" ) ]
933933pub fn stat ( p : & Path ) -> io:: Result < FileAttr > {
934934 let p = cstr ( p) ?;
935- let p = p. as_ptr ( ) ;
936- unsafe { try_statx (
937- libc:: AT_FDCWD ,
938- p,
939- libc:: AT_STATX_SYNC_AS_STAT ,
940- libc:: STATX_ALL ,
941- ) } . unwrap_or_else ( || {
942- let mut stat = unsafe { mem:: zeroed ( ) } ;
943- cvt ( unsafe { stat64 ( p, & mut stat) } ) ?;
944- Ok ( FileAttr { stat, statx_extra_fields : None } )
945- } )
946- }
947935
948- #[ cfg( not( target_os = "linux" ) ) ]
949- pub fn stat ( p : & Path ) -> io:: Result < FileAttr > {
950- let p = cstr ( p) ?;
936+ #[ cfg( target_os = "linux" ) ]
937+ {
938+ if let Some ( ret) = unsafe { try_statx (
939+ libc:: AT_FDCWD ,
940+ p. as_ptr ( ) ,
941+ libc:: AT_STATX_SYNC_AS_STAT ,
942+ libc:: STATX_ALL ,
943+ ) } {
944+ return ret;
945+ }
946+ }
947+
951948 let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
952949 cvt ( unsafe {
953950 stat64 ( p. as_ptr ( ) , & mut stat)
954951 } ) ?;
955- Ok ( FileAttr { stat } )
952+ Ok ( FileAttr :: from_stat64 ( stat) )
956953}
957954
958- #[ cfg( target_os = "linux" ) ]
959955pub fn lstat ( p : & Path ) -> io:: Result < FileAttr > {
960956 let p = cstr ( p) ?;
961- let p = p. as_ptr ( ) ;
962- unsafe { try_statx (
963- libc:: AT_FDCWD ,
964- p,
965- libc:: AT_SYMLINK_NOFOLLOW | libc:: AT_STATX_SYNC_AS_STAT ,
966- libc:: STATX_ALL ,
967- ) } . unwrap_or_else ( || {
968- let mut stat = unsafe { mem:: zeroed ( ) } ;
969- cvt ( unsafe { lstat64 ( p, & mut stat) } ) ?;
970- Ok ( FileAttr { stat, statx_extra_fields : None } )
971- } )
972- }
973957
974- #[ cfg( not( target_os = "linux" ) ) ]
975- pub fn lstat ( p : & Path ) -> io:: Result < FileAttr > {
976- let p = cstr ( p) ?;
958+ #[ cfg( target_os = "linux" ) ]
959+ {
960+ if let Some ( ret) = unsafe { try_statx (
961+ libc:: AT_FDCWD ,
962+ p. as_ptr ( ) ,
963+ libc:: AT_SYMLINK_NOFOLLOW | libc:: AT_STATX_SYNC_AS_STAT ,
964+ libc:: STATX_ALL ,
965+ ) } {
966+ return ret;
967+ }
968+ }
969+
977970 let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
978971 cvt ( unsafe {
979972 lstat64 ( p. as_ptr ( ) , & mut stat)
980973 } ) ?;
981- Ok ( FileAttr { stat } )
974+ Ok ( FileAttr :: from_stat64 ( stat) )
982975}
983976
984977pub fn canonicalize ( p : & Path ) -> io:: Result < PathBuf > {
0 commit comments