Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions src/uu/chgrp/src/chgrp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,26 @@ enum ChgrpError {

impl UError for ChgrpError {}

fn parse_group(group: &str) -> Result<u32, String> {
// 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::<u32>()
.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<u32, String> {
if let Some(gid_str) = group.strip_prefix(':') {
// Handle :gid format
gid_str
.parse::<u32>()
.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::<u32>()
.map_err(|_| translate!("chgrp-error-invalid-group", "group" => group)),
}
parse_group(group)
}
}

Expand All @@ -67,7 +72,8 @@ fn get_dest_gid(matches: &ArgMatches) -> UResult<(Option<u32>, 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)),
}
Expand Down
16 changes: 14 additions & 2 deletions tests/by-util/test_chgrp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ fn test_invalid_group() {
.stderr_is("chgrp: invalid group: '__nosuchgroup__'\n");
}

#[test]
fn test_invalid_group_with_colon_prefix() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test_numeric_group_formats still expects :gid to work as the target group, which is why CI is red. please update it

// 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() {
Expand Down Expand Up @@ -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();
Expand Down
Loading