Add luks support

This commit is contained in:
Ward from fusion-voyager-3 2024-08-19 23:42:36 +03:00
parent 907a7f1498
commit d84f14ea6d
6 changed files with 285 additions and 49 deletions

View File

@ -36,6 +36,16 @@ then
fi fi
fi fi
if [[ "$1" = "get_part_uuid" ]]
then
echo "$(blkid /dev/$2 -s UUID -o value)"
fi
if [[ "$1" = "get_luks_uuid" ]]
then
echo "$(blkid "$(lsblk -sJp | jq -r --arg dsk /dev/"$2" '.blockdevices | .[] | select(.name == $dsk) | .children | .[0] | .name')" -s UUID -o value)"
fi
if [[ "$1" = "get_partitions" ]] if [[ "$1" = "get_partitions" ]]
then then
lsblk -ln -o NAME,TYPE | grep -E "part|crypt|lvm" | awk '{print $1}' | while read i ; do lsblk -ln -o NAME,TYPE | grep -E "part|crypt|lvm" | awk '{print $1}' | while read i ; do

View File

@ -100,6 +100,7 @@ pub fn build_ui(app: &adw::Application) {
partitioning_page::partitioning_page( partitioning_page::partitioning_page(
&carousel, &carousel,
window.clone(),
&partition_method_type_refcell, &partition_method_type_refcell,
&partition_method_automatic_target_refcell, &partition_method_automatic_target_refcell,
&partition_method_automatic_target_fs_refcell, &partition_method_automatic_target_fs_refcell,

View File

@ -3,6 +3,7 @@ mod imp;
use glib::Object; use glib::Object;
use gtk::glib; use gtk::glib;
use crate::partitioning_page::create_parition_struct;
use crate::partitioning_page::FstabEntry; use crate::partitioning_page::FstabEntry;
glib::wrapper! { glib::wrapper! {
@ -22,7 +23,7 @@ impl DriveMountRow {
} }
pub fn get_fstab_entry(&self) -> FstabEntry { pub fn get_fstab_entry(&self) -> FstabEntry {
FstabEntry { FstabEntry {
partition: self.partition(), partition: create_parition_struct(&self.partition()),
mountpoint: self.mountpoint(), mountpoint: self.mountpoint(),
mountopts: self.mountopts(), mountopts: self.mountopts(),
} }

View File

@ -1,16 +1,19 @@
use crate::drive_mount_row::DriveMountRow; use crate::drive_mount_row::DriveMountRow;
use crate::installer_stack_page; use crate::installer_stack_page;
use crate::partitioning_page;
use crate::partitioning_page::{get_partitions, CrypttabEntry, FstabEntry, Partition}; use crate::partitioning_page::{get_partitions, CrypttabEntry, FstabEntry, Partition};
use adw::gio; use adw::gio;
use adw::prelude::*; use adw::prelude::*;
use glib::{clone, closure_local, ffi::gboolean}; use glib::{clone, closure_local, ffi::gboolean};
use gtk::{glib, prelude::*, Orientation}; use gtk::{glib, prelude::*, Orientation};
use std::{cell::RefCell, rc::Rc}; use std::{cell::RefCell, collections::HashSet, rc::Rc};
use crate::partitioning_page::get_luks_uuid;
mod func; mod func;
pub fn manual_partitioning_page( pub fn manual_partitioning_page(
partition_carousel: &adw::Carousel, partition_carousel: &adw::Carousel,
window: adw::ApplicationWindow,
partition_method_type_refcell: &Rc<RefCell<String>>, partition_method_type_refcell: &Rc<RefCell<String>>,
partition_method_manual_fstab_entry_array_refcell: &Rc<RefCell<Vec<FstabEntry>>>, partition_method_manual_fstab_entry_array_refcell: &Rc<RefCell<Vec<FstabEntry>>>,
partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>, partition_method_manual_luks_enabled_refcell: &Rc<RefCell<bool>>,
@ -104,15 +107,13 @@ pub fn manual_partitioning_page(
open_disk_utility_button.connect_clicked(clone!( open_disk_utility_button.connect_clicked(clone!(
#[weak] #[weak]
filesystem_table_refresh_button, filesystem_table_refresh_button,
move |_| move |_| {
{
let command = std::process::Command::new("blivet-gui").status(); let command = std::process::Command::new("blivet-gui").status();
if command.unwrap().success() { if command.unwrap().success() {
filesystem_table_refresh_button.emit_by_name("clicked", &[]) filesystem_table_refresh_button.emit_by_name("clicked", &[])
} }
} }
) ));
);
filesystem_table_refresh_button.connect_clicked(clone!( filesystem_table_refresh_button.connect_clicked(clone!(
#[weak] #[weak]
@ -135,8 +136,7 @@ pub fn manual_partitioning_page(
partition_method_manual_luks_enabled_refcell, partition_method_manual_luks_enabled_refcell,
#[strong] #[strong]
partition_method_manual_crypttab_entry_array_refcell, partition_method_manual_crypttab_entry_array_refcell,
move |_| move |_| {
{
while let Some(row) = drive_mounts_adw_listbox.last_child() { while let Some(row) = drive_mounts_adw_listbox.last_child() {
drive_mounts_adw_listbox.remove(&row); drive_mounts_adw_listbox.remove(&row);
} }
@ -156,8 +156,155 @@ pub fn manual_partitioning_page(
&subvol_partition_array_refcell, &subvol_partition_array_refcell,
); );
} }
));
filesystem_table_validate_button.connect_clicked(clone!(
#[weak]
drive_mounts_adw_listbox,
#[strong]
window,
#[strong]
partition_method_manual_fstab_entry_array_refcell,
#[strong]
partition_method_manual_luks_enabled_refcell,
#[strong]
partition_method_manual_crypttab_entry_array_refcell,
move |_| {
let mut errored = false;
(*partition_method_manual_fstab_entry_array_refcell.borrow_mut()) = Vec::new();
(*partition_method_manual_luks_enabled_refcell.borrow_mut()) = false;
(*partition_method_manual_crypttab_entry_array_refcell.borrow_mut()) = Vec::new();
let mut seen_mountpoints = HashSet::new();
for fs_entry in generate_filesystem_table_array(&drive_mounts_adw_listbox) {
let fs_entry_clone0 = fs_entry.clone();
if fs_entry.mountpoint.is_empty() {
errored = true;
println!("mountpoint empty");
break;
}
if fs_entry.mountpoint != "[SWAP]"
|| !fs_entry.mountpoint.starts_with("/")
|| fs_entry.mountpoint.starts_with("/dev")
{
errored = true;
println!("mountpoint invalid");
//break;
}
if fs_entry.partition.part_name.is_empty() {
errored = true;
println!("partition empty");
//break;
}
if !seen_mountpoints.insert(fs_entry.clone().mountpoint) {
errored = true;
println!("duplicate found");
//break;
}
//
(*partition_method_manual_fstab_entry_array_refcell.borrow_mut()).push(fs_entry);
//
if fs_entry_clone0.partition.has_encryption
&& !partition_method_manual_crypttab_entry_array_refcell
.borrow()
.iter()
.any(|x| x.partition == fs_entry_clone0.partition.part_name)
{
let fs_entry = fs_entry_clone0.clone();
let (luks_manual_password_sender, luks_manual_password_receiver) =
async_channel::unbounded::<bool>();
let crypttab_password_listbox = gtk::ListBox::builder()
.margin_top(10)
.margin_bottom(10)
.margin_start(10)
.margin_end(10)
.build();
crypttab_password_listbox.add_css_class("boxed-list");
let crypttab_password = adw::PasswordEntryRow::builder()
.title(t!("luks_password_for").to_string() + &fs_entry.partition.part_name)
.build();
crypttab_password.set_show_apply_button(true);
crypttab_password_listbox.append(&crypttab_password);
let crypttab_dialog = adw::MessageDialog::builder()
.transient_for(&window)
.hide_on_close(true)
.extra_child(&crypttab_password_listbox)
.width_request(400)
.height_request(200)
.heading(
t!("luks_how_should").to_string()
+ &fs_entry.partition.part_name
+ &t!("be_added_crypttab"),
) )
.build();
crypttab_dialog
.add_response("crypttab_dialog_boot", &t!("unlock_boot_manually"));
crypttab_dialog.add_response("crypttab_dialog_auto", &t!("unlock_boot_manual"));
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", false);
crypttab_password.connect_apply(clone!(
#[weak]
crypttab_password,
#[strong]
fs_entry,
#[weak]
crypttab_dialog,
move |_| {
let luks_manual_password_sender = luks_manual_password_sender.clone();
let luks_password = crypttab_password.text().to_string();
let fs_entry_clone1 = fs_entry.clone();
std::thread::spawn(move || {
luks_manual_password_sender
.send_blocking(partitioning_page::test_luks_passwd(
&fs_entry_clone1.partition.part_name,
&luks_password,
))
.expect("The channel needs to be open.");
});
}
));
let luks_manual_password_main_context = glib::MainContext::default();
// The main loop executes the asynchronous block
luks_manual_password_main_context.spawn_local(clone!(
#[weak]
crypttab_dialog,
async move {
while let Ok(state) = luks_manual_password_receiver.recv().await {
crypttab_dialog.set_response_enabled("crypttab_dialog_auto", state);
}
}
));
let partition_method_manual_crypttab_entry_array_refcell_clone0 = partition_method_manual_crypttab_entry_array_refcell.clone();
crypttab_dialog.choose(None::<&gio::Cancellable>,
move |choice|
{
let part_name = fs_entry.partition.part_name;
if choice == "crypttab_dialog_auto" {
(*partition_method_manual_crypttab_entry_array_refcell_clone0.borrow_mut()).push(CrypttabEntry{
partition: part_name.clone(),
map: part_name.replace("mapper/", ""),
uuid: get_luks_uuid(&part_name),
password: None,
});
} else {
(*partition_method_manual_crypttab_entry_array_refcell_clone0.borrow_mut()).push(CrypttabEntry{
partition: part_name.clone(),
map: part_name.replace("mapper/", ""),
uuid: get_luks_uuid(&part_name),
password: Some(crypttab_password.text().to_string()),
});
}
}
); );
}
}
}
));
content_box.append(&drive_mounts_viewport); content_box.append(&drive_mounts_viewport);
content_box.append(&utility_buttons_box); content_box.append(&utility_buttons_box);
@ -310,3 +457,18 @@ fn create_hardcoded_rows(
} }
)); ));
} }
fn generate_filesystem_table_array(drive_mounts_adw_listbox: &gtk::ListBox) -> Vec<FstabEntry> {
let mut fstab_array: Vec<FstabEntry> = Vec::new();
let mut widget_counter = drive_mounts_adw_listbox.first_child();
while let Some(ref child) = widget_counter {
match child.clone().downcast::<DriveMountRow>() {
Ok(t) => {
fstab_array.push(DriveMountRow::get_fstab_entry(&t));
}
Err(_) => {}
}
widget_counter = child.next_sibling();
}
fstab_array
}

View File

@ -8,6 +8,7 @@ use std::{cell::RefCell, rc::Rc};
pub fn partitioning_page( pub fn partitioning_page(
main_carousel: &adw::Carousel, main_carousel: &adw::Carousel,
window: adw::ApplicationWindow,
partition_method_type_refcell: &Rc<RefCell<String>>, partition_method_type_refcell: &Rc<RefCell<String>>,
partition_method_automatic_target_refcell: &Rc<RefCell<String>>, partition_method_automatic_target_refcell: &Rc<RefCell<String>>,
partition_method_automatic_target_fs_refcell: &Rc<RefCell<String>>, partition_method_automatic_target_fs_refcell: &Rc<RefCell<String>>,
@ -145,6 +146,7 @@ pub fn partitioning_page(
); );
manual_partitioning_page::manual_partitioning_page( manual_partitioning_page::manual_partitioning_page(
&partitioning_carousel, &partitioning_carousel,
window,
&partition_method_type_refcell, &partition_method_type_refcell,
&partition_method_manual_fstab_entry_array_refcell, &partition_method_manual_fstab_entry_array_refcell,
&partition_method_manual_luks_enabled_refcell, &partition_method_manual_luks_enabled_refcell,
@ -173,24 +175,26 @@ pub struct BlockDevice {
pub block_size_pretty: String, pub block_size_pretty: String,
} }
#[derive(Clone)] #[derive(Clone, Default)]
pub struct Partition { pub struct Partition {
pub part_name: String, pub part_name: String,
pub part_fs: String, pub part_fs: String,
pub part_uuid: String,
pub has_encryption: bool, pub has_encryption: bool,
pub need_mapper: bool, pub need_mapper: bool,
pub part_size: f64, pub part_size: f64,
pub part_size_pretty: String, pub part_size_pretty: String,
} }
#[derive(Default)] #[derive(Default, Clone)]
pub struct FstabEntry { pub struct FstabEntry {
pub partition: String, pub partition: Partition,
pub mountpoint: String, pub mountpoint: String,
pub mountopts: String, pub mountopts: String,
} }
pub struct CrypttabEntry { pub struct CrypttabEntry {
pub partition: String,
pub map: String, pub map: String,
pub uuid: String, pub uuid: String,
pub password: Option<String>, pub password: Option<String>,
@ -268,18 +272,7 @@ pub fn get_partitions() -> Vec<Partition> {
Some(t) => { Some(t) => {
for partition in std::io::BufReader::new(t).lines() { for partition in std::io::BufReader::new(t).lines() {
match partition { match partition {
Ok(r) => { Ok(r) => partitions.push(create_parition_struct(&r)),
let part_size = get_part_size(&r);
let part_fs = get_part_fs(&r);
partitions.push(Partition {
has_encryption: is_encrypted(&r),
need_mapper: is_needs_mapper(&part_fs),
part_name: r,
part_fs: part_fs,
part_size: part_size,
part_size_pretty: pretty_bytes::converter::convert(part_size),
})
}
Err(_) => return partitions, Err(_) => return partitions,
} }
} }
@ -290,6 +283,20 @@ pub fn get_partitions() -> Vec<Partition> {
partitions partitions
} }
pub fn create_parition_struct(part_dev: &str) -> Partition {
let part_size = get_part_size(&part_dev);
let part_fs = get_part_fs(&part_dev);
Partition {
has_encryption: is_encrypted(&part_dev),
need_mapper: is_needs_mapper(&part_fs),
part_uuid: get_part_uuid(&part_dev),
part_name: part_dev.to_string(),
part_fs: part_fs,
part_size: part_size,
part_size_pretty: pretty_bytes::converter::convert(part_size),
}
}
fn get_part_size(part_dev: &str) -> f64 { fn get_part_size(part_dev: &str) -> f64 {
let command = match std::process::Command::new("sudo") let command = match std::process::Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh") .arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
@ -351,3 +358,58 @@ fn is_encrypted(part_dev: &str) -> bool {
false false
} }
} }
pub fn test_luks_passwd(part_dev: &str, passwd: &str) -> bool {
let command = match std::process::Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("test_luks_passwd")
.arg(part_dev)
.arg(passwd)
.output()
{
Ok(t) => t,
Err(_) => return false,
};
if command.status.success() {
true
} else {
false
}
}
fn get_part_uuid(part_dev: &str) -> String {
let command = match std::process::Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_part_uuid")
.arg(part_dev)
.output()
{
Ok(t) => t,
Err(_) => return String::from(""),
};
let fs = match String::from_utf8(command.stdout) {
Ok(t) => t.trim().to_owned(),
Err(_) => String::from(""),
};
fs
}
pub fn get_luks_uuid(part_dev: &str) -> String {
let command = match std::process::Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
.arg("get_luks_uuid")
.arg(part_dev)
.output()
{
Ok(t) => t,
Err(_) => return String::from(""),
};
let fs = match String::from_utf8(command.stdout) {
Ok(t) => t.trim().to_owned(),
Err(_) => String::from(""),
};
fs
}