diff --git a/src/uu/chgrp/src/chgrp.rs b/src/uu/chgrp/src/chgrp.rs index 065b52ccae6..5b1d4263f5a 100644 --- a/src/uu/chgrp/src/chgrp.rs +++ b/src/uu/chgrp/src/chgrp.rs @@ -27,6 +27,18 @@ enum ChgrpError { impl UError for ChgrpError {} +fn parse_group(group: &str) -> Result { + // Try as group name first + match entries::grp2gid(group) { + Ok(g) => Ok(g), + // If group name lookup fails, try parsing as raw number + Err(_) => group + .parse::() + .map_err(|_| translate!("chgrp-error-invalid-group", "group" => group)), + } +} + +/// Parse the `--from` value, which also accepts the `:gid` format. fn parse_gid_from_str(group: &str) -> Result { if let Some(gid_str) = group.strip_prefix(':') { // Handle :gid format @@ -34,14 +46,7 @@ fn parse_gid_from_str(group: &str) -> Result { .parse::() .map_err(|_| translate!("chgrp-error-invalid-group-id", "gid_str" => gid_str)) } else { - // Try as group name first - match entries::grp2gid(group) { - Ok(g) => Ok(g), - // If group name lookup fails, try parsing as raw number - Err(_) => group - .parse::() - .map_err(|_| translate!("chgrp-error-invalid-group", "group" => group)), - } + parse_group(group) } } @@ -67,7 +72,8 @@ fn get_dest_gid(matches: &ArgMatches) -> UResult<(Option, String)> { if group.is_empty() { None } else { - match parse_gid_from_str(group) { + // Unlike --from, GNU does not accept the `:gid` format here. + match parse_group(group) { Ok(g) => Some(g), Err(e) => return Err(USimpleError::new(1, e)), } diff --git a/tests/by-util/test_chgrp.rs b/tests/by-util/test_chgrp.rs index 3f29e130a69..b128e64d0da 100644 --- a/tests/by-util/test_chgrp.rs +++ b/tests/by-util/test_chgrp.rs @@ -62,6 +62,18 @@ fn test_invalid_group() { .stderr_is("chgrp: invalid group: '__nosuchgroup__'\n"); } +#[test] +fn test_invalid_group_with_colon_prefix() { + // The `:gid` format is only accepted by --from, not for the group operand + let (at, mut ucmd) = at_and_ucmd!(); + at.touch("file"); + let gid = getegid().as_raw(); + ucmd.arg(format!(":{gid}")) + .arg("file") + .fails_with_code(1) + .stderr_is(format!("chgrp: invalid group: ':{gid}'\n")); +} + #[test] fn test_error_1() { if !getegid().is_root() { @@ -604,11 +616,11 @@ fn test_numeric_group_formats() { let new_gid = at.plus("test_file").metadata().unwrap().gid(); assert_eq!(new_gid, second_group.as_raw()); - // Test :gid format in target group + // Test numeric gid in target group (the :gid format is only valid for --from) scene .ucmd() .arg(format!("--from={}", second_group.as_raw())) - .arg(format!(":{}", first_group.as_raw())) + .arg(first_group.as_raw().to_string()) .arg("test_file") .succeeds() .no_stderr();