chmod: accept modes like -=r, -+x and -,u+x

extract_negative_modes only took an argument starting with '-' as a mode when its second character was a permission letter or a digit. Modes such as "-=r", "-+x" and "-,u+x" went on to clap, which has no such option and rejected them. Also accept '=', '+' and ',' there; no option starts with those.

Closes #15665
This commit is contained in:
fixfon authored and Sylvestre Ledru committed 2026-10-25 09:08:07 +01:00
1 parent 6f5138a82d
commit bd22b33a08
2 files changed
+28 -1

No files matched your search

+3 -1
View File
@@ -81,11 +81,13 @@ fn extract_negative_modes(args: impl uucore::Args) -> (Option<String>, Vec<OsStr
let Some(arg) = arg.to_str() else {
return false;
};
// A mode can also be "-=r", "-+x" or "-,u+x". No option starts with '=', '+' or ',',
// and a second '-' (a long option) is deliberately not listed.
arg.len() >= 2
&& arg.starts_with('-')
&& matches!(
arg.chars().nth(1).unwrap(),
'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '0'..='7'
'r' | 'w' | 'x' | 'X' | 's' | 't' | 'u' | 'g' | 'o' | '=' | '+' | ',' | '0'..='7'
)
};
+25
View File
@@ -364,6 +364,31 @@ fn test_chmod_many_options() {
run_tests(tests);
}
#[test]
fn test_chmod_option_like_mode_starting_with_operator() {
let tests = vec![
TestCase {
args: vec!["-=r", TEST_FILE],
before: 0o100_644,
after: 0o100_444,
umask: Some(0o022),
},
TestCase {
args: vec!["-+x", TEST_FILE],
before: 0o100_644,
after: 0o100_755,
umask: Some(0o022),
},
TestCase {
args: vec!["-,u+x", TEST_FILE],
before: 0o100_644,
after: 0o100_744,
umask: Some(0o022),
},
];
run_tests(tests);
}
#[test]
#[allow(clippy::unreadable_literal)]
fn test_chmod_reference_file() {