From 9ffb00cd5117a71f71e51ec74f6fa9f3e78f3d57 Mon Sep 17 00:00:00 2001 From: Stefin Date: Sat, 20 Aug 2022 18:38:10 +0530 Subject: [PATCH 1/5] rm: added write-protected check for files Signed-off-by: Stefin --- src/uu/rm/src/rm.rs | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index a55d3f2d1..32d50ee93 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -14,6 +14,8 @@ use clap::{crate_version, Arg, Command}; use remove_dir_all::remove_dir_all; use std::collections::VecDeque; use std::fs; +use std::fs::File; +use std::io::ErrorKind; use std::io::{stderr, stdin, BufRead, Write}; use std::ops::BitOr; use std::path::{Path, PathBuf}; @@ -384,7 +386,7 @@ fn remove_file(path: &Path, options: &Options) -> bool { } else { true }; - if response { + if response && prompt_write_protected(path, false) { match fs::remove_file(path) { Ok(_) => { if options.verbose { @@ -406,6 +408,23 @@ fn remove_file(path: &Path, options: &Options) -> bool { false } +fn prompt_write_protected(path: &Path, is_dir: bool) -> bool { + match File::open(path) { + Ok(_) => true, + Err(err) => { + if err.kind() == ErrorKind::PermissionDenied { + if is_dir { + prompt(&(format!("rm: remove write-protected directory {}? ", path.quote()))) + } else { + prompt(&(format!("rm: remove write-protected file {}? ", path.quote()))) + } + } else { + true + } + } + } +} + fn prompt_file(path: &Path, is_dir: bool) -> bool { if is_dir { prompt(&(format!("rm: remove directory {}? ", path.quote()))) From a8326d7f3f92b7aac371d79a5fc00a22d19dcc3a Mon Sep 17 00:00:00 2001 From: Stefin Date: Tue, 23 Aug 2022 19:33:34 +0530 Subject: [PATCH 2/5] rm: added new InteractiveMode InteractiveMode::Never Signed-off-by: Stefin --- src/uu/rm/src/rm.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index 32d50ee93..96ab77431 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -29,6 +29,7 @@ enum InteractiveMode { Never, Once, Always, + Default, } struct Options { @@ -114,7 +115,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } } } else { - InteractiveMode::Never + InteractiveMode::Default } }, one_fs: matches.contains_id(OPT_ONE_FILE_SYSTEM), @@ -386,7 +387,7 @@ fn remove_file(path: &Path, options: &Options) -> bool { } else { true }; - if response && prompt_write_protected(path, false) { + if response && prompt_write_protected(path, false, options) { match fs::remove_file(path) { Ok(_) => { if options.verbose { @@ -408,7 +409,10 @@ fn remove_file(path: &Path, options: &Options) -> bool { false } -fn prompt_write_protected(path: &Path, is_dir: bool) -> bool { +fn prompt_write_protected(path: &Path, is_dir: bool, options: &Options) -> bool { + if options.interactive == InteractiveMode::Never { + return true; + } match File::open(path) { Ok(_) => true, Err(err) => { From ad4eac867f4cd560ec8eee1d4beb409ab64e48a8 Mon Sep 17 00:00:00 2001 From: Stefin Date: Tue, 23 Aug 2022 21:17:48 +0530 Subject: [PATCH 3/5] rm: added test for rm_prompt_write_protected Signed-off-by: Stefin --- tests/by-util/test_rm.rs | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/by-util/test_rm.rs b/tests/by-util/test_rm.rs index e76593576..c752cc442 100644 --- a/tests/by-util/test_rm.rs +++ b/tests/by-util/test_rm.rs @@ -363,3 +363,33 @@ fn test_rm_directory_rights_rm1() { assert!(!at.dir_exists("b/c")); assert!(!at.dir_exists("b/d")); } + +#[test] +fn test_prompt_write_protected_yes() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let file_1 = "test_rm_prompt_write_protected_1"; + + at.touch(file_1); + + #[cfg(feature = "chmod")] + scene.ccmd("chmod").arg("0").arg(file_1).succeeds(); + + scene.ucmd().arg(file_1).pipe_in("y").succeeds(); + assert!(!at.file_exists(file_1)); +} + +#[test] +fn test_prompt_write_protected_no() { + let scene = TestScenario::new(util_name!()); + let at = &scene.fixtures; + let file_2 = "test_rm_prompt_write_protected_2"; + + at.touch(file_2); + + #[cfg(feature = "chmod")] + scene.ccmd("chmod").arg("0").arg(file_2).succeeds(); + + scene.ucmd().arg(file_2).pipe_in("n").succeeds(); + assert!(at.file_exists(file_2)); +} From 4c1c9ebf89eac19fb3b807da66fd0cdd941dbf47 Mon Sep 17 00:00:00 2001 From: Stefin Date: Sat, 27 Aug 2022 19:38:10 +0530 Subject: [PATCH 4/5] rm: change InteractiveMode::Default to InteractiveMode::PromptProtected Signed-off-by: Stefin --- src/uu/rm/src/rm.rs | 4 ++-- tests/by-util/test_rm.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index 96ab77431..80f1c8cd9 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -29,7 +29,7 @@ enum InteractiveMode { Never, Once, Always, - Default, + PromptProtected, } struct Options { @@ -115,7 +115,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { } } } else { - InteractiveMode::Default + InteractiveMode::PromptProtected } }, one_fs: matches.contains_id(OPT_ONE_FILE_SYSTEM), diff --git a/tests/by-util/test_rm.rs b/tests/by-util/test_rm.rs index c752cc442..c5c150371 100644 --- a/tests/by-util/test_rm.rs +++ b/tests/by-util/test_rm.rs @@ -364,6 +364,7 @@ fn test_rm_directory_rights_rm1() { assert!(!at.dir_exists("b/d")); } +#[cfg(feature = "chmod")] #[test] fn test_prompt_write_protected_yes() { let scene = TestScenario::new(util_name!()); @@ -372,13 +373,13 @@ fn test_prompt_write_protected_yes() { at.touch(file_1); - #[cfg(feature = "chmod")] scene.ccmd("chmod").arg("0").arg(file_1).succeeds(); scene.ucmd().arg(file_1).pipe_in("y").succeeds(); assert!(!at.file_exists(file_1)); } +#[cfg(feature = "chmod")] #[test] fn test_prompt_write_protected_no() { let scene = TestScenario::new(util_name!()); @@ -387,7 +388,6 @@ fn test_prompt_write_protected_no() { at.touch(file_2); - #[cfg(feature = "chmod")] scene.ccmd("chmod").arg("0").arg(file_2).succeeds(); scene.ucmd().arg(file_2).pipe_in("n").succeeds(); From a33bc185a5076ea5f6b478ec08b2a806773afb57 Mon Sep 17 00:00:00 2001 From: Stefin Date: Mon, 29 Aug 2022 18:09:02 +0530 Subject: [PATCH 5/5] rm: added check for write protected regular empty file Signed-off-by: Stefin --- src/uu/rm/src/rm.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index 80f1c8cd9..571a6d2c0 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -420,7 +420,15 @@ fn prompt_write_protected(path: &Path, is_dir: bool, options: &Options) -> bool if is_dir { prompt(&(format!("rm: remove write-protected directory {}? ", path.quote()))) } else { - prompt(&(format!("rm: remove write-protected file {}? ", path.quote()))) + if fs::metadata(path).unwrap().len() == 0 { + return prompt( + &(format!( + "rm: remove write-protected regular empty file {}? ", + path.quote() + )), + ); + } + prompt(&(format!("rm: remove write-protected regular file {}? ", path.quote()))) } } else { true