1#![cfg_attr(
4 all(feature = "system", feature = "disk", feature = "component", feature = "system"),
5 doc = include_str!("../README.md")
6)]
7#![cfg_attr(
8 not(all(
9 feature = "system",
10 feature = "disk",
11 feature = "component",
12 feature = "system"
13 )),
14 doc = "For crate-level documentation, all features need to be enabled."
15)]
16#![cfg_attr(feature = "serde", doc = include_str!("../md_doc/serde.md"))]
17#![allow(unknown_lints)]
18#![deny(missing_docs)]
19#![deny(rustdoc::broken_intra_doc_links)]
20#![allow(clippy::upper_case_acronyms)]
21#![allow(clippy::non_send_fields_in_send_ty)]
22#![allow(renamed_and_removed_lints)]
23#![allow(clippy::assertions_on_constants)]
24
25#[macro_use]
26mod macros;
27
28cfg_if! {
29 if #[cfg(feature = "unknown-ci")] {
30 mod unknown;
32 use crate::unknown as sys;
33
34 #[cfg(test)]
35 pub(crate) const MIN_USERS: usize = 0;
36 } else if #[cfg(any(
37 target_os = "macos", target_os = "ios",
38 target_os = "linux", target_os = "android",
39 target_os = "freebsd"))]
40 {
41 mod unix;
42 use crate::unix::sys as sys;
43
44 #[cfg(feature = "network")]
45 mod network;
46 #[cfg(feature = "network")]
47 use crate::unix::network_helper;
48
49 #[cfg(test)]
50 pub(crate) const MIN_USERS: usize = 1;
51 } else if #[cfg(windows)] {
52 mod windows;
53 use crate::windows as sys;
54
55 #[cfg(feature = "network")]
56 mod network;
57 #[cfg(feature = "network")]
58 use crate::windows::network_helper;
59
60 #[cfg(test)]
61 pub(crate) const MIN_USERS: usize = 1;
62 } else {
63 mod unknown;
64 use crate::unknown as sys;
65
66 #[cfg(test)]
67 pub(crate) const MIN_USERS: usize = 0;
68 }
69}
70
71#[cfg(feature = "component")]
72pub use crate::common::component::{Component, Components};
73#[cfg(feature = "disk")]
74pub use crate::common::disk::{Disk, DiskKind, DiskRefreshKind, Disks};
75#[cfg(feature = "network")]
76pub use crate::common::network::{
77 IpNetwork, IpNetworkFromStrError, MacAddr, MacAddrFromStrError, NetworkData, Networks,
78};
79#[cfg(feature = "system")]
80pub use crate::common::system::{
81 get_current_pid, CGroupLimits, Cpu, CpuRefreshKind, LoadAvg, MemoryRefreshKind, Pid, Process,
82 ProcessRefreshKind, ProcessStatus, ProcessesToUpdate, RefreshKind, Signal, System, ThreadKind,
83 UpdateKind,
84};
85#[cfg(feature = "user")]
86pub use crate::common::user::{Group, Groups, User, Users};
87#[cfg(any(feature = "user", feature = "system"))]
88pub use crate::common::{Gid, Uid};
89#[cfg(feature = "system")]
90pub use crate::sys::{MINIMUM_CPU_UPDATE_INTERVAL, SUPPORTED_SIGNALS};
91
92#[cfg(any(feature = "system", feature = "disk"))]
93pub use crate::common::DiskUsage;
94
95#[cfg(feature = "user")]
96pub(crate) use crate::common::user::GroupInner;
97#[cfg(feature = "user")]
98pub(crate) use crate::sys::UserInner;
99#[cfg(feature = "component")]
100pub(crate) use crate::sys::{ComponentInner, ComponentsInner};
101#[cfg(feature = "system")]
102pub(crate) use crate::sys::{CpuInner, ProcessInner, SystemInner};
103#[cfg(feature = "disk")]
104pub(crate) use crate::sys::{DiskInner, DisksInner};
105#[cfg(feature = "network")]
106pub(crate) use crate::sys::{NetworkDataInner, NetworksInner};
107
108pub use crate::sys::IS_SUPPORTED_SYSTEM;
109
110#[cfg(feature = "c-interface")]
111pub use crate::c_interface::*;
112
113#[cfg(feature = "c-interface")]
114mod c_interface;
115mod common;
116mod debug;
117#[cfg(feature = "serde")]
118mod serde;
119pub(crate) mod utils;
120
121#[cfg(any())]
123mod network;
124#[cfg(any())]
125mod unix;
126#[cfg(any())]
127mod unknown;
128#[cfg(any())]
129mod windows;
130
131#[cfg_attr(feature = "system", doc = "```no_run")]
145#[cfg_attr(not(feature = "system"), doc = "```ignore")]
146pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
156 cfg_if! {
157 if #[cfg(all(feature = "system", not(feature = "unknown-ci"), any(target_os = "linux", target_os = "android")))]
158 {
159 use crate::sys::system::remaining_files;
160 use std::sync::atomic::Ordering;
161
162 if _new_limit < 0 {
163 _new_limit = 0;
164 }
165 let max = sys::system::get_max_nb_fds();
166 if _new_limit > max {
167 _new_limit = max;
168 }
169
170 remaining_files().fetch_update(Ordering::SeqCst, Ordering::SeqCst, |remaining| {
174 let diff = max.saturating_sub(remaining);
175 Some(_new_limit.saturating_sub(diff))
176 }).unwrap();
177
178 true
179 } else {
180 false
181 }
182 }
183}
184
185#[cfg(doctest)]
186mod doctest {
187 macro_rules! compile_fail_import {
188 ($mod_name:ident => $($imports:ident),+ $(,)?) => {
189 $(#[doc = concat!(r"```compile_fail
190use sysinfo::", stringify!($imports), r";
191```
192")])+
193 mod $mod_name {}
194 };
195 }
196
197 #[cfg(not(feature = "system"))]
198 compile_fail_import!(
199 no_system_feature =>
200 get_current_pid,
201 CGroupLimits,
202 Cpu,
203 CpuRefreshKind,
204 DiskUsage,
205 LoadAvg,
206 MemoryRefreshKind,
207 Pid,
208 Process,
209 ProcessesToUpdate,
210 ProcessRefreshKind,
211 ProcessStatus,
212 RefreshKind,
213 Signal,
214 System,
215 ThreadKind,
216 UpdateKind,
217 );
218
219 #[cfg(not(feature = "disk"))]
220 compile_fail_import!(
221 no_disk_feature =>
222 Disk,
223 Disks,
224 DiskKind,
225 );
226
227 #[cfg(not(feature = "component"))]
228 compile_fail_import!(
229 no_component_feature =>
230 Component,
231 Components,
232 );
233
234 #[cfg(not(feature = "network"))]
235 compile_fail_import!(
236 no_network_feature =>
237 IpNetwork,
238 MacAddr,
239 NetworkData,
240 Networks,
241 );
242
243 #[cfg(not(feature = "user"))]
244 compile_fail_import!(
245 no_user_feature =>
246 Group,
247 Groups,
248 User,
249 Users,
250 );
251}
252
253#[cfg(test)]
254mod test {
255 use crate::*;
256
257 #[cfg(feature = "unknown-ci")]
258 #[test]
259 fn check_unknown_ci_feature() {
260 assert!(!IS_SUPPORTED_SYSTEM);
261 }
262
263 #[test]
265 fn check_macro_types() {
266 fn check_is_supported(_: bool) {}
267
268 check_is_supported(IS_SUPPORTED_SYSTEM);
269 }
270
271 #[cfg(feature = "system")]
273 #[test]
274 fn check_macro_types2() {
275 fn check_supported_signals(_: &'static [Signal]) {}
276 fn check_minimum_cpu_update_interval(_: std::time::Duration) {}
277
278 check_supported_signals(SUPPORTED_SIGNALS);
279 check_minimum_cpu_update_interval(MINIMUM_CPU_UPDATE_INTERVAL);
280 }
281
282 #[cfg(feature = "user")]
283 #[test]
284 fn check_uid_gid() {
285 let mut users = Users::new();
286 assert!(users.list().is_empty());
287 users.refresh();
288 let user_list = users.list();
289 assert!(user_list.len() >= MIN_USERS);
290
291 if IS_SUPPORTED_SYSTEM {
292 #[cfg(not(target_os = "windows"))]
293 {
294 let user = user_list
295 .iter()
296 .find(|u| u.name() == "root")
297 .expect("no root user");
298 assert_eq!(**user.id(), 0);
299 assert_eq!(*user.group_id(), 0);
300 if let Some(user) = users.iter().find(|u| *u.group_id() > 0) {
301 assert!(**user.id() > 0);
302 assert!(*user.group_id() > 0);
303 }
304 assert!(user_list.iter().filter(|u| **u.id() > 0).count() > 0);
305 }
306
307 #[cfg(feature = "system")]
308 {
309 let s =
311 System::new_with_specifics(RefreshKind::nothing().with_processes(
312 ProcessRefreshKind::nothing().with_user(UpdateKind::Always),
313 ));
314 assert!(s
315 .processes()
316 .iter()
317 .filter_map(|(_, p)| p.user_id())
318 .any(|uid| users.get_user_by_id(uid).is_some()));
319 }
320 }
321 }
322
323 #[cfg(all(feature = "system", feature = "user"))]
324 #[test]
325 fn check_all_process_uids_resolvable() {
326 if IS_SUPPORTED_SYSTEM && cfg!(not(target_os = "linux")) {
329 let s = System::new_with_specifics(
330 RefreshKind::nothing()
331 .with_processes(ProcessRefreshKind::nothing().with_user(UpdateKind::Always)),
332 );
333 let users = Users::new_with_refreshed_list();
334
335 for process in s.processes().values() {
338 if let Some(uid) = process.user_id() {
339 assert!(
340 users.get_user_by_id(uid).is_some(),
341 "No UID {:?} found",
342 uid
343 );
344 }
345 }
346 }
347 }
348
349 #[test]
350 fn ensure_is_supported_is_set_correctly() {
351 if MIN_USERS > 0 {
352 assert!(IS_SUPPORTED_SYSTEM);
353 } else {
354 assert!(!IS_SUPPORTED_SYSTEM);
355 }
356 }
357}