🧹 move mount of specified part and detection into gucc

This commit is contained in:
Vladislav Nepogodin 2024-07-11 19:43:32 +04:00
parent a70e641e36
commit 9d420d2577
No known key found for this signature in database
GPG Key ID: B62C3D10C54D5DA9
6 changed files with 132 additions and 83 deletions

View File

@ -35,6 +35,7 @@ add_library(${PROJECT_NAME} #SHARED
src/autologin.cpp include/gucc/autologin.hpp
src/mtab.cpp include/gucc/mtab.hpp
src/umount_partitions.cpp include/gucc/umount_partitions.hpp
src/mount_partitions.cpp include/gucc/mount_partitions.hpp
src/hwclock.cpp include/gucc/hwclock.hpp
src/package_profiles.cpp include/gucc/package_profiles.hpp
src/fetch_file.cpp include/gucc/fetch_file.hpp

View File

@ -0,0 +1,18 @@
#ifndef MOUNT_PARTITIONS_HPP
#define MOUNT_PARTITIONS_HPP
#include <cinttypes> // for int32_t
#include <string> // for string
#include <string_view> // for string_view
namespace gucc::mount {
// Mount partition
auto mount_partition(std::string_view partition, std::string_view mount_dir, std::string_view mount_opts) noexcept -> bool;
// Query partition
auto query_partition(std::string_view partition, std::int32_t& is_luks, std::int32_t& is_lvm, std::string& luks_name, std::string& luks_dev, std::string& luks_uuid) noexcept -> bool;
} // namespace gucc::mount
#endif // MOUNT_PARTITIONS_HPP

View File

@ -19,6 +19,7 @@ gucc_lib = library('gucc',
'src/autologin.cpp',
'src/mtab.cpp',
'src/umount_partitions.cpp',
'src/mount_partitions.cpp',
'src/hwclock.cpp',
'src/package_profiles.cpp',
'src/logger.cpp',

View File

@ -0,0 +1,96 @@
#include "gucc/mount_partitions.hpp"
#include "gucc/io_utils.hpp"
#include "gucc/string_utils.hpp"
#include <fmt/compile.h>
#include <fmt/format.h>
using namespace std::string_view_literals;
namespace gucc::mount {
auto mount_partition(std::string_view partition, std::string_view mount_dir, std::string_view mount_opts) noexcept -> bool {
if (!mount_opts.empty()) {
return utils::exec(fmt::format(FMT_COMPILE("mount -o {} {} {}"), mount_opts, partition, mount_dir)) == "0";
}
return utils::exec(fmt::format(FMT_COMPILE("mount {} {}"), partition, mount_dir)) == "0";
}
auto query_partition(std::string_view partition, std::int32_t& is_luks, std::int32_t& is_lvm, std::string& luks_name, std::string& luks_dev, std::string& luks_uuid) noexcept -> bool {
// Identify if mounted partition is type "crypt" (LUKS on LVM, or LUKS alone)
if (utils::exec(fmt::format(FMT_COMPILE("lsblk -lno TYPE {} | grep -q 'crypt'"), partition), true) == "0") {
// cryptname for bootloader configuration either way
is_luks = true;
luks_name = utils::exec(fmt::format(FMT_COMPILE("echo {} | sed \"s~^/dev/mapper/~~g\""), partition));
const auto& check_cryptparts = [&](auto&& cryptparts, const auto& functor) {
for (const auto& cryptpart : cryptparts) {
if (utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME {} | grep -q '{}'"), cryptpart, luks_name)) == "0") {
functor(cryptpart);
return true;
}
}
return false;
};
// Check if LUKS on LVM (parent = lvm /dev/mapper/...)
auto check_functor = [&](auto&& cryptpart) {
luks_dev = fmt::format(FMT_COMPILE("{} cryptdevice={}:{}"), luks_dev, cryptpart, luks_name);
is_lvm = true;
};
auto cryptparts = utils::make_multiline(utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep 'lvm' | grep -i 'crypto_luks' | uniq | awk '{print "/dev/mapper/"$1}')"));
if (check_cryptparts(cryptparts, check_functor)) {
return true;
}
// Check if LVM on LUKS
cryptparts = utils::make_multiline(utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep ' crypt$' | grep -i 'LVM2_member' | uniq | awk '{print "/dev/mapper/"$1}')"));
if (check_cryptparts(cryptparts, check_functor)) {
return true;
}
// Check if LUKS alone (parent = part /dev/...)
const auto& check_func_dev = [&](auto&& cryptpart) {
luks_uuid = utils::exec(fmt::format(FMT_COMPILE("lsblk -lno UUID,TYPE,FSTYPE {} | grep 'part' | grep -i 'crypto_luks' | {}"), cryptpart, "awk '{print $1}'"));
luks_dev = fmt::format(FMT_COMPILE("{} cryptdevice=UUID={}:{}"), luks_dev, luks_uuid, luks_name);
};
cryptparts = utils::make_multiline(utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep 'part' | grep -i 'crypto_luks' | uniq | awk '{print "/dev/"$1}')"));
if (check_cryptparts(cryptparts, check_func_dev)) {
return true;
}
}
/*
// If LVM logical volume....
elif [[ $(lsblk -lno TYPE ${PARTITION} | grep "lvm") != "" ]]; then
LVM=1
// First get crypt name (code above would get lv name)
cryptparts=$(lsblk -lno NAME,TYPE,FSTYPE | grep "crypt" | grep -i "lvm2_member" | uniq | awk '{print "/dev/mapper/"$1}')
for i in ${cryptparts}; do
if [[ $(lsblk -lno NAME ${i} | grep $(echo $PARTITION | sed "s~^/dev/mapper/~~g")) != "" ]]; then
LUKS_NAME=$(echo ${i} | sed s~/dev/mapper/~~g)
return 0;
fi
done
// Now get the device (/dev/...) for the crypt name
cryptparts=$(lsblk -lno NAME,FSTYPE,TYPE | grep "part" | grep -i "crypto_luks" | uniq | awk '{print "/dev/"$1}')
for i in ${cryptparts}; do
if [[ $(lsblk -lno NAME ${i} | grep $LUKS_NAME) != "" ]]; then
# Create UUID for comparison
LUKS_UUID=$(lsblk -lno UUID,TYPE,FSTYPE ${i} | grep "part" | grep -i "crypto_luks" | awk '{print $1}')
# Check if not already added as a LUKS DEVICE (i.e. multiple LVs on one crypt). If not, add.
if [[ $(echo $LUKS_DEV | grep $LUKS_UUID) == "" ]]; then
LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
LUKS=1
fi
return 0;
fi
fi*/
return true;
}
} // namespace gucc::mount

View File

@ -77,7 +77,7 @@ namespace tui {
// Revised to deal with partition sizes now being displayed to the user
bool confirm_mount([[maybe_unused]] const std::string_view& part_user, bool quite) {
#ifdef NDEVENV
const auto& ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("mount | grep {}"), part_user), true);
const auto& ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("mount | grep -q {}"), part_user), true);
if (!quite && (ret_status != "0"sv)) {
detail::infobox_widget("\nMount Failed!\n"sv);
std::this_thread::sleep_for(std::chrono::seconds(2));

View File

@ -13,6 +13,7 @@
#include "gucc/fs_utils.hpp"
#include "gucc/io_utils.hpp"
#include "gucc/locale.hpp"
#include "gucc/mount_partitions.hpp"
#include "gucc/string_utils.hpp"
#include "gucc/zfs.hpp"
@ -977,10 +978,10 @@ bool mount_current_partition(bool force) noexcept {
const auto& partition = std::get<std::string>(config_data["PARTITION"]);
const auto& mount_dev = std::get<std::string>(config_data["MOUNT"]);
// Make the mount directory
const auto& mount_dir = fmt::format(FMT_COMPILE("{}{}"), mountpoint, mount_dev);
#ifdef NDEVENV
std::error_code err{};
// Make the mount directory
const fs::path mount_dir(fmt::format(FMT_COMPILE("{}{}"), mountpoint, mount_dev));
fs::create_directories(mount_dir, err);
#endif
@ -995,96 +996,28 @@ bool mount_current_partition(bool force) noexcept {
// see https://github.com/util-linux/util-linux/blob/master/sys-utils/mount.c#L734
#ifdef NDEVENV
const auto& mount_opts_info = std::get<std::string>(config_data["MOUNT_OPTS"]);
if (!mount_opts_info.empty()) {
// check_for_error "mount ${PARTITION} $(cat ${MOUNT_OPTS})"
const auto& mount_status = gucc::utils::exec(fmt::format(FMT_COMPILE("mount -o {} {} {}{}"), mount_opts_info, partition, mountpoint, mount_dev));
spdlog::info("{}", mount_status);
} else {
// check_for_error "mount ${PARTITION}"
const auto& mount_status = gucc::utils::exec(fmt::format(FMT_COMPILE("mount {} {}{}"), partition, mountpoint, mount_dev));
spdlog::info("{}", mount_status);
if (!gucc::mount::mount_partition(partition, mount_dir, mount_opts_info)) {
spdlog::error("Failed to mount partition {} at {} with {}", partition, mount_dir, mount_opts_info);
}
#endif
/* clang-format off */
confirm_mount(fmt::format(FMT_COMPILE("{}{}"), mountpoint, mount_dev), force);
confirm_mount(mount_dir, force);
/* clang-format on */
// Identify if mounted partition is type "crypt" (LUKS on LVM, or LUKS alone)
if (!gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -lno TYPE {} | grep \"crypt\""), partition)).empty()) {
// cryptname for bootloader configuration either way
config_data["LUKS"] = 1;
auto& luks_name = std::get<std::string>(config_data["LUKS_NAME"]);
const auto& luks_dev = std::get<std::string>(config_data["LUKS_DEV"]);
luks_name = gucc::utils::exec(fmt::format(FMT_COMPILE("echo {} | sed \"s~^/dev/mapper/~~g\""), partition));
const auto& check_cryptparts = [&](const auto cryptparts, auto functor) {
for (const auto& cryptpart : cryptparts) {
if (!gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME {} | grep \"{}\""), cryptpart, luks_name)).empty()) {
functor(cryptpart);
return true;
}
}
return false;
};
// Check if LUKS on LVM (parent = lvm /dev/mapper/...)
auto cryptparts = gucc::utils::make_multiline(gucc::utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep "lvm" | grep -i "crypto_luks" | uniq | awk '{print "/dev/mapper/"$1}')"));
auto check_functor = [&](const auto cryptpart) {
config_data["LUKS_DEV"] = fmt::format(FMT_COMPILE("{} cryptdevice={}:{}"), luks_dev, cryptpart, luks_name);
config_data["LVM"] = 1;
};
if (check_cryptparts(cryptparts, check_functor)) {
return true;
}
// Check if LVM on LUKS
cryptparts = gucc::utils::make_multiline(gucc::utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep " crypt$" | grep -i "LVM2_member" | uniq | awk '{print "/dev/mapper/"$1}')"));
if (check_cryptparts(cryptparts, check_functor)) {
return true;
}
// Check if LUKS alone (parent = part /dev/...)
cryptparts = gucc::utils::make_multiline(gucc::utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep "part" | grep -i "crypto_luks" | uniq | awk '{print "/dev/"$1}')"));
const auto& check_func_dev = [&](const auto cryptpart) {
auto& luks_dev = std::get<std::string>(config_data["LUKS_DEV"]);
auto& luks_uuid = std::get<std::string>(config_data["LUKS_UUID"]);
luks_uuid = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -lno UUID,TYPE,FSTYPE {} | grep \"part\" | grep -i \"crypto_luks\" | {}"), cryptpart, "awk '{print $1}'"));
config_data["LUKS_DEV"] = fmt::format(FMT_COMPILE("{} cryptdevice=UUID={}:{}"), luks_dev, luks_uuid, luks_name);
};
if (check_cryptparts(cryptparts, check_func_dev)) {
return true;
auto& is_luks = std::get<std::int32_t>(config_data["LUKS"]);
auto& is_lvm = std::get<std::int32_t>(config_data["LVM"]);
if (!gucc::mount::query_partition(partition, is_luks, is_lvm, luks_name, luks_dev, luks_uuid)) {
spdlog::error("Failed to query partition: {}", partition);
return false;
}
}
/*
// If LVM logical volume....
elif [[ $(lsblk -lno TYPE ${PARTITION} | grep "lvm") != "" ]]; then
LVM=1
// First get crypt name (code above would get lv name)
cryptparts=$(lsblk -lno NAME,TYPE,FSTYPE | grep "crypt" | grep -i "lvm2_member" | uniq | awk '{print "/dev/mapper/"$1}')
for i in ${cryptparts}; do
if [[ $(lsblk -lno NAME ${i} | grep $(echo $PARTITION | sed "s~^/dev/mapper/~~g")) != "" ]]; then
LUKS_NAME=$(echo ${i} | sed s~/dev/mapper/~~g)
return 0;
fi
done
// Now get the device (/dev/...) for the crypt name
cryptparts=$(lsblk -lno NAME,FSTYPE,TYPE | grep "part" | grep -i "crypto_luks" | uniq | awk '{print "/dev/"$1}')
for i in ${cryptparts}; do
if [[ $(lsblk -lno NAME ${i} | grep $LUKS_NAME) != "" ]]; then
# Create UUID for comparison
LUKS_UUID=$(lsblk -lno UUID,TYPE,FSTYPE ${i} | grep "part" | grep -i "crypto_luks" | awk '{print $1}')
# Check if not already added as a LUKS DEVICE (i.e. multiple LVs on one crypt). If not, add.
if [[ $(echo $LUKS_DEV | grep $LUKS_UUID) == "" ]]; then
LUKS_DEV="$LUKS_DEV cryptdevice=UUID=$LUKS_UUID:$LUKS_NAME"
LUKS=1
fi
return 0;
fi
fi*/
spdlog::debug("partition '{}': is_luks:={};is_lvm:={};luks_name:='{}';luks_dev:='{}';luks_uuid:='{}'", partition, is_luks, is_lvm, luks_name, luks_dev, luks_uuid);
return true;
}