@@ -313,8 +313,11 @@ pub struct FilePermissions {
313313 mode : mode_t ,
314314}
315315
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+ }
318321
319322#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
320323pub struct FileType {
@@ -512,45 +515,11 @@ impl FilePermissions {
512515
513516impl FileTimes {
514517 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 ) ;
516519 }
517520
518521 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) ;
554523 }
555524}
556525
@@ -1084,6 +1053,17 @@ impl File {
10841053 }
10851054
10861055 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 ) ?] ;
10871067 cfg_if:: cfg_if! {
10881068 if #[ cfg( any( target_os = "redox" , target_os = "espidf" , target_os = "horizon" ) ) ] {
10891069 // Redox doesn't appear to support `UTIME_OMIT`.
@@ -1099,7 +1079,7 @@ impl File {
10991079 cvt( unsafe {
11001080 weak!( fn futimens( c_int, * const libc:: timespec) -> c_int) ;
11011081 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( ) ) ,
11031083 #[ cfg( target_os = "macos" ) ]
11041084 None => {
11051085 fn ts_to_tv( ts: & libc:: timespec) -> libc:: timeval {
@@ -1108,7 +1088,7 @@ impl File {
11081088 tv_usec: ( ts. tv_nsec / 1000 ) as _
11091089 }
11101090 }
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 ] ) ] ;
11121092 libc:: futimes( self . as_raw_fd( ) , timevals. as_ptr( ) )
11131093 }
11141094 // futimes requires even newer Android.
@@ -1121,7 +1101,7 @@ impl File {
11211101 } ) ?;
11221102 Ok ( ( ) )
11231103 } 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( ) ) } ) ?;
11251105 Ok ( ( ) )
11261106 }
11271107 }
0 commit comments