@@ -113,10 +113,19 @@ cfg_has_statx! {{
113
113
// This is needed to check if btime is supported by the filesystem.
114
114
stx_mask: u32 ,
115
115
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
+
116
124
}
117
125
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`.
120
129
unsafe fn try_statx(
121
130
fd: c_int,
122
131
path: * const c_char,
@@ -192,6 +201,13 @@ cfg_has_statx! {{
192
201
let extra = StatxExtraFields {
193
202
stx_mask: buf. stx_mask,
194
203
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,
195
211
} ;
196
212
197
213
Some ( Ok ( FileAttr { stat, statx_extra_fields: Some ( extra) } ) )
@@ -310,6 +326,36 @@ cfg_has_statx! {{
310
326
fn from_stat64( stat: stat64) -> Self {
311
327
Self { stat, statx_extra_fields: None }
312
328
}
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
+ }
313
359
}
314
360
} else {
315
361
impl FileAttr {
@@ -335,59 +381,52 @@ impl FileAttr {
335
381
#[ cfg( target_os = "netbsd" ) ]
336
382
impl FileAttr {
337
383
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 ) )
342
385
}
343
386
344
387
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 ) )
349
389
}
350
390
351
391
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 ) )
356
393
}
357
394
}
358
395
359
396
#[ cfg( not( target_os = "netbsd" ) ) ]
360
397
impl FileAttr {
361
398
#[ cfg( all( not( target_os = "vxworks" ) , not( target_os = "espidf" ) ) ) ]
362
399
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 ) )
367
408
}
368
409
369
410
#[ cfg( any( target_os = "vxworks" , target_os = "espidf" ) ) ]
370
411
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 ) )
375
413
}
376
414
377
415
#[ cfg( all( not( target_os = "vxworks" ) , not( target_os = "espidf" ) ) ) ]
378
416
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 ) )
383
425
}
384
426
385
427
#[ cfg( any( target_os = "vxworks" , target_os = "espidf" ) ) ]
386
428
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 ) )
391
430
}
392
431
393
432
#[ cfg( any(
@@ -397,10 +436,7 @@ impl FileAttr {
397
436
target_os = "ios"
398
437
) ) ]
399
438
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 ) )
404
440
}
405
441
406
442
#[ cfg( not( any(
@@ -413,10 +449,7 @@ impl FileAttr {
413
449
cfg_has_statx ! {
414
450
if let Some ( ext) = & self . statx_extra_fields {
415
451
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 ) )
420
453
} else {
421
454
Err ( io:: const_io_error!(
422
455
io:: ErrorKind :: Uncategorized ,
0 commit comments