Skip to content

Commit

Permalink
cp: show mode if target does not have S_IWUSR
Browse files Browse the repository at this point in the history
If the target exists, and does not have the user write bit (S_IWUSR)
set, additional information should be added to the overwrite
confirmation prompt.

This should get the "i-2" test to pass. See
#6658.
  • Loading branch information
andrewliebenow committed Sep 15, 2024
1 parent a275080 commit e2a8e86
Showing 1 changed file with 50 additions and 1 deletion.
51 changes: 50 additions & 1 deletion src/uu/cp/src/cp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1410,7 +1410,56 @@ impl OverwriteMode {
Err(Error::Skipped(false))
}
Self::Interactive(_) => {
if prompt_yes!("overwrite {}?", path.quote()) {
// TODO
// The destination metadata can be read multiple times in the course of a single execution of `cp`.
// This fix adds yet another metadata read.
// Should this metadata be read once and then reused throughout the execution?
// https://github.com/uutils/coreutils/issues/6658
let extra_prompt_information: Option<(String, String)> = {
#[cfg(unix)]
{
use libc::{mode_t, S_IWUSR};
use std::os::unix::prelude::MetadataExt;

match path.metadata() {
Ok(me) => {
let mode: mode_t = me.mode();

// It looks like this extra information is added to the prompt iff the file's user write bit is 0
if uucore::has!(mode, S_IWUSR) {
None
} else {
// Discard leading digits
let mode_without_leading_digits = mode & 0o7777;

Some((
format!("{mode_without_leading_digits:04o}"),
uucore::fs::display_permissions_unix(mode, false),
))
}
}
// TODO: How should failure to read the metadata be handled? Ignoring for now.
Err(_) => None,

Check warning on line 1442 in src/uu/cp/src/cp.rs

View check run for this annotation

Codecov / codecov/patch

src/uu/cp/src/cp.rs#L1442

Added line #L1442 was not covered by tests
}
}

#[cfg(not(unix))]
{
None
}
};

let prompt_yes_result =
if let Some((octal, human_readable)) = extra_prompt_information {
prompt_yes!(
"replace {}, overriding mode {octal} ({human_readable})?",
path.quote()
)
} else {
prompt_yes!("overwrite {}?", path.quote())
};

if prompt_yes_result {
Ok(())
} else {
Err(Error::Skipped(true))
Expand Down

0 comments on commit e2a8e86

Please sign in to comment.