Open
Description
These two syscalls sequentially scan the /etc/passwd/ and
/etc/group` databases and return all the entries in those files one by one.
Signature
pub fn getpwent() -> Result<Vec<User>, Errno>;
pub fn getgrent() -> Result<Vec<Group>, Errno>;
Implementation
On some OSes, we have non-reentrant functions getpwent_r()
and getgrent_r()
. If so, they will be used. Otherwise, will use getpwent()
and getgrent()
.
Here is draft implementation of getgrent
under Linux:
pub fn getgrent() -> Result<Vec<Group>, Errno> {
let mut v: Vec<Group> = Vec::new();
let mut gr_buf: group = unsafe { zeroed() };
let mut gr_str_buf: [c_char; 4096] = [0; 4096];
unsafe { setgrent() };
loop {
let mut result: *mut group = null_mut();
let res: c_int = unsafe {
getgrent_r(
&mut gr_buf as *mut group,
&mut gr_str_buf as *mut c_char,
4096,
&mut result as *mut *mut group,
)
};
// no more entries
if res == ENOENT {
unsafe { endgrent() };
break;
}
// error
if res == ERANGE {
return Err(Errno::from_i32(ERANGE));
}
// man page for `getgrent_r` only lists the two above erroneous cases.
// In other cases, it should be successful.
assert_eq!(res, 0);
v.push(Group::from(&gr_buf));
}
Ok(v)
}
Note
-
The above implementation calls
setgrent
andendgrent
inside, which actually changes the semantics of this syscall. -
Due to Note
1
, perhaps we can give a better name to those syscalls, like:impl User { pub fn all_users() -> Result<Vec<User>, Errno>; } impl Group { pub fn all_groups() -> Result<Vec<Group>, Errno>; }
Metadata
Metadata
Assignees
Labels
No labels