Skip to content

Commit

Permalink
Merge pull request #1083 from GuillaumeGomez/separate-users
Browse files Browse the repository at this point in the history
Separate Users from System
  • Loading branch information
GuillaumeGomez authored Sep 28, 2023
2 parents 68a25cc + ea47b40 commit f6c1a25
Show file tree
Hide file tree
Showing 22 changed files with 535 additions and 329 deletions.
6 changes: 3 additions & 3 deletions benches/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
extern crate test;

use sysinfo::get_current_pid;
use sysinfo::{ComponentsExt, DiskExt, DisksExt, NetworksExt, SystemExt};
use sysinfo::{ComponentsExt, DiskExt, DisksExt, NetworksExt, SystemExt, UsersExt};

#[bench]
fn bench_new(b: &mut test::Bencher) {
Expand Down Expand Up @@ -160,9 +160,9 @@ fn bench_refresh_components_list(b: &mut test::Bencher) {

#[bench]
fn bench_refresh_users_list(b: &mut test::Bencher) {
let mut s = sysinfo::System::new_all();
let mut users = sysinfo::Users::new();

b.iter(move || {
s.refresh_users_list();
users.refresh_list();
});
}
12 changes: 9 additions & 3 deletions examples/simple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::str::FromStr;
use sysinfo::Signal::*;
use sysinfo::{
Components, ComponentsExt, CpuExt, Disks, DisksExt, NetworkExt, Networks, NetworksExt, Pid,
ProcessExt, Signal, System, SystemExt, UserExt,
ProcessExt, Signal, System, SystemExt, UserExt, Users, UsersExt,
};

const signals: &[Signal] = &[
Expand Down Expand Up @@ -156,6 +156,7 @@ fn interpret_input(
networks: &mut Networks,
disks: &mut Disks,
components: &mut Components,
users: &mut Users,
) -> bool {
match input.trim() {
"help" => print_help(),
Expand All @@ -166,7 +167,7 @@ fn interpret_input(
}
"refresh_users" => {
writeln!(&mut io::stdout(), "Refreshing user list...");
sys.refresh_users_list();
users.refresh_list();
writeln!(&mut io::stdout(), "Done.");
}
"refresh_networks" => {
Expand Down Expand Up @@ -369,7 +370,7 @@ fn interpret_input(
}
}
"users" => {
for user in sys.users() {
for user in users.users() {
writeln!(
&mut io::stdout(),
"{:?} => {:?}",
Expand Down Expand Up @@ -464,9 +465,13 @@ fn main() {
let mut networks = Networks::new();
let mut disks = Disks::new();
let mut components = Components::new();
let mut users = Users::new();

networks.refresh_list();
disks.refresh_list();
components.refresh_list();
users.refresh_list();

println!("Done.");
let t_stin = io::stdin();
let mut stin = t_stin.lock();
Expand Down Expand Up @@ -494,6 +499,7 @@ fn main() {
&mut networks,
&mut disks,
&mut components,
&mut users,
);
}
}
11 changes: 7 additions & 4 deletions md_doc/user.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
Type containing user information.

It is returned by [`SystemExt::users`][crate::SystemExt::users].
It is returned by [`Users`][crate::Users].

```no_run
use sysinfo::{System, SystemExt};
use sysinfo::{Users, UsersExt};
let s = System::new_all();
println!("users: {:?}", s.users());
let mut users = Users::new();
users.refresh_list();
for user in users.users() {
println!("{:?}", user);
}
```
58 changes: 50 additions & 8 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::{
Component, Components, ComponentsExt, Disk, GroupExt, NetworkData, NetworksExt, User, UserExt,
UsersExt,
};

use std::cmp::Ordering;
Expand Down Expand Up @@ -369,7 +370,6 @@ pub struct RefreshKind {
processes: Option<ProcessRefreshKind>,
memory: bool,
cpu: Option<CpuRefreshKind>,
users_list: bool,
}

impl RefreshKind {
Expand All @@ -383,7 +383,6 @@ impl RefreshKind {
/// assert_eq!(r.processes().is_some(), false);
/// assert_eq!(r.memory(), false);
/// assert_eq!(r.cpu().is_some(), false);
/// assert_eq!(r.users_list(), false);
/// ```
pub fn new() -> Self {
Self::default()
Expand All @@ -399,14 +398,12 @@ impl RefreshKind {
/// assert_eq!(r.processes().is_some(), true);
/// assert_eq!(r.memory(), true);
/// assert_eq!(r.cpu().is_some(), true);
/// assert_eq!(r.users_list(), true);
/// ```
pub fn everything() -> Self {
Self {
processes: Some(ProcessRefreshKind::everything()),
memory: true,
cpu: Some(CpuRefreshKind::everything()),
users_list: true,
}
}

Expand All @@ -419,7 +416,6 @@ impl RefreshKind {
);
impl_get_set!(RefreshKind, memory, with_memory, without_memory);
impl_get_set!(RefreshKind, cpu, with_cpu, without_cpu, CpuRefreshKind);
impl_get_set!(RefreshKind, users_list, with_users_list, without_users_list);
}

/// Network interfaces.
Expand Down Expand Up @@ -543,6 +539,52 @@ impl std::ops::DerefMut for Components {
}
}

/// User interfaces.
///
/// ```no_run
/// use sysinfo::{Users, UsersExt, UserExt};
///
/// let mut users = Users::new();
/// for user in users.users() {
/// println!("{} is in {} groups", user.name(), user.groups().len());
/// }
/// ```
pub struct Users {
users: Vec<User>,
}

impl UsersExt for Users {
fn new() -> Self {
Self { users: Vec::new() }
}

fn users(&self) -> &[User] {
&self.users
}

fn users_mut(&mut self) -> &mut [User] {
&mut self.users
}

fn refresh_list(&mut self) {
crate::sys::get_users(&mut self.users);
}
}

impl std::ops::Deref for Users {
type Target = [User];

fn deref(&self) -> &Self::Target {
self.users()
}
}

impl std::ops::DerefMut for Users {
fn deref_mut(&mut self) -> &mut Self::Target {
self.users_mut()
}
}

/// An enum representing signals on UNIX-like systems.
///
/// On non-unix systems, this enum is mostly useless and is only there to keep coherency between
Expand Down Expand Up @@ -802,11 +844,11 @@ impl Ord for User {
/// It is returned by [`User::groups`].
///
/// ```no_run
/// use sysinfo::{GroupExt, System, SystemExt, UserExt};
/// use sysinfo::{GroupExt, UserExt, Users, UsersExt};
///
/// let s = System::new_all();
/// let mut users = Users::new();
///
/// for user in s.users() {
/// for user in users.users() {
/// println!(
/// "user: (ID: {:?}, group ID: {:?}, name: {:?})",
/// user.id(),
Expand Down
14 changes: 14 additions & 0 deletions src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use crate::{
Component, ComponentExt, Components, Cpu, CpuExt, Disk, DiskExt, Disks, NetworkData,
NetworkExt, Networks, NetworksExt, Process, ProcessExt, System, SystemExt, User, UserExt,
Users,
};

use std::fmt;
Expand Down Expand Up @@ -156,6 +157,19 @@ impl fmt::Debug for Disks {
}
}

impl fmt::Debug for Users {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Users {{ {} }}",
self.iter()
.map(|x| format!("{x:?}"))
.collect::<Vec<_>>()
.join(", ")
)
}
}

impl fmt::Debug for User {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("User")
Expand Down
54 changes: 26 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ cfg_if::cfg_if! {
mod unix;
mod network;
use crate::unix::sys as sys;
use crate::unix::{network_helper, users};
use crate::unix::network_helper;

#[cfg(test)]
pub(crate) const MIN_USERS: usize = 1;
Expand All @@ -54,12 +54,12 @@ cfg_if::cfg_if! {
pub use crate::common::{
get_current_pid, CpuRefreshKind, DiskKind, DiskUsage, Disks, Gid, Group, LoadAvg, MacAddr,
Networks, NetworksIter, Pid, PidExt, ProcessRefreshKind, ProcessStatus, RefreshKind, Signal,
Uid,
Uid, Users,
};
pub use crate::sys::{Component, Components, Cpu, Disk, NetworkData, Process, System, User};
pub use crate::traits::{
ComponentExt, ComponentsExt, CpuExt, DiskExt, DisksExt, GroupExt, NetworkExt, NetworksExt,
ProcessExt, SystemExt, UserExt,
ProcessExt, SystemExt, UserExt, UsersExt,
};

#[cfg(feature = "c-interface")]
Expand Down Expand Up @@ -275,32 +275,24 @@ mod test {

#[test]
fn check_users() {
let mut s = System::new();
assert!(s.users().is_empty());
s.refresh_users_list();
assert!(s.users().len() >= MIN_USERS);

let mut s = System::new();
assert!(s.users().is_empty());
s.refresh_all();
assert!(s.users().is_empty());

let s = System::new_all();
assert!(s.users().len() >= MIN_USERS);
let mut users = Users::new();
assert!(users.users().is_empty());
users.refresh_list();
assert!(users.users().len() >= MIN_USERS);
}

#[test]
fn check_uid_gid() {
let mut s = System::new();
assert!(s.users().is_empty());
s.refresh_users_list();
let users = s.users();
assert!(users.len() >= MIN_USERS);
let mut users = Users::new();
assert!(users.users().is_empty());
users.refresh_list();
let user_list = users.users();
assert!(user_list.len() >= MIN_USERS);

if System::IS_SUPPORTED {
#[cfg(not(target_os = "windows"))]
{
let user = users
let user = user_list
.iter()
.find(|u| u.name() == "root")
.expect("no root user");
Expand All @@ -310,16 +302,18 @@ mod test {
assert!(**user.id() > 0);
assert!(*user.group_id() > 0);
}
assert!(users.iter().filter(|u| **u.id() > 0).count() > 0);
assert!(user_list.iter().filter(|u| **u.id() > 0).count() > 0);
}

// And now check that our `get_user_by_id` method works.
s.refresh_processes();
let s = System::new_with_specifics(
RefreshKind::new().with_processes(ProcessRefreshKind::new().with_user()),
);
assert!(s
.processes()
.iter()
.filter_map(|(_, p)| p.user_id())
.any(|uid| s.get_user_by_id(uid).is_some()));
.any(|uid| users.get_user_by_id(uid).is_some()));
}
}

Expand All @@ -329,16 +323,20 @@ mod test {
// If `getent` doesn't find them, we can assume it's a dark secret from the linux land.
if System::IS_SUPPORTED && cfg!(not(target_os = "linux")) {
let s = System::new_with_specifics(
RefreshKind::new()
.with_processes(ProcessRefreshKind::new().with_user())
.with_users_list(),
RefreshKind::new().with_processes(ProcessRefreshKind::new().with_user()),
);
let mut users = Users::new();
users.refresh_list();

// For every process where we can get a user ID, we should also be able
// to find that user ID in the global user list
for process in s.processes().values() {
if let Some(uid) = process.user_id() {
assert!(s.get_user_by_id(uid).is_some(), "No UID {:?} found", uid);
assert!(
users.get_user_by_id(uid).is_some(),
"No UID {:?} found",
uid
);
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions src/serde.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ impl serde::Serialize for crate::System {
S: serde::Serializer,
{
// `23` corresponds to the number of fields.
let mut state = serializer.serialize_struct("System", 23)?;
let mut state = serializer.serialize_struct("System", 22)?;

state.serialize_field("IS_SUPPORTED", &<Self as SystemExt>::IS_SUPPORTED)?;
state.serialize_field("SUPPORTED_SIGNALS", <Self as SystemExt>::SUPPORTED_SIGNALS)?;
Expand All @@ -115,8 +115,6 @@ impl serde::Serialize for crate::System {
state.serialize_field("free_swap", &self.free_swap())?;
state.serialize_field("used_swap", &self.used_swap())?;

state.serialize_field("users", &self.users())?;

state.serialize_field("uptime", &self.uptime())?;
state.serialize_field("boot_time", &self.boot_time())?;
state.serialize_field("load_average", &self.load_average())?;
Expand Down Expand Up @@ -158,6 +156,15 @@ impl Serialize for crate::Components {
}
}

impl Serialize for crate::Users {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_seq(self.iter())
}
}

impl Serialize for Signal {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down
Loading

0 comments on commit f6c1a25

Please sign in to comment.