Skip to content

Commit

Permalink
Merge branch 'fix_3842' of github.com:jhscheer/coreutils into fix_3842
Browse files Browse the repository at this point in the history
  • Loading branch information
jhscheer committed Aug 31, 2022
2 parents 1864b46 + fbee4d1 commit ae94847
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/CICD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -921,7 +921,7 @@ jobs:
- uses: Swatinem/rust-cache@v1
- name: Prepare, build and test
## spell-checker:ignore (ToDO) sshfs usesh vmactions
uses: vmactions/[email protected].3
uses: vmactions/[email protected].4
with:
usesh: true
# sync: sshfs
Expand Down
8 changes: 4 additions & 4 deletions src/uu/realpath/src/realpath.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#[macro_use]
extern crate uucore;

use clap::{crate_version, Arg, ArgMatches, Command};
use clap::{builder::NonEmptyStringValueParser, crate_version, Arg, ArgMatches, Command};
use std::{
io::{stdout, Write},
path::{Path, PathBuf},
Expand Down Expand Up @@ -150,22 +150,22 @@ pub fn uu_app<'a>() -> Command<'a> {
.long(OPT_RELATIVE_TO)
.takes_value(true)
.value_name("DIR")
.forbid_empty_values(true)
.value_parser(NonEmptyStringValueParser::new())
.help("print the resolved path relative to DIR"),
)
.arg(
Arg::new(OPT_RELATIVE_BASE)
.long(OPT_RELATIVE_BASE)
.takes_value(true)
.value_name("DIR")
.forbid_empty_values(true)
.value_parser(NonEmptyStringValueParser::new())
.help("print absolute paths unless paths below DIR"),
)
.arg(
Arg::new(ARG_FILES)
.multiple_occurrences(true)
.required(true)
.forbid_empty_values(true)
.value_parser(NonEmptyStringValueParser::new())
.value_hint(clap::ValueHint::AnyPath),
)
}
Expand Down
35 changes: 33 additions & 2 deletions src/uu/rm/src/rm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -27,6 +29,7 @@ enum InteractiveMode {
Never,
Once,
Always,
PromptProtected,
}

struct Options {
Expand Down Expand Up @@ -112,7 +115,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
}
}
} else {
InteractiveMode::Never
InteractiveMode::PromptProtected
}
},
one_fs: matches.contains_id(OPT_ONE_FILE_SYSTEM),
Expand Down Expand Up @@ -384,7 +387,7 @@ fn remove_file(path: &Path, options: &Options) -> bool {
} else {
true
};
if response {
if response && prompt_write_protected(path, false, options) {
match fs::remove_file(path) {
Ok(_) => {
if options.verbose {
Expand All @@ -406,6 +409,34 @@ fn remove_file(path: &Path, options: &Options) -> bool {
false
}

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) => {
if err.kind() == ErrorKind::PermissionDenied {
if is_dir {
prompt(&(format!("rm: remove write-protected directory {}? ", path.quote())))
} else {
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
}
}
}
}

fn prompt_file(path: &Path, is_dir: bool) -> bool {
if is_dir {
prompt(&(format!("rm: remove directory {}? ", path.quote())))
Expand Down
30 changes: 30 additions & 0 deletions tests/by-util/test_rm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,3 +363,33 @@ fn test_rm_directory_rights_rm1() {
assert!(!at.dir_exists("b/c"));
assert!(!at.dir_exists("b/d"));
}

#[cfg(feature = "chmod")]
#[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);

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!());
let at = &scene.fixtures;
let file_2 = "test_rm_prompt_write_protected_2";

at.touch(file_2);

scene.ccmd("chmod").arg("0").arg(file_2).succeeds();

scene.ucmd().arg(file_2).pipe_in("n").succeeds();
assert!(at.file_exists(file_2));
}

0 comments on commit ae94847

Please sign in to comment.