Merge pull request #4359 from dmatos2012/chmod-multiple-files-error

chmod: change permissions for files present even when there is a missing file
This commit is contained in:
Terts Diepraam 2023-02-17 11:27:32 +01:00 committed by GitHub
commit 9fdce975fd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 77 additions and 6 deletions

View file

@ -12,12 +12,12 @@ use std::fs;
use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::Path;
use uucore::display::Quotable;
use uucore::error::{ExitCode, UResult, USimpleError, UUsageError};
use uucore::error::{set_exit_code, ExitCode, UResult, USimpleError, UUsageError};
use uucore::fs::display_permissions_unix;
use uucore::libc::mode_t;
#[cfg(not(windows))]
use uucore::mode;
use uucore::{format_usage, show_error};
use uucore::{format_usage, show, show_error};
const ABOUT: &str = "Change the mode of each FILE to MODE.\n\
With --reference, change the mode of each FILE to that of RFILE.";
@ -195,21 +195,24 @@ impl Chmoder {
filename.quote()
);
if !self.quiet {
return Err(USimpleError::new(
show!(USimpleError::new(
1,
format!("cannot operate on dangling symlink {}", filename.quote()),
));
}
} else if !self.quiet {
return Err(USimpleError::new(
show!(USimpleError::new(
1,
format!(
"cannot access {}: No such file or directory",
filename.quote()
),
)
));
}
return Err(ExitCode::new(1));
// GNU exits with exit code 1 even if -q or --quiet are passed
// So we set the exit code, because it hasn't been set yet if `self.quiet` is true.
set_exit_code(1);
continue;
}
if self.recursive && self.preserve_root && filename == "/" {
return Err(USimpleError::new(

View file

@ -574,3 +574,71 @@ fn test_mode_after_dash_dash() {
ucmd,
);
}
#[test]
fn test_chmod_file_after_non_existing_file() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
at.touch(TEST_FILE);
at.touch("file2");
set_permissions(at.plus(TEST_FILE), Permissions::from_mode(0o664)).unwrap();
set_permissions(at.plus("file2"), Permissions::from_mode(0o664)).unwrap();
scene
.ucmd()
.arg("u+x")
.arg("does-not-exist")
.arg(TEST_FILE)
.fails()
.stderr_contains("chmod: cannot access 'does-not-exist': No such file or directory")
.code_is(1);
assert_eq!(at.metadata(TEST_FILE).permissions().mode(), 0o100764);
scene
.ucmd()
.arg("u+x")
.arg("--q")
.arg("does-not-exist")
.arg("file2")
.fails()
.no_stderr()
.code_is(1);
assert_eq!(at.metadata("file2").permissions().mode(), 0o100764);
}
#[test]
fn test_chmod_file_symlink_after_non_existing_file() {
let scene = TestScenario::new(util_name!());
let at = &scene.fixtures;
let existing = "file";
let test_existing_symlink = "file_symlink";
let non_existing = "test_chmod_symlink_non_existing_file";
let test_dangling_symlink = "test_chmod_symlink_non_existing_file_symlink";
let expected_stdout = &format!(
"failed to change mode of '{test_dangling_symlink}' from 0000 (---------) to 0000 (---------)"
);
let expected_stderr = &format!("cannot operate on dangling symlink '{test_dangling_symlink}'");
at.touch(existing);
set_permissions(at.plus(existing), Permissions::from_mode(0o664)).unwrap();
at.symlink_file(non_existing, test_dangling_symlink);
at.symlink_file(existing, test_existing_symlink);
// this cannot succeed since the symbolic link dangles
// but the metadata for the existing target should change
scene
.ucmd()
.arg("u+x")
.arg("-v")
.arg(test_dangling_symlink)
.arg(test_existing_symlink)
.fails()
.code_is(1)
.stdout_contains(expected_stdout)
.stderr_contains(expected_stderr);
assert_eq!(
at.metadata(test_existing_symlink).permissions().mode(),
0o100764
);
}