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, KillError, LoadAvg, MemoryRefreshKind,
82 Motherboard, Pid, Process, ProcessRefreshKind, ProcessStatus, ProcessesToUpdate, Product,
83 RefreshKind, Signal, System, ThreadKind, 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, MotherboardInner, ProcessInner, ProductInner, 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: usize) -> 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 let max = sys::system::get_max_nb_fds();
163 if _new_limit > max {
164 _new_limit = max;
165 }
166
167 remaining_files().fetch_update(Ordering::SeqCst, Ordering::SeqCst, |remaining| {
171 let _new_limit = _new_limit as isize;
172 let diff = (max as isize).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 KillError,
204 LoadAvg,
205 MemoryRefreshKind,
206 Motherboard,
207 Pid,
208 Process,
209 ProcessesToUpdate,
210 ProcessRefreshKind,
211 ProcessStatus,
212 Product,
213 RefreshKind,
214 Signal,
215 System,
216 ThreadKind,
217 UpdateKind,
218 );
219
220 #[cfg(not(feature = "disk"))]
221 compile_fail_import!(
222 no_disk_feature =>
223 Disk,
224 Disks,
225 DiskKind,
226 );
227
228 #[cfg(not(feature = "component"))]
229 compile_fail_import!(
230 no_component_feature =>
231 Component,
232 Components,
233 );
234
235 #[cfg(not(feature = "network"))]
236 compile_fail_import!(
237 no_network_feature =>
238 IpNetwork,
239 MacAddr,
240 NetworkData,
241 Networks,
242 );
243
244 #[cfg(not(feature = "user"))]
245 compile_fail_import!(
246 no_user_feature =>
247 Group,
248 Groups,
249 User,
250 Users,
251 );
252}
253
254#[cfg(test)]
255mod test {
256 use crate::*;
257
258 #[cfg(feature = "unknown-ci")]
259 #[test]
260 fn check_unknown_ci_feature() {
261 assert!(!IS_SUPPORTED_SYSTEM);
262 }
263
264 #[test]
266 fn check_macro_types() {
267 fn check_is_supported(_: bool) {}
268
269 check_is_supported(IS_SUPPORTED_SYSTEM);
270 }
271
272 #[cfg(feature = "system")]
274 #[test]
275 fn check_macro_types2() {
276 fn check_supported_signals(_: &'static [Signal]) {}
277 fn check_minimum_cpu_update_interval(_: std::time::Duration) {}
278
279 check_supported_signals(SUPPORTED_SIGNALS);
280 check_minimum_cpu_update_interval(MINIMUM_CPU_UPDATE_INTERVAL);
281 }
282
283 #[cfg(feature = "user")]
284 #[test]
285 fn check_uid_gid() {
286 let mut users = Users::new();
287 assert!(users.list().is_empty());
288 users.refresh();
289 let user_list = users.list();
290 assert!(user_list.len() >= MIN_USERS);
291
292 if IS_SUPPORTED_SYSTEM {
293 #[cfg(not(target_os = "windows"))]
294 {
295 let user = user_list
296 .iter()
297 .find(|u| u.name() == "root")
298 .expect("no root user");
299 assert_eq!(**user.id(), 0);
300 assert_eq!(*user.group_id(), 0);
301 if let Some(user) = users.iter().find(|u| *u.group_id() > 0) {
302 assert!(**user.id() > 0);
303 assert!(*user.group_id() > 0);
304 }
305 assert!(user_list.iter().filter(|u| **u.id() > 0).count() > 0);
306 }
307
308 #[cfg(feature = "system")]
309 {
310 let s =
312 System::new_with_specifics(RefreshKind::nothing().with_processes(
313 ProcessRefreshKind::nothing().with_user(UpdateKind::Always),
314 ));
315 assert!(s
316 .processes()
317 .iter()
318 .filter_map(|(_, p)| p.user_id())
319 .any(|uid| users.get_user_by_id(uid).is_some()));
320 }
321 }
322 }
323
324 #[cfg(all(feature = "system", feature = "user"))]
325 #[test]
326 fn check_all_process_uids_resolvable() {
327 if IS_SUPPORTED_SYSTEM && cfg!(not(target_os = "linux")) {
330 let s = System::new_with_specifics(
331 RefreshKind::nothing()
332 .with_processes(ProcessRefreshKind::nothing().with_user(UpdateKind::Always)),
333 );
334 let users = Users::new_with_refreshed_list();
335
336 for process in s.processes().values() {
339 if let Some(uid) = process.user_id() {
340 assert!(users.get_user_by_id(uid).is_some(), "No UID {uid:?} found");
341 }
342 }
343 }
344 }
345
346 #[test]
347 fn ensure_is_supported_is_set_correctly() {
348 if MIN_USERS > 0 {
349 assert!(IS_SUPPORTED_SYSTEM);
350 } else {
351 assert!(!IS_SUPPORTED_SYSTEM);
352 }
353 }
354
355 #[cfg(any(
357 feature = "system",
358 feature = "disk",
359 feature = "component",
360 feature = "user",
361 feature = "network"
362 ))]
363 #[test]
364 fn test_send_and_sync() {
365 #[allow(dead_code)]
366 trait HasSendAndSync: Send + Sync {}
367
368 impl HasSendAndSync for CGroupLimits {}
370 impl HasSendAndSync for Component {}
371 impl HasSendAndSync for Components {}
372 impl HasSendAndSync for Cpu {}
373 impl HasSendAndSync for CpuRefreshKind {}
374 impl HasSendAndSync for Disk {}
375 impl HasSendAndSync for Disks {}
376 impl HasSendAndSync for DiskRefreshKind {}
377 impl HasSendAndSync for DiskUsage {}
378 impl HasSendAndSync for Gid {}
379 impl HasSendAndSync for Group {}
380 impl HasSendAndSync for Groups {}
381 impl HasSendAndSync for IpNetwork {}
382 impl HasSendAndSync for LoadAvg {}
383 impl HasSendAndSync for MacAddr {}
384 impl HasSendAndSync for MemoryRefreshKind {}
385 impl HasSendAndSync for NetworkData {}
386 impl HasSendAndSync for Networks {}
387 impl HasSendAndSync for Pid {}
388 impl HasSendAndSync for Process {}
389 impl HasSendAndSync for ProcessRefreshKind {}
390 impl HasSendAndSync for Product {}
391 impl HasSendAndSync for RefreshKind {}
392 impl HasSendAndSync for System {}
393 impl HasSendAndSync for Uid {}
394 impl HasSendAndSync for User {}
395 impl HasSendAndSync for Users {}
396
397 impl HasSendAndSync for DiskKind {}
399 impl HasSendAndSync for IpNetworkFromStrError {}
400 impl HasSendAndSync for KillError {}
401 impl HasSendAndSync for MacAddrFromStrError {}
402 impl HasSendAndSync for ProcessStatus {}
403 impl HasSendAndSync for ProcessesToUpdate<'_> {}
404 impl HasSendAndSync for Signal {}
405 impl HasSendAndSync for ThreadKind {}
406 impl HasSendAndSync for UpdateKind {}
407 }
408}