diff options
Diffstat (limited to 'vendor/sysinfo/src/lib.rs')
-rw-r--r-- | vendor/sysinfo/src/lib.rs | 447 |
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); + } + } +} |