summaryrefslogtreecommitdiffstats
path: root/src/app
diff options
context:
space:
mode:
authorClement Tsang <34804052+ClementTsang@users.noreply.github.com>2021-04-22 23:43:12 -0400
committerGitHub <noreply@github.com>2021-04-22 23:43:12 -0400
commitf33bb42c5b234183117fa30d87b1fe6d9ab94d69 (patch)
tree8fc79336c49b39f412e3f2c6e5a46c53aa920943 /src/app
parentd9fd6be2ccad9d2eec888bd761cefc9ecbc16298 (diff)
feature: Add mount filtering, rework filter priority logic (#455)
This PR accomplishes two things: 1. This PR aims to add mount_filter to the config file. This allows a user to filter their disk widget entries by the mount name as well; this was particularly a problem in trying to address #431. 2. A slight rework of how the filter system works due to the need of being able to manage two potentially conflicting filter sources, since the disk widget will now potentially filter on both the disk name and the mount name. In regards to the second point, the new behaviour is as such: 1. Is the entry allowed through any filter? That is, does it match an entry in a filter where is_list_ignored is false? If so, we always keep this entry. 2. Is the entry denied through any filter? That is, does it match an entry in a filter where is_list_ignored is true? If so, we always deny this entry. 3. Anything else is allowed. This main (breaking) change is really the third point. This would mean that temp_filter and net_filter, when set to allow listed entries with is_list_ignored = false, are kinda... useless, as a whitelist in the scenario of being the only filter is kinda pointless. But hopefully this shouldn't be a problem...?
Diffstat (limited to 'src/app')
-rw-r--r--src/app/data_harvester.rs7
-rw-r--r--src/app/data_harvester/disks.rs53
-rw-r--r--src/app/data_harvester/network.rs16
-rw-r--r--src/app/data_harvester/temperature.rs49
4 files changed, 78 insertions, 47 deletions
diff --git a/src/app/data_harvester.rs b/src/app/data_harvester.rs
index 989fcf6c..65fc680f 100644
--- a/src/app/data_harvester.rs
+++ b/src/app/data_harvester.rs
@@ -325,8 +325,11 @@ impl DataCollector {
}
};
let mem_data_fut = mem::get_mem_data(self.widgets_to_harvest.use_mem);
- let disk_data_fut =
- disks::get_disk_usage(self.widgets_to_harvest.use_disk, &self.filters.disk_filter);
+ let disk_data_fut = disks::get_disk_usage(
+ self.widgets_to_harvest.use_disk,
+ &self.filters.disk_filter,
+ &self.filters.mount_filter,
+ );
let disk_io_usage_fut = disks::get_io_usage(self.widgets_to_harvest.use_disk);
let temp_data_fut = {
#[cfg(not(target_os = "linux"))]
diff --git a/src/app/data_harvester/disks.rs b/src/app/data_harvester/disks.rs
index ba1d2d49..103bb701 100644
--- a/src/app/data_harvester/disks.rs
+++ b/src/app/data_harvester/disks.rs
@@ -34,7 +34,6 @@ pub async fn get_io_usage(actually_get: bool) -> crate::utils::error::Result<Opt
if let Ok(io) = io {
let mount_point = io.device_name().to_str().unwrap_or("Name Unavailable");
- // FIXME: [MOUNT POINT] Add the filter here I guess?
io_hash.insert(
mount_point.to_string(),
Some(IoData {
@@ -49,7 +48,7 @@ pub async fn get_io_usage(actually_get: bool) -> crate::utils::error::Result<Opt
}
pub async fn get_disk_usage(
- actually_get: bool, name_filter: &Option<Filter>,
+ actually_get: bool, disk_filter: &Option<Filter>, mount_filter: &Option<Filter>,
) -> crate::utils::error::Result<Option<Vec<DiskHarvest>>> {
if !actually_get {
return Ok(None);
@@ -108,21 +107,53 @@ pub async fn get_disk_usage(
.unwrap_or("Name Unavailable"))
.to_string();
- let to_keep = if let Some(filter) = name_filter {
- let mut ret = filter.is_list_ignored;
- for r in &filter.list {
- if r.is_match(&name) {
- ret = !filter.is_list_ignored;
- break;
+ // Precedence ordering in the case where name and mount filters disagree, "allow" takes precedence over "deny".
+ //
+ // For implementation, we do this as follows:
+ // 1. Is the entry allowed through any filter? That is, does it match an entry in a filter where `is_list_ignored` is `false`? If so, we always keep this entry.
+ // 2. Is the entry denied through any filter? That is, does it match an entry in a filter where `is_list_ignored` is `true`? If so, we always deny this entry.
+ // 3. Anything else is allowed.
+
+ let filter_check_map = [(disk_filter, &name), (mount_filter, &mount_point)];
+
+ // This represents case 1. That is, if there is a match in an allowing list - if there is, then
+ // immediately allow it!
+ let matches_allow_list = filter_check_map.iter().any(|(filter, text)| {
+ if let Some(filter) = filter {
+ if !filter.is_list_ignored {
+ for r in &filter.list {
+ if r.is_match(text) {
+ return true;
+ }
+ }
}
}
- ret
- } else {
+ false
+ });
+
+ let to_keep = if matches_allow_list {
true
+ } else {
+ // If it doesn't match an allow list, then check if it is denied.
+ // That is, if it matches in a reject filter, then reject. Otherwise, we always keep it.
+ !filter_check_map.iter().any(|(filter, text)| {
+ if let Some(filter) = filter {
+ if filter.is_list_ignored {
+ for r in &filter.list {
+ if r.is_match(text) {
+ return true;
+ }
+ }
+ }
+ }
+ false
+ })
};
if to_keep {
- // The usage line fails in some cases (Void linux + LUKS, see https://github.com/ClementTsang/bottom/issues/419)
+ // The usage line can fail in some cases (for example, if you use Void Linux + LUKS,
+ // see https://github.com/ClementTsang/bottom/issues/419 for details). As such, check
+ // it like this instead.
if let Ok(usage) = heim::disk::usage(partition.mount_point().to_path_buf()).await {
vec_disks.push(DiskHarvest {
free_space: Some(usage.free().get::<heim::units::information::byte>()),
diff --git a/src/app/data_harvester/network.rs b/src/app/data_harvester/network.rs
index 52dc8468..650a68e3 100644
--- a/src/app/data_harvester/network.rs
+++ b/src/app/data_harvester/network.rs
@@ -94,14 +94,18 @@ pub async fn get_network_data(
while let Some(io) = io_data.next().await {
if let Ok(io) = io {
let to_keep = if let Some(filter) = filter {
- let mut ret = filter.is_list_ignored;
- for r in &filter.list {
- if r.is_match(&io.interface()) {
- ret = !filter.is_list_ignored;
- break;
+ if filter.is_list_ignored {
+ let mut ret = true;
+ for r in &filter.list {
+ if r.is_match(&io.interface()) {
+ ret = false;
+ break;
+ }
}
+ ret
+ } else {
+ true
}
- ret
} else {
true
};
diff --git a/src/app/data_harvester/temperature.rs b/src/app/data_harvester/temperature.rs
index 3786adc7..eb3c2f6f 100644
--- a/src/app/data_harvester/temperature.rs
+++ b/src/app/data_harvester/temperature.rs
@@ -21,6 +21,25 @@ impl Default for TemperatureType {
}
}
+fn is_temp_filtered(filter: &Option<Filter>, text: &str) -> bool {
+ if let Some(filter) = filter {
+ if filter.is_list_ignored {
+ let mut ret = true;
+ for r in &filter.list {
+ if r.is_match(text) {
+ ret = false;
+ break;
+ }
+ }
+ ret
+ } else {
+ true
+ }
+ } else {
+ true
+ }
+}
+
#[cfg(not(target_os = "linux"))]
pub async fn get_temperature_data(
sys: &sysinfo::System, temp_type: &TemperatureType, actually_get: bool, filter: &Option<Filter>,
@@ -45,20 +64,7 @@ pub async fn get_temperature_data(
for component in sensor_data {
let name = component.get_label().to_string();
- let to_keep = if let Some(filter) = filter {
- let mut ret = filter.is_list_ignored;
- for r in &filter.list {
- if r.is_match(&name) {
- ret = !filter.is_list_ignored;
- break;
- }
- }
- ret
- } else {
- true
- };
-
- if to_keep {
+ if is_temp_filtered(filter, &name) {
temperature_vec.push(TempHarvest {
name,
temperature: match temp_type {
@@ -104,20 +110,7 @@ pub async fn get_temperature_data(
(None, None) => String::default(),
};
- let to_keep = if let Some(filter) = filter {
- let mut ret = filter.is_list_ignored;
- for r in &filter.list {
- if r.is_match(&name) {
- ret = !filter.is_list_ignored;
- break;
- }
- }
- ret
- } else {
- true
- };
-
- if to_keep {
+ if is_temp_filtered(filter, &name) {
temperature_vec.push(TempHarvest {
name,
temperature: match temp_type {