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