diff --git a/gucc/CMakeLists.txt b/gucc/CMakeLists.txt index eec883c..b8b7fcc 100644 --- a/gucc/CMakeLists.txt +++ b/gucc/CMakeLists.txt @@ -28,6 +28,7 @@ add_library(${PROJECT_NAME} SHARED src/systemd_services.cpp include/gucc/systemd_services.hpp src/autologin.cpp include/gucc/autologin.hpp src/mtab.cpp include/gucc/mtab.hpp + src/umount_partitions.cpp include/gucc/umount_partitions.hpp #src/chwd_profiles.cpp src/chwd_profiles.hpp #src/disk.cpp src/disk.hpp ) diff --git a/gucc/include/gucc/umount_partitions.hpp b/gucc/include/gucc/umount_partitions.hpp new file mode 100644 index 0000000..998fa83 --- /dev/null +++ b/gucc/include/gucc/umount_partitions.hpp @@ -0,0 +1,15 @@ +#ifndef UMOUNT_PARTITIONS_HPP +#define UMOUNT_PARTITIONS_HPP + +#include // for string +#include // for string_view +#include // for vector + +namespace gucc::umount { + +// Umount partitions +auto umount_partitions(std::string_view root_mountpoint, const std::vector& zfs_poolnames) noexcept -> bool; + +} // namespace gucc::umount + +#endif // UMOUNT_PARTITIONS_HPP diff --git a/gucc/meson.build b/gucc/meson.build index 7eb1847..f90f545 100644 --- a/gucc/meson.build +++ b/gucc/meson.build @@ -18,6 +18,7 @@ gucc_lib = library('gucc', 'src/systemd_services.cpp', 'src/autologin.cpp', 'src/mtab.cpp', + 'src/umount_partitions.cpp', ], include_directories : [include_directories('include')], dependencies: deps diff --git a/gucc/src/umount_partitions.cpp b/gucc/src/umount_partitions.cpp new file mode 100644 index 0000000..cdc973f --- /dev/null +++ b/gucc/src/umount_partitions.cpp @@ -0,0 +1,63 @@ +#include "gucc/umount_partitions.hpp" +#include "gucc/file_utils.hpp" +#include "gucc/io_utils.hpp" +#include "gucc/mtab.hpp" +#include "gucc/string_utils.hpp" + +#include // for sort + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wold-style-cast" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wuseless-cast" +#pragma GCC diagnostic ignored "-Wold-style-cast" +#endif + +#include + +#if defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif + +#include +#include + +#include + +using namespace std::string_view_literals; + +namespace gucc::umount { + +auto umount_partitions(std::string_view root_mountpoint, const std::vector& zfs_poolnames) noexcept -> bool { + auto mtab_entries = mtab::parse_mtab(root_mountpoint); + if (!mtab_entries) { + spdlog::error("Failed to umount partitions: failed to parse /etc/mtab"); + return false; + } + ranges::sort(*mtab_entries, {}, &mtab::MTabEntry::mountpoint); + + spdlog::debug("Got {} entries from mountpoint {}", mtab_entries->size(), root_mountpoint); + for (auto&& mtab_entry : std::move(*mtab_entries)) { + const auto& umount_cmd = fmt::format(FMT_COMPILE("umount -v {} &>>/tmp/cachyos-install.log"), mtab_entry.mountpoint); + if (utils::exec(umount_cmd, true) != "0") { + spdlog::error("Failed to umount partition: {} {}", mtab_entry.device, mtab_entry.mountpoint); + return false; + } + } + + for (auto&& zfs_poolname : zfs_poolnames) { + const auto& zpool_export_cmd = fmt::format(FMT_COMPILE("zpool export {} &>>/tmp/cachyos-install.log"), zfs_poolname); + if (utils::exec(zpool_export_cmd, true) != "0") { + spdlog::error("Failed to export zpool: {}", zfs_poolname); + return false; + } + } + + return true; +} + +} // namespace gucc::umount diff --git a/src/config.cpp b/src/config.cpp index 9b9e996..7315ecd 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -37,6 +37,7 @@ bool Config::initialize() noexcept { s_config->m_data["LVM_LV_NAME"] = ""; // Name of LV to create or use s_config->m_data["LVM_SEP_BOOT"] = 0; s_config->m_data["READY_PARTITIONS"] = std::vector{}; + s_config->m_data["ZFS_ZPOOL_NAMES"] = std::vector{}; // Mounting s_config->m_data["MOUNTPOINT"] = "/mnt"; diff --git a/src/disk.cpp b/src/disk.cpp index 114c23a..6b9e7f3 100644 --- a/src/disk.cpp +++ b/src/disk.cpp @@ -178,8 +178,6 @@ bool zfs_create_zpool(const std::string_view& partition, const std::string_view& auto* config_instance = Config::instance(); auto& config_data = config_instance->data(); - config_data["ZFS_ZPOOL_NAME"] = std::string{pool_name.data()}; - static constexpr auto zpool_options{"-f -o ashift=12 -o autotrim=on -O acltype=posixacl -O compression=zstd -O atime=off -O relatime=off -O normalization=formD -O xattr=sa -O mountpoint=none"sv}; #ifdef NDEVENV @@ -215,6 +213,10 @@ bool zfs_create_zpool(const std::string_view& partition, const std::string_view& gucc::utils::exec(fmt::format(FMT_COMPILE("zpool import -R {} {} 2>>/tmp/cachyos-install.log"), mountpoint, pool_name), true); #endif + // insert zpool name into config + auto zfs_zpool_names = std::get>(config_data["ZFS_ZPOOL_NAMES"]); + zfs_zpool_names.push_back(pool_name.data()); + return true; } diff --git a/src/tui.cpp b/src/tui.cpp index f718d91..f82e568 100644 --- a/src/tui.cpp +++ b/src/tui.cpp @@ -1355,7 +1355,6 @@ bool zfs_create_zpool(bool do_create_zpool = true) noexcept { if (zfs_menu_text == zfs_zpool_body) { break; } /* clang-format on */ } - config_data["ZFS_ZPOOL_NAME"] = zfs_zpool_name; /* clang-format off */ if (!do_create_zpool) { return true; } @@ -1592,15 +1591,17 @@ void zfs_auto() noexcept { return; } - auto* config_instance = Config::instance(); - auto& config_data = config_instance->data(); - const auto& partition = std::get(config_data["PARTITION"]); - const auto& zfs_zpool_name = std::get(config_data["ZFS_ZPOOL_NAME"]); + auto* config_instance = Config::instance(); + auto& config_data = config_instance->data(); + const auto& partition = std::get(config_data["PARTITION"]); + const auto& zfs_zpool_names = std::get>(config_data["ZFS_ZPOOL_NAMES"]); - if (!utils::zfs_auto_pres(partition, zfs_zpool_name)) { - detail::infobox_widget("\nOperation failed\n"sv); - std::this_thread::sleep_for(std::chrono::seconds(3)); - return; + for (auto&& zfs_zpool_name : zfs_zpool_names) { + if (!utils::zfs_auto_pres(partition, zfs_zpool_name)) { + detail::infobox_widget("\nOperation failed\n"sv); + std::this_thread::sleep_for(std::chrono::seconds(3)); + return; + } } // provide confirmation to the user diff --git a/src/utils.cpp b/src/utils.cpp index 44d9483..ce46291 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -18,6 +18,7 @@ #include "gucc/pacmanconf_repo.hpp" #include "gucc/string_utils.hpp" #include "gucc/systemd_services.hpp" +#include "gucc/umount_partitions.hpp" #include "gucc/user.hpp" #include // for transform @@ -260,20 +261,18 @@ void umount_partitions() noexcept { auto* config_instance = Config::instance(); auto& config_data = config_instance->data(); - const auto& mountpoint_info = std::get(config_data["MOUNTPOINT"]); - auto mount_info = gucc::utils::exec(fmt::format(FMT_COMPILE("mount | grep \"{}\" | {}"), mountpoint_info, "awk '{print $3}' | sort -r")); + const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); + const auto& zfs_zpool_names = std::get>(config_data["ZFS_ZPOOL_NAMES"]); #ifdef NDEVENV + gucc::utils::exec("swapoff -a"); -#endif - const auto& lines = gucc::utils::make_multiline(mount_info); - for (const auto& line : lines) { -#ifdef NDEVENV - umount(line.c_str()); + if (!gucc::umount::umount_partitions(mountpoint, zfs_zpool_names)) { + spdlog::error("Failed to umount partitions"); + } #else - spdlog::debug("{}\n", line); + spdlog::info("Unmounting partitions on {}, zfs zpool names {}", mountpoint, zfs_zpool_names); #endif - } } // BIOS and UEFI