From 6d264dbbcf3a30bfaba9b61165c29eca461716df Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Wed, 2 Apr 2025 11:19:06 -0400 Subject: [PATCH] find: Allow -user UID / -group GID POSIX says > -user uname > The primary shall evaluate as true if the file belongs to the user > uname. If uname is a decimal integer and the getpwnam() (or > equivalent) function does not return a valid user name, uname shall > be interpreted as a user ID. and similarly for -group. Link: https://pubs.opengroup.org/onlinepubs/9799919799/utilities/find.html --- src/find/matchers/mod.rs | 40 ++++++++++++++++++++++++---------------- src/find/mod.rs | 38 ++++++++++++++++---------------------- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/find/matchers/mod.rs b/src/find/matchers/mod.rs index 7e192e7..1cc7f68 100644 --- a/src/find/matchers/mod.rs +++ b/src/find/matchers/mod.rs @@ -717,16 +717,20 @@ fn build_matcher_tree( } i += 1; - let matcher = UserMatcher::from_user_name(user); - match matcher.uid() { - Some(_) => Some(matcher.into_box()), - None => { - return Err(From::from(format!( - "{} is not the name of a known user", - user - ))) + let mut matcher = UserMatcher::from_user_name(user); + if matcher.uid().is_none() { + // If it's not a valid user name, it may be a UID + match user.parse::() { + Ok(uid) => matcher = UserMatcher::from_uid(uid), + _ => { + return Err(From::from(format!( + "{} is not the name of a known user", + user + ))) + } } } + Some(matcher.into_box()) } "-nouser" => Some(NoUserMatcher {}.into_box()), "-uid" => { @@ -755,16 +759,20 @@ fn build_matcher_tree( } i += 1; - let matcher = GroupMatcher::from_group_name(group); - match matcher.gid() { - Some(_) => Some(matcher.into_box()), - None => { - return Err(From::from(format!( - "{} is not the name of an existing group", - group - ))) + let mut matcher = GroupMatcher::from_group_name(group); + if matcher.gid().is_none() { + // If it's not a valid group name, it may be a GID + match group.parse::() { + Ok(gid) => matcher = GroupMatcher::from_gid(gid), + _ => { + return Err(From::from(format!( + "{} is not the name of an existing group", + group + ))) + } } } + Some(matcher.into_box()) } "-nogroup" => Some(NoGroupMatcher {}.into_box()), "-gid" => { diff --git a/src/find/mod.rs b/src/find/mod.rs index f3519aa..25550b3 100644 --- a/src/find/mod.rs +++ b/src/find/mod.rs @@ -1163,17 +1163,14 @@ mod tests { ); // test uid - let deps = FakeDependencies::new(); - let rc = find_main( - &[ - "find", - "./test_data/simple/subdir", - "-uid", - &uid.to_string(), - ], - &deps, - ); - assert_eq!(rc, 0); + for arg in ["-uid", "-user"] { + let deps = FakeDependencies::new(); + let rc = find_main( + &["find", "./test_data/simple/subdir", arg, &uid.to_string()], + &deps, + ); + assert_eq!(rc, 0); + } // test empty uid let deps = FakeDependencies::new(); @@ -1233,17 +1230,14 @@ mod tests { ); // test gid - let deps = FakeDependencies::new(); - let rc = find_main( - &[ - "find", - "./test_data/simple/subdir", - "-gid", - gid.to_string().as_str(), - ], - &deps, - ); - assert_eq!(rc, 0); + for arg in ["-gid", "-group"] { + let deps = FakeDependencies::new(); + let rc = find_main( + &["find", "./test_data/simple/subdir", arg, &gid.to_string()], + &deps, + ); + assert_eq!(rc, 0); + } // test empty gid let deps = FakeDependencies::new();