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}