diff --git a/src/disk.cpp b/src/disk.cpp index 0519905..36ee3fd 100644 --- a/src/disk.cpp +++ b/src/disk.cpp @@ -10,7 +10,10 @@ #include "gucc/string_utils.hpp" #include "gucc/zfs.hpp" -#include // for exists, is_directory +#include // for find_if +#include // for exists, is_directory +#include // for ranges::* + #include // for Renderer, Button #include // for ButtonOption #include // for Component, ScreenI... @@ -24,13 +27,40 @@ using namespace std::string_view_literals; using namespace std::string_literals; namespace fs = std::filesystem; +namespace { + +constexpr auto is_root_btrfs_part(const gucc::fs::Partition& part) noexcept -> bool { + return (part.mountpoint == "/"sv) && (part.fstype == "btrfs"sv); +} + +// TODO(vnepogodin): refactor that out of this file +constexpr auto find_root_btrfs_part(auto&& parts) noexcept { + return std::ranges::find_if(parts, + [](auto&& part) { return is_root_btrfs_part(part); }); +} + +} // namespace + namespace utils { -void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::string_view& mode, bool ignore_note) noexcept { +void btrfs_create_subvols(std::vector& partitions, const std::string_view& mode, bool ignore_note) noexcept { /* clang-format off */ if (mode.empty()) { return; } /* clang-format on */ + const std::vector default_subvolumes{ + gucc::fs::BtrfsSubvolume{.subvolume = "/@"s, .mountpoint = "/"s}, + gucc::fs::BtrfsSubvolume{.subvolume = "/@home"s, .mountpoint = "/home"s}, + gucc::fs::BtrfsSubvolume{.subvolume = "/@cache"s, .mountpoint = "/var/cache"s}, + // gucc::fs::BtrfsSubvolume{.subvolume = "/@snapshots"sv, .mountpoint = "/.snapshots"sv}, + }; + + auto root_part = find_root_btrfs_part(partitions); + if (root_part == std::ranges::end(partitions)) { + spdlog::error("btrfs_create_subvols: unable to find btrfs root part"); + return; + } + #ifdef NDEVENV const auto root_mountpoint = "/mnt"sv; @@ -68,9 +98,12 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str } // Create subvolumes - if (!gucc::fs::btrfs_create_subvols(subvolumes, disk.root, root_mountpoint, disk.mount_opts)) { + if (!gucc::fs::btrfs_create_subvols(subvolumes, root_part->device, root_mountpoint, root_part->mount_opts)) { spdlog::error("Failed to create subvolumes"); } + if (!gucc::fs::btrfs_append_subvolumes(partitions, subvolumes)) { + spdlog::error("Failed to append btrfs subvolumes into partition scheme"); + } return; } if (!ignore_note) { @@ -82,35 +115,35 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str } // Create subvolumes automatically - const std::vector subvolumes{ - gucc::fs::BtrfsSubvolume{.subvolume = "/@"s, .mountpoint = "/"s}, - gucc::fs::BtrfsSubvolume{.subvolume = "/@home"s, .mountpoint = "/home"s}, - gucc::fs::BtrfsSubvolume{.subvolume = "/@cache"s, .mountpoint = "/var/cache"s}, - // gucc::fs::BtrfsSubvolume{.subvolume = "/@snapshots"sv, .mountpoint = "/.snapshots"sv}, - }; - if (!gucc::fs::btrfs_create_subvols(subvolumes, disk.root, root_mountpoint, disk.mount_opts)) { + if (!gucc::fs::btrfs_create_subvols(default_subvolumes, root_part->device, root_mountpoint, root_part->mount_opts)) { spdlog::error("Failed to create subvolumes automatically"); } - gucc::fs::Partition partition{}; - partition.fstype = "btrfs"s; - partition.mountpoint = subvolumes[0].mountpoint; - // partition.uuid_str = ""; - partition.device = disk.root; - partition.mount_opts = disk.mount_opts; - partition.subvolume = std::make_optional(subvolumes[0].subvolume); - spdlog::debug("partition: fs='{}';mountpoint='{}';uuid_str='{}';device='{}';mount_opts='{}';subvolume='{}'", - partition.fstype, partition.mountpoint, partition.uuid_str, partition.device, partition.mount_opts, *partition.subvolume); + if (!gucc::fs::btrfs_append_subvolumes(partitions, default_subvolumes)) { + spdlog::error("Failed to append btrfs subvolumes into partition scheme"); + } #else spdlog::info("Do we ignore note? {}", ignore_note); #endif + + // need to find it again, due to modifying the parts + root_part = find_root_btrfs_part(partitions); + + spdlog::debug("root partition: fs='{}';mountpoint='{}';uuid_str='{}';device='{}';mount_opts='{}';subvolume='{}'", + root_part->fstype, root_part->mountpoint, root_part->uuid_str, root_part->device, root_part->mount_opts, *root_part->subvolume); } -void mount_existing_subvols(const disk_part& disk) noexcept { +void mount_existing_subvols(std::vector& partitions) noexcept { + auto root_part = find_root_btrfs_part(partitions); + if (root_part == std::ranges::end(partitions)) { + spdlog::error("mount_existing_subvols: unable to find btrfs root part"); + return; + } + // Set mount options - const auto& format_name = gucc::utils::exec(fmt::format(FMT_COMPILE("echo {} | rev | cut -d/ -f1 | rev"), disk.part)); - const auto& format_device = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e '/{}/,/disk/p' | {}"), format_name, "awk '/disk/ {print $1}'"sv)); - const auto& rotational_queue = (gucc::utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/queue/rotational"), format_device)) == "1"sv); + const auto& part_dev_name = gucc::utils::exec(fmt::format(FMT_COMPILE("echo {} | rev | cut -d/ -f1 | rev"), root_part->device)); + const auto& device_name = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e '/{}/,/disk/p' | {}"), part_dev_name, "awk '/disk/ {print $1}'"sv)); + const auto& rotational_queue = (gucc::utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/queue/rotational"), device_name)) == "1"sv); std::string fs_opts{}; if (rotational_queue) { @@ -144,9 +177,19 @@ void mount_existing_subvols(const disk_part& disk) noexcept { // TODO(vnepogodin): add confirmation for selected mountpoint for particular subvolume // Mount subvolumes - if (!gucc::fs::btrfs_mount_subvols(subvolumes, disk.root, root_mountpoint, fs_opts)) { + if (!gucc::fs::btrfs_mount_subvols(subvolumes, root_part->device, root_mountpoint, fs_opts)) { spdlog::error("Failed to mount btrfs subvolumes"); } + + if (!gucc::fs::btrfs_append_subvolumes(partitions, subvolumes)) { + spdlog::error("Failed to append btrfs subvolumes into partition scheme"); + } + + // need to find it again, due to modifying the parts + root_part = find_root_btrfs_part(partitions); + + spdlog::debug("root partition: fs='{}';mountpoint='{}';uuid_str='{}';device='{}';mount_opts='{}';subvolume='{}'", + root_part->fstype, root_part->mountpoint, root_part->uuid_str, root_part->device, root_part->mount_opts, *root_part->subvolume); #endif } diff --git a/src/disk.hpp b/src/disk.hpp index 01233a0..d701378 100644 --- a/src/disk.hpp +++ b/src/disk.hpp @@ -1,20 +1,16 @@ #ifndef DISK_HPP #define DISK_HPP +#include "gucc/partition.hpp" + #include // for string #include // for string_view #include // for vector namespace utils { -struct disk_part { - const std::string_view root{}; - const std::string_view part{}; - const std::string_view mount_opts{}; -}; - -void btrfs_create_subvols(const disk_part& disk, const std::string_view& mode, bool ignore_note = false) noexcept; -void mount_existing_subvols(const disk_part& disk) noexcept; +void btrfs_create_subvols(std::vector& partitions, const std::string_view& mode, bool ignore_note = false) noexcept; +void mount_existing_subvols(std::vector& partitions) noexcept; auto lvm_show_vg() noexcept -> std::vector; // ZFS filesystem diff --git a/src/simple_tui.cpp b/src/simple_tui.cpp index 284fe62..a75d47e 100644 --- a/src/simple_tui.cpp +++ b/src/simple_tui.cpp @@ -156,6 +156,8 @@ auto make_partitions_prepared(std::string_view bootloader, std::string_view root if (ready_parts.empty()) { spdlog::error("Invalid use! ready parts empty."); return false; } /* clang-format on */ + std::vector partitions{}; + std::string root_part{}; for (auto&& ready_part : ready_parts) { auto part_info = gucc::utils::make_multiline(ready_part, false, '\t'); @@ -193,11 +195,14 @@ auto make_partitions_prepared(std::string_view bootloader, std::string_view root const auto& subvolumes = fmt::format(FMT_COMPILE("btrfs subvolume list \"{}\" 2>/dev/null"), part_mountpoint); const auto& subvolumes_count = gucc::utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); const auto& lines_count = utils::to_int(subvolumes_count); + + auto part_struct = gucc::fs::Partition{.fstype = part_fs, .mountpoint = part_mountpoint, .device = root_part, .mount_opts = std::string{mount_opts_info}}; + partitions.emplace_back(std::move(part_struct)); if (lines_count > 1) { // Pre-existing subvolumes and user wants to mount them - utils::mount_existing_subvols({root_part, root_part}); + utils::mount_existing_subvols(partitions); } else { - utils::btrfs_create_subvols({.root = part_name, .mount_opts = mount_opts_info}, "automatic"sv, true); + utils::btrfs_create_subvols(partitions, "automatic"sv, true); } } continue; diff --git a/src/tui.cpp b/src/tui.cpp index 8d3d8ae..acb5f49 100644 --- a/src/tui.cpp +++ b/src/tui.cpp @@ -14,6 +14,7 @@ #include "gucc/io_utils.hpp" #include "gucc/locale.hpp" #include "gucc/mount_partitions.hpp" +#include "gucc/partition.hpp" #include "gucc/string_utils.hpp" #include "gucc/zfs.hpp" @@ -42,6 +43,7 @@ namespace fs = std::filesystem; #include "follow_process_log.hpp" #endif +using namespace std::string_literals; using namespace std::string_view_literals; namespace tui { @@ -108,7 +110,12 @@ void btrfs_subvolumes() noexcept { const auto& mount_opts_info = std::get(config_data["MOUNT_OPTS"]); const auto& root_part = std::get(config_data["ROOT_PART"]); - utils::btrfs_create_subvols({.root = root_part, .mount_opts = mount_opts_info}, btrfsvols_mode); + + std::vector partitions{ + gucc::fs::Partition{.fstype = "btrfs"s, .mountpoint = "/"s, .device = root_part, .mount_opts = mount_opts_info}, + }; + + utils::btrfs_create_subvols(partitions, btrfsvols_mode); } // Function will not allow incorrect UUID type for installed system. @@ -1710,6 +1717,8 @@ void mount_partitions() noexcept { utils::delete_partition_in_list(part); }*/ + std::vector partitions{}; + // check to see if we already have a zfs root mounted const auto& mountpoint_info = std::get(config_data["MOUNTPOINT"]); if (gucc::fs::utils::get_mountpoint_fs(mountpoint_info) == "zfs"sv) { @@ -1752,11 +1761,20 @@ void mount_partitions() noexcept { // utils::delete_partition_in_list(std::get(config_data["ROOT_PART"])); + // TODO(vnepogodin): parse luks information + const auto& mount_opts_info = std::get(config_data["MOUNT_OPTS"]); + + const auto& part_fs = gucc::fs::utils::get_mountpoint_fs(mountpoint_info); + auto root_part_struct = gucc::fs::Partition{.fstype = part_fs, .mountpoint = "/"s, .device = root_part, .mount_opts = mount_opts_info}; + + // insert root partition + partitions.emplace_back(std::move(root_part_struct)); + // Extra check if root is on LUKS or lvm // get_cryptroot // echo "$LUKS_DEV" > /tmp/.luks_dev // If the root partition is btrfs, offer to create subvolumes - if (gucc::fs::utils::get_mountpoint_fs(mountpoint_info) == "btrfs"sv) { + if (part_fs == "btrfs"sv) { // Check if there are subvolumes already on the btrfs partition const auto& subvolumes = fmt::format(FMT_COMPILE("btrfs subvolume list '{}' 2>/dev/null"), mountpoint_info); const auto& subvolumes_count = gucc::utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); @@ -1766,7 +1784,7 @@ void mount_partitions() noexcept { const auto& existing_subvolumes = detail::yesno_widget(fmt::format(FMT_COMPILE("\nFound subvolumes {}\n \nWould you like to mount them?\n "), subvolumes_formated), size(HEIGHT, LESS_THAN, 15) | size(WIDTH, LESS_THAN, 75)); // Pre-existing subvolumes and user wants to mount them /* clang-format off */ - if (existing_subvolumes) { utils::mount_existing_subvols({root_part, part}); } + if (existing_subvolumes) { utils::mount_existing_subvols(partitions); } /* clang-format on */ } else { // No subvolumes present. Make some new ones