diff options
-rw-r--r-- | .vscode/settings.json | 1 | ||||
-rw-r--r-- | CHANGELOG.md | 2 | ||||
-rw-r--r-- | src/app/data_harvester/disks.rs | 75 | ||||
-rw-r--r-- | src/data_conversion.rs | 38 |
4 files changed, 88 insertions, 28 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json index 2c88c1a2..a04896e8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -18,6 +18,7 @@ "GIGA", "Hamberg", "KIBI", + "LUKS", "Lukas", "MEBI", "MEBIBYTE", diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b1ca437..3176e72b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#417](https://github.com/ClementTsang/bottom/pull/417): Fixes the sort menu and sort shortcuts not syncing up. +- [#423](https://github.com/ClementTsang/bottom/pull/423): Fixes disk encryption causing the disk widget to fail or not properly map I/O statistics. + ## [0.5.7] - 2021-01-30 ## Bug Fixes diff --git a/src/app/data_harvester/disks.rs b/src/app/data_harvester/disks.rs index 5a67a909..246f5b5d 100644 --- a/src/app/data_harvester/disks.rs +++ b/src/app/data_harvester/disks.rs @@ -4,9 +4,9 @@ use crate::app::Filter; pub struct DiskHarvest { pub name: String, pub mount_point: String, - pub free_space: u64, - pub used_space: u64, - pub total_space: u64, + pub free_space: Option<u64>, + pub used_space: Option<u64>, + pub total_space: Option<u64>, } #[derive(Clone, Debug)] @@ -35,7 +35,6 @@ pub async fn get_io_usage(actually_get: bool) -> crate::utils::error::Result<Opt 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 { @@ -64,11 +63,43 @@ pub async fn get_disk_usage( while let Some(part) = partitions_stream.next().await { if let Ok(partition) = part { - let name = (partition - .device() - .unwrap_or_else(|| std::ffi::OsStr::new("Name Unavailable")) - .to_str() - .unwrap_or("Name Unavailable")) + let symlink: std::ffi::OsString; + + let name = (if let Some(device) = partition.device() { + // See if this disk is actually mounted elsewhere on Linux... + // This is a workaround to properly map I/O in some cases (i.e. disk encryption), see + // https://github.com/ClementTsang/bottom/issues/419 + if cfg!(target_os = "linux") { + if let Ok(path) = std::fs::read_link(device) { + if path.is_absolute() { + symlink = path.into_os_string(); + symlink.as_os_str() + } else { + let mut combined_path = std::path::PathBuf::new(); + combined_path.push(device); + combined_path.pop(); // Pop the current file... + combined_path.push(path.clone()); + + if let Ok(path) = std::fs::canonicalize(combined_path) { + // Resolve the local path into an absolute one... + symlink = path.into_os_string(); + symlink.as_os_str() + } else { + symlink = path.into_os_string(); + symlink.as_os_str() + } + } + } else { + device + } + } else { + device + } + } else { + std::ffi::OsStr::new("Name Unavailable") + } + .to_str() + .unwrap_or("Name Unavailable")) .to_string(); let mount_point = (partition @@ -91,14 +122,24 @@ pub async fn get_disk_usage( }; if to_keep { - let usage = heim::disk::usage(partition.mount_point().to_path_buf()).await?; - vec_disks.push(DiskHarvest { - free_space: usage.free().get::<heim::units::information::byte>(), - used_space: usage.used().get::<heim::units::information::byte>(), - total_space: usage.total().get::<heim::units::information::byte>(), - mount_point, - name, - }); + // The usage line fails in some cases (Void linux + LUKS, see https://github.com/ClementTsang/bottom/issues/419) + 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>()), + used_space: Some(usage.used().get::<heim::units::information::byte>()), + total_space: Some(usage.total().get::<heim::units::information::byte>()), + mount_point, + name, + }); + } else { + vec_disks.push(DiskHarvest { + free_space: None, + used_space: None, + total_space: None, + mount_point, + name, + }); + } } } } diff --git a/src/data_conversion.rs b/src/data_conversion.rs index 57698b7f..b3614cf1 100644 --- a/src/data_conversion.rs +++ b/src/data_conversion.rs @@ -116,20 +116,36 @@ pub fn convert_disk_row(current_data: &data_farmer::DataCollection) -> Vec<Vec<S .iter() .zip(¤t_data.io_labels) .for_each(|(disk, (io_read, io_write))| { - let converted_free_space = get_simple_byte_values(disk.free_space, false); - let converted_total_space = get_simple_byte_values(disk.total_space, false); - disk_vector.push(vec![ - disk.name.to_string(), - disk.mount_point.to_string(), - format!( - "{:.0}%", - disk.used_space as f64 / disk.total_space as f64 * 100_f64 - ), - format!("{:.*}{}", 0, converted_free_space.0, converted_free_space.1), + let free_space_fmt = if let Some(free_space) = disk.free_space { + let converted_free_space = get_simple_byte_values(free_space, false); + format!("{:.*}{}", 0, converted_free_space.0, converted_free_space.1) + } else { + "N/A".to_string() + }; + let total_space_fmt = if let Some(total_space) = disk.total_space { + let converted_total_space = get_simple_byte_values(total_space, false); format!( "{:.*}{}", 0, converted_total_space.0, converted_total_space.1 - ), + ) + } else { + "N/A".to_string() + }; + + let usage_fmt = if let (Some(used_space), Some(total_space)) = + (disk.used_space, disk.total_space) + { + format!("{:.0}%", used_space as f64 / total_space as f64 * 100_f64) + } else { + "N/A".to_string() + }; + + disk_vector.push(vec![ + disk.name.to_string(), + disk.mount_point.to_string(), + usage_fmt, + free_space_fmt, + total_space_fmt, io_read.to_string(), io_write.to_string(), ]); |