diff --git a/src/uu/chmod/src/chmod.rs b/src/uu/chmod/src/chmod.rs index 24566272b23..b7e0f3fd965 100644 --- a/src/uu/chmod/src/chmod.rs +++ b/src/uu/chmod/src/chmod.rs @@ -411,7 +411,7 @@ impl Chmoder { return Err(ChmodError::PreserveRoot("/".into()).into()); } if self.recursive { - r = self.walk_dir_with_context(file, true); + r = self.walk_dir_with_context(file, true).and(r); } else { r = self.chmod_file(file).and(r); } diff --git a/tests/by-util/test_chmod.rs b/tests/by-util/test_chmod.rs index 446cdd6d39e..5e340732832 100644 --- a/tests/by-util/test_chmod.rs +++ b/tests/by-util/test_chmod.rs @@ -375,6 +375,38 @@ fn test_permission_denied() { .stderr_is("chmod: cannot access 'd/no-x/y': Permission denied\n"); } +#[test] +#[allow(clippy::unreadable_literal)] +fn test_chmod_recursive_correct_exit_code() { + let (at, mut ucmd) = at_and_ucmd!(); + + // create 3 folders to test on + at.mkdir("a"); + at.mkdir("a/b"); + at.mkdir("z"); + + // remove read permissions for folder a so the chmod command for a/b fails + let mut perms = at.metadata("a").permissions(); + perms.set_mode(0o000); + set_permissions(at.plus_as_string("a"), perms).unwrap(); + + #[cfg(not(target_os = "linux"))] + let err_msg = "chmod: Permission denied\n"; + #[cfg(target_os = "linux")] + let err_msg = "chmod: cannot access 'a': Permission denied\n"; + + // order of command is a, a/b then c + // command is expected to fail and not just take the last exit code + ucmd.arg("-R") + .arg("--verbose") + .arg("a+w") + .arg("a") + .arg("z") + .umask(0) + .fails() + .stderr_is(err_msg); +} + #[test] #[allow(clippy::unreadable_literal)] fn test_chmod_recursive() {