Skip to content
Open
1 change: 1 addition & 0 deletions src/uu/chmod/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ chmod-verbose-neither-changed = neither symbolic link {$file} nor referent has b
chmod-verbose-mode-retained = mode of {$file} retained as {$mode_octal} ({$mode_display})
chmod-verbose-failed-change = failed to change mode of file {$file} from {$old_mode} ({$old_mode_display}) to {$new_mode} ({$new_mode_display})
chmod-verbose-mode-changed = mode of {$file} changed from {$old_mode} ({$old_mode_display}) to {$new_mode} ({$new_mode_display})
chmod-permissions-changed = changing permissions of {$file}: {$errno}
16 changes: 9 additions & 7 deletions src/uu/chmod/src/chmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ use std::os::unix::fs::{MetadataExt, PermissionsExt};
use std::path::{Path, PathBuf};
use thiserror::Error;
use uucore::display::Quotable;
use uucore::error::{ExitCode, UError, UResult, USimpleError, UUsageError, set_exit_code};
use uucore::error::{
ExitCode, UError, UResult, USimpleError, UUsageError, set_exit_code, strip_errno,
};
use uucore::fs::{FileInformation, display_permissions_unix};
use uucore::mode;
use uucore::perms::{TraverseSymlinks, configure_symlink_and_recursion};
Expand Down Expand Up @@ -772,13 +774,13 @@ impl Chmoder {
}

fn change_file(&self, fperm: u32, mode: u32, file: &Path) -> Result<(), i32> {
if fperm == mode {
// Use the helper method for consistent reporting
self.report_permission_change(file, fperm, mode);
Ok(())
} else if let Err(err) = fs::set_permissions(file, fs::Permissions::from_mode(mode)) {
// fs::set_permissions calls chmod which we need for the gnu test chmod/only-op.sh
if let Err(err) = fs::set_permissions(file, fs::Permissions::from_mode(mode)) {
if !self.quiet {
show_error!("{err}");
show_error!(
"{}",
translate!("chmod-permissions-changed", "file" => file.quote(), "errno" => strip_errno(&err))
);
}
if self.verbose {
println!(
Expand Down
11 changes: 11 additions & 0 deletions tests/by-util/test_chmod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1500,3 +1500,14 @@ fn test_chmod_symlink_two_links_same_dir() {
.stdout_contains("mode of 'base/link2/file'");
// cSpell:enable
}

#[test]
#[cfg(target_os = "linux")]
fn test_chmod_permission_denied() {
let (_, mut ucmd) = at_and_ucmd!();

ucmd.args(&["+", "/"]).fails_with_code(1).stderr_is(
// spell-checker:disable-next-line
"chmod: changing permissions of '/': Operation not permitted\n",
);
}
Loading