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_select! {
29 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 }
37 any(
38 target_os = "macos", target_os = "ios",
39 target_os = "linux", target_os = "android",
40 target_os = "freebsd", target_os = "netbsd") =>
41 {
42 mod unix;
43 use crate::unix::sys as sys;
44
45 #[cfg(feature = "network")]
46 mod network;
47 #[cfg(feature = "network")]
48 use crate::unix::network_helper;
49
50 #[cfg(test)]
51 pub(crate) const MIN_USERS: usize = 1;
52 }
53 windows => {
54 mod windows;
55 use crate::windows as sys;
56
57 #[cfg(feature = "network")]
58 mod network;
59 #[cfg(feature = "network")]
60 use crate::windows::network_helper;
61
62 #[cfg(test)]
63 pub(crate) const MIN_USERS: usize = 1;
64 }
65 _ => {
66 mod unknown;
67 use crate::unknown as sys;
68
69 #[cfg(test)]
70 pub(crate) const MIN_USERS: usize = 0;
71 }
72}
73
74#[cfg(feature = "component")]
75pub use crate::common::component::{Component, Components};
76#[cfg(feature = "disk")]
77pub use crate::common::disk::{Disk, DiskKind, DiskRefreshKind, Disks};
78#[cfg(feature = "network")]
79pub use crate::common::network::{
80 InterfaceOperationalState, IpNetwork, IpNetworkFromStrError, MacAddr, MacAddrFromStrError,
81 NetworkData, Networks,
82};
83#[cfg(feature = "system")]
84pub use crate::common::system::{
85 CGroupLimits, Cpu, CpuRefreshKind, KillError, LoadAvg, MemoryRefreshKind, Motherboard, Pid,
86 Process, ProcessRefreshKind, ProcessStatus, ProcessesToUpdate, Product, RefreshKind, Signal,
87 System, ThreadKind, UpdateKind, get_current_pid,
88};
89#[cfg(feature = "user")]
90pub use crate::common::user::{Group, Groups, User, Users};
91#[cfg(any(feature = "user", feature = "system"))]
92pub use crate::common::{Gid, Uid};
93#[cfg(feature = "system")]
94pub use crate::sys::{MINIMUM_CPU_UPDATE_INTERVAL, SUPPORTED_SIGNALS};
95
96#[cfg(any(feature = "system", feature = "disk"))]
97pub use crate::common::DiskUsage;
98
99#[cfg(feature = "user")]
100pub(crate) use crate::common::user::GroupInner;
101#[cfg(feature = "user")]
102pub(crate) use crate::sys::UserInner;
103#[cfg(feature = "component")]
104pub(crate) use crate::sys::{ComponentInner, ComponentsInner};
105#[cfg(feature = "system")]
106pub(crate) use crate::sys::{CpuInner, MotherboardInner, ProcessInner, ProductInner, SystemInner};
107#[cfg(feature = "disk")]
108pub(crate) use crate::sys::{DiskInner, DisksInner};
109#[cfg(feature = "network")]
110pub(crate) use crate::sys::{NetworkDataInner, NetworksInner};
111
112pub use crate::sys::IS_SUPPORTED_SYSTEM;
113
114#[cfg(feature = "c-interface")]
115pub use crate::c_interface::*;
116
117#[cfg(feature = "c-interface")]
118mod c_interface;
119mod common;
120mod debug;
121#[cfg(feature = "serde")]
122mod serde;
123pub(crate) mod utils;
124
125#[cfg(any())]
127mod network;
128#[cfg(any())]
129mod unix;
130#[cfg(any())]
131mod unknown;
132#[cfg(any())]
133mod windows;
134
135#[cfg_attr(feature = "system", doc = "```no_run")]
149#[cfg_attr(not(feature = "system"), doc = "```ignore")]
150pub fn set_open_files_limit(mut _new_limit: usize) -> bool {
160 cfg_select! {
161 all(feature = "system", not(feature = "unknown-ci"), any(target_os = "linux", target_os = "android")) =>
162 {
163 use crate::sys::system::remaining_files;
164 use std::sync::atomic::Ordering;
165
166 let max = sys::system::get_max_nb_fds();
167 if _new_limit > max {
168 _new_limit = max;
169 }
170
171 if remaining_files().fetch_update(Ordering::SeqCst, Ordering::SeqCst, |remaining| {
175 let _new_limit = _new_limit as isize;
176 let diff = (max as isize).saturating_sub(remaining);
177 Some(_new_limit.saturating_sub(diff))
178 }).is_err() {
179 sysinfo_debug!("failed to update open files limit");
180 }
181
182 true
183 }
184 _ => {
185 false
186 }
187 }
188}
189
190#[cfg(doctest)]
191mod doctest {
192 macro_rules! compile_fail_import {
193 ($mod_name:ident => $($imports:ident),+ $(,)?) => {
194 $(#[doc = concat!(r"```compile_fail
195use sysinfo::", stringify!($imports), r";
196```
197")])+
198 mod $mod_name {}
199 };
200 }
201
202 #[cfg(not(feature = "system"))]
203 compile_fail_import!(
204 no_system_feature =>
205 get_current_pid,
206 CGroupLimits,
207 Cpu,
208 CpuRefreshKind,
209 DiskUsage,
210 KillError,
211 LoadAvg,
212 MemoryRefreshKind,
213 Motherboard,
214 Pid,
215 Process,
216 ProcessesToUpdate,
217 ProcessRefreshKind,
218 ProcessStatus,
219 Product,
220 RefreshKind,
221 Signal,
222 System,
223 ThreadKind,
224 UpdateKind,
225 );
226
227 #[cfg(not(feature = "disk"))]
228 compile_fail_import!(
229 no_disk_feature =>
230 Disk,
231 Disks,
232 DiskKind,
233 );
234
235 #[cfg(not(feature = "component"))]
236 compile_fail_import!(
237 no_component_feature =>
238 Component,
239 Components,
240 );
241
242 #[cfg(not(feature = "network"))]
243 compile_fail_import!(
244 no_network_feature =>
245 IpNetwork,
246 MacAddr,
247 NetworkData,
248 Networks,
249 );
250
251 #[cfg(not(feature = "user"))]
252 compile_fail_import!(
253 no_user_feature =>
254 Group,
255 Groups,
256 User,
257 Users,
258 );
259}
260
261#[cfg(test)]
262mod test {
263 use crate::*;
264
265 #[cfg(feature = "unknown-ci")]
266 #[test]
267 fn check_unknown_ci_feature() {
268 assert!(!IS_SUPPORTED_SYSTEM);
269 }
270
271 #[test]
273 fn check_macro_types() {
274 fn check_is_supported(_: bool) {}
275
276 check_is_supported(IS_SUPPORTED_SYSTEM);
277 }
278
279 #[cfg(feature = "system")]
281 #[test]
282 fn check_macro_types2() {
283 fn check_supported_signals(_: &'static [Signal]) {}
284 fn check_minimum_cpu_update_interval(_: std::time::Duration) {}
285
286 check_supported_signals(SUPPORTED_SIGNALS);
287 check_minimum_cpu_update_interval(MINIMUM_CPU_UPDATE_INTERVAL);
288 }
289
290 #[cfg(feature = "user")]
291 #[test]
292 fn check_uid_gid() {
293 let mut users = Users::new();
294 assert!(users.list().is_empty());
295 users.refresh();
296 let user_list = users.list();
297 assert!(user_list.len() >= MIN_USERS);
298
299 if IS_SUPPORTED_SYSTEM {
300 #[cfg(not(target_os = "windows"))]
301 {
302 let user = user_list
303 .iter()
304 .find(|u| u.name() == "root")
305 .expect("no root user");
306 assert_eq!(**user.id(), 0);
307 assert_eq!(*user.group_id(), 0);
308 if let Some(user) = users.iter().find(|u| *u.group_id() > 0) {
309 assert!(**user.id() > 0);
310 assert!(*user.group_id() > 0);
311 }
312 assert!(user_list.iter().filter(|u| **u.id() > 0).count() > 0);
313 }
314
315 #[cfg(feature = "system")]
316 {
317 let s =
319 System::new_with_specifics(RefreshKind::nothing().with_processes(
320 ProcessRefreshKind::nothing().with_user(UpdateKind::Always),
321 ));
322 assert!(
323 s.processes()
324 .values()
325 .filter_map(|p| p.user_id())
326 .any(|uid| users.get_user_by_id(uid).is_some())
327 );
328 }
329 }
330 }
331
332 #[cfg(all(feature = "system", feature = "user"))]
333 #[test]
334 fn check_all_process_uids_resolvable() {
335 if IS_SUPPORTED_SYSTEM && cfg!(not(target_os = "linux")) {
338 let s = System::new_with_specifics(
339 RefreshKind::nothing()
340 .with_processes(ProcessRefreshKind::nothing().with_user(UpdateKind::Always)),
341 );
342 let users = Users::new_with_refreshed_list();
343
344 for process in s.processes().values() {
347 if let Some(uid) = process.user_id() {
348 assert!(users.get_user_by_id(uid).is_some(), "No UID {uid:?} found");
349 }
350 }
351 }
352 }
353
354 #[test]
355 fn ensure_is_supported_is_set_correctly() {
356 if MIN_USERS > 0 {
357 assert!(IS_SUPPORTED_SYSTEM);
358 } else {
359 assert!(!IS_SUPPORTED_SYSTEM);
360 }
361 }
362
363 #[cfg(any(
365 feature = "system",
366 feature = "disk",
367 feature = "component",
368 feature = "user",
369 feature = "network"
370 ))]
371 #[test]
372 fn test_send_and_sync() {
373 #[allow(dead_code)]
374 trait HasSendAndSync: Send + Sync {}
375
376 impl HasSendAndSync for CGroupLimits {}
378 impl HasSendAndSync for Component {}
379 impl HasSendAndSync for Components {}
380 impl HasSendAndSync for Cpu {}
381 impl HasSendAndSync for CpuRefreshKind {}
382 impl HasSendAndSync for Disk {}
383 impl HasSendAndSync for Disks {}
384 impl HasSendAndSync for DiskRefreshKind {}
385 impl HasSendAndSync for DiskUsage {}
386 impl HasSendAndSync for Gid {}
387 impl HasSendAndSync for Group {}
388 impl HasSendAndSync for Groups {}
389 impl HasSendAndSync for IpNetwork {}
390 impl HasSendAndSync for LoadAvg {}
391 impl HasSendAndSync for MacAddr {}
392 impl HasSendAndSync for MemoryRefreshKind {}
393 impl HasSendAndSync for NetworkData {}
394 impl HasSendAndSync for Networks {}
395 impl HasSendAndSync for Pid {}
396 impl HasSendAndSync for Process {}
397 impl HasSendAndSync for ProcessRefreshKind {}
398 impl HasSendAndSync for Product {}
399 impl HasSendAndSync for RefreshKind {}
400 impl HasSendAndSync for System {}
401 impl HasSendAndSync for Uid {}
402 impl HasSendAndSync for User {}
403 impl HasSendAndSync for Users {}
404
405 impl HasSendAndSync for DiskKind {}
407 impl HasSendAndSync for IpNetworkFromStrError {}
408 impl HasSendAndSync for KillError {}
409 impl HasSendAndSync for MacAddrFromStrError {}
410 impl HasSendAndSync for ProcessStatus {}
411 impl HasSendAndSync for ProcessesToUpdate<'_> {}
412 impl HasSendAndSync for Signal {}
413 impl HasSendAndSync for ThreadKind {}
414 impl HasSendAndSync for UpdateKind {}
415 }
416}