From 2f9f29deb5d435b982365a3dee29853ac4a4c9ff Mon Sep 17 00:00:00 2001 From: arookieofc <2128194521@qq.com> Date: Fri, 5 Jun 2026 22:49:55 +0800 Subject: [PATCH 1/3] fix: remove Windows directory symlinks recursively --- src/uu/rm/src/rm.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index f9aba615f51..d9804a3631a 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -458,7 +458,9 @@ fn count_files_in_directory(p: &Path) -> u64 { entries .flatten() .map(|entry| match entry.file_type() { - Ok(ft) if ft.is_dir() => count_files_in_directory(&entry.path()), + Ok(ft) if ft.is_dir() && !ft.is_symlink() => { + count_files_in_directory(&entry.path()) + } Ok(_) => 1, Err(_) => 0, }) @@ -592,7 +594,14 @@ fn remove_dir_recursive( // a directory and we don't want to recurse. In particular, this // avoids an infinite recursion in the case of a link to the current // directory, like `ln -s . link`. - if !path.is_dir() || path.is_symlink() { + let metadata = match fs::symlink_metadata(path) { + Ok(metadata) => metadata, + Err(e) => return show_removal_error(e, path), + }; + if is_symlink_dir(&metadata) { + return remove_dir(path, options, progress_bar); + } + if !metadata.is_dir() || metadata.file_type().is_symlink() { return remove_file(path, options, progress_bar); } From 73ca8bb9e55d06e1a6571109738b4207e051c3cf Mon Sep 17 00:00:00 2001 From: arookieofc <2128194521@qq.com> Date: Mon, 8 Jun 2026 19:22:24 +0800 Subject: [PATCH 2/3] test: cover Windows directory symlink removal --- tests/by-util/test_rm.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/by-util/test_rm.rs b/tests/by-util/test_rm.rs index 43c712e9c4b..e9b0c29e991 100644 --- a/tests/by-util/test_rm.rs +++ b/tests/by-util/test_rm.rs @@ -300,9 +300,11 @@ fn test_symlink_dir() { let at = &scene.fixtures; let dir = "test_rm_symlink_dir_directory"; + let file = "test_rm_symlink_dir_directory/file"; let link = "test_rm_symlink_dir_link"; at.mkdir(dir); + at.touch(file); at.symlink_dir(dir, link); scene @@ -314,6 +316,9 @@ fn test_symlink_dir() { assert!(at.dir_exists(link)); scene.ucmd().arg("-r").arg(link).succeeds(); + assert!(!at.dir_exists(link)); + assert!(at.dir_exists(dir)); + assert!(at.file_exists(file)); } #[test] From ae9a58241a144dcfd2b537f3d348a5d3e53be921 Mon Sep 17 00:00:00 2001 From: arookieofc <2128194521@qq.com> Date: Mon, 8 Jun 2026 20:29:22 +0800 Subject: [PATCH 3/3] test: tolerate coverage diagnostics in mkfifo stderr --- tests/by-util/test_mkfifo.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/by-util/test_mkfifo.rs b/tests/by-util/test_mkfifo.rs index 02fa91b2a52..ae5fffc4c39 100644 --- a/tests/by-util/test_mkfifo.rs +++ b/tests/by-util/test_mkfifo.rs @@ -83,7 +83,7 @@ fn test_create_one_fifo_already_exists() { .arg("abcdef") .arg("abcdef") .fails() - .stderr_is("mkfifo: cannot create fifo 'abcdef': File exists\n"); + .stderr_contains("mkfifo: cannot create fifo 'abcdef': File exists"); } #[test]