From d43e49aacfb1c8c688f252afde06fef0c0844fd7 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 14:56:14 +0100 Subject: [PATCH 01/23] DBusStructures: Add new file system enum and partition usage struct --- common/DBusStructures.vala | 43 +++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 388e2b9ed..22c5e9a43 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -31,14 +31,41 @@ public struct InstallerDaemon.Disk { Partition[] partitions; } +public enum InstallerDaemon.FileSystem { + NONE, + BTRFS, + EXT2, + EXT3, + EXT4, + F2FS, + FAT16, + FAT32, + NTFS, + SWAP, + XFS, + LVM, + LUKS, +} + +public struct InstallerDaemon.PartitionUsage { + /** + * None = 0; Some(usage) = 1; + */ + public uint8 tag; + /** + * The size, in sectors, that a partition is used. + */ + public uint64 value; +} + public struct InstallerDaemon.Partition { string device_path; - Distinst.FileSystem filesystem; + FileSystem filesystem; uint64 start_sector; uint64 end_sector; - Distinst.PartitionUsage sectors_used; + PartitionUsage sectors_used; string? current_lvm_volume_group; } @@ -62,18 +89,18 @@ public struct InstallerDaemon.Mount { string parent_disk; string mount_point; uint64 sectors; - Distinst.FileSystem filesystem; + FileSystem filesystem; MountFlags flags; public bool is_valid_boot_mount () { - return filesystem == Distinst.FileSystem.FAT16 - || filesystem == Distinst.FileSystem.FAT32; + return filesystem == FileSystem.FAT16 + || filesystem == FileSystem.FAT32; } public bool is_valid_root_mount () { - return filesystem != Distinst.FileSystem.FAT16 - && filesystem != Distinst.FileSystem.FAT32 - && filesystem != Distinst.FileSystem.NTFS; + return filesystem != FileSystem.FAT16 + && filesystem != FileSystem.FAT32 + && filesystem != FileSystem.NTFS; } public bool is_lvm () { From ff2b6d044e6f17491dca0bb6f898a3be095dea07 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 15:02:20 +0100 Subject: [PATCH 02/23] DBusStructures: Add to_string method to FileSystem enum --- common/DBusStructures.vala | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 22c5e9a43..8d441bd6c 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -44,7 +44,40 @@ public enum InstallerDaemon.FileSystem { SWAP, XFS, LVM, - LUKS, + LUKS; + + public string to_string () { + switch (this) { + case BTRFS: + return "btrfs"; + case EXT2: + return "ext2"; + case EXT3: + return "ext3"; + case EXT4: + return "ext4"; + case F2FS: + return "f2fs"; + case FAT16: + return "fat16"; + case FAT32: + return "fat32"; + case NONE: + return "none"; + case NTFS: + return "ntfs"; + case SWAP: + return "swap"; + case XFS: + return "xfs"; + case LVM: + return "lvm"; + case LUKS: + return "luks"; + } + + return "none"; + } } public struct InstallerDaemon.PartitionUsage { From 5853498e370d5779358a70470deb8e3916410a8e Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 15:02:36 +0100 Subject: [PATCH 03/23] Update file system types to use InstallerDaemon instead of Distinst --- src/Objects/Mount.vala | 14 +++++++------- src/Views/PartitioningView.vala | 2 +- src/Widgets/DiskBar.vala | 2 +- src/Widgets/PartitionBar.vala | 8 ++++---- src/Widgets/PartitionMenu.vala | 26 +++++++++++++------------- 5 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/Objects/Mount.vala b/src/Objects/Mount.vala index 6896f0ac6..7fca8c30e 100644 --- a/src/Objects/Mount.vala +++ b/src/Objects/Mount.vala @@ -23,12 +23,12 @@ public class Installer.Mount { public string parent_disk; public string mount_point; public uint64 sectors; - public Distinst.FileSystem filesystem; + public InstallerDaemon.FileSystem filesystem; public InstallerDaemon.MountFlags flags; public PartitionMenu menu; public Mount (string partition, string parent_disk, string mount, - uint64 sectors, InstallerDaemon.MountFlags flags, Distinst.FileSystem fs, + uint64 sectors, InstallerDaemon.MountFlags flags, InstallerDaemon.FileSystem fs, PartitionMenu menu) { filesystem = fs; mount_point = mount; @@ -40,14 +40,14 @@ public class Installer.Mount { } public bool is_valid_boot_mount () { - return filesystem == Distinst.FileSystem.FAT16 - || filesystem == Distinst.FileSystem.FAT32; + return filesystem == InstallerDaemon.FileSystem.FAT16 + || filesystem == InstallerDaemon.FileSystem.FAT32; } public bool is_valid_root_mount () { - return filesystem != Distinst.FileSystem.FAT16 - && filesystem != Distinst.FileSystem.FAT32 - && filesystem != Distinst.FileSystem.NTFS; + return filesystem != InstallerDaemon.FileSystem.FAT16 + && filesystem != InstallerDaemon.FileSystem.FAT32 + && filesystem != InstallerDaemon.FileSystem.NTFS; } public bool is_lvm () { diff --git a/src/Views/PartitioningView.vala b/src/Views/PartitioningView.vala index 90e4cee1e..4751713e5 100644 --- a/src/Views/PartitioningView.vala +++ b/src/Views/PartitioningView.vala @@ -236,7 +236,7 @@ public class Installer.PartitioningView : AbstractInstallerView { m.parent_disk, m.partition_path, m.mount_point, - Distinst.strfilesys (m.filesystem), + m.filesystem.to_string (), m.should_format () ? "true" : "false" ); diff --git a/src/Widgets/DiskBar.vala b/src/Widgets/DiskBar.vala index aa606d506..afe6ee2ba 100644 --- a/src/Widgets/DiskBar.vala +++ b/src/Widgets/DiskBar.vala @@ -89,7 +89,7 @@ public class Installer.DiskBar: Gtk.Grid { legend.add (legend_container); foreach (PartitionBar p in partitions) { - add_legend (p.path, p.get_size () * 512, Distinst.strfilesys (p.filesystem), p.vg, p.menu); + add_legend (p.path, p.get_size () * 512, p.filesystem.to_string (), p.vg, p.menu); } uint64 used = 0; diff --git a/src/Widgets/PartitionBar.vala b/src/Widgets/PartitionBar.vala index df44cc955..719ac3c8f 100644 --- a/src/Widgets/PartitionBar.vala +++ b/src/Widgets/PartitionBar.vala @@ -29,7 +29,7 @@ public class Installer.PartitionBar : Gtk.EventBox { public Gtk.Label label; public Gtk.Popover menu; - public Distinst.FileSystem filesystem; + public InstallerDaemon.FileSystem filesystem; public signal void decrypted (InstallerDaemon.LuksCredentials credential); @@ -48,17 +48,17 @@ public class Installer.PartitionBar : Gtk.EventBox { path = part.device_path; filesystem = part.filesystem; - vg = (Distinst.FileSystem.LVM == filesystem) + vg = (InstallerDaemon.FileSystem.LVM == filesystem) ? part.current_lvm_volume_group : null; tooltip_text = path; var style_context = get_style_context (); - style_context.add_class (Distinst.strfilesys (filesystem)); + style_context.add_class (filesystem.to_string ()); container = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - if (filesystem == Distinst.FileSystem.LUKS) { + if (filesystem == InstallerDaemon.FileSystem.LUKS) { menu = new DecryptMenu (path); ((DecryptMenu)menu).decrypted.connect ((creds) => decrypted (creds)); } else { diff --git a/src/Widgets/PartitionMenu.vala b/src/Widgets/PartitionMenu.vala index 51007cf49..5e1750f77 100644 --- a/src/Widgets/PartitionMenu.vala +++ b/src/Widgets/PartitionMenu.vala @@ -28,7 +28,7 @@ public class Installer.PartitionMenu : Gtk.Popover { private bool is_lvm; private string parent_disk; private string partition_path; - private Distinst.FileSystem original_filesystem; + private InstallerDaemon.FileSystem original_filesystem; private Granite.SwitchModelButton format_partition; private Granite.SwitchModelButton use_partition; @@ -40,7 +40,7 @@ public class Installer.PartitionMenu : Gtk.Popover { // A reference to the parent which owns this menu. private PartitionBar partition_bar; - public PartitionMenu (string path, string parent, Distinst.FileSystem fs, + public PartitionMenu (string path, string parent, InstallerDaemon.FileSystem fs, bool lvm, SetMount set_mount, UnsetMount unset_mount, MountSetFn mount_set, PartitionBar partition_bar) { this.partition_bar = partition_bar; @@ -203,13 +203,13 @@ public class Installer.PartitionMenu : Gtk.Popover { disable_signals = false; int select = 0; - if (fs == Distinst.FileSystem.FAT16 || fs == Distinst.FileSystem.FAT32) { + if (fs == InstallerDaemon.FileSystem.FAT16 || fs == InstallerDaemon.FileSystem.FAT32) { if (mount_set (boot_partition)) { select = 4; } else { select = 2; } - } else if (fs == Distinst.FileSystem.SWAP) { + } else if (fs == InstallerDaemon.FileSystem.SWAP) { select = 3; } else if (mount_set ("/")) { if (mount_set ("/home" )) { @@ -256,7 +256,7 @@ public class Installer.PartitionMenu : Gtk.Popover { private void update_values (SetMount set_mount) { var mount = get_mount (); var filesystem = mount == "swap" - ? Distinst.FileSystem.SWAP + ? InstallerDaemon.FileSystem.SWAP : get_file_system (); string? error = null; @@ -297,22 +297,22 @@ public class Installer.PartitionMenu : Gtk.Popover { return original_filesystem == get_file_system (); } - private Distinst.FileSystem get_file_system () { + private InstallerDaemon.FileSystem get_file_system () { switch (type.active) { case 0: - return Distinst.FileSystem.EXT4; + return InstallerDaemon.FileSystem.EXT4; case 1: - return Distinst.FileSystem.FAT16; + return InstallerDaemon.FileSystem.FAT16; case 2: - return Distinst.FileSystem.FAT32; + return InstallerDaemon.FileSystem.FAT32; case 3: - return Distinst.FileSystem.BTRFS; + return InstallerDaemon.FileSystem.BTRFS; case 4: - return Distinst.FileSystem.XFS; + return InstallerDaemon.FileSystem.XFS; case 5: - return Distinst.FileSystem.NTFS; + return InstallerDaemon.FileSystem.NTFS; default: - return Distinst.FileSystem.NONE; + return InstallerDaemon.FileSystem.NONE; } } From 8c137fe387608331fdb0561918b45df3b2419be4 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 16:18:50 +0100 Subject: [PATCH 04/23] Daemon: Convert file system and partition usage to common format --- daemon/Daemon.vala | 95 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 84 insertions(+), 11 deletions(-) diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index 2a93ea6c0..bed269b47 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -69,10 +69,10 @@ public class InstallerDaemon.Daemon : GLib.Object { partitions += Partition () { device_path = string_from_utf8 (part.get_device_path ()), - filesystem = part.get_file_system (), + filesystem = to_common_fs (part.get_file_system ()), start_sector = part.get_start_sector (), end_sector = part.get_end_sector (), - sectors_used = part.sectors_used (disk.get_sector_size ()), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), current_lvm_volume_group = lvm_vg }; } @@ -103,10 +103,10 @@ public class InstallerDaemon.Daemon : GLib.Object { partitions += Partition () { device_path = string_from_utf8 (part.get_device_path ()), - filesystem = part.get_file_system (), + filesystem = to_common_fs (part.get_file_system ()), start_sector = part.get_start_sector (), end_sector = part.get_end_sector (), - sectors_used = part.sectors_used (disk.get_sector_size ()), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), current_lvm_volume_group = lvm_vg }; } @@ -149,10 +149,10 @@ public class InstallerDaemon.Daemon : GLib.Object { partitions += Partition () { device_path = string_from_utf8 (part.get_device_path ()), - filesystem = part.get_file_system (), + filesystem = to_common_fs (part.get_file_system ()), start_sector = part.get_start_sector (), end_sector = part.get_end_sector (), - sectors_used = part.sectors_used (disk.get_sector_size ()), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), current_lvm_volume_group = lvm_vg }; } @@ -451,7 +451,7 @@ public class InstallerDaemon.Daemon : GLib.Object { if (m.mount_point == "/boot/efi") { if (m.is_valid_boot_mount ()) { if (m.should_format ()) { - partition.format_with (m.filesystem); + partition.format_with (to_distinst_fs (m.filesystem)); } partition.set_mount (m.mount_point); @@ -460,7 +460,7 @@ public class InstallerDaemon.Daemon : GLib.Object { throw new GLib.IOError.FAILED ("Unreachable code path -- EFI partition is invalid"); } } else { - if (m.filesystem != Distinst.FileSystem.SWAP) { + if (m.filesystem != InstallerDaemon.FileSystem.SWAP) { partition.set_mount (m.mount_point); } @@ -469,7 +469,7 @@ public class InstallerDaemon.Daemon : GLib.Object { } if (m.should_format ()) { - partition.format_with (m.filesystem); + partition.format_with (to_distinst_fs (m.filesystem)); } } } @@ -498,12 +498,12 @@ public class InstallerDaemon.Daemon : GLib.Object { throw new GLib.IOError.FAILED ("could not find %s", m.partition_path); } - if (m.filesystem != Distinst.FileSystem.SWAP) { + if (m.filesystem != InstallerDaemon.FileSystem.SWAP) { partition.set_mount (m.mount_point); } if (m.should_format ()) { - partition.format_and_keep_name (m.filesystem); + partition.format_and_keep_name (to_distinst_fs (m.filesystem)); } } } @@ -513,6 +513,79 @@ public class InstallerDaemon.Daemon : GLib.Object { builder.append_len ((string) input, input.length); return (owned) builder.str; } + + private InstallerDaemon.FileSystem to_common_fs (Distinst.FileSystem fs) { + switch (fs) { + case BTRFS: + return InstallerDaemon.FileSystem.BTRFS; + case EXT2: + return InstallerDaemon.FileSystem.EXT2; + case EXT3: + return InstallerDaemon.FileSystem.EXT3; + case EXT4: + return InstallerDaemon.FileSystem.EXT4; + case F2FS: + return InstallerDaemon.FileSystem.F2FS; + case FAT16: + return InstallerDaemon.FileSystem.FAT16; + case FAT32: + return InstallerDaemon.FileSystem.FAT32; + case NONE: + return InstallerDaemon.FileSystem.NONE; + case NTFS: + return InstallerDaemon.FileSystem.NTFS; + case SWAP: + return InstallerDaemon.FileSystem.SWAP; + case XFS: + return InstallerDaemon.FileSystem.XFS; + case LVM: + return InstallerDaemon.FileSystem.LVM; + case LUKS: + return InstallerDaemon.FileSystem.LUKS; + default: + return InstallerDaemon.FileSystem.NONE; + } + } + + private InstallerDaemon.PartitionUsage to_common_usage (Distinst.PartitionUsage usage) { + return InstallerDaemon.PartitionUsage () { + tag = usage.tag, + value = usage.value + }; + } + + private Distinst.FileSystem to_distinst_fs (InstallerDaemon.FileSystem fs) { + switch (fs) { + case BTRFS: + return Distinst.FileSystem.BTRFS; + case EXT2: + return Distinst.FileSystem.EXT2; + case EXT3: + return Distinst.FileSystem.EXT3; + case EXT4: + return Distinst.FileSystem.EXT4; + case F2FS: + return Distinst.FileSystem.F2FS; + case FAT16: + return Distinst.FileSystem.FAT16; + case FAT32: + return Distinst.FileSystem.FAT32; + case NONE: + return Distinst.FileSystem.NONE; + case NTFS: + return Distinst.FileSystem.NTFS; + case SWAP: + return Distinst.FileSystem.SWAP; + case XFS: + return Distinst.FileSystem.XFS; + case LVM: + return Distinst.FileSystem.LVM; + case LUKS: + return Distinst.FileSystem.LUKS; + default: + return Distinst.FileSystem.NONE; + } + } } private void on_bus_acquired (GLib.DBusConnection connection, string name) { From 3e041ce19659e26ac4f861a6dd7040e9650fa034 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 16:27:01 +0100 Subject: [PATCH 05/23] Add PartitionTable enum and update bootloader_detect method --- common/DBusStructures.vala | 6 ++++++ daemon/Daemon.vala | 17 +++++++++++++++-- src/Helpers/InstallerDaemon.vala | 10 +++++----- src/Views/PartitioningView.vala | 8 ++++---- src/Widgets/PartitionMenu.vala | 6 +++--- 5 files changed, 33 insertions(+), 14 deletions(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 8d441bd6c..2b1308464 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -91,6 +91,12 @@ public struct InstallerDaemon.PartitionUsage { public uint64 value; } +public enum InstallerDaemon.PartitionTable { + NONE, + GPT, + MSDOS; +} + public struct InstallerDaemon.Partition { string device_path; diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index bed269b47..e458528ae 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -33,8 +33,8 @@ public class InstallerDaemon.Daemon : GLib.Object { }); } - public Distinst.PartitionTable bootloader_detect () throws GLib.Error { - return Distinst.bootloader_detect (); + public InstallerDaemon.PartitionTable bootloader_detect () throws GLib.Error { + return to_common_usage_bootloader (Distinst.bootloader_detect ()); } public DiskInfo get_disks (bool get_partitions = false) throws GLib.Error { @@ -586,6 +586,19 @@ public class InstallerDaemon.Daemon : GLib.Object { return Distinst.FileSystem.NONE; } } + + public InstallerDaemon.PartitionTable to_common_usage_bootloader (Distinst.PartitionTable bootloader) { + switch (bootloader) { + case GPT: + return InstallerDaemon.PartitionTable.GPT; + case MSDOS: + return InstallerDaemon.PartitionTable.MSDOS; + case NONE: + return InstallerDaemon.PartitionTable.NONE; + default: + return InstallerDaemon.PartitionTable.NONE; + } + } } private void on_bus_acquired (GLib.DBusConnection connection, string name) { diff --git a/src/Helpers/InstallerDaemon.vala b/src/Helpers/InstallerDaemon.vala index 254bb8f90..1d523c258 100644 --- a/src/Helpers/InstallerDaemon.vala +++ b/src/Helpers/InstallerDaemon.vala @@ -27,7 +27,7 @@ public class Installer.Daemon { public signal void on_status (Distinst.Status status); public signal void on_log_message (Distinst.LogLevel level, string message); - public abstract Distinst.PartitionTable bootloader_detect () throws GLib.Error; + public abstract InstallerDaemon.PartitionTable bootloader_detect () throws GLib.Error; public async abstract InstallerDaemon.DiskInfo get_disks (bool get_partitions = false) throws GLib.Error; public async abstract int decrypt_partition (string path, string pv, string password) throws GLib.Error; @@ -59,7 +59,7 @@ public class Installer.Daemon { daemon.on_log_message.connect ((level, message) => on_log_message (level, message)); } - public Distinst.PartitionTable bootloader_detect () { + public InstallerDaemon.PartitionTable bootloader_detect () { if (daemon == null) { return fallback_bootloader_detect (); } @@ -71,12 +71,12 @@ public class Installer.Daemon { } } - private Distinst.PartitionTable fallback_bootloader_detect () { + private InstallerDaemon.PartitionTable fallback_bootloader_detect () { var efi_file = GLib.File.new_for_path ("/sys/firmware/efi"); if (efi_file.query_exists ()) { - return Distinst.PartitionTable.GPT; + return InstallerDaemon.PartitionTable.GPT; } else { - return Distinst.PartitionTable.MSDOS; + return InstallerDaemon.PartitionTable.MSDOS; } } diff --git a/src/Views/PartitioningView.vala b/src/Views/PartitioningView.vala index 4751713e5..ada7412a4 100644 --- a/src/Views/PartitioningView.vala +++ b/src/Views/PartitioningView.vala @@ -53,11 +53,11 @@ public class Installer.PartitioningView : AbstractInstallerView { var bootloader = Daemon.get_default ().bootloader_detect (); switch (bootloader) { - case Distinst.PartitionTable.MSDOS: + case MSDOS: // Device is in BIOS mode, so we just require a root partition required_description = _("You must at least select a Root (/) partition."); break; - case Distinst.PartitionTable.GPT: + case GPT: // Device is in EFI mode, so we also require a boot partition required_description = _("You must at least select a Root (/) partition and a Boot (/boot/efi) partition."); break; @@ -222,9 +222,9 @@ public class Installer.PartitioningView : AbstractInstallerView { var bootloader = Daemon.get_default ().bootloader_detect (); switch (bootloader) { - case Distinst.PartitionTable.MSDOS: + case MSDOS: break; - case Distinst.PartitionTable.GPT: + case GPT: required |= Defined.EFI; break; } diff --git a/src/Widgets/PartitionMenu.vala b/src/Widgets/PartitionMenu.vala index 5e1750f77..3fde1af5c 100644 --- a/src/Widgets/PartitionMenu.vala +++ b/src/Widgets/PartitionMenu.vala @@ -49,7 +49,7 @@ public class Installer.PartitionMenu : Gtk.Popover { partition_path = path; parent_disk = parent; - string boot_partition = (Daemon.get_default ().bootloader_detect () == Distinst.PartitionTable.GPT) + string boot_partition = (Daemon.get_default ().bootloader_detect () == InstallerDaemon.PartitionTable.GPT) ? "/boot/efi" : "/boot"; @@ -156,7 +156,7 @@ public class Installer.PartitionMenu : Gtk.Popover { custom.visible = visible; if (active == 2) { - if (Daemon.get_default ().bootloader_detect () == Distinst.PartitionTable.GPT) { + if (Daemon.get_default ().bootloader_detect () == InstallerDaemon.PartitionTable.GPT) { type.active = 2; } else { type.active = 0; @@ -323,7 +323,7 @@ public class Installer.PartitionMenu : Gtk.Popover { case 1: return "/home"; case 2: - if (Daemon.get_default ().bootloader_detect () == Distinst.PartitionTable.GPT) { + if (Daemon.get_default ().bootloader_detect () == InstallerDaemon.PartitionTable.GPT) { return "/boot/efi"; } else { return "/boot"; From 3a2ed8dab8d502f95da83cd62b39ec600d9d54ee Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 20:35:15 +0100 Subject: [PATCH 06/23] Add new enums and struct for InstallerDaemon and update flags in Daemon and ProgressView --- common/DBusStructures.vala | 17 ++++++++++++++++- daemon/Daemon.vala | 11 ++++++++++- src/Views/ProgressView.vala | 28 ++++++++++++++-------------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 2b1308464..59ea1aa8d 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -97,6 +97,20 @@ public enum InstallerDaemon.PartitionTable { MSDOS; } +public enum InstallerDaemon.Step { + BACKUP, + INIT, + PARTITION, + EXTRACT, + CONFIGURE, + BOOTLOADER; +} + +public struct InstallerDaemon.Status { + Step step; + int percent; +} + public struct InstallerDaemon.Partition { string device_path; @@ -113,7 +127,8 @@ public struct InstallerDaemon.InstallConfig { string keyboard_layout; string keyboard_variant; string lang; - uint8 flags; + bool modify_boot_order; + bool install_drivers; } [Flags] diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index e458528ae..a3cdb46af 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -186,7 +186,16 @@ public class InstallerDaemon.Daemon : GLib.Object { installer.on_status ((status) => on_status (status)); var distinst_config = Distinst.Config (); - distinst_config.flags = config.flags; + uint8 flags = 0; + if (config.modify_boot_order) { + flags = Distinst.MODIFY_BOOT_ORDER; + } + + if (config.install_drivers) { + flags |= Distinst.RUN_UBUNTU_DRIVERS; + } + + distinst_config.flags = flags; distinst_config.hostname = config.hostname; var casper = casper_dir (); diff --git a/src/Views/ProgressView.vala b/src/Views/ProgressView.vala index d0e7f105f..5943e991e 100644 --- a/src/Views/ProgressView.vala +++ b/src/Views/ProgressView.vala @@ -112,10 +112,10 @@ public class ProgressView : AbstractInstallerView { public void start_installation () { if (Installer.App.test_mode) { new Thread (null, () => { - fake_status (Distinst.Step.PARTITION); - fake_status (Distinst.Step.EXTRACT); - fake_status (Distinst.Step.CONFIGURE); - fake_status (Distinst.Step.BOOTLOADER); + fake_status (InstallerDaemon.Step.PARTITION); + fake_status (InstallerDaemon.Step.EXTRACT); + fake_status (InstallerDaemon.Step.CONFIGURE); + fake_status (InstallerDaemon.Step.BOOTLOADER); return null; }); } else { @@ -133,9 +133,9 @@ public class ProgressView : AbstractInstallerView { unowned Configuration current_config = Configuration.get_default (); var config = InstallerDaemon.InstallConfig (); - config.flags = Distinst.MODIFY_BOOT_ORDER; + config.modify_boot_order = true; if (current_config.install_drivers) { - config.flags |= Distinst.RUN_UBUNTU_DRIVERS; + config.install_drivers = true; } config.hostname = Utils.get_hostname (); config.lang = "en_US.UTF-8"; @@ -199,9 +199,9 @@ public class ProgressView : AbstractInstallerView { } } - private void fake_status (Distinst.Step step) { + private void fake_status (InstallerDaemon.Step step) { for (var percent = 0; percent <= 100; percent++) { - Distinst.Status status = Distinst.Status () { + InstallerDaemon.Status status = InstallerDaemon.Status () { step = step, percent = percent }; @@ -210,9 +210,9 @@ public class ProgressView : AbstractInstallerView { } } - private void installation_status_callback (Distinst.Status status) { + private void installation_status_callback (InstallerDaemon.Status status) { Idle.add (() => { - if (status.percent == 100 && status.step == Distinst.Step.BOOTLOADER) { + if (status.percent == 100 && status.step == InstallerDaemon.Step.BOOTLOADER) { on_success (); return GLib.Source.REMOVE; } @@ -220,21 +220,21 @@ public class ProgressView : AbstractInstallerView { string step_string = ""; double fraction = ((double) status.percent) / (100.0 * NUM_STEP); switch (status.step) { - case Distinst.Step.PARTITION: + case PARTITION: ///TRANSLATORS: The current step of the installer back-end step_string = _("Partitioning Drive"); break; - case Distinst.Step.EXTRACT: + case EXTRACT: fraction += 2 * (1.0 / NUM_STEP); ///TRANSLATORS: The current step of the installer back-end step_string = _("Extracting Files"); break; - case Distinst.Step.CONFIGURE: + case CONFIGURE: fraction += 3 * (1.0 / NUM_STEP); ///TRANSLATORS: The current step of the installer back-end step_string = _("Configuring the System"); break; - case Distinst.Step.BOOTLOADER: + case BOOTLOADER: fraction += 4 * (1.0 / NUM_STEP); ///TRANSLATORS: The current step of the installer back-end step_string = _("Finishing the Installation"); From c1e4fa95982aa81c30ace6c9edd53ce879703a08 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 20:44:17 +0100 Subject: [PATCH 07/23] Refactor to_common_usage_bootloader method in Daemon class --- daemon/Daemon.vala | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index a3cdb46af..ab9c4a2b2 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -596,14 +596,13 @@ public class InstallerDaemon.Daemon : GLib.Object { } } - public InstallerDaemon.PartitionTable to_common_usage_bootloader (Distinst.PartitionTable bootloader) { + private InstallerDaemon.PartitionTable to_common_usage_bootloader (Distinst.PartitionTable bootloader) { switch (bootloader) { case GPT: return InstallerDaemon.PartitionTable.GPT; case MSDOS: return InstallerDaemon.PartitionTable.MSDOS; case NONE: - return InstallerDaemon.PartitionTable.NONE; default: return InstallerDaemon.PartitionTable.NONE; } From 7cdde6a836a307542341a906ddf6e9460616cfd7 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 21:05:44 +0100 Subject: [PATCH 08/23] Add InstallerDaemon.LogLevel and InstallerDaemon.Error to InstallerDaemon.Daemon signals --- common/DBusStructures.vala | 13 +++++++ daemon/Daemon.vala | 64 ++++++++++++++++++++++++++++---- src/Helpers/InstallerDaemon.vala | 12 +++--- src/Helpers/LogHelper.vala | 14 +++---- src/Views/ProgressView.vala | 6 +-- 5 files changed, 85 insertions(+), 24 deletions(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 59ea1aa8d..7f83735dc 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -111,6 +111,19 @@ public struct InstallerDaemon.Status { int percent; } +public enum InstallerDaemon.LogLevel { + TRACE, + DEBUG, + INFO, + WARN, + ERROR; +} + +public struct InstallerDaemon.Error { + Step step; + int err; +} + public struct InstallerDaemon.Partition { string device_path; diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index ab9c4a2b2..9711a964f 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -19,16 +19,16 @@ private static GLib.MainLoop loop; [DBus (name = "io.elementary.InstallerDaemon")] public class InstallerDaemon.Daemon : GLib.Object { - public signal void on_log_message (Distinst.LogLevel level, string message); - public signal void on_status (Distinst.Status status); - public signal void on_error (Distinst.Error error); + public signal void on_log_message (InstallerDaemon.LogLevel level, string message); + public signal void on_status (InstallerDaemon.Status status); + public signal void on_error (InstallerDaemon.Error error); private Distinst.Disks disks; construct { Distinst.log ((level, message) => { Idle.add (() => { - on_log_message (level, message); + on_log_message (to_common_log_level (level), message); }); }); } @@ -182,8 +182,8 @@ public class InstallerDaemon.Daemon : GLib.Object { private void install (InstallConfig config, owned Distinst.Disks disks) { var installer = new Distinst.Installer (); - installer.on_error ((error) => on_error (error)); - installer.on_status ((status) => on_status (status)); + installer.on_error ((error) => on_error (to_common_error (error))); + installer.on_status ((status) => on_status (to_common_status (status))); var distinst_config = Distinst.Config (); uint8 flags = 0; @@ -212,7 +212,7 @@ public class InstallerDaemon.Daemon : GLib.Object { new Thread (null, () => { if (installer.install ((owned) disks, distinst_config) != 0) { Idle.add (() => { - on_error (Distinst.Error ()); + on_error (InstallerDaemon.Error ()); return GLib.Source.REMOVE; }); } @@ -229,7 +229,7 @@ public class InstallerDaemon.Daemon : GLib.Object { var demo_mode_file = GLib.File.new_for_path ("/var/lib/lightdm/demo-mode"); try { demo_mode_file.create (GLib.FileCreateFlags.NONE); - } catch (Error e) { + } catch (GLib.Error e) { if (!(e is GLib.IOError.EXISTS)) { throw e; } @@ -607,6 +607,54 @@ public class InstallerDaemon.Daemon : GLib.Object { return InstallerDaemon.PartitionTable.NONE; } } + + private InstallerDaemon.LogLevel to_common_log_level (Distinst.LogLevel level) { + switch (level) { + case DEBUG: + return InstallerDaemon.LogLevel.DEBUG; + case INFO: + return InstallerDaemon.LogLevel.INFO; + case WARN: + return InstallerDaemon.LogLevel.WARN; + case ERROR: + return InstallerDaemon.LogLevel.ERROR; + case TRACE: + default: + return InstallerDaemon.LogLevel.TRACE; + } + } + + private InstallerDaemon.Error to_common_error (Distinst.Error error) { + return InstallerDaemon.Error () { + step = to_common_step (error.step), + err = error.err + }; + } + + private InstallerDaemon.Step to_common_step (Distinst.Step step) { + switch (step) { + case BACKUP: + return InstallerDaemon.Step.BACKUP; + case PARTITION: + return InstallerDaemon.Step.PARTITION; + case EXTRACT: + return InstallerDaemon.Step.EXTRACT; + case CONFIGURE: + return InstallerDaemon.Step.CONFIGURE; + case BOOTLOADER: + return InstallerDaemon.Step.BOOTLOADER; + case INIT: + default: + return InstallerDaemon.Step.INIT; + } + } + + private InstallerDaemon.Status to_common_status (Distinst.Status status) { + return InstallerDaemon.Status () { + step = to_common_step (status.step), + percent = status.percent + }; + } } private void on_bus_acquired (GLib.DBusConnection connection, string name) { diff --git a/src/Helpers/InstallerDaemon.vala b/src/Helpers/InstallerDaemon.vala index 1d523c258..25cdbec16 100644 --- a/src/Helpers/InstallerDaemon.vala +++ b/src/Helpers/InstallerDaemon.vala @@ -23,9 +23,9 @@ public class Installer.Daemon { [DBus (name = "io.elementary.InstallerDaemon")] private interface InstallerInterface : GLib.DBusProxy { - public signal void on_error (Distinst.Error error); - public signal void on_status (Distinst.Status status); - public signal void on_log_message (Distinst.LogLevel level, string message); + public signal void on_error (InstallerDaemon.Error error); + public signal void on_status (InstallerDaemon.Status status); + public signal void on_log_message (InstallerDaemon.LogLevel level, string message); public abstract InstallerDaemon.PartitionTable bootloader_detect () throws GLib.Error; @@ -38,9 +38,9 @@ public class Installer.Daemon { public async abstract void trigger_demo_mode () throws GLib.Error; } - public signal void on_error (Distinst.Error error); - public signal void on_status (Distinst.Status status); - public signal void on_log_message (Distinst.LogLevel level, string message); + public signal void on_error (InstallerDaemon.Error error); + public signal void on_status (InstallerDaemon.Status status); + public signal void on_log_message (InstallerDaemon.LogLevel level, string message); private InstallerInterface daemon; diff --git a/src/Helpers/LogHelper.vala b/src/Helpers/LogHelper.vala index 00677e1db..0bbb1e72f 100644 --- a/src/Helpers/LogHelper.vala +++ b/src/Helpers/LogHelper.vala @@ -16,17 +16,17 @@ * along with this program. If not, see . */ -static string level_name (Distinst.LogLevel level) { +static string level_name (InstallerDaemon.LogLevel level) { switch (level) { - case Distinst.LogLevel.TRACE: + case TRACE: return "TRACE"; - case Distinst.LogLevel.DEBUG: + case DEBUG: return "DEBUG"; - case Distinst.LogLevel.INFO: + case INFO: return "INFO"; - case Distinst.LogLevel.WARN: + case WARN: return "WARN"; - case Distinst.LogLevel.ERROR: + case ERROR: return "ERROR"; default: return "UNKNOWN"; @@ -50,7 +50,7 @@ public class LogHelper : GLib.Object { buffer.text = ""; } - public void log_func (Distinst.LogLevel level, string message) { + public void log_func (InstallerDaemon.LogLevel level, string message) { stdout.printf ("log: %s: %s\n", level_name (level), message); Gtk.TextIter end_iter; buffer.get_end_iter (out end_iter); diff --git a/src/Views/ProgressView.vala b/src/Views/ProgressView.vala index 5943e991e..9759d4289 100644 --- a/src/Views/ProgressView.vala +++ b/src/Views/ProgressView.vala @@ -167,7 +167,7 @@ public class ProgressView : AbstractInstallerView { current_config.encryption_password ?? "" ); } catch (Error e) { - log_helper.log_func (Distinst.LogLevel.ERROR, e.message); + log_helper.log_func (InstallerDaemon.LogLevel.ERROR, e.message); on_error (); } } else { @@ -193,7 +193,7 @@ public class ProgressView : AbstractInstallerView { try { yield daemon.install_with_custom_disk_layout (config, mounts, creds); } catch (Error e) { - log_helper.log_func (Distinst.LogLevel.ERROR, e.message); + log_helper.log_func (InstallerDaemon.LogLevel.ERROR, e.message); on_error (); } } @@ -247,7 +247,7 @@ public class ProgressView : AbstractInstallerView { }); } - private void installation_error_callback (Distinst.Error error) { + private void installation_error_callback (InstallerDaemon.Error error) { Idle.add (() => { on_error (); return GLib.Source.REMOVE; From 08a0147ff786e3003a30cea310478613cade46ec Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 21:07:33 +0100 Subject: [PATCH 09/23] Utils: Remove distinst specific code --- src/Utils.vala | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Utils.vala b/src/Utils.vala index 8368ab2cf..8c7afcc34 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -264,13 +264,6 @@ namespace Utils { string hostname = get_ubiquity_compatible_hostname () ?? ("elementary-os" + "-" + get_chassis ()); hostname += "-" + get_machine_id ().substring (0, 8); - // If the automatic hostname logic fails in some way, it's possible we may generate an invalid - // hostname. We could fix this by trimming traling/leading hyphens or other invalid characters. - // But it's probably a bad hostname anyway, so just fallback - if (!Distinst.validate_hostname (hostname)) { - hostname = "elementary-os"; - } - return hostname; } } From dd09a4b0ecd79dff324c297f22ac9a85a016c235 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 21:08:46 +0100 Subject: [PATCH 10/23] Refactor file common/DBusStructures.vala to handle FileSystem.NONE case in a default statement. --- common/DBusStructures.vala | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 7f83735dc..8a5ec8b18 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -62,8 +62,6 @@ public enum InstallerDaemon.FileSystem { return "fat16"; case FAT32: return "fat32"; - case NONE: - return "none"; case NTFS: return "ntfs"; case SWAP: @@ -74,9 +72,10 @@ public enum InstallerDaemon.FileSystem { return "lvm"; case LUKS: return "luks"; + case NONE: + default: + return "none"; } - - return "none"; } } From 82c20cd20c329e4673f38bfe160428256746ac8f Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 21:10:40 +0100 Subject: [PATCH 11/23] Remove distinst_dep from gui_dependencies --- src/meson.build | 1 - 1 file changed, 1 deletion(-) diff --git a/src/meson.build b/src/meson.build index 39dbd5913..1c3a007e1 100644 --- a/src/meson.build +++ b/src/meson.build @@ -54,7 +54,6 @@ config_file = configure_file( ) gui_dependencies = [ - distinst_dep, gee_dep, glib_dep, gnome_keyboard_dep, From 2d382d2b8e074d4f6f5d9043dbe42860af017207 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 21:19:10 +0100 Subject: [PATCH 12/23] Add support for Distinst installer backend in daemon --- daemon/Daemon.vala | 644 +---------------------------------- daemon/DistinstBackend.vala | 656 ++++++++++++++++++++++++++++++++++++ daemon/meson.build | 12 +- meson.build | 8 +- meson_options.txt | 1 + 5 files changed, 678 insertions(+), 643 deletions(-) create mode 100644 daemon/DistinstBackend.vala diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index 9711a964f..0fd716099 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -17,649 +17,11 @@ private static GLib.MainLoop loop; -[DBus (name = "io.elementary.InstallerDaemon")] -public class InstallerDaemon.Daemon : GLib.Object { - public signal void on_log_message (InstallerDaemon.LogLevel level, string message); - public signal void on_status (InstallerDaemon.Status status); - public signal void on_error (InstallerDaemon.Error error); - - private Distinst.Disks disks; - - construct { - Distinst.log ((level, message) => { - Idle.add (() => { - on_log_message (to_common_log_level (level), message); - }); - }); - } - - public InstallerDaemon.PartitionTable bootloader_detect () throws GLib.Error { - return to_common_usage_bootloader (Distinst.bootloader_detect ()); - } - - public DiskInfo get_disks (bool get_partitions = false) throws GLib.Error { - disks = Distinst.Disks.probe (); - - if (get_partitions) { - disks.initialize_volume_groups (); - } - - DiskInfo result = DiskInfo (); - - Disk[] physical_disks = {}; - Disk[] logical_disks = {}; - - foreach (unowned Distinst.Disk disk in disks.list ()) { - if (disk.is_read_only ()) { - continue; - } - - // Skip root disk or live disk - if (disk.contains_mount ("/", disks) || disk.contains_mount ("/cdrom", disks)) { - continue; - } - - Partition[] partitions = {}; - - if (get_partitions) { - foreach (unowned Distinst.Partition part in disk.list_partitions ()) { - string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) - ? string_from_utf8 (part.get_current_lvm_volume_group ()) - : ""; - - partitions += Partition () { - device_path = string_from_utf8 (part.get_device_path ()), - filesystem = to_common_fs (part.get_file_system ()), - start_sector = part.get_start_sector (), - end_sector = part.get_end_sector (), - sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), - current_lvm_volume_group = lvm_vg - }; - } - } - - string model = string_from_utf8 (disk.get_model ()); - string name = model.length == 0 ? string_from_utf8 (disk.get_serial ()).replace ("_", " ") : model; - - physical_disks += Disk () { - name = name, - device_path = string_from_utf8 (disk.get_device_path ()), - sectors = disk.get_sectors (), - sector_size = disk.get_sector_size (), - rotational = disk.is_rotational (), - removable = disk.is_removable (), - partitions = partitions - }; - } - - if (get_partitions) { - foreach (unowned Distinst.LvmDevice disk in disks.list_logical ()) { - Partition[] partitions = {}; - - foreach (unowned Distinst.Partition part in disk.list_partitions ()) { - string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) - ? string_from_utf8 (part.get_current_lvm_volume_group ()) - : ""; - - partitions += Partition () { - device_path = string_from_utf8 (part.get_device_path ()), - filesystem = to_common_fs (part.get_file_system ()), - start_sector = part.get_start_sector (), - end_sector = part.get_end_sector (), - sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), - current_lvm_volume_group = lvm_vg - }; - } - - logical_disks += Disk () { - name = string_from_utf8 (disk.get_model ()), - device_path = string_from_utf8 (disk.get_device_path ()), - sectors = disk.get_sectors (), - sector_size = disk.get_sector_size (), - partitions = partitions - }; - } - } - - result.physical_disks = physical_disks; - result.logical_disks = logical_disks; - return result; - } - - public int decrypt_partition (string path, string pv, string password) throws GLib.Error { - return disks.decrypt_partition (path, Distinst.LvmEncryption () { - physical_volume = pv, - password = password, - keydata = null - }); - } - - public Disk get_logical_device (string pv) throws GLib.Error { - unowned Distinst.LvmDevice disk = disks.get_logical_device (pv); - if (disk == null) { - throw new GLib.IOError.NOT_FOUND ("Couldn't find a logical device with that name"); - } - - Partition[] partitions = {}; - - foreach (unowned Distinst.Partition part in disk.list_partitions ()) { - string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) - ? string_from_utf8 (part.get_current_lvm_volume_group ()) - : ""; - - partitions += Partition () { - device_path = string_from_utf8 (part.get_device_path ()), - filesystem = to_common_fs (part.get_file_system ()), - start_sector = part.get_start_sector (), - end_sector = part.get_end_sector (), - sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), - current_lvm_volume_group = lvm_vg - }; - } - - return Disk () { - name = string_from_utf8 (disk.get_model ()), - device_path = string_from_utf8 (disk.get_device_path ()), - sectors = disk.get_sectors (), - sector_size = disk.get_sector_size (), - partitions = partitions - }; - } - - public void install_with_default_disk_layout (InstallConfig config, string disk, bool encrypt, string encryption_password) throws GLib.Error { - var disks = new Distinst.Disks (); - default_disk_configuration (disks, disk, encrypt ? encryption_password : null); - - install (config, (owned) disks); - } - - public void install_with_custom_disk_layout (InstallConfig config, Mount[] disk_config, LuksCredentials[] credentials) throws GLib.Error { - var disks = new Distinst.Disks (); - custom_disk_configuration (disks, disk_config, credentials); - - install (config, (owned) disks); - } - - private void install (InstallConfig config, owned Distinst.Disks disks) { - var installer = new Distinst.Installer (); - installer.on_error ((error) => on_error (to_common_error (error))); - installer.on_status ((status) => on_status (to_common_status (status))); - - var distinst_config = Distinst.Config (); - uint8 flags = 0; - if (config.modify_boot_order) { - flags = Distinst.MODIFY_BOOT_ORDER; - } - - if (config.install_drivers) { - flags |= Distinst.RUN_UBUNTU_DRIVERS; - } - - distinst_config.flags = flags; - distinst_config.hostname = config.hostname; - - var casper = casper_dir (); - distinst_config.remove = GLib.Path.build_filename (casper, "filesystem.manifest-remove"); - distinst_config.squashfs = GLib.Path.build_filename (casper, "filesystem.squashfs"); - - debug ("language: %s\n", config.lang); - distinst_config.lang = config.lang; - - distinst_config.keyboard_layout = config.keyboard_layout; - distinst_config.keyboard_model = null; - distinst_config.keyboard_variant = config.keyboard_variant == "" ? null : config.keyboard_variant; - - new Thread (null, () => { - if (installer.install ((owned) disks, distinst_config) != 0) { - Idle.add (() => { - on_error (InstallerDaemon.Error ()); - return GLib.Source.REMOVE; - }); - } - - return null; - }); - } - - public void set_demo_mode_locale (string locale) throws GLib.Error { - GLib.FileUtils.set_contents ("/etc/default/locale", "LANG=" + locale); - } - - public void trigger_demo_mode () throws GLib.Error { - var demo_mode_file = GLib.File.new_for_path ("/var/lib/lightdm/demo-mode"); - try { - demo_mode_file.create (GLib.FileCreateFlags.NONE); - } catch (GLib.Error e) { - if (!(e is GLib.IOError.EXISTS)) { - throw e; - } - } - } - - private string casper_dir () { - const string CDROM = "/cdrom"; - - try { - var cdrom_dir = File.new_for_path (CDROM); - var iter = cdrom_dir.enumerate_children (FileAttribute.STANDARD_NAME, 0); - - FileInfo info; - while ((info = iter.next_file ()) != null) { - unowned string name = info.get_name (); - if (name.has_prefix ("casper")) { - return GLib.Path.build_filename (CDROM, name); - } - } - } catch (GLib.Error e) { - critical ("failed to find casper dir automatically: %s\n", e.message); - } - - return GLib.Path.build_filename (CDROM, "casper"); - } - - private void default_disk_configuration (Distinst.Disks disks, string disk_path, string? encryption_password) throws GLib.IOError { - var encrypted_vg = Distinst.generate_unique_id ("cryptdata"); - var root_vg = Distinst.generate_unique_id ("data"); - if (encrypted_vg == null || root_vg == null) { - throw new GLib.IOError.FAILED ("Unable to generate unique volume group IDs"); - } - - Distinst.LvmEncryption? encryption; - if (encryption_password != null) { - debug ("encrypting"); - encryption = Distinst.LvmEncryption () { - physical_volume = encrypted_vg, - password = encryption_password, - keydata = null - }; - } else { - debug ("not encrypting"); - encryption = null; - } - - debug ("disk: %s\n", disk_path); - var disk = new Distinst.Disk (disk_path); - if (disk == null) { - throw new GLib.IOError.FAILED ("Could not find %s", disk_path); - } - - var bootloader = Distinst.bootloader_detect (); - - var start_sector = Distinst.Sector () { - flag = Distinst.SectorKind.START, - value = 0 - }; - - // 256 MiB is the minimum distinst ESP partition size, so this is 256 MiB in MB plus a bit - // extra for safety - var efi_sector = Distinst.Sector () { - flag = Distinst.SectorKind.MEGABYTE, - value = 278 - }; - - // 1024MB /boot partition that's created if we're doing encryption - var boot_sector = Distinst.Sector () { - flag = Distinst.SectorKind.MEGABYTE, - value = efi_sector.value + 1024 - }; - - // 4GB swap partition at the end - var swap_sector = Distinst.Sector () { - flag = Distinst.SectorKind.MEGABYTE_FROM_END, - value = 4096 - }; - - var end_sector = Distinst.Sector () { - flag = Distinst.SectorKind.END, - value = 0 - }; - - // Prepares a new partition table. - int result = disk.mklabel (bootloader); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to write partition table to %s", disk_path); - } - - var start = disk.get_sector (ref start_sector); - var end = disk.get_sector (ref boot_sector); - - switch (bootloader) { - case Distinst.PartitionTable.MSDOS: - // This is used to ensure LVM installs will work with BIOS - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) - .partition_type (Distinst.PartitionType.PRIMARY) - .flag (Distinst.PartitionFlag.BOOT) - .mount ("/boot") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add boot partition to %s", disk_path); - } - - // Start the LVM from the end of our /boot partition - start = disk.get_sector (ref boot_sector); - break; - case Distinst.PartitionTable.GPT: - end = disk.get_sector (ref efi_sector); - - // A FAT32 partition is required for EFI installs - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.FAT32) - .partition_type (Distinst.PartitionType.PRIMARY) - .flag (Distinst.PartitionFlag.ESP) - .mount ("/boot/efi") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add EFI partition to %s", disk_path); - } - - // If we're encrypting, we need an unencrypted partition to store kernels and initramfs images - if (encryption != null) { - start = disk.get_sector (ref efi_sector); - end = disk.get_sector (ref boot_sector); - - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) - .partition_type (Distinst.PartitionType.PRIMARY) - .mount ("/boot") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("unable to add /boot partition to %s", disk_path); - } - - // Start the LVM from the end of our /boot/efi and /boot partitions - start = disk.get_sector (ref boot_sector); - } else { - // No encryption, we only have a /boot/efi partition, start the LVM from there - start = disk.get_sector (ref efi_sector); - } - - break; - } - - end = disk.get_sector (ref end_sector); - - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.LVM) - .partition_type (Distinst.PartitionType.PRIMARY) - .logical_volume (root_vg, encryption) - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add LVM partition to %s", disk_path); - } - - disks.push ((owned) disk); - - result = disks.initialize_volume_groups (); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to initialize volume groups on %s", disk_path); - } - - unowned Distinst.LvmDevice lvm_device = disks.get_logical_device (root_vg); - - if (lvm_device == null) { - throw new GLib.IOError.FAILED ("Unable to find '%s' volume group on %s", root_vg, disk_path); - } - - start = lvm_device.get_sector (ref start_sector); - end = lvm_device.get_sector (ref swap_sector); - - result = lvm_device.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) - .name ("root") - .mount ("/") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add / partition to LVM on %s", disk_path); - } - - start = lvm_device.get_sector (ref swap_sector); - end = lvm_device.get_sector (ref end_sector); - - result = lvm_device.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.SWAP) - .name ("swap") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add swap partition to LVM on %s", disk_path); - } - } - - private void custom_disk_configuration (Distinst.Disks disks, Mount[] mounts, LuksCredentials[] credentials) throws GLib.IOError { - Mount[] lvm_devices = {}; - - foreach (Mount m in mounts) { - if (m.is_lvm ()) { - lvm_devices += m; - } else { - unowned Distinst.Disk disk = disks.get_physical_device (m.parent_disk); - if (disk == null) { - var new_disk = new Distinst.Disk (m.parent_disk); - if (new_disk == null) { - throw new GLib.IOError.FAILED ("Could not find physical device: '%s'", m.parent_disk); - } - - disks.push ((owned) new_disk); - disk = disks.get_physical_device (m.parent_disk); - } - - unowned Distinst.Partition partition = disk.get_partition_by_path (m.partition_path); - - if (partition == null) { - throw new GLib.IOError.FAILED ("Could not find %s", m.partition_path); - } - - if (m.mount_point == "/boot/efi") { - if (m.is_valid_boot_mount ()) { - if (m.should_format ()) { - partition.format_with (to_distinst_fs (m.filesystem)); - } - - partition.set_mount (m.mount_point); - partition.set_flags ({ Distinst.PartitionFlag.ESP }); - } else { - throw new GLib.IOError.FAILED ("Unreachable code path -- EFI partition is invalid"); - } - } else { - if (m.filesystem != InstallerDaemon.FileSystem.SWAP) { - partition.set_mount (m.mount_point); - } - - if (m.mount_point == "/boot") { - partition.set_flags ({ Distinst.PartitionFlag.BOOT }); - } - - if (m.should_format ()) { - partition.format_with (to_distinst_fs (m.filesystem)); - } - } - } - } - - disks.initialize_volume_groups (); - - foreach (LuksCredentials cred in credentials) { - disks.decrypt_partition (cred.device, Distinst.LvmEncryption () { - physical_volume = cred.pv, - password = cred.password, - keydata = null - }); - } - - foreach (Mount m in lvm_devices) { - var vg = m.parent_disk.offset (12); - unowned Distinst.LvmDevice disk = disks.get_logical_device (vg); - if (disk == null) { - throw new GLib.IOError.FAILED ("Could not find %s", vg); - } - - unowned Distinst.Partition partition = disk.get_partition_by_path (m.partition_path); - - if (partition == null) { - throw new GLib.IOError.FAILED ("could not find %s", m.partition_path); - } - - if (m.filesystem != InstallerDaemon.FileSystem.SWAP) { - partition.set_mount (m.mount_point); - } - - if (m.should_format ()) { - partition.format_and_keep_name (to_distinst_fs (m.filesystem)); - } - } - } - - private static string string_from_utf8 (uint8[] input) { - var builder = new GLib.StringBuilder.sized (input.length); - builder.append_len ((string) input, input.length); - return (owned) builder.str; - } - - private InstallerDaemon.FileSystem to_common_fs (Distinst.FileSystem fs) { - switch (fs) { - case BTRFS: - return InstallerDaemon.FileSystem.BTRFS; - case EXT2: - return InstallerDaemon.FileSystem.EXT2; - case EXT3: - return InstallerDaemon.FileSystem.EXT3; - case EXT4: - return InstallerDaemon.FileSystem.EXT4; - case F2FS: - return InstallerDaemon.FileSystem.F2FS; - case FAT16: - return InstallerDaemon.FileSystem.FAT16; - case FAT32: - return InstallerDaemon.FileSystem.FAT32; - case NONE: - return InstallerDaemon.FileSystem.NONE; - case NTFS: - return InstallerDaemon.FileSystem.NTFS; - case SWAP: - return InstallerDaemon.FileSystem.SWAP; - case XFS: - return InstallerDaemon.FileSystem.XFS; - case LVM: - return InstallerDaemon.FileSystem.LVM; - case LUKS: - return InstallerDaemon.FileSystem.LUKS; - default: - return InstallerDaemon.FileSystem.NONE; - } - } - - private InstallerDaemon.PartitionUsage to_common_usage (Distinst.PartitionUsage usage) { - return InstallerDaemon.PartitionUsage () { - tag = usage.tag, - value = usage.value - }; - } - - private Distinst.FileSystem to_distinst_fs (InstallerDaemon.FileSystem fs) { - switch (fs) { - case BTRFS: - return Distinst.FileSystem.BTRFS; - case EXT2: - return Distinst.FileSystem.EXT2; - case EXT3: - return Distinst.FileSystem.EXT3; - case EXT4: - return Distinst.FileSystem.EXT4; - case F2FS: - return Distinst.FileSystem.F2FS; - case FAT16: - return Distinst.FileSystem.FAT16; - case FAT32: - return Distinst.FileSystem.FAT32; - case NONE: - return Distinst.FileSystem.NONE; - case NTFS: - return Distinst.FileSystem.NTFS; - case SWAP: - return Distinst.FileSystem.SWAP; - case XFS: - return Distinst.FileSystem.XFS; - case LVM: - return Distinst.FileSystem.LVM; - case LUKS: - return Distinst.FileSystem.LUKS; - default: - return Distinst.FileSystem.NONE; - } - } - - private InstallerDaemon.PartitionTable to_common_usage_bootloader (Distinst.PartitionTable bootloader) { - switch (bootloader) { - case GPT: - return InstallerDaemon.PartitionTable.GPT; - case MSDOS: - return InstallerDaemon.PartitionTable.MSDOS; - case NONE: - default: - return InstallerDaemon.PartitionTable.NONE; - } - } - - private InstallerDaemon.LogLevel to_common_log_level (Distinst.LogLevel level) { - switch (level) { - case DEBUG: - return InstallerDaemon.LogLevel.DEBUG; - case INFO: - return InstallerDaemon.LogLevel.INFO; - case WARN: - return InstallerDaemon.LogLevel.WARN; - case ERROR: - return InstallerDaemon.LogLevel.ERROR; - case TRACE: - default: - return InstallerDaemon.LogLevel.TRACE; - } - } - - private InstallerDaemon.Error to_common_error (Distinst.Error error) { - return InstallerDaemon.Error () { - step = to_common_step (error.step), - err = error.err - }; - } - - private InstallerDaemon.Step to_common_step (Distinst.Step step) { - switch (step) { - case BACKUP: - return InstallerDaemon.Step.BACKUP; - case PARTITION: - return InstallerDaemon.Step.PARTITION; - case EXTRACT: - return InstallerDaemon.Step.EXTRACT; - case CONFIGURE: - return InstallerDaemon.Step.CONFIGURE; - case BOOTLOADER: - return InstallerDaemon.Step.BOOTLOADER; - case INIT: - default: - return InstallerDaemon.Step.INIT; - } - } - - private InstallerDaemon.Status to_common_status (Distinst.Status status) { - return InstallerDaemon.Status () { - step = to_common_step (status.step), - percent = status.percent - }; - } -} - private void on_bus_acquired (GLib.DBusConnection connection, string name) { try { - connection.register_object ("/io/elementary/InstallerDaemon", new InstallerDaemon.Daemon ()); +#if DISTINST_BACKEND + connection.register_object ("/io/elementary/InstallerDaemon", new InstallerDaemon.DistinstBackend ()); +#endif } catch (GLib.Error e) { critical ("Unable to register the object: %s", e.message); } diff --git a/daemon/DistinstBackend.vala b/daemon/DistinstBackend.vala new file mode 100644 index 000000000..b356ba868 --- /dev/null +++ b/daemon/DistinstBackend.vala @@ -0,0 +1,656 @@ +/* + * Copyright 2021 elementary, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +[DBus (name = "io.elementary.InstallerDaemon")] +public class InstallerDaemon.DistinstBackend : GLib.Object { + public signal void on_log_message (InstallerDaemon.LogLevel level, string message); + public signal void on_status (InstallerDaemon.Status status); + public signal void on_error (InstallerDaemon.Error error); + + private Distinst.Disks disks; + + construct { + Distinst.log ((level, message) => { + Idle.add (() => { + on_log_message (to_common_log_level (level), message); + }); + }); + } + + public InstallerDaemon.PartitionTable bootloader_detect () throws GLib.Error { + return to_common_usage_bootloader (Distinst.bootloader_detect ()); + } + + public DiskInfo get_disks (bool get_partitions = false) throws GLib.Error { + disks = Distinst.Disks.probe (); + + if (get_partitions) { + disks.initialize_volume_groups (); + } + + DiskInfo result = DiskInfo (); + + Disk[] physical_disks = {}; + Disk[] logical_disks = {}; + + foreach (unowned Distinst.Disk disk in disks.list ()) { + if (disk.is_read_only ()) { + continue; + } + + // Skip root disk or live disk + if (disk.contains_mount ("/", disks) || disk.contains_mount ("/cdrom", disks)) { + continue; + } + + Partition[] partitions = {}; + + if (get_partitions) { + foreach (unowned Distinst.Partition part in disk.list_partitions ()) { + string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) + ? string_from_utf8 (part.get_current_lvm_volume_group ()) + : ""; + + partitions += Partition () { + device_path = string_from_utf8 (part.get_device_path ()), + filesystem = to_common_fs (part.get_file_system ()), + start_sector = part.get_start_sector (), + end_sector = part.get_end_sector (), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), + current_lvm_volume_group = lvm_vg + }; + } + } + + string model = string_from_utf8 (disk.get_model ()); + string name = model.length == 0 ? string_from_utf8 (disk.get_serial ()).replace ("_", " ") : model; + + physical_disks += Disk () { + name = name, + device_path = string_from_utf8 (disk.get_device_path ()), + sectors = disk.get_sectors (), + sector_size = disk.get_sector_size (), + rotational = disk.is_rotational (), + removable = disk.is_removable (), + partitions = partitions + }; + } + + if (get_partitions) { + foreach (unowned Distinst.LvmDevice disk in disks.list_logical ()) { + Partition[] partitions = {}; + + foreach (unowned Distinst.Partition part in disk.list_partitions ()) { + string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) + ? string_from_utf8 (part.get_current_lvm_volume_group ()) + : ""; + + partitions += Partition () { + device_path = string_from_utf8 (part.get_device_path ()), + filesystem = to_common_fs (part.get_file_system ()), + start_sector = part.get_start_sector (), + end_sector = part.get_end_sector (), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), + current_lvm_volume_group = lvm_vg + }; + } + + logical_disks += Disk () { + name = string_from_utf8 (disk.get_model ()), + device_path = string_from_utf8 (disk.get_device_path ()), + sectors = disk.get_sectors (), + sector_size = disk.get_sector_size (), + partitions = partitions + }; + } + } + + result.physical_disks = physical_disks; + result.logical_disks = logical_disks; + return result; + } + + public int decrypt_partition (string path, string pv, string password) throws GLib.Error { + return disks.decrypt_partition (path, Distinst.LvmEncryption () { + physical_volume = pv, + password = password, + keydata = null + }); + } + + public Disk get_logical_device (string pv) throws GLib.Error { + unowned Distinst.LvmDevice disk = disks.get_logical_device (pv); + if (disk == null) { + throw new GLib.IOError.NOT_FOUND ("Couldn't find a logical device with that name"); + } + + Partition[] partitions = {}; + + foreach (unowned Distinst.Partition part in disk.list_partitions ()) { + string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) + ? string_from_utf8 (part.get_current_lvm_volume_group ()) + : ""; + + partitions += Partition () { + device_path = string_from_utf8 (part.get_device_path ()), + filesystem = to_common_fs (part.get_file_system ()), + start_sector = part.get_start_sector (), + end_sector = part.get_end_sector (), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), + current_lvm_volume_group = lvm_vg + }; + } + + return Disk () { + name = string_from_utf8 (disk.get_model ()), + device_path = string_from_utf8 (disk.get_device_path ()), + sectors = disk.get_sectors (), + sector_size = disk.get_sector_size (), + partitions = partitions + }; + } + + public void install_with_default_disk_layout (InstallConfig config, string disk, bool encrypt, string encryption_password) throws GLib.Error { + var disks = new Distinst.Disks (); + default_disk_configuration (disks, disk, encrypt ? encryption_password : null); + + install (config, (owned) disks); + } + + public void install_with_custom_disk_layout (InstallConfig config, Mount[] disk_config, LuksCredentials[] credentials) throws GLib.Error { + var disks = new Distinst.Disks (); + custom_disk_configuration (disks, disk_config, credentials); + + install (config, (owned) disks); + } + + private void install (InstallConfig config, owned Distinst.Disks disks) { + var installer = new Distinst.Installer (); + installer.on_error ((error) => on_error (to_common_error (error))); + installer.on_status ((status) => on_status (to_common_status (status))); + + var distinst_config = Distinst.Config (); + uint8 flags = 0; + if (config.modify_boot_order) { + flags = Distinst.MODIFY_BOOT_ORDER; + } + + if (config.install_drivers) { + flags |= Distinst.RUN_UBUNTU_DRIVERS; + } + + distinst_config.flags = flags; + distinst_config.hostname = config.hostname; + + var casper = casper_dir (); + distinst_config.remove = GLib.Path.build_filename (casper, "filesystem.manifest-remove"); + distinst_config.squashfs = GLib.Path.build_filename (casper, "filesystem.squashfs"); + + debug ("language: %s\n", config.lang); + distinst_config.lang = config.lang; + + distinst_config.keyboard_layout = config.keyboard_layout; + distinst_config.keyboard_model = null; + distinst_config.keyboard_variant = config.keyboard_variant == "" ? null : config.keyboard_variant; + + new Thread (null, () => { + if (installer.install ((owned) disks, distinst_config) != 0) { + Idle.add (() => { + on_error (InstallerDaemon.Error ()); + return GLib.Source.REMOVE; + }); + } + + return null; + }); + } + + public void set_demo_mode_locale (string locale) throws GLib.Error { + GLib.FileUtils.set_contents ("/etc/default/locale", "LANG=" + locale); + } + + public void trigger_demo_mode () throws GLib.Error { + var demo_mode_file = GLib.File.new_for_path ("/var/lib/lightdm/demo-mode"); + try { + demo_mode_file.create (GLib.FileCreateFlags.NONE); + } catch (GLib.Error e) { + if (!(e is GLib.IOError.EXISTS)) { + throw e; + } + } + } + + private string casper_dir () { + const string CDROM = "/cdrom"; + + try { + var cdrom_dir = File.new_for_path (CDROM); + var iter = cdrom_dir.enumerate_children (FileAttribute.STANDARD_NAME, 0); + + FileInfo info; + while ((info = iter.next_file ()) != null) { + unowned string name = info.get_name (); + if (name.has_prefix ("casper")) { + return GLib.Path.build_filename (CDROM, name); + } + } + } catch (GLib.Error e) { + critical ("failed to find casper dir automatically: %s\n", e.message); + } + + return GLib.Path.build_filename (CDROM, "casper"); + } + + private void default_disk_configuration (Distinst.Disks disks, string disk_path, string? encryption_password) throws GLib.IOError { + var encrypted_vg = Distinst.generate_unique_id ("cryptdata"); + var root_vg = Distinst.generate_unique_id ("data"); + if (encrypted_vg == null || root_vg == null) { + throw new GLib.IOError.FAILED ("Unable to generate unique volume group IDs"); + } + + Distinst.LvmEncryption? encryption; + if (encryption_password != null) { + debug ("encrypting"); + encryption = Distinst.LvmEncryption () { + physical_volume = encrypted_vg, + password = encryption_password, + keydata = null + }; + } else { + debug ("not encrypting"); + encryption = null; + } + + debug ("disk: %s\n", disk_path); + var disk = new Distinst.Disk (disk_path); + if (disk == null) { + throw new GLib.IOError.FAILED ("Could not find %s", disk_path); + } + + var bootloader = Distinst.bootloader_detect (); + + var start_sector = Distinst.Sector () { + flag = Distinst.SectorKind.START, + value = 0 + }; + + // 256 MiB is the minimum distinst ESP partition size, so this is 256 MiB in MB plus a bit + // extra for safety + var efi_sector = Distinst.Sector () { + flag = Distinst.SectorKind.MEGABYTE, + value = 278 + }; + + // 1024MB /boot partition that's created if we're doing encryption + var boot_sector = Distinst.Sector () { + flag = Distinst.SectorKind.MEGABYTE, + value = efi_sector.value + 1024 + }; + + // 4GB swap partition at the end + var swap_sector = Distinst.Sector () { + flag = Distinst.SectorKind.MEGABYTE_FROM_END, + value = 4096 + }; + + var end_sector = Distinst.Sector () { + flag = Distinst.SectorKind.END, + value = 0 + }; + + // Prepares a new partition table. + int result = disk.mklabel (bootloader); + + if (result != 0) { + throw new GLib.IOError.FAILED ("Unable to write partition table to %s", disk_path); + } + + var start = disk.get_sector (ref start_sector); + var end = disk.get_sector (ref boot_sector); + + switch (bootloader) { + case Distinst.PartitionTable.MSDOS: + // This is used to ensure LVM installs will work with BIOS + result = disk.add_partition ( + new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) + .partition_type (Distinst.PartitionType.PRIMARY) + .flag (Distinst.PartitionFlag.BOOT) + .mount ("/boot") + ); + + if (result != 0) { + throw new GLib.IOError.FAILED ("Unable to add boot partition to %s", disk_path); + } + + // Start the LVM from the end of our /boot partition + start = disk.get_sector (ref boot_sector); + break; + case Distinst.PartitionTable.GPT: + end = disk.get_sector (ref efi_sector); + + // A FAT32 partition is required for EFI installs + result = disk.add_partition ( + new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.FAT32) + .partition_type (Distinst.PartitionType.PRIMARY) + .flag (Distinst.PartitionFlag.ESP) + .mount ("/boot/efi") + ); + + if (result != 0) { + throw new GLib.IOError.FAILED ("Unable to add EFI partition to %s", disk_path); + } + + // If we're encrypting, we need an unencrypted partition to store kernels and initramfs images + if (encryption != null) { + start = disk.get_sector (ref efi_sector); + end = disk.get_sector (ref boot_sector); + + result = disk.add_partition ( + new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) + .partition_type (Distinst.PartitionType.PRIMARY) + .mount ("/boot") + ); + + if (result != 0) { + throw new GLib.IOError.FAILED ("unable to add /boot partition to %s", disk_path); + } + + // Start the LVM from the end of our /boot/efi and /boot partitions + start = disk.get_sector (ref boot_sector); + } else { + // No encryption, we only have a /boot/efi partition, start the LVM from there + start = disk.get_sector (ref efi_sector); + } + + break; + } + + end = disk.get_sector (ref end_sector); + + result = disk.add_partition ( + new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.LVM) + .partition_type (Distinst.PartitionType.PRIMARY) + .logical_volume (root_vg, encryption) + ); + + if (result != 0) { + throw new GLib.IOError.FAILED ("Unable to add LVM partition to %s", disk_path); + } + + disks.push ((owned) disk); + + result = disks.initialize_volume_groups (); + + if (result != 0) { + throw new GLib.IOError.FAILED ("Unable to initialize volume groups on %s", disk_path); + } + + unowned Distinst.LvmDevice lvm_device = disks.get_logical_device (root_vg); + + if (lvm_device == null) { + throw new GLib.IOError.FAILED ("Unable to find '%s' volume group on %s", root_vg, disk_path); + } + + start = lvm_device.get_sector (ref start_sector); + end = lvm_device.get_sector (ref swap_sector); + + result = lvm_device.add_partition ( + new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) + .name ("root") + .mount ("/") + ); + + if (result != 0) { + throw new GLib.IOError.FAILED ("Unable to add / partition to LVM on %s", disk_path); + } + + start = lvm_device.get_sector (ref swap_sector); + end = lvm_device.get_sector (ref end_sector); + + result = lvm_device.add_partition ( + new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.SWAP) + .name ("swap") + ); + + if (result != 0) { + throw new GLib.IOError.FAILED ("Unable to add swap partition to LVM on %s", disk_path); + } + } + + private void custom_disk_configuration (Distinst.Disks disks, Mount[] mounts, LuksCredentials[] credentials) throws GLib.IOError { + Mount[] lvm_devices = {}; + + foreach (Mount m in mounts) { + if (m.is_lvm ()) { + lvm_devices += m; + } else { + unowned Distinst.Disk disk = disks.get_physical_device (m.parent_disk); + if (disk == null) { + var new_disk = new Distinst.Disk (m.parent_disk); + if (new_disk == null) { + throw new GLib.IOError.FAILED ("Could not find physical device: '%s'", m.parent_disk); + } + + disks.push ((owned) new_disk); + disk = disks.get_physical_device (m.parent_disk); + } + + unowned Distinst.Partition partition = disk.get_partition_by_path (m.partition_path); + + if (partition == null) { + throw new GLib.IOError.FAILED ("Could not find %s", m.partition_path); + } + + if (m.mount_point == "/boot/efi") { + if (m.is_valid_boot_mount ()) { + if (m.should_format ()) { + partition.format_with (to_distinst_fs (m.filesystem)); + } + + partition.set_mount (m.mount_point); + partition.set_flags ({ Distinst.PartitionFlag.ESP }); + } else { + throw new GLib.IOError.FAILED ("Unreachable code path -- EFI partition is invalid"); + } + } else { + if (m.filesystem != InstallerDaemon.FileSystem.SWAP) { + partition.set_mount (m.mount_point); + } + + if (m.mount_point == "/boot") { + partition.set_flags ({ Distinst.PartitionFlag.BOOT }); + } + + if (m.should_format ()) { + partition.format_with (to_distinst_fs (m.filesystem)); + } + } + } + } + + disks.initialize_volume_groups (); + + foreach (LuksCredentials cred in credentials) { + disks.decrypt_partition (cred.device, Distinst.LvmEncryption () { + physical_volume = cred.pv, + password = cred.password, + keydata = null + }); + } + + foreach (Mount m in lvm_devices) { + var vg = m.parent_disk.offset (12); + unowned Distinst.LvmDevice disk = disks.get_logical_device (vg); + if (disk == null) { + throw new GLib.IOError.FAILED ("Could not find %s", vg); + } + + unowned Distinst.Partition partition = disk.get_partition_by_path (m.partition_path); + + if (partition == null) { + throw new GLib.IOError.FAILED ("could not find %s", m.partition_path); + } + + if (m.filesystem != InstallerDaemon.FileSystem.SWAP) { + partition.set_mount (m.mount_point); + } + + if (m.should_format ()) { + partition.format_and_keep_name (to_distinst_fs (m.filesystem)); + } + } + } + + private static string string_from_utf8 (uint8[] input) { + var builder = new GLib.StringBuilder.sized (input.length); + builder.append_len ((string) input, input.length); + return (owned) builder.str; + } + + private InstallerDaemon.FileSystem to_common_fs (Distinst.FileSystem fs) { + switch (fs) { + case BTRFS: + return InstallerDaemon.FileSystem.BTRFS; + case EXT2: + return InstallerDaemon.FileSystem.EXT2; + case EXT3: + return InstallerDaemon.FileSystem.EXT3; + case EXT4: + return InstallerDaemon.FileSystem.EXT4; + case F2FS: + return InstallerDaemon.FileSystem.F2FS; + case FAT16: + return InstallerDaemon.FileSystem.FAT16; + case FAT32: + return InstallerDaemon.FileSystem.FAT32; + case NONE: + return InstallerDaemon.FileSystem.NONE; + case NTFS: + return InstallerDaemon.FileSystem.NTFS; + case SWAP: + return InstallerDaemon.FileSystem.SWAP; + case XFS: + return InstallerDaemon.FileSystem.XFS; + case LVM: + return InstallerDaemon.FileSystem.LVM; + case LUKS: + return InstallerDaemon.FileSystem.LUKS; + default: + return InstallerDaemon.FileSystem.NONE; + } + } + + private InstallerDaemon.PartitionUsage to_common_usage (Distinst.PartitionUsage usage) { + return InstallerDaemon.PartitionUsage () { + tag = usage.tag, + value = usage.value + }; + } + + private Distinst.FileSystem to_distinst_fs (InstallerDaemon.FileSystem fs) { + switch (fs) { + case BTRFS: + return Distinst.FileSystem.BTRFS; + case EXT2: + return Distinst.FileSystem.EXT2; + case EXT3: + return Distinst.FileSystem.EXT3; + case EXT4: + return Distinst.FileSystem.EXT4; + case F2FS: + return Distinst.FileSystem.F2FS; + case FAT16: + return Distinst.FileSystem.FAT16; + case FAT32: + return Distinst.FileSystem.FAT32; + case NONE: + return Distinst.FileSystem.NONE; + case NTFS: + return Distinst.FileSystem.NTFS; + case SWAP: + return Distinst.FileSystem.SWAP; + case XFS: + return Distinst.FileSystem.XFS; + case LVM: + return Distinst.FileSystem.LVM; + case LUKS: + return Distinst.FileSystem.LUKS; + default: + return Distinst.FileSystem.NONE; + } + } + + private InstallerDaemon.PartitionTable to_common_usage_bootloader (Distinst.PartitionTable bootloader) { + switch (bootloader) { + case GPT: + return InstallerDaemon.PartitionTable.GPT; + case MSDOS: + return InstallerDaemon.PartitionTable.MSDOS; + case NONE: + default: + return InstallerDaemon.PartitionTable.NONE; + } + } + + private InstallerDaemon.LogLevel to_common_log_level (Distinst.LogLevel level) { + switch (level) { + case DEBUG: + return InstallerDaemon.LogLevel.DEBUG; + case INFO: + return InstallerDaemon.LogLevel.INFO; + case WARN: + return InstallerDaemon.LogLevel.WARN; + case ERROR: + return InstallerDaemon.LogLevel.ERROR; + case TRACE: + default: + return InstallerDaemon.LogLevel.TRACE; + } + } + + private InstallerDaemon.Error to_common_error (Distinst.Error error) { + return InstallerDaemon.Error () { + step = to_common_step (error.step), + err = error.err + }; + } + + private InstallerDaemon.Step to_common_step (Distinst.Step step) { + switch (step) { + case BACKUP: + return InstallerDaemon.Step.BACKUP; + case PARTITION: + return InstallerDaemon.Step.PARTITION; + case EXTRACT: + return InstallerDaemon.Step.EXTRACT; + case CONFIGURE: + return InstallerDaemon.Step.CONFIGURE; + case BOOTLOADER: + return InstallerDaemon.Step.BOOTLOADER; + case INIT: + default: + return InstallerDaemon.Step.INIT; + } + } + + private InstallerDaemon.Status to_common_status (Distinst.Status status) { + return InstallerDaemon.Status () { + step = to_common_step (status.step), + percent = status.percent + }; + } +} diff --git a/daemon/meson.build b/daemon/meson.build index f041264cc..f4a07ee25 100644 --- a/daemon/meson.build +++ b/daemon/meson.build @@ -4,13 +4,22 @@ vala_files = [ ] daemon_dependencies = [ - distinst_dep, gee_dep, glib_dep, gio_dep, gobject_dep, ] +args = '' + +if installer_backend == 'distinst' + vala_files += ['DistinstBackend.vala'] + daemon_dependencies += [distinst_dep] + args += '--define=DISTINST_BACKEND' +else + error('No supported installer backend provided') +endif + systemdunitdir = systemd_dep.get_pkgconfig_variable('systemdsystemunitdir') install_data( @@ -22,4 +31,5 @@ install_data('io.elementary.InstallerDaemon.conf', install_dir : get_option('dat executable(meson.project_name() + '-daemon', vala_files, dependencies : daemon_dependencies, + vala_args : args, install: true) diff --git a/meson.build b/meson.build index a89a27857..ecd03a888 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,6 @@ add_project_arguments(['--vapidir', join_paths(meson.current_source_dir(), 'vapi gnome = import('gnome') i18n = import('i18n') -distinst_dep = dependency('distinst') glib_dep = dependency('glib-2.0') gobject_dep = dependency('gobject-2.0') gtk_dep = dependency('gtk+-3.0') @@ -27,6 +26,13 @@ gnome_keyboard_ui_dep = meson.get_compiler('c').find_library('gnomekbdui') pwquality_dep = dependency('pwquality') systemd_dep = dependency('systemd') +installer_backend = get_option('installer_backend') +if installer_backend == 'distinst' + distinst_dep = dependency('distinst') +else + error('No supported installer backend provided') +endif + asresources = gnome.compile_resources( 'as-resources', 'data/' + meson.project_name() + '.gresource.xml', source_dir: 'data', diff --git a/meson_options.txt b/meson_options.txt index fefae3b5e..7973bb2a5 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,2 +1,3 @@ option('supported_languages', type : 'string', value : 'aa;ab;ae;af;ak;am;an;ar;as;ast;av;ay;az;ba;be;bg;bh;bi;bm;bn;bo;br;bs;ca;ce;ch;ckb;co;cr;cs;cu;cv;cy;da;de;de_CH;de_DE;dv;dz;ee;el;en;en_US;en_AU;en_CA;en_GB;eo;es;et;eu;fa;ff;fi;fj;fo;fr;fr_BE;fr_CA;fr_FR;fy;ga;gd;gl;gn;gu;gv;ha;he;hi;ho;hr;ht;hu;hy;hz;ia;id;ie;ig;ii;ik;io;is;it;iu;ja;jv;ka;kab;kg;ki;kj;kk;kl;km;kn;ko;kr;ks;ku;kv;kw;ky;la;lb;lg;li;ln;lo;lt;lu;lv;mg;mh;mi;mk;ml;mn;mo;mr;ms;mt;my;na;nb;nd;ne;ng;nl;nn;no;nr;nv;ny;oc;oj;om;or;os;pa;pi;pl;ps;pt;pt_PT;pt_BR;qu;rm;rn;ro;ru;rue;rw;sa;sc;sd;se;sg;si;sk;sl;sm;sma;sn;so;sq;sr;ss;st;su;sv;sw;szl;ta;te;tg;th;ti;tk;tl;tn;to;tr;ts;tt;tw;ty;udm;ug;uk;ur;uz;ve;vi;vo;wa;wo;xh;yi;yo;za;zh;zh_CN;zh_HK;zh_TW;zu', description : 'The list of supported languages') option('preferred_languages', type : 'string', value : 'en;zh;es;fr;pt;ru;de', description : 'A prioritized list of languages') +option('installer_backend', type : 'combo', choices : ['distinst'], value : 'distinst') From 400d56773ec59f7ed84cdbf631ef1e28024a1e3d Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 9 Nov 2023 21:23:18 +0100 Subject: [PATCH 13/23] Satisfy linter --- src/Views/ProgressView.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/ProgressView.vala b/src/Views/ProgressView.vala index 9759d4289..fb3e20a8e 100644 --- a/src/Views/ProgressView.vala +++ b/src/Views/ProgressView.vala @@ -135,7 +135,7 @@ public class ProgressView : AbstractInstallerView { var config = InstallerDaemon.InstallConfig (); config.modify_boot_order = true; if (current_config.install_drivers) { - config.install_drivers = true; + config.install_drivers = true; } config.hostname = Utils.get_hostname (); config.lang = "en_US.UTF-8"; From a27bda796ff3c30b2f79fd60c4d2b68bdf921495 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Sat, 11 Nov 2023 06:17:15 +0100 Subject: [PATCH 14/23] DBusStructures: Refactor to unowned reference --- common/DBusStructures.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 8a5ec8b18..eaa64cecd 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -46,7 +46,7 @@ public enum InstallerDaemon.FileSystem { LVM, LUKS; - public string to_string () { + public unowned string to_string () { switch (this) { case BTRFS: return "btrfs"; From 3ad086a021a42e87843e56abe718a0059cce8ab7 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Wed, 25 Sep 2024 12:15:30 +0000 Subject: [PATCH 15/23] Merge main --- common/DBusStructures.vala | 45 +++++++++++++++++++++++++++++++++ daemon/Daemon.vala | 15 ++++++++--- src/Views/PartitioningView.vala | 6 ++--- src/Views/ProgressView.vala | 4 +-- 4 files changed, 61 insertions(+), 9 deletions(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index ece02c669..9c6cafd23 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -97,6 +97,7 @@ public struct InstallerDaemon.InstallConfig { string lang; bool modify_boot_order; bool install_drivers; + uint8 flags; } [Flags] @@ -139,3 +140,47 @@ public struct InstallerDaemon.LuksCredentials { string pv; string password; } + +public enum InstallerDaemon.LogLevel { + TRACE, + DEBUG, + INFO, + WARN, + ERROR; +} + +public struct InstallerDaemon.Error { + Step step; + int err; +} + +public enum InstallerDaemon.Step { + BACKUP, + INIT, + PARTITION, + EXTRACT, + CONFIGURE, + BOOTLOADER; +} + +public struct InstallerDaemon.Status { + Step step; + int percent; +} + +public struct InstallerDaemon.PartitionUsage { + /** + * None = 0; Some(usage) = 1; + */ + public uint8 tag; + /** + * The size, in sectors, that a partition is used. + */ + public uint64 value; +} + +public enum InstallerDaemon.PartitionTable { + NONE, + GPT, + MSDOS; +} diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index 0ccc1f7db..5e605728d 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -72,7 +72,7 @@ public class InstallerDaemon.Daemon : GLib.Object { filesystem = to_common_fs (part.get_file_system ()), start_sector = part.get_start_sector (), end_sector = part.get_end_sector (), - sectors_used = part.sectors_used (disk.get_sector_size ()), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), current_lvm_volume_group = lvm_vg }; } @@ -106,7 +106,7 @@ public class InstallerDaemon.Daemon : GLib.Object { filesystem = to_common_fs (part.get_file_system ()), start_sector = part.get_start_sector (), end_sector = part.get_end_sector (), - sectors_used = part.sectors_used (disk.get_sector_size ()), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), current_lvm_volume_group = lvm_vg }; } @@ -152,7 +152,7 @@ public class InstallerDaemon.Daemon : GLib.Object { filesystem = to_common_fs (part.get_file_system ()), start_sector = part.get_start_sector (), end_sector = part.get_end_sector (), - sectors_used = part.sectors_used (disk.get_sector_size ()), + sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), current_lvm_volume_group = lvm_vg }; } @@ -220,7 +220,7 @@ public class InstallerDaemon.Daemon : GLib.Object { var demo_mode_file = GLib.File.new_for_path ("/var/lib/lightdm/demo-mode"); try { demo_mode_file.create (GLib.FileCreateFlags.NONE); - } catch (Error e) { + } catch (GLib.Error e) { if (!(e is GLib.IOError.EXISTS)) { throw e; } @@ -547,6 +547,13 @@ public class InstallerDaemon.Daemon : GLib.Object { } } + private InstallerDaemon.PartitionUsage to_common_usage (Distinst.PartitionUsage usage) { + return InstallerDaemon.PartitionUsage () { + tag = usage.tag, + value = usage.value + }; + } + private Distinst.FileSystem to_distinst_fs (InstallerDaemon.FileSystem fs) { switch (fs) { case BTRFS: diff --git a/src/Views/PartitioningView.vala b/src/Views/PartitioningView.vala index d6f52bf17..d751b4751 100644 --- a/src/Views/PartitioningView.vala +++ b/src/Views/PartitioningView.vala @@ -238,7 +238,7 @@ public class Installer.PartitioningView : AbstractInstallerView { switch (bootloader) { case MSDOS: break; - case Distinst.PartitionTable.GPT: + case InstallerDaemon.PartitionTable.GPT: break; } @@ -344,7 +344,7 @@ public class Installer.PartitioningView : AbstractInstallerView { InstallerDaemon.Partition[] partitions = {}; - var usage_1 = Distinst.PartitionUsage () { + var usage_1 = InstallerDaemon.PartitionUsage () { tag = 1, value = 30312 }; @@ -358,7 +358,7 @@ public class Installer.PartitioningView : AbstractInstallerView { current_lvm_volume_group = "" }; - var usage_2 = Distinst.PartitionUsage () { + var usage_2 = InstallerDaemon.PartitionUsage () { tag = 0, value = 0 }; diff --git a/src/Views/ProgressView.vala b/src/Views/ProgressView.vala index a2a86a94e..3c7450574 100644 --- a/src/Views/ProgressView.vala +++ b/src/Views/ProgressView.vala @@ -196,11 +196,11 @@ public class ProgressView : Adw.NavigationPage { } } - private void fake_status (Distinst.Step step) { + private void fake_status (InstallerDaemon.Step step) { unowned var log_helper = LogHelper.get_default (); for (var percent = 0; percent <= 100; percent++) { log_helper.log_func (INFO, "I'm faking it!"); - Distinst.Status status = Distinst.Status () { + InstallerDaemon.Status status = InstallerDaemon.Status () { step = step, percent = percent }; From aab202c5ad6cf4d54c5a33527878613f1b347f6d Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Wed, 25 Sep 2024 15:00:36 +0200 Subject: [PATCH 16/23] Improve logging --- src/Helpers/LocaleHelper.vala | 10 ++++++---- src/MainWindow.vala | 2 +- src/Utils.vala | 16 ++++++++-------- src/Views/CheckView.vala | 6 +++--- 4 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/Helpers/LocaleHelper.vala b/src/Helpers/LocaleHelper.vala index 13b538de2..927b42930 100644 --- a/src/Helpers/LocaleHelper.vala +++ b/src/Helpers/LocaleHelper.vala @@ -54,8 +54,9 @@ namespace LocaleHelper { var langs = Build.LANG_LIST.split (";"); var parser = new Json.Parser (); + string ISO_639_3_PATH = "%s/iso_639-3.json".printf (Build.ISO_CODES_LOCATION); try { - parser.load_from_file ("%s/iso_639-3.json".printf (Build.ISO_CODES_LOCATION)); + parser.load_from_file (ISO_639_3_PATH); weak Json.Object root_object = parser.get_root ().get_object (); weak Json.Array 639_3_array = root_object.get_array_member ("639-3"); foreach (unowned Json.Node element in 639_3_array.get_elements ()) { @@ -73,13 +74,14 @@ namespace LocaleHelper { } } } catch (Error e) { - critical (e.message); + critical ("Unable to parse '%s': %s", ISO_639_3_PATH, e.message); } var countries = new Gee.HashMap (); parser = new Json.Parser (); + string ISO_3166_1_PATH = "%s/iso_3166-1.json".printf (Build.ISO_CODES_LOCATION); try { - parser.load_from_file ("%s/iso_3166-1.json".printf (Build.ISO_CODES_LOCATION)); + parser.load_from_file (ISO_3166_1_PATH); weak Json.Object root_object = parser.get_root ().get_object (); weak Json.Array 3166_1_array = root_object.get_array_member ("3166-1"); foreach (unowned Json.Node element in 3166_1_array.get_elements ()) { @@ -98,7 +100,7 @@ namespace LocaleHelper { countries[entry.alpha_2] = entry; } } catch (Error e) { - critical (e.message); + critical ("Unable to parse '%s': %s", ISO_3166_1_PATH, e.message); } foreach (var lang in langs) { diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 2faf178f8..e0ae0bf16 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -93,7 +93,7 @@ public class Installer.MainWindow : Gtk.Window { } }); } catch (Error e) { - warning (e.message); + warning ("Unable to query upower: %s", e.message); battery_infobar.revealed = false; } diff --git a/src/Utils.vala b/src/Utils.vala index 8c7afcc34..7b008c8f2 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -38,7 +38,7 @@ namespace Utils { try { system_instance.power_off (false); } catch (GLib.Error e) { - critical (e.message); + critical ("Unable to shutdown: %s", e.message); } } } @@ -52,7 +52,7 @@ namespace Utils { try { system_instance.reboot (false); } catch (GLib.Error e) { - critical (e.message); + critical ("Unable to restart: %s", e.message); } } } @@ -102,7 +102,7 @@ namespace Utils { "/org/freedesktop/login1" ); } catch (GLib.Error e) { - warning ("%s", e.message); + warning ("Unable to get system instance: %s", e.message); } } } @@ -145,7 +145,7 @@ namespace Utils { "/org/freedesktop/hostname1" ); } catch (GLib.Error e) { - warning ("%s", e.message); + warning ("Unable to get hostname instance: %s", e.message); } } } @@ -161,7 +161,7 @@ namespace Utils { try { FileUtils.get_contents ("/etc/machine-id", out machine_id); } catch (FileError e) { - warning ("%s", e.message); + warning ("Unable to get machine id: %s", e.message); return null; } @@ -173,7 +173,7 @@ namespace Utils { try { FileUtils.get_contents ("/sys/devices/virtual/dmi/id/sys_vendor", out vendor); } catch (FileError e) { - warning ("%s", e.message); + warning ("Unable to get sys vendor: %s", e.message); return null; } @@ -185,7 +185,7 @@ namespace Utils { try { FileUtils.get_contents ("/sys/devices/virtual/dmi/id/product_name", out model); } catch (FileError e) { - warning ("%s", e.message); + warning ("Unable to get product name: %s", e.message); return null; } @@ -197,7 +197,7 @@ namespace Utils { try { FileUtils.get_contents ("/sys/devices/virtual/dmi/id/product_version", out model); } catch (FileError e) { - warning ("%s", e.message); + warning ("Unable to get product version: %s", e.message); return null; } diff --git a/src/Views/CheckView.vala b/src/Views/CheckView.vala index 06d26a501..d1bb34239 100644 --- a/src/Views/CheckView.vala +++ b/src/Views/CheckView.vala @@ -132,7 +132,7 @@ public class Installer.CheckView : AbstractInstallerView { return int.parse (line); } } catch (Error e) { - stdout.printf ("Error: %s\n", e.message); + warning ("Unable to get frequency: %s\n", e.message); } return 0; @@ -151,7 +151,7 @@ public class Installer.CheckView : AbstractInstallerView { } } } catch (Error e) { - warning (e.message); + warning ("Unable to get meminfo: %s", e.message); } return 0; @@ -168,7 +168,7 @@ public class Installer.CheckView : AbstractInstallerView { } } } catch (Error e) { - critical (e.message); + critical ("Unable to get vm: %s", e.message); } return false; From 421e6367ef7fab79251a2530942446835638316d Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 26 Sep 2024 11:25:42 +0200 Subject: [PATCH 17/23] update --- common/DBusStructures.vala | 89 +++--- daemon/Daemon.vala | 571 ------------------------------------- meson.build | 1 - 3 files changed, 44 insertions(+), 617 deletions(-) diff --git a/common/DBusStructures.vala b/common/DBusStructures.vala index 9c6cafd23..eaa64cecd 100644 --- a/common/DBusStructures.vala +++ b/common/DBusStructures.vala @@ -79,6 +79,50 @@ public enum InstallerDaemon.FileSystem { } } +public struct InstallerDaemon.PartitionUsage { + /** + * None = 0; Some(usage) = 1; + */ + public uint8 tag; + /** + * The size, in sectors, that a partition is used. + */ + public uint64 value; +} + +public enum InstallerDaemon.PartitionTable { + NONE, + GPT, + MSDOS; +} + +public enum InstallerDaemon.Step { + BACKUP, + INIT, + PARTITION, + EXTRACT, + CONFIGURE, + BOOTLOADER; +} + +public struct InstallerDaemon.Status { + Step step; + int percent; +} + +public enum InstallerDaemon.LogLevel { + TRACE, + DEBUG, + INFO, + WARN, + ERROR; +} + +public struct InstallerDaemon.Error { + Step step; + int err; +} + public struct InstallerDaemon.Partition { string device_path; @@ -97,7 +141,6 @@ public struct InstallerDaemon.InstallConfig { string lang; bool modify_boot_order; bool install_drivers; - uint8 flags; } [Flags] @@ -140,47 +183,3 @@ public struct InstallerDaemon.LuksCredentials { string pv; string password; } - -public enum InstallerDaemon.LogLevel { - TRACE, - DEBUG, - INFO, - WARN, - ERROR; -} - -public struct InstallerDaemon.Error { - Step step; - int err; -} - -public enum InstallerDaemon.Step { - BACKUP, - INIT, - PARTITION, - EXTRACT, - CONFIGURE, - BOOTLOADER; -} - -public struct InstallerDaemon.Status { - Step step; - int percent; -} - -public struct InstallerDaemon.PartitionUsage { - /** - * None = 0; Some(usage) = 1; - */ - public uint8 tag; - /** - * The size, in sectors, that a partition is used. - */ - public uint64 value; -} - -public enum InstallerDaemon.PartitionTable { - NONE, - GPT, - MSDOS; -} diff --git a/daemon/Daemon.vala b/daemon/Daemon.vala index 5e605728d..0fd716099 100644 --- a/daemon/Daemon.vala +++ b/daemon/Daemon.vala @@ -17,577 +17,6 @@ private static GLib.MainLoop loop; -[DBus (name = "io.elementary.InstallerDaemon")] -public class InstallerDaemon.Daemon : GLib.Object { - public signal void on_log_message (Distinst.LogLevel level, string message); - public signal void on_status (Distinst.Status status); - public signal void on_error (Distinst.Error error); - - private Distinst.Disks disks; - - construct { - Distinst.log ((level, message) => { - Idle.add (() => { - on_log_message (level, message); - }); - }); - } - - public Distinst.PartitionTable bootloader_detect () throws GLib.Error { - return Distinst.bootloader_detect (); - } - - public DiskInfo get_disks (bool get_partitions = false) throws GLib.Error { - disks = Distinst.Disks.probe (); - - if (get_partitions) { - disks.initialize_volume_groups (); - } - - DiskInfo result = DiskInfo (); - - Disk[] physical_disks = {}; - Disk[] logical_disks = {}; - - foreach (unowned Distinst.Disk disk in disks.list ()) { - if (disk.is_read_only ()) { - continue; - } - - // Skip root disk or live disk - if (disk.contains_mount ("/", disks) || disk.contains_mount ("/cdrom", disks)) { - continue; - } - - Partition[] partitions = {}; - - if (get_partitions) { - foreach (unowned Distinst.Partition part in disk.list_partitions ()) { - string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) - ? string_from_utf8 (part.get_current_lvm_volume_group ()) - : ""; - - partitions += Partition () { - device_path = string_from_utf8 (part.get_device_path ()), - filesystem = to_common_fs (part.get_file_system ()), - start_sector = part.get_start_sector (), - end_sector = part.get_end_sector (), - sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), - current_lvm_volume_group = lvm_vg - }; - } - } - - string model = string_from_utf8 (disk.get_model ()); - string name = model.length == 0 ? string_from_utf8 (disk.get_serial ()).replace ("_", " ") : model; - - physical_disks += Disk () { - name = name, - device_path = string_from_utf8 (disk.get_device_path ()), - sectors = disk.get_sectors (), - sector_size = disk.get_sector_size (), - rotational = disk.is_rotational (), - removable = disk.is_removable (), - partitions = partitions - }; - } - - if (get_partitions) { - foreach (unowned Distinst.LvmDevice disk in disks.list_logical ()) { - Partition[] partitions = {}; - - foreach (unowned Distinst.Partition part in disk.list_partitions ()) { - string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) - ? string_from_utf8 (part.get_current_lvm_volume_group ()) - : ""; - - partitions += Partition () { - device_path = string_from_utf8 (part.get_device_path ()), - filesystem = to_common_fs (part.get_file_system ()), - start_sector = part.get_start_sector (), - end_sector = part.get_end_sector (), - sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), - current_lvm_volume_group = lvm_vg - }; - } - - logical_disks += Disk () { - name = string_from_utf8 (disk.get_model ()), - device_path = string_from_utf8 (disk.get_device_path ()), - sectors = disk.get_sectors (), - sector_size = disk.get_sector_size (), - partitions = partitions - }; - } - } - - result.physical_disks = physical_disks; - result.logical_disks = logical_disks; - return result; - } - - public int decrypt_partition (string path, string pv, string password) throws GLib.Error { - return disks.decrypt_partition (path, Distinst.LvmEncryption () { - physical_volume = pv, - password = password, - keydata = null - }); - } - - public Disk get_logical_device (string pv) throws GLib.Error { - unowned Distinst.LvmDevice disk = disks.get_logical_device (pv); - if (disk == null) { - throw new GLib.IOError.NOT_FOUND ("Couldn't find a logical device with that name"); - } - - Partition[] partitions = {}; - - foreach (unowned Distinst.Partition part in disk.list_partitions ()) { - string lvm_vg = (part.get_file_system () == Distinst.FileSystem.LVM) - ? string_from_utf8 (part.get_current_lvm_volume_group ()) - : ""; - - partitions += Partition () { - device_path = string_from_utf8 (part.get_device_path ()), - filesystem = to_common_fs (part.get_file_system ()), - start_sector = part.get_start_sector (), - end_sector = part.get_end_sector (), - sectors_used = to_common_usage (part.sectors_used (disk.get_sector_size ())), - current_lvm_volume_group = lvm_vg - }; - } - - return Disk () { - name = string_from_utf8 (disk.get_model ()), - device_path = string_from_utf8 (disk.get_device_path ()), - sectors = disk.get_sectors (), - sector_size = disk.get_sector_size (), - partitions = partitions - }; - } - - public void install_with_default_disk_layout (InstallConfig config, string disk, bool encrypt, string encryption_password) throws GLib.Error { - var disks = new Distinst.Disks (); - default_disk_configuration (disks, disk, encrypt ? encryption_password : null); - - install (config, (owned) disks); - } - - public void install_with_custom_disk_layout (InstallConfig config, Mount[] disk_config, LuksCredentials[] credentials) throws GLib.Error { - var disks = new Distinst.Disks (); - custom_disk_configuration (disks, disk_config, credentials); - - install (config, (owned) disks); - } - - private void install (InstallConfig config, owned Distinst.Disks disks) { - var installer = new Distinst.Installer (); - installer.on_error ((error) => on_error (error)); - installer.on_status ((status) => on_status (status)); - - var distinst_config = Distinst.Config (); - distinst_config.flags = config.flags; - distinst_config.hostname = config.hostname; - - var casper = casper_dir (); - distinst_config.remove = GLib.Path.build_filename (casper, "filesystem.manifest-remove"); - distinst_config.squashfs = GLib.Path.build_filename (casper, "filesystem.squashfs"); - - debug ("language: %s\n", config.lang); - distinst_config.lang = config.lang; - - distinst_config.keyboard_layout = config.keyboard_layout; - distinst_config.keyboard_model = null; - distinst_config.keyboard_variant = config.keyboard_variant == "" ? null : config.keyboard_variant; - - new Thread (null, () => { - if (installer.install ((owned) disks, distinst_config) != 0) { - Idle.add (() => { - on_error (Distinst.Error ()); - return GLib.Source.REMOVE; - }); - } - - return null; - }); - } - - public void set_demo_mode_locale (string locale) throws GLib.Error { - GLib.FileUtils.set_contents ("/etc/default/locale", "LANG=" + locale); - } - - public void trigger_demo_mode () throws GLib.Error { - var demo_mode_file = GLib.File.new_for_path ("/var/lib/lightdm/demo-mode"); - try { - demo_mode_file.create (GLib.FileCreateFlags.NONE); - } catch (GLib.Error e) { - if (!(e is GLib.IOError.EXISTS)) { - throw e; - } - } - } - - private string casper_dir () { - const string CDROM = "/cdrom"; - - try { - var cdrom_dir = File.new_for_path (CDROM); - var iter = cdrom_dir.enumerate_children (FileAttribute.STANDARD_NAME, 0); - - FileInfo info; - while ((info = iter.next_file ()) != null) { - unowned string name = info.get_name (); - if (name.has_prefix ("casper")) { - return GLib.Path.build_filename (CDROM, name); - } - } - } catch (GLib.Error e) { - critical ("failed to find casper dir automatically: %s\n", e.message); - } - - return GLib.Path.build_filename (CDROM, "casper"); - } - - private void default_disk_configuration (Distinst.Disks disks, string disk_path, string? encryption_password) throws GLib.IOError { - var encrypted_vg = Distinst.generate_unique_id ("cryptdata"); - var root_vg = Distinst.generate_unique_id ("data"); - if (encrypted_vg == null || root_vg == null) { - throw new GLib.IOError.FAILED ("Unable to generate unique volume group IDs"); - } - - Distinst.LvmEncryption? encryption; - if (encryption_password != null) { - debug ("encrypting"); - encryption = Distinst.LvmEncryption () { - physical_volume = encrypted_vg, - password = encryption_password, - keydata = null - }; - } else { - debug ("not encrypting"); - encryption = null; - } - - debug ("disk: %s\n", disk_path); - var disk = new Distinst.Disk (disk_path); - if (disk == null) { - throw new GLib.IOError.FAILED ("Could not find %s", disk_path); - } - - var bootloader = Distinst.bootloader_detect (); - - var start_sector = Distinst.Sector () { - flag = Distinst.SectorKind.START, - value = 0 - }; - - // 256 MiB is the minimum distinst ESP partition size, so this is 256 MiB in MB plus a bit - // extra for safety - var efi_sector = Distinst.Sector () { - flag = Distinst.SectorKind.MEGABYTE, - value = 278 - }; - - // 1024MB /boot partition that's created if we're doing encryption - var boot_sector = Distinst.Sector () { - flag = Distinst.SectorKind.MEGABYTE, - value = efi_sector.value + 1024 - }; - - // 4GB swap partition at the end - var swap_sector = Distinst.Sector () { - flag = Distinst.SectorKind.MEGABYTE_FROM_END, - value = 4096 - }; - - var end_sector = Distinst.Sector () { - flag = Distinst.SectorKind.END, - value = 0 - }; - - // Prepares a new partition table. - int result = disk.mklabel (bootloader); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to write partition table to %s", disk_path); - } - - var start = disk.get_sector (ref start_sector); - var end = disk.get_sector (ref boot_sector); - - switch (bootloader) { - case Distinst.PartitionTable.MSDOS: - // This is used to ensure LVM installs will work with BIOS - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) - .partition_type (Distinst.PartitionType.PRIMARY) - .flag (Distinst.PartitionFlag.BOOT) - .mount ("/boot") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add boot partition to %s", disk_path); - } - - // Start the LVM from the end of our /boot partition - start = disk.get_sector (ref boot_sector); - break; - case Distinst.PartitionTable.GPT: - end = disk.get_sector (ref efi_sector); - - // A FAT32 partition is required for EFI installs - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.FAT32) - .partition_type (Distinst.PartitionType.PRIMARY) - .flag (Distinst.PartitionFlag.ESP) - .mount ("/boot/efi") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add EFI partition to %s", disk_path); - } - - // If we're encrypting, we need an unencrypted partition to store kernels and initramfs images - if (encryption != null) { - start = disk.get_sector (ref efi_sector); - end = disk.get_sector (ref boot_sector); - - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) - .partition_type (Distinst.PartitionType.PRIMARY) - .mount ("/boot") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("unable to add /boot partition to %s", disk_path); - } - - // Start the LVM from the end of our /boot/efi and /boot partitions - start = disk.get_sector (ref boot_sector); - } else { - // No encryption, we only have a /boot/efi partition, start the LVM from there - start = disk.get_sector (ref efi_sector); - } - - break; - } - - end = disk.get_sector (ref end_sector); - - result = disk.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.LVM) - .partition_type (Distinst.PartitionType.PRIMARY) - .logical_volume (root_vg, encryption) - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add LVM partition to %s", disk_path); - } - - disks.push ((owned) disk); - - result = disks.initialize_volume_groups (); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to initialize volume groups on %s", disk_path); - } - - unowned Distinst.LvmDevice lvm_device = disks.get_logical_device (root_vg); - - if (lvm_device == null) { - throw new GLib.IOError.FAILED ("Unable to find '%s' volume group on %s", root_vg, disk_path); - } - - start = lvm_device.get_sector (ref start_sector); - end = lvm_device.get_sector (ref swap_sector); - - result = lvm_device.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.EXT4) - .name ("root") - .mount ("/") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add / partition to LVM on %s", disk_path); - } - - start = lvm_device.get_sector (ref swap_sector); - end = lvm_device.get_sector (ref end_sector); - - result = lvm_device.add_partition ( - new Distinst.PartitionBuilder (start, end, Distinst.FileSystem.SWAP) - .name ("swap") - ); - - if (result != 0) { - throw new GLib.IOError.FAILED ("Unable to add swap partition to LVM on %s", disk_path); - } - } - - private void custom_disk_configuration (Distinst.Disks disks, Mount[] mounts, LuksCredentials[] credentials) throws GLib.IOError { - Mount[] lvm_devices = {}; - - foreach (Mount m in mounts) { - if (m.is_lvm ()) { - lvm_devices += m; - } else { - unowned Distinst.Disk disk = disks.get_physical_device (m.parent_disk); - if (disk == null) { - var new_disk = new Distinst.Disk (m.parent_disk); - if (new_disk == null) { - throw new GLib.IOError.FAILED ("Could not find physical device: '%s'", m.parent_disk); - } - - disks.push ((owned) new_disk); - disk = disks.get_physical_device (m.parent_disk); - } - - unowned Distinst.Partition partition = disk.get_partition_by_path (m.partition_path); - - if (partition == null) { - throw new GLib.IOError.FAILED ("Could not find %s", m.partition_path); - } - - if (m.mount_point == "/boot/efi") { - if (m.is_valid_boot_mount ()) { - if (m.should_format ()) { - partition.format_with (to_distinst_fs (m.filesystem)); - } - - partition.set_mount (m.mount_point); - partition.set_flags ({ Distinst.PartitionFlag.ESP }); - } else { - throw new GLib.IOError.FAILED ("Unreachable code path -- EFI partition is invalid"); - } - } else { - if (m.filesystem != SWAP) { - partition.set_mount (m.mount_point); - } - - if (m.mount_point == "/boot") { - partition.set_flags ({ Distinst.PartitionFlag.BOOT }); - } - - if (m.should_format ()) { - partition.format_with (to_distinst_fs (m.filesystem)); - } - } - } - } - - disks.initialize_volume_groups (); - - foreach (LuksCredentials cred in credentials) { - disks.decrypt_partition (cred.device, Distinst.LvmEncryption () { - physical_volume = cred.pv, - password = cred.password, - keydata = null - }); - } - - foreach (Mount m in lvm_devices) { - var vg = m.parent_disk.offset (12); - unowned Distinst.LvmDevice disk = disks.get_logical_device (vg); - if (disk == null) { - throw new GLib.IOError.FAILED ("Could not find %s", vg); - } - - unowned Distinst.Partition partition = disk.get_partition_by_path (m.partition_path); - - if (partition == null) { - throw new GLib.IOError.FAILED ("could not find %s", m.partition_path); - } - - if (m.filesystem != SWAP) { - partition.set_mount (m.mount_point); - } - - if (m.should_format ()) { - partition.format_and_keep_name (to_distinst_fs (m.filesystem)); - } - } - } - - private static string string_from_utf8 (uint8[] input) { - var builder = new GLib.StringBuilder.sized (input.length); - builder.append_len ((string) input, input.length); - return (owned) builder.str; - } - - private InstallerDaemon.FileSystem to_common_fs (Distinst.FileSystem fs) { - switch (fs) { - case BTRFS: - return InstallerDaemon.FileSystem.BTRFS; - case EXT2: - return InstallerDaemon.FileSystem.EXT2; - case EXT3: - return InstallerDaemon.FileSystem.EXT3; - case EXT4: - return InstallerDaemon.FileSystem.EXT4; - case F2FS: - return InstallerDaemon.FileSystem.F2FS; - case FAT16: - return InstallerDaemon.FileSystem.FAT16; - case FAT32: - return InstallerDaemon.FileSystem.FAT32; - case NONE: - return InstallerDaemon.FileSystem.NONE; - case NTFS: - return InstallerDaemon.FileSystem.NTFS; - case SWAP: - return InstallerDaemon.FileSystem.SWAP; - case XFS: - return InstallerDaemon.FileSystem.XFS; - case LVM: - return InstallerDaemon.FileSystem.LVM; - case LUKS: - return InstallerDaemon.FileSystem.LUKS; - default: - return InstallerDaemon.FileSystem.NONE; - } - } - - private InstallerDaemon.PartitionUsage to_common_usage (Distinst.PartitionUsage usage) { - return InstallerDaemon.PartitionUsage () { - tag = usage.tag, - value = usage.value - }; - } - - private Distinst.FileSystem to_distinst_fs (InstallerDaemon.FileSystem fs) { - switch (fs) { - case BTRFS: - return Distinst.FileSystem.BTRFS; - case EXT2: - return Distinst.FileSystem.EXT2; - case EXT3: - return Distinst.FileSystem.EXT3; - case EXT4: - return Distinst.FileSystem.EXT4; - case F2FS: - return Distinst.FileSystem.F2FS; - case FAT16: - return Distinst.FileSystem.FAT16; - case FAT32: - return Distinst.FileSystem.FAT32; - case NONE: - return Distinst.FileSystem.NONE; - case NTFS: - return Distinst.FileSystem.NTFS; - case SWAP: - return Distinst.FileSystem.SWAP; - case XFS: - return Distinst.FileSystem.XFS; - case LVM: - return Distinst.FileSystem.LVM; - case LUKS: - return Distinst.FileSystem.LUKS; - default: - return Distinst.FileSystem.NONE; - } - } -} - private void on_bus_acquired (GLib.DBusConnection connection, string name) { try { #if DISTINST_BACKEND diff --git a/meson.build b/meson.build index a335271a7..2da8f0ec7 100644 --- a/meson.build +++ b/meson.build @@ -12,7 +12,6 @@ add_project_arguments(['--vapidir', join_paths(meson.current_source_dir(), 'vapi gnome = import('gnome') i18n = import('i18n') -distinst_dep = dependency('distinst') glib_dep = dependency('glib-2.0', version: '>=2.74') gobject_dep = dependency('gobject-2.0') gtk_dep = dependency('gtk4') From 490bdb4341a6a73f9ef7538bb8d26da90619ca34 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 26 Sep 2024 12:17:59 +0200 Subject: [PATCH 18/23] Revert "Improve logging" This reverts commit aab202c5ad6cf4d54c5a33527878613f1b347f6d. --- src/Helpers/LocaleHelper.vala | 10 ++++------ src/MainWindow.vala | 2 +- src/Utils.vala | 16 ++++++++-------- src/Views/CheckView.vala | 6 +++--- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/Helpers/LocaleHelper.vala b/src/Helpers/LocaleHelper.vala index 927b42930..13b538de2 100644 --- a/src/Helpers/LocaleHelper.vala +++ b/src/Helpers/LocaleHelper.vala @@ -54,9 +54,8 @@ namespace LocaleHelper { var langs = Build.LANG_LIST.split (";"); var parser = new Json.Parser (); - string ISO_639_3_PATH = "%s/iso_639-3.json".printf (Build.ISO_CODES_LOCATION); try { - parser.load_from_file (ISO_639_3_PATH); + parser.load_from_file ("%s/iso_639-3.json".printf (Build.ISO_CODES_LOCATION)); weak Json.Object root_object = parser.get_root ().get_object (); weak Json.Array 639_3_array = root_object.get_array_member ("639-3"); foreach (unowned Json.Node element in 639_3_array.get_elements ()) { @@ -74,14 +73,13 @@ namespace LocaleHelper { } } } catch (Error e) { - critical ("Unable to parse '%s': %s", ISO_639_3_PATH, e.message); + critical (e.message); } var countries = new Gee.HashMap (); parser = new Json.Parser (); - string ISO_3166_1_PATH = "%s/iso_3166-1.json".printf (Build.ISO_CODES_LOCATION); try { - parser.load_from_file (ISO_3166_1_PATH); + parser.load_from_file ("%s/iso_3166-1.json".printf (Build.ISO_CODES_LOCATION)); weak Json.Object root_object = parser.get_root ().get_object (); weak Json.Array 3166_1_array = root_object.get_array_member ("3166-1"); foreach (unowned Json.Node element in 3166_1_array.get_elements ()) { @@ -100,7 +98,7 @@ namespace LocaleHelper { countries[entry.alpha_2] = entry; } } catch (Error e) { - critical ("Unable to parse '%s': %s", ISO_3166_1_PATH, e.message); + critical (e.message); } foreach (var lang in langs) { diff --git a/src/MainWindow.vala b/src/MainWindow.vala index e0ae0bf16..2faf178f8 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -93,7 +93,7 @@ public class Installer.MainWindow : Gtk.Window { } }); } catch (Error e) { - warning ("Unable to query upower: %s", e.message); + warning (e.message); battery_infobar.revealed = false; } diff --git a/src/Utils.vala b/src/Utils.vala index 7b008c8f2..8c7afcc34 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -38,7 +38,7 @@ namespace Utils { try { system_instance.power_off (false); } catch (GLib.Error e) { - critical ("Unable to shutdown: %s", e.message); + critical (e.message); } } } @@ -52,7 +52,7 @@ namespace Utils { try { system_instance.reboot (false); } catch (GLib.Error e) { - critical ("Unable to restart: %s", e.message); + critical (e.message); } } } @@ -102,7 +102,7 @@ namespace Utils { "/org/freedesktop/login1" ); } catch (GLib.Error e) { - warning ("Unable to get system instance: %s", e.message); + warning ("%s", e.message); } } } @@ -145,7 +145,7 @@ namespace Utils { "/org/freedesktop/hostname1" ); } catch (GLib.Error e) { - warning ("Unable to get hostname instance: %s", e.message); + warning ("%s", e.message); } } } @@ -161,7 +161,7 @@ namespace Utils { try { FileUtils.get_contents ("/etc/machine-id", out machine_id); } catch (FileError e) { - warning ("Unable to get machine id: %s", e.message); + warning ("%s", e.message); return null; } @@ -173,7 +173,7 @@ namespace Utils { try { FileUtils.get_contents ("/sys/devices/virtual/dmi/id/sys_vendor", out vendor); } catch (FileError e) { - warning ("Unable to get sys vendor: %s", e.message); + warning ("%s", e.message); return null; } @@ -185,7 +185,7 @@ namespace Utils { try { FileUtils.get_contents ("/sys/devices/virtual/dmi/id/product_name", out model); } catch (FileError e) { - warning ("Unable to get product name: %s", e.message); + warning ("%s", e.message); return null; } @@ -197,7 +197,7 @@ namespace Utils { try { FileUtils.get_contents ("/sys/devices/virtual/dmi/id/product_version", out model); } catch (FileError e) { - warning ("Unable to get product version: %s", e.message); + warning ("%s", e.message); return null; } diff --git a/src/Views/CheckView.vala b/src/Views/CheckView.vala index d1bb34239..06d26a501 100644 --- a/src/Views/CheckView.vala +++ b/src/Views/CheckView.vala @@ -132,7 +132,7 @@ public class Installer.CheckView : AbstractInstallerView { return int.parse (line); } } catch (Error e) { - warning ("Unable to get frequency: %s\n", e.message); + stdout.printf ("Error: %s\n", e.message); } return 0; @@ -151,7 +151,7 @@ public class Installer.CheckView : AbstractInstallerView { } } } catch (Error e) { - warning ("Unable to get meminfo: %s", e.message); + warning (e.message); } return 0; @@ -168,7 +168,7 @@ public class Installer.CheckView : AbstractInstallerView { } } } catch (Error e) { - critical ("Unable to get vm: %s", e.message); + critical (e.message); } return false; From 93b8f5cbf5c42356af9dce1a4b1c0acdb9885ccc Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Thu, 26 Sep 2024 12:21:01 +0200 Subject: [PATCH 19/23] Refactor --- src/Views/PartitioningView.vala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Views/PartitioningView.vala b/src/Views/PartitioningView.vala index 134cc095c..1a3cadeec 100644 --- a/src/Views/PartitioningView.vala +++ b/src/Views/PartitioningView.vala @@ -229,7 +229,7 @@ public class Installer.PartitioningView : AbstractInstallerView { switch (bootloader) { case MSDOS: break; - case InstallerDaemon.PartitionTable.GPT: + case GPT: break; } From fff2b008f16f05510f76dbfb5d7c8c13e1ec2057 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Tue, 1 Oct 2024 07:47:23 +0200 Subject: [PATCH 20/23] Utils: Port hostname validation from distinst and add tests --- .github/workflows/ci.yml | 1 + meson.build | 1 + src/HostnameValidator.vala | 47 +++++++++++++++++++++++++++++++++ src/Utils.vala | 7 +++++ src/meson.build | 1 + test/HostnameValidatorTest.vala | 24 +++++++++++++++++ test/Test.vala | 5 ++++ test/meson.build | 13 +++++++++ 8 files changed, 99 insertions(+) create mode 100644 src/HostnameValidator.vala create mode 100644 test/HostnameValidatorTest.vala create mode 100644 test/Test.vala create mode 100644 test/meson.build diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5bd86320b..359b907fb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,6 +30,7 @@ jobs: run: | meson setup build ninja -C build install + ninja -C build test lint: runs-on: ubuntu-latest diff --git a/meson.build b/meson.build index 2da8f0ec7..85c73b6b3 100644 --- a/meson.build +++ b/meson.build @@ -42,3 +42,4 @@ subdir('common') subdir('daemon') subdir('src') subdir('data') +subdir('test') diff --git a/src/HostnameValidator.vala b/src/HostnameValidator.vala new file mode 100644 index 000000000..64c9193d3 --- /dev/null +++ b/src/HostnameValidator.vala @@ -0,0 +1,47 @@ +// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- +/*- + * Copyright 2024 elementary, Inc. (https://elementary.io) + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Authored by: Marius Meisenzahl + */ + +namespace Utils { + private bool hostname_is_valid_char (char c) { + return ((c >= 'a' && c <= 'z') || + (c >= 'A' && c <= 'Z') || + (c >= '0' && c <= '9') || + c == '-' || + c == '.'); + } + + // Based on https://github.com/pop-os/hostname-validator/blob/458fa5a1df98cb663f0456dffb542e1a907861c9/src/lib.rs#L29 + public bool hostname_is_valid (string hostname) { + for (int i = 0; i < hostname.char_count (); i++) { + char c = hostname[i]; + if (!hostname_is_valid_char (c)) { + return false; + } + } + + string[] labels = hostname.split (".", -1); + foreach (string label in labels) { + if (label.char_count () == 0 || label.length > 63 || label[0] == '-' || label[label.length - 1] == '-') { + return false; + } + } + + return !(hostname.char_count () == 0 || hostname.length > 253); + } +} diff --git a/src/Utils.vala b/src/Utils.vala index 8c7afcc34..c8b59a0a4 100644 --- a/src/Utils.vala +++ b/src/Utils.vala @@ -264,6 +264,13 @@ namespace Utils { string hostname = get_ubiquity_compatible_hostname () ?? ("elementary-os" + "-" + get_chassis ()); hostname += "-" + get_machine_id ().substring (0, 8); + // If the automatic hostname logic fails in some way, it's possible we may generate an invalid + // hostname. We could fix this by trimming traling/leading hyphens or other invalid characters. + // But it's probably a bad hostname anyway, so just fallback + if (!hostname_is_valid (hostname)) { + hostname = "elementary-os"; + } + return hostname; } } diff --git a/src/meson.build b/src/meson.build index 1ae8f0018..13bf7e43a 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,5 +1,6 @@ vala_files = [ 'Application.vala', + 'HostnameValidator.vala', 'MainWindow.vala', 'Utils.vala', 'Helpers/InstallerDaemon.vala', diff --git a/test/HostnameValidatorTest.vala b/test/HostnameValidatorTest.vala new file mode 100644 index 000000000..7399c553e --- /dev/null +++ b/test/HostnameValidatorTest.vala @@ -0,0 +1,24 @@ +void add_hostname_validator_tests () { + Test.add_func ("/valid", () => { + assert (Utils.hostname_is_valid ("VaLiD-HoStNaMe")); + assert (Utils.hostname_is_valid ("50-name")); + assert (Utils.hostname_is_valid ("235235")); + assert (Utils.hostname_is_valid ("example.com")); + assert (Utils.hostname_is_valid ("VaLid.HoStNaMe")); + assert (Utils.hostname_is_valid ("123.456")); + }); + + Test.add_func ("/invalid", () => { + assert (!Utils.hostname_is_valid ("-invalid-name")); + assert (!Utils.hostname_is_valid ("also-invalid-")); + assert (!Utils.hostname_is_valid ("asdf@fasd")); + assert (!Utils.hostname_is_valid ("@asdfl")); + assert (!Utils.hostname_is_valid ("asd f@")); + assert (!Utils.hostname_is_valid (".invalid")); + assert (!Utils.hostname_is_valid ("invalid.name.")); + assert (!Utils.hostname_is_valid ("foo.label-is-way-to-longgggggggggggggggggggggggggggggggggggggggggggg.org")); + assert (!Utils.hostname_is_valid ("invalid.-starting.char")); + assert (!Utils.hostname_is_valid ("invalid.ending-.char")); + assert (!Utils.hostname_is_valid ("empty..label")); + }); +} diff --git a/test/Test.vala b/test/Test.vala new file mode 100644 index 000000000..de40a0434 --- /dev/null +++ b/test/Test.vala @@ -0,0 +1,5 @@ +void main (string[] args) { + Test.init (ref args); + add_hostname_validator_tests (); + Test.run (); +} diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 000000000..1ef64043d --- /dev/null +++ b/test/meson.build @@ -0,0 +1,13 @@ +test_dependencies = [ + glib_dep, +] + +tests = executable( + meson.project_name() + '-tests', + 'HostnameValidatorTest.vala', + 'Test.vala', + meson.project_source_root() + '/src/HostnameValidator.vala', + dependencies: test_dependencies +) + +test('Test', tests) From 81151c82cfac4f8f1f0d1b366c630f232440c3cf Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Wed, 2 Oct 2024 07:33:16 +0200 Subject: [PATCH 21/23] HostnameValidator: Refactor to use char.isalnum --- src/HostnameValidator.vala | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/HostnameValidator.vala b/src/HostnameValidator.vala index 64c9193d3..27bda24e9 100644 --- a/src/HostnameValidator.vala +++ b/src/HostnameValidator.vala @@ -19,9 +19,7 @@ namespace Utils { private bool hostname_is_valid_char (char c) { - return ((c >= 'a' && c <= 'z') || - (c >= 'A' && c <= 'Z') || - (c >= '0' && c <= '9') || + return (c.isalnum () || c == '-' || c == '.'); } From c4eec26902a190521f7eea3f986365e3db7f86ea Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Wed, 2 Oct 2024 07:34:30 +0200 Subject: [PATCH 22/23] HostnameValidator: Add comment --- src/HostnameValidator.vala | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/HostnameValidator.vala b/src/HostnameValidator.vala index 27bda24e9..5be9a3efd 100644 --- a/src/HostnameValidator.vala +++ b/src/HostnameValidator.vala @@ -25,6 +25,17 @@ namespace Utils { } // Based on https://github.com/pop-os/hostname-validator/blob/458fa5a1df98cb663f0456dffb542e1a907861c9/src/lib.rs#L29 + /// Validate a hostname according to [IETF RFC 1123](https://tools.ietf.org/html/rfc1123). + /// + /// A hostname is valid if the following condition are true: + /// + /// - It does not start or end with `-` or `.`. + /// - It does not contain any characters outside of the alphanumeric range, except for `-` and `.`. + /// - It is not empty. + /// - It is 253 or fewer characters. + /// - Its labels (characters separated by `.`) are not empty. + /// - Its labels are 63 or fewer characters. + /// - Its labels do not start or end with '-' or '.'. public bool hostname_is_valid (string hostname) { for (int i = 0; i < hostname.char_count (); i++) { char c = hostname[i]; From 56d4d1966821ea0d12387ea4df56a98158a0a8c1 Mon Sep 17 00:00:00 2001 From: Marius Meisenzahl Date: Wed, 2 Oct 2024 07:37:09 +0200 Subject: [PATCH 23/23] HostnameValidator: Update copyright and license --- src/HostnameValidator.vala | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/src/HostnameValidator.vala b/src/HostnameValidator.vala index 5be9a3efd..27e7e9fb5 100644 --- a/src/HostnameValidator.vala +++ b/src/HostnameValidator.vala @@ -1,20 +1,7 @@ -// -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- -/*- +/* + * Copyright 2018-2022 System76 * Copyright 2024 elementary, Inc. (https://elementary.io) - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * Authored by: Marius Meisenzahl + * SPDX-License-Identifier: MIT */ namespace Utils {