Skip to content

Commit e06f692

Browse files
committed
Auto merge of #31468 - pitdicker:fs_tests_cleanup, r=alexcrichton
See #29412
2 parents 7fce503 + d1bfe9b commit e06f692

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

src/libstd/fs.rs

+34
Original file line numberDiff line numberDiff line change
@@ -1940,12 +1940,46 @@ mod tests {
19401940
check!(fs::create_dir_all(&d2));
19411941
check!(check!(File::create(&canary)).write(b"foo"));
19421942
check!(symlink_junction(&d2, &dt.join("d2")));
1943+
let _ = symlink_file(&canary, &d1.join("canary"));
19431944
check!(fs::remove_dir_all(&d1));
19441945

19451946
assert!(!d1.is_dir());
19461947
assert!(canary.exists());
19471948
}
19481949

1950+
#[test]
1951+
fn recursive_rmdir_of_symlink() {
1952+
// test we do not recursively delete a symlink but only dirs.
1953+
let tmpdir = tmpdir();
1954+
let link = tmpdir.join("d1");
1955+
let dir = tmpdir.join("d2");
1956+
let canary = dir.join("do_not_delete");
1957+
check!(fs::create_dir_all(&dir));
1958+
check!(check!(File::create(&canary)).write(b"foo"));
1959+
check!(symlink_junction(&dir, &link));
1960+
check!(fs::remove_dir_all(&link));
1961+
1962+
assert!(!link.is_dir());
1963+
assert!(canary.exists());
1964+
}
1965+
1966+
#[test]
1967+
// only Windows makes a distinction between file and directory symlinks.
1968+
#[cfg(windows)]
1969+
fn recursive_rmdir_of_file_symlink() {
1970+
let tmpdir = tmpdir();
1971+
if !got_symlink_permission(&tmpdir) { return };
1972+
1973+
let f1 = tmpdir.join("f1");
1974+
let f2 = tmpdir.join("f2");
1975+
check!(check!(File::create(&f1)).write(b"foo"));
1976+
check!(symlink_file(&f1, &f2));
1977+
match fs::remove_dir_all(&f2) {
1978+
Ok(..) => panic!("wanted a failure"),
1979+
Err(..) => {}
1980+
}
1981+
}
1982+
19491983
#[test]
19501984
fn unicode_path_is_dir() {
19511985
assert!(Path::new(".").is_dir());

src/libstd/sys/unix/fs.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -627,10 +627,19 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
627627
}
628628

629629
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
630+
let filetype = try!(lstat(path)).file_type();
631+
if filetype.is_symlink() {
632+
unlink(path)
633+
} else {
634+
remove_dir_all_recursive(path)
635+
}
636+
}
637+
638+
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
630639
for child in try!(readdir(path)) {
631640
let child = try!(child);
632641
if try!(child.file_type()).is_dir() {
633-
try!(remove_dir_all(&child.path()));
642+
try!(remove_dir_all_recursive(&child.path()));
634643
} else {
635644
try!(unlink(&child.path()));
636645
}

src/libstd/sys/windows/fs.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -552,11 +552,22 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
552552
}
553553

554554
pub fn remove_dir_all(path: &Path) -> io::Result<()> {
555+
let filetype = try!(lstat(path)).file_type();
556+
if filetype.is_symlink() {
557+
// On Windows symlinks to files and directories are removed differently.
558+
// rmdir only deletes dir symlinks and junctions, not file symlinks.
559+
rmdir(path)
560+
} else {
561+
remove_dir_all_recursive(path)
562+
}
563+
}
564+
565+
fn remove_dir_all_recursive(path: &Path) -> io::Result<()> {
555566
for child in try!(readdir(path)) {
556567
let child = try!(child);
557568
let child_type = try!(child.file_type());
558569
if child_type.is_dir() {
559-
try!(remove_dir_all(&child.path()));
570+
try!(remove_dir_all_recursive(&child.path()));
560571
} else if child_type.is_symlink_dir() {
561572
try!(rmdir(&child.path()));
562573
} else {

0 commit comments

Comments
 (0)