@@ -313,8 +313,11 @@ pub struct FilePermissions {
313
313
mode : mode_t ,
314
314
}
315
315
316
- #[ derive( Copy , Clone ) ]
317
- pub struct FileTimes ( [ libc:: timespec ; 2 ] ) ;
316
+ #[ derive( Copy , Clone , Debug , Default ) ]
317
+ pub struct FileTimes {
318
+ accessed : Option < SystemTime > ,
319
+ modified : Option < SystemTime > ,
320
+ }
318
321
319
322
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
320
323
pub struct FileType {
@@ -512,45 +515,11 @@ impl FilePermissions {
512
515
513
516
impl FileTimes {
514
517
pub fn set_accessed ( & mut self , t : SystemTime ) {
515
- self . 0 [ 0 ] = t . t . to_timespec ( ) . expect ( "Invalid system time" ) ;
518
+ self . accessed = Some ( t ) ;
516
519
}
517
520
518
521
pub fn set_modified ( & mut self , t : SystemTime ) {
519
- self . 0 [ 1 ] = t. t . to_timespec ( ) . expect ( "Invalid system time" ) ;
520
- }
521
- }
522
-
523
- struct TimespecDebugAdapter < ' a > ( & ' a libc:: timespec ) ;
524
-
525
- impl fmt:: Debug for TimespecDebugAdapter < ' _ > {
526
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
527
- f. debug_struct ( "timespec" )
528
- . field ( "tv_sec" , & self . 0 . tv_sec )
529
- . field ( "tv_nsec" , & self . 0 . tv_nsec )
530
- . finish ( )
531
- }
532
- }
533
-
534
- impl fmt:: Debug for FileTimes {
535
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
536
- f. debug_struct ( "FileTimes" )
537
- . field ( "accessed" , & TimespecDebugAdapter ( & self . 0 [ 0 ] ) )
538
- . field ( "modified" , & TimespecDebugAdapter ( & self . 0 [ 1 ] ) )
539
- . finish ( )
540
- }
541
- }
542
-
543
- impl Default for FileTimes {
544
- fn default ( ) -> Self {
545
- // Redox doesn't appear to support `UTIME_OMIT`, so we stub it out here, and always return
546
- // an error in `set_times`.
547
- // ESP-IDF and HorizonOS do not support `futimens` at all and the behavior for those OS is therefore
548
- // the same as for Redox.
549
- #[ cfg( any( target_os = "redox" , target_os = "espidf" , target_os = "horizon" ) ) ]
550
- let omit = libc:: timespec { tv_sec : 0 , tv_nsec : 0 } ;
551
- #[ cfg( not( any( target_os = "redox" , target_os = "espidf" , target_os = "horizon" ) ) ) ]
552
- let omit = libc:: timespec { tv_sec : 0 , tv_nsec : libc:: UTIME_OMIT as _ } ;
553
- Self ( [ omit; 2 ] )
522
+ self . modified = Some ( t) ;
554
523
}
555
524
}
556
525
@@ -1084,6 +1053,17 @@ impl File {
1084
1053
}
1085
1054
1086
1055
pub fn set_times ( & self , times : FileTimes ) -> io:: Result < ( ) > {
1056
+ #[ cfg( not( any( target_os = "redox" , target_os = "espidf" , target_os = "horizon" ) ) ) ]
1057
+ let to_timespec = |time : Option < SystemTime > | {
1058
+ match time {
1059
+ Some ( time) if let Some ( ts) = time. t . to_timespec ( ) => Ok ( ts) ,
1060
+ Some ( time) if time > crate :: sys:: time:: UNIX_EPOCH => Err ( io:: const_io_error!( io:: ErrorKind :: InvalidInput , "timestamp is too large to set as a file time" ) ) ,
1061
+ Some ( _) => Err ( io:: const_io_error!( io:: ErrorKind :: InvalidInput , "timestamp is too small to set as a file time" ) ) ,
1062
+ None => Ok ( libc:: timespec { tv_sec : 0 , tv_nsec : libc:: UTIME_OMIT as _ } ) ,
1063
+ }
1064
+ } ;
1065
+ #[ cfg( not( any( target_os = "redox" , target_os = "espidf" , target_os = "horizon" ) ) ) ]
1066
+ let times = [ to_timespec ( times. accessed ) ?, to_timespec ( times. modified ) ?] ;
1087
1067
cfg_if:: cfg_if! {
1088
1068
if #[ cfg( any( target_os = "redox" , target_os = "espidf" , target_os = "horizon" ) ) ] {
1089
1069
// Redox doesn't appear to support `UTIME_OMIT`.
@@ -1099,7 +1079,7 @@ impl File {
1099
1079
cvt( unsafe {
1100
1080
weak!( fn futimens( c_int, * const libc:: timespec) -> c_int) ;
1101
1081
match futimens. get( ) {
1102
- Some ( futimens) => futimens( self . as_raw_fd( ) , times. 0 . as_ptr( ) ) ,
1082
+ Some ( futimens) => futimens( self . as_raw_fd( ) , times. as_ptr( ) ) ,
1103
1083
#[ cfg( target_os = "macos" ) ]
1104
1084
None => {
1105
1085
fn ts_to_tv( ts: & libc:: timespec) -> libc:: timeval {
@@ -1108,7 +1088,7 @@ impl File {
1108
1088
tv_usec: ( ts. tv_nsec / 1000 ) as _
1109
1089
}
1110
1090
}
1111
- let timevals = [ ts_to_tv( & times. 0 [ 0 ] ) , ts_to_tv( & times. 0 [ 1 ] ) ] ;
1091
+ let timevals = [ ts_to_tv( & times[ 0 ] ) , ts_to_tv( & times[ 1 ] ) ] ;
1112
1092
libc:: futimes( self . as_raw_fd( ) , timevals. as_ptr( ) )
1113
1093
}
1114
1094
// futimes requires even newer Android.
@@ -1121,7 +1101,7 @@ impl File {
1121
1101
} ) ?;
1122
1102
Ok ( ( ) )
1123
1103
} else {
1124
- cvt( unsafe { libc:: futimens( self . as_raw_fd( ) , times. 0 . as_ptr( ) ) } ) ?;
1104
+ cvt( unsafe { libc:: futimens( self . as_raw_fd( ) , times. as_ptr( ) ) } ) ?;
1125
1105
Ok ( ( ) )
1126
1106
}
1127
1107
}
0 commit comments