diff --git a/gucc/CMakeLists.txt b/gucc/CMakeLists.txt index debef86..04602c5 100644 --- a/gucc/CMakeLists.txt +++ b/gucc/CMakeLists.txt @@ -10,6 +10,7 @@ project(gucc add_library(${PROJECT_NAME} SHARED #src/utils.cpp src/utils.hpp + src/io_utils.cpp include/gucc/io_utils.hpp src/string_utils.cpp include/gucc/string_utils.hpp src/file_utils.cpp include/gucc/file_utils.hpp src/cpu.cpp include/gucc/cpu.hpp diff --git a/gucc/include/gucc/io_utils.hpp b/gucc/include/gucc/io_utils.hpp new file mode 100644 index 0000000..4f73a8f --- /dev/null +++ b/gucc/include/gucc/io_utils.hpp @@ -0,0 +1,16 @@ +#ifndef IO_UTILS_HPP +#define IO_UTILS_HPP + +#include // for string +#include // for string_view +#include // for vector + +namespace gucc::utils { + +auto safe_getenv(const char* env_name) noexcept -> std::string_view; +void exec(const std::vector& vec) noexcept; +auto exec(std::string_view command, bool interactive = false) noexcept -> std::string; + +} // namespace gucc::utils + +#endif // IO_UTILS_HPP diff --git a/gucc/src/io_utils.cpp b/gucc/src/io_utils.cpp new file mode 100644 index 0000000..0856d75 --- /dev/null +++ b/gucc/src/io_utils.cpp @@ -0,0 +1,91 @@ +#include "gucc/io_utils.hpp" + +#include // for waitpid +#include // for execvp, fork + +#include // for int32_t +#include // for feof, fgets, pclose, popen +#include // for WIFEXITED, WIFSIGNALED + +#include // for transform +#include // for ofstream + +#include +#include + +using namespace std::string_view_literals; + +namespace gucc::utils { + +auto safe_getenv(const char* env_name) noexcept -> std::string_view { + const char* const raw_val = getenv(env_name); + return raw_val != nullptr ? std::string_view{raw_val} : std::string_view{}; +} + +void exec(const std::vector& vec) noexcept { + const bool log_exec_cmds = utils::safe_getenv("LOG_EXEC_CMDS") == "1"sv; + const bool dirty_cmd_run = utils::safe_getenv("DIRTY_CMD_RUN") == "1"sv; + + if (log_exec_cmds && spdlog::default_logger_raw() != nullptr) { + spdlog::debug("[exec] cmd := {}", vec); + } + if (dirty_cmd_run) { + return; + } + + std::int32_t status{}; + auto pid = fork(); + if (pid == 0) { + std::vector args; + std::transform(vec.cbegin(), vec.cend(), std::back_inserter(args), + [=](const std::string& arg) -> char* { return const_cast(arg.data()); }); + args.push_back(nullptr); + + char** command = args.data(); + execvp(command[0], command); + } else { + do { + waitpid(pid, &status, 0); + } while ((!WIFEXITED(status)) && (!WIFSIGNALED(status))); + } +} + +// https://github.com/sheredom/subprocess.h +// https://gist.github.com/konstantint/d49ab683b978b3d74172 +// https://github.com/arun11299/cpp-subprocess/blob/master/subprocess.hpp#L1218 +// https://stackoverflow.com/questions/11342868/c-interface-for-interactive-bash +// https://github.com/hniksic/rust-subprocess +auto exec(std::string_view command, bool interactive) noexcept -> std::string { + const bool log_exec_cmds = utils::safe_getenv("LOG_EXEC_CMDS") == "1"sv; + + if (log_exec_cmds && spdlog::default_logger_raw() != nullptr) { + spdlog::debug("[exec] cmd := '{}'", command); + } + + if (interactive) { + const auto& ret_code = system(command.data()); + return std::to_string(ret_code); + } + + const std::unique_ptr pipe(popen(command.data(), "r"), pclose); + if (!pipe) { + spdlog::error("popen failed! '{}'", command); + return "-1"; + } + + std::string result{}; + std::array buffer{}; + while (!feof(pipe.get())) { + if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { + result += buffer.data(); + } + } + + if (result.ends_with('\n')) { + result.pop_back(); + } + + return result; +} + +} // namespace gucc::utils diff --git a/src/chwd_profiles.cpp b/src/chwd_profiles.cpp index abe4a41..cd8c978 100644 --- a/src/chwd_profiles.cpp +++ b/src/chwd_profiles.cpp @@ -2,6 +2,7 @@ #include "utils.hpp" // import gucc +#include "gucc/io_utils.hpp" #include "gucc/string_utils.hpp" #include // for any_of, sort, for_each @@ -64,7 +65,7 @@ auto get_available_profile_names(std::string_view profile_type) noexcept -> std: if (!all_profile_names.has_value()) { return {}; } /* clang-format on */ - const auto& available_profile_names = gucc::utils::make_multiline(utils::exec("chwd --list -d | grep Name | awk '{print $4}'")); + const auto& available_profile_names = gucc::utils::make_multiline(gucc::utils::exec("chwd --list -d | grep Name | awk '{print $4}'")); std::vector filtered_profile_names{}; const auto& functor = [available_profile_names](auto&& profile_name) { return ranges::any_of(available_profile_names, [profile_name](auto&& available_profile) { return available_profile == profile_name; }); }; diff --git a/src/crypto.cpp b/src/crypto.cpp index 331423f..f91efac 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -4,6 +4,7 @@ #include "widgets.hpp" // import gucc +#include "gucc/io_utils.hpp" #include "gucc/string_utils.hpp" #include @@ -114,7 +115,7 @@ bool luks_open() noexcept { detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format(FMT_COMPILE("echo \"{}\" | cryptsetup open --type luks {} {}"), luks_password, partition, luks_root_name)}); #endif - const auto& devlist = utils::exec(fmt::format(FMT_COMPILE("lsblk -o NAME,TYPE,FSTYPE,SIZE,MOUNTPOINT {} | grep \"crypt\\|NAME\\|MODEL\\|TYPE\\|FSTYPE\\|SIZE\""), partition)); + const auto& devlist = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -o NAME,TYPE,FSTYPE,SIZE,MOUNTPOINT {} | grep \"crypt\\|NAME\\|MODEL\\|TYPE\\|FSTYPE\\|SIZE\""), partition)); detail::msgbox_widget(devlist); return true; @@ -125,7 +126,7 @@ bool luks_setup() noexcept { auto& config_data = config_instance->data(); #ifdef NDEVENV - utils::exec("modprobe -a dm-mod dm_crypt"); + gucc::utils::exec("modprobe -a dm-mod dm_crypt"); #endif config_data["INCLUDE_PART"] = "part\\|lvm"; utils::umount_partitions(); @@ -187,7 +188,7 @@ void luks_express() noexcept { void luks_show() noexcept { static constexpr auto luks_success = "Done!"; - const auto& lsblk = utils::exec(R"(lsblk -o NAME,TYPE,FSTYPE,SIZE | grep "part\|crypt\|NAME\|TYPE\|FSTYPE\|SIZE")"); + const auto& lsblk = gucc::utils::exec(R"(lsblk -o NAME,TYPE,FSTYPE,SIZE | grep "part\|crypt\|NAME\|TYPE\|FSTYPE\|SIZE")"); const auto& content = fmt::format(FMT_COMPILE("\n{}\n \n{}"), luks_success, lsblk); detail::msgbox_widget(content, size(HEIGHT, GREATER_THAN, 5)); } diff --git a/src/disk.cpp b/src/disk.cpp index 7693a31..0058b99 100644 --- a/src/disk.cpp +++ b/src/disk.cpp @@ -4,6 +4,7 @@ #include "widgets.hpp" // import gucc +#include "gucc/io_utils.hpp" #include "gucc/string_utils.hpp" #include // for exists, is_directory @@ -28,8 +29,8 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str #ifdef NDEVENV // save mount options and name of the root partition - utils::exec("mount | grep \"on /mnt \" | grep -Po '(?<=\\().*(?=\\))' > /tmp/.root_mount_options"sv); - // utils::exec("lsblk -lno MOUNTPOINT,NAME | awk '/^\\/mnt / {print $2}' > /tmp/.root_partition"sv); + gucc::utils::exec("mount | grep \"on /mnt \" | grep -Po '(?<=\\().*(?=\\))' > /tmp/.root_mount_options"sv); + // gucc::utils::exec("lsblk -lno MOUNTPOINT,NAME | awk '/^\\/mnt / {print $2}' > /tmp/.root_partition"sv); if (mode == "manual"sv) { // Create subvolumes manually @@ -42,13 +43,13 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str fs::current_path("/mnt"); auto subvol_list = gucc::utils::make_multiline(subvols, false, ' '); for (const auto& subvol : subvol_list) { - utils::exec(fmt::format(FMT_COMPILE("btrfs subvolume create {} 2>>/tmp/cachyos-install.log"), subvol), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("btrfs subvolume create {} 2>>/tmp/cachyos-install.log"), subvol), true); } fs::current_path(saved_path); // Mount subvolumes umount("/mnt"); // Mount the first subvolume as / - utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=\"{}\" \"{}\" /mnt"), disk.mount_opts, subvol_list[0], disk.root)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=\"{}\" \"{}\" /mnt"), disk.mount_opts, subvol_list[0], disk.root)); // Remove the first subvolume from the subvolume list subvol_list.erase(subvol_list.begin()); @@ -62,7 +63,7 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str const auto& mountp_formatted = fmt::format(FMT_COMPILE("/mnt{}"), mountp); fs::create_directories(mountp_formatted); - utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=\"{}\" \"{}\" \"{}\""), disk.mount_opts, subvol, disk.root, mountp_formatted)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=\"{}\" \"{}\" \"{}\""), disk.mount_opts, subvol, disk.root, mountp_formatted)); } return; } @@ -77,18 +78,18 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str // Create subvolumes automatically const auto& saved_path = fs::current_path(); fs::current_path("/mnt"); - utils::exec("btrfs subvolume create @ 2>>/tmp/cachyos-install.log"sv, true); - utils::exec("btrfs subvolume create @home 2>>/tmp/cachyos-install.log"sv, true); - utils::exec("btrfs subvolume create @cache 2>>/tmp/cachyos-install.log"sv, true); - // utils::exec("btrfs subvolume create @snapshots 2>>/tmp/cachyos-install.log"sv, true); + gucc::utils::exec("btrfs subvolume create @ 2>>/tmp/cachyos-install.log"sv, true); + gucc::utils::exec("btrfs subvolume create @home 2>>/tmp/cachyos-install.log"sv, true); + gucc::utils::exec("btrfs subvolume create @cache 2>>/tmp/cachyos-install.log"sv, true); + // gucc::utils::exec("btrfs subvolume create @snapshots 2>>/tmp/cachyos-install.log"sv, true); fs::current_path(saved_path); // Mount subvolumes umount("/mnt"); - utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@ \"{}\" /mnt"), disk.mount_opts, disk.root)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@ \"{}\" /mnt"), disk.mount_opts, disk.root)); fs::create_directories("/mnt/home"); fs::create_directories("/mnt/var/cache"); - utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@home \"{}\" /mnt/home"), disk.mount_opts, disk.root)); - utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@cache \"{}\" /mnt/var/cache"), disk.mount_opts, disk.root)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@home \"{}\" /mnt/home"), disk.mount_opts, disk.root)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount -o {},subvol=@cache \"{}\" /mnt/var/cache"), disk.mount_opts, disk.root)); #else spdlog::info("Do we ignore note? {}", ignore_note); #endif @@ -96,21 +97,21 @@ void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::str void mount_existing_subvols(const disk_part& disk) noexcept { // Set mount options - const auto& format_name = utils::exec(fmt::format(FMT_COMPILE("echo {} | rev | cut -d/ -f1 | rev"), disk.part)); - const auto& format_device = 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& 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)); std::string fs_opts{}; - if (utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/queue/rotational)"), format_device), true) == "1"sv) { + if (gucc::utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/queue/rotational)"), format_device), true) == "1"sv) { fs_opts = "autodefrag,compress=zlib,noatime,nossd,commit=120"sv; } else { fs_opts = "compress=lzo,noatime,space_cache,ssd,commit=120"sv; } #ifdef NDEVENV - utils::exec("btrfs subvolume list /mnt 2>/dev/null | cut -d\" \" -f9 > /tmp/.subvols"sv, true); + gucc::utils::exec("btrfs subvolume list /mnt 2>/dev/null | cut -d\" \" -f9 > /tmp/.subvols"sv, true); umount("/mnt"); // Mount subvolumes one by one - for (const auto& subvol : gucc::utils::make_multiline(utils::exec("cat /tmp/.subvols"sv))) { + for (const auto& subvol : gucc::utils::make_multiline(gucc::utils::exec("cat /tmp/.subvols"sv))) { // Ask for mountpoint const auto& content = fmt::format(FMT_COMPILE("\nInput mountpoint of\nthe subvolume {}\nas it would appear\nin installed system\n(without prepending /mnt).\n"), subvol); std::string mountpoint{"/"}; @@ -122,18 +123,18 @@ void mount_existing_subvols(const disk_part& disk) noexcept { fs::create_directories(mount_dir); } // Mount the subvolume - utils::exec(fmt::format(FMT_COMPILE("mount -o \"{},subvol={}\" \"{}\" \"{}\""), fs_opts, subvol, disk.root, mount_dir)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount -o \"{},subvol={}\" \"{}\" \"{}\""), fs_opts, subvol, disk.root, mount_dir)); } #endif } std::vector lvm_show_vg() noexcept { - const auto& vg_list = gucc::utils::make_multiline(utils::exec("lvs --noheadings | awk '{print $2}' | uniq"sv)); + const auto& vg_list = gucc::utils::make_multiline(gucc::utils::exec("lvs --noheadings | awk '{print $2}' | uniq"sv)); std::vector res{}; res.reserve(vg_list.size()); for (const auto& vg : vg_list) { - const auto& temp = utils::exec(fmt::format(FMT_COMPILE("vgdisplay {} | grep -i \"vg size\" | {}"), vg, "awk '{print $3$4}'"sv)); + const auto& temp = gucc::utils::exec(fmt::format(FMT_COMPILE("vgdisplay {} | grep -i \"vg size\" | {}"), vg, "awk '{print $3$4}'"sv)); res.push_back(temp); } @@ -157,7 +158,7 @@ bool zfs_auto_pres(const std::string_view& partition, const std::string_view& zf #ifdef NDEVENV // set the rootfs - utils::exec(fmt::format(FMT_COMPILE("zpool set bootfs={0}/ROOT/cos/root {0} 2>>/tmp/cachyos-install.log"), zfs_zpool_name), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zpool set bootfs={0}/ROOT/cos/root {0} 2>>/tmp/cachyos-install.log"), zfs_zpool_name), true); #endif return true; } @@ -175,15 +176,15 @@ bool zfs_create_zpool(const std::string_view& partition, const std::string_view& std::int32_t ret_code{}; // Find the UUID of the partition - const auto& partuuid = utils::exec(fmt::format(FMT_COMPILE("lsblk -lno PATH,PARTUUID | grep \"^{}\" | {}"), partition, "awk '{print $2}'"sv), false); + const auto& partuuid = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -lno PATH,PARTUUID | grep \"^{}\" | {}"), partition, "awk '{print $2}'"sv), false); // See if the partition has a partuuid, if not use the device name const auto& zfs_zpool_cmd = fmt::format(FMT_COMPILE("zpool create {} {}"), zpool_options, pool_name); if (!partuuid.empty()) { - ret_code = utils::to_int(utils::exec(fmt::format(FMT_COMPILE("{} {} 2>>/tmp/cachyos-install.log"), zfs_zpool_cmd, partuuid), true)); + ret_code = utils::to_int(gucc::utils::exec(fmt::format(FMT_COMPILE("{} {} 2>>/tmp/cachyos-install.log"), zfs_zpool_cmd, partuuid), true)); spdlog::info("Creating zpool {} on device {} using partuuid {}", pool_name, partition, partuuid); } else { - ret_code = utils::to_int(utils::exec(fmt::format(FMT_COMPILE("{} {} 2>>/tmp/cachyos-install.log"), zfs_zpool_cmd, partition), true)); + ret_code = utils::to_int(gucc::utils::exec(fmt::format(FMT_COMPILE("{} {} 2>>/tmp/cachyos-install.log"), zfs_zpool_cmd, partition), true)); spdlog::info("Creating zpool {} on device {}", pool_name, partition); } @@ -200,8 +201,8 @@ bool zfs_create_zpool(const std::string_view& partition, const std::string_view& #ifdef NDEVENV // Since zfs manages mountpoints, we export it and then import with a root of MOUNTPOINT const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); - utils::exec(fmt::format(FMT_COMPILE("zpool export {} 2>>/tmp/cachyos-install.log"), pool_name), true); - utils::exec(fmt::format(FMT_COMPILE("zpool import -R {} {} 2>>/tmp/cachyos-install.log"), mountpoint, pool_name), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zpool export {} 2>>/tmp/cachyos-install.log"), pool_name), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zpool import -R {} {} 2>>/tmp/cachyos-install.log"), mountpoint, pool_name), true); #endif return true; @@ -210,7 +211,7 @@ bool zfs_create_zpool(const std::string_view& partition, const std::string_view& // Creates a zfs volume void zfs_create_zvol(const std::string_view& zsize, const std::string_view& zpath) noexcept { #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("zfs create -V {}M {} 2>>/tmp/cachyos-install.log"), zsize, zpath), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zfs create -V {}M {} 2>>/tmp/cachyos-install.log"), zsize, zpath), true); #else spdlog::debug("zfs create -V {}M {}", zsize, zpath); #endif @@ -219,7 +220,7 @@ void zfs_create_zvol(const std::string_view& zsize, const std::string_view& zpat // Creates a zfs filesystem, the first parameter is the ZFS path and the second is the mount path void zfs_create_dataset(const std::string_view& zpath, const std::string_view& zmount) noexcept { #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("zfs create -o mountpoint={} {} 2>>/tmp/cachyos-install.log"), zmount, zpath), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zfs create -o mountpoint={} {} 2>>/tmp/cachyos-install.log"), zmount, zpath), true); #else spdlog::debug("zfs create -o mountpoint={} {}", zmount, zpath); #endif @@ -227,7 +228,7 @@ void zfs_create_dataset(const std::string_view& zpath, const std::string_view& z void zfs_destroy_dataset(const std::string_view& zdataset) noexcept { #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("zfs destroy -r {} 2>>/tmp/cachyos-install.log"), zdataset), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zfs destroy -r {} 2>>/tmp/cachyos-install.log"), zdataset), true); #else spdlog::debug("zfs destroy -r {}", zdataset); #endif @@ -236,7 +237,7 @@ void zfs_destroy_dataset(const std::string_view& zdataset) noexcept { // returns a list of imported zpools std::string zfs_list_pools() noexcept { #ifdef NDEVENV - return utils::exec("zfs list -H -o name 2>/dev/null | grep \"/\""sv); + return gucc::utils::exec("zfs list -H -o name 2>/dev/null | grep \"/\""sv); #else return "vol0\nvol1\n"; #endif @@ -246,12 +247,12 @@ std::string zfs_list_pools() noexcept { std::string zfs_list_devs() noexcept { std::string list_of_devices{}; // get a list of devices with zpools on them - const auto& devices = gucc::utils::make_multiline(utils::exec("zpool status -PL 2>/dev/null | awk '{print $1}' | grep \"^/\""sv)); + const auto& devices = gucc::utils::make_multiline(gucc::utils::exec("zpool status -PL 2>/dev/null | awk '{print $1}' | grep \"^/\""sv)); for (const auto& device : devices) { // add the device list_of_devices += fmt::format(FMT_COMPILE("{}\n"), device); // now let's add any other forms of those devices - list_of_devices += utils::exec(fmt::format(FMT_COMPILE("find -L /dev/ -xtype l -samefile {} 2>/dev/null"), device)); + list_of_devices += gucc::utils::exec(fmt::format(FMT_COMPILE("find -L /dev/ -xtype l -samefile {} 2>/dev/null"), device)); } return list_of_devices; } @@ -259,12 +260,12 @@ std::string zfs_list_devs() noexcept { std::string zfs_list_datasets(const std::string_view& type) noexcept { #ifdef NDEVENV if (type == "zvol"sv) { - return utils::exec("zfs list -Ht volume -o name,volsize 2>/dev/null"sv); + return gucc::utils::exec("zfs list -Ht volume -o name,volsize 2>/dev/null"sv); } else if (type == "legacy"sv) { - return utils::exec("zfs list -Ht filesystem -o name,mountpoint 2>/dev/null | grep \"^.*/.*legacy$\" | awk '{print $1}'"sv); + return gucc::utils::exec("zfs list -Ht filesystem -o name,mountpoint 2>/dev/null | grep \"^.*/.*legacy$\" | awk '{print $1}'"sv); } - return utils::exec("zfs list -H -o name 2>/dev/null | grep \"/\""sv); + return gucc::utils::exec("zfs list -H -o name 2>/dev/null | grep \"/\""sv); #else spdlog::debug("type := {}", type); return "zpcachyos"; @@ -273,7 +274,7 @@ std::string zfs_list_datasets(const std::string_view& type) noexcept { void zfs_set_property(const std::string_view& property, const std::string_view& dataset) noexcept { #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("zfs set {} {} 2>>/tmp/cachyos-install.log"), property, dataset), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zfs set {} {} 2>>/tmp/cachyos-install.log"), property, dataset), true); #else spdlog::debug("zfs set {} {}", property, dataset); #endif @@ -290,7 +291,7 @@ void select_filesystem(const std::string_view& file_sys) noexcept { config_data["FILESYSTEM"] = "mkfs.btrfs -f"; config_data["fs_opts"] = std::vector{"autodefrag", "compress=zlib", "compress=lzo", "compress=zstd", "compress=no", "compress-force=zlib", "compress-force=lzo", "compress-force=zstd", "discard", "noacl", "noatime", "nodatasum", "nospace_cache", "recovery", "skip_balance", "space_cache", "nossd", "ssd", "ssd_spread", "commit=120"}; #ifdef NDEVENV - utils::exec("modprobe btrfs"sv); + gucc::utils::exec("modprobe btrfs"sv); #endif } else if (file_sys == "ext4"sv) { config_data["FILESYSTEM"] = "mkfs.ext4 -q"; @@ -299,7 +300,7 @@ void select_filesystem(const std::string_view& file_sys) noexcept { config_data["FILESYSTEM"] = "mkfs.f2fs -q"; config_data["fs_opts"] = std::vector{"data_flush", "disable_roll_forward", "disable_ext_identify", "discard", "fastboot", "flush_merge", "inline_xattr", "inline_data", "inline_dentry", "no_heap", "noacl", "nobarrier", "noextent_cache", "noinline_data", "norecovery"}; #ifdef NDEVENV - utils::exec("modprobe f2fs"sv); + gucc::utils::exec("modprobe f2fs"sv); #endif } else if (file_sys == "xfs"sv) { config_data["FILESYSTEM"] = "mkfs.xfs -f"; diff --git a/src/main.cpp b/src/main.cpp index 813136c..3be86c8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -3,6 +3,9 @@ #include "tui.hpp" // for init #include "utils.hpp" // for exec, check_root, clear_sc... +// import gucc +#include "gucc/io_utils.hpp" + #include // for seconds #include // for regex_search, match_result... #include // for sleep_for @@ -13,10 +16,10 @@ #include // for set_default_logger, set_level int main() { - const auto& tty = utils::exec("tty"); + const auto& tty = gucc::utils::exec("tty"); const std::regex tty_regex("/dev/tty[0-9]*"); if (std::regex_search(tty, tty_regex)) { - utils::exec("setterm -blank 0 -powersave off"); + gucc::utils::exec("setterm -blank 0 -powersave off"); } // Check if installer has enough permissions. diff --git a/src/misc.cpp b/src/misc.cpp index 68921b2..0b22bbc 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -3,6 +3,9 @@ #include "utils.hpp" #include "widgets.hpp" +// import gucc +#include "gucc/io_utils.hpp" + /* clang-format off */ #include // for exists, is_directory #include // for Renderer, Button @@ -37,7 +40,7 @@ void edit_mkinitcpio(ScreenInteractive& screen) noexcept { const std::string& mountpoint = "/"; #endif - utils::exec(fmt::format(FMT_COMPILE("vim \"{}/etc/mkinitcpio.conf\""), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("vim \"{}/etc/mkinitcpio.conf\""), mountpoint), true); screen.Resume(); static constexpr auto content = "\nRun mkinitcpio?\n"sv; @@ -57,7 +60,7 @@ void edit_grub(ScreenInteractive& screen) noexcept { const std::string& mountpoint = "/"; #endif - utils::exec(fmt::format(FMT_COMPILE("vim \"{}/etc/default/grub\""), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("vim \"{}/etc/default/grub\""), mountpoint), true); screen.Resume(); static constexpr auto content = "\nUpdate GRUB?\n"sv; @@ -74,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 = utils::exec(fmt::format(FMT_COMPILE("mount | grep {}"), part_user), true); + const auto& ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("mount | grep {}"), 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)); @@ -142,7 +145,7 @@ void edit_configs() noexcept { bool is_custom = false, std::function&& cust_func = []() {}) { const auto& append_function = [&functions](const std::string& filename) { /* clang-format off */ - functions.emplace_back([filename]{ utils::exec(fmt::format(FMT_COMPILE("vim {}"), filename), true); }); + functions.emplace_back([filename]{ gucc::utils::exec(fmt::format(FMT_COMPILE("vim {}"), filename), true); }); /* clang-format on */ }; /* clang-format off */ @@ -215,12 +218,12 @@ void edit_configs() noexcept { } void edit_pacman_conf() noexcept { - utils::exec("vim /etc/pacman.conf"sv, true); + gucc::utils::exec("vim /etc/pacman.conf"sv, true); #ifdef NDEVENV // NOTE: don't care now, Will change in future.. detail::infobox_widget("\nUpdating database ...\n"sv); - utils::exec("pacman -Syy"sv, true); + gucc::utils::exec("pacman -Syy"sv, true); #endif } @@ -247,16 +250,16 @@ void logs_menu() noexcept { screen.Suspend(); switch (selected) { case 0: - utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} dmesg | fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \""), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} dmesg | fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \""), mountpoint), true); break; case 1: - utils::exec(fmt::format(FMT_COMPILE("fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \" < {}/var/log/pacman.log"), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \" < {}/var/log/pacman.log"), mountpoint), true); break; case 2: - utils::exec(fmt::format(FMT_COMPILE("fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \" < {}/var/log/Xorg.0.log"), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \" < {}/var/log/Xorg.0.log"), mountpoint), true); break; case 3: - utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} journalctl | fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \""), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} journalctl | fzf --reverse --header=\"Exit by pressing esc\" --prompt=\"Type to filter log entries > \""), mountpoint), true); break; default: screen.Resume(); diff --git a/src/simple_tui.cpp b/src/simple_tui.cpp index 3dd35a0..9fb240e 100644 --- a/src/simple_tui.cpp +++ b/src/simple_tui.cpp @@ -6,6 +6,7 @@ #include "widgets.hpp" // import gucc +#include "gucc/io_utils.hpp" #include "gucc/string_utils.hpp" /* clang-format off */ @@ -128,10 +129,10 @@ void make_esp(const std::string& part_name, std::string_view bootloader_name, bo config_data["UEFI_PART"] = partition; // If it is already a fat/vfat partition... - const auto& ret_status = utils::exec(fmt::format(FMT_COMPILE("fsck -N {} | grep fat &>/dev/null"), partition), true); + const auto& ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("fsck -N {} | grep fat &>/dev/null"), partition), true); if (ret_status != "0" && reformat_part) { #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("mkfs.vfat -F32 {} &>/dev/null"), partition)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mkfs.vfat -F32 {} &>/dev/null"), partition)); #endif spdlog::debug("Formating boot partition with fat/vfat!"); } @@ -140,8 +141,8 @@ void make_esp(const std::string& part_name, std::string_view bootloader_name, bo const auto& mountpoint_info = std::get(config_data["MOUNTPOINT"]); const auto& path_formatted = fmt::format(FMT_COMPILE("{}{}"), mountpoint_info, uefi_mount); - utils::exec(fmt::format(FMT_COMPILE("mkdir -p {}"), path_formatted)); - utils::exec(fmt::format(FMT_COMPILE("mount {} {}"), partition, path_formatted)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mkdir -p {}"), path_formatted)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount {} {}"), partition, path_formatted)); #endif } @@ -188,7 +189,7 @@ auto make_partitions_prepared(std::string_view bootloader, std::string_view root if (root_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"), part_mountpoint); - const auto& subvolumes_count = utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); + const auto& subvolumes_count = gucc::utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); const auto& lines_count = utils::to_int(subvolumes_count.data()); if (lines_count > 1) { // Pre-existing subvolumes and user wants to mount them @@ -212,7 +213,7 @@ auto make_partitions_prepared(std::string_view bootloader, std::string_view root // 2 = separate lvm boot. For Grub configuration if (part_mountpoint == "/boot"sv) { const auto& cmd = fmt::format(FMT_COMPILE("lsblk -lno TYPE {} | grep \"lvm\""), part_name); - const auto& cmd_out = utils::exec(cmd); + const auto& cmd_out = gucc::utils::exec(cmd); config_data["LVM_SEP_BOOT"] = 1; if (!cmd_out.empty()) { config_data["LVM_SEP_BOOT"] = 2; @@ -342,7 +343,7 @@ void menu_simple() noexcept { utils::umount_partitions(); // We need to remount the zfs filesystems that have defined mountpoints already - utils::exec("zfs mount -aO &>/dev/null"); + gucc::utils::exec("zfs mount -aO &>/dev/null"); // Get list of available partitions utils::find_partitions(); @@ -388,7 +389,7 @@ void menu_simple() noexcept { /*if (utils::get_mountpoint_fs(mountpoint) == "btrfs") { // Check if there are subvolumes already on the btrfs partition const auto& subvolumes = fmt::format(FMT_COMPILE("btrfs subvolume list \"{}\" 2>/dev/null"), mountpoint); - const auto& subvolumes_count = utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); + const auto& subvolumes_count = gucc::utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); const auto& lines_count = utils::to_int(subvolumes_count.data()); if (lines_count > 1) { // Pre-existing subvolumes and user wants to mount them @@ -473,7 +474,7 @@ void menu_simple() noexcept { // so that output will be synchronized. auto logger = spdlog::get("cachyos_logger"); logger->flush(); - utils::exec(fmt::format(FMT_COMPILE("{} &>>/tmp/cachyos-install.log"), post_install), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("{} &>>/tmp/cachyos-install.log"), post_install), true); } tui::exit_done(); diff --git a/src/tui.cpp b/src/tui.cpp index 850b5fe..c784e78 100644 --- a/src/tui.cpp +++ b/src/tui.cpp @@ -10,6 +10,7 @@ #include "widgets.hpp" // import gucc +#include "gucc/io_utils.hpp" #include "gucc/string_utils.hpp" #include @@ -175,7 +176,7 @@ void set_hostname() noexcept { // Set system language void set_locale() noexcept { - const auto& locales = gucc::utils::make_multiline(utils::exec("cat /etc/locale.gen | grep -v \"# \" | sed 's/#//g' | awk '/UTF-8/ {print $1}'")); + const auto& locales = gucc::utils::make_multiline(gucc::utils::exec("cat /etc/locale.gen | grep -v \"# \" | sed 's/#//g' | awk '/UTF-8/ {print $1}'")); // System language std::string locale{}; @@ -209,7 +210,7 @@ void set_xkbmap() noexcept { std::string xkbmap_choice{}; auto ok_callback = [&] { const auto& keymap = xkbmap_list[static_cast(selected)]; - xkbmap_choice = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed 's/_.*//'"), keymap)); + xkbmap_choice = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed 's/_.*//'"), keymap)); success = true; screen.ExitLoopClosure()(); }; @@ -238,7 +239,7 @@ void select_keymap() noexcept { if (!keep_default) { return; } /* clang-format on */ - const auto& keymaps = gucc::utils::make_multiline(utils::exec(R"(ls -R /usr/share/kbd/keymaps | grep "map.gz" | sed 's/\.map\.gz//g' | sort)")); + const auto& keymaps = gucc::utils::make_multiline(gucc::utils::exec(R"(ls -R /usr/share/kbd/keymaps | grep "map.gz" | sed 's/\.map\.gz//g' | sort)")); auto screen = ScreenInteractive::Fullscreen(); std::int32_t selected{226}; @@ -257,7 +258,7 @@ bool set_timezone() noexcept { std::string zone{}; { auto screen = ScreenInteractive::Fullscreen(); - const auto& cmd = utils::exec(R"(cat /usr/share/zoneinfo/zone.tab | awk '{print $3}' | grep "/" | sed "s/\/.*//g" | sort -ud)"); + const auto& cmd = gucc::utils::exec(R"(cat /usr/share/zoneinfo/zone.tab | awk '{print $3}' | grep "/" | sed "s/\/.*//g" | sort -ud)"); const auto& zone_list = gucc::utils::make_multiline(cmd); std::int32_t selected{}; @@ -277,7 +278,7 @@ bool set_timezone() noexcept { std::string subzone{}; { auto screen = ScreenInteractive::Fullscreen(); - const auto& cmd = utils::exec(fmt::format(FMT_COMPILE("cat /usr/share/zoneinfo/zone.tab | {1} | grep \"{0}/\" | sed \"s/{0}\\///g\" | sort -ud"), zone, "awk '{print $3}'")); + const auto& cmd = gucc::utils::exec(fmt::format(FMT_COMPILE("cat /usr/share/zoneinfo/zone.tab | {1} | grep \"{0}/\" | sed \"s/{0}\\///g\" | sort -ud"), zone, "awk '{print $3}'")); const auto& city_list = gucc::utils::make_multiline(cmd); std::int32_t selected{}; @@ -465,9 +466,9 @@ void chroot_interactive() noexcept { const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); const auto& cmd_formatted = fmt::format(FMT_COMPILE("arch-chroot {} bash"), mountpoint); - utils::exec(cmd_formatted, true); + gucc::utils::exec(cmd_formatted, true); #else - utils::exec("bash", true); + gucc::utils::exec("bash", true); #endif } @@ -479,7 +480,7 @@ void install_grub_uefi() noexcept { /* clang-format on */ std::string bootid{"cachyos"}; - auto ret_status = utils::exec("efibootmgr | cut -d\\ -f2 | grep -q -o cachyos", true); + auto ret_status = gucc::utils::exec("efibootmgr | cut -d\\ -f2 | grep -q -o cachyos", true); if (ret_status == "0"sv) { static constexpr auto bootid_content = "\nInput the name identify your grub installation. Choosing an existing name overwrites it.\n"sv; if (!detail::inputbox_widget(bootid, bootid_content, size(ftxui::HEIGHT, ftxui::LESS_THAN, 9) | size(ftxui::WIDTH, ftxui::LESS_THAN, 30))) { @@ -544,7 +545,7 @@ void uefi_bootloader() noexcept { static constexpr auto efi_path = "/sys/firmware/efi/"sv; if (fs::exists(efi_path) && fs::is_directory(efi_path)) { // Mount efivarfs if it is not already mounted - const auto& mount_out = utils::exec("mount | grep /sys/firmware/efi/efivars"); + const auto& mount_out = gucc::utils::exec("mount | grep /sys/firmware/efi/efivars"); if (mount_out.empty() && (mount("efivarfs", "/sys/firmware/efi/efivars", "efivarfs", 0, "") != 0)) { perror("utils::uefi_bootloader"); exit(1); @@ -608,16 +609,16 @@ void install_base() noexcept { std::string packages{}; auto ok_callback = [&] { packages = detail::from_checklist_string(available_kernels, kernels_state.get()); - auto ret_status = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | grep \"linux\""), packages), true); + auto ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | grep \"linux\""), packages), true); if (ret_status != "0") { // Check if a kernel is already installed - ret_status = utils::exec(fmt::format(FMT_COMPILE("ls {}/boot/*.img >/dev/null 2>&1"), mountpoint), true); + ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("ls {}/boot/*.img >/dev/null 2>&1"), mountpoint), true); if (ret_status != "0") { static constexpr auto ErrNoKernel = "\nAt least one kernel must be selected.\n"sv; detail::msgbox_widget(ErrNoKernel); return; } - const auto& cmd = utils::exec(fmt::format(FMT_COMPILE("ls {}/boot/*.img | cut -d'-' -f2 | grep -v ucode.img | sort -u"), mountpoint)); + const auto& cmd = gucc::utils::exec(fmt::format(FMT_COMPILE("ls {}/boot/*.img | cut -d'-' -f2 | grep -v ucode.img | sort -u"), mountpoint)); detail::msgbox_widget(fmt::format(FMT_COMPILE("\nlinux-{} detected\n"), cmd)); screen.ExitLoopClosure()(); } @@ -766,14 +767,14 @@ void bios_bootloader() { void enable_autologin() { // Detect display manager - const auto& dm = utils::exec("file /mnt/etc/systemd/system/display-manager.service 2>/dev/null | awk -F'/' '{print $NF}' | cut -d. -f1"); + const auto& dm = gucc::utils::exec("file /mnt/etc/systemd/system/display-manager.service 2>/dev/null | awk -F'/' '{print $NF}' | cut -d. -f1"); const auto& content = fmt::format(FMT_COMPILE("\nThis option enables autologin using {}.\n\nProceed?\n"), dm); /* clang-format off */ if (!detail::yesno_widget(content, size(HEIGHT, LESS_THAN, 15) | size(WIDTH, LESS_THAN, 75))) { return; } - if (utils::exec("echo /mnt/home/* | xargs -n1 | wc -l") != "1") { return; } + if (gucc::utils::exec("echo /mnt/home/* | xargs -n1 | wc -l") != "1") { return; } /* clang-format on */ - const auto& autologin_user = utils::exec("echo /mnt/home/* | cut -d/ -f4"); + const auto& autologin_user = gucc::utils::exec("echo /mnt/home/* | cut -d/ -f4"); utils::enable_autologin(dm, autologin_user); } @@ -859,13 +860,13 @@ void auto_partition() noexcept { utils::auto_partition(); // Show created partitions - const auto& disk_list = utils::exec(fmt::format(FMT_COMPILE("lsblk {} -o NAME,TYPE,FSTYPE,SIZE"), device_info)); + const auto& disk_list = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk {} -o NAME,TYPE,FSTYPE,SIZE"), device_info)); detail::msgbox_widget(disk_list, size(HEIGHT, GREATER_THAN, 5)); } // Simple code to show devices / partitions. void show_devices() noexcept { - const auto& lsblk = utils::exec(R"(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE,MOUNTPOINT | grep "disk\|part\|lvm\|crypt\|NAME\|MODEL\|TYPE\|FSTYPE\|SIZE\|MOUNTPOINT")"); + const auto& lsblk = gucc::utils::exec(R"(lsblk -o NAME,MODEL,TYPE,FSTYPE,SIZE,MOUNTPOINT | grep "disk\|part\|lvm\|crypt\|NAME\|MODEL\|TYPE\|FSTYPE\|SIZE\|MOUNTPOINT")"); detail::msgbox_widget(lsblk, size(HEIGHT, GREATER_THAN, 5)); } @@ -883,7 +884,7 @@ void refresh_pacman_keys() noexcept { bool select_device() noexcept { auto* config_instance = Config::instance(); auto& config_data = config_instance->data(); - auto devices = utils::exec(R"(lsblk -lno NAME,SIZE,TYPE | grep 'disk' | awk '{print "/dev/" $1 " " $2}' | sort -u)"); + auto devices = gucc::utils::exec(R"(lsblk -lno NAME,SIZE,TYPE | grep 'disk' | awk '{print "/dev/" $1 " " $2}' | sort -u)"); const auto& devices_list = gucc::utils::make_multiline(devices); auto screen = ScreenInteractive::Fullscreen(); @@ -942,7 +943,7 @@ bool select_filesystem() noexcept { const auto& do_mount = detail::yesno_widget(content, size(HEIGHT, LESS_THAN, 15) | size(WIDTH, LESS_THAN, 75)); if (do_mount) { #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("{} {}"), file_sys, partition)); + gucc::utils::exec(fmt::format(FMT_COMPILE("{} {}"), file_sys, partition)); #endif spdlog::info("mount.{} {}", partition, file_sys); } @@ -959,10 +960,10 @@ void mount_opts(bool force) noexcept { const auto& file_sys = std::get(config_data["FILESYSTEM"]); const auto& fs_opts = std::get>(config_data["fs_opts"]); const auto& partition = std::get(config_data["PARTITION"]); - const auto& format_name = utils::exec(fmt::format(FMT_COMPILE("echo {} | rev | cut -d/ -f1 | rev"), partition)); - const auto& format_device = utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {}"), format_name, "awk '/disk/ {print $1}'")); + const auto& format_name = gucc::utils::exec(fmt::format(FMT_COMPILE("echo {} | rev | cut -d/ -f1 | rev"), partition)); + 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}'")); - const auto& rotational_queue = (utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/queue/rotational"), format_device)) == "1"sv); + const auto& rotational_queue = (gucc::utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/queue/rotational"), format_device)) == "1"sv); std::unique_ptr fs_opts_state{new bool[fs_opts.size()]{false}}; for (size_t i = 0; i < fs_opts.size(); ++i) { @@ -988,8 +989,8 @@ void mount_opts(bool force) noexcept { // Now clean up the file auto cleaup_mount_opts = [](auto& opts_info) { - opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed 's/ /,/g'"), opts_info)); - opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed '$s/,$//'"), opts_info)); + opts_info = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed 's/ /,/g'"), opts_info)); + opts_info = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed '$s/,$//'"), opts_info)); }; if (force) { @@ -1004,7 +1005,7 @@ void mount_opts(bool force) noexcept { screen.ExitLoopClosure()(); }; - const auto& file_sys_formatted = utils::exec(fmt::format(FMT_COMPILE("echo {} | sed \"s/.*\\.//g;s/-.*//g\""), file_sys)); + const auto& file_sys_formatted = gucc::utils::exec(fmt::format(FMT_COMPILE("echo {} | sed \"s/.*\\.//g;s/-.*//g\""), file_sys)); const auto& fs_title = fmt::format(FMT_COMPILE("New CLI Installer | {}"), file_sys_formatted); auto content_size = size(HEIGHT, GREATER_THAN, 10) | size(WIDTH, GREATER_THAN, 40) | vscroll_indicator | yframe | flex; @@ -1052,11 +1053,11 @@ bool mount_current_partition(bool force) noexcept { const auto& mount_opts_info = std::get(config_data["MOUNT_OPTS"]); if (!mount_opts_info.empty()) { // check_for_error "mount ${PARTITION} $(cat ${MOUNT_OPTS})" - const auto& mount_status = utils::exec(fmt::format(FMT_COMPILE("mount -o {} {} {}{}"), mount_opts_info, partition, mountpoint, mount_dev)); + 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 = utils::exec(fmt::format(FMT_COMPILE("mount {} {}{}"), partition, mountpoint, mount_dev)); + const auto& mount_status = gucc::utils::exec(fmt::format(FMT_COMPILE("mount {} {}{}"), partition, mountpoint, mount_dev)); spdlog::info("{}", mount_status); } #endif @@ -1066,15 +1067,15 @@ bool mount_current_partition(bool force) noexcept { /* clang-format on */ // Identify if mounted partition is type "crypt" (LUKS on LVM, or LUKS alone) - if (!utils::exec(fmt::format(FMT_COMPILE("lsblk -lno TYPE {} | grep \"crypt\""), partition)).empty()) { + 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(config_data["LUKS_NAME"]); const auto& luks_dev = std::get(config_data["LUKS_DEV"]); - luks_name = utils::exec(fmt::format(FMT_COMPILE("echo {} | sed \"s~^/dev/mapper/~~g\""), partition)); + 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 (!utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME {} | grep \"{}\""), cryptpart, luks_name)).empty()) { + if (!gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME {} | grep \"{}\""), cryptpart, luks_name)).empty()) { functor(cryptpart); return true; } @@ -1083,7 +1084,7 @@ bool mount_current_partition(bool force) noexcept { }; // Check if LUKS on LVM (parent = lvm /dev/mapper/...) - auto cryptparts = gucc::utils::make_multiline(utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep "lvm" | grep -i "crypto_luks" | uniq | awk '{print "/dev/mapper/"$1}')")); + 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; @@ -1093,16 +1094,16 @@ bool mount_current_partition(bool force) noexcept { } // Check if LVM on LUKS - cryptparts = gucc::utils::make_multiline(utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep " crypt$" | grep -i "LVM2_member" | uniq | awk '{print "/dev/mapper/"$1}')")); + 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(utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep "part" | grep -i "crypto_luks" | uniq | awk '{print "/dev/"$1}')")); + 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_uuid = std::get(config_data["LUKS_UUID"]); - luks_uuid = utils::exec(fmt::format(FMT_COMPILE("lsblk -lno UUID,TYPE,FSTYPE {} | grep \"part\" | grep -i \"crypto_luks\" | {}"), cryptpart, "awk '{print $1}'")); + 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)) { @@ -1186,13 +1187,13 @@ void make_swap() noexcept { /* clang-format on */ if (partition == sel_swap_file) { - const auto& total_memory = utils::exec("grep MemTotal /proc/meminfo | awk '{print $2/1024}' | sed 's/\\..*//'"); + const auto& total_memory = gucc::utils::exec("grep MemTotal /proc/meminfo | awk '{print $2/1024}' | sed 's/\\..*//'"); std::string value{fmt::format(FMT_COMPILE("{}M"), total_memory)}; if (!detail::inputbox_widget(value, "\nM = MB, G = GB\n", size(ftxui::HEIGHT, ftxui::LESS_THAN, 9) | size(ftxui::WIDTH, ftxui::LESS_THAN, 30))) { return; } - while (utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | grep \"M\\|G\""), value)).empty()) { + while (gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | grep \"M\\|G\""), value)).empty()) { detail::msgbox_widget(fmt::format(FMT_COMPILE("\n{} Error: M = MB, G = GB\n"), sel_swap_file)); value = fmt::format(FMT_COMPILE("{}M"), total_memory); if (!detail::inputbox_widget(value, "\nM = MB, G = GB\n", size(ftxui::HEIGHT, ftxui::LESS_THAN, 9) | size(ftxui::WIDTH, ftxui::LESS_THAN, 30))) { @@ -1202,10 +1203,10 @@ void make_swap() noexcept { #ifdef NDEVENV const auto& swapfile_path = fmt::format(FMT_COMPILE("{}/swapfile"), mountpoint_info); - utils::exec(fmt::format(FMT_COMPILE("fallocate -l {} {} 2>>/tmp/cachyos-install.log &>/dev/null"), value, swapfile_path)); - utils::exec(fmt::format(FMT_COMPILE("chmod 600 {} 2>>/tmp/cachyos-install.log"), swapfile_path)); - utils::exec(fmt::format(FMT_COMPILE("mkswap {} 2>>/tmp/cachyos-install.log &>/dev/null"), swapfile_path)); - utils::exec(fmt::format(FMT_COMPILE("swapon {} 2>>/tmp/cachyos-install.log &>/dev/null"), swapfile_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("fallocate -l {} {} 2>>/tmp/cachyos-install.log &>/dev/null"), value, swapfile_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("chmod 600 {} 2>>/tmp/cachyos-install.log"), swapfile_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mkswap {} 2>>/tmp/cachyos-install.log &>/dev/null"), swapfile_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("swapon {} 2>>/tmp/cachyos-install.log &>/dev/null"), swapfile_path)); #endif return; } @@ -1214,7 +1215,7 @@ void make_swap() noexcept { auto& number_partitions = std::get(config_data["NUMBER_PARTITIONS"]); // Warn user if creating a new swap - const auto& swap_part = utils::exec(fmt::format(FMT_COMPILE("lsblk -o FSTYPE \"{}\" | grep -i \"swap\""), partition)); + const auto& swap_part = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -o FSTYPE \"{}\" | grep -i \"swap\""), partition)); if (swap_part != "swap") { const auto& do_swap = detail::yesno_widget(fmt::format(FMT_COMPILE("\nmkswap {}\n"), partition), size(HEIGHT, LESS_THAN, 15) | size(WIDTH, LESS_THAN, 75)); /* clang-format off */ @@ -1222,14 +1223,14 @@ void make_swap() noexcept { /* clang-format on */ #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("mkswap {} &>/dev/null"), partition)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mkswap {} &>/dev/null"), partition)); #endif spdlog::info("mkswap.{}", partition); } #ifdef NDEVENV // Whether existing to newly created, activate swap - utils::exec(fmt::format(FMT_COMPILE("swapon {} &>/dev/null"), partition)); + gucc::utils::exec(fmt::format(FMT_COMPILE("swapon {} &>/dev/null"), partition)); #endif // Since a partition was used, remove that partition from the list @@ -1276,7 +1277,7 @@ void lvm_del_vg() noexcept { #ifdef NDEVENV // if confirmation given, delete - utils::exec(fmt::format(FMT_COMPILE("vgremove -f {} 2>/dev/null"), sel_vg), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("vgremove -f {} 2>/dev/null"), sel_vg), true); #endif } @@ -1397,7 +1398,7 @@ bool zfs_create_zpool(bool do_create_zpool = true) noexcept { } bool zfs_import_pool() noexcept { - const auto& zlist = gucc::utils::make_multiline(utils::exec("zpool import 2>/dev/null | grep \"^[[:space:]]*pool\" | awk -F : '{print $2}' | awk '{$1=$1};1'")); + const auto& zlist = gucc::utils::make_multiline(gucc::utils::exec("zpool import 2>/dev/null | grep \"^[[:space:]]*pool\" | awk -F : '{print $2}' | awk '{$1=$1};1'")); if (zlist.empty()) { // no available datasets detail::infobox_widget("\nNo pools available\"\n"sv); @@ -1428,7 +1429,7 @@ bool zfs_import_pool() noexcept { #ifdef NDEVENV const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); - utils::exec(fmt::format(FMT_COMPILE("zpool import -R {} {} 2>>/tmp/cachyos-install.log"), mountpoint, zfs_zpool_name), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zpool import -R {} {} 2>>/tmp/cachyos-install.log"), mountpoint, zfs_zpool_name), true); #endif config_data["ZFS"] = 1; @@ -1691,7 +1692,7 @@ void zfs_menu_manual() noexcept { void zfs_menu() noexcept { #ifdef NDEVENV // check for zfs support - if (utils::exec("modprobe zfs 2>>/tmp/cachyos-install.log &>/dev/null", true) != "0"sv) { + if (gucc::utils::exec("modprobe zfs 2>>/tmp/cachyos-install.log &>/dev/null", true) != "0"sv) { detail::infobox_widget("\nThe kernel modules to support ZFS could not be found\n"sv); std::this_thread::sleep_for(std::chrono::seconds(3)); return; @@ -1763,7 +1764,7 @@ void make_esp() noexcept { config_data["UEFI_PART"] = partition; // If it is already a fat/vfat partition... - const auto& ret_status = utils::exec(fmt::format(FMT_COMPILE("fsck -N {} | grep fat"), partition), true); + const auto& ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("fsck -N {} | grep fat"), partition), true); bool do_boot_partition{}; if (ret_status != "0") { const auto& content = fmt::format(FMT_COMPILE("\nThe UEFI partition {} has already been formatted.\n \nReformat? Doing so will erase ALL data already on that partition.\n"), partition); @@ -1771,7 +1772,7 @@ void make_esp() noexcept { } if (do_boot_partition) { #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("mkfs.vfat -F32 {} &>/dev/null"), partition)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mkfs.vfat -F32 {} &>/dev/null"), partition)); #endif spdlog::debug("Formating boot partition with fat/vfat!"); } @@ -1804,8 +1805,8 @@ void make_esp() noexcept { uefi_mount = answer; const auto& path_formatted = fmt::format(FMT_COMPILE("{}{}"), mountpoint_info, uefi_mount); #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("mkdir -p {}"), path_formatted)); - utils::exec(fmt::format(FMT_COMPILE("mount {} {}"), partition, path_formatted)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mkdir -p {}"), path_formatted)); + gucc::utils::exec(fmt::format(FMT_COMPILE("mount {} {}"), partition, path_formatted)); #endif confirm_mount(path_formatted); } @@ -1825,7 +1826,7 @@ void mount_partitions() noexcept { utils::umount_partitions(); // We need to remount the zfs filesystems that have defined mountpoints already - utils::exec("zfs mount -aO &>/dev/null"); + gucc::utils::exec("zfs mount -aO &>/dev/null"); // Get list of available partitions utils::find_partitions(); @@ -1896,10 +1897,10 @@ void mount_partitions() noexcept { if (utils::get_mountpoint_fs(mountpoint_info) == "btrfs") { // 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 = utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); + const auto& subvolumes_count = gucc::utils::exec(fmt::format(FMT_COMPILE("{} | wc -l"), subvolumes)); const auto& lines_count = utils::to_int(subvolumes_count); if (lines_count > 1) { - const auto& subvolumes_formated = utils::exec(fmt::format(FMT_COMPILE("{} | cut -d\" \" -f9"), subvolumes)); + const auto& subvolumes_formated = gucc::utils::exec(fmt::format(FMT_COMPILE("{} | cut -d\" \" -f9"), subvolumes)); 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 */ @@ -2008,7 +2009,7 @@ void mount_partitions() noexcept { // 2 = separate lvm boot. For Grub configuration if (mount_dev == "/boot") { const auto& cmd = fmt::format(FMT_COMPILE("lsblk -lno TYPE {} | grep \"lvm\""), partition); - const auto& cmd_out = utils::exec(cmd); + const auto& cmd_out = gucc::utils::exec(cmd); config_data["LVM_SEP_BOOT"] = 1; if (!cmd_out.empty()) { config_data["LVM_SEP_BOOT"] = 2; @@ -2035,7 +2036,7 @@ void configure_mirrorlist() noexcept { break; case 1: screen.Suspend(); - utils::exec("cachyos-rate-mirrors"sv, true); + gucc::utils::exec("cachyos-rate-mirrors"sv, true); screen.Resume(); break; default: @@ -2072,7 +2073,7 @@ void create_partitions() noexcept { if (selected_entry != optwipe && selected_entry != optauto) { screen.Suspend(); #ifdef NDEVENV - utils::exec(fmt::format(FMT_COMPILE("{} {}"), selected_entry, std::get(config_data["DEVICE"])), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("{} {}"), selected_entry, std::get(config_data["DEVICE"])), true); #else spdlog::debug("to be executed: {}", fmt::format(FMT_COMPILE("{} {}"), selected_entry, std::get(config_data["DEVICE"]))); #endif diff --git a/src/utils.cpp b/src/utils.cpp index 6e88eb8..41a0361 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -9,6 +9,7 @@ #include "gucc/cpu.hpp" #include "gucc/file_utils.hpp" #include "gucc/initcpio.hpp" +#include "gucc/io_utils.hpp" #include "gucc/pacmanconf_repo.hpp" #include "gucc/string_utils.hpp" @@ -26,9 +27,7 @@ #include // for mutex #include // for operator==, string, basic_string, allocator #include // for mount -#include // for waitpid #include // for sleep_for -#include // for execvp, fork #include // for unordered_map #include @@ -107,14 +106,9 @@ bool is_connected() noexcept { #endif } -std::string safe_getenv(const char* env_name) noexcept { - const char* const raw_val = getenv(env_name); - return raw_val != nullptr ? std::string(raw_val) : std::string{}; -} - bool check_root() noexcept { #ifdef NDEVENV - return (utils::exec("whoami") == "root"); + return (gucc::utils::exec("whoami") == "root"); #else return true; #endif @@ -136,13 +130,13 @@ void arch_chroot(const std::string_view& command, bool follow) noexcept { if (follow) { const auto& headless_mode = std::get(config_data["HEADLESS_MODE"]); if (headless_mode) { - utils::exec(cmd_formatted, true); + gucc::utils::exec(cmd_formatted, true); } else { tui::detail::follow_process_log_widget({"/bin/sh", "-c", cmd_formatted}); } return; } - utils::exec(cmd_formatted); + gucc::utils::exec(cmd_formatted); #else spdlog::info("Running with arch-chroot(follow='{}'): '{}'", follow, cmd_formatted); #endif @@ -154,8 +148,8 @@ void exec_follow(const std::vector& vec, std::string& process_log, return; } - const bool log_exec_cmds = safe_getenv("LOG_EXEC_CMDS") == "1"; - const bool dirty_cmd_run = safe_getenv("DIRTY_CMD_RUN") == "1"; + const bool log_exec_cmds = gucc::utils::safe_getenv("LOG_EXEC_CMDS") == "1"; + const bool dirty_cmd_run = gucc::utils::safe_getenv("DIRTY_CMD_RUN") == "1"; if (log_exec_cmds && spdlog::default_logger_raw() != nullptr) { spdlog::debug("[exec_follow] cmd := {}", vec); @@ -202,72 +196,6 @@ void exec_follow(const std::vector& vec, std::string& process_log, running = false; } -void exec(const std::vector& vec) noexcept { - const bool log_exec_cmds = safe_getenv("LOG_EXEC_CMDS") == "1"; - const bool dirty_cmd_run = safe_getenv("DIRTY_CMD_RUN") == "1"; - - if (log_exec_cmds && spdlog::default_logger_raw() != nullptr) { - spdlog::debug("[exec] cmd := {}", vec); - } - if (dirty_cmd_run) { - return; - } - - std::int32_t status{}; - auto pid = fork(); - if (pid == 0) { - std::vector args; - std::transform(vec.cbegin(), vec.cend(), std::back_inserter(args), - [=](const std::string& arg) -> char* { return const_cast(arg.data()); }); - args.push_back(nullptr); - - char** command = args.data(); - execvp(command[0], command); - } else { - do { - waitpid(pid, &status, 0); - } while ((!WIFEXITED(status)) && (!WIFSIGNALED(status))); - } -} - -// https://github.com/sheredom/subprocess.h -// https://gist.github.com/konstantint/d49ab683b978b3d74172 -// https://github.com/arun11299/cpp-subprocess/blob/master/subprocess.hpp#L1218 -// https://stackoverflow.com/questions/11342868/c-interface-for-interactive-bash -// https://github.com/hniksic/rust-subprocess -std::string exec(const std::string_view& command, const bool& interactive) noexcept { - const bool log_exec_cmds = safe_getenv("LOG_EXEC_CMDS") == "1"; - - if (log_exec_cmds && spdlog::default_logger_raw() != nullptr) { - spdlog::debug("[exec] cmd := '{}'", command); - } - - if (interactive) { - const auto& ret_code = system(command.data()); - return std::to_string(ret_code); - } - - const std::unique_ptr pipe(popen(command.data(), "r"), pclose); - if (!pipe) { - spdlog::error("popen failed! '{}'", command); - return "-1"; - } - - std::string result{}; - std::array buffer{}; - while (!feof(pipe.get())) { - if (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) { - result += buffer.data(); - } - } - - if (result.ends_with('\n')) { - result.pop_back(); - } - - return result; -} - void dump_to_log(const std::string& data) noexcept { spdlog::info("[DUMP_TO_LOG] :=\n{}", data); } @@ -301,7 +229,7 @@ bool prompt_char(const char* prompt, const char* color, char* read) noexcept { // install a pkg in the live session if not installed void inst_needed(const std::string_view& pkg) noexcept { - if (utils::exec(fmt::format(FMT_COMPILE("pacman -Qq {} &>/dev/null"), pkg), true) != "0") { + if (gucc::utils::exec(fmt::format(FMT_COMPILE("pacman -Qq {} &>/dev/null"), pkg), true) != "0") { std::this_thread::sleep_for(std::chrono::seconds(1)); utils::clear_screen(); @@ -312,11 +240,11 @@ void inst_needed(const std::string_view& pkg) noexcept { auto& config_data = config_instance->data(); const auto& headless_mode = std::get(config_data["HEADLESS_MODE"]); if (headless_mode) { - utils::exec(cmd_formatted, true); + gucc::utils::exec(cmd_formatted, true); } else { tui::detail::follow_process_log_widget({"/bin/sh", "-c", cmd_formatted}); } - // utils::exec(fmt::format(FMT_COMPILE("pacman -Sy --noconfirm {}"), pkg)); + // gucc::utils::exec(fmt::format(FMT_COMPILE("pacman -Sy --noconfirm {}"), pkg)); #else spdlog::info("Installing needed: '{}'", cmd_formatted); #endif @@ -329,9 +257,9 @@ void umount_partitions() noexcept { auto& config_data = config_instance->data(); const auto& mountpoint_info = std::get(config_data["MOUNTPOINT"]); - auto mount_info = utils::exec(fmt::format(FMT_COMPILE("mount | grep \"{}\" | {}"), mountpoint_info, "awk '{print $3}' | sort -r")); + auto mount_info = gucc::utils::exec(fmt::format(FMT_COMPILE("mount | grep \"{}\" | {}"), mountpoint_info, "awk '{print $3}' | sort -r")); #ifdef NDEVENV - utils::exec("swapoff -a"); + gucc::utils::exec("swapoff -a"); #endif const auto& lines = gucc::utils::make_multiline(mount_info); @@ -354,34 +282,34 @@ void auto_partition() noexcept { #ifdef NDEVENV // Find existing partitions (if any) to remove - const auto& parts = utils::exec(fmt::format(FMT_COMPILE("parted -s {} print | {}"), device_info, "awk '/^ / {print $1}'")); + const auto& parts = gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} print | {}"), device_info, "awk '/^ / {print $1}'")); const auto& del_parts = gucc::utils::make_multiline(parts); for (const auto& del_part : del_parts) { - utils::exec(fmt::format(FMT_COMPILE("parted -s {} rm {} 2>>/tmp/cachyos-install.log &>/dev/null"), device_info, del_part)); + gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} rm {} 2>>/tmp/cachyos-install.log &>/dev/null"), device_info, del_part)); } // Clear disk - utils::exec(fmt::format(FMT_COMPILE("dd if=/dev/zero of=\"{}\" bs=512 count=1 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); - utils::exec(fmt::format(FMT_COMPILE("wipefs -af \"{}\" 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); - utils::exec(fmt::format(FMT_COMPILE("sgdisk -Zo \"{}\" 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("dd if=/dev/zero of=\"{}\" bs=512 count=1 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("wipefs -af \"{}\" 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sgdisk -Zo \"{}\" 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); // Identify the partition table - const auto& part_table = utils::exec(fmt::format(FMT_COMPILE("parted -s {} print 2>/dev/null | grep -i 'partition table' | {}"), device_info, "awk '{print $3}'")); + const auto& part_table = gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} print 2>/dev/null | grep -i 'partition table' | {}"), device_info, "awk '{print $3}'")); // Create partition table if one does not already exist if ((system_info == "BIOS") && (part_table != "msdos")) - utils::exec(fmt::format(FMT_COMPILE("parted -s {} mklabel msdos 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} mklabel msdos 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); if ((system_info == "UEFI") && (part_table != "gpt")) - utils::exec(fmt::format(FMT_COMPILE("parted -s {} mklabel gpt 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} mklabel gpt 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); // Create partitions (same basic partitioning scheme for BIOS and UEFI) if (system_info == "BIOS") - utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart primary ext3 1MiB 513MiB 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart primary ext3 1MiB 513MiB 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); else - utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart ESP fat32 1MiB 513MiB 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart ESP fat32 1MiB 513MiB 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); - utils::exec(fmt::format(FMT_COMPILE("parted -s {} set 1 boot on 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); - utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart primary ext3 513MiB 100% 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} set 1 boot on 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart primary ext3 513MiB 100% 2>>/tmp/cachyos-install.log &>/dev/null"), device_info)); #else spdlog::info("lsblk {} -o NAME,TYPE,FSTYPE,SIZE", device_info); #endif @@ -399,11 +327,11 @@ void secure_wipe() noexcept { const auto& headless_mode = std::get(config_data["HEADLESS_MODE"]); const auto& cmd_formatted = fmt::format(FMT_COMPILE("wipe -Ifre {}"), device_info); if (headless_mode) { - utils::exec(cmd_formatted, true); + gucc::utils::exec(cmd_formatted, true); } else { tui::detail::follow_process_log_widget({"/bin/sh", "-c", cmd_formatted}); } - // utils::exec(fmt::format(FMT_COMPILE("wipe -Ifre {}"), device_info)); + // gucc::utils::exec(fmt::format(FMT_COMPILE("wipe -Ifre {}"), device_info)); #else spdlog::debug("{}\n", device_info); #endif @@ -416,7 +344,7 @@ void generate_fstab(const std::string_view& fstab_cmd) noexcept { auto* config_instance = Config::instance(); auto& config_data = config_instance->data(); const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); - utils::exec(fmt::format(FMT_COMPILE("{0} {1} > {1}/etc/fstab"), fstab_cmd, mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("{0} {1} > {1}/etc/fstab"), fstab_cmd, mountpoint)); spdlog::info("Created fstab file:"); const auto& fstab_content = gucc::file_utils::read_whole_file(fmt::format(FMT_COMPILE("{}/etc/fstab"), mountpoint)); @@ -425,17 +353,17 @@ void generate_fstab(const std::string_view& fstab_cmd) noexcept { const auto& swap_file = fmt::format(FMT_COMPILE("{}/swapfile"), mountpoint); if (fs::exists(swap_file) && fs::is_regular_file(swap_file)) { spdlog::info("appending swapfile to the fstab.."); - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/\\\\{0}//\" {0}/etc/fstab"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/\\\\{0}//\" {0}/etc/fstab"), mountpoint)); } // Edit fstab in case of btrfs subvolumes - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/subvolid=.*,subvol=\\/.*,//g\" {}/etc/fstab"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/subvolid=.*,subvol=\\/.*,//g\" {}/etc/fstab"), mountpoint)); // remove any zfs datasets that are mounted by zfs - const auto& msource_list = gucc::utils::make_multiline(utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab | grep \"^[a-z,A-Z]\" | {}"), mountpoint, "awk '{print $1}'"))); + const auto& msource_list = gucc::utils::make_multiline(gucc::utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab | grep \"^[a-z,A-Z]\" | {}"), mountpoint, "awk '{print $1}'"))); for (const auto& msource : msource_list) { - if (utils::exec(fmt::format(FMT_COMPILE("zfs list -H -o mountpoint,name | grep \"^/\" | {} | grep \"^{}$\""), "awk '{print $2}'", msource), true) == "0") - utils::exec(fmt::format(FMT_COMPILE("sed -e \"\\|^{}[[:space:]]| s/^#*/#/\" -i {}/etc/fstab"), msource, mountpoint)); + if (gucc::utils::exec(fmt::format(FMT_COMPILE("zfs list -H -o mountpoint,name | grep \"^/\" | {} | grep \"^{}$\""), "awk '{print $2}'", msource), true) == "0") + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e \"\\|^{}[[:space:]]| s/^#*/#/\" -i {}/etc/fstab"), msource, mountpoint)); } #endif } @@ -447,9 +375,9 @@ void set_hostname(const std::string_view& hostname) noexcept { auto* config_instance = Config::instance(); auto& config_data = config_instance->data(); const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); - utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" > {}/etc/hostname"), hostname, mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" > {}/etc/hostname"), hostname, mountpoint)); const auto& cmd = fmt::format(FMT_COMPILE("echo -e \"#\\t\\t\\n127.0.0.1\\tlocalhost.localdomain\\tlocalhost\\t{0}\\n::1\\tlocalhost.localdomain\\tlocalhost\\t{0}\">{1}/etc/hosts"), hostname, mountpoint); - utils::exec(cmd); + gucc::utils::exec(cmd); #endif } @@ -478,7 +406,7 @@ LC_MESSAGES="{0}")"; std::ofstream locale_config_file{locale_config_path}; locale_config_file << fmt::format(locale_config_part, locale); - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/#{0}/{0}/\" {1}"), locale, locale_gen_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/#{0}/{0}/\" {1}"), locale, locale_gen_path)); // Generate locales utils::arch_chroot("locale-gen", false); @@ -492,7 +420,7 @@ void set_xkbmap(const std::string_view& xkbmap) noexcept { auto& config_data = config_instance->data(); const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); - utils::exec(fmt::format(FMT_COMPILE("echo -e \"Section \"\\\"InputClass\"\\\"\\nIdentifier \"\\\"system-keyboard\"\\\"\\nMatchIsKeyboard \"\\\"on\"\\\"\\nOption \"\\\"XkbLayout\"\\\" \"\\\"{0}\"\\\"\\nEndSection\" > {1}/etc/X11/xorg.conf.d/00-keyboard.conf"), xkbmap, mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("echo -e \"Section \"\\\"InputClass\"\\\"\\nIdentifier \"\\\"system-keyboard\"\\\"\\nMatchIsKeyboard \"\\\"on\"\\\"\\nOption \"\\\"XkbLayout\"\\\" \"\\\"{0}\"\\\"\\nEndSection\" > {1}/etc/X11/xorg.conf.d/00-keyboard.conf"), xkbmap, mountpoint)); #endif } @@ -535,7 +463,7 @@ void create_new_user(const std::string_view& user, const std::string_view& passw const auto& headless_mode = std::get(config_data["HEADLESS_MODE"]); const auto& cmd_formatted = fmt::format(FMT_COMPILE("{} {} {} |& tee -a /tmp/pacstrap.log"), cmd, mountpoint, packages); if (headless_mode) { - utils::exec(cmd_formatted, true); + gucc::utils::exec(cmd_formatted, true); } else { tui::detail::follow_process_log_widget({"/bin/sh", "-c", cmd_formatted}); } @@ -548,13 +476,13 @@ void create_new_user(const std::string_view& user, const std::string_view& passw spdlog::info("add user to groups"); // check if user has been created - const auto& user_check = utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} getent passwd {}"), mountpoint, user)); + const auto& user_check = gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} getent passwd {}"), mountpoint, user)); if (user_check.empty()) { spdlog::error("User has not been created!"); } std::error_code err{}; - utils::exec(fmt::format(FMT_COMPILE("echo -e \"{0}\\n{0}\" > /tmp/.passwd"), password)); - const auto& ret_status = utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd {} < /tmp/.passwd &>/dev/null"), mountpoint, user), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("echo -e \"{0}\\n{0}\" > /tmp/.passwd"), password)); + const auto& ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd {} < /tmp/.passwd &>/dev/null"), mountpoint, user), true); spdlog::info("create user pwd: {}", ret_status); fs::remove("/tmp/.passwd", err); @@ -563,7 +491,7 @@ void create_new_user(const std::string_view& user, const std::string_view& passw utils::arch_chroot(fmt::format(FMT_COMPILE("chown -R {0}:{0} /home/{0}"), user), false); const auto& sudoers_file = fmt::format(FMT_COMPILE("{}/etc/sudoers"), mountpoint); if (fs::exists(sudoers_file)) { - utils::exec(fmt::format(FMT_COMPILE("sed -i '/NOPASSWD/!s/# %sudo/%sudo/g' {}"), sudoers_file)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i '/NOPASSWD/!s/# %sudo/%sudo/g' {}"), sudoers_file)); } #else spdlog::debug("user := {}, password := {}", user, password); @@ -578,8 +506,8 @@ void set_root_password(const std::string_view& password) noexcept { const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); std::error_code err{}; - utils::exec(fmt::format(FMT_COMPILE("echo -e \"{0}\n{0}\" > /tmp/.passwd"), password)); - utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd root < /tmp/.passwd &>/dev/null"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("echo -e \"{0}\n{0}\" > /tmp/.passwd"), password)); + gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd root < /tmp/.passwd &>/dev/null"), mountpoint)); fs::remove("/tmp/.passwd", err); #else spdlog::debug("root password := {}", password); @@ -599,7 +527,7 @@ void find_partitions() noexcept { // get the list of partitions and also include the zvols since it is common to mount filesystems directly on them. It should be safe to include them here since they present as block devices. static constexpr auto other_piece = R"(sed 's/part$/\/dev\//g' | sed 's/lvm$\|crypt$/\/dev\/mapper\//g' | awk '{print $3$1 " " $2}' | awk '!/mapper/{a[++i]=$0;next}1;END{while(x/dev/null | awk '{printf "/dev/zvol/%s %s\n", $1, $2}')"; - const auto& partitions_tmp = utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME,SIZE,TYPE | grep '{}' | {}"), include_part, other_piece)); + const auto& partitions_tmp = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME,SIZE,TYPE | grep '{}' | {}"), include_part, other_piece)); spdlog::info("found partitions:\n{}", partitions_tmp); @@ -646,9 +574,9 @@ void find_partitions() noexcept { } void lvm_detect(std::optional> func_callback) noexcept { - const auto& lvm_pv = utils::exec("pvs -o pv_name --noheading 2>/dev/null"); - const auto& lvm_vg = utils::exec("vgs -o vg_name --noheading 2>/dev/null"); - const auto& lvm_lv = utils::exec("lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null"); + const auto& lvm_pv = gucc::utils::exec("pvs -o pv_name --noheading 2>/dev/null"); + const auto& lvm_vg = gucc::utils::exec("vgs -o vg_name --noheading 2>/dev/null"); + const auto& lvm_lv = gucc::utils::exec("lvs -o vg_name,lv_name --noheading --separator - 2>/dev/null"); if (lvm_lv.empty() || lvm_vg.empty() || lvm_pv.empty()) { return; @@ -659,9 +587,9 @@ void lvm_detect(std::optional> func_callback) noexcept { } #ifdef NDEVENV - utils::exec("modprobe dm-mod"); - utils::exec("vgscan >/dev/null 2>&1"); - utils::exec("vgchange -ay >/dev/null 2>&1"); + gucc::utils::exec("modprobe dm-mod"); + gucc::utils::exec("vgscan >/dev/null 2>&1"); + gucc::utils::exec("vgchange -ay >/dev/null 2>&1"); #endif } @@ -910,7 +838,7 @@ void install_from_pkglist(const std::string_view& packages) noexcept { #ifdef NDEVENV const auto& headless_mode = std::get(config_data["HEADLESS_MODE"]); if (headless_mode) { - utils::exec(cmd_formatted, true); + gucc::utils::exec(cmd_formatted, true); } else { tui::detail::follow_process_log_widget({"/bin/sh", "-c", cmd_formatted}); } @@ -1008,8 +936,8 @@ void install_base(const std::string_view& packages) noexcept { utils::arch_chroot("systemctl enable zfs-import.target", false); // we also need create the cachefile - utils::exec(fmt::format(FMT_COMPILE("zpool set cachefile=/etc/zfs/zpool.cache $(findmnt {} -lno SOURCE | {}) 2>>/tmp/cachyos-install.log"), mountpoint, "awk -F / '{print $1}'"), true); - utils::exec(fmt::format(FMT_COMPILE("cp /etc/zfs/zpool.cache {}/etc/zfs/zpool.cache 2>>/tmp/cachyos-install.log"), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zpool set cachefile=/etc/zfs/zpool.cache $(findmnt {} -lno SOURCE | {}) 2>>/tmp/cachyos-install.log"), mountpoint, "awk -F / '{print $1}'"), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("cp /etc/zfs/zpool.cache {}/etc/zfs/zpool.cache 2>>/tmp/cachyos-install.log"), mountpoint), true); #endif } @@ -1040,13 +968,13 @@ void remove_pkgs(const std::string_view& packages) noexcept { void install_grub_uefi(const std::string_view& bootid, bool as_default) noexcept { #ifdef NDEVENV fs::create_directory("/mnt/hostlvm"); - utils::exec("mount --bind /run/lvm /mnt/hostlvm"); + gucc::utils::exec("mount --bind /run/lvm /mnt/hostlvm"); #endif // if root is encrypted, amend /etc/default/grub - const auto& root_name = utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); - const auto& root_device = utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {}"), root_name, "awk '/disk/ {print $1}'")); - const auto& root_part = utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/part/p\" | {} | tr -cd '[:alnum:]'"), root_name, "awk '/part/ {print $1}'")); + const auto& root_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + const auto& root_device = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {}"), root_name, "awk '/disk/ {print $1}'")); + const auto& root_part = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/part/p\" | {} | tr -cd '[:alnum:]'"), root_name, "awk '/part/ {print $1}'")); #ifdef NDEVENV utils::boot_encrypted_setting(); #endif @@ -1066,7 +994,7 @@ void install_grub_uefi(const std::string_view& bootid, bool as_default) noexcept // grub config changes for zfs root if (utils::get_mountpoint_fs(mountpoint) == "zfs") { // zfs needs ZPOOL_VDEV_NAME_PATH set to properly find the device - utils::exec(fmt::format(FMT_COMPILE("echo ZPOOL_VDEV_NAME_PATH=YES >> {}/etc/environment"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("echo ZPOOL_VDEV_NAME_PATH=YES >> {}/etc/environment"), mountpoint)); setenv("ZPOOL_VDEV_NAME_PATH", "YES", 1); constexpr auto bash_codepart1 = R"(#!/bin/bash @@ -1106,20 +1034,20 @@ lsblk -ino TYPE,MOUNTPOINT | grep " /$" | grep -q lvm && sed -e '/GRUB_SAVEDEFAU fs::perm_options::add); // if the device is removable append removable to the grub-install - const auto& removable = utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/removable"), root_device)); + const auto& removable = gucc::utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/removable"), root_device)); if (utils::to_int(removable.data()) == 1) { - utils::exec(fmt::format(FMT_COMPILE("sed -e '/^grub-install /s/$/ --removable/g' -i {}"), grub_installer_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e '/^grub-install /s/$/ --removable/g' -i {}"), grub_installer_path)); } // If the root is on btrfs-subvolume, amend grub installation - auto ret_status = utils::exec("mount | awk '$3 == \"/mnt\" {print $0}' | grep btrfs | grep -qv subvolid=5", true); + auto ret_status = gucc::utils::exec("mount | awk '$3 == \"/mnt\" {print $0}' | grep btrfs | grep -qv subvolid=5", true); if (ret_status != "0") { - utils::exec(fmt::format(FMT_COMPILE("sed -e 's/ grub-btrfs//g' -i {}"), grub_installer_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e 's/ grub-btrfs//g' -i {}"), grub_installer_path)); } // If encryption used amend grub if (luks_dev != "") { - const auto& luks_dev_formatted = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | {}"), luks_dev, "awk '{print $1}'")); - ret_status = utils::exec(fmt::format(FMT_COMPILE("echo \"sed -i \\\"s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\\\\\\\"\"{}\\\\\\\"~g\\\"\" /etc/default/grub\" >> {}"), luks_dev_formatted, grub_installer_path), true); + const auto& luks_dev_formatted = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | {}"), luks_dev, "awk '{print $1}'")); + ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"sed -i \\\"s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\\\\\\\"\"{}\\\\\\\"~g\\\"\" /etc/default/grub\" >> {}"), luks_dev_formatted, grub_installer_path), true); if (ret_status == "0") { spdlog::info("adding kernel parameter {}", luks_dev); } @@ -1129,7 +1057,7 @@ lsblk -ino TYPE,MOUNTPOINT | grep " /$" | grep -q lvm && sed -e '/GRUB_SAVEDEFAU const auto& fde = std::get(config_data["fde"]); if (fde == 1) { spdlog::info("Full disk encryption enabled"); - utils::exec(fmt::format(FMT_COMPILE("sed -i '3a\\grep -q \"^GRUB_ENABLE_CRYPTODISK=y\" /etc/default/grub || sed -i \"s/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/\" /etc/default/grub' {}"), grub_installer_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i '3a\\grep -q \"^GRUB_ENABLE_CRYPTODISK=y\" /etc/default/grub || sed -i \"s/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/\" /etc/default/grub' {}"), grub_installer_path)); } std::error_code err{}; @@ -1165,8 +1093,8 @@ void install_refind() noexcept { utils::inst_needed("refind"); // Check if the volume is removable. If so, install all drivers - const auto& root_name = utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); - const auto& root_device = utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {}"), root_name, "awk '/disk/ {print $1}'")); + const auto& root_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + const auto& root_device = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {}"), root_name, "awk '/disk/ {print $1}'")); spdlog::info("root_name: {}. root_device: {}", root_name, root_device); // Clean the configuration in case there is previous one because the configuration part is not idempotent @@ -1176,9 +1104,9 @@ void install_refind() noexcept { } // install refind - const auto& removable = utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/removable"), root_device)); + const auto& removable = gucc::utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/removable"), root_device)); if (utils::to_int(removable.data()) == 1) { - utils::exec("refind-install --root /mnt --alldrivers --yes &>>/tmp/cachyos-install.log"); + gucc::utils::exec("refind-install --root /mnt --alldrivers --yes &>>/tmp/cachyos-install.log"); const auto& initcpio_filename = fmt::format(FMT_COMPILE("{}/etc/mkinitcpio.conf"), mountpoint); auto initcpio = gucc::detail::Initcpio{initcpio_filename}; @@ -1187,57 +1115,57 @@ void install_refind() noexcept { initcpio.remove_hook("autodetect"); spdlog::info("\"Autodetect\" hook was removed"); } else if (luks == 1) { - utils::exec("refind-install --root /mnt --alldrivers --yes &>>/tmp/cachyos-install.log"); + gucc::utils::exec("refind-install --root /mnt --alldrivers --yes &>>/tmp/cachyos-install.log"); } else { - utils::exec("refind-install --root /mnt --alldrivers &>>/tmp/cachyos-install.log"); + gucc::utils::exec("refind-install --root /mnt --alldrivers &>>/tmp/cachyos-install.log"); } // Mount as rw // sed -i 's/ro\ /rw\ \ /g' /mnt/boot/refind_linux.conf // Set appropriate rootflags if installed on btrfs subvolume - if (utils::exec("mount | awk '$3 == \"/mnt\" {print $0}' | grep btrfs | grep -qv subvolid=5", true) == "0") { - const auto& rootflag = fmt::format(FMT_COMPILE("rootflags={}"), utils::exec("mount | awk '$3 == \"/mnt\" {print $6}' | sed 's/^.*subvol=/subvol=/' | sed -e 's/,.*$/,/p' | sed 's/)//g'")); - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$|\\ {}\\\"|g\" /mnt/boot/refind_linux.conf"), rootflag)); + if (gucc::utils::exec("mount | awk '$3 == \"/mnt\" {print $0}' | grep btrfs | grep -qv subvolid=5", true) == "0") { + const auto& rootflag = fmt::format(FMT_COMPILE("rootflags={}"), gucc::utils::exec("mount | awk '$3 == \"/mnt\" {print $6}' | sed 's/^.*subvol=/subvol=/' | sed -e 's/,.*$/,/p' | sed 's/)//g'")); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$|\\ {}\\\"|g\" /mnt/boot/refind_linux.conf"), rootflag)); } // LUKS and lvm with LUKS if (luks == 1) { - const auto& mapper_name = utils::exec("mount | awk '/\\/mnt / {print $1}'"); - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|root=.* |{} root={} |g\" /mnt/boot/refind_linux.conf"), luks_dev, mapper_name)); - utils::exec("sed -i '/Boot with minimal options/d' /mnt/boot/refind_linux.conf"); + const auto& mapper_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}'"); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|root=.* |{} root={} |g\" /mnt/boot/refind_linux.conf"), luks_dev, mapper_name)); + gucc::utils::exec("sed -i '/Boot with minimal options/d' /mnt/boot/refind_linux.conf"); } // Lvm without LUKS - else if (utils::exec("lsblk -i | sed -r 's/^[^[:alnum:]]+//' | grep \"/mnt$\" | awk '{print $6}'") == "lvm") { - const auto& mapper_name = utils::exec("mount | awk '/\\/mnt / {print $1}'"); - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|root=.* |root={} |g\" /mnt/boot/refind_linux.conf"), mapper_name)); - utils::exec("sed -i '/Boot with minimal options/d' /mnt/boot/refind_linux.conf"); + else if (gucc::utils::exec("lsblk -i | sed -r 's/^[^[:alnum:]]+//' | grep \"/mnt$\" | awk '{print $6}'") == "lvm") { + const auto& mapper_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}'"); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|root=.* |root={} |g\" /mnt/boot/refind_linux.conf"), mapper_name)); + gucc::utils::exec("sed -i '/Boot with minimal options/d' /mnt/boot/refind_linux.conf"); } // Figure out microcode - const auto& rootsubvol = utils::exec("findmnt -o TARGET,SOURCE | awk '/\\/mnt / {print $2}' | grep -o \"\\[.*\\]\" | cut -d \"[\" -f2 | cut -d \"]\" -f1 | sed 's/^\\///'"); - const auto& ucode = utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} pacman -Qqs ucode 2>>/tmp/cachyos-install.log"), mountpoint)); - if (utils::to_int(utils::exec(fmt::format(FMT_COMPILE("echo {} | wc -l)"), ucode)).data()) > 1) { + const auto& rootsubvol = gucc::utils::exec("findmnt -o TARGET,SOURCE | awk '/\\/mnt / {print $2}' | grep -o \"\\[.*\\]\" | cut -d \"[\" -f2 | cut -d \"]\" -f1 | sed 's/^\\///'"); + const auto& ucode = gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} pacman -Qqs ucode 2>>/tmp/cachyos-install.log"), mountpoint)); + if (utils::to_int(gucc::utils::exec(fmt::format(FMT_COMPILE("echo {} | wc -l)"), ucode)).data()) > 1) { // set microcode - if (utils::exec("findmnt -o TARGET,SOURCE | grep -q \"/mnt/boot \"", true) == "0") { + if (gucc::utils::exec("findmnt -o TARGET,SOURCE | grep -q \"/mnt/boot \"", true) == "0") { // there is a separate boot, path to microcode is at partition root - utils::exec("sed -i \"s|\\\"$| initrd=/intel-ucode.img initrd=/amd-ucode.img initrd=/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"); + gucc::utils::exec("sed -i \"s|\\\"$| initrd=/intel-ucode.img initrd=/amd-ucode.img initrd=/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"); } else if (!rootsubvol.empty()) { // Initramfs is on the root partition and root is on btrfs subvolume - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$| initrd={0}/boot/intel-ucode.img initrd={0}/boot/amd-ucode.img initrd={0}/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), rootsubvol)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$| initrd={0}/boot/intel-ucode.img initrd={0}/boot/amd-ucode.img initrd={0}/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), rootsubvol)); } else { // Initramfs is on the root partition - utils::exec("sed -i \"s|\\\"$| initrd=/boot/intel-ucode.img initrd=/boot/amd-ucode.img initrd=/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"); + gucc::utils::exec("sed -i \"s|\\\"$| initrd=/boot/intel-ucode.img initrd=/boot/amd-ucode.img initrd=/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"); } } else { - if (utils::exec("findmnt -o TARGET,SOURCE | grep -q \"/mnt/boot \"", true) == "0") { + if (gucc::utils::exec("findmnt -o TARGET,SOURCE | grep -q \"/mnt/boot \"", true) == "0") { // there is a separate boot, path to microcode is at partition root - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$| initrd=/{}.img initrd=/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), ucode)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$| initrd=/{}.img initrd=/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), ucode)); } else if (!rootsubvol.empty()) { // Initramfs is on the root partition and root is on btrfs subvolume - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$| initrd={0}/boot/{1}.img initrd={0}/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), rootsubvol, ucode)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s|\\\"$| initrd={0}/boot/{1}.img initrd={0}/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), rootsubvol, ucode)); } else { // Initramfs is on the root partition - utils::exec(fmt::format(FMT_COMPILE(" sed -i \"s|\\\"$| initrd=/boot/{}.img initrd=/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), ucode)); + gucc::utils::exec(fmt::format(FMT_COMPILE(" sed -i \"s|\\\"$| initrd=/boot/{}.img initrd=/boot/initramfs-%v.img\\\"|g\" /mnt/boot/refind_linux.conf"), ucode)); } } @@ -1262,10 +1190,10 @@ void install_systemd_boot() noexcept { utils::arch_chroot("sdboot-manage gen", false); // Check if the volume is removable. If so, don't use autodetect - const auto& root_name = utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); - const auto& root_device = utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {}"), root_name, "awk '/disk/ {print $1}'")); + const auto& root_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + const auto& root_device = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {}"), root_name, "awk '/disk/ {print $1}'")); spdlog::info("root_name: {}. root_device: {}", root_name, root_device); - const auto& removable = utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/removable"), root_device)); + const auto& removable = gucc::utils::exec(fmt::format(FMT_COMPILE("cat /sys/block/{}/removable"), root_device)); if (utils::to_int(removable.data()) == 1) { const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); const auto& initcpio_filename = fmt::format(FMT_COMPILE("{}/etc/mkinitcpio.conf"), mountpoint); @@ -1285,7 +1213,7 @@ void uefi_bootloader(const std::string_view& bootloader) noexcept { static constexpr auto efi_path = "/sys/firmware/efi/"; if (fs::exists(efi_path) && fs::is_directory(efi_path)) { // Mount efivarfs if it is not already mounted - const auto& mount_out = utils::exec("mount | grep /sys/firmware/efi/efivars"); + const auto& mount_out = gucc::utils::exec("mount | grep /sys/firmware/efi/efivars"); if (mount_out.empty()) { if (mount("efivarfs", "/sys/firmware/efi/efivars", "efivarfs", 0, "") != 0) { perror("utils::uefi_bootloader"); @@ -1322,18 +1250,18 @@ void bios_bootloader(const std::string_view& bootloader) noexcept { // if /boot is LVM (whether using a seperate /boot mount or not), amend grub if ((lvm == 1 && lvm_sep_boot == 0) || lvm_sep_boot == 2) { - utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/GRUB_PRELOAD_MODULES=\\\"/GRUB_PRELOAD_MODULES=\\\"lvm /g\" {}/etc/default/grub"), mountpoint)); - utils::exec(fmt::format(FMT_COMPILE("sed -e '/GRUB_SAVEDEFAULT/ s/^#*/#/' -i {}/etc/default/grub"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/GRUB_PRELOAD_MODULES=\\\"/GRUB_PRELOAD_MODULES=\\\"lvm /g\" {}/etc/default/grub"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e '/GRUB_SAVEDEFAULT/ s/^#*/#/' -i {}/etc/default/grub"), mountpoint)); } // If root is on btrfs volume, amend grub if (utils::get_mountpoint_fs(mountpoint) == "btrfs") { - utils::exec(fmt::format(FMT_COMPILE("sed -e '/GRUB_SAVEDEFAULT/ s/^#*/#/' -i {}/etc/default/grub"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e '/GRUB_SAVEDEFAULT/ s/^#*/#/' -i {}/etc/default/grub"), mountpoint)); } // Same setting is needed for LVM if (lvm == 1) { - utils::exec(fmt::format(FMT_COMPILE("sed -e '/GRUB_SAVEDEFAULT/ s/^#*/#/' -i {}/etc/default/grub"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e '/GRUB_SAVEDEFAULT/ s/^#*/#/' -i {}/etc/default/grub"), mountpoint)); } const auto& grub_installer_path = fmt::format(FMT_COMPILE("{}/usr/bin/grub_installer.sh"), mountpoint); @@ -1341,7 +1269,7 @@ void bios_bootloader(const std::string_view& bootloader) noexcept { // grub config changes for zfs root if (utils::get_mountpoint_fs(mountpoint) == "zfs") { // zfs needs ZPOOL_VDEV_NAME_PATH set to properly find the device - utils::exec(fmt::format(FMT_COMPILE("echo ZPOOL_VDEV_NAME_PATH=YES >> {}/etc/environment"), mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("echo ZPOOL_VDEV_NAME_PATH=YES >> {}/etc/environment"), mountpoint)); setenv("ZPOOL_VDEV_NAME_PATH", "YES", 1); constexpr auto bash_codepart1 = R"(#!/bin/bash @@ -1378,15 +1306,15 @@ grub-install --target=i386-pc --recheck)"; } // If the root is on btrfs-subvolume, amend grub installation - auto ret_status = utils::exec("mount | awk '$3 == \"/mnt\" {print $0}' | grep btrfs | grep -qv subvolid=5", true); + auto ret_status = gucc::utils::exec("mount | awk '$3 == \"/mnt\" {print $0}' | grep btrfs | grep -qv subvolid=5", true); if (ret_status != "0") { - utils::exec(fmt::format(FMT_COMPILE("sed -e 's/ grub-btrfs//g' -i {}"), grub_installer_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e 's/ grub-btrfs//g' -i {}"), grub_installer_path)); } // If encryption used amend grub if (luks_dev != "") { - const auto& luks_dev_formatted = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | {}"), luks_dev, "awk '{print $1}'")); - ret_status = utils::exec(fmt::format(FMT_COMPILE("echo \"sed -i \\\"s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\\\\\\\"\"{}\\\\\\\"~g\\\"\" /etc/default/grub\" >> {}"), luks_dev_formatted, grub_installer_path), true); + const auto& luks_dev_formatted = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | {}"), luks_dev, "awk '{print $1}'")); + ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("echo \"sed -i \\\"s~GRUB_CMDLINE_LINUX=.*~GRUB_CMDLINE_LINUX=\\\\\\\"\"{}\\\\\\\"~g\\\"\" /etc/default/grub\" >> {}"), luks_dev_formatted, grub_installer_path), true); if (ret_status == "0") { spdlog::info("adding kernel parameter {}", luks_dev); } @@ -1396,14 +1324,14 @@ grub-install --target=i386-pc --recheck)"; const auto& fde = std::get(config_data["fde"]); if (fde == 1) { spdlog::info("Full disk encryption enabled"); - utils::exec(fmt::format(FMT_COMPILE("sed -i '3a\\grep -q \"^GRUB_ENABLE_CRYPTODISK=y\" /etc/default/grub || sed -i \"s/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/\" /etc/default/grub' {}"), grub_installer_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i '3a\\grep -q \"^GRUB_ENABLE_CRYPTODISK=y\" /etc/default/grub || sed -i \"s/#GRUB_ENABLE_CRYPTODISK=y/GRUB_ENABLE_CRYPTODISK=y/\" /etc/default/grub' {}"), grub_installer_path)); } // Remove os-prober if not selected constexpr std::string_view needle{"os-prober"}; const auto& found = ranges::search(bootloader, needle); if (found.empty()) { - utils::exec(fmt::format(FMT_COMPILE("sed -e 's/ os-prober//g' -i {}"), grub_installer_path)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -e 's/ os-prober//g' -i {}"), grub_installer_path)); } std::error_code err{}; @@ -1413,9 +1341,9 @@ grub-install --target=i386-pc --recheck)"; fs::perm_options::add); tui::detail::infobox_widget("\nPlease wait...\n"); - utils::exec(fmt::format(FMT_COMPILE("dd if=/dev/zero of={} seek=1 count=2047"), device_info)); + gucc::utils::exec(fmt::format(FMT_COMPILE("dd if=/dev/zero of={} seek=1 count=2047"), device_info)); fs::create_directory("/mnt/hostlvm", err); - utils::exec("mount --bind /run/lvm /mnt/hostlvm"); + gucc::utils::exec("mount --bind /run/lvm /mnt/hostlvm"); // install grub utils::arch_chroot("grub_installer.sh"); @@ -1445,24 +1373,24 @@ void install_bootloader(const std::string_view& bootloader) noexcept { // List partitions to be hidden from the mounting menu std::string list_mounted() noexcept { - utils::exec("lsblk -l | awk '$7 ~ /mnt/ {print $1}' > /tmp/.mounted"); - return utils::exec("echo /dev/* /dev/mapper/* | xargs -n1 2>/dev/null | grep -f /tmp/.mounted"); + gucc::utils::exec("lsblk -l | awk '$7 ~ /mnt/ {print $1}' > /tmp/.mounted"); + return gucc::utils::exec("echo /dev/* /dev/mapper/* | xargs -n1 2>/dev/null | grep -f /tmp/.mounted"); } std::string get_mountpoint_fs(const std::string_view& mountpoint) noexcept { - return utils::exec(fmt::format(FMT_COMPILE("findmnt -ln -o FSTYPE \"{}\""), mountpoint)); + return gucc::utils::exec(fmt::format(FMT_COMPILE("findmnt -ln -o FSTYPE \"{}\""), mountpoint)); } std::string get_mountpoint_source(const std::string_view& mountpoint) noexcept { - return utils::exec(fmt::format(FMT_COMPILE("findmnt -ln -o SOURCE \"{}\""), mountpoint)); + return gucc::utils::exec(fmt::format(FMT_COMPILE("findmnt -ln -o SOURCE \"{}\""), mountpoint)); } std::string list_containing_crypt() noexcept { - return utils::exec("blkid | awk '/TYPE=\"crypto_LUKS\"/{print $1}' | sed 's/.$//'"); + return gucc::utils::exec("blkid | awk '/TYPE=\"crypto_LUKS\"/{print $1}' | sed 's/.$//'"); } std::string list_non_crypt() noexcept { - return utils::exec("blkid | awk '!/TYPE=\"crypto_LUKS\"/{print $1}' | sed 's/.$//'"); + return gucc::utils::exec("blkid | awk '!/TYPE=\"crypto_LUKS\"/{print $1}' | sed 's/.$//'"); } void get_cryptroot() noexcept { @@ -1470,30 +1398,30 @@ void get_cryptroot() noexcept { auto& config_data = config_instance->data(); // Identify if /mnt or partition is type "crypt" (LUKS on LVM, or LUKS alone) - if ((utils::exec("lsblk | sed -r 's/^[^[:alnum:]]+//' | awk '/\\/mnt$/ {print $6}' | grep -q crypt", true) != "0") - || (utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt$/,/part/p" | awk '{print $6}' | grep -q crypt)", true) != "0")) { + if ((gucc::utils::exec("lsblk | sed -r 's/^[^[:alnum:]]+//' | awk '/\\/mnt$/ {print $6}' | grep -q crypt", true) != "0") + || (gucc::utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt$/,/part/p" | awk '{print $6}' | grep -q crypt)", true) != "0")) { return; } config_data["LUKS"] = 1; auto& luks_name = std::get(config_data["LUKS_ROOT_NAME"]); - luks_name = utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + luks_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); // Get the name of the Luks device - if (utils::exec("lsblk -i | grep -q -e \"crypt /mnt\"", true) != "0") { + if (gucc::utils::exec("lsblk -i | grep -q -e \"crypt /mnt\"", true) != "0") { // Mountpoint is not directly on LUKS device, so we need to get the crypt device above the mountpoint - luks_name = utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt$/,/crypt/p" | awk '/crypt/ {print $1}')"); + luks_name = gucc::utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt$/,/crypt/p" | awk '/crypt/ {print $1}')"); } const auto& check_cryptparts = [&luks_name](const auto& cryptparts, auto functor) { for (const auto& cryptpart : cryptparts) { - if (!utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME {} | grep \"{}\""), cryptpart, luks_name)).empty()) { + if (!gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -lno NAME {} | grep \"{}\""), cryptpart, luks_name)).empty()) { functor(cryptpart); } } }; // Check if LUKS on LVM (parent = lvm /dev/mapper/...) - auto temp_out = utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE,MOUNTPOINT | grep "lvm" | grep "/mnt$" | grep -i "crypto_luks" | uniq | awk '{print "/dev/mapper/"$1}')"); + auto temp_out = gucc::utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE,MOUNTPOINT | grep "lvm" | grep "/mnt$" | grep -i "crypto_luks" | uniq | awk '{print "/dev/mapper/"$1}')"); if (!temp_out.empty()) { const auto& cryptparts = gucc::utils::make_multiline(temp_out); const auto& check_functor = [&](const auto& cryptpart) { @@ -1505,12 +1433,12 @@ void get_cryptroot() noexcept { } // Check if LVM on LUKS - temp_out = utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep " crypt$" | grep -i "LVM2_member" | uniq | awk '{print "/dev/mapper/"$1}')"); + temp_out = gucc::utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE | grep " crypt$" | grep -i "LVM2_member" | uniq | awk '{print "/dev/mapper/"$1}')"); if (!temp_out.empty()) { const auto& cryptparts = gucc::utils::make_multiline(temp_out); const auto& check_functor = [&]([[maybe_unused]] const auto& cryptpart) { auto& luks_uuid = std::get(config_data["LUKS_UUID"]); - luks_uuid = utils::exec(R"(lsblk -ino NAME,FSTYPE,TYPE,MOUNTPOINT,UUID | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt /,/part/p" | awk '/crypto_LUKS/ {print $4}')"); + luks_uuid = gucc::utils::exec(R"(lsblk -ino NAME,FSTYPE,TYPE,MOUNTPOINT,UUID | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt /,/part/p" | awk '/crypto_LUKS/ {print $4}')"); config_data["LUKS_DEV"] = fmt::format(FMT_COMPILE("cryptdevice=UUID={}:{}"), luks_uuid, luks_name); config_data["LVM"] = 1; }; @@ -1519,12 +1447,12 @@ void get_cryptroot() noexcept { } // Check if LUKS alone (parent = part /dev/...) - temp_out = utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE,MOUNTPOINT | grep "/mnt$" | grep "part" | grep -i "crypto_luks" | uniq | awk '{print "/dev/"$1}')"); + temp_out = gucc::utils::exec(R"(lsblk -lno NAME,FSTYPE,TYPE,MOUNTPOINT | grep "/mnt$" | grep "part" | grep -i "crypto_luks" | uniq | awk '{print "/dev/"$1}')"); if (!temp_out.empty()) { const auto& cryptparts = gucc::utils::make_multiline(temp_out); const auto& check_functor = [&](const auto& cryptpart) { auto& luks_uuid = std::get(config_data["LUKS_UUID"]); - luks_uuid = utils::exec(fmt::format(FMT_COMPILE("lsblk -lno UUID,TYPE,FSTYPE {} | grep \"part\" | grep -i \"crypto_luks\" | {}"), cryptpart, "awk '{print $1}'")); + 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_uuid, luks_name); }; check_cryptparts(cryptparts, check_functor); @@ -1536,18 +1464,18 @@ void recheck_luks() noexcept { auto* config_instance = Config::instance(); auto& config_data = config_instance->data(); - const auto& root_name = utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + const auto& root_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); // Check if there is separate encrypted /boot partition - if (utils::exec("lsblk | grep '/mnt/boot' | grep -q 'crypt'", true) == "0") { + if (gucc::utils::exec("lsblk | grep '/mnt/boot' | grep -q 'crypt'", true) == "0") { config_data["LUKS"] = 1; } // Check if root is encrypted and there is no separate /boot - else if ((utils::exec("lsblk | grep \"/mnt$\" | grep -q 'crypt'", true) == "0") && utils::exec("lsblk | grep \"/mnt/boot$\"", false).empty()) { + else if ((gucc::utils::exec("lsblk | grep \"/mnt$\" | grep -q 'crypt'", true) == "0") && gucc::utils::exec("lsblk | grep \"/mnt/boot$\"", false).empty()) { config_data["LUKS"] = 1; } // Check if root is on encrypted lvm volume - else if ((utils::exec("lsblk | grep '/mnt/boot' | grep -q 'crypt'", true) == "0") && (utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {} | grep -q crypt"), root_name, "awk '{print $6}'"), true) == "0")) { + else if ((gucc::utils::exec("lsblk | grep '/mnt/boot' | grep -q 'crypt'", true) == "0") && (gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {} | grep -q crypt"), root_name, "awk '{print $6}'"), true) == "0")) { config_data["LUKS"] = 1; } } @@ -1557,26 +1485,26 @@ void get_cryptboot() noexcept { auto& config_data = config_instance->data(); // If /boot is encrypted - if ((utils::exec("lsblk | sed -r 's/^[^[:alnum:]]+//' | awk '/\\/mnt\\/boot$/ {print $6}' | grep -q crypt", true) != "0") - || (utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt\/boot$/,/part/p" | awk '{print $6}' | grep -q crypt)", true) != "0")) { + if ((gucc::utils::exec("lsblk | sed -r 's/^[^[:alnum:]]+//' | awk '/\\/mnt\\/boot$/ {print $6}' | grep -q crypt", true) != "0") + || (gucc::utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt\/boot$/,/part/p" | awk '{print $6}' | grep -q crypt)", true) != "0")) { return; } config_data["LUKS"] = 1; // Mountpoint is directly on the LUKS device, so LUKS device is the same as root name - std::string boot_name{utils::exec("mount | awk '/\\/mnt\\/boot / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g")}; + std::string boot_name{gucc::utils::exec("mount | awk '/\\/mnt\\/boot / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g")}; // Get UUID of the encrypted /boot - std::string boot_uuid{utils::exec("lsblk -lno UUID,MOUNTPOINT | awk '/\\mnt\\/boot$/ {print $1}'")}; + std::string boot_uuid{gucc::utils::exec("lsblk -lno UUID,MOUNTPOINT | awk '/\\mnt\\/boot$/ {print $1}'")}; // Get the name of the Luks device - if (utils::exec("lsblk -i | grep -q -e \"crypt /mnt\"", true) != "0") { + if (gucc::utils::exec("lsblk -i | grep -q -e \"crypt /mnt\"", true) != "0") { // Mountpoint is not directly on LUKS device, so we need to get the crypt device above the mountpoint - boot_name = utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt\/boot$/,/crypt/p" | awk '/crypt/ {print $1}')"); - boot_uuid = utils::exec(R"(lsblk -ino NAME,FSTYPE,TYPE,MOUNTPOINT,UUID | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt\/boot /,/part/p" | awk '/crypto_LUKS/ {print $4}')"); + boot_name = gucc::utils::exec(R"(lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt\/boot$/,/crypt/p" | awk '/crypt/ {print $1}')"); + boot_uuid = gucc::utils::exec(R"(lsblk -ino NAME,FSTYPE,TYPE,MOUNTPOINT,UUID | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e "/\/mnt\/boot /,/part/p" | awk '/crypto_LUKS/ {print $4}')"); } // Check if LVM on LUKS - if (utils::exec("lsblk -lno TYPE,MOUNTPOINT | grep \"/mnt/boot$\" | grep -q lvm", true) == "0") { + if (gucc::utils::exec("lsblk -lno TYPE,MOUNTPOINT | grep \"/mnt/boot$\" | grep -q lvm", true) == "0") { config_data["LVM"] = 1; } @@ -1596,27 +1524,27 @@ void boot_encrypted_setting() noexcept { auto& fde = std::get(config_data["fde"]); // Check if there is separate /boot partition - if (utils::exec("lsblk | grep \"/mnt/boot$\"").empty()) { + if (gucc::utils::exec("lsblk | grep \"/mnt/boot$\"").empty()) { // There is no separate /boot parition - const auto& root_name = utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + const auto& root_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); const auto& luks = std::get(config_data["LUKS"]); // Check if root is encrypted if ((luks == 1) - || (utils::exec(fmt::format(FMT_COMPILE("lsblk \"/dev/mapper/{}\" | grep -q 'crypt'"), root_name), true) == "0") - || (utils::exec("lsblk | grep \"/mnt$\" | grep -q 'crypt'", true) == "0") + || (gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk \"/dev/mapper/{}\" | grep -q 'crypt'"), root_name), true) == "0") + || (gucc::utils::exec("lsblk | grep \"/mnt$\" | grep -q 'crypt'", true) == "0") // Check if root is on encrypted lvm volume - || (utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {} | grep -q crypt"), root_name, "awk '{print $6}'"), true) == "0")) { + || (gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {} | grep -q crypt"), root_name, "awk '{print $6}'"), true) == "0")) { fde = 1; utils::setup_luks_keyfile(); } return; } // There is a separate /boot. Check if it is encrypted - const auto& boot_name = utils::exec("mount | awk '/\\/mnt\\/boot / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); - if ((utils::exec("lsblk | grep '/mnt/boot' | grep -q 'crypt'", true) == "0") + const auto& boot_name = gucc::utils::exec("mount | awk '/\\/mnt\\/boot / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + if ((gucc::utils::exec("lsblk | grep '/mnt/boot' | grep -q 'crypt'", true) == "0") // Check if the /boot is inside encrypted lvm volume - || (utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {} | grep -q crypt"), boot_name, "awk '{print $6}'"), true) == "0") - || (utils::exec(fmt::format(FMT_COMPILE("lsblk \"/dev/mapper/{}\" | grep -q 'crypt'"), boot_name), true) == "0")) { + || (gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/disk/p\" | {} | grep -q crypt"), boot_name, "awk '{print $6}'"), true) == "0") + || (gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk \"/dev/mapper/{}\" | grep -q 'crypt'"), boot_name), true) == "0")) { fde = 1; utils::setup_luks_keyfile(); } @@ -1628,7 +1556,7 @@ bool check_mount() noexcept { auto* config_instance = Config::instance(); auto& config_data = config_instance->data(); const auto& mountpoint_info = std::get(config_data["MOUNTPOINT"]); - if (utils::exec(fmt::format(FMT_COMPILE("findmnt -nl {}"), mountpoint_info)) == "") { + if (gucc::utils::exec(fmt::format(FMT_COMPILE("findmnt -nl {}"), mountpoint_info)) == "") { return false; } #endif @@ -1657,18 +1585,18 @@ void id_system() noexcept { auto& config_data = config_instance->data(); // Apple System Detection - const auto& sys_vendor = utils::exec("cat /sys/class/dmi/id/sys_vendor"); + const auto& sys_vendor = gucc::utils::exec("cat /sys/class/dmi/id/sys_vendor"); if ((sys_vendor == "Apple Inc.") || (sys_vendor == "Apple Computer, Inc.")) { - utils::exec("modprobe -r -q efivars || true"); // if MAC + gucc::utils::exec("modprobe -r -q efivars || true"); // if MAC } else { - utils::exec("modprobe -q efivarfs"); // all others + gucc::utils::exec("modprobe -q efivarfs"); // all others } // BIOS or UEFI Detection static constexpr auto efi_path = "/sys/firmware/efi/"; if (fs::exists(efi_path) && fs::is_directory(efi_path)) { // Mount efivarfs if it is not already mounted - const auto& mount_out = utils::exec("mount | grep /sys/firmware/efi/efivars"); + const auto& mount_out = gucc::utils::exec("mount | grep /sys/firmware/efi/efivars"); if (mount_out.empty()) { if (mount("efivarfs", "/sys/firmware/efi/efivars", "efivarfs", 0, "") != 0) { perror("utils::id_system"); @@ -1679,14 +1607,14 @@ void id_system() noexcept { } // init system - const auto& init_sys = utils::exec("cat /proc/1/comm"); + const auto& init_sys = gucc::utils::exec("cat /proc/1/comm"); auto& h_init = std::get(config_data["H_INIT"]); if (init_sys == "systemd") { h_init = "systemd"; } // TODO(vnepogodin): Test which nw-client is available, including if the service according to $H_INIT is running - if (h_init == "systemd" && utils::exec("systemctl is-active NetworkManager") == "active") { + if (h_init == "systemd" && gucc::utils::exec("systemctl is-active NetworkManager") == "active") { config_data["NW_CMD"] = "nmtui"; } } @@ -1731,8 +1659,8 @@ void install_cachyos_repo() noexcept { spdlog::info("install_cachyos_repo: repo_list := '{}'", repo_list); #ifdef NDEVENV - utils::exec("pacman-key --recv-keys F3B607488DB35A47 --keyserver keyserver.ubuntu.com", true); - utils::exec("pacman-key --lsign-key F3B607488DB35A47", true); + gucc::utils::exec("pacman-key --recv-keys F3B607488DB35A47 --keyserver keyserver.ubuntu.com", true); + gucc::utils::exec("pacman-key --lsign-key F3B607488DB35A47", true); #endif const auto& isa_levels = gucc::cpu::get_isa_levels(); @@ -1794,7 +1722,7 @@ bool handle_connection() noexcept { if (connected) { utils::install_cachyos_repo(); - utils::exec("yes | pacman -Sy --noconfirm", true); + gucc::utils::exec("yes | pacman -Sy --noconfirm", true); } #else utils::install_cachyos_repo(); @@ -1813,7 +1741,7 @@ void show_iwctl() noexcept { info_inter("6 - type `exit`\n"); while (utils::prompt_char("Press a key to continue...", CYAN)) { - utils::exec("iwctl", true); + gucc::utils::exec("iwctl", true); break; } } @@ -1823,28 +1751,28 @@ void set_keymap() noexcept { auto& config_data = config_instance->data(); const auto& keymap = std::get(config_data["KEYMAP"]); - utils::exec(fmt::format(FMT_COMPILE("loadkeys {}"), keymap)); + gucc::utils::exec(fmt::format(FMT_COMPILE("loadkeys {}"), keymap)); } void enable_autologin([[maybe_unused]] const std::string_view& dm, [[maybe_unused]] const std::string_view& user) noexcept { #ifdef NDEVENV // enable autologin if (dm == "gdm") { - utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^AutomaticLogin=*/AutomaticLogin={}/g' /mnt/etc/gdm/custom.conf"), user)); - utils::exec("sed -i 's/^AutomaticLoginEnable=*/AutomaticLoginEnable=true/g' /mnt/etc/gdm/custom.conf"); - utils::exec("sed -i 's/^TimedLoginEnable=*/TimedLoginEnable=true/g' /mnt/etc/gdm/custom.conf"); - utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^TimedLogin=*/TimedLoginEnable={}/g' /mnt/etc/gdm/custom.conf"), user)); - utils::exec("sed -i 's/^TimedLoginDelay=*/TimedLoginDelay=0/g' /mnt/etc/gdm/custom.conf"); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^AutomaticLogin=*/AutomaticLogin={}/g' /mnt/etc/gdm/custom.conf"), user)); + gucc::utils::exec("sed -i 's/^AutomaticLoginEnable=*/AutomaticLoginEnable=true/g' /mnt/etc/gdm/custom.conf"); + gucc::utils::exec("sed -i 's/^TimedLoginEnable=*/TimedLoginEnable=true/g' /mnt/etc/gdm/custom.conf"); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^TimedLogin=*/TimedLoginEnable={}/g' /mnt/etc/gdm/custom.conf"), user)); + gucc::utils::exec("sed -i 's/^TimedLoginDelay=*/TimedLoginDelay=0/g' /mnt/etc/gdm/custom.conf"); } else if (dm == "lightdm") { - utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^#autologin-user=/autologin-user={}/' /mnt/etc/lightdm/lightdm.conf"), user)); - utils::exec("sed -i 's/^#autologin-user-timeout=0/autologin-user-timeout=0/' /mnt/etc/lightdm/lightdm.conf"); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^#autologin-user=/autologin-user={}/' /mnt/etc/lightdm/lightdm.conf"), user)); + gucc::utils::exec("sed -i 's/^#autologin-user-timeout=0/autologin-user-timeout=0/' /mnt/etc/lightdm/lightdm.conf"); utils::arch_chroot("groupadd -r autologin", false); utils::arch_chroot(fmt::format(FMT_COMPILE("gpasswd -a {} autologin"), user), false); } else if (dm == "sddm") { - utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^User=/User={}/g' /mnt/etc/sddm.conf"), user)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^User=/User={}/g' /mnt/etc/sddm.conf"), user)); } else if (dm == "lxdm") { - utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^# autologin=dgod/autologin={}/g' /mnt/etc/lxdm/lxdm.conf"), user)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i 's/^# autologin=dgod/autologin={}/g' /mnt/etc/lxdm/lxdm.conf"), user)); } #endif } @@ -1862,9 +1790,9 @@ ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue std::ofstream rules{rules_path}; rules << ioscheduler_rules; } - utils::exec("vim /mnt/etc/udev/rules.d/60-ioscheduler.rules", true); + gucc::utils::exec("vim /mnt/etc/udev/rules.d/60-ioscheduler.rules", true); #else - utils::exec("vim /etc/udev/rules.d/60-ioscheduler.rules", true); + gucc::utils::exec("vim /etc/udev/rules.d/60-ioscheduler.rules", true); #endif } @@ -1878,9 +1806,9 @@ vm.vfs_cache_pressure = 50 std::ofstream rules{rules_path}; rules << sysctl_rules; } - utils::exec("vim /mnt/etc/sysctl.d/99-sysctl.conf", true); + gucc::utils::exec("vim /mnt/etc/sysctl.d/99-sysctl.conf", true); #else - utils::exec("vim /etc/sysctl.d/99-sysctl.conf", true); + gucc::utils::exec("vim /etc/sysctl.d/99-sysctl.conf", true); #endif } @@ -2101,27 +2029,27 @@ bool parse_config() noexcept { void setup_luks_keyfile() noexcept { // Add keyfile to luks - const auto& root_name = utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); - const auto& root_part = utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/part/p\" | {} | tr -cd '[:alnum:]'"), root_name, "awk '/part/ {print $1}'")); - const auto& number_of_lukskeys = utils::to_int(utils::exec(fmt::format(FMT_COMPILE("cryptsetup luksDump /dev/\"{}\" | grep \"ENABLED\" | wc -l"), root_part))); + const auto& root_name = gucc::utils::exec("mount | awk '/\\/mnt / {print $1}' | sed s~/dev/mapper/~~g | sed s~/dev/~~g"); + const auto& root_part = gucc::utils::exec(fmt::format(FMT_COMPILE("lsblk -i | tac | sed -r 's/^[^[:alnum:]]+//' | sed -n -e \"/{}/,/part/p\" | {} | tr -cd '[:alnum:]'"), root_name, "awk '/part/ {print $1}'")); + const auto& number_of_lukskeys = utils::to_int(gucc::utils::exec(fmt::format(FMT_COMPILE("cryptsetup luksDump /dev/\"{}\" | grep \"ENABLED\" | wc -l"), root_part))); if (number_of_lukskeys < 4) { // Create a keyfile #ifdef NDEVENV if (!fs::exists("/mnt/crypto_keyfile.bin")) { - const auto& ret_status = utils::exec("dd bs=512 count=4 if=/dev/urandom of=/mnt/crypto_keyfile.bin", true); + const auto& ret_status = gucc::utils::exec("dd bs=512 count=4 if=/dev/urandom of=/mnt/crypto_keyfile.bin", true); /* clang-format off */ if (ret_status == "0") { spdlog::info("Generating a keyfile"); } /* clang-format on */ } - utils::exec("chmod 000 /mnt/crypto_keyfile.bin"); + gucc::utils::exec("chmod 000 /mnt/crypto_keyfile.bin"); spdlog::info("Adding the keyfile to the LUKS configuration"); - auto ret_status = utils::exec(fmt::format(FMT_COMPILE("cryptsetup --pbkdf-force-iterations 200000 luksAddKey /dev/\"{}\" /mnt/crypto_keyfile.bin"), root_part), true); + auto ret_status = gucc::utils::exec(fmt::format(FMT_COMPILE("cryptsetup --pbkdf-force-iterations 200000 luksAddKey /dev/\"{}\" /mnt/crypto_keyfile.bin"), root_part), true); /* clang-format off */ if (ret_status != "0") { spdlog::info("Something went wrong with adding the LUKS key. Is /dev/{} the right partition?", root_part); } /* clang-format on */ // Add keyfile to initcpio - ret_status = utils::exec("grep -q '/crypto_keyfile.bin' /mnt/etc/mkinitcpio.conf || sed -i '/FILES/ s~)~/crypto_keyfile.bin)~' /mnt/etc/mkinitcpio.conf", true); + ret_status = gucc::utils::exec("grep -q '/crypto_keyfile.bin' /mnt/etc/mkinitcpio.conf || sed -i '/FILES/ s~)~/crypto_keyfile.bin)~' /mnt/etc/mkinitcpio.conf", true); /* clang-format off */ if (ret_status == "0") { spdlog::info("Adding keyfile to the initcpio"); } /* clang-format on */ @@ -2149,7 +2077,7 @@ void set_lightdm_greeter() { if (temp == "lightdm-gtk-greeter") { continue; } - utils::exec(fmt::format(FMT_COMPILE("sed -i -e \"s/^.*greeter-session=.*/greeter-session={}/\" {}/etc/lightdm/lightdm.conf"), temp, mountpoint)); + gucc::utils::exec(fmt::format(FMT_COMPILE("sed -i -e \"s/^.*greeter-session=.*/greeter-session={}/\" {}/etc/lightdm/lightdm.conf"), temp, mountpoint)); break; } } @@ -2177,16 +2105,16 @@ void enable_services() noexcept { // enable display manager for systemd const auto& temp = fmt::format(FMT_COMPILE("arch-chroot {} pacman -Qq"), mountpoint); - if (utils::exec(fmt::format(FMT_COMPILE("{} lightdm &> /dev/null"), temp), true) == "0") { + if (gucc::utils::exec(fmt::format(FMT_COMPILE("{} lightdm &> /dev/null"), temp), true) == "0") { utils::set_lightdm_greeter(); utils::arch_chroot("systemctl enable lightdm", false); - } else if (utils::exec(fmt::format(FMT_COMPILE("{} sddm &> /dev/null"), temp), true) == "0") { + } else if (gucc::utils::exec(fmt::format(FMT_COMPILE("{} sddm &> /dev/null"), temp), true) == "0") { utils::arch_chroot("systemctl enable sddm", false); - } else if (utils::exec(fmt::format(FMT_COMPILE("{} gdm &> /dev/null"), temp), true) == "0") { + } else if (gucc::utils::exec(fmt::format(FMT_COMPILE("{} gdm &> /dev/null"), temp), true) == "0") { utils::arch_chroot("systemctl enable gdm", false); - } else if (utils::exec(fmt::format(FMT_COMPILE("{} lxdm &> /dev/null"), temp), true) == "0") { + } else if (gucc::utils::exec(fmt::format(FMT_COMPILE("{} lxdm &> /dev/null"), temp), true) == "0") { utils::arch_chroot("systemctl enable lxdm", false); - } else if (utils::exec(fmt::format(FMT_COMPILE("{} ly &> /dev/null"), temp), true) == "0") { + } else if (gucc::utils::exec(fmt::format(FMT_COMPILE("{} ly &> /dev/null"), temp), true) == "0") { utils::arch_chroot("systemctl enable ly", false); } @@ -2201,8 +2129,8 @@ void enable_services() noexcept { utils::arch_chroot("systemctl enable zfs-import.target", false); // we also need create the cachefile - utils::exec(fmt::format(FMT_COMPILE("zpool set cachefile=/etc/zfs/zpool.cache $(findmnt {} -lno SOURCE | {}) 2>>/tmp/cachyos-install.log"), mountpoint, "awk -F / '{print $1}'"), true); - utils::exec(fmt::format(FMT_COMPILE("cp /etc/zfs/zpool.cache {}/etc/zfs/zpool.cache 2>>/tmp/cachyos-install.log"), mountpoint), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("zpool set cachefile=/etc/zfs/zpool.cache $(findmnt {} -lno SOURCE | {}) 2>>/tmp/cachyos-install.log"), mountpoint, "awk -F / '{print $1}'"), true); + gucc::utils::exec(fmt::format(FMT_COMPILE("cp /etc/zfs/zpool.cache {}/etc/zfs/zpool.cache 2>>/tmp/cachyos-install.log"), mountpoint), true); #endif } @@ -2223,13 +2151,13 @@ void final_check() noexcept { const auto& mountpoint = std::get(config_data["MOUNTPOINT"]); // Check if bootloader is installed if (system_info == "BIOS") { - if (utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} pacman -Qq grub &> /dev/null"), mountpoint), true) != "0") { + if (gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} pacman -Qq grub &> /dev/null"), mountpoint), true) != "0") { checklist += "- Bootloader is not installed\n"; } } // Check if fstab is generated - if (utils::exec(fmt::format(FMT_COMPILE("grep -qv '^#' {}/etc/fstab 2>/dev/null"), mountpoint), true) != "0") { + if (gucc::utils::exec(fmt::format(FMT_COMPILE("grep -qv '^#' {}/etc/fstab 2>/dev/null"), mountpoint), true) != "0") { checklist += "- Fstab has not been generated\n"; } @@ -2237,12 +2165,12 @@ void final_check() noexcept { //[[ ! -e /mnt/.video_installed ]] && echo "- $_GCCheck" >> ${CHECKLIST} // Check if locales have been generated - if (utils::to_int(utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} locale -a | wc -l"), mountpoint), false)) < 3) { + if (utils::to_int(gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} locale -a | wc -l"), mountpoint), false)) < 3) { checklist += "- Locales have not been generated\n"; } // Check if root password has been set - if (utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd --status root | cut -d' ' -f2 | grep -q 'NP'"), mountpoint), true) == "0") { + if (gucc::utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd --status root | cut -d' ' -f2 | grep -q 'NP'"), mountpoint), true) == "0") { checklist += "- Root password is not set\n"; } diff --git a/src/utils.hpp b/src/utils.hpp index 2bd7a0a..8fad763 100644 --- a/src/utils.hpp +++ b/src/utils.hpp @@ -59,10 +59,6 @@ void recheck_luks() noexcept; void arch_chroot(const std::string_view& command, bool follow = true) noexcept; void exec_follow(const std::vector& vec, std::string& process_log, bool& running, subprocess_s& child, bool async = true) noexcept; -void exec(const std::vector& vec) noexcept; -auto exec(const std::string_view& command, const bool& interactive = false) noexcept -> std::string; -[[nodiscard]] auto read_whole_file(const std::string_view& filepath) noexcept -> std::string; -bool write_to_file(const std::string_view& data, const std::string_view& filepath) noexcept; void dump_to_log(const std::string& data) noexcept; void dump_settings_to_log() noexcept; [[nodiscard]] bool check_root() noexcept; diff --git a/tests/unit-exec-interactive.cpp b/tests/unit-exec-interactive.cpp index 66db739..76a9e4e 100644 --- a/tests/unit-exec-interactive.cpp +++ b/tests/unit-exec-interactive.cpp @@ -1,8 +1,11 @@ #include "definitions.hpp" #include "utils.hpp" +// import gucc +#include "gucc/io_utils.hpp" + int main() { output_inter("\n\n------ TEST BASH LAUNCH BEGIN ------\n\n"); - utils::exec("bash", true); + gucc::utils::exec("bash", true); output_inter("\n\n------ TEST BASH LAUNCH END ------\n\n"); }