Implement getgroups

This commit is contained in:
Wildan M
2026-03-07 11:02:50 +07:00
parent ecfeceab6d
commit fb07b5f982
3 changed files with 72 additions and 4 deletions
+46 -4
View File
@@ -611,10 +611,52 @@ impl Pal for Sys {
redox_rt::sys::posix_getresugid().rgid as gid_t
}
fn getgroups(list: Out<[gid_t]>) -> Result<c_int> {
// TODO
todo_skip!(0, "getgroups({}, {:p}): not implemented", list.len(), list);
Err(Errno(ENOSYS))
fn getgroups(mut list: Out<[gid_t]>) -> Result<c_int> {
// FIXME: this operation doesn't scale when group/passwd file grows
let uid = Self::geteuid();
let pwd = crate::header::pwd::getpwuid(uid);
if pwd.is_null() {
return Err(Errno(ENOENT));
}
let username = unsafe { CStr::from_ptr((*pwd).pw_name) };
let username = username.to_bytes_with_nul();
let mut count = 0;
unsafe {
use crate::header::grp;
grp::setgrent();
while let Some(grp) = grp::getgrent().as_ref() {
let mut i = 0;
let mut found = false;
while !(*grp.gr_mem.offset(i)).is_null() {
let member = CStr::from_ptr(*grp.gr_mem.offset(i));
if member.to_bytes_with_nul() == username {
found = true;
break;
}
i += 1;
}
if found {
if !list.is_empty() && (count as usize) < list.len() {
list.index(count).write(grp.gr_gid);
}
count += 1;
}
}
grp::endgrent();
}
if !list.is_empty() && (count as usize) > list.len() {
return Err(Errno(EINVAL));
}
Ok(count as i32)
}
fn getpagesize() -> usize {
+1
View File
@@ -305,6 +305,7 @@ VARIED_NAMES=\
pthread/timeout \
pthread/tls \
grp/getgrouplist \
grp/getgroups \
grp/getgrgid_r \
grp/getgrnam_r \
grp/gr_iter \
+25
View File
@@ -0,0 +1,25 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <grp.h>
int main() {
gid_t primary_gid = getegid();
struct group *pg = getgrgid(primary_gid);
printf("getegid: %u (%s)\n", primary_gid, pg ? pg->gr_name : "?");
int count = getgroups(0, NULL);
gid_t *list = malloc(sizeof(gid_t) * count);
getgroups(count, list);
printf("getgroups: %d\n", count);
for (int i = 0; i < count; i++) {
struct group *sg = getgrgid(list[i]);
printf(" - %u (%s)\n", list[i], sg ? sg->gr_name : "?");
}
free(list);
return 0;
}