summaryrefslogtreecommitdiffstats
path: root/vendor/sysinfo/src/users.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sysinfo/src/users.rs')
-rw-r--r--vendor/sysinfo/src/users.rs162
1 files changed, 93 insertions, 69 deletions
diff --git a/vendor/sysinfo/src/users.rs b/vendor/sysinfo/src/users.rs
index 1891ec7cc..6d3343bd7 100644
--- a/vendor/sysinfo/src/users.rs
+++ b/vendor/sysinfo/src/users.rs
@@ -5,14 +5,87 @@ use crate::{
User,
};
-use libc::{getgrgid, getgrouplist};
+use libc::{getgrgid_r, getgrouplist};
use std::fs::File;
use std::io::Read;
-pub fn get_users_list() -> Vec<User> {
+pub(crate) unsafe fn get_group_name(
+ id: libc::gid_t,
+ buffer: &mut Vec<libc::c_char>,
+) -> Option<String> {
+ let mut g = std::mem::MaybeUninit::<libc::group>::uninit();
+ let mut tmp_ptr = std::ptr::null_mut();
+ let mut last_errno = 0;
+ loop {
+ if retry_eintr!(set_to_0 => last_errno => getgrgid_r(
+ id as _,
+ g.as_mut_ptr() as _,
+ buffer.as_mut_ptr(),
+ buffer.capacity() as _,
+ &mut tmp_ptr as _
+ )) != 0
+ {
+ // If there was not enough memory, we give it more.
+ if last_errno == libc::ERANGE as _ {
+ buffer.reserve(2048);
+ continue;
+ }
+ return None;
+ }
+ break;
+ }
+ let g = g.assume_init();
+ let mut group_name = Vec::new();
+ let c_group_name = g.gr_name;
+ let mut x = 0;
+ loop {
+ let c = *c_group_name.offset(x);
+ if c == 0 {
+ break;
+ }
+ group_name.push(c as u8);
+ x += 1;
+ }
+ String::from_utf8(group_name).ok()
+}
+
+pub(crate) unsafe fn get_user_groups(
+ name: *const libc::c_char,
+ group_id: libc::gid_t,
+ groups: &mut Vec<crate::GroupId>,
+ buffer: &mut Vec<libc::c_char>,
+) -> Vec<String> {
+ loop {
+ let mut nb_groups = groups.capacity();
+ if getgrouplist(
+ name,
+ group_id as _,
+ groups.as_mut_ptr(),
+ &mut nb_groups as *mut _ as *mut _,
+ ) == -1
+ {
+ groups.reserve(256);
+ continue;
+ }
+ groups.set_len(nb_groups as _);
+ return groups
+ .iter()
+ .filter_map(|group_id| crate::users::get_group_name(*group_id as _, buffer))
+ .collect();
+ }
+}
+
+// Not used by mac.
+#[allow(unused)]
+pub(crate) fn get_users_list() -> Vec<User> {
+ #[inline]
+ fn parse_id(id: &str) -> Option<u32> {
+ id.parse::<u32>().ok()
+ }
+
let mut s = String::new();
- let mut ngroups = 100;
- let mut groups = vec![0; ngroups as usize];
+ let mut buffer = Vec::with_capacity(2048);
+ let mut groups = Vec::with_capacity(256);
let _ = File::open("/etc/passwd").and_then(|mut f| f.read_to_string(&mut s));
s.lines()
@@ -23,66 +96,22 @@ pub fn get_users_list() -> Vec<User> {
// Skip the user if the uid cannot be parsed correctly
if let Some(uid) = parts.next().and_then(parse_id) {
if let Some(group_id) = parts.next().and_then(parse_id) {
- if let Some(command) = parts.last() {
- if command.is_empty()
- || command.ends_with("/false")
- || command.ends_with("/nologin")
- {
- // We don't want "fake" users so in case the user command is "bad", we
- // ignore this user.
- return None;
- }
- let mut c_user = username.as_bytes().to_vec();
- c_user.push(0);
- loop {
- let mut current = ngroups;
-
- unsafe {
- if getgrouplist(
- c_user.as_ptr() as *const _,
- group_id,
- groups.as_mut_ptr(),
- &mut current,
- ) == -1
- {
- if current > ngroups {
- groups.resize(current as _, 0);
- ngroups = current;
- continue;
- }
- // It really failed, let's move on...
- return None;
- }
- // Let's get all the group names!
- return Some(User {
- uid: Uid(uid),
- gid: Gid(group_id),
- name: username.to_owned(),
- groups: groups[..current as usize]
- .iter()
- .filter_map(|id| {
- let g = getgrgid(*id as _);
- if g.is_null() {
- return None;
- }
- let mut group_name = Vec::new();
- let c_group_name = (*g).gr_name;
- let mut x = 0;
- loop {
- let c = *c_group_name.offset(x);
- if c == 0 {
- break;
- }
- group_name.push(c as u8);
- x += 1;
- }
- String::from_utf8(group_name).ok()
- })
- .collect(),
- });
- }
- }
- }
+ let mut c_user = username.as_bytes().to_vec();
+ c_user.push(0);
+ // Let's get all the group names!
+ return Some(User {
+ uid: Uid(uid),
+ gid: Gid(group_id),
+ name: username.to_owned(),
+ groups: unsafe {
+ get_user_groups(
+ c_user.as_ptr() as *const _,
+ group_id,
+ &mut groups,
+ &mut buffer,
+ )
+ },
+ });
}
}
}
@@ -90,8 +119,3 @@ pub fn get_users_list() -> Vec<User> {
})
.collect()
}
-
-#[inline]
-fn parse_id(id: &str) -> Option<u32> {
- id.parse::<u32>().ok()
-}