@@ -59,7 +59,8 @@ struct StatxExtraFields {
59
59
stx_btime : libc:: statx_timestamp ,
60
60
}
61
61
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.
63
64
#[ cfg( target_os = "linux" ) ]
64
65
unsafe fn try_statx (
65
66
fd : c_int ,
@@ -178,6 +179,14 @@ pub struct FileType { mode: mode_t }
178
179
pub struct DirBuilder { mode : mode_t }
179
180
180
181
impl 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
+
181
190
pub fn size ( & self ) -> u64 { self . stat . st_size as u64 }
182
191
pub fn perm ( & self ) -> FilePermissions {
183
192
FilePermissions { mode : ( self . stat . st_mode as mode_t ) }
@@ -228,26 +237,6 @@ impl FileAttr {
228
237
} ) )
229
238
}
230
239
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
-
251
240
#[ cfg( any( target_os = "freebsd" ,
252
241
target_os = "openbsd" ,
253
242
target_os = "macos" ,
@@ -259,12 +248,28 @@ impl FileAttr {
259
248
} ) )
260
249
}
261
250
262
- #[ cfg( not( any( target_os = "linux" ,
263
- target_os = "freebsd" ,
251
+ #[ cfg( not( any( target_os = "freebsd" ,
264
252
target_os = "openbsd" ,
265
253
target_os = "macos" ,
266
254
target_os = "ios" ) ) ) ]
267
255
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
+
268
273
Err ( io:: Error :: new ( io:: ErrorKind :: Other ,
269
274
"creation time is not available on this platform \
270
275
currently") )
@@ -405,30 +410,28 @@ impl DirEntry {
405
410
OsStr :: from_bytes ( self . name_bytes ( ) ) . to_os_string ( )
406
411
}
407
412
408
- #[ cfg( target_os = "linux" ) ]
413
+ #[ cfg( any ( target_os = "linux" , target_os = "emscripten" , target_os = "android" ) ) ]
409
414
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
+ }
423
429
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 ) } ) ?;
427
430
let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
428
431
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 )
430
433
} ) ?;
431
- Ok ( FileAttr { stat } )
434
+ Ok ( FileAttr :: from_stat64 ( stat) )
432
435
}
433
436
434
437
#[ cfg( not( any( target_os = "linux" , target_os = "emscripten" , target_os = "android" ) ) ) ]
@@ -633,28 +636,26 @@ impl File {
633
636
Ok ( File ( fd) )
634
637
}
635
638
636
- #[ cfg( target_os = "linux" ) ]
637
639
pub fn file_attr ( & self ) -> io:: Result < FileAttr > {
638
640
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
- }
650
641
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
+
653
654
let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
654
655
cvt ( unsafe {
655
- fstat64 ( self . 0 . raw ( ) , & mut stat)
656
+ fstat64 ( fd , & mut stat)
656
657
} ) ?;
657
- Ok ( FileAttr { stat } )
658
+ Ok ( FileAttr :: from_stat64 ( stat) )
658
659
}
659
660
660
661
pub fn fsync ( & self ) -> io:: Result < ( ) > {
@@ -929,56 +930,48 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
929
930
Ok ( ( ) )
930
931
}
931
932
932
- #[ cfg( target_os = "linux" ) ]
933
933
pub fn stat ( p : & Path ) -> io:: Result < FileAttr > {
934
934
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
- }
947
935
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
+
951
948
let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
952
949
cvt ( unsafe {
953
950
stat64 ( p. as_ptr ( ) , & mut stat)
954
951
} ) ?;
955
- Ok ( FileAttr { stat } )
952
+ Ok ( FileAttr :: from_stat64 ( stat) )
956
953
}
957
954
958
- #[ cfg( target_os = "linux" ) ]
959
955
pub fn lstat ( p : & Path ) -> io:: Result < FileAttr > {
960
956
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
- }
973
957
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
+
977
970
let mut stat: stat64 = unsafe { mem:: zeroed ( ) } ;
978
971
cvt ( unsafe {
979
972
lstat64 ( p. as_ptr ( ) , & mut stat)
980
973
} ) ?;
981
- Ok ( FileAttr { stat } )
974
+ Ok ( FileAttr :: from_stat64 ( stat) )
982
975
}
983
976
984
977
pub fn canonicalize ( p : & Path ) -> io:: Result < PathBuf > {
0 commit comments