@@ -20,7 +20,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
20
20
target_os = "watchos" ,
21
21
) ) ]
22
22
use crate :: sys:: weak:: syscall;
23
- #[ cfg( target_os = "macos" ) ]
23
+ #[ cfg( any ( target_os = "android" , target_os = " macos") ) ]
24
24
use crate :: sys:: weak:: weak;
25
25
26
26
use libc:: { c_int, mode_t} ;
@@ -313,6 +313,9 @@ pub struct FilePermissions {
313
313
mode : mode_t ,
314
314
}
315
315
316
+ #[ derive( Copy , Clone ) ]
317
+ pub struct FileTimes ( [ libc:: timespec ; 2 ] ) ;
318
+
316
319
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
317
320
pub struct FileType {
318
321
mode : mode_t ,
@@ -507,6 +510,48 @@ impl FilePermissions {
507
510
}
508
511
}
509
512
513
+ impl FileTimes {
514
+ pub fn set_accessed ( & mut self , t : SystemTime ) {
515
+ self . 0 [ 0 ] = t. t . to_timespec ( ) . expect ( "Invalid system time" ) ;
516
+ }
517
+
518
+ 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
+ #[ cfg( target_os = "redox" ) ]
548
+ let omit = libc:: timespec { tv_sec : 0 , tv_nsec : 0 } ;
549
+ #[ cfg( not( target_os = "redox" ) ) ]
550
+ let omit = libc:: timespec { tv_sec : 0 , tv_nsec : libc:: UTIME_OMIT as _ } ;
551
+ Self ( [ omit; 2 ] )
552
+ }
553
+ }
554
+
510
555
impl FileType {
511
556
pub fn is_dir ( & self ) -> bool {
512
557
self . is ( libc:: S_IFDIR )
@@ -1029,6 +1074,48 @@ impl File {
1029
1074
cvt_r ( || unsafe { libc:: fchmod ( self . as_raw_fd ( ) , perm. mode ) } ) ?;
1030
1075
Ok ( ( ) )
1031
1076
}
1077
+
1078
+ pub fn set_times ( & self , times : FileTimes ) -> io:: Result < ( ) > {
1079
+ cfg_if:: cfg_if! {
1080
+ if #[ cfg( target_os = "redox" ) ] {
1081
+ // Redox doesn't appear to support `UTIME_OMIT`.
1082
+ drop( times) ;
1083
+ Err ( io:: const_io_error!(
1084
+ io:: ErrorKind :: Unsupported ,
1085
+ "setting file times not supported" ,
1086
+ ) )
1087
+ } else if #[ cfg( any( target_os = "android" , target_os = "macos" ) ) ] {
1088
+ // futimens requires macOS 10.13, and Android API level 19
1089
+ cvt( unsafe {
1090
+ weak!( fn futimens( c_int, * const libc:: timespec) -> c_int) ;
1091
+ match futimens. get( ) {
1092
+ Some ( futimens) => futimens( self . as_raw_fd( ) , times. 0 . as_ptr( ) ) ,
1093
+ #[ cfg( target_os = "macos" ) ]
1094
+ None => {
1095
+ fn ts_to_tv( ts: & libc:: timespec) -> libc:: timeval {
1096
+ libc:: timeval {
1097
+ tv_sec: ts. tv_sec,
1098
+ tv_usec: ( ts. tv_nsec / 1000 ) as _
1099
+ }
1100
+ }
1101
+ let timevals = [ ts_to_tv( & times. 0 [ 0 ] ) , ts_to_tv( & times. 0 [ 1 ] ) ] ;
1102
+ libc:: futimes( self . as_raw_fd( ) , timevals. as_ptr( ) )
1103
+ }
1104
+ // futimes requires even newer Android.
1105
+ #[ cfg( target_os = "android" ) ]
1106
+ None => return Err ( io:: const_io_error!(
1107
+ io:: ErrorKind :: Unsupported ,
1108
+ "setting file times requires Android API level >= 19" ,
1109
+ ) ) ,
1110
+ }
1111
+ } ) ?;
1112
+ Ok ( ( ) )
1113
+ } else {
1114
+ cvt( unsafe { libc:: futimens( self . as_raw_fd( ) , times. 0 . as_ptr( ) ) } ) ?;
1115
+ Ok ( ( ) )
1116
+ }
1117
+ }
1118
+ }
1032
1119
}
1033
1120
1034
1121
impl DirBuilder {
0 commit comments