Working on partitions stuff related to issue #2
This commit is contained in:
@@ -0,0 +1,302 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
pub fn format_bytes_size(size: u64) -> String {
|
||||||
|
let suffixs: [&str; 5] = ["KB", "MB", "GB", "TB", "PB"];
|
||||||
|
|
||||||
|
if size < 1000 {
|
||||||
|
format!("{}B", size)
|
||||||
|
} else {
|
||||||
|
let mut s = size as f64;
|
||||||
|
let mut idx = 0;
|
||||||
|
for i in 0..5 {
|
||||||
|
s = s / 1024.0;
|
||||||
|
idx = i;
|
||||||
|
if s < 1000.0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
format!("{:.2}{}", s, suffixs[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// size - device size in bytes
|
||||||
|
/// sector size - default 4096
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct BlkDev {
|
||||||
|
name: String,
|
||||||
|
size: u64,
|
||||||
|
sector_size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for BlkDev {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} ({})", &self.name, format_bytes_size(self.size))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BlkDev {
|
||||||
|
pub fn new(name: String, size: u64) -> Self {
|
||||||
|
Self {
|
||||||
|
name: name,
|
||||||
|
size: size,
|
||||||
|
sector_size: 4096,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum FSType {
|
||||||
|
VFAT,
|
||||||
|
XFS,
|
||||||
|
LUKS,
|
||||||
|
SWAP,
|
||||||
|
EXT4,
|
||||||
|
BTRFS,
|
||||||
|
BCACHEFS,
|
||||||
|
UNKNOWN,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for FSType {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::VFAT => write!(f, "vfat"),
|
||||||
|
Self::XFS => write!(f, "xfs"),
|
||||||
|
Self::LUKS => write!(f, "luks"),
|
||||||
|
Self::SWAP => write!(f, "swap"),
|
||||||
|
Self::EXT4 => write!(f, "ext4"),
|
||||||
|
Self::BTRFS => write!(f, "btrfs"),
|
||||||
|
Self::BCACHEFS => write!(f, "bcachefs"),
|
||||||
|
Self::UNKNOWN => write!(f, "unknown"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FSType {
|
||||||
|
pub fn from_str(s: &str) -> Self {
|
||||||
|
let s_low = s.to_lowercase();
|
||||||
|
match s_low.as_str() {
|
||||||
|
"vfat" => Self::VFAT,
|
||||||
|
"xfs" => Self::XFS,
|
||||||
|
"crypto_luks" => Self::LUKS,
|
||||||
|
"swap" => Self::SWAP,
|
||||||
|
"ext4" => Self::EXT4,
|
||||||
|
"btrfs" => Self::BTRFS,
|
||||||
|
"bcachefs" => Self::BCACHEFS,
|
||||||
|
_ => Self::UNKNOWN,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn part_type_to_color(t: &str) -> Color {
|
||||||
|
// match t {
|
||||||
|
// "vfat" => Color::from_rgb8(204, 121, 167),
|
||||||
|
// "xfs" => Color::from_rgb8(0, 158, 115),
|
||||||
|
// "crypto_LUKS" => Color::from_rgb8(240, 228, 66),
|
||||||
|
// "swap" => Color::from_rgb8(213, 94, 0),
|
||||||
|
// "ext4" => Color::from_rgb8(0, 114, 178),
|
||||||
|
// "btrfs" => Color::from_rgb8(86, 180, 233),
|
||||||
|
// _ => Color::from_rgb8(230, 159, 0),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub struct PartInfo {
|
||||||
|
name: String,
|
||||||
|
size: u64,
|
||||||
|
fs_type: FSType,
|
||||||
|
gpt_label: Option<String>,
|
||||||
|
fs_label: Option<String>,
|
||||||
|
mount_point: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for PartInfo {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{} {} {}",
|
||||||
|
&self.name,
|
||||||
|
&self.fs_type,
|
||||||
|
format_bytes_size(self.size)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartInfo {
|
||||||
|
pub fn from_hash_map(data: &HashMap<String, String>) -> Option<Self> {
|
||||||
|
Some(Self {
|
||||||
|
name: data.get("NAME")?.clone(),
|
||||||
|
size: u64::from_str_radix(data.get("SIZE")?, 10).ok()?,
|
||||||
|
fs_type: FSType::from_str(data.get("FSTYPE")?),
|
||||||
|
gpt_label: data
|
||||||
|
.get("PARTLABEL")
|
||||||
|
.and_then(|v| if v.is_empty() { None } else { Some(v.clone()) }),
|
||||||
|
fs_label: data
|
||||||
|
.get("LABEL")
|
||||||
|
.and_then(|v| if v.is_empty() { None } else { Some(v.clone()) }),
|
||||||
|
mount_point: data
|
||||||
|
.get("MOUNTPOINT")
|
||||||
|
.and_then(|v| if v.is_empty() { None } else { Some(v.clone()) }),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getting list of device partitions
|
||||||
|
fn get_dev_part_blocking(dev_name: &str) -> Result<Vec<PartInfo>, String> {
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
//"lsblk -o NAME,SIZE,FSTYPE -l -n /dev/nvme0n1"
|
||||||
|
// lsblk -o NAME,SIZE,FSTYPE,TYPE,PARTLABEL,LABEL,PARTFLAGS -b -P
|
||||||
|
|
||||||
|
match Command::new("lsblk")
|
||||||
|
.args([
|
||||||
|
"-o",
|
||||||
|
"NAME,SIZE,FSTYPE,TYPE,PARTLABEL,LABEL,MOUNTPOINT,PARTFLAGS",
|
||||||
|
"-b",
|
||||||
|
"-P",
|
||||||
|
format!("/dev/{}", dev_name).as_str(),
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
Ok(cmd_output) => {
|
||||||
|
if cmd_output.status.success() {
|
||||||
|
match String::from_utf8(cmd_output.stdout) {
|
||||||
|
Ok(raw_str_list) => Ok(raw_str_list
|
||||||
|
.lines()
|
||||||
|
.map(|l| {
|
||||||
|
l.split_whitespace()
|
||||||
|
.filter_map(|pair| {
|
||||||
|
pair.split_once("=").and_then(|kv| {
|
||||||
|
Some((
|
||||||
|
kv.0.trim_matches('"').to_string(),
|
||||||
|
kv.1.trim_matches('"').to_string(),
|
||||||
|
))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect::<HashMap<String, String>>()
|
||||||
|
})
|
||||||
|
.filter(|mp| mp.get("TYPE").is_some_and(|v| v == "part"))
|
||||||
|
.filter_map(|mp| PartInfo::from_hash_map(&mp))
|
||||||
|
.collect()),
|
||||||
|
Err(ex) => Err(format!(
|
||||||
|
"Exception while converting partition info to UTF8 {}",
|
||||||
|
ex
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Err(format!(
|
||||||
|
"Error getting device partitions list: {}",
|
||||||
|
String::from_utf8(cmd_output.stderr).unwrap_or("UNKNOWN".into())
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(ex) => Err(ex.to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// size - size in bytes
|
||||||
|
/// start - start byte of partition, inclusive index.
|
||||||
|
/// returns tuple of aligned size, start index, and end index
|
||||||
|
/// return none if aligment is not possibe (size of partition is less than align)
|
||||||
|
pub fn align_part(size: u64, start: u64, align: u64) -> Option<(u64, u64, u64)> {
|
||||||
|
if size < align {
|
||||||
|
println!("if size < align !!!!!!!");
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let start_mod = start % align;
|
||||||
|
// increasing start if not align
|
||||||
|
let align_start = if start_mod > 0 {
|
||||||
|
start + (align - start_mod)
|
||||||
|
} else {
|
||||||
|
start
|
||||||
|
};
|
||||||
|
|
||||||
|
// decreasing end if not align
|
||||||
|
let part_end = align_start + size;
|
||||||
|
let end_mod = part_end % align;
|
||||||
|
println!("part_end: {} end_mod: {}", part_end, end_mod);
|
||||||
|
let align_end = part_end - end_mod - 1;
|
||||||
|
|
||||||
|
let align_size = align_end - align_start + 1;
|
||||||
|
|
||||||
|
if align_size < align {
|
||||||
|
println!("if align_size < align !!!!!!! align_size: {} align: {}",align_size,align);
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some((align_size, align_start, align_end))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PartLayout {
|
||||||
|
dev: BlkDev,
|
||||||
|
empty_space: u64,
|
||||||
|
part_list: Vec<PartInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartLayout {
|
||||||
|
pub fn new(dev: BlkDev) -> Self {
|
||||||
|
Self {
|
||||||
|
empty_space: dev.size,
|
||||||
|
dev: dev,
|
||||||
|
part_list: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn read_from_dev(dev: &BlkDev) -> Result<Self, String> {
|
||||||
|
let part_list = get_dev_part_blocking(&dev.name)?;
|
||||||
|
let parts_size = part_list.iter().fold(0, |acc, part| acc + part.size);
|
||||||
|
Ok(Self {
|
||||||
|
dev: dev.clone(),
|
||||||
|
empty_space: dev.size - parts_size,
|
||||||
|
part_list: part_list,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_table(mut self) -> Self {
|
||||||
|
self.empty_space = self.dev.size;
|
||||||
|
self.part_list = Vec::new();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_part(
|
||||||
|
mut self,
|
||||||
|
part_size: u64,
|
||||||
|
fs_type: FSType,
|
||||||
|
gpt_label: Option<String>,
|
||||||
|
fs_label: Option<String>,
|
||||||
|
mount_point: Option<String>,
|
||||||
|
) -> Self {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_align_part_fn() {
|
||||||
|
//START (S),SIZE (Z),ALIGNMENT (A),ALIGNED_START (Salign),ALIGNED_END (Ealign),Effektive Größe (Zalign)
|
||||||
|
let joes_test_data: Vec<(u64, u64, u64, u64, u64, u64)> = vec![
|
||||||
|
(0, 10000, 4096, 0, 8191, 8192),
|
||||||
|
(5000, 20000, 4096, 8192, 24575, 16384),
|
||||||
|
(4096, 4096, 4096, 4096, 8191, 4096),
|
||||||
|
(1000000, 5000000, 1048576, 1048576, 5242879, 4194304),
|
||||||
|
(2097152, 1050000, 1048576, 2097152, 3145727, 1048576),
|
||||||
|
];
|
||||||
|
for test_data in joes_test_data {
|
||||||
|
let res = align_part(test_data.1,test_data.0,test_data.2).unwrap();
|
||||||
|
let test_res = (test_data.5, test_data.3, test_data.4);
|
||||||
|
assert_eq!(res, test_res);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// fn add_part(part_list: Vec<PartInfo>, rem_size: u64, part_t: PartType, )
|
||||||
|
|
||||||
|
// fn gen_layout(dev: &BlkDev, swap_size: u64) -> Vec<PartInfo> {
|
||||||
|
|
||||||
|
// Vec::new()
|
||||||
|
// }
|
||||||
@@ -35,6 +35,7 @@ rust_i18n::i18n!("src/locales", fallback = "en");
|
|||||||
mod kira_theming;
|
mod kira_theming;
|
||||||
mod kira_scroll_list;
|
mod kira_scroll_list;
|
||||||
mod kira_color_bar;
|
mod kira_color_bar;
|
||||||
|
mod kira_disk_layout;
|
||||||
mod stage;
|
mod stage;
|
||||||
mod stages;
|
mod stages;
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::kira_scroll_list::{self, ListViewMessage};
|
use crate::kira_scroll_list::{self, ListViewMessage};
|
||||||
use crate::stage::{ConfigValue, StageAction, StageResult};
|
use crate::stage::{StageAction, StageResult};
|
||||||
use iced::{Alignment, Length, widget};
|
use iced::{Alignment, Length, widget};
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
use iced::{Alignment, Task, widget};
|
use iced::{Alignment, Task, widget};
|
||||||
use iced_moving_picture::widget::apng;
|
use iced_moving_picture::widget::apng;
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
use std::collections::HashMap;
|
|
||||||
use toml::Table;
|
use toml::Table;
|
||||||
|
|
||||||
use crate::stage;
|
use crate::stage;
|
||||||
|
|||||||
@@ -18,12 +18,11 @@
|
|||||||
This is partition stage!
|
This is partition stage!
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::stage::{ConfigValue, StageAction, StageResult};
|
use crate::stage::{StageAction, StageResult};
|
||||||
|
|
||||||
use crate::kira_color_bar;
|
use crate::kira_color_bar;
|
||||||
use iced::{Alignment, Color, Length, widget};
|
use iced::{Alignment, Color, Length, widget};
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum SwapMode {
|
pub enum SwapMode {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
This is TimeZone stage, used to select timezone
|
This is TimeZone stage, used to select timezone
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::stage::{ConfigValue, StageAction, StageResult};
|
use crate::stage::{StageAction, StageResult};
|
||||||
use iced::{Alignment, Length, widget};
|
use iced::{Alignment, Length, widget};
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|||||||
@@ -20,10 +20,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
use crate::{stage::{ConfigValue, StageAction, StageResult}, kira_theming};
|
use crate::{stage::{StageAction, StageResult}, kira_theming};
|
||||||
use iced::{Alignment, widget};
|
use iced::{Alignment, widget};
|
||||||
use rust_i18n::t;
|
use rust_i18n::t;
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct LocData {
|
pub struct LocData {
|
||||||
|
|||||||
Reference in New Issue
Block a user