From 4f6841df321850eae8d35932b3cdd48b8660f60f Mon Sep 17 00:00:00 2001 From: Shinichiro Hamaji Date: Sat, 1 Apr 2017 23:38:38 +0900 Subject: [PATCH 1/2] rm: Remove symlinks to directories without -r Path::is_dir follows symlinks so it returns true for symlinks to directories. Use symlink_metadata instead so you can remove symlinks to directories without -r flag. --- src/rm/rm.rs | 2 +- tests/test_rm.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/rm/rm.rs b/src/rm/rm.rs index 3dbee442f..087f73b9d 100644 --- a/src/rm/rm.rs +++ b/src/rm/rm.rs @@ -129,7 +129,7 @@ fn remove(files: Vec, force: bool, interactive: InteractiveMode, one_fs: let filename = &filename[..]; let file = Path::new(filename); if file.exists() { - if file.is_dir() { + if file.symlink_metadata().unwrap().is_dir() { if recursive && (filename != "/" || !preserve_root) { if interactive != InteractiveMode::InteractiveAlways { if let Err(e) = fs::remove_dir_all(file) { diff --git a/tests/test_rm.rs b/tests/test_rm.rs index a3cac9dbf..b0083e019 100644 --- a/tests/test_rm.rs +++ b/tests/test_rm.rs @@ -136,3 +136,15 @@ fn test_rm_verbose() { ucmd.arg("-v").arg(file_a).arg(file_b).succeeds() .stdout_only(format!("removed '{}'\nremoved '{}'\n", file_a, file_b)); } + +#[test] +fn test_rm_dir_symlink() { + let (at, mut ucmd) = at_and_ucmd!(); + let dir = "test_rm_dir_symlink_dir"; + let link = "test_rm_dir_symlink_link"; + + at.mkdir(dir); + at.symlink(dir, link); + + ucmd.arg(link).succeeds(); +} From bb1d8956eba4599af805857f4018b6e51ee51378 Mon Sep 17 00:00:00 2001 From: Shinichiro Hamaji Date: Tue, 4 Apr 2017 00:10:45 +0900 Subject: [PATCH 2/2] rm: Fail when symlink_metadata() fails --- src/rm/rm.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/rm/rm.rs b/src/rm/rm.rs index 087f73b9d..73c2d07ed 100644 --- a/src/rm/rm.rs +++ b/src/rm/rm.rs @@ -129,7 +129,15 @@ fn remove(files: Vec, force: bool, interactive: InteractiveMode, one_fs: let filename = &filename[..]; let file = Path::new(filename); if file.exists() { - if file.symlink_metadata().unwrap().is_dir() { + let is_dir = match file.symlink_metadata() { + Ok(metadata) => metadata.is_dir(), + Err(e) => { + had_err = true; + show_error!("could not read metadata of '{}': {}", filename, e); + continue; + } + }; + if is_dir { if recursive && (filename != "/" || !preserve_root) { if interactive != InteractiveMode::InteractiveAlways { if let Err(e) = fs::remove_dir_all(file) {