diff --git a/src/uucore/src/lib/features/perms.rs b/src/uucore/src/lib/features/perms.rs index 2823b35b1a2..d1e351ee3ef 100644 --- a/src/uucore/src/lib/features/perms.rs +++ b/src/uucore/src/lib/features/perms.rs @@ -619,7 +619,6 @@ impl ChownExecutor { ); continue; } - ret = match wrap_chown( path, &meta, @@ -632,7 +631,8 @@ impl ChownExecutor { if !n.is_empty() { show_error!("{n}"); } - 0 + // retain previous errors + ret.max(0) } Err(e) => { if self.verbosity.level != VerbosityLevel::Silent { diff --git a/tests/by-util/test_chgrp.rs b/tests/by-util/test_chgrp.rs index cc0727dd3eb..aa2c9192c1c 100644 --- a/tests/by-util/test_chgrp.rs +++ b/tests/by-util/test_chgrp.rs @@ -640,3 +640,26 @@ fn test_chgrp_recursive_on_file() { current_gid ); } + +#[test] +fn test_chgrp_exit_code_not_being_overwritten_by_last_file() { + use std::os::unix::prelude::PermissionsExt; + + let current_gid = getegid(); + let (at, mut ucmd) = at_and_ucmd!(); + at.mkdir("dir"); + at.mkdir("dir/a"); + at.mkdir("dir/b"); + at.touch("dir/b/file"); + at.touch("dir/a/file"); + std::fs::set_permissions(at.plus("dir/a"), PermissionsExt::from_mode(0o0000)).unwrap(); + + // chgrp walks the dir alphabetically. Dir a does not have permissions so it fails, dir b does have + // permissions so it succeeds. We check that the overall command does fail although the + // last step succeeded. + + ucmd.arg("-R") + .arg(current_gid.to_string()) + .arg("dir") + .fails(); +}