summaryrefslogtreecommitdiffstats
path: root/vendor/sysinfo/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/sysinfo/src/lib.rs')
-rw-r--r--vendor/sysinfo/src/lib.rs447
1 files changed, 447 insertions, 0 deletions
diff --git a/vendor/sysinfo/src/lib.rs b/vendor/sysinfo/src/lib.rs
new file mode 100644
index 000000000..977de23a3
--- /dev/null
+++ b/vendor/sysinfo/src/lib.rs
@@ -0,0 +1,447 @@
+// Take a look at the license at the top of the repository in the LICENSE file.
+
+#![doc = include_str!("../README.md")]
+#![allow(unknown_lints)]
+#![deny(missing_docs)]
+#![deny(rustdoc::broken_intra_doc_links)]
+#![allow(clippy::upper_case_acronyms)]
+#![allow(clippy::non_send_fields_in_send_ty)]
+#![allow(renamed_and_removed_lints)]
+#![allow(unknown_lints)]
+
+#[macro_use]
+mod macros;
+
+cfg_if::cfg_if! {
+ if #[cfg(feature = "unknown-ci")] {
+ // This is used in CI to check that the build for unknown targets is compiling fine.
+ mod unknown;
+ use unknown as sys;
+
+ #[cfg(test)]
+ pub(crate) const MIN_USERS: usize = 0;
+ } else if #[cfg(any(target_os = "macos", target_os = "ios"))] {
+ mod apple;
+ use apple as sys;
+ extern crate core_foundation_sys;
+
+ #[cfg(test)]
+ pub(crate) const MIN_USERS: usize = 1;
+ } else if #[cfg(windows)] {
+ mod windows;
+ use windows as sys;
+ extern crate winapi;
+ extern crate ntapi;
+
+ #[cfg(test)]
+ pub(crate) const MIN_USERS: usize = 1;
+ } else if #[cfg(any(target_os = "linux", target_os = "android"))] {
+ mod linux;
+ use linux as sys;
+ pub(crate) mod users;
+
+ #[cfg(test)]
+ pub(crate) const MIN_USERS: usize = 1;
+ } else if #[cfg(target_os = "freebsd")] {
+ mod freebsd;
+ use freebsd as sys;
+ pub(crate) mod users;
+
+ #[cfg(test)]
+ pub(crate) const MIN_USERS: usize = 1;
+ } else {
+ mod unknown;
+ use unknown as sys;
+
+ #[cfg(test)]
+ pub(crate) const MIN_USERS: usize = 0;
+ }
+}
+
+pub use common::{
+ get_current_pid, CpuRefreshKind, DiskType, DiskUsage, Gid, LoadAvg, NetworksIter, Pid, PidExt,
+ ProcessRefreshKind, ProcessStatus, RefreshKind, Signal, Uid, User,
+};
+pub use sys::{Component, Cpu, Disk, NetworkData, Networks, Process, System};
+pub use traits::{
+ ComponentExt, CpuExt, DiskExt, NetworkExt, NetworksExt, ProcessExt, SystemExt, UserExt,
+};
+
+#[cfg(feature = "c-interface")]
+pub use c_interface::*;
+
+#[cfg(feature = "c-interface")]
+mod c_interface;
+mod common;
+mod debug;
+mod system;
+mod traits;
+mod utils;
+
+/// This function is only used on linux targets, on the other platforms it does nothing and returns
+/// `false`.
+///
+/// On linux, to improve performance, we keep a `/proc` file open for each process we index with
+/// a maximum number of files open equivalent to half of the system limit.
+///
+/// The problem is that some users might need all the available file descriptors so we need to
+/// allow them to change this limit.
+///
+/// Note that if you set a limit bigger than the system limit, the system limit will be set.
+///
+/// Returns `true` if the new value has been set.
+///
+/// ```no_run
+/// use sysinfo::{System, SystemExt, set_open_files_limit};
+///
+/// // We call the function before any call to the processes update.
+/// if !set_open_files_limit(10) {
+/// // It'll always return false on non-linux targets.
+/// eprintln!("failed to update the open files limit...");
+/// }
+/// let s = System::new_all();
+/// ```
+pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
+ cfg_if::cfg_if! {
+ if #[cfg(all(not(feature = "unknown-ci"), any(target_os = "linux", target_os = "android")))]
+ {
+ if _new_limit < 0 {
+ _new_limit = 0;
+ }
+ let max = sys::system::get_max_nb_fds();
+ if _new_limit > max {
+ _new_limit = max;
+ }
+ unsafe {
+ if let Ok(ref mut x) = sys::system::REMAINING_FILES.lock() {
+ // If files are already open, to be sure that the number won't be bigger when those
+ // files are closed, we subtract the current number of opened files to the new
+ // limit.
+ let diff = max.saturating_sub(**x);
+ **x = _new_limit.saturating_sub(diff);
+ true
+ } else {
+ false
+ }
+ }
+ } else {
+ false
+ }
+ }
+}
+
+// FIXME: Can be removed once negative trait bounds are supported.
+#[cfg(doctest)]
+mod doctest {
+ /// Check that `Process` doesn't implement `Clone`.
+ ///
+ /// First we check that the "basic" code works:
+ ///
+ /// ```no_run
+ /// use sysinfo::{Process, System, SystemExt};
+ ///
+ /// let mut s = System::new_all();
+ /// let p: &Process = s.processes().values().next().unwrap();
+ /// ```
+ ///
+ /// And now we check if it fails when we try to clone it:
+ ///
+ /// ```compile_fail
+ /// use sysinfo::{Process, System, SystemExt};
+ ///
+ /// let mut s = System::new_all();
+ /// let p: &Process = s.processes().values().next().unwrap();
+ /// let p = (*p).clone();
+ /// ```
+ mod process_clone {}
+
+ /// Check that `System` doesn't implement `Clone`.
+ ///
+ /// First we check that the "basic" code works:
+ ///
+ /// ```no_run
+ /// use sysinfo::{Process, System, SystemExt};
+ ///
+ /// let s = System::new();
+ /// ```
+ ///
+ /// And now we check if it fails when we try to clone it:
+ ///
+ /// ```compile_fail
+ /// use sysinfo::{Process, System, SystemExt};
+ ///
+ /// let s = System::new();
+ /// let s = s.clone();
+ /// ```
+ mod system_clone {}
+}
+
+#[cfg(test)]
+mod test {
+ use crate::*;
+
+ #[cfg(feature = "unknown-ci")]
+ #[test]
+ fn check_unknown_ci_feature() {
+ assert!(!System::IS_SUPPORTED);
+ }
+
+ #[test]
+ fn check_process_memory_usage() {
+ let mut s = System::new();
+ s.refresh_all();
+
+ if System::IS_SUPPORTED {
+ // No process should have 0 as memory usage.
+ #[cfg(not(feature = "apple-sandbox"))]
+ assert!(!s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
+ } else {
+ // There should be no process, but if there is one, its memory usage should be 0.
+ assert!(s.processes().iter().all(|(_, proc_)| proc_.memory() == 0));
+ }
+ }
+
+ #[test]
+ fn check_memory_usage() {
+ let mut s = System::new();
+
+ assert_eq!(s.total_memory(), 0);
+ assert_eq!(s.free_memory(), 0);
+ assert_eq!(s.available_memory(), 0);
+ assert_eq!(s.used_memory(), 0);
+ assert_eq!(s.total_swap(), 0);
+ assert_eq!(s.free_swap(), 0);
+ assert_eq!(s.used_swap(), 0);
+
+ s.refresh_memory();
+ if System::IS_SUPPORTED {
+ assert!(s.total_memory() > 0);
+ assert!(s.used_memory() > 0);
+ if s.total_swap() > 0 {
+ // I think it's pretty safe to assume that there is still some swap left...
+ assert!(s.free_swap() > 0);
+ }
+ } else {
+ assert_eq!(s.total_memory(), 0);
+ assert_eq!(s.used_memory(), 0);
+ assert_eq!(s.total_swap(), 0);
+ assert_eq!(s.free_swap(), 0);
+ }
+ }
+
+ #[cfg(target_os = "linux")]
+ #[test]
+ fn check_processes_cpu_usage() {
+ if !System::IS_SUPPORTED {
+ return;
+ }
+ let mut s = System::new();
+
+ s.refresh_processes();
+ // All CPU usage will start at zero until the second refresh
+ assert!(s
+ .processes()
+ .iter()
+ .all(|(_, proc_)| proc_.cpu_usage() == 0.0));
+
+ // Wait a bit to update CPU usage values
+ std::thread::sleep(std::time::Duration::from_millis(100));
+ s.refresh_processes();
+ assert!(s
+ .processes()
+ .iter()
+ .all(|(_, proc_)| proc_.cpu_usage() >= 0.0
+ && proc_.cpu_usage() <= (s.cpus().len() as f32) * 100.0));
+ assert!(s
+ .processes()
+ .iter()
+ .any(|(_, proc_)| proc_.cpu_usage() > 0.0));
+ }
+
+ #[test]
+ fn check_cpu_usage() {
+ if !System::IS_SUPPORTED {
+ return;
+ }
+ let mut s = System::new();
+ for _ in 0..10 {
+ s.refresh_cpu();
+ // Wait a bit to update CPU usage values
+ std::thread::sleep(std::time::Duration::from_millis(100));
+ if s.cpus().iter().any(|c| c.cpu_usage() > 0.0) {
+ // All good!
+ return;
+ }
+ }
+ panic!("CPU usage is always zero...");
+ }
+
+ #[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);
+ }
+
+ #[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);
+
+ if System::IS_SUPPORTED {
+ #[cfg(not(target_os = "windows"))]
+ {
+ let user = users
+ .iter()
+ .find(|u| u.name() == "root")
+ .expect("no root user");
+ assert_eq!(**user.id(), 0);
+ assert_eq!(*user.group_id(), 0);
+ if let Some(user) = users.iter().find(|u| *u.group_id() > 0) {
+ assert!(**user.id() > 0);
+ assert!(*user.group_id() > 0);
+ }
+ assert!(users.iter().filter(|u| **u.id() > 0).count() > 0);
+ }
+
+ // And now check that our `get_user_by_id` method works.
+ s.refresh_processes();
+ assert!(s
+ .processes()
+ .iter()
+ .filter_map(|(_, p)| p.user_id())
+ .any(|uid| s.get_user_by_id(uid).is_some()));
+ }
+ }
+
+ #[test]
+ fn check_system_info() {
+ // We don't want to test on unsupported systems.
+ if System::IS_SUPPORTED {
+ let s = System::new();
+ assert!(!s.name().expect("Failed to get system name").is_empty());
+
+ assert!(!s
+ .kernel_version()
+ .expect("Failed to get kernel version")
+ .is_empty());
+
+ assert!(!s.os_version().expect("Failed to get os version").is_empty());
+
+ assert!(!s
+ .long_os_version()
+ .expect("Failed to get long OS version")
+ .is_empty());
+ }
+ }
+
+ #[test]
+ fn check_host_name() {
+ // We don't want to test on unsupported systems.
+ if System::IS_SUPPORTED {
+ let s = System::new();
+ assert!(s.host_name().is_some());
+ }
+ }
+
+ #[test]
+ fn check_refresh_process_return_value() {
+ // We don't want to test on unsupported systems.
+ if System::IS_SUPPORTED {
+ let _pid = get_current_pid().expect("Failed to get current PID");
+
+ #[cfg(not(feature = "apple-sandbox"))]
+ {
+ let mut s = System::new();
+ // First check what happens in case the process isn't already in our process list.
+ assert!(s.refresh_process(_pid));
+ // Then check that it still returns true if the process is already in our process list.
+ assert!(s.refresh_process(_pid));
+ }
+ }
+ }
+
+ #[test]
+ fn ensure_is_supported_is_set_correctly() {
+ if MIN_USERS > 0 {
+ assert!(System::IS_SUPPORTED);
+ } else {
+ assert!(!System::IS_SUPPORTED);
+ }
+ }
+
+ #[test]
+ fn check_cpus_number() {
+ let mut s = System::new();
+
+ // This information isn't retrieved by default.
+ assert!(s.cpus().is_empty());
+ if System::IS_SUPPORTED {
+ // The physical cores count is recomputed every time the function is called, so the
+ // information must be relevant even with nothing initialized.
+ let physical_cores_count = s
+ .physical_core_count()
+ .expect("failed to get number of physical cores");
+
+ s.refresh_cpu();
+ // The cpus shouldn't be empty anymore.
+ assert!(!s.cpus().is_empty());
+
+ // In case we are running inside a VM, it's possible to not have a physical core, only
+ // logical ones, which is why we don't test `physical_cores_count > 0`.
+ let physical_cores_count2 = s
+ .physical_core_count()
+ .expect("failed to get number of physical cores");
+ assert!(physical_cores_count2 <= s.cpus().len());
+ assert_eq!(physical_cores_count, physical_cores_count2);
+ } else {
+ assert_eq!(s.physical_core_count(), None);
+ }
+ assert!(s.physical_core_count().unwrap_or(0) <= s.cpus().len());
+ }
+
+ #[test]
+ fn check_nb_supported_signals() {
+ if System::IS_SUPPORTED {
+ assert!(
+ !System::SUPPORTED_SIGNALS.is_empty(),
+ "SUPPORTED_SIGNALS shoudn't be empty on supported systems!"
+ );
+ } else {
+ assert!(
+ System::SUPPORTED_SIGNALS.is_empty(),
+ "SUPPORTED_SIGNALS should be empty on not support systems!"
+ );
+ }
+ }
+
+ // Ensure that the CPUs frequency isn't retrieved until we ask for it.
+ #[test]
+ #[cfg(not(target_os = "freebsd"))] // In a VM, it'll fail.
+ fn check_cpu_frequency() {
+ if !System::IS_SUPPORTED {
+ return;
+ }
+ let mut s = System::new();
+ s.refresh_processes();
+ for proc_ in s.cpus() {
+ assert_eq!(proc_.frequency(), 0);
+ }
+ s.refresh_cpu();
+ for proc_ in s.cpus() {
+ assert_ne!(proc_.frequency(), 0);
+ }
+ }
+}