feature: FreeBSD add ufs disk io counters (#2055)

This PR adds ufs disk io counters on freebsd by using sysinfo. This PR also updates the Cargo.toml to use the dep syntax for the unused feature flags starship-battery and nvml-wrapper.
This commit is contained in:
Justin Martin
2026-06-20 06:39:47 +00:00
committed by GitHub
parent 382dfdb80c
commit 3542c0bc49
20 changed files with 214 additions and 129 deletions
Generated
+26 -3
View File
@@ -160,7 +160,6 @@ version = "0.13.0"
dependencies = [
"anyhow",
"assert_cmd",
"cfg-if",
"clap",
"clap_complete",
"clap_complete_fig",
@@ -1144,6 +1143,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536"
dependencies = [
"bitflags 2.10.0",
"dispatch2",
"objc2",
]
[[package]]
@@ -1152,6 +1153,16 @@ version = "4.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
[[package]]
name = "objc2-foundation"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [
"bitflags 2.10.0",
"objc2",
]
[[package]]
name = "objc2-io-kit"
version = "0.3.2"
@@ -1162,6 +1173,17 @@ dependencies = [
"objc2-core-foundation",
]
[[package]]
name = "objc2-open-directory"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb82bed227edf5201dfedf072bba4015a33d3d4a98519837295a90f0a23f676d"
dependencies = [
"objc2",
"objc2-core-foundation",
"objc2-foundation",
]
[[package]]
name = "once_cell"
version = "1.21.3"
@@ -1910,15 +1932,16 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.38.4"
version = "0.39.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ab6a2f8bfe508deb3c6406578252e491d299cbbf3bc0529ecc3313aee4a52f"
checksum = "21d0d938c10fcda3e897e28aaddf4ab462375d411f4378cd63b1c945f69aba96"
dependencies = [
"libc",
"memchr",
"ntapi",
"objc2-core-foundation",
"objc2-io-kit",
"objc2-open-directory",
"windows",
]
+5 -6
View File
@@ -62,11 +62,11 @@ required-features = ["generate_schema"]
[features]
# Used for general builds.
battery = ["starship-battery"]
nvidia = ["nvml-wrapper"]
gpu = ["nvidia"]
battery = ["dep:starship-battery"]
nvidia = ["gpu", "dep:nvml-wrapper"]
gpu = []
zfs = []
deploy = ["battery", "gpu", "zfs"]
deploy = ["battery", "nvidia", "zfs"]
default = ["deploy"]
# Should not be included in builds.
@@ -75,7 +75,6 @@ generate_schema = ["schemars", "serde_json", "strum"]
[dependencies]
anyhow = "1.0.101"
cfg-if = "1.0.4"
clap = { version = "4.5.57", features = ["default", "cargo", "wrap_help", "derive"] }
concat-string = "1.0.1"
crossterm = "0.29.0"
@@ -91,7 +90,7 @@ regex = "1.12.3"
rustc-hash = "2.1.1"
serde = { version = "1.0.228", features = ["derive"] }
starship-battery = { version = "0.10.3", optional = true }
sysinfo = "=0.38.4"
sysinfo = "=0.39.3"
timeless = "0.0.14-alpha"
toml_edit = { version = "0.24.0", features = ["serde"] }
tui = { version = "0.30.0", package = "ratatui", features = [
+4
View File
@@ -379,6 +379,10 @@
# Network widget configuration
#[network_graph]
# Whether to display packet rate and average packet size info. Defaults to false.
#show_packets = false
# By default, there are no network interface filters enabled. An example use case is provided below.
#[network_graph.interface_filter]
# Whether to ignore any matches. Defaults to true.
+7 -6
View File
@@ -994,12 +994,13 @@ impl App {
let current_process = (id, pids);
let use_simple_selection = {
cfg_if::cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))] {
!self.app_config_fields.is_advanced_kill
} else {
true
}
cfg_select! {
any(target_os = "linux", target_os = "macos", target_os = "freebsd") => {
!self.app_config_fields.is_advanced_kill
}
_ => {
true
}
}
};
+11 -5
View File
@@ -204,16 +204,22 @@ impl StoredData {
}
#[cfg(not(target_os = "windows"))]
{
#[cfg(feature = "zfs")]
#[cfg(any(feature = "zfs", target_os = "freebsd"))]
{
if !device.name.starts_with('/') {
Some(device.name.as_str()) // use the whole zfs
// dataset name
Some(device.name.as_str()) // use the whole name
} else {
device.name.split('/').next_back()
#[cfg(target_os = "freebsd")]
{
Some(device.mount_point.as_str()) // use mount_point for sysinfo
}
#[cfg(not(target_os = "freebsd"))]
{
device.name.split('/').next_back() // use device name
}
}
}
#[cfg(not(feature = "zfs"))]
#[cfg(not(any(feature = "zfs", target_os = "freebsd")))]
{
device.name.split('/').next_back()
}
+17 -12
View File
@@ -2,7 +2,6 @@
use std::time::Instant;
use cfg_if::cfg_if;
#[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))]
use tui::widgets::ListState;
use tui::{
@@ -21,8 +20,8 @@ use crate::{
};
// Configure signal text based on the target OS.
cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
const DEFAULT_KILL_SIGNAL: usize = 15;
const SIGNAL_TEXT: [&str; 63] = [
"0: Cancel",
@@ -89,7 +88,8 @@ cfg_if! {
"63: RTMAX-1",
"64: RTMAX",
];
} else if #[cfg(target_os = "macos")] {
}
target_os = "macos" => {
const DEFAULT_KILL_SIGNAL: usize = 15;
const SIGNAL_TEXT: [&str; 32] = [
"0: Cancel",
@@ -125,7 +125,8 @@ cfg_if! {
"30: USR1",
"31: USR2",
];
} else if #[cfg(target_os = "freebsd")] {
}
target_os = "freebsd" => {
const DEFAULT_KILL_SIGNAL: usize = 15;
const SIGNAL_TEXT: [&str; 34] = [
"0: Cancel",
@@ -164,6 +165,7 @@ cfg_if! {
"33: LIBRT",
];
}
_ => {}
}
/// Button state type for a [`ProcessKillDialog`].
@@ -267,8 +269,8 @@ impl ProcessKillDialog {
}
ButtonState::Simple { yes, .. } => {
if yes {
cfg_if! {
if #[cfg(target_os = "windows")] {
cfg_select! {
target_os = "windows" => {
use crate::utils::process_killer;
for pid in pids {
@@ -277,7 +279,8 @@ impl ProcessKillDialog {
break;
}
}
} else if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))] {
}
any(target_os = "linux", target_os = "macos", target_os = "freebsd") => {
use crate::utils::process_killer;
for pid in pids {
@@ -287,7 +290,8 @@ impl ProcessKillDialog {
break;
}
}
} else {
}
_ => {
self.state = ProcessKillDialogState::Error { process_name, pid: None, err: "Killing processes is not supported on this platform.".into() };
}
@@ -582,10 +586,11 @@ impl ProcessKillDialog {
last_no_button_area: Rect::default(),
}
} else {
cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "freebsd"))] {
cfg_select! {
any(target_os = "linux", target_os = "macos", target_os = "freebsd") => {
ButtonState::Signals { state: ListState::default().with_selected(Some(DEFAULT_KILL_SIGNAL)), last_button_draw_area: Rect::default() }
} else {
}
_ => {
ButtonState::Simple { yes: false, last_yes_button_area: Rect::default(), last_no_button_area: Rect::default()}
}
}
+4 -3
View File
@@ -176,10 +176,11 @@ impl Painter {
// TODO: [MOUSE] Mouse support for these in search
// TODO: [MOVEMENT] Movement support for these in search
let (case, whole, regex) = {
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
cfg_select! {
target_os = "macos" => {
("Case(F1)", "Whole(F2)", "Regex(F3)")
} else {
}
_ => {
("Case(Alt+C)", "Whole(Alt+W)", "Regex(Alt+R)")
}
}
+6 -6
View File
@@ -126,7 +126,7 @@ pub struct SysinfoSource {
pub(crate) network: sysinfo::Networks,
#[cfg(not(target_os = "linux"))]
pub(crate) temps: sysinfo::Components,
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "freebsd")))]
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
pub(crate) disks: sysinfo::Disks,
#[cfg(target_os = "windows")]
pub(crate) users: sysinfo::Users,
@@ -141,7 +141,7 @@ impl Default for SysinfoSource {
network: Networks::new(),
#[cfg(not(target_os = "linux"))]
temps: Components::new(),
#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "freebsd")))]
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
disks: Disks::new(),
#[cfg(target_os = "windows")]
users: Users::new(),
@@ -306,7 +306,7 @@ impl DataCollector {
/// - Memory usage
/// - Network usage
/// - Processes (non-Linux)
/// - Disk (Windows)
/// - Disk (Windows, FreeBSD)
/// - Temperatures (non-Linux)
fn refresh_sysinfo_data(&mut self) {
// Refresh the list of objects once every minute. If it's too frequent it can
@@ -326,7 +326,7 @@ impl DataCollector {
// sysinfo is used on non-Linux systems for the following:
// - Processes (users list as well for Windows)
// - Disks (Windows only)
// - Disks (Windows/FreeBSD)
// - Temperatures and temperature components list.
#[cfg(not(target_os = "linux"))]
{
@@ -357,7 +357,7 @@ impl DataCollector {
}
}
#[cfg(target_os = "windows")]
#[cfg(any(target_os = "windows", target_os = "freebsd"))]
if self.widgets_to_harvest.use_disk {
if self.should_run_less_routine_tasks {
self.sys.disks.refresh(true);
@@ -635,7 +635,7 @@ impl DataCollector {
fn update_disks(&mut self) {
if self.widgets_to_harvest.use_disk || self.widgets_to_harvest.use_disk_io_graph {
self.data.disks = disks::get_disk_usage(self).ok();
self.data.io = disks::get_io_usage().ok();
self.data.io = disks::get_io_usage(self).ok();
}
}
+4 -3
View File
@@ -10,13 +10,14 @@ pub fn get_cpu_data_list(collector: &DataCollector) -> CollectionResult<CpuHarve
let mut cpus = vec![];
if show_average_cpu {
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
cpus.push(CpuData {
data_type: CpuDataType::Avg,
usage: collector.cgroup_cpu_data.avg_cpu_percent.unwrap_or_else(|| sys.global_cpu_usage()),
});
} else {
}
_ => {
cpus.push(CpuData {
data_type: CpuDataType::Avg,
usage: sys.global_cpu_usage(),
+20 -12
View File
@@ -1,7 +1,7 @@
//! Data collection about disks (e.g. I/O, usage, space).
cfg_if! {
if #[cfg(target_os = "freebsd")] {
cfg_select! {
target_os = "freebsd" => {
mod freebsd;
#[cfg(feature = "zfs")]
mod io_counters;
@@ -10,24 +10,27 @@ cfg_if! {
#[cfg(feature = "zfs")]
pub use io_counters::IoCounters;
pub(crate) use self::freebsd::*;
} else if #[cfg(target_os = "windows")] {
}
target_os = "windows" => {
mod windows;
pub(crate) use self::windows::*;
} else if #[cfg(target_os = "linux")] {
}
target_os = "linux" => {
mod unix;
#[cfg(feature = "zfs")]
mod zfs_io_counters;
pub(crate) use self::unix::*;
} else if #[cfg(target_os = "macos")] {
}
target_os = "macos" => {
mod unix;
pub(crate) use self::unix::*;
} else {
}
_ => {
mod other;
pub(crate) use self::other::*;
}
}
use cfg_if::cfg_if;
use rustc_hash::FxHashMap as HashMap;
use crate::app::filter::Filter;
@@ -57,15 +60,17 @@ pub struct IoData {
pub type IoHarvest = HashMap<String, Option<IoData>>;
cfg_if! {
if #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] {
cfg_select! {
any(target_os = "linux", target_os = "macos", target_os = "windows") => {
mod io_counters;
pub use io_counters::IoCounters;
use crate::collection::DataCollector;
/// Returns the I/O usage of certain mount points.
pub fn get_io_usage() -> anyhow::Result<IoHarvest> {
pub fn get_io_usage(_collector: &DataCollector) -> anyhow::Result<IoHarvest> {
let mut io_hash: HashMap<String, Option<IoData>> = HashMap::default();
// TODO: Maybe rewrite this to not do a result of vec of result...
for io in io_stats()?.into_iter() {
let mount_point = io.device_name().to_string_lossy();
@@ -81,11 +86,14 @@ cfg_if! {
Ok(io_hash)
}
} else if #[cfg(not(target_os = "freebsd"))] {
pub fn get_io_usage() -> anyhow::Result<IoHarvest> {
}
not(target_os = "freebsd") => {
use crate::collection::DataCollector;
pub fn get_io_usage(_collector: &DataCollector) -> anyhow::Result<IoHarvest> {
anyhow::bail!("Unsupported OS");
}
}
_ => {}
}
/// Whether to keep the current disk entry given the filters, disk name, and
+16 -11
View File
@@ -24,18 +24,23 @@ struct FileSystem {
mounted_on: String,
}
pub fn get_io_usage() -> CollectionResult<IoHarvest> {
// TODO: Should this (and other I/O collectors) fail fast? In general, should
// collection ever fail fast?
pub fn get_io_usage(collector: &DataCollector) -> CollectionResult<IoHarvest> {
#[cfg_attr(not(feature = "zfs"), expect(unused_mut))]
let mut io_harvest: HashMap<String, Option<IoData>> =
get_disk_info().map(|storage_system_information| {
storage_system_information
.filesystem
.into_iter()
.map(|disk| (disk.name, None))
.collect()
})?;
let mut io_harvest: HashMap<String, Option<IoData>> = collector
.sys
.disks
.iter()
.map(|disk| {
let usage = disk.usage();
(
disk.mount_point().to_string_lossy().to_string(),
Some(IoData {
read_bytes: usage.read_bytes,
write_bytes: usage.written_bytes,
}),
)
})
.collect();
#[cfg(feature = "zfs")]
{
+6 -4
View File
@@ -5,17 +5,19 @@ mod file_systems;
mod usage;
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
mod linux;
pub use linux::*;
} else if #[cfg(target_os = "macos")] {
}
target_os = "macos" => {
mod other;
use other::*;
mod macos;
pub use macos::*;
} else {
}
_ => {
mod other;
use other::*;
}
+4 -3
View File
@@ -6,11 +6,12 @@ pub(crate) use self::sysinfo::get_ram_usage;
pub mod sysinfo;
cfg_if::cfg_if! {
if #[cfg(target_os = "windows")] {
cfg_select! {
target_os = "windows" => {
mod windows;
pub(crate) use self::windows::get_swap_usage;
} else {
}
_ => {
pub(crate) use self::sysinfo::{get_cache_usage, get_swap_usage};
}
}
+6 -4
View File
@@ -6,8 +6,8 @@ pub(crate) fn get_arc_usage() -> Option<(MemData, u64)> {
use std::num::NonZeroU64;
let (mem_total, mem_used, mem_min) = {
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
// TODO: [OPT] is this efficient?
use std::fs::read_to_string;
if let Ok(arc_stats) = read_to_string("/proc/spl/kstat/zfs/arcstats") {
@@ -45,7 +45,8 @@ pub(crate) fn get_arc_usage() -> Option<(MemData, u64)> {
} else {
(0, 0, 0)
}
} else if #[cfg(target_os = "freebsd")] {
}
target_os = "freebsd" => {
use sysctl::Sysctl;
if let (Ok(mem_arc_value), Ok(mem_sys_value), Ok(mem_min_value)) = (
sysctl::Ctl::new("kstat.zfs.misc.arcstats.size"),
@@ -62,7 +63,8 @@ pub(crate) fn get_arc_usage() -> Option<(MemData, u64)> {
} else {
(0, 0, 0)
}
} else {
}
_ => {
(0, 0, 0)
}
}
+8 -6
View File
@@ -18,8 +18,8 @@ fn get_usage(used: u64, total: u64) -> Option<MemData> {
pub(crate) fn get_ram_usage(collector: &DataCollector) -> Option<MemData> {
let sys = &collector.sys.system;
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
use crate::collection::linux::cgroups;
let base_used = sys.used_memory();
@@ -40,7 +40,8 @@ pub(crate) fn get_ram_usage(collector: &DataCollector) -> Option<MemData> {
};
get_usage(used, total)
} else {
}
_ => {
get_usage(sys.used_memory(), sys.total_memory())
}
}
@@ -53,8 +54,8 @@ pub(crate) fn get_ram_usage(collector: &DataCollector) -> Option<MemData> {
pub(crate) fn get_swap_usage(collector: &DataCollector) -> Option<MemData> {
let sys = &collector.sys.system;
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
use crate::collection::linux::cgroups;
let base_used = sys.used_swap();
@@ -75,7 +76,8 @@ pub(crate) fn get_swap_usage(collector: &DataCollector) -> Option<MemData> {
};
get_usage(used, total)
} else {
}
_ => {
get_usage(sys.used_swap(), sys.total_swap())
}
}
+35 -22
View File
@@ -3,47 +3,54 @@
//! For Linux, this is handled by a custom set of functions.
//! For Windows, macOS, FreeBSD, Android, and Linux, this is handled by sysinfo.
use cfg_if::cfg_if;
use sysinfo::ProcessStatus;
cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
pub mod linux;
pub use self::linux::*;
} else if #[cfg(target_os = "macos")] {
}
target_os = "macos" => {
pub mod macos;
pub(crate) use self::macos::*;
} else if #[cfg(target_os = "windows")] {
}
target_os = "windows" => {
pub mod windows;
pub use self::windows::*;
} else if #[cfg(target_os = "freebsd")] {
}
target_os = "freebsd" => {
pub mod freebsd;
pub(crate) use self::freebsd::*;
} else if #[cfg(unix)] {
}
unix => {
pub(crate) struct GenericProcessExt;
impl UnixProcessExt for GenericProcessExt {}
}
_ => {}
}
cfg_if! {
if #[cfg(unix)] {
cfg_select! {
unix => {
pub mod unix;
pub use self::unix::*;
}
_ => {}
}
use std::{sync::Arc, time::Duration};
use super::{DataCollector, error::CollectionResult};
cfg_if! {
if #[cfg(target_family = "windows")] {
cfg_select! {
target_family = "windows" => {
/// A Windows process ID.
pub type Pid = usize;
} else if #[cfg(unix)] {
}
unix => {
/// A UNIX process ID.
pub type Pid = libc::pid_t;
}
_ => {}
}
pub type Bytes = u64;
@@ -163,8 +170,8 @@ pub struct ProcessHarvest {
impl DataCollector {
pub(crate) fn get_processes(&mut self) -> CollectionResult<Vec<ProcessHarvest>> {
cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
let time_diff = self.data.collection_time
.duration_since(self.last_collection_time)
.as_secs();
@@ -173,9 +180,11 @@ impl DataCollector {
self,
time_diff,
)
} else if #[cfg(any(target_os = "freebsd", target_os = "macos", target_os = "windows", target_os = "android", target_os = "ios"))] {
}
any(target_os = "freebsd", target_os = "macos", target_os = "windows", target_os = "android", target_os = "ios") => {
sysinfo_process_data(self)
} else {
}
_ => {
Err(crate::collection::error::CollectionError::Unsupported)
}
}
@@ -184,8 +193,8 @@ impl DataCollector {
/// Pulled from [`ProcessStatus::to_string`] to avoid an alloc.
pub(super) fn process_status_str(status: ProcessStatus) -> &'static str {
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
match status {
ProcessStatus::Idle => "Idle",
ProcessStatus::Run => "Runnable",
@@ -200,12 +209,14 @@ pub(super) fn process_status_str(status: ProcessStatus) -> &'static str {
ProcessStatus::UninterruptibleDiskSleep => "UninterruptibleDiskSleep",
_ => "Unknown",
}
} else if #[cfg(target_os = "windows")] {
}
target_os = "windows" => {
match status {
ProcessStatus::Run => "Runnable",
_ => "Unknown",
}
} else if #[cfg(target_os = "macos")] {
}
target_os = "macos" => {
match status {
ProcessStatus::Idle => "Idle",
ProcessStatus::Run => "Runnable",
@@ -214,7 +225,8 @@ pub(super) fn process_status_str(status: ProcessStatus) -> &'static str {
ProcessStatus::Zombie => "Zombie",
_ => "Unknown",
}
} else if #[cfg(target_os = "freebsd")] {
}
target_os = "freebsd" => {
match status {
ProcessStatus::Idle => "Idle",
ProcessStatus::Run => "Runnable",
@@ -225,7 +237,8 @@ pub(super) fn process_status_str(status: ProcessStatus) -> &'static str {
ProcessStatus::LockBlocked => "LockBlocked",
_ => "Unknown",
}
} else {
}
_ => {
"Unknown"
}
}
+9 -7
View File
@@ -2,11 +2,10 @@
mod user_table;
use cfg_if::cfg_if;
pub use user_table::*;
cfg_if! {
if #[cfg(all(target_family = "unix", not(target_os = "linux")))] {
cfg_select! {
all(target_family = "unix", not(target_os = "linux")) => {
mod process_ext;
pub(crate) use process_ext::*;
@@ -22,16 +21,19 @@ cfg_if! {
let total_memory = collector.total_memory();
let user_table = &mut collector.user_table;
cfg_if! {
if #[cfg(target_os = "macos")] {
cfg_select! {
target_os = "macos" => {
MacOSProcessExt::sysinfo_process_data(sys, use_current_cpu_total, unnormalized_cpu, total_memory, user_table)
} else if #[cfg(target_os = "freebsd")] {
}
target_os = "freebsd" => {
FreeBSDProcessExt::sysinfo_process_data(sys, use_current_cpu_total, unnormalized_cpu, total_memory, user_table)
} else {
}
_ => {
GenericProcessExt::sysinfo_process_data(sys, use_current_cpu_total, unnormalized_cpu, total_memory, user_table)
}
}
}
}
_ => {}
}
+18 -13
View File
@@ -2,7 +2,6 @@
use std::{io, time::Duration};
use cfg_if::cfg_if;
use itertools::Itertools;
use sysinfo::{ProcessStatus, System};
@@ -17,26 +16,29 @@ use crate::{
fn get_nice(pid: Pid) -> i32 {
// SAFETY: getpriority takes no user pointers; pid is passed as a value
// and errors are reported via the return value.
cfg_if! {
if #[cfg(target_os = "freebsd")] {
cfg_select! {
target_os = "freebsd" => {
unsafe { libc::getpriority(libc::PRIO_PROCESS, pid) }
} else if #[cfg(target_os = "macos")] {
}
target_os = "macos" => {
unsafe { libc::getpriority(libc::PRIO_PROCESS, pid as u32) }
} else {
}
_ => {
0
}
}
}
fn get_priority(pid: Pid) -> i32 {
cfg_if! {
if #[cfg(target_os = "macos")] {
cfg_select! {
target_os = "macos" => {
if let Ok(kinfo) = sysctl_bindings::kinfo_process(pid) {
kinfo.kp_proc.p_priority as i32
} else {
0
}
} else if #[cfg(target_os = "freebsd")] {
}
target_os = "freebsd" => {
use libc::{c_int, c_void};
use std::{mem, ptr};
@@ -60,7 +62,8 @@ fn get_priority(pid: Pid) -> i32 {
};
if ret == 0 { kp.ki_pri.pri_level as i32 } else { 0 }
} else {
}
_ => {
0
}
}
@@ -204,8 +207,8 @@ pub(crate) trait UnixProcessExt {
fn convert_process_status_to_char(status: ProcessStatus) -> char {
// TODO: Based on https://github.com/GuillaumeGomez/sysinfo/blob/baa46efb46d82f21b773088603720262f4a34646/src/unix/freebsd/process.rs#L13?
cfg_if::cfg_if! {
if #[cfg(target_os = "macos")] {
cfg_select! {
target_os = "macos" => {
// SAFETY: These are all const and should be valid characters.
const SIDL: char = unsafe { char::from_u32_unchecked(libc::SIDL) };
@@ -229,7 +232,8 @@ fn convert_process_status_to_char(status: ProcessStatus) -> char {
ProcessStatus::Zombie => SZOMB,
_ => '?'
}
} else if #[cfg(target_os = "freebsd")] {
}
target_os = "freebsd" => {
const fn assert_u8(val: libc::c_char) -> u8 {
if val < 0 { panic!("there was an invalid i8 constant that is supposed to be a char") } else { val as u8 }
}
@@ -252,7 +256,8 @@ fn convert_process_status_to_char(status: ProcessStatus) -> char {
ProcessStatus::LockBlocked => SLOCK as char,
_ => '?'
}
} else {
}
_ => {
'?'
}
}
+4 -3
View File
@@ -3,11 +3,12 @@
//! For Linux, this is handled by custom code.
//! For everything else, this is handled by sysinfo.
cfg_if::cfg_if! {
if #[cfg(target_os = "linux")] {
cfg_select! {
target_os = "linux" => {
pub mod linux;
pub use self::linux::*;
} else {
}
_ => {
pub mod sysinfo;
pub use self::sysinfo::*;
}
+4
View File
@@ -628,6 +628,10 @@ pub(crate) const CONFIG_TEXT: &str = r#"# This is a default config file for bott
# Network widget configuration
#[network_graph]
# Whether to display packet rate and average packet size info. Defaults to false.
#show_packets = false
# By default, there are no network interface filters enabled. An example use case is provided below.
#[network_graph.interface_filter]
# Whether to ignore any matches. Defaults to true.