mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
chgrp: support the --from=:X syntax
This commit is contained in:
parent
8e9a4b5f9a
commit
d76c561516
2 changed files with 69 additions and 10 deletions
|
@ -19,6 +19,24 @@ use std::os::unix::fs::MetadataExt;
|
||||||
const ABOUT: &str = help_about!("chgrp.md");
|
const ABOUT: &str = help_about!("chgrp.md");
|
||||||
const USAGE: &str = help_usage!("chgrp.md");
|
const USAGE: &str = help_usage!("chgrp.md");
|
||||||
|
|
||||||
|
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(|_| format!("invalid group id: '{}'", 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(|_| format!("invalid group: '{}'", group)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<GidUidOwnerFilter> {
|
fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<GidUidOwnerFilter> {
|
||||||
let mut raw_group: String = String::new();
|
let mut raw_group: String = String::new();
|
||||||
let dest_gid = if let Some(file) = matches.get_one::<String>(options::REFERENCE) {
|
let dest_gid = if let Some(file) = matches.get_one::<String>(options::REFERENCE) {
|
||||||
|
@ -38,26 +56,21 @@ fn parse_gid_and_uid(matches: &ArgMatches) -> UResult<GidUidOwnerFilter> {
|
||||||
if group.is_empty() {
|
if group.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
match entries::grp2gid(group) {
|
match parse_gid_from_str(group) {
|
||||||
Ok(g) => Some(g),
|
Ok(g) => Some(g),
|
||||||
_ => {
|
Err(e) => return Err(USimpleError::new(1, e)),
|
||||||
return Err(USimpleError::new(
|
|
||||||
1,
|
|
||||||
format!("invalid group: {}", group.quote()),
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Handle --from option
|
// Handle --from option
|
||||||
let filter = if let Some(from_group) = matches.get_one::<String>(options::FROM) {
|
let filter = if let Some(from_group) = matches.get_one::<String>(options::FROM) {
|
||||||
match entries::grp2gid(from_group) {
|
match parse_gid_from_str(from_group) {
|
||||||
Ok(g) => IfFrom::Group(g),
|
Ok(g) => IfFrom::Group(g),
|
||||||
_ => {
|
Err(_) => {
|
||||||
return Err(USimpleError::new(
|
return Err(USimpleError::new(
|
||||||
1,
|
1,
|
||||||
format!("invalid group: {}", from_group.quote()),
|
format!("invalid user: '{}'", from_group),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -547,3 +547,49 @@ fn test_from_with_reference() {
|
||||||
let ref_gid = at.plus("ref_file").metadata().unwrap().gid();
|
let ref_gid = at.plus("ref_file").metadata().unwrap().gid();
|
||||||
assert_eq!(new_gid, ref_gid);
|
assert_eq!(new_gid, ref_gid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(target_vendor = "apple"))]
|
||||||
|
fn test_numeric_group_formats() {
|
||||||
|
use std::os::unix::fs::MetadataExt;
|
||||||
|
let scene = TestScenario::new(util_name!());
|
||||||
|
let at = &scene.fixtures;
|
||||||
|
|
||||||
|
let groups = nix::unistd::getgroups().unwrap();
|
||||||
|
if groups.len() < 2 {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let (first_group, second_group) = (groups[0], groups[1]);
|
||||||
|
|
||||||
|
at.touch("test_file");
|
||||||
|
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg(first_group.to_string())
|
||||||
|
.arg("test_file")
|
||||||
|
.succeeds();
|
||||||
|
|
||||||
|
// Test :gid format in --from
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg(format!("--from=:{}", first_group.as_raw()))
|
||||||
|
.arg(second_group.to_string())
|
||||||
|
.arg("test_file")
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
let new_gid = at.plus("test_file").metadata().unwrap().gid();
|
||||||
|
assert_eq!(new_gid, second_group.as_raw());
|
||||||
|
|
||||||
|
// Test :gid format in target group
|
||||||
|
scene
|
||||||
|
.ucmd()
|
||||||
|
.arg(format!("--from={}", second_group.as_raw()))
|
||||||
|
.arg(format!(":{}", first_group.as_raw()))
|
||||||
|
.arg("test_file")
|
||||||
|
.succeeds()
|
||||||
|
.no_stderr();
|
||||||
|
|
||||||
|
let final_gid = at.plus("test_file").metadata().unwrap().gid();
|
||||||
|
assert_eq!(final_gid, first_group.as_raw());
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue