Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/uu/chmod/src/chmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,9 +177,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
.unwrap_or_default();
let cmode = if fmode.is_some() {
// "--reference" and MODE are mutually exclusive
// if "--reference" was used MODE needs to be interpreted as another FILE
// if "--reference" was used MODE needs to be interpreted as another FILE,
// it is the first FILE, keep the command-line order
// it wasn't possible to implement this behavior directly with clap
files.push(OsString::from(cmode));
files.insert(0, OsString::from(cmode));
None
} else {
Some(cmode)
Expand Down
45 changes: 45 additions & 0 deletions tests/by-util/test_chmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,51 @@ fn test_chmod_reference_file() {
run_single_test(&tests[0], &at, ucmd);
}

#[test]
fn test_chmod_reference_keeps_operand_order() {
let (at, mut ucmd) = at_and_ucmd!();
at.touch("ref");
at.set_mode("ref", 0o644);
for name in ["a", "b", "c"] {
at.touch(name);
at.set_mode(name, 0o600);
}

ucmd.args(&["-v", "--reference=ref", "a", "b", "c"])
.succeeds()
.stdout_is(
"mode of 'a' changed from 0600 (rw-------) to 0644 (rw-r--r--)\n\
mode of 'b' changed from 0600 (rw-------) to 0644 (rw-r--r--)\n\
mode of 'c' changed from 0600 (rw-------) to 0644 (rw-r--r--)\n",
);
}

#[test]
fn test_chmod_reference_first_operand_before_its_parent_dir() {
use rustix::process::geteuid;

// The reference mode drops the search bit of `dir`, so `dir/file` is only
// reachable if it is handled first. root ignores directory permissions.
if geteuid().is_root() {
return;
}

let (at, mut ucmd) = at_and_ucmd!();
at.touch("ref");
at.set_mode("ref", 0o644);
at.mkdir("dir");
at.touch("dir/file");
at.set_mode("dir/file", 0o600);
at.set_mode("dir", 0o755);

ucmd.args(&["--reference=ref", "dir/file", "dir"])
.succeeds();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please run cargo fmt, this should fit on one line

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I simplified the comment in chmod.rs (5126783). For test_chmod.rs I tried joining the two lines, but rustfmt (chain_width = 60) splits that chain back onto two lines, so the single-line form would fail cargo fmt --check in CI. I left it as is; happy to restructure the chain if you prefer.


assert_eq!(at.metadata("dir").permissions().mode() & 0o7777, 0o644);
at.set_mode("dir", 0o755);
assert_eq!(at.metadata("dir/file").permissions().mode() & 0o7777, 0o644);
}

#[test]
fn test_permission_denied() {
let scene = TestScenario::new(util_name!());
Expand Down
Loading