@@ -2226,3 +2226,124 @@ fn test_open_options_invalid_combinations() {
22262226 assert_eq ! ( err. kind( ) , ErrorKind :: InvalidInput ) ;
22272227 assert_eq ! ( err. to_string( ) , "must specify at least one of read, write, or append access" ) ;
22282228}
2229+
2230+ #[ test]
2231+ fn test_fs_set_times ( ) {
2232+ #[ cfg( target_vendor = "apple" ) ]
2233+ use crate :: os:: darwin:: fs:: FileTimesExt ;
2234+ #[ cfg( windows) ]
2235+ use crate :: os:: windows:: fs:: FileTimesExt ;
2236+
2237+ let tmp = tmpdir ( ) ;
2238+ let path = tmp. join ( "foo" ) ;
2239+ File :: create ( & path) . unwrap ( ) ;
2240+
2241+ let mut times = FileTimes :: new ( ) ;
2242+ let accessed = SystemTime :: UNIX_EPOCH + Duration :: from_secs ( 12345 ) ;
2243+ let modified = SystemTime :: UNIX_EPOCH + Duration :: from_secs ( 54321 ) ;
2244+ times = times. set_accessed ( accessed) . set_modified ( modified) ;
2245+
2246+ #[ cfg( any( windows, target_vendor = "apple" ) ) ]
2247+ let created = SystemTime :: UNIX_EPOCH + Duration :: from_secs ( 32123 ) ;
2248+ #[ cfg( any( windows, target_vendor = "apple" ) ) ]
2249+ {
2250+ times = times. set_created ( created) ;
2251+ }
2252+
2253+ match fs:: set_times ( & path, times) {
2254+ // Allow unsupported errors on platforms which don't support setting times.
2255+ #[ cfg( not( any(
2256+ windows,
2257+ all(
2258+ unix,
2259+ not( any(
2260+ target_os = "android" ,
2261+ target_os = "redox" ,
2262+ target_os = "espidf" ,
2263+ target_os = "horizon"
2264+ ) )
2265+ )
2266+ ) ) ) ]
2267+ Err ( e) if e. kind ( ) == ErrorKind :: Unsupported => return ,
2268+ Err ( e) => panic ! ( "error setting file times: {e:?}" ) ,
2269+ Ok ( _) => { }
2270+ }
2271+
2272+ let metadata = fs:: metadata ( & path) . unwrap ( ) ;
2273+ assert_eq ! ( metadata. accessed( ) . unwrap( ) , accessed) ;
2274+ assert_eq ! ( metadata. modified( ) . unwrap( ) , modified) ;
2275+ #[ cfg( any( windows, target_vendor = "apple" ) ) ]
2276+ {
2277+ assert_eq ! ( metadata. created( ) . unwrap( ) , created) ;
2278+ }
2279+ }
2280+
2281+ #[ test]
2282+ fn test_fs_set_times_nofollow ( ) {
2283+ #[ cfg( target_vendor = "apple" ) ]
2284+ use crate :: os:: darwin:: fs:: FileTimesExt ;
2285+ #[ cfg( windows) ]
2286+ use crate :: os:: windows:: fs:: FileTimesExt ;
2287+
2288+ let tmp = tmpdir ( ) ;
2289+
2290+ // Create a target file and a symlink to it
2291+ let target = tmp. join ( "target" ) ;
2292+ File :: create ( & target) . unwrap ( ) ;
2293+
2294+ #[ cfg( unix) ]
2295+ let link = tmp. join ( "link" ) ;
2296+ #[ cfg( unix) ]
2297+ crate :: os:: unix:: fs:: symlink ( & target, & link) . unwrap ( ) ;
2298+
2299+ #[ cfg( windows) ]
2300+ let link = tmp. join ( "link.txt" ) ;
2301+ #[ cfg( windows) ]
2302+ crate :: os:: windows:: fs:: symlink_file ( & target, & link) . unwrap ( ) ;
2303+
2304+ let mut times = FileTimes :: new ( ) ;
2305+ let accessed = SystemTime :: UNIX_EPOCH + Duration :: from_secs ( 11111 ) ;
2306+ let modified = SystemTime :: UNIX_EPOCH + Duration :: from_secs ( 22222 ) ;
2307+ times = times. set_accessed ( accessed) . set_modified ( modified) ;
2308+
2309+ #[ cfg( any( windows, target_vendor = "apple" ) ) ]
2310+ let created = SystemTime :: UNIX_EPOCH + Duration :: from_secs ( 33333 ) ;
2311+ #[ cfg( any( windows, target_vendor = "apple" ) ) ]
2312+ {
2313+ times = times. set_created ( created) ;
2314+ }
2315+
2316+ // Set times on the symlink itself (not following it)
2317+ match fs:: set_times_nofollow ( & link, times) {
2318+ // Allow unsupported errors on platforms which don't support setting times.
2319+ #[ cfg( not( any(
2320+ windows,
2321+ all(
2322+ unix,
2323+ not( any(
2324+ target_os = "android" ,
2325+ target_os = "redox" ,
2326+ target_os = "espidf" ,
2327+ target_os = "horizon"
2328+ ) )
2329+ )
2330+ ) ) ) ]
2331+ Err ( e) if e. kind ( ) == ErrorKind :: Unsupported => return ,
2332+ Err ( e) => panic ! ( "error setting symlink times: {e:?}" ) ,
2333+ Ok ( _) => { }
2334+ }
2335+
2336+ // Read symlink metadata (without following)
2337+ let metadata = fs:: symlink_metadata ( & link) . unwrap ( ) ;
2338+ assert_eq ! ( metadata. accessed( ) . unwrap( ) , accessed) ;
2339+ assert_eq ! ( metadata. modified( ) . unwrap( ) , modified) ;
2340+ #[ cfg( any( windows, target_vendor = "apple" ) ) ]
2341+ {
2342+ assert_eq ! ( metadata. created( ) . unwrap( ) , created) ;
2343+ }
2344+
2345+ // Verify that the target file's times were NOT changed
2346+ let target_metadata = fs:: metadata ( & target) . unwrap ( ) ;
2347+ assert_ne ! ( target_metadata. accessed( ) . unwrap( ) , accessed) ;
2348+ assert_ne ! ( target_metadata. modified( ) . unwrap( ) , modified) ;
2349+ }
0 commit comments