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::{IpNetwork, MacAddr, NetworkData, Networks};
77#[cfg(feature = "system")]
78pub use crate::common::system::{
79 get_current_pid, CGroupLimits, Cpu, CpuRefreshKind, LoadAvg, MemoryRefreshKind, Pid, Process,
80 ProcessRefreshKind, ProcessStatus, ProcessesToUpdate, RefreshKind, Signal, System, ThreadKind,
81 UpdateKind,
82};
83#[cfg(feature = "user")]
84pub use crate::common::user::{Group, Groups, User, Users};
85#[cfg(any(feature = "user", feature = "system"))]
86pub use crate::common::{Gid, Uid};
87#[cfg(feature = "system")]
88pub use crate::sys::{MINIMUM_CPU_UPDATE_INTERVAL, SUPPORTED_SIGNALS};
89
90#[cfg(any(feature = "system", feature = "disk"))]
91pub use crate::common::DiskUsage;
92
93#[cfg(feature = "user")]
94pub(crate) use crate::common::user::GroupInner;
95#[cfg(feature = "user")]
96pub(crate) use crate::sys::UserInner;
97#[cfg(feature = "component")]
98pub(crate) use crate::sys::{ComponentInner, ComponentsInner};
99#[cfg(feature = "system")]
100pub(crate) use crate::sys::{CpuInner, ProcessInner, SystemInner};
101#[cfg(feature = "disk")]
102pub(crate) use crate::sys::{DiskInner, DisksInner};
103#[cfg(feature = "network")]
104pub(crate) use crate::sys::{NetworkDataInner, NetworksInner};
105
106pub use crate::sys::IS_SUPPORTED_SYSTEM;
107
108#[cfg(feature = "c-interface")]
109pub use crate::c_interface::*;
110
111#[cfg(feature = "c-interface")]
112mod c_interface;
113mod common;
114mod debug;
115#[cfg(feature = "serde")]
116mod serde;
117pub(crate) mod utils;
118
119#[cfg(any())]
121mod network;
122#[cfg(any())]
123mod unix;
124#[cfg(any())]
125mod unknown;
126#[cfg(any())]
127mod windows;
128
129#[cfg_attr(feature = "system", doc = "```no_run")]
143#[cfg_attr(not(feature = "system"), doc = "```ignore")]
144pub fn set_open_files_limit(mut _new_limit: isize) -> bool {
154 cfg_if! {
155 if #[cfg(all(feature = "system", not(feature = "unknown-ci"), any(target_os = "linux", target_os = "android")))]
156 {
157 use crate::sys::system::remaining_files;
158 use std::sync::atomic::Ordering;
159
160 if _new_limit < 0 {
161 _new_limit = 0;
162 }
163 let max = sys::system::get_max_nb_fds();
164 if _new_limit > max {
165 _new_limit = max;
166 }
167
168 remaining_files().fetch_update(Ordering::SeqCst, Ordering::SeqCst, |remaining| {
172 let diff = max.saturating_sub(remaining);
173 Some(_new_limit.saturating_sub(diff))
174 }).unwrap();
175
176 true
177 } else {
178 false
179 }
180 }
181}
182
183#[cfg(doctest)]
184mod doctest {
185 macro_rules! compile_fail_import {
186 ($mod_name:ident => $($imports:ident),+ $(,)?) => {
187 $(#[doc = concat!(r"```compile_fail
188use sysinfo::", stringify!($imports), r";
189```
190")])+
191 mod $mod_name {}
192 };
193 }
194
195 #[cfg(not(feature = "system"))]
196 compile_fail_import!(
197 no_system_feature =>
198 get_current_pid,
199 CGroupLimits,
200 Cpu,
201 CpuRefreshKind,
202 DiskUsage,
203 LoadAvg,
204 MemoryRefreshKind,
205 Pid,
206 Process,
207 ProcessesToUpdate,
208 ProcessRefreshKind,
209 ProcessStatus,
210 RefreshKind,
211 Signal,
212 System,
213 ThreadKind,
214 UpdateKind,
215 );
216
217 #[cfg(not(feature = "disk"))]
218 compile_fail_import!(
219 no_disk_feature =>
220 Disk,
221 Disks,
222 DiskKind,
223 );
224
225 #[cfg(not(feature = "component"))]
226 compile_fail_import!(
227 no_component_feature =>
228 Component,
229 Components,
230 );
231
232 #[cfg(not(feature = "network"))]
233 compile_fail_import!(
234 no_network_feature =>
235 IpNetwork,
236 MacAddr,
237 NetworkData,
238 Networks,
239 );
240
241 #[cfg(not(feature = "user"))]
242 compile_fail_import!(
243 no_user_feature =>
244 Group,
245 Groups,
246 User,
247 Users,
248 );
249}
250
251#[cfg(test)]
252mod test {
253 use crate::*;
254
255 #[cfg(feature = "unknown-ci")]
256 #[test]
257 fn check_unknown_ci_feature() {
258 assert!(!IS_SUPPORTED_SYSTEM);
259 }
260
261 #[test]
263 fn check_macro_types() {
264 fn check_is_supported(_: bool) {}
265
266 check_is_supported(IS_SUPPORTED_SYSTEM);
267 }
268
269 #[cfg(feature = "system")]
271 #[test]
272 fn check_macro_types2() {
273 fn check_supported_signals(_: &'static [Signal]) {}
274 fn check_minimum_cpu_update_interval(_: std::time::Duration) {}
275
276 check_supported_signals(SUPPORTED_SIGNALS);
277 check_minimum_cpu_update_interval(MINIMUM_CPU_UPDATE_INTERVAL);
278 }
279
280 #[cfg(feature = "user")]
281 #[test]
282 fn check_uid_gid() {
283 let mut users = Users::new();
284 assert!(users.list().is_empty());
285 users.refresh();
286 let user_list = users.list();
287 assert!(user_list.len() >= MIN_USERS);
288
289 if IS_SUPPORTED_SYSTEM {
290 #[cfg(not(target_os = "windows"))]
291 {
292 let user = user_list
293 .iter()
294 .find(|u| u.name() == "root")
295 .expect("no root user");
296 assert_eq!(**user.id(), 0);
297 assert_eq!(*user.group_id(), 0);
298 if let Some(user) = users.iter().find(|u| *u.group_id() > 0) {
299 assert!(**user.id() > 0);
300 assert!(*user.group_id() > 0);
301 }
302 assert!(user_list.iter().filter(|u| **u.id() > 0).count() > 0);
303 }
304
305 #[cfg(feature = "system")]
306 {
307 let s =
309 System::new_with_specifics(RefreshKind::nothing().with_processes(
310 ProcessRefreshKind::nothing().with_user(UpdateKind::Always),
311 ));
312 assert!(s
313 .processes()
314 .iter()
315 .filter_map(|(_, p)| p.user_id())
316 .any(|uid| users.get_user_by_id(uid).is_some()));
317 }
318 }
319 }
320
321 #[cfg(feature = "system")]
322 #[test]
323 fn check_all_process_uids_resolvable() {
324 if IS_SUPPORTED_SYSTEM && cfg!(not(target_os = "linux")) {
327 let s = System::new_with_specifics(
328 RefreshKind::nothing()
329 .with_processes(ProcessRefreshKind::nothing().with_user(UpdateKind::Always)),
330 );
331 let users = Users::new_with_refreshed_list();
332
333 for process in s.processes().values() {
336 if let Some(uid) = process.user_id() {
337 assert!(
338 users.get_user_by_id(uid).is_some(),
339 "No UID {:?} found",
340 uid
341 );
342 }
343 }
344 }
345 }
346
347 #[test]
348 fn ensure_is_supported_is_set_correctly() {
349 if MIN_USERS > 0 {
350 assert!(IS_SUPPORTED_SYSTEM);
351 } else {
352 assert!(!IS_SUPPORTED_SYSTEM);
353 }
354 }
355}