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
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" ]]
then
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(
&carousel,
window.clone(),
&partition_method_type_refcell,
&partition_method_automatic_target_refcell,
&partition_method_automatic_target_fs_refcell,

View File

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

View File

@ -853,4 +853,4 @@ fn post_check_drive_mount(
}
}
));
}
}

View File

@ -1,16 +1,19 @@
use crate::drive_mount_row::DriveMountRow;
use crate::installer_stack_page;
use crate::partitioning_page;
use crate::partitioning_page::{get_partitions, CrypttabEntry, FstabEntry, Partition};
use adw::gio;
use adw::prelude::*;
use glib::{clone, closure_local, ffi::gboolean};
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;
pub fn manual_partitioning_page(
partition_carousel: &adw::Carousel,
window: adw::ApplicationWindow,
partition_method_type_refcell: &Rc<RefCell<String>>,
partition_method_manual_fstab_entry_array_refcell: &Rc<RefCell<Vec<FstabEntry>>>,
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!(
#[weak]
filesystem_table_refresh_button,
move |_|
{
let command = std::process::Command::new("blivet-gui").status();
if command.unwrap().success() {
filesystem_table_refresh_button.emit_by_name("clicked", &[])
}
move |_| {
let command = std::process::Command::new("blivet-gui").status();
if command.unwrap().success() {
filesystem_table_refresh_button.emit_by_name("clicked", &[])
}
)
);
}
));
filesystem_table_refresh_button.connect_clicked(clone!(
#[weak]
@ -135,30 +136,176 @@ pub fn manual_partitioning_page(
partition_method_manual_luks_enabled_refcell,
#[strong]
partition_method_manual_crypttab_entry_array_refcell,
move |_|
{
while let Some(row) = drive_mounts_adw_listbox.last_child() {
drive_mounts_adw_listbox.remove(&row);
}
(*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();
(*used_partition_array_refcell.borrow_mut()) = Vec::new();
(*subvol_partition_array_refcell.borrow_mut()) = Vec::new();
create_hardcoded_rows(
&drive_mounts_adw_listbox,
&drive_rows_size_group,
&partition_array_refcell,
&partition_changed_action,
&language_changed_action,
&used_partition_array_refcell,
&subvol_partition_array_refcell,
);
move |_| {
while let Some(row) = drive_mounts_adw_listbox.last_child() {
drive_mounts_adw_listbox.remove(&row);
}
)
);
(*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();
(*used_partition_array_refcell.borrow_mut()) = Vec::new();
(*subvol_partition_array_refcell.borrow_mut()) = Vec::new();
create_hardcoded_rows(
&drive_mounts_adw_listbox,
&drive_rows_size_group,
&partition_array_refcell,
&partition_changed_action,
&language_changed_action,
&used_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(&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(
main_carousel: &adw::Carousel,
window: adw::ApplicationWindow,
partition_method_type_refcell: &Rc<RefCell<String>>,
partition_method_automatic_target_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(
&partitioning_carousel,
window,
&partition_method_type_refcell,
&partition_method_manual_fstab_entry_array_refcell,
&partition_method_manual_luks_enabled_refcell,
@ -173,24 +175,26 @@ pub struct BlockDevice {
pub block_size_pretty: String,
}
#[derive(Clone)]
#[derive(Clone, Default)]
pub struct Partition {
pub part_name: String,
pub part_fs: String,
pub part_uuid: String,
pub has_encryption: bool,
pub need_mapper: bool,
pub part_size: f64,
pub part_size_pretty: String,
}
#[derive(Default)]
#[derive(Default, Clone)]
pub struct FstabEntry {
pub partition: String,
pub partition: Partition,
pub mountpoint: String,
pub mountopts: String,
}
pub struct CrypttabEntry {
pub partition: String,
pub map: String,
pub uuid: String,
pub password: Option<String>,
@ -268,18 +272,7 @@ pub fn get_partitions() -> Vec<Partition> {
Some(t) => {
for partition in std::io::BufReader::new(t).lines() {
match partition {
Ok(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),
})
}
Ok(r) => partitions.push(create_parition_struct(&r)),
Err(_) => return partitions,
}
}
@ -290,6 +283,20 @@ pub fn get_partitions() -> Vec<Partition> {
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 {
let command = match std::process::Command::new("sudo")
.arg("/usr/lib/pika/pika-installer-gtk4/scripts/partition-utility.sh")
@ -351,3 +358,58 @@ fn is_encrypted(part_dev: &str) -> bool {
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
}