@@ -1253,20 +1253,7 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
1253
1253
/// ```
1254
1254
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
1255
1255
pub fn remove_dir_all < P : AsRef < Path > > ( path : P ) -> io:: Result < ( ) > {
1256
- _remove_dir_all ( path. as_ref ( ) )
1257
- }
1258
-
1259
- fn _remove_dir_all ( path : & Path ) -> io:: Result < ( ) > {
1260
- for child in try!( read_dir ( path) ) {
1261
- let child = try!( child) . path ( ) ;
1262
- let stat = try!( symlink_metadata ( & * child) ) ;
1263
- if stat. is_dir ( ) {
1264
- try!( remove_dir_all ( & * child) ) ;
1265
- } else {
1266
- try!( remove_file ( & * child) ) ;
1267
- }
1268
- }
1269
- remove_dir ( path)
1256
+ fs_imp:: remove_dir_all ( path. as_ref ( ) )
1270
1257
}
1271
1258
1272
1259
/// Returns an iterator over the entries within a directory.
@@ -1477,19 +1464,25 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
1477
1464
1478
1465
#[ cfg( test) ]
1479
1466
mod tests {
1480
- #![ allow( deprecated) ] //rand
1481
-
1482
1467
use prelude:: v1:: * ;
1483
1468
use io:: prelude:: * ;
1484
1469
1485
1470
use env;
1486
1471
use fs:: { self , File , OpenOptions } ;
1487
1472
use io:: { ErrorKind , SeekFrom } ;
1488
- use path:: PathBuf ;
1489
- use path:: Path as Path2 ;
1473
+ use path:: { Path , PathBuf } ;
1490
1474
use rand:: { self , StdRng , Rng } ;
1491
1475
use str;
1492
1476
1477
+ #[ cfg( windows) ]
1478
+ use os:: windows:: fs:: { symlink_dir, symlink_file, symlink_junction} ;
1479
+ #[ cfg( unix) ]
1480
+ use os:: unix:: fs:: symlink as symlink_dir;
1481
+ #[ cfg( unix) ]
1482
+ use os:: unix:: fs:: symlink as symlink_file;
1483
+ #[ cfg( unix) ]
1484
+ use os:: unix:: fs:: symlink as symlink_junction;
1485
+
1493
1486
macro_rules! check { ( $e: expr) => (
1494
1487
match $e {
1495
1488
Ok ( t) => t,
@@ -1513,7 +1506,7 @@ mod tests {
1513
1506
p. join ( path)
1514
1507
}
1515
1508
1516
- fn path < ' a > ( & ' a self ) -> & ' a Path2 {
1509
+ fn path < ' a > ( & ' a self ) -> & ' a Path {
1517
1510
let TempDir ( ref p) = * self ;
1518
1511
p
1519
1512
}
@@ -1536,6 +1529,24 @@ mod tests {
1536
1529
TempDir ( ret)
1537
1530
}
1538
1531
1532
+ // Several test fail on windows if the user does not have permission to create symlinks (the
1533
+ // `SeCreateSymbolicLinkPrivilege`). Instead of disabling these test on Windows, use this
1534
+ // function to test whether we have permission, and return otherwise. This way, we still don't
1535
+ // run these tests most of the time, but at least we do if the user has the right permissions.
1536
+ pub fn got_symlink_permission ( tmpdir : & TempDir ) -> bool {
1537
+ let link = tmpdir. join ( "some_hopefully_unique_link_name" ) ;
1538
+
1539
+ match symlink_file ( r"nonexisting_target" , link) {
1540
+ Ok ( _) => true ,
1541
+ Err ( ref err) =>
1542
+ if err. to_string ( ) . contains ( "A required privilege is not held by the client." ) {
1543
+ false
1544
+ } else {
1545
+ true
1546
+ }
1547
+ }
1548
+ }
1549
+
1539
1550
#[ test]
1540
1551
fn file_test_io_smoke_test ( ) {
1541
1552
let message = "it's alright. have a good time" ;
@@ -1566,8 +1577,9 @@ mod tests {
1566
1577
if cfg ! ( unix) {
1567
1578
error ! ( result, "o such file or directory" ) ;
1568
1579
}
1569
- // error!(result, "couldn't open path as file");
1570
- // error!(result, format!("path={}; mode=open; access=read", filename.display()));
1580
+ if cfg ! ( windows) {
1581
+ error ! ( result, "The system cannot find the file specified" ) ;
1582
+ }
1571
1583
}
1572
1584
1573
1585
#[ test]
@@ -1580,8 +1592,9 @@ mod tests {
1580
1592
if cfg ! ( unix) {
1581
1593
error ! ( result, "o such file or directory" ) ;
1582
1594
}
1583
- // error!(result, "couldn't unlink path");
1584
- // error!(result, format!("path={}", filename.display()));
1595
+ if cfg ! ( windows) {
1596
+ error ! ( result, "The system cannot find the file specified" ) ;
1597
+ }
1585
1598
}
1586
1599
1587
1600
#[ test]
@@ -1787,6 +1800,7 @@ mod tests {
1787
1800
}
1788
1801
1789
1802
#[ test]
1803
+ #[ allow( deprecated) ]
1790
1804
fn file_test_walk_dir ( ) {
1791
1805
let tmpdir = tmpdir ( ) ;
1792
1806
let dir = & tmpdir. join ( "walk_dir" ) ;
@@ -1843,19 +1857,13 @@ mod tests {
1843
1857
let result = fs:: create_dir_all ( & file) ;
1844
1858
1845
1859
assert ! ( result. is_err( ) ) ;
1846
- // error!(result, "couldn't recursively mkdir");
1847
- // error!(result, "couldn't create directory");
1848
- // error!(result, "mode=0700");
1849
- // error!(result, format!("path={}", file.display()));
1850
1860
}
1851
1861
1852
1862
#[ test]
1853
1863
fn recursive_mkdir_slash ( ) {
1854
- check ! ( fs:: create_dir_all( & Path2 :: new( "/" ) ) ) ;
1864
+ check ! ( fs:: create_dir_all( & Path :: new( "/" ) ) ) ;
1855
1865
}
1856
1866
1857
- // FIXME(#12795) depends on lstat to work on windows
1858
- #[ cfg( not( windows) ) ]
1859
1867
#[ test]
1860
1868
fn recursive_rmdir ( ) {
1861
1869
let tmpdir = tmpdir ( ) ;
@@ -1867,7 +1875,7 @@ mod tests {
1867
1875
check ! ( fs:: create_dir_all( & dtt) ) ;
1868
1876
check ! ( fs:: create_dir_all( & d2) ) ;
1869
1877
check ! ( check!( File :: create( & canary) ) . write( b"foo" ) ) ;
1870
- check ! ( fs :: soft_link ( & d2, & dt. join( "d2" ) ) ) ;
1878
+ check ! ( symlink_junction ( & d2, & dt. join( "d2" ) ) ) ;
1871
1879
check ! ( fs:: remove_dir_all( & d1) ) ;
1872
1880
1873
1881
assert ! ( !d1. is_dir( ) ) ;
@@ -1876,8 +1884,8 @@ mod tests {
1876
1884
1877
1885
#[ test]
1878
1886
fn unicode_path_is_dir ( ) {
1879
- assert ! ( Path2 :: new( "." ) . is_dir( ) ) ;
1880
- assert ! ( !Path2 :: new( "test/stdtest/fs.rs" ) . is_dir( ) ) ;
1887
+ assert ! ( Path :: new( "." ) . is_dir( ) ) ;
1888
+ assert ! ( !Path :: new( "test/stdtest/fs.rs" ) . is_dir( ) ) ;
1881
1889
1882
1890
let tmpdir = tmpdir ( ) ;
1883
1891
@@ -1895,21 +1903,21 @@ mod tests {
1895
1903
1896
1904
#[ test]
1897
1905
fn unicode_path_exists ( ) {
1898
- assert ! ( Path2 :: new( "." ) . exists( ) ) ;
1899
- assert ! ( !Path2 :: new( "test/nonexistent-bogus-path" ) . exists( ) ) ;
1906
+ assert ! ( Path :: new( "." ) . exists( ) ) ;
1907
+ assert ! ( !Path :: new( "test/nonexistent-bogus-path" ) . exists( ) ) ;
1900
1908
1901
1909
let tmpdir = tmpdir ( ) ;
1902
1910
let unicode = tmpdir. path ( ) ;
1903
1911
let unicode = unicode. join ( & format ! ( "test-각丁ー再见" ) ) ;
1904
1912
check ! ( fs:: create_dir( & unicode) ) ;
1905
1913
assert ! ( unicode. exists( ) ) ;
1906
- assert ! ( !Path2 :: new( "test/unicode-bogus-path-각丁ー再见" ) . exists( ) ) ;
1914
+ assert ! ( !Path :: new( "test/unicode-bogus-path-각丁ー再见" ) . exists( ) ) ;
1907
1915
}
1908
1916
1909
1917
#[ test]
1910
1918
fn copy_file_does_not_exist ( ) {
1911
- let from = Path2 :: new ( "test/nonexistent-bogus-path" ) ;
1912
- let to = Path2 :: new ( "test/other-bogus-path" ) ;
1919
+ let from = Path :: new ( "test/nonexistent-bogus-path" ) ;
1920
+ let to = Path :: new ( "test/other-bogus-path" ) ;
1913
1921
1914
1922
match fs:: copy ( & from, & to) {
1915
1923
Ok ( ..) => panic ! ( ) ,
@@ -1923,7 +1931,7 @@ mod tests {
1923
1931
#[ test]
1924
1932
fn copy_src_does_not_exist ( ) {
1925
1933
let tmpdir = tmpdir ( ) ;
1926
- let from = Path2 :: new ( "test/nonexistent-bogus-path" ) ;
1934
+ let from = Path :: new ( "test/nonexistent-bogus-path" ) ;
1927
1935
let to = tmpdir. join ( "out.txt" ) ;
1928
1936
check ! ( check!( File :: create( & to) ) . write( b"hello" ) ) ;
1929
1937
assert ! ( fs:: copy( & from, & to) . is_err( ) ) ;
@@ -2014,34 +2022,34 @@ mod tests {
2014
2022
assert_eq ! ( v, b"carrot" . to_vec( ) ) ;
2015
2023
}
2016
2024
2017
- #[ cfg( not( windows) ) ] // FIXME(#10264) operation not permitted?
2018
2025
#[ test]
2019
2026
fn symlinks_work ( ) {
2020
2027
let tmpdir = tmpdir ( ) ;
2028
+ if !got_symlink_permission ( & tmpdir) { return } ;
2029
+
2021
2030
let input = tmpdir. join ( "in.txt" ) ;
2022
2031
let out = tmpdir. join ( "out.txt" ) ;
2023
2032
2024
2033
check ! ( check!( File :: create( & input) ) . write( "foobar" . as_bytes( ) ) ) ;
2025
- check ! ( fs:: soft_link( & input, & out) ) ;
2026
- // if cfg!(not(windows)) {
2027
- // assert_eq!(check!(lstat(&out)).kind, FileType::Symlink);
2028
- // assert_eq!(check!(out.lstat()).kind, FileType::Symlink);
2029
- // }
2034
+ check ! ( symlink_file( & input, & out) ) ;
2035
+ assert ! ( check!( out. symlink_metadata( ) ) . file_type( ) . is_symlink( ) ) ;
2030
2036
assert_eq ! ( check!( fs:: metadata( & out) ) . len( ) ,
2031
2037
check!( fs:: metadata( & input) ) . len( ) ) ;
2032
2038
let mut v = Vec :: new ( ) ;
2033
2039
check ! ( check!( File :: open( & out) ) . read_to_end( & mut v) ) ;
2034
2040
assert_eq ! ( v, b"foobar" . to_vec( ) ) ;
2035
2041
}
2036
2042
2037
- #[ cfg( not( windows) ) ] // apparently windows doesn't like symlinks
2038
2043
#[ test]
2039
2044
fn symlink_noexist ( ) {
2045
+ // Symlinks can point to things that don't exist
2040
2046
let tmpdir = tmpdir ( ) ;
2041
- // symlinks can point to things that don't exist
2042
- check ! ( fs:: soft_link( & tmpdir. join( "foo" ) , & tmpdir. join( "bar" ) ) ) ;
2043
- assert_eq ! ( check!( fs:: read_link( & tmpdir. join( "bar" ) ) ) ,
2044
- tmpdir. join( "foo" ) ) ;
2047
+ if !got_symlink_permission ( & tmpdir) { return } ;
2048
+
2049
+ // Use a relative path for testing. Symlinks get normalized by Windows, so we may not get
2050
+ // the same path back for absolute paths
2051
+ check ! ( symlink_file( & "foo" , & tmpdir. join( "bar" ) ) ) ;
2052
+ assert_eq ! ( check!( fs:: read_link( & tmpdir. join( "bar" ) ) ) . to_str( ) . unwrap( ) , "foo" ) ;
2045
2053
}
2046
2054
2047
2055
#[ test]
@@ -2312,9 +2320,10 @@ mod tests {
2312
2320
}
2313
2321
2314
2322
#[ test]
2315
- #[ cfg( not( windows) ) ]
2316
2323
fn realpath_works ( ) {
2317
2324
let tmpdir = tmpdir ( ) ;
2325
+ if !got_symlink_permission ( & tmpdir) { return } ;
2326
+
2318
2327
let tmpdir = fs:: canonicalize ( tmpdir. path ( ) ) . unwrap ( ) ;
2319
2328
let file = tmpdir. join ( "test" ) ;
2320
2329
let dir = tmpdir. join ( "test2" ) ;
@@ -2323,8 +2332,8 @@ mod tests {
2323
2332
2324
2333
File :: create ( & file) . unwrap ( ) ;
2325
2334
fs:: create_dir ( & dir) . unwrap ( ) ;
2326
- fs :: soft_link ( & file, & link) . unwrap ( ) ;
2327
- fs :: soft_link ( & dir, & linkdir) . unwrap ( ) ;
2335
+ symlink_file ( & file, & link) . unwrap ( ) ;
2336
+ symlink_dir ( & dir, & linkdir) . unwrap ( ) ;
2328
2337
2329
2338
assert ! ( link. symlink_metadata( ) . unwrap( ) . file_type( ) . is_symlink( ) ) ;
2330
2339
@@ -2336,11 +2345,11 @@ mod tests {
2336
2345
}
2337
2346
2338
2347
#[ test]
2339
- #[ cfg( not( windows) ) ]
2340
2348
fn realpath_works_tricky ( ) {
2341
2349
let tmpdir = tmpdir ( ) ;
2342
- let tmpdir = fs :: canonicalize ( tmpdir. path ( ) ) . unwrap ( ) ;
2350
+ if ! got_symlink_permission ( & tmpdir) { return } ;
2343
2351
2352
+ let tmpdir = fs:: canonicalize ( tmpdir. path ( ) ) . unwrap ( ) ;
2344
2353
let a = tmpdir. join ( "a" ) ;
2345
2354
let b = a. join ( "b" ) ;
2346
2355
let c = b. join ( "c" ) ;
@@ -2351,8 +2360,14 @@ mod tests {
2351
2360
fs:: create_dir_all ( & b) . unwrap ( ) ;
2352
2361
fs:: create_dir_all ( & d) . unwrap ( ) ;
2353
2362
File :: create ( & f) . unwrap ( ) ;
2354
- fs:: soft_link ( "../d/e" , & c) . unwrap ( ) ;
2355
- fs:: soft_link ( "../f" , & e) . unwrap ( ) ;
2363
+ if cfg ! ( not( windows) ) {
2364
+ symlink_dir ( "../d/e" , & c) . unwrap ( ) ;
2365
+ symlink_file ( "../f" , & e) . unwrap ( ) ;
2366
+ }
2367
+ if cfg ! ( windows) {
2368
+ symlink_dir ( r"..\d\e" , & c) . unwrap ( ) ;
2369
+ symlink_file ( r"..\f" , & e) . unwrap ( ) ;
2370
+ }
2356
2371
2357
2372
assert_eq ! ( fs:: canonicalize( & c) . unwrap( ) , f) ;
2358
2373
assert_eq ! ( fs:: canonicalize( & e) . unwrap( ) , f) ;
0 commit comments