sysinfo/common.rs
1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use crate::{
4 utils::into_iter_mut, ComponentInner, ComponentsInner, CpuInner, NetworkDataInner,
5 NetworksInner, ProcessInner, SystemInner, UserInner,
6};
7
8use std::cmp::Ordering;
9use std::collections::{HashMap, HashSet};
10use std::convert::TryFrom;
11use std::ffi::OsStr;
12use std::fmt;
13use std::path::Path;
14use std::str::FromStr;
15
16/// Structs containing system's information such as processes, memory and CPU.
17///
18/// ```
19/// use sysinfo::System;
20///
21/// if sysinfo::IS_SUPPORTED_SYSTEM {
22/// println!("System: {:?}", System::new_all());
23/// } else {
24/// println!("This OS isn't supported (yet?).");
25/// }
26/// ```
27pub struct System {
28 pub(crate) inner: SystemInner,
29}
30
31impl Default for System {
32 fn default() -> System {
33 System::new()
34 }
35}
36
37impl System {
38 /// Creates a new [`System`] instance with nothing loaded.
39 ///
40 /// Use one of the refresh methods (like [`refresh_all`]) to update its internal information.
41 ///
42 /// [`System`]: crate::System
43 /// [`refresh_all`]: #method.refresh_all
44 ///
45 /// ```no_run
46 /// use sysinfo::System;
47 ///
48 /// let s = System::new();
49 /// ```
50 pub fn new() -> Self {
51 Self::new_with_specifics(RefreshKind::new())
52 }
53
54 /// Creates a new [`System`] instance with everything loaded.
55 ///
56 /// It is an equivalent of [`System::new_with_specifics`]`(`[`RefreshKind::everything`]`())`.
57 ///
58 /// [`System`]: crate::System
59 ///
60 /// ```no_run
61 /// use sysinfo::System;
62 ///
63 /// let s = System::new_all();
64 /// ```
65 pub fn new_all() -> Self {
66 Self::new_with_specifics(RefreshKind::everything())
67 }
68
69 /// Creates a new [`System`] instance and refresh the data corresponding to the
70 /// given [`RefreshKind`].
71 ///
72 /// [`System`]: crate::System
73 ///
74 /// ```
75 /// use sysinfo::{ProcessRefreshKind, RefreshKind, System};
76 ///
77 /// // We want to only refresh processes.
78 /// let mut system = System::new_with_specifics(
79 /// RefreshKind::new().with_processes(ProcessRefreshKind::everything()),
80 /// );
81 ///
82 /// # if sysinfo::IS_SUPPORTED_SYSTEM && !cfg!(feature = "apple-sandbox") {
83 /// assert!(!system.processes().is_empty());
84 /// # }
85 /// ```
86 pub fn new_with_specifics(refreshes: RefreshKind) -> Self {
87 let mut s = Self {
88 inner: SystemInner::new(),
89 };
90 s.refresh_specifics(refreshes);
91 s
92 }
93
94 /// Refreshes according to the given [`RefreshKind`]. It calls the corresponding
95 /// "refresh_" methods.
96 ///
97 /// ```
98 /// use sysinfo::{ProcessRefreshKind, RefreshKind, System};
99 ///
100 /// let mut s = System::new_all();
101 ///
102 /// // Let's just update processes:
103 /// s.refresh_specifics(
104 /// RefreshKind::new().with_processes(ProcessRefreshKind::everything()),
105 /// );
106 /// ```
107 pub fn refresh_specifics(&mut self, refreshes: RefreshKind) {
108 if let Some(kind) = refreshes.memory() {
109 self.refresh_memory_specifics(kind);
110 }
111 if let Some(kind) = refreshes.cpu() {
112 self.refresh_cpu_specifics(kind);
113 }
114 if let Some(kind) = refreshes.processes() {
115 self.refresh_processes_specifics(kind);
116 }
117 }
118
119 /// Refreshes all system and processes information.
120 ///
121 /// It is the same as calling `system.refresh_specifics(RefreshKind::everything())`.
122 ///
123 /// Don't forget to take a look at [`ProcessRefreshKind::everything`] method to see what it
124 /// will update for processes more in details.
125 ///
126 /// ```no_run
127 /// use sysinfo::System;
128 ///
129 /// let mut s = System::new();
130 /// s.refresh_all();
131 /// ```
132 pub fn refresh_all(&mut self) {
133 self.refresh_specifics(RefreshKind::everything());
134 }
135
136 /// Refreshes RAM and SWAP usage.
137 ///
138 /// It is the same as calling `system.refresh_memory_specifics(MemoryRefreshKind::everything())`.
139 ///
140 /// If you don't want to refresh both, take a look at [`System::refresh_memory_specifics`].
141 ///
142 /// ```no_run
143 /// use sysinfo::System;
144 ///
145 /// let mut s = System::new();
146 /// s.refresh_memory();
147 /// ```
148 pub fn refresh_memory(&mut self) {
149 self.refresh_memory_specifics(MemoryRefreshKind::everything())
150 }
151
152 /// Refreshes system memory specific information.
153 ///
154 /// ```no_run
155 /// use sysinfo::{MemoryRefreshKind, System};
156 ///
157 /// let mut s = System::new();
158 /// s.refresh_memory_specifics(MemoryRefreshKind::new().with_ram());
159 /// ```
160 pub fn refresh_memory_specifics(&mut self, refresh_kind: MemoryRefreshKind) {
161 self.inner.refresh_memory_specifics(refresh_kind)
162 }
163
164 /// Refreshes CPUs usage.
165 ///
166 /// ⚠️ Please note that the result will very likely be inaccurate at the first call.
167 /// You need to call this method at least twice (with a bit of time between each call, like
168 /// 200 ms, take a look at [`MINIMUM_CPU_UPDATE_INTERVAL`] for more information)
169 /// to get accurate value as it uses previous results to compute the next value.
170 ///
171 /// Calling this method is the same as calling
172 /// `system.refresh_cpu_specifics(CpuRefreshKind::new().with_cpu_usage())`.
173 ///
174 /// ```no_run
175 /// use sysinfo::System;
176 ///
177 /// let mut s = System::new_all();
178 /// s.refresh_cpu_usage();
179 /// ```
180 ///
181 /// [`MINIMUM_CPU_UPDATE_INTERVAL`]: crate::MINIMUM_CPU_UPDATE_INTERVAL
182 pub fn refresh_cpu_usage(&mut self) {
183 self.refresh_cpu_specifics(CpuRefreshKind::new().with_cpu_usage())
184 }
185
186 /// Refreshes CPUs frequency information.
187 ///
188 /// Calling this method is the same as calling
189 /// `system.refresh_cpu_specifics(CpuRefreshKind::new().with_frequency())`.
190 ///
191 /// ```no_run
192 /// use sysinfo::System;
193 ///
194 /// let mut s = System::new_all();
195 /// s.refresh_cpu_frequency();
196 /// ```
197 pub fn refresh_cpu_frequency(&mut self) {
198 self.refresh_cpu_specifics(CpuRefreshKind::new().with_frequency())
199 }
200
201 /// Refreshes all information related to CPUs information.
202 ///
203 /// ⚠️ Please note that the result will very likely be inaccurate at the first call.
204 /// You need to call this method at least twice (with a bit of time between each call, like
205 /// 200 ms, take a look at [`MINIMUM_CPU_UPDATE_INTERVAL`] for more information)
206 /// to get accurate value as it uses previous results to compute the next value.
207 ///
208 /// Calling this method is the same as calling
209 /// `system.refresh_cpu_specifics(CpuRefreshKind::everything())`.
210 ///
211 /// ```no_run
212 /// use sysinfo::System;
213 ///
214 /// let mut s = System::new_all();
215 /// s.refresh_cpu();
216 /// ```
217 ///
218 /// [`MINIMUM_CPU_UPDATE_INTERVAL`]: crate::MINIMUM_CPU_UPDATE_INTERVAL
219 pub fn refresh_cpu(&mut self) {
220 self.refresh_cpu_specifics(CpuRefreshKind::everything())
221 }
222
223 /// Refreshes CPUs specific information.
224 ///
225 /// ```no_run
226 /// use sysinfo::{System, CpuRefreshKind};
227 ///
228 /// let mut s = System::new_all();
229 /// s.refresh_cpu_specifics(CpuRefreshKind::everything());
230 /// ```
231 pub fn refresh_cpu_specifics(&mut self, refresh_kind: CpuRefreshKind) {
232 self.inner.refresh_cpu_specifics(refresh_kind)
233 }
234
235 /// Gets all processes and updates their information.
236 ///
237 /// It does the same as:
238 ///
239 /// ```no_run
240 /// # use sysinfo::{ProcessRefreshKind, System, UpdateKind};
241 /// # let mut system = System::new();
242 /// system.refresh_processes_specifics(
243 /// ProcessRefreshKind::new()
244 /// .with_memory()
245 /// .with_cpu()
246 /// .with_disk_usage()
247 /// .with_exe(UpdateKind::OnlyIfNotSet),
248 /// );
249 /// ```
250 ///
251 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
252 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
253 ///
254 /// Example:
255 ///
256 /// ```no_run
257 /// use sysinfo::System;
258 ///
259 /// let mut s = System::new_all();
260 /// s.refresh_processes();
261 /// ```
262 pub fn refresh_processes(&mut self) {
263 self.refresh_processes_specifics(
264 ProcessRefreshKind::new()
265 .with_memory()
266 .with_cpu()
267 .with_disk_usage()
268 .with_exe(UpdateKind::OnlyIfNotSet),
269 );
270 }
271
272 /// Gets all processes and updates the specified information.
273 ///
274 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
275 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
276 ///
277 /// ```no_run
278 /// use sysinfo::{ProcessRefreshKind, System};
279 ///
280 /// let mut s = System::new_all();
281 /// s.refresh_processes_specifics(ProcessRefreshKind::new());
282 /// ```
283 pub fn refresh_processes_specifics(&mut self, refresh_kind: ProcessRefreshKind) {
284 self.inner.refresh_processes_specifics(None, refresh_kind)
285 }
286
287 /// Gets specified processes and updates their information.
288 ///
289 /// It does the same as:
290 ///
291 /// ```no_run
292 /// # use sysinfo::{Pid, ProcessRefreshKind, System, UpdateKind};
293 /// # let mut system = System::new();
294 /// system.refresh_pids_specifics(
295 /// &[Pid::from(1), Pid::from(2)],
296 /// ProcessRefreshKind::new()
297 /// .with_memory()
298 /// .with_cpu()
299 /// .with_disk_usage()
300 /// .with_exe(UpdateKind::OnlyIfNotSet),
301 /// );
302 /// ```
303 ///
304 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
305 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
306 ///
307 /// Example:
308 ///
309 /// ```no_run
310 /// use sysinfo::System;
311 ///
312 /// let mut s = System::new_all();
313 /// s.refresh_processes();
314 /// ```
315 pub fn refresh_pids(&mut self, pids: &[Pid]) {
316 self.refresh_pids_specifics(
317 pids,
318 ProcessRefreshKind::new()
319 .with_memory()
320 .with_cpu()
321 .with_disk_usage()
322 .with_exe(UpdateKind::OnlyIfNotSet),
323 );
324 }
325
326 /// Gets specified processes and updates the specified information.
327 ///
328 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
329 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
330 ///
331 /// ```no_run
332 /// use sysinfo::{Pid, ProcessRefreshKind, System};
333 ///
334 /// let mut s = System::new_all();
335 /// s.refresh_pids_specifics(&[Pid::from(1), Pid::from(2)], ProcessRefreshKind::new());
336 /// ```
337 pub fn refresh_pids_specifics(&mut self, pids: &[Pid], refresh_kind: ProcessRefreshKind) {
338 if pids.is_empty() {
339 return;
340 }
341 self.inner
342 .refresh_processes_specifics(Some(pids), refresh_kind)
343 }
344
345 /// Refreshes *only* the process corresponding to `pid`. Returns `false` if the process doesn't
346 /// exist (it will **NOT** be removed from the processes if it doesn't exist anymore). If it
347 /// isn't listed yet, it'll be added.
348 ///
349 /// It is the same as calling:
350 ///
351 /// ```no_run
352 /// # use sysinfo::{Pid, ProcessRefreshKind, System, UpdateKind};
353 /// # let mut system = System::new();
354 /// # let pid = Pid::from(0);
355 /// system.refresh_process_specifics(
356 /// pid,
357 /// ProcessRefreshKind::new()
358 /// .with_memory()
359 /// .with_cpu()
360 /// .with_disk_usage()
361 /// .with_exe(UpdateKind::OnlyIfNotSet),
362 /// );
363 /// ```
364 ///
365 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
366 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
367 ///
368 /// Example:
369 ///
370 /// ```no_run
371 /// use sysinfo::{Pid, System};
372 ///
373 /// let mut s = System::new_all();
374 /// s.refresh_process(Pid::from(1337));
375 /// ```
376 pub fn refresh_process(&mut self, pid: Pid) -> bool {
377 self.refresh_process_specifics(
378 pid,
379 ProcessRefreshKind::new()
380 .with_memory()
381 .with_cpu()
382 .with_disk_usage()
383 .with_exe(UpdateKind::OnlyIfNotSet),
384 )
385 }
386
387 /// Refreshes *only* the process corresponding to `pid`. Returns `false` if the process doesn't
388 /// exist (it will **NOT** be removed from the processes if it doesn't exist anymore). If it
389 /// isn't listed yet, it'll be added.
390 ///
391 /// ⚠️ On Linux, `sysinfo` keeps the `stat` files open by default. You can change this behaviour
392 /// by using [`set_open_files_limit`][crate::set_open_files_limit].
393 ///
394 /// ```no_run
395 /// use sysinfo::{Pid, ProcessRefreshKind, System};
396 ///
397 /// let mut s = System::new_all();
398 /// s.refresh_process_specifics(Pid::from(1337), ProcessRefreshKind::new());
399 /// ```
400 pub fn refresh_process_specifics(
401 &mut self,
402 pid: Pid,
403 refresh_kind: ProcessRefreshKind,
404 ) -> bool {
405 self.inner.refresh_process_specifics(pid, refresh_kind)
406 }
407
408 /// Returns the process list.
409 ///
410 /// ```no_run
411 /// use sysinfo::System;
412 ///
413 /// let s = System::new_all();
414 /// for (pid, process) in s.processes() {
415 /// println!("{} {}", pid, process.name());
416 /// }
417 /// ```
418 pub fn processes(&self) -> &HashMap<Pid, Process> {
419 self.inner.processes()
420 }
421
422 /// Returns the process corresponding to the given `pid` or `None` if no such process exists.
423 ///
424 /// ```no_run
425 /// use sysinfo::{Pid, System};
426 ///
427 /// let s = System::new_all();
428 /// if let Some(process) = s.process(Pid::from(1337)) {
429 /// println!("{}", process.name());
430 /// }
431 /// ```
432 pub fn process(&self, pid: Pid) -> Option<&Process> {
433 self.inner.process(pid)
434 }
435
436 /// Returns an iterator of process containing the given `name`.
437 ///
438 /// If you want only the processes with exactly the given `name`, take a look at
439 /// [`System::processes_by_exact_name`].
440 ///
441 /// **⚠️ Important ⚠️**
442 ///
443 /// On **Linux**, there are two things to know about processes' name:
444 /// 1. It is limited to 15 characters.
445 /// 2. It is not always the exe name.
446 ///
447 /// ```no_run
448 /// use sysinfo::System;
449 ///
450 /// let s = System::new_all();
451 /// for process in s.processes_by_name("htop") {
452 /// println!("{} {}", process.pid(), process.name());
453 /// }
454 /// ```
455 pub fn processes_by_name<'a: 'b, 'b>(
456 &'a self,
457 name: &'b str,
458 ) -> impl Iterator<Item = &'a Process> + 'b {
459 self.processes()
460 .values()
461 .filter(move |val: &&Process| val.name().contains(name))
462 }
463
464 /// Returns an iterator of processes with exactly the given `name`.
465 ///
466 /// If you instead want the processes containing `name`, take a look at
467 /// [`System::processes_by_name`].
468 ///
469 /// **⚠️ Important ⚠️**
470 ///
471 /// On **Linux**, there are two things to know about processes' name:
472 /// 1. It is limited to 15 characters.
473 /// 2. It is not always the exe name.
474 ///
475 /// ```no_run
476 /// use sysinfo::System;
477 ///
478 /// let s = System::new_all();
479 /// for process in s.processes_by_exact_name("htop") {
480 /// println!("{} {}", process.pid(), process.name());
481 /// }
482 /// ```
483 pub fn processes_by_exact_name<'a: 'b, 'b>(
484 &'a self,
485 name: &'b str,
486 ) -> impl Iterator<Item = &'a Process> + 'b {
487 self.processes()
488 .values()
489 .filter(move |val: &&Process| val.name() == name)
490 }
491
492 /// Returns "global" CPUs information (aka the addition of all the CPUs).
493 ///
494 /// To have up-to-date information, you need to call [`System::refresh_cpu`] or
495 /// [`System::refresh_specifics`] with `cpu` enabled.
496 ///
497 /// **⚠️ Important ⚠️**
498 ///
499 /// Information like [`Cpu::brand`], [`Cpu::vendor_id`] or [`Cpu::frequency`]
500 /// are not set on the "global" CPU.
501 ///
502 /// ```no_run
503 /// use sysinfo::{CpuRefreshKind, RefreshKind, System};
504 ///
505 /// let s = System::new_with_specifics(
506 /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
507 /// );
508 /// println!("{}%", s.global_cpu_info().cpu_usage());
509 /// ```
510 ///
511 /// [`Cpu::brand`]: crate::Cpu::brand
512 /// [`Cpu::vendor_id`]: crate::Cpu::vendor_id
513 /// [`Cpu::frequency`]: crate::Cpu::frequency
514 pub fn global_cpu_info(&self) -> &Cpu {
515 self.inner.global_cpu_info()
516 }
517
518 /// Returns the list of the CPUs.
519 ///
520 /// By default, the list of CPUs is empty until you call [`System::refresh_cpu`] or
521 /// [`System::refresh_specifics`] with `cpu` enabled.
522 ///
523 /// ```no_run
524 /// use sysinfo::{CpuRefreshKind, RefreshKind, System};
525 ///
526 /// let s = System::new_with_specifics(
527 /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
528 /// );
529 /// for cpu in s.cpus() {
530 /// println!("{}%", cpu.cpu_usage());
531 /// }
532 /// ```
533 pub fn cpus(&self) -> &[Cpu] {
534 self.inner.cpus()
535 }
536
537 /// Returns the number of physical cores on the CPU or `None` if it couldn't get it.
538 ///
539 /// In case there are multiple CPUs, it will combine the physical core count of all the CPUs.
540 ///
541 /// **Important**: this information is computed every time this function is called.
542 ///
543 /// ```no_run
544 /// use sysinfo::System;
545 ///
546 /// let s = System::new();
547 /// println!("{:?}", s.physical_core_count());
548 /// ```
549 pub fn physical_core_count(&self) -> Option<usize> {
550 self.inner.physical_core_count()
551 }
552
553 /// Returns the RAM size in bytes.
554 ///
555 /// ```no_run
556 /// use sysinfo::System;
557 ///
558 /// let s = System::new_all();
559 /// println!("{} bytes", s.total_memory());
560 /// ```
561 ///
562 /// On Linux, if you want to see this information with the limit of your cgroup, take a look
563 /// at [`cgroup_limits`](System::cgroup_limits).
564 pub fn total_memory(&self) -> u64 {
565 self.inner.total_memory()
566 }
567
568 /// Returns the amount of free RAM in bytes.
569 ///
570 /// Generally, "free" memory refers to unallocated memory whereas "available" memory refers to
571 /// memory that is available for (re)use.
572 ///
573 /// Side note: Windows doesn't report "free" memory so this method returns the same value
574 /// as [`available_memory`](System::available_memory).
575 ///
576 /// ```no_run
577 /// use sysinfo::System;
578 ///
579 /// let s = System::new_all();
580 /// println!("{} bytes", s.free_memory());
581 /// ```
582 pub fn free_memory(&self) -> u64 {
583 self.inner.free_memory()
584 }
585
586 /// Returns the amount of available RAM in bytes.
587 ///
588 /// Generally, "free" memory refers to unallocated memory whereas "available" memory refers to
589 /// memory that is available for (re)use.
590 ///
591 /// ⚠️ Windows and FreeBSD don't report "available" memory so [`System::free_memory`]
592 /// returns the same value as this method.
593 ///
594 /// ```no_run
595 /// use sysinfo::System;
596 ///
597 /// let s = System::new_all();
598 /// println!("{} bytes", s.available_memory());
599 /// ```
600 pub fn available_memory(&self) -> u64 {
601 self.inner.available_memory()
602 }
603
604 /// Returns the amount of used RAM in bytes.
605 ///
606 /// ```no_run
607 /// use sysinfo::System;
608 ///
609 /// let s = System::new_all();
610 /// println!("{} bytes", s.used_memory());
611 /// ```
612 pub fn used_memory(&self) -> u64 {
613 self.inner.used_memory()
614 }
615
616 /// Returns the SWAP size in bytes.
617 ///
618 /// ```no_run
619 /// use sysinfo::System;
620 ///
621 /// let s = System::new_all();
622 /// println!("{} bytes", s.total_swap());
623 /// ```
624 pub fn total_swap(&self) -> u64 {
625 self.inner.total_swap()
626 }
627
628 /// Returns the amount of free SWAP in bytes.
629 ///
630 /// ```no_run
631 /// use sysinfo::System;
632 ///
633 /// let s = System::new_all();
634 /// println!("{} bytes", s.free_swap());
635 /// ```
636 pub fn free_swap(&self) -> u64 {
637 self.inner.free_swap()
638 }
639
640 /// Returns the amount of used SWAP in bytes.
641 ///
642 /// ```no_run
643 /// use sysinfo::System;
644 ///
645 /// let s = System::new_all();
646 /// println!("{} bytes", s.used_swap());
647 /// ```
648 pub fn used_swap(&self) -> u64 {
649 self.inner.used_swap()
650 }
651
652 /// Retrieves the limits for the current cgroup (if any), otherwise it returns `None`.
653 ///
654 /// This information is computed every time the method is called.
655 ///
656 /// ⚠️ You need to have run [`refresh_memory`](System::refresh_memory) at least once before
657 /// calling this method.
658 ///
659 /// ⚠️ This method is only implemented for Linux. It always returns `None` for all other
660 /// systems.
661 ///
662 /// ```no_run
663 /// use sysinfo::System;
664 ///
665 /// let s = System::new_all();
666 /// println!("limits: {:?}", s.cgroup_limits());
667 /// ```
668 pub fn cgroup_limits(&self) -> Option<CGroupLimits> {
669 self.inner.cgroup_limits()
670 }
671
672 /// Returns system uptime (in seconds).
673 ///
674 /// **Important**: this information is computed every time this function is called.
675 ///
676 /// ```no_run
677 /// use sysinfo::System;
678 ///
679 /// println!("System running since {} seconds", System::uptime());
680 /// ```
681 pub fn uptime() -> u64 {
682 SystemInner::uptime()
683 }
684
685 /// Returns the time (in seconds) when the system booted since UNIX epoch.
686 ///
687 /// **Important**: this information is computed every time this function is called.
688 ///
689 /// ```no_run
690 /// use sysinfo::System;
691 ///
692 /// println!("System booted at {} seconds", System::boot_time());
693 /// ```
694 pub fn boot_time() -> u64 {
695 SystemInner::boot_time()
696 }
697
698 /// Returns the system load average value.
699 ///
700 /// **Important**: this information is computed every time this function is called.
701 ///
702 /// ⚠️ This is currently not working on **Windows**.
703 ///
704 /// ```no_run
705 /// use sysinfo::System;
706 ///
707 /// let load_avg = System::load_average();
708 /// println!(
709 /// "one minute: {}%, five minutes: {}%, fifteen minutes: {}%",
710 /// load_avg.one,
711 /// load_avg.five,
712 /// load_avg.fifteen,
713 /// );
714 /// ```
715 pub fn load_average() -> LoadAvg {
716 SystemInner::load_average()
717 }
718
719 /// Returns the system name.
720 ///
721 /// **Important**: this information is computed every time this function is called.
722 ///
723 /// ```no_run
724 /// use sysinfo::System;
725 ///
726 /// println!("OS: {:?}", System::name());
727 /// ```
728 pub fn name() -> Option<String> {
729 SystemInner::name()
730 }
731
732 /// Returns the system's kernel version.
733 ///
734 /// **Important**: this information is computed every time this function is called.
735 ///
736 /// ```no_run
737 /// use sysinfo::System;
738 ///
739 /// println!("kernel version: {:?}", System::kernel_version());
740 /// ```
741 pub fn kernel_version() -> Option<String> {
742 SystemInner::kernel_version()
743 }
744
745 /// Returns the system version (e.g. for MacOS this will return 11.1 rather than the kernel
746 /// version).
747 ///
748 /// **Important**: this information is computed every time this function is called.
749 ///
750 /// ```no_run
751 /// use sysinfo::System;
752 ///
753 /// println!("OS version: {:?}", System::os_version());
754 /// ```
755 pub fn os_version() -> Option<String> {
756 SystemInner::os_version()
757 }
758
759 /// Returns the system long os version (e.g "MacOS 11.2 BigSur").
760 ///
761 /// **Important**: this information is computed every time this function is called.
762 ///
763 /// ```no_run
764 /// use sysinfo::System;
765 ///
766 /// println!("Long OS Version: {:?}", System::long_os_version());
767 /// ```
768 pub fn long_os_version() -> Option<String> {
769 SystemInner::long_os_version()
770 }
771
772 /// Returns the distribution id as defined by os-release,
773 /// or [`std::env::consts::OS`].
774 ///
775 /// See also
776 /// - <https://www.freedesktop.org/software/systemd/man/os-release.html#ID=>
777 /// - <https://doc.rust-lang.org/std/env/consts/constant.OS.html>
778 ///
779 /// **Important**: this information is computed every time this function is called.
780 ///
781 /// ```no_run
782 /// use sysinfo::System;
783 ///
784 /// println!("Distribution ID: {:?}", System::distribution_id());
785 /// ```
786 pub fn distribution_id() -> String {
787 SystemInner::distribution_id()
788 }
789
790 /// Returns the system hostname based off DNS.
791 ///
792 /// **Important**: this information is computed every time this function is called.
793 ///
794 /// ```no_run
795 /// use sysinfo::System;
796 ///
797 /// println!("Hostname: {:?}", System::host_name());
798 /// ```
799 pub fn host_name() -> Option<String> {
800 SystemInner::host_name()
801 }
802
803 /// Returns the CPU architecture (eg. x86, amd64, aarch64, ...).
804 ///
805 /// **Important**: this information is computed every time this function is called.
806 ///
807 /// ```no_run
808 /// use sysinfo::System;
809 ///
810 /// println!("CPU Architecture: {:?}", System::cpu_arch());
811 /// ```
812 pub fn cpu_arch() -> Option<String> {
813 SystemInner::cpu_arch()
814 }
815}
816
817/// Struct containing information of a process.
818///
819/// ## iOS
820///
821/// This information cannot be retrieved on iOS due to sandboxing.
822///
823/// ## Apple app store
824///
825/// If you are building a macOS Apple app store, it won't be able
826/// to retrieve this information.
827///
828/// ```no_run
829/// use sysinfo::{Pid, System};
830///
831/// let s = System::new_all();
832/// if let Some(process) = s.process(Pid::from(1337)) {
833/// println!("{}", process.name());
834/// }
835/// ```
836pub struct Process {
837 pub(crate) inner: ProcessInner,
838}
839
840impl Process {
841 /// Sends [`Signal::Kill`] to the process (which is the only signal supported on all supported
842 /// platforms by this crate).
843 ///
844 /// If you want to send another signal, take a look at [`Process::kill_with`].
845 ///
846 /// To get the list of the supported signals on this system, use
847 /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
848 ///
849 /// ```no_run
850 /// use sysinfo::{Pid, System};
851 ///
852 /// let s = System::new_all();
853 /// if let Some(process) = s.process(Pid::from(1337)) {
854 /// process.kill();
855 /// }
856 /// ```
857 pub fn kill(&self) -> bool {
858 self.kill_with(Signal::Kill).unwrap_or(false)
859 }
860
861 /// Sends the given `signal` to the process. If the signal doesn't exist on this platform,
862 /// it'll do nothing and will return `None`. Otherwise it'll return if the signal was sent
863 /// successfully.
864 ///
865 /// If you just want to kill the process, use [`Process::kill`] directly.
866 ///
867 /// To get the list of the supported signals on this system, use
868 /// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
869 ///
870 /// ```no_run
871 /// use sysinfo::{Pid, Signal, System};
872 ///
873 /// let s = System::new_all();
874 /// if let Some(process) = s.process(Pid::from(1337)) {
875 /// if process.kill_with(Signal::Kill).is_none() {
876 /// println!("This signal isn't supported on this platform");
877 /// }
878 /// }
879 /// ```
880 pub fn kill_with(&self, signal: Signal) -> Option<bool> {
881 self.inner.kill_with(signal)
882 }
883
884 /// Returns the name of the process.
885 ///
886 /// **⚠️ Important ⚠️**
887 ///
888 /// On **Linux**, there are two things to know about processes' name:
889 /// 1. It is limited to 15 characters.
890 /// 2. It is not always the exe name.
891 ///
892 /// If you are looking for a specific process, unless you know what you are
893 /// doing, in most cases it's better to use [`Process::exe`] instead (which
894 /// can be empty sometimes!).
895 ///
896 /// ```no_run
897 /// use sysinfo::{Pid, System};
898 ///
899 /// let s = System::new_all();
900 /// if let Some(process) = s.process(Pid::from(1337)) {
901 /// println!("{}", process.name());
902 /// }
903 /// ```
904 pub fn name(&self) -> &str {
905 self.inner.name()
906 }
907
908 /// Returns the command line.
909 ///
910 /// ```no_run
911 /// use sysinfo::{Pid, System};
912 ///
913 /// let s = System::new_all();
914 /// if let Some(process) = s.process(Pid::from(1337)) {
915 /// println!("{:?}", process.cmd());
916 /// }
917 /// ```
918 pub fn cmd(&self) -> &[String] {
919 self.inner.cmd()
920 }
921
922 /// Returns the path to the process.
923 ///
924 /// ```no_run
925 /// use sysinfo::{Pid, System};
926 ///
927 /// let s = System::new_all();
928 /// if let Some(process) = s.process(Pid::from(1337)) {
929 /// println!("{:?}", process.exe());
930 /// }
931 /// ```
932 ///
933 /// ### Implementation notes
934 ///
935 /// On Linux, this method will return an empty path if there
936 /// was an error trying to read `/proc/<pid>/exe`. This can
937 /// happen, for example, if the permission levels or UID namespaces
938 /// between the caller and target processes are different.
939 ///
940 /// It is also the case that `cmd[0]` is _not_ usually a correct
941 /// replacement for this.
942 /// A process [may change its `cmd[0]` value](https://man7.org/linux/man-pages/man5/proc.5.html)
943 /// freely, making this an untrustworthy source of information.
944 pub fn exe(&self) -> Option<&Path> {
945 self.inner.exe()
946 }
947
948 /// Returns the PID of the process.
949 ///
950 /// ```no_run
951 /// use sysinfo::{Pid, System};
952 ///
953 /// let s = System::new_all();
954 /// if let Some(process) = s.process(Pid::from(1337)) {
955 /// println!("{}", process.pid());
956 /// }
957 /// ```
958 pub fn pid(&self) -> Pid {
959 self.inner.pid()
960 }
961
962 /// Returns the environment variables of the process.
963 ///
964 /// ```no_run
965 /// use sysinfo::{Pid, System};
966 ///
967 /// let s = System::new_all();
968 /// if let Some(process) = s.process(Pid::from(1337)) {
969 /// println!("{:?}", process.environ());
970 /// }
971 /// ```
972 pub fn environ(&self) -> &[String] {
973 self.inner.environ()
974 }
975
976 /// Returns the current working directory.
977 ///
978 /// ```no_run
979 /// use sysinfo::{Pid, System};
980 ///
981 /// let s = System::new_all();
982 /// if let Some(process) = s.process(Pid::from(1337)) {
983 /// println!("{:?}", process.cwd());
984 /// }
985 /// ```
986 pub fn cwd(&self) -> Option<&Path> {
987 self.inner.cwd()
988 }
989
990 /// Returns the path of the root directory.
991 ///
992 /// ```no_run
993 /// use sysinfo::{Pid, System};
994 ///
995 /// let s = System::new_all();
996 /// if let Some(process) = s.process(Pid::from(1337)) {
997 /// println!("{:?}", process.root());
998 /// }
999 /// ```
1000 pub fn root(&self) -> Option<&Path> {
1001 self.inner.root()
1002 }
1003
1004 /// Returns the memory usage (in bytes).
1005 ///
1006 /// This method returns the [size of the resident set], that is, the amount of memory that the
1007 /// process allocated and which is currently mapped in physical RAM. It does not include memory
1008 /// that is swapped out, or, in some operating systems, that has been allocated but never used.
1009 ///
1010 /// Thus, it represents exactly the amount of physical RAM that the process is using at the
1011 /// present time, but it might not be a good indicator of the total memory that the process will
1012 /// be using over its lifetime. For that purpose, you can try and use
1013 /// [`virtual_memory`](Process::virtual_memory).
1014 ///
1015 /// ```no_run
1016 /// use sysinfo::{Pid, System};
1017 ///
1018 /// let s = System::new_all();
1019 /// if let Some(process) = s.process(Pid::from(1337)) {
1020 /// println!("{} bytes", process.memory());
1021 /// }
1022 /// ```
1023 ///
1024 /// [size of the resident set]: https://en.wikipedia.org/wiki/Resident_set_size
1025 pub fn memory(&self) -> u64 {
1026 self.inner.memory()
1027 }
1028
1029 /// Returns the virtual memory usage (in bytes).
1030 ///
1031 /// This method returns the [size of virtual memory], that is, the amount of memory that the
1032 /// process can access, whether it is currently mapped in physical RAM or not. It includes
1033 /// physical RAM, allocated but not used regions, swapped-out regions, and even memory
1034 /// associated with [memory-mapped files](https://en.wikipedia.org/wiki/Memory-mapped_file).
1035 ///
1036 /// This value has limitations though. Depending on the operating system and type of process,
1037 /// this value might be a good indicator of the total memory that the process will be using over
1038 /// its lifetime. However, for example, in the version 14 of MacOS this value is in the order of
1039 /// the hundreds of gigabytes for every process, and thus not very informative. Moreover, if a
1040 /// process maps into memory a very large file, this value will increase accordingly, even if
1041 /// the process is not actively using the memory.
1042 ///
1043 /// ```no_run
1044 /// use sysinfo::{Pid, System};
1045 ///
1046 /// let s = System::new_all();
1047 /// if let Some(process) = s.process(Pid::from(1337)) {
1048 /// println!("{} bytes", process.virtual_memory());
1049 /// }
1050 /// ```
1051 ///
1052 /// [size of virtual memory]: https://en.wikipedia.org/wiki/Virtual_memory
1053 pub fn virtual_memory(&self) -> u64 {
1054 self.inner.virtual_memory()
1055 }
1056
1057 /// Returns the parent PID.
1058 ///
1059 /// ```no_run
1060 /// use sysinfo::{Pid, System};
1061 ///
1062 /// let s = System::new_all();
1063 /// if let Some(process) = s.process(Pid::from(1337)) {
1064 /// println!("{:?}", process.parent());
1065 /// }
1066 /// ```
1067 pub fn parent(&self) -> Option<Pid> {
1068 self.inner.parent()
1069 }
1070
1071 /// Returns the status of the process.
1072 ///
1073 /// ```no_run
1074 /// use sysinfo::{Pid, System};
1075 ///
1076 /// let s = System::new_all();
1077 /// if let Some(process) = s.process(Pid::from(1337)) {
1078 /// println!("{:?}", process.status());
1079 /// }
1080 /// ```
1081 pub fn status(&self) -> ProcessStatus {
1082 self.inner.status()
1083 }
1084
1085 /// Returns the time where the process was started (in seconds) from epoch.
1086 ///
1087 /// ```no_run
1088 /// use sysinfo::{Pid, System};
1089 ///
1090 /// let s = System::new_all();
1091 /// if let Some(process) = s.process(Pid::from(1337)) {
1092 /// println!("Started at {} seconds", process.start_time());
1093 /// }
1094 /// ```
1095 pub fn start_time(&self) -> u64 {
1096 self.inner.start_time()
1097 }
1098
1099 /// Returns for how much time the process has been running (in seconds).
1100 ///
1101 /// ```no_run
1102 /// use sysinfo::{Pid, System};
1103 ///
1104 /// let s = System::new_all();
1105 /// if let Some(process) = s.process(Pid::from(1337)) {
1106 /// println!("Running since {} seconds", process.run_time());
1107 /// }
1108 /// ```
1109 pub fn run_time(&self) -> u64 {
1110 self.inner.run_time()
1111 }
1112
1113 /// Returns the total CPU usage (in %). Notice that it might be bigger than
1114 /// 100 if run on a multi-core machine.
1115 ///
1116 /// If you want a value between 0% and 100%, divide the returned value by
1117 /// the number of CPUs.
1118 ///
1119 /// ⚠️ To start to have accurate CPU usage, a process needs to be refreshed
1120 /// **twice** because CPU usage computation is based on time diff (process
1121 /// time on a given time period divided by total system time on the same
1122 /// time period).
1123 ///
1124 /// ⚠️ If you want accurate CPU usage number, better leave a bit of time
1125 /// between two calls of this method (take a look at
1126 /// [`MINIMUM_CPU_UPDATE_INTERVAL`][crate::MINIMUM_CPU_UPDATE_INTERVAL] for
1127 /// more information).
1128 ///
1129 /// ```no_run
1130 /// use sysinfo::{Pid, System};
1131 ///
1132 /// let s = System::new_all();
1133 /// if let Some(process) = s.process(Pid::from(1337)) {
1134 /// println!("{}%", process.cpu_usage());
1135 /// }
1136 /// ```
1137 pub fn cpu_usage(&self) -> f32 {
1138 self.inner.cpu_usage()
1139 }
1140
1141 /// Returns number of bytes read and written to disk.
1142 ///
1143 /// ⚠️ On Windows, this method actually returns **ALL** I/O read and
1144 /// written bytes.
1145 ///
1146 /// ```no_run
1147 /// use sysinfo::{Pid, System};
1148 ///
1149 /// let s = System::new_all();
1150 /// if let Some(process) = s.process(Pid::from(1337)) {
1151 /// let disk_usage = process.disk_usage();
1152 /// println!("read bytes : new/total => {}/{}",
1153 /// disk_usage.read_bytes,
1154 /// disk_usage.total_read_bytes,
1155 /// );
1156 /// println!("written bytes: new/total => {}/{}",
1157 /// disk_usage.written_bytes,
1158 /// disk_usage.total_written_bytes,
1159 /// );
1160 /// }
1161 /// ```
1162 pub fn disk_usage(&self) -> DiskUsage {
1163 self.inner.disk_usage()
1164 }
1165
1166 /// Returns the ID of the owner user of this process or `None` if this
1167 /// information couldn't be retrieved. If you want to get the [`User`] from
1168 /// it, take a look at [`Users::get_user_by_id`].
1169 ///
1170 /// [`User`]: crate::User
1171 /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1172 ///
1173 /// ```no_run
1174 /// use sysinfo::{Pid, System};
1175 ///
1176 /// let mut s = System::new_all();
1177 ///
1178 /// if let Some(process) = s.process(Pid::from(1337)) {
1179 /// println!("User id for process 1337: {:?}", process.user_id());
1180 /// }
1181 /// ```
1182 pub fn user_id(&self) -> Option<&Uid> {
1183 self.inner.user_id()
1184 }
1185
1186 /// Returns the user ID of the effective owner of this process or `None` if
1187 /// this information couldn't be retrieved. If you want to get the [`User`]
1188 /// from it, take a look at [`Users::get_user_by_id`].
1189 ///
1190 /// If you run something with `sudo`, the real user ID of the launched
1191 /// process will be the ID of the user you are logged in as but effective
1192 /// user ID will be `0` (i-e root).
1193 ///
1194 /// ⚠️ It always returns `None` on Windows.
1195 ///
1196 /// [`User`]: crate::User
1197 /// [`Users::get_user_by_id`]: crate::Users::get_user_by_id
1198 ///
1199 /// ```no_run
1200 /// use sysinfo::{Pid, System};
1201 ///
1202 /// let mut s = System::new_all();
1203 ///
1204 /// if let Some(process) = s.process(Pid::from(1337)) {
1205 /// println!("User id for process 1337: {:?}", process.effective_user_id());
1206 /// }
1207 /// ```
1208 pub fn effective_user_id(&self) -> Option<&Uid> {
1209 self.inner.effective_user_id()
1210 }
1211
1212 /// Returns the process group ID of the process.
1213 ///
1214 /// ⚠️ It always returns `None` on Windows.
1215 ///
1216 /// ```no_run
1217 /// use sysinfo::{Pid, System};
1218 ///
1219 /// let mut s = System::new_all();
1220 ///
1221 /// if let Some(process) = s.process(Pid::from(1337)) {
1222 /// println!("Group ID for process 1337: {:?}", process.group_id());
1223 /// }
1224 /// ```
1225 pub fn group_id(&self) -> Option<Gid> {
1226 self.inner.group_id()
1227 }
1228
1229 /// Returns the effective group ID of the process.
1230 ///
1231 /// If you run something with `sudo`, the real group ID of the launched
1232 /// process will be the primary group ID you are logged in as but effective
1233 /// group ID will be `0` (i-e root).
1234 ///
1235 /// ⚠️ It always returns `None` on Windows.
1236 ///
1237 /// ```no_run
1238 /// use sysinfo::{Pid, System};
1239 ///
1240 /// let mut s = System::new_all();
1241 ///
1242 /// if let Some(process) = s.process(Pid::from(1337)) {
1243 /// println!("User id for process 1337: {:?}", process.effective_group_id());
1244 /// }
1245 /// ```
1246 pub fn effective_group_id(&self) -> Option<Gid> {
1247 self.inner.effective_group_id()
1248 }
1249
1250 /// Wait for process termination.
1251 ///
1252 /// ```no_run
1253 /// use sysinfo::{Pid, System};
1254 ///
1255 /// let mut s = System::new_all();
1256 ///
1257 /// if let Some(process) = s.process(Pid::from(1337)) {
1258 /// println!("Waiting for pid 1337");
1259 /// process.wait();
1260 /// println!("Pid 1337 exited");
1261 /// }
1262 /// ```
1263 pub fn wait(&self) {
1264 self.inner.wait()
1265 }
1266
1267 /// Returns the session ID for the current process or `None` if it couldn't
1268 /// be retrieved.
1269 ///
1270 /// ⚠️ This information is computed every time this method is called.
1271 ///
1272 /// ```no_run
1273 /// use sysinfo::{Pid, System};
1274 ///
1275 /// let mut s = System::new_all();
1276 ///
1277 /// if let Some(process) = s.process(Pid::from(1337)) {
1278 /// println!("Session ID for process 1337: {:?}", process.session_id());
1279 /// }
1280 /// ```
1281 pub fn session_id(&self) -> Option<Pid> {
1282 self.inner.session_id()
1283 }
1284
1285 /// Tasks run by this process. If there are none, returns `None`.
1286 ///
1287 /// ⚠️ This method always returns `None` on other platforms than Linux.
1288 ///
1289 /// ```no_run
1290 /// use sysinfo::{Pid, System};
1291 ///
1292 /// let mut s = System::new_all();
1293 ///
1294 /// if let Some(process) = s.process(Pid::from(1337)) {
1295 /// if let Some(tasks) = process.tasks() {
1296 /// println!("Listing tasks for process {:?}", process.pid());
1297 /// for task_pid in tasks {
1298 /// if let Some(task) = s.process(*task_pid) {
1299 /// println!("Task {:?}: {:?}", task.pid(), task.name());
1300 /// }
1301 /// }
1302 /// }
1303 /// }
1304 /// ```
1305 pub fn tasks(&self) -> Option<&HashSet<Pid>> {
1306 cfg_if::cfg_if! {
1307 if #[cfg(all(
1308 any(target_os = "linux", target_os = "android"),
1309 not(feature = "unknown-ci")
1310 ))] {
1311 self.inner.tasks.as_ref()
1312 } else {
1313 None
1314 }
1315 }
1316 }
1317
1318 /// If the process is a thread, it'll return `Some` with the kind of thread it is. Returns
1319 /// `None` otherwise.
1320 ///
1321 /// ⚠️ This method always returns `None` on other platforms than Linux.
1322 ///
1323 /// ```no_run
1324 /// use sysinfo::System;
1325 ///
1326 /// let s = System::new_all();
1327 ///
1328 /// for (_, process) in s.processes() {
1329 /// if let Some(thread_kind) = process.thread_kind() {
1330 /// println!("Process {:?} is a {thread_kind:?} thread", process.pid());
1331 /// }
1332 /// }
1333 /// ```
1334 pub fn thread_kind(&self) -> Option<ThreadKind> {
1335 cfg_if::cfg_if! {
1336 if #[cfg(all(
1337 any(target_os = "linux", target_os = "android"),
1338 not(feature = "unknown-ci")
1339 ))] {
1340 self.inner.thread_kind()
1341 } else {
1342 None
1343 }
1344 }
1345 }
1346}
1347
1348macro_rules! pid_decl {
1349 ($typ:ty) => {
1350 #[doc = include_str!("../md_doc/pid.md")]
1351 #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
1352 #[repr(transparent)]
1353 pub struct Pid(pub(crate) $typ);
1354
1355 impl From<usize> for Pid {
1356 fn from(v: usize) -> Self {
1357 Self(v as _)
1358 }
1359 }
1360 impl From<Pid> for usize {
1361 fn from(v: Pid) -> Self {
1362 v.0 as _
1363 }
1364 }
1365 impl FromStr for Pid {
1366 type Err = <$typ as FromStr>::Err;
1367 fn from_str(s: &str) -> Result<Self, Self::Err> {
1368 Ok(Self(<$typ>::from_str(s)?))
1369 }
1370 }
1371 impl fmt::Display for Pid {
1372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1373 write!(f, "{}", self.0)
1374 }
1375 }
1376 impl Pid {
1377 /// Allows to convert [`Pid`][crate::Pid] into [`u32`].
1378 ///
1379 /// ```
1380 /// use sysinfo::Pid;
1381 ///
1382 /// let pid = Pid::from_u32(0);
1383 /// let value: u32 = pid.as_u32();
1384 /// ```
1385 pub fn as_u32(self) -> u32 {
1386 self.0 as _
1387 }
1388 /// Allows to convert a [`u32`] into [`Pid`][crate::Pid].
1389 ///
1390 /// ```
1391 /// use sysinfo::Pid;
1392 ///
1393 /// let pid = Pid::from_u32(0);
1394 /// ```
1395 pub fn from_u32(v: u32) -> Self {
1396 Self(v as _)
1397 }
1398 }
1399 };
1400}
1401
1402cfg_if::cfg_if! {
1403 if #[cfg(all(
1404 not(feature = "unknown-ci"),
1405 any(
1406 target_os = "freebsd",
1407 target_os = "linux",
1408 target_os = "android",
1409 target_os = "macos",
1410 target_os = "ios",
1411 )
1412 ))] {
1413 use libc::pid_t;
1414
1415 pid_decl!(pid_t);
1416 } else {
1417 pid_decl!(usize);
1418 }
1419}
1420
1421macro_rules! impl_get_set {
1422 ($ty_name:ident, $name:ident, $with:ident, $without:ident $(, $extra_doc:literal)? $(,)?) => {
1423 #[doc = concat!("Returns the value of the \"", stringify!($name), "\" refresh kind.")]
1424 $(#[doc = concat!("
1425", $extra_doc, "
1426")])?
1427 #[doc = concat!("
1428```
1429use sysinfo::", stringify!($ty_name), ";
1430
1431let r = ", stringify!($ty_name), "::new();
1432assert_eq!(r.", stringify!($name), "(), false);
1433
1434let r = r.with_", stringify!($name), "();
1435assert_eq!(r.", stringify!($name), "(), true);
1436
1437let r = r.without_", stringify!($name), "();
1438assert_eq!(r.", stringify!($name), "(), false);
1439```")]
1440 pub fn $name(&self) -> bool {
1441 self.$name
1442 }
1443
1444 #[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `true`.
1445
1446```
1447use sysinfo::", stringify!($ty_name), ";
1448
1449let r = ", stringify!($ty_name), "::new();
1450assert_eq!(r.", stringify!($name), "(), false);
1451
1452let r = r.with_", stringify!($name), "();
1453assert_eq!(r.", stringify!($name), "(), true);
1454```")]
1455 #[must_use]
1456 pub fn $with(mut self) -> Self {
1457 self.$name = true;
1458 self
1459 }
1460
1461 #[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `false`.
1462
1463```
1464use sysinfo::", stringify!($ty_name), ";
1465
1466let r = ", stringify!($ty_name), "::everything();
1467assert_eq!(r.", stringify!($name), "(), true);
1468
1469let r = r.without_", stringify!($name), "();
1470assert_eq!(r.", stringify!($name), "(), false);
1471```")]
1472 #[must_use]
1473 pub fn $without(mut self) -> Self {
1474 self.$name = false;
1475 self
1476 }
1477 };
1478
1479 // To handle `UpdateKind`.
1480 ($ty_name:ident, $name:ident, $with:ident, $without:ident, UpdateKind $(, $extra_doc:literal)? $(,)?) => {
1481 #[doc = concat!("Returns the value of the \"", stringify!($name), "\" refresh kind.")]
1482 $(#[doc = concat!("
1483", $extra_doc, "
1484")])?
1485 #[doc = concat!("
1486```
1487use sysinfo::{", stringify!($ty_name), ", UpdateKind};
1488
1489let r = ", stringify!($ty_name), "::new();
1490assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
1491
1492let r = r.with_", stringify!($name), "(UpdateKind::OnlyIfNotSet);
1493assert_eq!(r.", stringify!($name), "(), UpdateKind::OnlyIfNotSet);
1494
1495let r = r.without_", stringify!($name), "();
1496assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
1497```")]
1498 pub fn $name(&self) -> UpdateKind {
1499 self.$name
1500 }
1501
1502 #[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind.
1503
1504```
1505use sysinfo::{", stringify!($ty_name), ", UpdateKind};
1506
1507let r = ", stringify!($ty_name), "::new();
1508assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
1509
1510let r = r.with_", stringify!($name), "(UpdateKind::OnlyIfNotSet);
1511assert_eq!(r.", stringify!($name), "(), UpdateKind::OnlyIfNotSet);
1512```")]
1513 #[must_use]
1514 pub fn $with(mut self, kind: UpdateKind) -> Self {
1515 self.$name = kind;
1516 self
1517 }
1518
1519 #[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `UpdateKind::Never`.
1520
1521```
1522use sysinfo::{", stringify!($ty_name), ", UpdateKind};
1523
1524let r = ", stringify!($ty_name), "::everything();
1525assert_eq!(r.", stringify!($name), "(), UpdateKind::OnlyIfNotSet);
1526
1527let r = r.without_", stringify!($name), "();
1528assert_eq!(r.", stringify!($name), "(), UpdateKind::Never);
1529```")]
1530 #[must_use]
1531 pub fn $without(mut self) -> Self {
1532 self.$name = UpdateKind::Never;
1533 self
1534 }
1535 };
1536
1537 // To handle `*RefreshKind`.
1538 ($ty_name:ident, $name:ident, $with:ident, $without:ident, $typ:ty $(,)?) => {
1539 #[doc = concat!("Returns the value of the \"", stringify!($name), "\" refresh kind.
1540
1541```
1542use sysinfo::{", stringify!($ty_name), ", ", stringify!($typ), "};
1543
1544let r = ", stringify!($ty_name), "::new();
1545assert_eq!(r.", stringify!($name), "().is_some(), false);
1546
1547let r = r.with_", stringify!($name), "(", stringify!($typ), "::everything());
1548assert_eq!(r.", stringify!($name), "().is_some(), true);
1549
1550let r = r.without_", stringify!($name), "();
1551assert_eq!(r.", stringify!($name), "().is_some(), false);
1552```")]
1553 pub fn $name(&self) -> Option<$typ> {
1554 self.$name
1555 }
1556
1557 #[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `Some(...)`.
1558
1559```
1560use sysinfo::{", stringify!($ty_name), ", ", stringify!($typ), "};
1561
1562let r = ", stringify!($ty_name), "::new();
1563assert_eq!(r.", stringify!($name), "().is_some(), false);
1564
1565let r = r.with_", stringify!($name), "(", stringify!($typ), "::everything());
1566assert_eq!(r.", stringify!($name), "().is_some(), true);
1567```")]
1568 #[must_use]
1569 pub fn $with(mut self, kind: $typ) -> Self {
1570 self.$name = Some(kind);
1571 self
1572 }
1573
1574 #[doc = concat!("Sets the value of the \"", stringify!($name), "\" refresh kind to `None`.
1575
1576```
1577use sysinfo::", stringify!($ty_name), ";
1578
1579let r = ", stringify!($ty_name), "::everything();
1580assert_eq!(r.", stringify!($name), "().is_some(), true);
1581
1582let r = r.without_", stringify!($name), "();
1583assert_eq!(r.", stringify!($name), "().is_some(), false);
1584```")]
1585 #[must_use]
1586 pub fn $without(mut self) -> Self {
1587 self.$name = None;
1588 self
1589 }
1590 };
1591}
1592
1593/// This enum allows you to specify when you want the related information to be updated.
1594///
1595/// For example if you only want the [`Process::exe()`] information to be refreshed only if it's not
1596/// already set:
1597///
1598/// ```no_run
1599/// use sysinfo::{ProcessRefreshKind, System, UpdateKind};
1600///
1601/// let mut system = System::new();
1602/// system.refresh_processes_specifics(
1603/// ProcessRefreshKind::new().with_exe(UpdateKind::OnlyIfNotSet),
1604/// );
1605/// ```
1606#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1607pub enum UpdateKind {
1608 /// Never update the related information.
1609 #[default]
1610 Never,
1611 /// Always update the related information.
1612 Always,
1613 /// Only update the related information if it was not already set at least once.
1614 OnlyIfNotSet,
1615}
1616
1617impl UpdateKind {
1618 /// If `self` is `OnlyIfNotSet`, `f` is called and its returned value is returned.
1619 #[allow(dead_code)] // Needed for unsupported targets.
1620 pub(crate) fn needs_update(self, f: impl Fn() -> bool) -> bool {
1621 match self {
1622 Self::Never => false,
1623 Self::Always => true,
1624 Self::OnlyIfNotSet => f(),
1625 }
1626 }
1627}
1628
1629/// Used to determine what you want to refresh specifically on the [`Process`] type.
1630///
1631/// When all refresh are ruled out, a [`Process`] will still retrieve the following information:
1632/// * Process ID ([`Pid`])
1633/// * Parent process ID (on Windows it never changes though)
1634/// * Process name
1635/// * Start time
1636///
1637/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
1638/// the information won't be retrieved if the information is accessible without needing
1639/// extra computation.
1640///
1641/// ```
1642/// use sysinfo::{ProcessRefreshKind, System};
1643///
1644/// let mut system = System::new();
1645///
1646/// // We don't want to update the CPU information.
1647/// system.refresh_processes_specifics(ProcessRefreshKind::everything().without_cpu());
1648///
1649/// for (_, proc_) in system.processes() {
1650/// // We use a `==` comparison on float only because we know it's set to 0 here.
1651/// assert_eq!(proc_.cpu_usage(), 0.);
1652/// }
1653/// ```
1654///
1655/// [`Process`]: crate::Process
1656#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1657pub struct ProcessRefreshKind {
1658 cpu: bool,
1659 disk_usage: bool,
1660 memory: bool,
1661 user: UpdateKind,
1662 cwd: UpdateKind,
1663 root: UpdateKind,
1664 environ: UpdateKind,
1665 cmd: UpdateKind,
1666 exe: UpdateKind,
1667}
1668
1669impl ProcessRefreshKind {
1670 /// Creates a new `ProcessRefreshKind` with every refresh set to `false`.
1671 ///
1672 /// ```
1673 /// use sysinfo::{ProcessRefreshKind, UpdateKind};
1674 ///
1675 /// let r = ProcessRefreshKind::new();
1676 ///
1677 /// assert_eq!(r.cpu(), false);
1678 /// assert_eq!(r.user(), UpdateKind::Never);
1679 /// ```
1680 pub fn new() -> Self {
1681 Self::default()
1682 }
1683
1684 /// Creates a new `ProcessRefreshKind` with every refresh set to `true` or
1685 /// [`UpdateKind::OnlyIfNotSet`].
1686 ///
1687 /// ```
1688 /// use sysinfo::{ProcessRefreshKind, UpdateKind};
1689 ///
1690 /// let r = ProcessRefreshKind::everything();
1691 ///
1692 /// assert_eq!(r.cpu(), true);
1693 /// assert_eq!(r.user(), UpdateKind::OnlyIfNotSet);
1694 /// ```
1695 pub fn everything() -> Self {
1696 Self {
1697 cpu: true,
1698 disk_usage: true,
1699 memory: true,
1700 user: UpdateKind::OnlyIfNotSet,
1701 cwd: UpdateKind::OnlyIfNotSet,
1702 root: UpdateKind::OnlyIfNotSet,
1703 environ: UpdateKind::OnlyIfNotSet,
1704 cmd: UpdateKind::OnlyIfNotSet,
1705 exe: UpdateKind::OnlyIfNotSet,
1706 }
1707 }
1708
1709 impl_get_set!(ProcessRefreshKind, cpu, with_cpu, without_cpu);
1710 impl_get_set!(
1711 ProcessRefreshKind,
1712 disk_usage,
1713 with_disk_usage,
1714 without_disk_usage
1715 );
1716 impl_get_set!(
1717 ProcessRefreshKind,
1718 user,
1719 with_user,
1720 without_user,
1721 UpdateKind,
1722 "\
1723It will retrieve the following information:
1724
1725 * user ID
1726 * user effective ID (if available on the platform)
1727 * user group ID (if available on the platform)
1728 * user effective ID (if available on the platform)"
1729 );
1730 impl_get_set!(ProcessRefreshKind, memory, with_memory, without_memory);
1731 impl_get_set!(ProcessRefreshKind, cwd, with_cwd, without_cwd, UpdateKind);
1732 impl_get_set!(
1733 ProcessRefreshKind,
1734 root,
1735 with_root,
1736 without_root,
1737 UpdateKind
1738 );
1739 impl_get_set!(
1740 ProcessRefreshKind,
1741 environ,
1742 with_environ,
1743 without_environ,
1744 UpdateKind
1745 );
1746 impl_get_set!(ProcessRefreshKind, cmd, with_cmd, without_cmd, UpdateKind);
1747 impl_get_set!(ProcessRefreshKind, exe, with_exe, without_exe, UpdateKind);
1748}
1749
1750/// Used to determine what you want to refresh specifically on the [`Cpu`] type.
1751///
1752/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
1753/// the information won't be retrieved if the information is accessible without needing
1754/// extra computation.
1755///
1756/// ```
1757/// use sysinfo::{CpuRefreshKind, System};
1758///
1759/// let mut system = System::new();
1760///
1761/// // We don't want to update all the CPU information.
1762/// system.refresh_cpu_specifics(CpuRefreshKind::everything().without_frequency());
1763///
1764/// for cpu in system.cpus() {
1765/// assert_eq!(cpu.frequency(), 0);
1766/// }
1767/// ```
1768///
1769/// [`Cpu`]: crate::Cpu
1770#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1771pub struct CpuRefreshKind {
1772 cpu_usage: bool,
1773 frequency: bool,
1774}
1775
1776impl CpuRefreshKind {
1777 /// Creates a new `CpuRefreshKind` with every refresh set to `false`.
1778 ///
1779 /// ```
1780 /// use sysinfo::CpuRefreshKind;
1781 ///
1782 /// let r = CpuRefreshKind::new();
1783 ///
1784 /// assert_eq!(r.frequency(), false);
1785 /// assert_eq!(r.cpu_usage(), false);
1786 /// ```
1787 pub fn new() -> Self {
1788 Self::default()
1789 }
1790
1791 /// Creates a new `CpuRefreshKind` with every refresh set to `true`.
1792 ///
1793 /// ```
1794 /// use sysinfo::CpuRefreshKind;
1795 ///
1796 /// let r = CpuRefreshKind::everything();
1797 ///
1798 /// assert_eq!(r.frequency(), true);
1799 /// assert_eq!(r.cpu_usage(), true);
1800 /// ```
1801 pub fn everything() -> Self {
1802 Self {
1803 cpu_usage: true,
1804 frequency: true,
1805 }
1806 }
1807
1808 impl_get_set!(CpuRefreshKind, cpu_usage, with_cpu_usage, without_cpu_usage);
1809 impl_get_set!(CpuRefreshKind, frequency, with_frequency, without_frequency);
1810}
1811
1812/// Used to determine which memory you want to refresh specifically.
1813///
1814/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
1815/// the information won't be retrieved if the information is accessible without needing
1816/// extra computation.
1817///
1818/// ```
1819/// use sysinfo::{MemoryRefreshKind, System};
1820///
1821/// let mut system = System::new();
1822///
1823/// // We don't want to update all memories information.
1824/// system.refresh_memory_specifics(MemoryRefreshKind::new().with_ram());
1825///
1826/// println!("total RAM: {}", system.total_memory());
1827/// println!("free RAM: {}", system.free_memory());
1828/// ```
1829#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1830pub struct MemoryRefreshKind {
1831 ram: bool,
1832 swap: bool,
1833}
1834
1835impl MemoryRefreshKind {
1836 /// Creates a new `MemoryRefreshKind` with every refresh set to `false`.
1837 ///
1838 /// ```
1839 /// use sysinfo::MemoryRefreshKind;
1840 ///
1841 /// let r = MemoryRefreshKind::new();
1842 ///
1843 /// assert_eq!(r.ram(), false);
1844 /// assert_eq!(r.swap(), false);
1845 /// ```
1846 pub fn new() -> Self {
1847 Self::default()
1848 }
1849
1850 /// Creates a new `MemoryRefreshKind` with every refresh set to `true`.
1851 ///
1852 /// ```
1853 /// use sysinfo::MemoryRefreshKind;
1854 ///
1855 /// let r = MemoryRefreshKind::everything();
1856 ///
1857 /// assert_eq!(r.ram(), true);
1858 /// assert_eq!(r.swap(), true);
1859 /// ```
1860 pub fn everything() -> Self {
1861 Self {
1862 ram: true,
1863 swap: true,
1864 }
1865 }
1866
1867 impl_get_set!(MemoryRefreshKind, ram, with_ram, without_ram);
1868 impl_get_set!(MemoryRefreshKind, swap, with_swap, without_swap);
1869}
1870
1871/// Used to determine what you want to refresh specifically on the [`System`][crate::System] type.
1872///
1873/// ⚠️ Just like all other refresh types, ruling out a refresh doesn't assure you that
1874/// the information won't be retrieved if the information is accessible without needing
1875/// extra computation.
1876///
1877/// ```
1878/// use sysinfo::{RefreshKind, System};
1879///
1880/// // We want everything except memory.
1881/// let mut system = System::new_with_specifics(RefreshKind::everything().without_memory());
1882///
1883/// assert_eq!(system.total_memory(), 0);
1884/// # if sysinfo::IS_SUPPORTED_SYSTEM && !cfg!(feature = "apple-sandbox") {
1885/// assert!(system.processes().len() > 0);
1886/// # }
1887/// ```
1888#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
1889pub struct RefreshKind {
1890 processes: Option<ProcessRefreshKind>,
1891 memory: Option<MemoryRefreshKind>,
1892 cpu: Option<CpuRefreshKind>,
1893}
1894
1895impl RefreshKind {
1896 /// Creates a new `RefreshKind` with every refresh set to `false`/`None`.
1897 ///
1898 /// ```
1899 /// use sysinfo::RefreshKind;
1900 ///
1901 /// let r = RefreshKind::new();
1902 ///
1903 /// assert_eq!(r.processes().is_some(), false);
1904 /// assert_eq!(r.memory().is_some(), false);
1905 /// assert_eq!(r.cpu().is_some(), false);
1906 /// ```
1907 pub fn new() -> Self {
1908 Self::default()
1909 }
1910
1911 /// Creates a new `RefreshKind` with every refresh set to `true`/`Some(...)`.
1912 ///
1913 /// ```
1914 /// use sysinfo::RefreshKind;
1915 ///
1916 /// let r = RefreshKind::everything();
1917 ///
1918 /// assert_eq!(r.processes().is_some(), true);
1919 /// assert_eq!(r.memory().is_some(), true);
1920 /// assert_eq!(r.cpu().is_some(), true);
1921 /// ```
1922 pub fn everything() -> Self {
1923 Self {
1924 processes: Some(ProcessRefreshKind::everything()),
1925 memory: Some(MemoryRefreshKind::everything()),
1926 cpu: Some(CpuRefreshKind::everything()),
1927 }
1928 }
1929
1930 impl_get_set!(
1931 RefreshKind,
1932 processes,
1933 with_processes,
1934 without_processes,
1935 ProcessRefreshKind
1936 );
1937 impl_get_set!(
1938 RefreshKind,
1939 memory,
1940 with_memory,
1941 without_memory,
1942 MemoryRefreshKind
1943 );
1944 impl_get_set!(RefreshKind, cpu, with_cpu, without_cpu, CpuRefreshKind);
1945}
1946
1947/// Interacting with network interfaces.
1948///
1949/// ```no_run
1950/// use sysinfo::Networks;
1951///
1952/// let networks = Networks::new_with_refreshed_list();
1953/// for (interface_name, network) in &networks {
1954/// println!("[{interface_name}]: {network:?}");
1955/// }
1956/// ```
1957pub struct Networks {
1958 pub(crate) inner: NetworksInner,
1959}
1960
1961impl<'a> IntoIterator for &'a Networks {
1962 type Item = (&'a String, &'a NetworkData);
1963 type IntoIter = std::collections::hash_map::Iter<'a, String, NetworkData>;
1964
1965 fn into_iter(self) -> Self::IntoIter {
1966 self.iter()
1967 }
1968}
1969
1970impl Default for Networks {
1971 fn default() -> Self {
1972 Networks::new()
1973 }
1974}
1975
1976impl Networks {
1977 /// Creates a new empty [`Networks`][crate::Networks] type.
1978 ///
1979 /// If you want it to be filled directly, take a look at [`Networks::new_with_refreshed_list`].
1980 ///
1981 /// ```no_run
1982 /// use sysinfo::Networks;
1983 ///
1984 /// let mut networks = Networks::new();
1985 /// networks.refresh_list();
1986 /// for (interface_name, network) in &networks {
1987 /// println!("[{interface_name}]: {network:?}");
1988 /// }
1989 /// ```
1990 pub fn new() -> Self {
1991 Self {
1992 inner: NetworksInner::new(),
1993 }
1994 }
1995
1996 /// Creates a new [`Networks`][crate::Networks] type with the disk list
1997 /// loaded. It is a combination of [`Networks::new`] and
1998 /// [`Networks::refresh_list`].
1999 ///
2000 /// ```no_run
2001 /// use sysinfo::Networks;
2002 ///
2003 /// let networks = Networks::new_with_refreshed_list();
2004 /// for network in &networks {
2005 /// println!("{network:?}");
2006 /// }
2007 /// ```
2008 pub fn new_with_refreshed_list() -> Self {
2009 let mut networks = Self::new();
2010 networks.refresh_list();
2011 networks
2012 }
2013
2014 /// Returns the network interfaces map.
2015 ///
2016 /// ```no_run
2017 /// use sysinfo::Networks;
2018 ///
2019 /// let networks = Networks::new_with_refreshed_list();
2020 /// for network in networks.list() {
2021 /// println!("{network:?}");
2022 /// }
2023 /// ```
2024 pub fn list(&self) -> &HashMap<String, NetworkData> {
2025 self.inner.list()
2026 }
2027
2028 /// Refreshes the network interfaces list.
2029 ///
2030 /// ```no_run
2031 /// use sysinfo::Networks;
2032 ///
2033 /// let mut networks = Networks::new();
2034 /// networks.refresh_list();
2035 /// ```
2036 pub fn refresh_list(&mut self) {
2037 self.inner.refresh_list()
2038 }
2039
2040 /// Refreshes the network interfaces' content. If you didn't run [`Networks::refresh_list`]
2041 /// before, calling this method won't do anything as no interfaces are present.
2042 ///
2043 /// ⚠️ If a network interface is added or removed, this method won't take it into account. Use
2044 /// [`Networks::refresh_list`] instead.
2045 ///
2046 /// ⚠️ If you didn't call [`Networks::refresh_list`] beforehand, this method will do nothing
2047 /// as the network list will be empty.
2048 ///
2049 /// ```no_run
2050 /// use sysinfo::Networks;
2051 ///
2052 /// let mut networks = Networks::new_with_refreshed_list();
2053 /// // Wait some time...? Then refresh the data of each network.
2054 /// networks.refresh();
2055 /// ```
2056 pub fn refresh(&mut self) {
2057 self.inner.refresh()
2058 }
2059}
2060
2061impl std::ops::Deref for Networks {
2062 type Target = HashMap<String, NetworkData>;
2063
2064 fn deref(&self) -> &Self::Target {
2065 self.list()
2066 }
2067}
2068
2069/// Getting volume of received and transmitted data.
2070///
2071/// ```no_run
2072/// use sysinfo::Networks;
2073///
2074/// let networks = Networks::new_with_refreshed_list();
2075/// for (interface_name, network) in &networks {
2076/// println!("[{interface_name}] {network:?}");
2077/// }
2078/// ```
2079pub struct NetworkData {
2080 pub(crate) inner: NetworkDataInner,
2081}
2082
2083impl NetworkData {
2084 /// Returns the number of received bytes since the last refresh.
2085 ///
2086 /// If you want the total number of bytes received, take a look at the
2087 /// [`total_received`](NetworkData::total_received) method.
2088 ///
2089 /// ```no_run
2090 /// use sysinfo::Networks;
2091 /// use std::{thread, time};
2092 ///
2093 /// let mut networks = Networks::new_with_refreshed_list();
2094 /// // Waiting a bit to get data from network...
2095 /// thread::sleep(time::Duration::from_millis(10));
2096 /// // Refreshing again to generate diff.
2097 /// networks.refresh();
2098 ///
2099 /// for (interface_name, network) in &networks {
2100 /// println!("in: {} B", network.received());
2101 /// }
2102 /// ```
2103 pub fn received(&self) -> u64 {
2104 self.inner.received()
2105 }
2106
2107 /// Returns the total number of received bytes.
2108 ///
2109 /// If you want the amount of received bytes since the last refresh, take a look at the
2110 /// [`received`](NetworkData::received) method.
2111 ///
2112 /// ```no_run
2113 /// use sysinfo::Networks;
2114 ///
2115 /// let networks = Networks::new_with_refreshed_list();
2116 /// for (interface_name, network) in &networks {
2117 /// println!("in: {} B", network.total_received());
2118 /// }
2119 /// ```
2120 pub fn total_received(&self) -> u64 {
2121 self.inner.total_received()
2122 }
2123
2124 /// Returns the number of transmitted bytes since the last refresh.
2125 ///
2126 /// If you want the total number of bytes transmitted, take a look at the
2127 /// [`total_transmitted`](NetworkData::total_transmitted) method.
2128 ///
2129 /// ```no_run
2130 /// use sysinfo::Networks;
2131 /// use std::{thread, time};
2132 ///
2133 /// let mut networks = Networks::new_with_refreshed_list();
2134 /// // Waiting a bit to get data from network...
2135 /// thread::sleep(time::Duration::from_millis(10));
2136 /// // Refreshing again to generate diff.
2137 /// networks.refresh();
2138 ///
2139 /// for (interface_name, network) in &networks {
2140 /// println!("out: {} B", network.transmitted());
2141 /// }
2142 /// ```
2143 pub fn transmitted(&self) -> u64 {
2144 self.inner.transmitted()
2145 }
2146
2147 /// Returns the total number of transmitted bytes.
2148 ///
2149 /// If you want the amount of transmitted bytes since the last refresh, take a look at the
2150 /// [`transmitted`](NetworkData::transmitted) method.
2151 ///
2152 /// ```no_run
2153 /// use sysinfo::Networks;
2154 ///
2155 /// let networks = Networks::new_with_refreshed_list();
2156 /// for (interface_name, network) in &networks {
2157 /// println!("out: {} B", network.total_transmitted());
2158 /// }
2159 /// ```
2160 pub fn total_transmitted(&self) -> u64 {
2161 self.inner.total_transmitted()
2162 }
2163
2164 /// Returns the number of incoming packets since the last refresh.
2165 ///
2166 /// If you want the total number of packets received, take a look at the
2167 /// [`total_packets_received`](NetworkData::total_packets_received) method.
2168 ///
2169 /// ```no_run
2170 /// use sysinfo::Networks;
2171 /// use std::{thread, time};
2172 ///
2173 /// let mut networks = Networks::new_with_refreshed_list();
2174 /// // Waiting a bit to get data from network...
2175 /// thread::sleep(time::Duration::from_millis(10));
2176 /// // Refreshing again to generate diff.
2177 /// networks.refresh();
2178 ///
2179 /// for (interface_name, network) in &networks {
2180 /// println!("in: {}", network.packets_received());
2181 /// }
2182 /// ```
2183 pub fn packets_received(&self) -> u64 {
2184 self.inner.packets_received()
2185 }
2186
2187 /// Returns the total number of incoming packets.
2188 ///
2189 /// If you want the amount of received packets since the last refresh, take a look at the
2190 /// [`packets_received`](NetworkData::packets_received) method.
2191 ///
2192 /// ```no_run
2193 /// use sysinfo::Networks;
2194 ///
2195 /// let networks = Networks::new_with_refreshed_list();
2196 /// for (interface_name, network) in &networks {
2197 /// println!("in: {}", network.total_packets_received());
2198 /// }
2199 /// ```
2200 pub fn total_packets_received(&self) -> u64 {
2201 self.inner.total_packets_received()
2202 }
2203
2204 /// Returns the number of outcoming packets since the last refresh.
2205 ///
2206 /// If you want the total number of packets transmitted, take a look at the
2207 /// [`total_packets_transmitted`](NetworkData::total_packets_transmitted) method.
2208 ///
2209 /// ```no_run
2210 /// use sysinfo::Networks;
2211 /// use std::{thread, time};
2212 ///
2213 /// let mut networks = Networks::new_with_refreshed_list();
2214 /// // Waiting a bit to get data from network...
2215 /// thread::sleep(time::Duration::from_millis(10));
2216 /// // Refreshing again to generate diff.
2217 /// networks.refresh();
2218 ///
2219 /// for (interface_name, network) in &networks {
2220 /// println!("out: {}", network.packets_transmitted());
2221 /// }
2222 /// ```
2223 pub fn packets_transmitted(&self) -> u64 {
2224 self.inner.packets_transmitted()
2225 }
2226
2227 /// Returns the total number of outcoming packets.
2228 ///
2229 /// If you want the amount of transmitted packets since the last refresh, take a look at the
2230 /// [`packets_transmitted`](NetworkData::packets_transmitted) method.
2231 ///
2232 /// ```no_run
2233 /// use sysinfo::Networks;
2234 ///
2235 /// let networks = Networks::new_with_refreshed_list();
2236 /// for (interface_name, network) in &networks {
2237 /// println!("out: {}", network.total_packets_transmitted());
2238 /// }
2239 /// ```
2240 pub fn total_packets_transmitted(&self) -> u64 {
2241 self.inner.total_packets_transmitted()
2242 }
2243
2244 /// Returns the number of incoming errors since the last refresh.
2245 ///
2246 /// If you want the total number of errors on received packets, take a look at the
2247 /// [`total_errors_on_received`](NetworkData::total_errors_on_received) method.
2248 ///
2249 /// ```no_run
2250 /// use sysinfo::Networks;
2251 /// use std::{thread, time};
2252 ///
2253 /// let mut networks = Networks::new_with_refreshed_list();
2254 /// // Waiting a bit to get data from network...
2255 /// thread::sleep(time::Duration::from_millis(10));
2256 /// // Refreshing again to generate diff.
2257 /// networks.refresh();
2258 ///
2259 /// for (interface_name, network) in &networks {
2260 /// println!("in: {}", network.errors_on_received());
2261 /// }
2262 /// ```
2263 pub fn errors_on_received(&self) -> u64 {
2264 self.inner.errors_on_received()
2265 }
2266
2267 /// Returns the total number of incoming errors.
2268 ///
2269 /// If you want the amount of errors on received packets since the last refresh, take a look at
2270 /// the [`errors_on_received`](NetworkData::errors_on_received) method.
2271 ///
2272 /// ```no_run
2273 /// use sysinfo::Networks;
2274 ///
2275 /// let networks = Networks::new_with_refreshed_list();
2276 /// for (interface_name, network) in &networks {
2277 /// println!("in: {}", network.total_errors_on_received());
2278 /// }
2279 /// ```
2280 pub fn total_errors_on_received(&self) -> u64 {
2281 self.inner.total_errors_on_received()
2282 }
2283
2284 /// Returns the number of outcoming errors since the last refresh.
2285 ///
2286 /// If you want the total number of errors on transmitted packets, take a look at the
2287 /// [`total_errors_on_transmitted`](NetworkData::total_errors_on_transmitted) method.
2288 ///
2289 /// ```no_run
2290 /// use sysinfo::Networks;
2291 /// use std::{thread, time};
2292 ///
2293 /// let mut networks = Networks::new_with_refreshed_list();
2294 /// // Waiting a bit to get data from network...
2295 /// thread::sleep(time::Duration::from_millis(10));
2296 /// // Refreshing again to generate diff.
2297 /// networks.refresh();
2298 ///
2299 /// for (interface_name, network) in &networks {
2300 /// println!("out: {}", network.errors_on_transmitted());
2301 /// }
2302 /// ```
2303 pub fn errors_on_transmitted(&self) -> u64 {
2304 self.inner.errors_on_transmitted()
2305 }
2306
2307 /// Returns the total number of outcoming errors.
2308 ///
2309 /// If you want the amount of errors on transmitted packets since the last refresh, take a look at
2310 /// the [`errors_on_transmitted`](NetworkData::errors_on_transmitted) method.
2311 ///
2312 /// ```no_run
2313 /// use sysinfo::Networks;
2314 ///
2315 /// let networks = Networks::new_with_refreshed_list();
2316 /// for (interface_name, network) in &networks {
2317 /// println!("out: {}", network.total_errors_on_transmitted());
2318 /// }
2319 /// ```
2320 pub fn total_errors_on_transmitted(&self) -> u64 {
2321 self.inner.total_errors_on_transmitted()
2322 }
2323
2324 /// Returns the MAC address associated to current interface.
2325 ///
2326 /// ```no_run
2327 /// use sysinfo::Networks;
2328 ///
2329 /// let mut networks = Networks::new_with_refreshed_list();
2330 /// for (interface_name, network) in &networks {
2331 /// println!("MAC address: {}", network.mac_address());
2332 /// }
2333 /// ```
2334 pub fn mac_address(&self) -> MacAddr {
2335 self.inner.mac_address()
2336 }
2337}
2338
2339/// Struct containing a disk information.
2340///
2341/// ```no_run
2342/// use sysinfo::Disks;
2343///
2344/// let disks = Disks::new_with_refreshed_list();
2345/// for disk in disks.list() {
2346/// println!("{:?}: {:?}", disk.name(), disk.kind());
2347/// }
2348/// ```
2349pub struct Disk {
2350 pub(crate) inner: crate::DiskInner,
2351}
2352
2353impl Disk {
2354 /// Returns the kind of disk.
2355 ///
2356 /// ```no_run
2357 /// use sysinfo::Disks;
2358 ///
2359 /// let disks = Disks::new_with_refreshed_list();
2360 /// for disk in disks.list() {
2361 /// println!("[{:?}] {:?}", disk.name(), disk.kind());
2362 /// }
2363 /// ```
2364 pub fn kind(&self) -> DiskKind {
2365 self.inner.kind()
2366 }
2367
2368 /// Returns the disk name.
2369 ///
2370 /// ```no_run
2371 /// use sysinfo::Disks;
2372 ///
2373 /// let disks = Disks::new_with_refreshed_list();
2374 /// for disk in disks.list() {
2375 /// println!("{:?}", disk.name());
2376 /// }
2377 /// ```
2378 pub fn name(&self) -> &OsStr {
2379 self.inner.name()
2380 }
2381
2382 /// Returns the file system used on this disk (so for example: `EXT4`, `NTFS`, etc...).
2383 ///
2384 /// ```no_run
2385 /// use sysinfo::Disks;
2386 ///
2387 /// let disks = Disks::new_with_refreshed_list();
2388 /// for disk in disks.list() {
2389 /// println!("[{:?}] {:?}", disk.name(), disk.file_system());
2390 /// }
2391 /// ```
2392 pub fn file_system(&self) -> &OsStr {
2393 self.inner.file_system()
2394 }
2395
2396 /// Returns the mount point of the disk (`/` for example).
2397 ///
2398 /// ```no_run
2399 /// use sysinfo::Disks;
2400 ///
2401 /// let disks = Disks::new_with_refreshed_list();
2402 /// for disk in disks.list() {
2403 /// println!("[{:?}] {:?}", disk.name(), disk.mount_point());
2404 /// }
2405 /// ```
2406 pub fn mount_point(&self) -> &Path {
2407 self.inner.mount_point()
2408 }
2409
2410 /// Returns the total disk size, in bytes.
2411 ///
2412 /// ```no_run
2413 /// use sysinfo::Disks;
2414 ///
2415 /// let disks = Disks::new_with_refreshed_list();
2416 /// for disk in disks.list() {
2417 /// println!("[{:?}] {}B", disk.name(), disk.total_space());
2418 /// }
2419 /// ```
2420 pub fn total_space(&self) -> u64 {
2421 self.inner.total_space()
2422 }
2423
2424 /// Returns the available disk size, in bytes.
2425 ///
2426 /// ```no_run
2427 /// use sysinfo::Disks;
2428 ///
2429 /// let disks = Disks::new_with_refreshed_list();
2430 /// for disk in disks.list() {
2431 /// println!("[{:?}] {}B", disk.name(), disk.available_space());
2432 /// }
2433 /// ```
2434 pub fn available_space(&self) -> u64 {
2435 self.inner.available_space()
2436 }
2437
2438 /// Returns `true` if the disk is removable.
2439 ///
2440 /// ```no_run
2441 /// use sysinfo::Disks;
2442 ///
2443 /// let disks = Disks::new_with_refreshed_list();
2444 /// for disk in disks.list() {
2445 /// println!("[{:?}] {}", disk.name(), disk.is_removable());
2446 /// }
2447 /// ```
2448 pub fn is_removable(&self) -> bool {
2449 self.inner.is_removable()
2450 }
2451
2452 /// Updates the disk' information.
2453 ///
2454 /// ```no_run
2455 /// use sysinfo::Disks;
2456 ///
2457 /// let mut disks = Disks::new_with_refreshed_list();
2458 /// for disk in disks.list_mut() {
2459 /// disk.refresh();
2460 /// }
2461 /// ```
2462 pub fn refresh(&mut self) -> bool {
2463 self.inner.refresh()
2464 }
2465}
2466
2467/// Disks interface.
2468///
2469/// ```no_run
2470/// use sysinfo::Disks;
2471///
2472/// let disks = Disks::new_with_refreshed_list();
2473/// for disk in disks.list() {
2474/// println!("{disk:?}");
2475/// }
2476/// ```
2477///
2478/// ⚠️ Note that tmpfs mounts are excluded by default under Linux.
2479/// To display tmpfs mount points, the `linux-tmpfs` feature must be enabled.
2480///
2481/// ⚠️ Note that network devices are excluded by default under Linux.
2482/// To display mount points using the CIFS and NFS protocols, the `linux-netdevs`
2483/// feature must be enabled. Note, however, that sysinfo may hang under certain
2484/// circumstances. For example, if a CIFS or NFS share has been mounted with
2485/// the _hard_ option, but the connection has an error, such as the share server has stopped.
2486pub struct Disks {
2487 inner: crate::DisksInner,
2488}
2489
2490impl Default for Disks {
2491 fn default() -> Self {
2492 Self::new()
2493 }
2494}
2495
2496impl From<Disks> for Vec<Disk> {
2497 fn from(disks: Disks) -> Vec<Disk> {
2498 disks.inner.into_vec()
2499 }
2500}
2501
2502impl From<Vec<Disk>> for Disks {
2503 fn from(disks: Vec<Disk>) -> Self {
2504 Self {
2505 inner: crate::DisksInner::from_vec(disks),
2506 }
2507 }
2508}
2509
2510impl<'a> IntoIterator for &'a Disks {
2511 type Item = &'a Disk;
2512 type IntoIter = std::slice::Iter<'a, Disk>;
2513
2514 fn into_iter(self) -> Self::IntoIter {
2515 self.list().iter()
2516 }
2517}
2518
2519impl<'a> IntoIterator for &'a mut Disks {
2520 type Item = &'a mut Disk;
2521 type IntoIter = std::slice::IterMut<'a, Disk>;
2522
2523 fn into_iter(self) -> Self::IntoIter {
2524 self.list_mut().iter_mut()
2525 }
2526}
2527
2528impl Disks {
2529 /// Creates a new empty [`Disks`][crate::Disks] type.
2530 ///
2531 /// If you want it to be filled directly, take a look at [`Disks::new_with_refreshed_list`].
2532 ///
2533 /// ```no_run
2534 /// use sysinfo::Disks;
2535 ///
2536 /// let mut disks = Disks::new();
2537 /// disks.refresh_list();
2538 /// for disk in disks.list() {
2539 /// println!("{disk:?}");
2540 /// }
2541 /// ```
2542 pub fn new() -> Self {
2543 Self {
2544 inner: crate::DisksInner::new(),
2545 }
2546 }
2547
2548 /// Creates a new [`Disks`][crate::Disks] type with the disk list loaded.
2549 /// It is a combination of [`Disks::new`] and [`Disks::refresh_list`].
2550 ///
2551 /// ```no_run
2552 /// use sysinfo::Disks;
2553 ///
2554 /// let mut disks = Disks::new_with_refreshed_list();
2555 /// for disk in disks.list() {
2556 /// println!("{disk:?}");
2557 /// }
2558 /// ```
2559 pub fn new_with_refreshed_list() -> Self {
2560 let mut disks = Self::new();
2561 disks.refresh_list();
2562 disks
2563 }
2564
2565 /// Returns the disks list.
2566 ///
2567 /// ```no_run
2568 /// use sysinfo::Disks;
2569 ///
2570 /// let disks = Disks::new_with_refreshed_list();
2571 /// for disk in disks.list() {
2572 /// println!("{disk:?}");
2573 /// }
2574 /// ```
2575 pub fn list(&self) -> &[Disk] {
2576 self.inner.list()
2577 }
2578
2579 /// Returns the disks list.
2580 ///
2581 /// ```no_run
2582 /// use sysinfo::Disks;
2583 ///
2584 /// let mut disks = Disks::new_with_refreshed_list();
2585 /// for disk in disks.list_mut() {
2586 /// disk.refresh();
2587 /// println!("{disk:?}");
2588 /// }
2589 /// ```
2590 pub fn list_mut(&mut self) -> &mut [Disk] {
2591 self.inner.list_mut()
2592 }
2593
2594 /// Refreshes the listed disks' information.
2595 ///
2596 /// ⚠️ If a disk is added or removed, this method won't take it into account. Use
2597 /// [`Disks::refresh_list`] instead.
2598 ///
2599 /// ⚠️ If you didn't call [`Disks::refresh_list`] beforehand, this method will do nothing as
2600 /// the disk list will be empty.
2601 ///
2602 /// ```no_run
2603 /// use sysinfo::Disks;
2604 ///
2605 /// let mut disks = Disks::new_with_refreshed_list();
2606 /// // We wait some time...?
2607 /// disks.refresh();
2608 /// ```
2609 pub fn refresh(&mut self) {
2610 for disk in self.list_mut() {
2611 disk.refresh();
2612 }
2613 }
2614
2615 /// The disk list will be emptied then completely recomputed.
2616 ///
2617 /// ## Linux
2618 ///
2619 /// ⚠️ On Linux, the [NFS](https://en.wikipedia.org/wiki/Network_File_System) file
2620 /// systems are ignored and the information of a mounted NFS **cannot** be obtained
2621 /// via [`Disks::refresh_list`]. This is due to the fact that I/O function
2622 /// `statvfs` used by [`Disks::refresh_list`] is blocking and
2623 /// [may hang](https://github.com/GuillaumeGomez/sysinfo/pull/876) in some cases,
2624 /// requiring to call `systemctl stop` to terminate the NFS service from the remote
2625 /// server in some cases.
2626 ///
2627 /// ```no_run
2628 /// use sysinfo::Disks;
2629 ///
2630 /// let mut disks = Disks::new();
2631 /// disks.refresh_list();
2632 /// ```
2633 pub fn refresh_list(&mut self) {
2634 self.inner.refresh_list();
2635 }
2636}
2637
2638impl std::ops::Deref for Disks {
2639 type Target = [Disk];
2640
2641 fn deref(&self) -> &Self::Target {
2642 self.list()
2643 }
2644}
2645
2646impl std::ops::DerefMut for Disks {
2647 fn deref_mut(&mut self) -> &mut Self::Target {
2648 self.list_mut()
2649 }
2650}
2651
2652/// Enum containing the different supported kinds of disks.
2653///
2654/// This type is returned by [`Disk::kind`](`crate::Disk::kind`).
2655///
2656/// ```no_run
2657/// use sysinfo::Disks;
2658///
2659/// let disks = Disks::new_with_refreshed_list();
2660/// for disk in disks.list() {
2661/// println!("{:?}: {:?}", disk.name(), disk.kind());
2662/// }
2663/// ```
2664#[derive(Debug, PartialEq, Eq, Clone, Copy)]
2665pub enum DiskKind {
2666 /// HDD type.
2667 HDD,
2668 /// SSD type.
2669 SSD,
2670 /// Unknown type.
2671 Unknown(isize),
2672}
2673
2674impl fmt::Display for DiskKind {
2675 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2676 f.write_str(match *self {
2677 DiskKind::HDD => "HDD",
2678 DiskKind::SSD => "SSD",
2679 _ => "Unknown",
2680 })
2681 }
2682}
2683
2684/// Interacting with users.
2685///
2686/// ```no_run
2687/// use sysinfo::Users;
2688///
2689/// let mut users = Users::new();
2690/// for user in users.list() {
2691/// println!("{} is in {} groups", user.name(), user.groups().len());
2692/// }
2693/// ```
2694pub struct Users {
2695 users: Vec<User>,
2696}
2697
2698impl Default for Users {
2699 fn default() -> Self {
2700 Self::new()
2701 }
2702}
2703
2704impl From<Users> for Vec<User> {
2705 fn from(users: Users) -> Self {
2706 users.users
2707 }
2708}
2709
2710impl From<Vec<User>> for Users {
2711 fn from(users: Vec<User>) -> Self {
2712 Self { users }
2713 }
2714}
2715
2716impl std::ops::Deref for Users {
2717 type Target = [User];
2718
2719 fn deref(&self) -> &Self::Target {
2720 self.list()
2721 }
2722}
2723
2724impl std::ops::DerefMut for Users {
2725 fn deref_mut(&mut self) -> &mut Self::Target {
2726 self.list_mut()
2727 }
2728}
2729
2730impl<'a> IntoIterator for &'a Users {
2731 type Item = &'a User;
2732 type IntoIter = std::slice::Iter<'a, User>;
2733
2734 fn into_iter(self) -> Self::IntoIter {
2735 self.list().iter()
2736 }
2737}
2738
2739impl<'a> IntoIterator for &'a mut Users {
2740 type Item = &'a mut User;
2741 type IntoIter = std::slice::IterMut<'a, User>;
2742
2743 fn into_iter(self) -> Self::IntoIter {
2744 self.list_mut().iter_mut()
2745 }
2746}
2747
2748impl Users {
2749 /// Creates a new empty [`Users`][crate::Users] type.
2750 ///
2751 /// If you want it to be filled directly, take a look at [`Users::new_with_refreshed_list`].
2752 ///
2753 /// ```no_run
2754 /// use sysinfo::Users;
2755 ///
2756 /// let mut users = Users::new();
2757 /// users.refresh_list();
2758 /// for user in users.list() {
2759 /// println!("{user:?}");
2760 /// }
2761 /// ```
2762 pub fn new() -> Self {
2763 Self { users: Vec::new() }
2764 }
2765
2766 /// Creates a new [`Users`][crate::Users] type with the user list loaded.
2767 /// It is a combination of [`Users::new`] and [`Users::refresh_list`].
2768 ///
2769 /// ```no_run
2770 /// use sysinfo::Users;
2771 ///
2772 /// let mut users = Users::new_with_refreshed_list();
2773 /// for user in users.list() {
2774 /// println!("{user:?}");
2775 /// }
2776 /// ```
2777 pub fn new_with_refreshed_list() -> Self {
2778 let mut users = Self::new();
2779 users.refresh_list();
2780 users
2781 }
2782
2783 /// Returns the users list.
2784 ///
2785 /// ```no_run
2786 /// use sysinfo::Users;
2787 ///
2788 /// let users = Users::new_with_refreshed_list();
2789 /// for user in users.list() {
2790 /// println!("{user:?}");
2791 /// }
2792 /// ```
2793 pub fn list(&self) -> &[User] {
2794 &self.users
2795 }
2796
2797 /// Returns the users list.
2798 ///
2799 /// ```no_run
2800 /// use sysinfo::Users;
2801 ///
2802 /// let mut users = Users::new_with_refreshed_list();
2803 /// users.list_mut().sort_by(|user1, user2| {
2804 /// user1.name().partial_cmp(user2.name()).unwrap()
2805 /// });
2806 /// ```
2807 pub fn list_mut(&mut self) -> &mut [User] {
2808 &mut self.users
2809 }
2810
2811 /// The user list will be emptied then completely recomputed.
2812 ///
2813 /// ```no_run
2814 /// use sysinfo::Users;
2815 ///
2816 /// let mut users = Users::new();
2817 /// users.refresh_list();
2818 /// ```
2819 pub fn refresh_list(&mut self) {
2820 crate::sys::get_users(&mut self.users);
2821 }
2822
2823 /// Returns the [`User`] matching the given `user_id`.
2824 ///
2825 /// **Important**: The user list must be filled before using this method, otherwise it will
2826 /// always return `None` (through the `refresh_*` methods).
2827 ///
2828 /// It is a shorthand for:
2829 ///
2830 /// ```ignore
2831 /// # use sysinfo::Users;
2832 /// let users = Users::new_with_refreshed_list();
2833 /// users.list().find(|user| user.id() == user_id);
2834 /// ```
2835 ///
2836 /// Full example:
2837 ///
2838 /// ```no_run
2839 /// use sysinfo::{Pid, System, Users};
2840 ///
2841 /// let mut s = System::new_all();
2842 /// let users = Users::new_with_refreshed_list();
2843 ///
2844 /// if let Some(process) = s.process(Pid::from(1337)) {
2845 /// if let Some(user_id) = process.user_id() {
2846 /// println!("User for process 1337: {:?}", users.get_user_by_id(user_id));
2847 /// }
2848 /// }
2849 /// ```
2850 pub fn get_user_by_id(&self, user_id: &Uid) -> Option<&User> {
2851 self.users.iter().find(|user| user.id() == user_id)
2852 }
2853}
2854
2855/// Interacting with groups.
2856///
2857/// ```no_run
2858/// use sysinfo::Groups;
2859///
2860/// let mut groups = Groups::new();
2861/// for group in groups.list() {
2862/// println!("{}", group.name());
2863/// }
2864/// ```
2865pub struct Groups {
2866 groups: Vec<Group>,
2867}
2868
2869impl Default for Groups {
2870 fn default() -> Self {
2871 Self::new()
2872 }
2873}
2874
2875impl From<Groups> for Vec<Group> {
2876 fn from(groups: Groups) -> Self {
2877 groups.groups
2878 }
2879}
2880
2881impl From<Vec<Group>> for Groups {
2882 fn from(groups: Vec<Group>) -> Self {
2883 Self { groups }
2884 }
2885}
2886
2887impl std::ops::Deref for Groups {
2888 type Target = [Group];
2889
2890 fn deref(&self) -> &Self::Target {
2891 self.list()
2892 }
2893}
2894
2895impl std::ops::DerefMut for Groups {
2896 fn deref_mut(&mut self) -> &mut Self::Target {
2897 self.list_mut()
2898 }
2899}
2900
2901impl<'a> IntoIterator for &'a Groups {
2902 type Item = &'a Group;
2903 type IntoIter = std::slice::Iter<'a, Group>;
2904
2905 fn into_iter(self) -> Self::IntoIter {
2906 self.list().iter()
2907 }
2908}
2909
2910impl<'a> IntoIterator for &'a mut Groups {
2911 type Item = &'a mut Group;
2912 type IntoIter = std::slice::IterMut<'a, Group>;
2913
2914 fn into_iter(self) -> Self::IntoIter {
2915 self.list_mut().iter_mut()
2916 }
2917}
2918
2919impl Groups {
2920 /// Creates a new empty [`Groups`][crate::Groups] type.
2921 ///
2922 /// If you want it to be filled directly, take a look at [`Groups::new_with_refreshed_list`].
2923 ///
2924 /// ```no_run
2925 /// use sysinfo::Groups;
2926 ///
2927 /// let mut groups = Groups::new();
2928 /// groups.refresh_list();
2929 /// for group in groups.list() {
2930 /// println!("{group:?}");
2931 /// }
2932 /// ```
2933 pub fn new() -> Self {
2934 Self { groups: Vec::new() }
2935 }
2936
2937 /// Creates a new [`Groups`][crate::Groups] type with the user list loaded.
2938 /// It is a combination of [`Groups::new`] and [`Groups::refresh_list`].
2939 ///
2940 /// ```no_run
2941 /// use sysinfo::Groups;
2942 ///
2943 /// let mut groups = Groups::new_with_refreshed_list();
2944 /// for group in groups.list() {
2945 /// println!("{group:?}");
2946 /// }
2947 /// ```
2948 pub fn new_with_refreshed_list() -> Self {
2949 let mut groups = Self::new();
2950 groups.refresh_list();
2951 groups
2952 }
2953
2954 /// Returns the users list.
2955 ///
2956 /// ```no_run
2957 /// use sysinfo::Groups;
2958 ///
2959 /// let groups = Groups::new_with_refreshed_list();
2960 /// for group in groups.list() {
2961 /// println!("{group:?}");
2962 /// }
2963 /// ```
2964 pub fn list(&self) -> &[Group] {
2965 &self.groups
2966 }
2967
2968 /// Returns the groups list.
2969 ///
2970 /// ```no_run
2971 /// use sysinfo::Groups;
2972 ///
2973 /// let mut groups = Groups::new_with_refreshed_list();
2974 /// groups.list_mut().sort_by(|user1, user2| {
2975 /// user1.name().partial_cmp(user2.name()).unwrap()
2976 /// });
2977 /// ```
2978 pub fn list_mut(&mut self) -> &mut [Group] {
2979 &mut self.groups
2980 }
2981
2982 /// The group list will be emptied then completely recomputed.
2983 ///
2984 /// ```no_run
2985 /// use sysinfo::Users;
2986 ///
2987 /// let mut users = Users::new();
2988 /// users.refresh_list();
2989 /// ```
2990 pub fn refresh_list(&mut self) {
2991 crate::sys::get_groups(&mut self.groups);
2992 }
2993}
2994
2995/// An enum representing signals on UNIX-like systems.
2996///
2997/// On non-unix systems, this enum is mostly useless and is only there to keep coherency between
2998/// the different OSes.
2999///
3000/// If you want the list of the supported signals on the current system, use
3001/// [`SUPPORTED_SIGNALS`][crate::SUPPORTED_SIGNALS].
3002#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Debug)]
3003pub enum Signal {
3004 /// Hangup detected on controlling terminal or death of controlling process.
3005 Hangup,
3006 /// Interrupt from keyboard.
3007 Interrupt,
3008 /// Quit from keyboard.
3009 Quit,
3010 /// Illegal instruction.
3011 Illegal,
3012 /// Trace/breakpoint trap.
3013 Trap,
3014 /// Abort signal from C abort function.
3015 Abort,
3016 /// IOT trap. A synonym for SIGABRT.
3017 IOT,
3018 /// Bus error (bad memory access).
3019 Bus,
3020 /// Floating point exception.
3021 FloatingPointException,
3022 /// Kill signal.
3023 Kill,
3024 /// User-defined signal 1.
3025 User1,
3026 /// Invalid memory reference.
3027 Segv,
3028 /// User-defined signal 2.
3029 User2,
3030 /// Broken pipe: write to pipe with no readers.
3031 Pipe,
3032 /// Timer signal from C alarm function.
3033 Alarm,
3034 /// Termination signal.
3035 Term,
3036 /// Child stopped or terminated.
3037 Child,
3038 /// Continue if stopped.
3039 Continue,
3040 /// Stop process.
3041 Stop,
3042 /// Stop typed at terminal.
3043 TSTP,
3044 /// Terminal input for background process.
3045 TTIN,
3046 /// Terminal output for background process.
3047 TTOU,
3048 /// Urgent condition on socket.
3049 Urgent,
3050 /// CPU time limit exceeded.
3051 XCPU,
3052 /// File size limit exceeded.
3053 XFSZ,
3054 /// Virtual alarm clock.
3055 VirtualAlarm,
3056 /// Profiling time expired.
3057 Profiling,
3058 /// Windows resize signal.
3059 Winch,
3060 /// I/O now possible.
3061 IO,
3062 /// Pollable event (Sys V). Synonym for IO
3063 Poll,
3064 /// Power failure (System V).
3065 ///
3066 /// Doesn't exist on apple systems so will be ignored.
3067 Power,
3068 /// Bad argument to routine (SVr4).
3069 Sys,
3070}
3071
3072impl std::fmt::Display for Signal {
3073 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
3074 let s = match *self {
3075 Self::Hangup => "Hangup",
3076 Self::Interrupt => "Interrupt",
3077 Self::Quit => "Quit",
3078 Self::Illegal => "Illegal",
3079 Self::Trap => "Trap",
3080 Self::Abort => "Abort",
3081 Self::IOT => "IOT",
3082 Self::Bus => "Bus",
3083 Self::FloatingPointException => "FloatingPointException",
3084 Self::Kill => "Kill",
3085 Self::User1 => "User1",
3086 Self::Segv => "Segv",
3087 Self::User2 => "User2",
3088 Self::Pipe => "Pipe",
3089 Self::Alarm => "Alarm",
3090 Self::Term => "Term",
3091 Self::Child => "Child",
3092 Self::Continue => "Continue",
3093 Self::Stop => "Stop",
3094 Self::TSTP => "TSTP",
3095 Self::TTIN => "TTIN",
3096 Self::TTOU => "TTOU",
3097 Self::Urgent => "Urgent",
3098 Self::XCPU => "XCPU",
3099 Self::XFSZ => "XFSZ",
3100 Self::VirtualAlarm => "VirtualAlarm",
3101 Self::Profiling => "Profiling",
3102 Self::Winch => "Winch",
3103 Self::IO => "IO",
3104 Self::Poll => "Poll",
3105 Self::Power => "Power",
3106 Self::Sys => "Sys",
3107 };
3108 f.write_str(s)
3109 }
3110}
3111
3112/// Contains memory limits for the current process.
3113#[derive(Default, Debug, Clone)]
3114pub struct CGroupLimits {
3115 /// Total memory (in bytes) for the current cgroup.
3116 pub total_memory: u64,
3117 /// Free memory (in bytes) for the current cgroup.
3118 pub free_memory: u64,
3119 /// Free swap (in bytes) for the current cgroup.
3120 pub free_swap: u64,
3121}
3122
3123/// A struct representing system load average value.
3124///
3125/// It is returned by [`System::load_average`][crate::System::load_average].
3126///
3127/// ```no_run
3128/// use sysinfo::System;
3129///
3130/// let load_avg = System::load_average();
3131/// println!(
3132/// "one minute: {}%, five minutes: {}%, fifteen minutes: {}%",
3133/// load_avg.one,
3134/// load_avg.five,
3135/// load_avg.fifteen,
3136/// );
3137/// ```
3138#[repr(C)]
3139#[derive(Default, Debug, Clone)]
3140pub struct LoadAvg {
3141 /// Average load within one minute.
3142 pub one: f64,
3143 /// Average load within five minutes.
3144 pub five: f64,
3145 /// Average load within fifteen minutes.
3146 pub fifteen: f64,
3147}
3148
3149macro_rules! xid {
3150 ($(#[$outer:meta])+ $name:ident, $type:ty $(, $trait:ty)?) => {
3151 $(#[$outer])+
3152 #[repr(transparent)]
3153 #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
3154 pub struct $name(pub(crate) $type);
3155
3156 impl std::ops::Deref for $name {
3157 type Target = $type;
3158
3159 fn deref(&self) -> &Self::Target {
3160 &self.0
3161 }
3162 }
3163
3164 $(
3165 impl TryFrom<usize> for $name {
3166 type Error = <$type as TryFrom<usize>>::Error;
3167
3168 fn try_from(t: usize) -> Result<Self, <$type as TryFrom<usize>>::Error> {
3169 Ok(Self(<$type>::try_from(t)?))
3170 }
3171 }
3172
3173 impl $trait for $name {
3174 type Err = <$type as FromStr>::Err;
3175
3176 fn from_str(t: &str) -> Result<Self, <$type as FromStr>::Err> {
3177 Ok(Self(<$type>::from_str(t)?))
3178 }
3179 }
3180 )?
3181 };
3182}
3183
3184macro_rules! uid {
3185 ($type:ty$(, $trait:ty)?) => {
3186 xid!(
3187 /// A user id wrapping a platform specific type.
3188 Uid,
3189 $type
3190 $(, $trait)?
3191 );
3192 };
3193}
3194
3195macro_rules! gid {
3196 ($type:ty) => {
3197 xid!(
3198 /// A group id wrapping a platform specific type.
3199 #[derive(Copy)]
3200 Gid,
3201 $type,
3202 FromStr
3203 );
3204 };
3205}
3206
3207cfg_if::cfg_if! {
3208 if #[cfg(all(
3209 not(feature = "unknown-ci"),
3210 any(
3211 target_os = "freebsd",
3212 target_os = "linux",
3213 target_os = "android",
3214 target_os = "macos",
3215 target_os = "ios",
3216 )
3217 ))] {
3218 uid!(libc::uid_t, FromStr);
3219 gid!(libc::gid_t);
3220 } else if #[cfg(windows)] {
3221 uid!(crate::windows::Sid);
3222 gid!(u32);
3223 // Manual implementation outside of the macro...
3224 impl FromStr for Uid {
3225 type Err = <crate::windows::Sid as FromStr>::Err;
3226
3227 fn from_str(t: &str) -> Result<Self, Self::Err> {
3228 Ok(Self(t.parse()?))
3229 }
3230 }
3231 } else {
3232 uid!(u32, FromStr);
3233 gid!(u32);
3234 }
3235}
3236
3237/// Type containing user information.
3238///
3239/// It is returned by [`Users`][crate::Users].
3240///
3241/// ```no_run
3242/// use sysinfo::Users;
3243///
3244/// let users = Users::new_with_refreshed_list();
3245/// for user in users.list() {
3246/// println!("{:?}", user);
3247/// }
3248/// ```
3249pub struct User {
3250 pub(crate) inner: UserInner,
3251}
3252
3253impl PartialEq for User {
3254 fn eq(&self, other: &Self) -> bool {
3255 self.id() == other.id()
3256 && self.group_id() == other.group_id()
3257 && self.name() == other.name()
3258 }
3259}
3260
3261impl Eq for User {}
3262
3263impl PartialOrd for User {
3264 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
3265 Some(self.cmp(other))
3266 }
3267}
3268
3269impl Ord for User {
3270 fn cmp(&self, other: &Self) -> Ordering {
3271 self.name().cmp(other.name())
3272 }
3273}
3274
3275impl User {
3276 /// Returns the ID of the user.
3277 ///
3278 /// ```no_run
3279 /// use sysinfo::Users;
3280 ///
3281 /// let users = Users::new_with_refreshed_list();
3282 /// for user in users.list() {
3283 /// println!("{:?}", *user.id());
3284 /// }
3285 /// ```
3286 pub fn id(&self) -> &Uid {
3287 self.inner.id()
3288 }
3289
3290 /// Returns the group ID of the user.
3291 ///
3292 /// ⚠️ This information is not set on Windows. Windows doesn't have a `username` specific
3293 /// group assigned to the user. They do however have unique
3294 /// [Security Identifiers](https://docs.microsoft.com/en-us/windows/win32/secauthz/security-identifiers)
3295 /// made up of various [Components](https://docs.microsoft.com/en-us/windows/win32/secauthz/sid-components).
3296 /// Pieces of the SID may be a candidate for this field, but it doesn't map well to a single
3297 /// group ID.
3298 ///
3299 /// ```no_run
3300 /// use sysinfo::Users;
3301 ///
3302 /// let users = Users::new_with_refreshed_list();
3303 /// for user in users.list() {
3304 /// println!("{}", *user.group_id());
3305 /// }
3306 /// ```
3307 pub fn group_id(&self) -> Gid {
3308 self.inner.group_id()
3309 }
3310
3311 /// Returns the name of the user.
3312 ///
3313 /// ```no_run
3314 /// use sysinfo::Users;
3315 ///
3316 /// let users = Users::new_with_refreshed_list();
3317 /// for user in users.list() {
3318 /// println!("{}", user.name());
3319 /// }
3320 /// ```
3321 pub fn name(&self) -> &str {
3322 self.inner.name()
3323 }
3324
3325 /// Returns the groups of the user.
3326 ///
3327 /// ⚠️ This is computed every time this method is called.
3328 ///
3329 /// ```no_run
3330 /// use sysinfo::Users;
3331 ///
3332 /// let users = Users::new_with_refreshed_list();
3333 /// for user in users.list() {
3334 /// println!("{} is in {:?}", user.name(), user.groups());
3335 /// }
3336 /// ```
3337 pub fn groups(&self) -> Vec<Group> {
3338 self.inner.groups()
3339 }
3340}
3341
3342#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
3343pub(crate) struct GroupInner {
3344 pub(crate) id: Gid,
3345 pub(crate) name: String,
3346}
3347
3348/// Type containing group information.
3349///
3350/// It is returned by [`User::groups`] or [`Groups::list`].
3351///
3352/// ```no_run
3353/// use sysinfo::Users;
3354///
3355/// let mut users = Users::new_with_refreshed_list();
3356///
3357/// for user in users.list() {
3358/// println!(
3359/// "user: (ID: {:?}, group ID: {:?}, name: {:?})",
3360/// user.id(),
3361/// user.group_id(),
3362/// user.name(),
3363/// );
3364/// for group in user.groups() {
3365/// println!("group: (ID: {:?}, name: {:?})", group.id(), group.name());
3366/// }
3367/// }
3368/// ```
3369#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
3370pub struct Group {
3371 pub(crate) inner: GroupInner,
3372}
3373
3374impl Group {
3375 /// Returns the ID of the group.
3376 ///
3377 /// ⚠️ This information is not set on Windows.
3378 ///
3379 /// ```no_run
3380 /// use sysinfo::Users;
3381 ///
3382 /// let mut users = Users::new_with_refreshed_list();
3383 ///
3384 /// for user in users.list() {
3385 /// for group in user.groups() {
3386 /// println!("{:?}", group.id());
3387 /// }
3388 /// }
3389 /// ```
3390 pub fn id(&self) -> &Gid {
3391 self.inner.id()
3392 }
3393
3394 /// Returns the name of the group.
3395 ///
3396 /// ```no_run
3397 /// use sysinfo::Users;
3398 ///
3399 /// let mut users = Users::new_with_refreshed_list();
3400 ///
3401 /// for user in users.list() {
3402 /// for group in user.groups() {
3403 /// println!("{}", group.name());
3404 /// }
3405 /// }
3406 /// ```
3407 pub fn name(&self) -> &str {
3408 self.inner.name()
3409 }
3410}
3411
3412/// Type containing read and written bytes.
3413///
3414/// It is returned by [`Process::disk_usage`][crate::Process::disk_usage].
3415///
3416/// ```no_run
3417/// use sysinfo::System;
3418///
3419/// let s = System::new_all();
3420/// for (pid, process) in s.processes() {
3421/// let disk_usage = process.disk_usage();
3422/// println!("[{}] read bytes : new/total => {}/{} B",
3423/// pid,
3424/// disk_usage.read_bytes,
3425/// disk_usage.total_read_bytes,
3426/// );
3427/// println!("[{}] written bytes: new/total => {}/{} B",
3428/// pid,
3429/// disk_usage.written_bytes,
3430/// disk_usage.total_written_bytes,
3431/// );
3432/// }
3433/// ```
3434#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd)]
3435pub struct DiskUsage {
3436 /// Total number of written bytes.
3437 pub total_written_bytes: u64,
3438 /// Number of written bytes since the last refresh.
3439 pub written_bytes: u64,
3440 /// Total number of read bytes.
3441 pub total_read_bytes: u64,
3442 /// Number of read bytes since the last refresh.
3443 pub read_bytes: u64,
3444}
3445
3446/// Enum describing the different status of a process.
3447#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3448pub enum ProcessStatus {
3449 /// ## Linux
3450 ///
3451 /// Idle kernel thread.
3452 ///
3453 /// ## macOs/FreeBSD
3454 ///
3455 /// Process being created by fork.
3456 ///
3457 /// ## Other OS
3458 ///
3459 /// Not available.
3460 Idle,
3461 /// Running.
3462 Run,
3463 /// ## Linux
3464 ///
3465 /// Sleeping in an interruptible waiting.
3466 ///
3467 /// ## macOS/FreeBSD
3468 ///
3469 /// Sleeping on an address.
3470 ///
3471 /// ## Other OS
3472 ///
3473 /// Not available.
3474 Sleep,
3475 /// ## Linux
3476 ///
3477 /// Stopped (on a signal) or (before Linux 2.6.33) trace stopped.
3478 ///
3479 /// ## macOS/FreeBSD
3480 ///
3481 /// Process debugging or suspension.
3482 ///
3483 /// ## Other OS
3484 ///
3485 /// Not available.
3486 Stop,
3487 /// ## Linux/FreeBSD/macOS
3488 ///
3489 /// Zombie process. Terminated but not reaped by its parent.
3490 ///
3491 /// ## Other OS
3492 ///
3493 /// Not available.
3494 Zombie,
3495 /// ## Linux
3496 ///
3497 /// Tracing stop (Linux 2.6.33 onward). Stopped by debugger during the tracing.
3498 ///
3499 /// ## Other OS
3500 ///
3501 /// Not available.
3502 Tracing,
3503 /// ## Linux
3504 ///
3505 /// Dead/uninterruptible sleep (usually IO).
3506 ///
3507 /// ## FreeBSD
3508 ///
3509 /// A process should never end up in this state.
3510 ///
3511 /// ## Other OS
3512 ///
3513 /// Not available.
3514 Dead,
3515 /// ## Linux
3516 ///
3517 /// Wakekill (Linux 2.6.33 to 3.13 only).
3518 ///
3519 /// ## Other OS
3520 ///
3521 /// Not available.
3522 Wakekill,
3523 /// ## Linux
3524 ///
3525 /// Waking (Linux 2.6.33 to 3.13 only).
3526 ///
3527 /// ## Other OS
3528 ///
3529 /// Not available.
3530 Waking,
3531 /// ## Linux
3532 ///
3533 /// Parked (Linux 3.9 to 3.13 only).
3534 ///
3535 /// ## macOS
3536 ///
3537 /// Halted at a clean point.
3538 ///
3539 /// ## Other OS
3540 ///
3541 /// Not available.
3542 Parked,
3543 /// ## FreeBSD
3544 ///
3545 /// Blocked on a lock.
3546 ///
3547 /// ## Other OS
3548 ///
3549 /// Not available.
3550 LockBlocked,
3551 /// ## Linux
3552 ///
3553 /// Waiting in uninterruptible disk sleep.
3554 ///
3555 /// ## Other OS
3556 ///
3557 /// Not available.
3558 UninterruptibleDiskSleep,
3559 /// Unknown.
3560 Unknown(u32),
3561}
3562
3563/// Enum describing the different kind of threads.
3564#[derive(Clone, Copy, Debug, PartialEq, Eq)]
3565pub enum ThreadKind {
3566 /// Kernel thread.
3567 Kernel,
3568 /// User thread.
3569 Userland,
3570}
3571
3572/// Returns the pid for the current process.
3573///
3574/// `Err` is returned in case the platform isn't supported.
3575///
3576/// ```no_run
3577/// use sysinfo::get_current_pid;
3578///
3579/// match get_current_pid() {
3580/// Ok(pid) => {
3581/// println!("current pid: {}", pid);
3582/// }
3583/// Err(e) => {
3584/// println!("failed to get current pid: {}", e);
3585/// }
3586/// }
3587/// ```
3588#[allow(clippy::unnecessary_wraps)]
3589pub fn get_current_pid() -> Result<Pid, &'static str> {
3590 cfg_if::cfg_if! {
3591 if #[cfg(feature = "unknown-ci")] {
3592 fn inner() -> Result<Pid, &'static str> {
3593 Err("Unknown platform (CI)")
3594 }
3595 } else if #[cfg(any(
3596 target_os = "freebsd",
3597 target_os = "linux",
3598 target_os = "android",
3599 target_os = "macos",
3600 target_os = "ios",
3601 ))] {
3602 fn inner() -> Result<Pid, &'static str> {
3603 unsafe { Ok(Pid(libc::getpid())) }
3604 }
3605 } else if #[cfg(windows)] {
3606 fn inner() -> Result<Pid, &'static str> {
3607 use windows::Win32::System::Threading::GetCurrentProcessId;
3608
3609 unsafe { Ok(Pid(GetCurrentProcessId() as _)) }
3610 }
3611 } else {
3612 fn inner() -> Result<Pid, &'static str> {
3613 Err("Unknown platform")
3614 }
3615 }
3616 }
3617 inner()
3618}
3619
3620/// MAC address for network interface.
3621///
3622/// It is returned by [`NetworkData::mac_address`][crate::NetworkData::mac_address].
3623#[derive(PartialEq, Eq, Copy, Clone, Debug)]
3624pub struct MacAddr(pub [u8; 6]);
3625
3626impl MacAddr {
3627 /// A `MacAddr` with all bytes set to `0`.
3628 pub const UNSPECIFIED: Self = MacAddr([0; 6]);
3629
3630 /// Checks if this `MacAddr` has all bytes equal to `0`.
3631 pub fn is_unspecified(&self) -> bool {
3632 self == &MacAddr::UNSPECIFIED
3633 }
3634}
3635
3636impl fmt::Display for MacAddr {
3637 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3638 let data = &self.0;
3639 write!(
3640 f,
3641 "{:02x}:{:02x}:{:02x}:{:02x}:{:02x}:{:02x}",
3642 data[0], data[1], data[2], data[3], data[4], data[5],
3643 )
3644 }
3645}
3646
3647/// Interacting with components.
3648///
3649/// ```no_run
3650/// use sysinfo::Components;
3651///
3652/// let components = Components::new_with_refreshed_list();
3653/// for component in &components {
3654/// println!("{component:?}");
3655/// }
3656/// ```
3657pub struct Components {
3658 pub(crate) inner: ComponentsInner,
3659}
3660
3661impl Default for Components {
3662 fn default() -> Self {
3663 Self::new()
3664 }
3665}
3666
3667impl From<Components> for Vec<Component> {
3668 fn from(components: Components) -> Self {
3669 components.inner.into_vec()
3670 }
3671}
3672
3673impl From<Vec<Component>> for Components {
3674 fn from(components: Vec<Component>) -> Self {
3675 Self {
3676 inner: ComponentsInner::from_vec(components),
3677 }
3678 }
3679}
3680
3681impl std::ops::Deref for Components {
3682 type Target = [Component];
3683
3684 fn deref(&self) -> &Self::Target {
3685 self.list()
3686 }
3687}
3688
3689impl std::ops::DerefMut for Components {
3690 fn deref_mut(&mut self) -> &mut Self::Target {
3691 self.list_mut()
3692 }
3693}
3694
3695impl<'a> IntoIterator for &'a Components {
3696 type Item = &'a Component;
3697 type IntoIter = std::slice::Iter<'a, Component>;
3698
3699 fn into_iter(self) -> Self::IntoIter {
3700 self.list().iter()
3701 }
3702}
3703
3704impl<'a> IntoIterator for &'a mut Components {
3705 type Item = &'a mut Component;
3706 type IntoIter = std::slice::IterMut<'a, Component>;
3707
3708 fn into_iter(self) -> Self::IntoIter {
3709 self.list_mut().iter_mut()
3710 }
3711}
3712
3713impl Components {
3714 /// Creates a new empty [`Components`][crate::Components] type.
3715 ///
3716 /// If you want it to be filled directly, take a look at
3717 /// [`Components::new_with_refreshed_list`].
3718 ///
3719 /// ```no_run
3720 /// use sysinfo::Components;
3721 ///
3722 /// let mut components = Components::new();
3723 /// components.refresh_list();
3724 /// for component in &components {
3725 /// println!("{component:?}");
3726 /// }
3727 /// ```
3728 pub fn new() -> Self {
3729 Self {
3730 inner: ComponentsInner::new(),
3731 }
3732 }
3733
3734 /// Creates a new [`Components`][crate::Components] type with the user list
3735 /// loaded. It is a combination of [`Components::new`] and
3736 /// [`Components::refresh_list`].
3737 ///
3738 /// ```no_run
3739 /// use sysinfo::Components;
3740 ///
3741 /// let mut components = Components::new_with_refreshed_list();
3742 /// for component in components.list() {
3743 /// println!("{component:?}");
3744 /// }
3745 /// ```
3746 pub fn new_with_refreshed_list() -> Self {
3747 let mut components = Self::new();
3748 components.refresh_list();
3749 components
3750 }
3751
3752 /// Returns the components list.
3753 ///
3754 /// ```no_run
3755 /// use sysinfo::Components;
3756 ///
3757 /// let components = Components::new_with_refreshed_list();
3758 /// for component in components.list() {
3759 /// println!("{component:?}");
3760 /// }
3761 /// ```
3762 pub fn list(&self) -> &[Component] {
3763 self.inner.list()
3764 }
3765
3766 /// Returns the components list.
3767 ///
3768 /// ```no_run
3769 /// use sysinfo::Components;
3770 ///
3771 /// let mut components = Components::new_with_refreshed_list();
3772 /// for component in components.list_mut() {
3773 /// component.refresh();
3774 /// println!("{component:?}");
3775 /// }
3776 /// ```
3777 pub fn list_mut(&mut self) -> &mut [Component] {
3778 self.inner.list_mut()
3779 }
3780
3781 /// Refreshes the listed components' information.
3782 ///
3783 /// ⚠️ If a component is added or removed, this method won't take it into account. Use
3784 /// [`Components::refresh_list`] instead.
3785 ///
3786 /// ⚠️ If you didn't call [`Components::refresh_list`] beforehand, this method will do
3787 /// nothing as the component list will be empty.
3788 ///
3789 /// ```no_run
3790 /// use sysinfo::Components;
3791 ///
3792 /// let mut components = Components::new_with_refreshed_list();
3793 /// // We wait some time...?
3794 /// components.refresh();
3795 /// ```
3796 pub fn refresh(&mut self) {
3797 #[cfg(all(
3798 feature = "multithread",
3799 not(feature = "unknown-ci"),
3800 not(all(target_os = "macos", feature = "apple-sandbox")),
3801 ))]
3802 use rayon::iter::ParallelIterator;
3803 into_iter_mut(self.list_mut()).for_each(|component| component.refresh());
3804 }
3805
3806 /// The component list will be emptied then completely recomputed.
3807 ///
3808 /// ```no_run
3809 /// use sysinfo::Components;
3810 ///
3811 /// let mut components = Components::new();
3812 /// components.refresh_list();
3813 /// ```
3814 pub fn refresh_list(&mut self) {
3815 self.inner.refresh_list()
3816 }
3817}
3818
3819/// Getting a component temperature information.
3820///
3821/// ```no_run
3822/// use sysinfo::Components;
3823///
3824/// let components = Components::new_with_refreshed_list();
3825/// for component in &components {
3826/// println!("{} {}°C", component.label(), component.temperature());
3827/// }
3828/// ```
3829pub struct Component {
3830 pub(crate) inner: ComponentInner,
3831}
3832
3833impl Component {
3834 /// Returns the temperature of the component (in celsius degree).
3835 ///
3836 /// ## Linux
3837 ///
3838 /// Returns `f32::NAN` if it failed to retrieve it.
3839 ///
3840 /// ```no_run
3841 /// use sysinfo::Components;
3842 ///
3843 /// let components = Components::new_with_refreshed_list();
3844 /// for component in &components {
3845 /// println!("{}°C", component.temperature());
3846 /// }
3847 /// ```
3848 pub fn temperature(&self) -> f32 {
3849 self.inner.temperature()
3850 }
3851
3852 /// Returns the maximum temperature of the component (in celsius degree).
3853 ///
3854 /// Note: if `temperature` is higher than the current `max`,
3855 /// `max` value will be updated on refresh.
3856 ///
3857 /// ## Linux
3858 ///
3859 /// May be computed by `sysinfo` from kernel.
3860 /// Returns `f32::NAN` if it failed to retrieve it.
3861 ///
3862 /// ```no_run
3863 /// use sysinfo::Components;
3864 ///
3865 /// let components = Components::new_with_refreshed_list();
3866 /// for component in &components {
3867 /// println!("{}°C", component.max());
3868 /// }
3869 /// ```
3870 pub fn max(&self) -> f32 {
3871 self.inner.max()
3872 }
3873
3874 /// Returns the highest temperature before the component halts (in celsius degree).
3875 ///
3876 /// ## Linux
3877 ///
3878 /// Critical threshold defined by chip or kernel.
3879 ///
3880 /// ```no_run
3881 /// use sysinfo::Components;
3882 ///
3883 /// let components = Components::new_with_refreshed_list();
3884 /// for component in &components {
3885 /// println!("{:?}°C", component.critical());
3886 /// }
3887 /// ```
3888 pub fn critical(&self) -> Option<f32> {
3889 self.inner.critical()
3890 }
3891
3892 /// Returns the label of the component.
3893 ///
3894 /// ## Linux
3895 ///
3896 /// Since components information is retrieved thanks to `hwmon`,
3897 /// the labels are generated as follows.
3898 /// Note: it may change and it was inspired by `sensors` own formatting.
3899 ///
3900 /// | name | label | device_model | id_sensor | Computed label by `sysinfo` |
3901 /// |---------|--------|------------|----------|----------------------|
3902 /// | ✓ | ✓ | ✓ | ✓ | `"{name} {label} {device_model} temp{id}"` |
3903 /// | ✓ | ✓ | ✗ | ✓ | `"{name} {label} {id}"` |
3904 /// | ✓ | ✗ | ✓ | ✓ | `"{name} {device_model}"` |
3905 /// | ✓ | ✗ | ✗ | ✓ | `"{name} temp{id}"` |
3906 ///
3907 /// ```no_run
3908 /// use sysinfo::Components;
3909 ///
3910 /// let components = Components::new_with_refreshed_list();
3911 /// for component in &components {
3912 /// println!("{}", component.label());
3913 /// }
3914 /// ```
3915 pub fn label(&self) -> &str {
3916 self.inner.label()
3917 }
3918
3919 /// Refreshes component.
3920 ///
3921 /// ```no_run
3922 /// use sysinfo::Components;
3923 ///
3924 /// let mut components = Components::new_with_refreshed_list();
3925 /// for component in components.iter_mut() {
3926 /// component.refresh();
3927 /// }
3928 /// ```
3929 pub fn refresh(&mut self) {
3930 self.inner.refresh()
3931 }
3932}
3933
3934/// Contains all the methods of the [`Cpu`][crate::Cpu] struct.
3935///
3936/// ```no_run
3937/// use sysinfo::{System, RefreshKind, CpuRefreshKind};
3938///
3939/// let mut s = System::new_with_specifics(
3940/// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
3941/// );
3942///
3943/// // Wait a bit because CPU usage is based on diff.
3944/// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
3945/// // Refresh CPUs again.
3946/// s.refresh_cpu();
3947///
3948/// for cpu in s.cpus() {
3949/// println!("{}%", cpu.cpu_usage());
3950/// }
3951/// ```
3952pub struct Cpu {
3953 pub(crate) inner: CpuInner,
3954}
3955
3956impl Cpu {
3957 /// Returns this CPU's usage.
3958 ///
3959 /// Note: You'll need to refresh it at least twice (diff between the first and the second is
3960 /// how CPU usage is computed) at first if you want to have a non-zero value.
3961 ///
3962 /// ```no_run
3963 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
3964 ///
3965 /// let mut s = System::new_with_specifics(
3966 /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
3967 /// );
3968 ///
3969 /// // Wait a bit because CPU usage is based on diff.
3970 /// std::thread::sleep(sysinfo::MINIMUM_CPU_UPDATE_INTERVAL);
3971 /// // Refresh CPUs again.
3972 /// s.refresh_cpu();
3973 ///
3974 /// for cpu in s.cpus() {
3975 /// println!("{}%", cpu.cpu_usage());
3976 /// }
3977 /// ```
3978 pub fn cpu_usage(&self) -> f32 {
3979 self.inner.cpu_usage()
3980 }
3981
3982 /// Returns this CPU's name.
3983 ///
3984 /// ```no_run
3985 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
3986 ///
3987 /// let s = System::new_with_specifics(
3988 /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
3989 /// );
3990 /// for cpu in s.cpus() {
3991 /// println!("{}", cpu.name());
3992 /// }
3993 /// ```
3994 pub fn name(&self) -> &str {
3995 self.inner.name()
3996 }
3997
3998 /// Returns the CPU's vendor id.
3999 ///
4000 /// ```no_run
4001 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
4002 ///
4003 /// let s = System::new_with_specifics(
4004 /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
4005 /// );
4006 /// for cpu in s.cpus() {
4007 /// println!("{}", cpu.vendor_id());
4008 /// }
4009 /// ```
4010 pub fn vendor_id(&self) -> &str {
4011 self.inner.vendor_id()
4012 }
4013
4014 /// Returns the CPU's brand.
4015 ///
4016 /// ```no_run
4017 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
4018 ///
4019 /// let s = System::new_with_specifics(
4020 /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
4021 /// );
4022 /// for cpu in s.cpus() {
4023 /// println!("{}", cpu.brand());
4024 /// }
4025 /// ```
4026 pub fn brand(&self) -> &str {
4027 self.inner.brand()
4028 }
4029
4030 /// Returns the CPU's frequency.
4031 ///
4032 /// ```no_run
4033 /// use sysinfo::{System, RefreshKind, CpuRefreshKind};
4034 ///
4035 /// let s = System::new_with_specifics(
4036 /// RefreshKind::new().with_cpu(CpuRefreshKind::everything()),
4037 /// );
4038 /// for cpu in s.cpus() {
4039 /// println!("{}", cpu.frequency());
4040 /// }
4041 /// ```
4042 pub fn frequency(&self) -> u64 {
4043 self.inner.frequency()
4044 }
4045}