@@ -125,6 +125,9 @@ macro_rules! cfg_has_statx {
125125 } ;
126126}
127127
128+ #[ cfg( all( target_os = "linux" , target_env = "gnu" ) ) ]
129+ pub ( crate ) use cfg_has_statx;
130+
128131cfg_has_statx ! { {
129132 #[ derive( Clone ) ]
130133 pub struct FileAttr {
@@ -133,7 +136,7 @@ cfg_has_statx! {{
133136 }
134137
135138 #[ derive( Clone ) ]
136- struct StatxExtraFields {
139+ pub struct StatxExtraFields {
137140 // This is needed to check if btime is supported by the filesystem.
138141 stx_mask: u32 ,
139142 stx_btime: libc:: statx_timestamp,
@@ -212,40 +215,7 @@ cfg_has_statx! {{
212215 STATX_SAVED_STATE . store( STATX_STATE :: Present as u8 , Ordering :: Relaxed ) ;
213216 }
214217
215- // We cannot fill `stat64` exhaustively because of private padding fields.
216- let mut stat: stat64 = mem:: zeroed( ) ;
217- // `c_ulong` on gnu-mips, `dev_t` otherwise
218- stat. st_dev = libc:: makedev( buf. stx_dev_major, buf. stx_dev_minor) as _;
219- stat. st_ino = buf. stx_ino as libc:: ino64_t;
220- stat. st_nlink = buf. stx_nlink as libc:: nlink_t;
221- stat. st_mode = buf. stx_mode as libc:: mode_t;
222- stat. st_uid = buf. stx_uid as libc:: uid_t;
223- stat. st_gid = buf. stx_gid as libc:: gid_t;
224- stat. st_rdev = libc:: makedev( buf. stx_rdev_major, buf. stx_rdev_minor) as _;
225- stat. st_size = buf. stx_size as off64_t;
226- stat. st_blksize = buf. stx_blksize as libc:: blksize_t;
227- stat. st_blocks = buf. stx_blocks as libc:: blkcnt64_t;
228- stat. st_atime = buf. stx_atime. tv_sec as libc:: time_t;
229- // `i64` on gnu-x86_64-x32, `c_ulong` otherwise.
230- stat. st_atime_nsec = buf. stx_atime. tv_nsec as _;
231- stat. st_mtime = buf. stx_mtime. tv_sec as libc:: time_t;
232- stat. st_mtime_nsec = buf. stx_mtime. tv_nsec as _;
233- stat. st_ctime = buf. stx_ctime. tv_sec as libc:: time_t;
234- stat. st_ctime_nsec = buf. stx_ctime. tv_nsec as _;
235-
236- let extra = StatxExtraFields {
237- stx_mask: buf. stx_mask,
238- stx_btime: buf. stx_btime,
239- // Store full times to avoid 32-bit `time_t` truncation.
240- #[ cfg( target_pointer_width = "32" ) ]
241- stx_atime: buf. stx_atime,
242- #[ cfg( target_pointer_width = "32" ) ]
243- stx_ctime: buf. stx_ctime,
244- #[ cfg( target_pointer_width = "32" ) ]
245- stx_mtime: buf. stx_mtime,
246- } ;
247-
248- Some ( Ok ( FileAttr { stat, statx_extra_fields: Some ( extra) } ) )
218+ Some ( Ok ( FileAttr :: from_statx( buf) ) )
249219 }
250220
251221} else {
@@ -525,11 +495,65 @@ pub struct DirBuilder {
525495struct Mode ( mode_t ) ;
526496
527497cfg_has_statx ! { {
498+ impl StatxExtraFields {
499+ /// Constructs `StatxExtraFields` from a given `libc::statx` struct
500+ ///
501+ /// SAFETY:
502+ /// The caller must take care to provide a `libc::statx` buffer that is
503+ /// populated by the statx syscall with the flags `STATX_BASIC_STATS`
504+ /// and `STATX_BTIME` enabled
505+ pub unsafe fn from_statx( buf: libc:: statx) -> Self {
506+ StatxExtraFields {
507+ stx_mask: buf. stx_mask,
508+ stx_btime: buf. stx_btime,
509+ // Store full times to avoid 32-bit `time_t` truncation.
510+ #[ cfg( target_pointer_width = "32" ) ]
511+ stx_atime: buf. stx_atime,
512+ #[ cfg( target_pointer_width = "32" ) ]
513+ stx_ctime: buf. stx_ctime,
514+ #[ cfg( target_pointer_width = "32" ) ]
515+ stx_mtime: buf. stx_mtime,
516+ }
517+ }
518+ }
528519 impl FileAttr {
529520 fn from_stat64( stat: stat64) -> Self {
530521 Self { stat, statx_extra_fields: None }
531522 }
532523
524+ /// Constructs `FileAttr` from a given `libc::statx` struct
525+ ///
526+ /// SAFETY:
527+ /// The caller must take care to provide a `libc::statx` buffer that is
528+ /// populated by the statx syscall with the flags `STATX_BASIC_STATS`
529+ /// and `STATX_BTIME` enabled
530+ pub unsafe fn from_statx( buf: libc:: statx) -> Self {
531+ // We cannot fill `stat64` exhaustively because of private padding fields.
532+ let mut stat: libc:: stat64 = mem:: zeroed( ) ;
533+ // `c_ulong` on gnu-mips, `dev_t` otherwise
534+ stat. st_dev = libc:: makedev( ( buf) . stx_dev_major, ( buf) . stx_dev_minor) as _;
535+ stat. st_ino = buf. stx_ino as libc:: ino64_t;
536+ stat. st_nlink = buf. stx_nlink as libc:: nlink_t;
537+ stat. st_mode = buf. stx_mode as libc:: mode_t;
538+ stat. st_uid = buf. stx_uid as libc:: uid_t;
539+ stat. st_gid = buf. stx_gid as libc:: gid_t;
540+ stat. st_rdev = libc:: makedev( buf. stx_rdev_major, buf. stx_rdev_minor) as _;
541+ stat. st_size = buf. stx_size as libc:: off64_t;
542+ stat. st_blksize = buf. stx_blksize as libc:: blksize_t;
543+ stat. st_blocks = buf. stx_blocks as libc:: blkcnt64_t;
544+ stat. st_atime = buf. stx_atime. tv_sec as libc:: time_t;
545+ // `i64` on gnu-x86_64-x32, `c_ulong` otherwise.
546+ stat. st_atime_nsec = buf. stx_atime. tv_nsec as _;
547+ stat. st_mtime = buf. stx_mtime. tv_sec as libc:: time_t;
548+ stat. st_mtime_nsec = buf. stx_mtime. tv_nsec as _;
549+ stat. st_ctime = buf. stx_ctime. tv_sec as libc:: time_t;
550+ stat. st_ctime_nsec = buf. stx_ctime. tv_nsec as _;
551+
552+ let statx_extra_fields = Some ( StatxExtraFields :: from_statx( buf) ) ;
553+
554+ Self { stat, statx_extra_fields}
555+ }
556+
533557 #[ cfg( target_pointer_width = "32" ) ]
534558 pub fn stx_mtime( & self ) -> Option <& libc:: statx_timestamp> {
535559 if let Some ( ext) = & self . statx_extra_fields {
0 commit comments