1- // This file is derived from Rust's library/std/src/fs.rs at revision
2- // 108e90ca78f052c0c1c49c42a22c85620be19712 .
3- //
4- // This is the contents of the `tests` module, ported to use `cap_std`.
1+ // This file is derived from Rust's library/std/src/fs/tests .rs at revision
2+ // e4b1d5841494d6eb7f4944c91a057e16b0f0a9ea .
3+
4+ #! [ cfg_attr ( io_error_uncategorized , feature ( io_error_uncategorized ) ) ]
55
66#[ macro_use]
77mod sys_common;
8+ #[ macro_use]
9+ mod sys;
810
911use std:: io:: prelude:: * ;
1012
13+ #[ cfg( target_os = "macos" ) ]
14+ use crate :: sys:: weak:: weak;
1115use cap_std:: ambient_authority;
1216use cap_std:: fs:: { self , Dir , OpenOptions } ;
17+ #[ cfg( target_os = "macos" ) ]
18+ use libc:: { c_char, c_int} ;
1319use std:: io:: { self , ErrorKind , SeekFrom } ;
1420use std:: path:: { Path , PathBuf } ;
1521use std:: str;
@@ -59,13 +65,23 @@ pub fn got_symlink_permission(tmpdir: &TempDir) -> bool {
5965 let link = "some_hopefully_unique_link_name" ;
6066
6167 match symlink_file ( r"nonexisting_target" , tmpdir, link) {
62- Ok ( _) => true ,
6368 // ERROR_PRIVILEGE_NOT_HELD = 1314
6469 Err ( ref err) if err. raw_os_error ( ) == Some ( 1314 ) => false ,
65- Err ( _) => true ,
70+ Ok ( _ ) | Err ( _) => true ,
6671 }
6772}
6873
74+ #[ cfg( target_os = "macos" ) ]
75+ fn able_to_not_follow_symlinks_while_hard_linking ( ) -> bool {
76+ weak ! ( fn linkat( c_int, * const c_char, c_int, * const c_char, c_int) -> c_int) ;
77+ linkat. get ( ) . is_some ( )
78+ }
79+
80+ #[ cfg( not( target_os = "macos" ) ) ]
81+ fn able_to_not_follow_symlinks_while_hard_linking ( ) -> bool {
82+ return true ;
83+ }
84+
6985#[ test]
7086fn file_test_io_smoke_test ( ) {
7187 let message = "it's alright. have a good time" ;
@@ -838,7 +854,7 @@ fn symlink_noexist() {
838854 } ;
839855
840856 // Use a relative path for testing. Symlinks get normalized by Windows,
841- // so we may not get the same path back for absolute paths
857+ // so we might not get the same path back for absolute paths
842858 check ! ( symlink_file( & "foo" , & tmpdir, "bar" ) ) ;
843859 assert_eq ! ( check!( tmpdir. read_link( "bar" ) ) . to_str( ) . unwrap( ) , "foo" ) ;
844860}
@@ -1386,8 +1402,15 @@ fn metadata_access_times() {
13861402 // Not always available
13871403 match ( a. created ( ) , b. created ( ) ) {
13881404 ( Ok ( t1) , Ok ( t2) ) => assert ! ( t1 <= t2) ,
1405+ #[ cfg( not( io_error_uncategorized) ) ]
13891406 ( Err ( e1) , Err ( e2) )
13901407 if e1. kind ( ) == ErrorKind :: Other && e2. kind ( ) == ErrorKind :: Other => { }
1408+ #[ cfg( io_error_uncategorized) ]
1409+ ( Err ( e1) , Err ( e2) )
1410+ if e1. kind ( ) == ErrorKind :: Uncategorized
1411+ && e2. kind ( ) == ErrorKind :: Uncategorized
1412+ || e1. kind ( ) == ErrorKind :: Unsupported
1413+ && e2. kind ( ) == ErrorKind :: Unsupported => { }
13911414 ( a, b) => panic ! (
13921415 "creation time must be always supported or not supported: {:?} {:?}" ,
13931416 a, b,
@@ -1403,6 +1426,9 @@ fn symlink_hard_link() {
14031426 if !got_symlink_permission ( & tmpdir) {
14041427 return ;
14051428 }
1429+ if !able_to_not_follow_symlinks_while_hard_linking ( ) {
1430+ return ;
1431+ }
14061432
14071433 // Create "file", a file.
14081434 check ! ( tmpdir. create( "file" ) ) ;
@@ -1453,3 +1479,41 @@ fn symlink_hard_link() {
14531479 . file_type( )
14541480 . is_symlink( ) ) ;
14551481}
1482+
1483+ /// Ensure `fs::create_dir` works on Windows with longer paths.
1484+ #[ test]
1485+ #[ cfg( windows) ]
1486+ fn create_dir_long_paths ( ) {
1487+ use std:: ffi:: OsStr ;
1488+ use std:: iter;
1489+ use std:: os:: windows:: ffi:: OsStrExt ;
1490+ const PATH_LEN : usize = 247 ;
1491+
1492+ let tmpdir = tmpdir ( ) ;
1493+ let mut path = PathBuf :: new ( ) ;
1494+ path. push ( "a" ) ;
1495+ let mut path = path. into_os_string ( ) ;
1496+
1497+ let utf16_len = path. encode_wide ( ) . count ( ) ;
1498+ if utf16_len >= PATH_LEN {
1499+ // Skip the test in the unlikely event the local user has a long temp directory
1500+ // path. This should not affect CI.
1501+ return ;
1502+ }
1503+ // Increase the length of the path.
1504+ path. extend ( iter:: repeat ( OsStr :: new ( "a" ) ) . take ( PATH_LEN - utf16_len) ) ;
1505+
1506+ // This should succeed.
1507+ tmpdir. create_dir ( & path) . unwrap ( ) ;
1508+
1509+ // This will fail if the path isn't converted to verbatim.
1510+ path. push ( "a" ) ;
1511+ tmpdir. create_dir ( & path) . unwrap ( ) ;
1512+
1513+ // #90940: Ensure an empty path returns the "Not Found" error.
1514+ let path = Path :: new ( "" ) ;
1515+ assert_eq ! (
1516+ tmpdir. canonicalize( path) . unwrap_err( ) . kind( ) ,
1517+ std:: io:: ErrorKind :: NotFound
1518+ ) ;
1519+ }
0 commit comments