@@ -113,10 +113,19 @@ cfg_has_statx! {{
113113 // This is needed to check if btime is supported by the filesystem.
114114 stx_mask: u32 ,
115115 stx_btime: libc:: statx_timestamp,
116+ // With statx, we can overcome 32-bit `time_t` too.
117+ #[ cfg( target_pointer_width = "32" ) ]
118+ stx_atime: libc:: statx_timestamp,
119+ #[ cfg( target_pointer_width = "32" ) ]
120+ stx_ctime: libc:: statx_timestamp,
121+ #[ cfg( target_pointer_width = "32" ) ]
122+ stx_mtime: libc:: statx_timestamp,
123+
116124 }
117125
118- // We prefer `statx` on Linux if available, which contains file creation time.
119- // Default `stat64` contains no creation time.
126+ // We prefer `statx` on Linux if available, which contains file creation time,
127+ // as well as 64-bit timestamps of all kinds.
128+ // Default `stat64` contains no creation time and may have 32-bit `time_t`.
120129 unsafe fn try_statx(
121130 fd: c_int,
122131 path: * const c_char,
@@ -192,6 +201,13 @@ cfg_has_statx! {{
192201 let extra = StatxExtraFields {
193202 stx_mask: buf. stx_mask,
194203 stx_btime: buf. stx_btime,
204+ // Store full times to avoid 32-bit `time_t` truncation.
205+ #[ cfg( target_pointer_width = "32" ) ]
206+ stx_atime: buf. stx_atime,
207+ #[ cfg( target_pointer_width = "32" ) ]
208+ stx_ctime: buf. stx_ctime,
209+ #[ cfg( target_pointer_width = "32" ) ]
210+ stx_mtime: buf. stx_mtime,
195211 } ;
196212
197213 Some ( Ok ( FileAttr { stat, statx_extra_fields: Some ( extra) } ) )
@@ -310,6 +326,36 @@ cfg_has_statx! {{
310326 fn from_stat64( stat: stat64) -> Self {
311327 Self { stat, statx_extra_fields: None }
312328 }
329+
330+ #[ cfg( target_pointer_width = "32" ) ]
331+ pub fn stx_mtime( & self ) -> Option <& libc:: statx_timestamp> {
332+ if let Some ( ext) = & self . statx_extra_fields {
333+ if ( ext. stx_mask & libc:: STATX_MTIME ) != 0 {
334+ return Some ( & ext. stx_mtime) ;
335+ }
336+ }
337+ None
338+ }
339+
340+ #[ cfg( target_pointer_width = "32" ) ]
341+ pub fn stx_atime( & self ) -> Option <& libc:: statx_timestamp> {
342+ if let Some ( ext) = & self . statx_extra_fields {
343+ if ( ext. stx_mask & libc:: STATX_ATIME ) != 0 {
344+ return Some ( & ext. stx_atime) ;
345+ }
346+ }
347+ None
348+ }
349+
350+ #[ cfg( target_pointer_width = "32" ) ]
351+ pub fn stx_ctime( & self ) -> Option <& libc:: statx_timestamp> {
352+ if let Some ( ext) = & self . statx_extra_fields {
353+ if ( ext. stx_mask & libc:: STATX_CTIME ) != 0 {
354+ return Some ( & ext. stx_ctime) ;
355+ }
356+ }
357+ None
358+ }
313359 }
314360} else {
315361 impl FileAttr {
@@ -335,59 +381,52 @@ impl FileAttr {
335381#[ cfg( target_os = "netbsd" ) ]
336382impl FileAttr {
337383 pub fn modified ( & self ) -> io:: Result < SystemTime > {
338- Ok ( SystemTime :: from ( libc:: timespec {
339- tv_sec : self . stat . st_mtime as libc:: time_t ,
340- tv_nsec : self . stat . st_mtimensec as libc:: c_long ,
341- } ) )
384+ Ok ( SystemTime :: new ( self . stat . st_mtime as i64 , self . stat . st_mtimensec as i64 ) )
342385 }
343386
344387 pub fn accessed ( & self ) -> io:: Result < SystemTime > {
345- Ok ( SystemTime :: from ( libc:: timespec {
346- tv_sec : self . stat . st_atime as libc:: time_t ,
347- tv_nsec : self . stat . st_atimensec as libc:: c_long ,
348- } ) )
388+ Ok ( SystemTime :: new ( self . stat . st_atime as i64 , self . stat . st_atimensec as i64 ) )
349389 }
350390
351391 pub fn created ( & self ) -> io:: Result < SystemTime > {
352- Ok ( SystemTime :: from ( libc:: timespec {
353- tv_sec : self . stat . st_birthtime as libc:: time_t ,
354- tv_nsec : self . stat . st_birthtimensec as libc:: c_long ,
355- } ) )
392+ Ok ( SystemTime :: new ( self . stat . st_birthtime as i64 , self . stat . st_birthtimensec as i64 ) )
356393 }
357394}
358395
359396#[ cfg( not( target_os = "netbsd" ) ) ]
360397impl FileAttr {
361398 #[ cfg( all( not( target_os = "vxworks" ) , not( target_os = "espidf" ) ) ) ]
362399 pub fn modified ( & self ) -> io:: Result < SystemTime > {
363- Ok ( SystemTime :: from ( libc:: timespec {
364- tv_sec : self . stat . st_mtime as libc:: time_t ,
365- tv_nsec : self . stat . st_mtime_nsec as _ ,
366- } ) )
400+ #[ cfg( target_pointer_width = "32" ) ]
401+ cfg_has_statx ! {
402+ if let Some ( mtime) = self . stx_mtime( ) {
403+ return Ok ( SystemTime :: new( mtime. tv_sec, mtime. tv_nsec as i64 ) ) ;
404+ }
405+ }
406+
407+ Ok ( SystemTime :: new ( self . stat . st_mtime as i64 , self . stat . st_mtime_nsec as i64 ) )
367408 }
368409
369410 #[ cfg( any( target_os = "vxworks" , target_os = "espidf" ) ) ]
370411 pub fn modified ( & self ) -> io:: Result < SystemTime > {
371- Ok ( SystemTime :: from ( libc:: timespec {
372- tv_sec : self . stat . st_mtime as libc:: time_t ,
373- tv_nsec : 0 ,
374- } ) )
412+ Ok ( SystemTime :: new ( self . stat . st_mtime as i64 , 0 ) )
375413 }
376414
377415 #[ cfg( all( not( target_os = "vxworks" ) , not( target_os = "espidf" ) ) ) ]
378416 pub fn accessed ( & self ) -> io:: Result < SystemTime > {
379- Ok ( SystemTime :: from ( libc:: timespec {
380- tv_sec : self . stat . st_atime as libc:: time_t ,
381- tv_nsec : self . stat . st_atime_nsec as _ ,
382- } ) )
417+ #[ cfg( target_pointer_width = "32" ) ]
418+ cfg_has_statx ! {
419+ if let Some ( atime) = self . stx_atime( ) {
420+ return Ok ( SystemTime :: new( atime. tv_sec, atime. tv_nsec as i64 ) ) ;
421+ }
422+ }
423+
424+ Ok ( SystemTime :: new ( self . stat . st_atime as i64 , self . stat . st_atime_nsec as i64 ) )
383425 }
384426
385427 #[ cfg( any( target_os = "vxworks" , target_os = "espidf" ) ) ]
386428 pub fn accessed ( & self ) -> io:: Result < SystemTime > {
387- Ok ( SystemTime :: from ( libc:: timespec {
388- tv_sec : self . stat . st_atime as libc:: time_t ,
389- tv_nsec : 0 ,
390- } ) )
429+ Ok ( SystemTime :: new ( self . stat . st_atime as i64 , 0 ) )
391430 }
392431
393432 #[ cfg( any(
@@ -397,10 +436,7 @@ impl FileAttr {
397436 target_os = "ios"
398437 ) ) ]
399438 pub fn created ( & self ) -> io:: Result < SystemTime > {
400- Ok ( SystemTime :: from ( libc:: timespec {
401- tv_sec : self . stat . st_birthtime as libc:: time_t ,
402- tv_nsec : self . stat . st_birthtime_nsec as libc:: c_long ,
403- } ) )
439+ Ok ( SystemTime :: new ( self . stat . st_birthtime as i64 , self . stat . st_birthtime_nsec as i64 ) )
404440 }
405441
406442 #[ cfg( not( any(
@@ -413,10 +449,7 @@ impl FileAttr {
413449 cfg_has_statx ! {
414450 if let Some ( ext) = & self . statx_extra_fields {
415451 return if ( ext. stx_mask & libc:: STATX_BTIME ) != 0 {
416- Ok ( SystemTime :: from( libc:: timespec {
417- tv_sec: ext. stx_btime. tv_sec as libc:: time_t,
418- tv_nsec: ext. stx_btime. tv_nsec as _,
419- } ) )
452+ Ok ( SystemTime :: new( ext. stx_btime. tv_sec, ext. stx_btime. tv_nsec as i64 ) )
420453 } else {
421454 Err ( io:: const_io_error!(
422455 io:: ErrorKind :: Uncategorized ,
0 commit comments