Introduce config

The config can be used to automatically install
the CachyOS on the target
This commit is contained in:
Vladislav Nepogodin 2022-06-11 04:18:31 +04:00
parent 7fa573d83a
commit 5357735671
No known key found for this signature in database
GPG Key ID: B62C3D10C54D5DA9
15 changed files with 577 additions and 209 deletions

1
.gitignore vendored
View File

@ -13,6 +13,7 @@ subprojects/ftxui
subprojects/nlohmann_json-* subprojects/nlohmann_json-*
subprojects/spdlog subprojects/spdlog
subprojects/simdjson subprojects/simdjson
subprojects/rapidjson
subprojects/range-v3 subprojects/range-v3
subprojects/packagecache subprojects/packagecache

View File

@ -48,9 +48,9 @@ CPMAddPackage(
EXCLUDE_FROM_ALL YES EXCLUDE_FROM_ALL YES
) )
CPMAddPackage( CPMAddPackage(
NAME simdjson NAME rapidjson
GITHUB_REPOSITORY simdjson/simdjson GITHUB_REPOSITORY Tencent/rapidjson
GIT_TAG fbe955e9a449c6bbeae69aacfa995795f2100791 GIT_TAG 232389d4f1012dddec4ef84861face2d2ba85709
EXCLUDE_FROM_ALL YES EXCLUDE_FROM_ALL YES
) )
CPMAddPackage( CPMAddPackage(
@ -94,6 +94,7 @@ add_executable(${PROJECT_NAME}
src/follow_process_log.hpp src/follow_process_log.cpp src/follow_process_log.hpp src/follow_process_log.cpp
src/crypto.cpp src/crypto.hpp src/crypto.cpp src/crypto.hpp
src/misc.cpp src/misc.hpp src/misc.cpp src/misc.hpp
src/simple_tui.cpp src/simple_tui.hpp
src/tui.cpp src/tui.hpp src/tui.cpp src/tui.hpp
src/main.cpp src/main.cpp
) )
@ -105,6 +106,7 @@ add_executable(test-exec-interactive
src/widgets.cpp src/widgets.hpp src/widgets.cpp src/widgets.hpp
src/follow_process_log.hpp src/follow_process_log.cpp src/follow_process_log.hpp src/follow_process_log.cpp
src/crypto.cpp src/crypto.hpp src/crypto.cpp src/crypto.hpp
src/simple_tui.cpp src/simple_tui.hpp
src/tui.cpp src/tui.hpp src/tui.cpp src/tui.hpp
src/main_test.cpp src/main_test.cpp
) )
@ -116,6 +118,7 @@ add_executable(test-process-tailing
src/widgets.cpp src/widgets.hpp src/widgets.cpp src/widgets.hpp
src/follow_process_log.hpp src/follow_process_log.cpp src/follow_process_log.hpp src/follow_process_log.cpp
src/crypto.cpp src/crypto.hpp src/crypto.cpp src/crypto.hpp
src/simple_tui.cpp src/simple_tui.hpp
src/tui.cpp src/tui.hpp src/tui.cpp src/tui.hpp
src/test_proccess_tailing.cpp src/test_proccess_tailing.cpp
) )
@ -132,9 +135,9 @@ enable_sanitizers(project_options)
include_directories(${CMAKE_SOURCE_DIR}/src) include_directories(${CMAKE_SOURCE_DIR}/src)
target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::screen ftxui::dom ftxui::component cpr::cpr range-v3::range-v3)#simdjson::simdjson) target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::screen ftxui::dom ftxui::component cpr::cpr range-v3::range-v3)
target_link_libraries(test-exec-interactive PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr range-v3::range-v3)#simdjson::simdjson) target_link_libraries(test-exec-interactive PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr range-v3::range-v3)
target_link_libraries(test-process-tailing PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr)#simdjson::simdjson) target_link_libraries(test-process-tailing PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component cpr::cpr)
option(ENABLE_UNITY "Enable Unity builds of projects" OFF) option(ENABLE_UNITY "Enable Unity builds of projects" OFF)
if(ENABLE_UNITY) if(ENABLE_UNITY)

View File

@ -36,7 +36,7 @@ endif
spdlog = dependency('spdlog', version : ['>=1.9.2'], fallback : ['spdlog', 'spdlog_dep']) spdlog = dependency('spdlog', version : ['>=1.9.2'], fallback : ['spdlog', 'spdlog_dep'])
fmt = dependency('fmt', version : ['>=8.0.0'], fallback : ['fmt', 'fmt_dep']) fmt = dependency('fmt', version : ['>=8.0.0'], fallback : ['fmt', 'fmt_dep'])
ftxui = dependency('ftxui', modules : ['ftxui::screen', 'ftxui::dom', 'ftxui::component'], fallback : ['ftxui', 'ftxui_dep']) ftxui = dependency('ftxui', modules : ['ftxui::screen', 'ftxui::dom', 'ftxui::component'], fallback : ['ftxui', 'ftxui_dep'])
simdjson = dependency('simdjson', version : ['>=1.0.2'], fallback : ['simdjson', 'simdjson_dep']) rapidjson = dependency('rapidjson', version : ['>=1.1.0'], fallback : ['rapidjson', 'rapidjson_dep'])
cpr = dependency('cpr', version : ['>=1.7.0'], fallback : ['cpr', 'cpr_dep']) cpr = dependency('cpr', version : ['>=1.7.0'], fallback : ['cpr', 'cpr_dep'])
ranges = dependency('range-v3', version : ['>=0.11.0'], fallback : ['range-v3', 'range_dep']) ranges = dependency('range-v3', version : ['>=0.11.0'], fallback : ['range-v3', 'range_dep'])
#glibmm = dependency('glibmm-2.4', version : ['>=2.56.0']) #glibmm = dependency('glibmm-2.4', version : ['>=2.56.0'])
@ -53,6 +53,7 @@ src_files = files(
'src/follow_process_log.cpp', 'src/follow_process_log.hpp', 'src/follow_process_log.cpp', 'src/follow_process_log.hpp',
'src/crypto.cpp', 'src/crypto.hpp', 'src/crypto.cpp', 'src/crypto.hpp',
'src/misc.cpp', 'src/misc.hpp', 'src/misc.cpp', 'src/misc.hpp',
'src/simple_tui.cpp', 'src/simple_tui.hpp',
'src/tui.cpp', 'src/tui.hpp', 'src/tui.cpp', 'src/tui.hpp',
'src/main.cpp', 'src/main.cpp',
) )
@ -122,7 +123,7 @@ endif
add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'cpp') add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'cpp')
deps = [fmt, spdlog, ftxui, cpr, ranges] deps = [fmt, spdlog, ftxui, cpr, ranges, rapidjson]
executable( executable(
'cachyos-installer', 'cachyos-installer',

13
settings.json Normal file
View File

@ -0,0 +1,13 @@
{
"menus": -1,
"fs_name": "btrfs",
"device": "/dev/nvme0n1",
"locale": "en_US",
"user_name": "testuser",
"user_pass": "test",
"user_shell": "/bin/bash",
"root_pass": "secure",
"hostname": "cachyos",
"xkbmap": "us",
"timezone": "America/New_York"
}

View File

@ -16,6 +16,7 @@ bool Config::initialize() noexcept {
s_config = std::make_unique<Config>(); s_config = std::make_unique<Config>();
if (s_config) { if (s_config) {
s_config->m_data["hostcache"] = static_cast<std::int32_t>(!fs::exists("/run/miso/bootmnt")); s_config->m_data["hostcache"] = static_cast<std::int32_t>(!fs::exists("/run/miso/bootmnt"));
s_config->m_data["menus"] = -1;
s_config->m_data["H_INIT"] = "openrc"; s_config->m_data["H_INIT"] = "openrc";
s_config->m_data["SYSTEM"] = "BIOS"; s_config->m_data["SYSTEM"] = "BIOS";

View File

@ -1,4 +1,5 @@
#include "disk.hpp" #include "disk.hpp"
#include "config.hpp"
#include "utils.hpp" #include "utils.hpp"
#include "widgets.hpp" #include "widgets.hpp"
@ -148,7 +149,7 @@ std::string zfs_list_devs() noexcept {
for (const auto& device : devices) { for (const auto& device : devices) {
// add the device // add the device
list_of_devices += fmt::format("{}\n", device); list_of_devices += fmt::format("{}\n", device);
// now lets add any other forms of those devices // now let's add any other forms of those devices
list_of_devices += utils::exec(fmt::format("find -L /dev/ -xtype l -samefile {} 2>/dev/null", device)); list_of_devices += utils::exec(fmt::format("find -L /dev/ -xtype l -samefile {} 2>/dev/null", device));
} }
return list_of_devices; return list_of_devices;
@ -164,4 +165,49 @@ std::string zfs_list_datasets(const std::string_view& type) noexcept {
return utils::exec("zfs list -H -o name 2>/dev/null | grep \"/\""); return utils::exec("zfs list -H -o name 2>/dev/null | grep \"/\"");
} }
// Other filesystems
void select_filesystem(const std::string_view& file_sys) noexcept {
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
config_data["FILESYSTEM_NAME"] = std::string{file_sys.data()};
if (file_sys == "btrfs") {
config_data["FILESYSTEM"] = "mkfs.btrfs -f";
config_data["fs_opts"] = std::vector<std::string>{"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");
#endif
} else if (file_sys == "ext2") {
config_data["FILESYSTEM"] = "mkfs.ext2 -q";
} else if (file_sys == "ext3") {
config_data["FILESYSTEM"] = "mkfs.ext3 -q";
} else if (file_sys == "ext4") {
config_data["FILESYSTEM"] = "mkfs.ext4 -q";
config_data["fs_opts"] = std::vector<std::string>{"data=journal", "data=writeback", "dealloc", "discard", "noacl", "noatime", "nobarrier", "nodelalloc"};
} else if (file_sys == "f2fs") {
config_data["FILESYSTEM"] = "mkfs.f2fs -q";
config_data["fs_opts"] = std::vector<std::string>{"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");
#endif
} else if (file_sys == "jfs") {
config_data["FILESYSTEM"] = "mkfs.jfs -q";
config_data["fs_opts"] = std::vector<std::string>{"discard", "errors=continue", "errors=panic", "nointegrity"};
} else if (file_sys == "nilfs2") {
config_data["FILESYSTEM"] = "mkfs.nilfs2 -fq";
config_data["fs_opts"] = std::vector<std::string>{"discard", "nobarrier", "errors=continue", "errors=panic", "order=relaxed", "order=strict", "norecovery"};
} else if (file_sys == "ntfs") {
config_data["FILESYSTEM"] = "mkfs.ntfs -q";
} else if (file_sys == "reiserfs") {
config_data["FILESYSTEM"] = "mkfs.reiserfs -q";
config_data["fs_opts"] = std::vector<std::string>{"acl", "nolog", "notail", "replayonly", "user_xattr"};
} else if (file_sys == "vfat") {
config_data["FILESYSTEM"] = "mkfs.vfat -F32";
} else if (file_sys == "xfs") {
config_data["FILESYSTEM"] = "mkfs.xfs -f";
config_data["fs_opts"] = std::vector<std::string>{"discard", "filestreams", "ikeep", "largeio", "noalign", "nobarrier", "norecovery", "noquota", "wsync"};
}
}
} // namespace utils } // namespace utils

View File

@ -22,6 +22,9 @@ void zfs_create_dataset(const std::string_view& zpath, const std::string_view& z
std::string zfs_list_devs() noexcept; std::string zfs_list_devs() noexcept;
std::string zfs_list_datasets(const std::string_view& type = "none") noexcept; std::string zfs_list_datasets(const std::string_view& type = "none") noexcept;
// Other filesystems
void select_filesystem(const std::string_view& fs) noexcept;
} // namespace utils } // namespace utils
#endif // DISK_HPP #endif // DISK_HPP

173
src/simple_tui.cpp Normal file
View File

@ -0,0 +1,173 @@
#include "simple_tui.hpp"
#include "config.hpp"
#include "disk.hpp"
#include "tui.hpp"
#include "utils.hpp"
#include "widgets.hpp"
/* clang-format off */
#include <cstdlib> // for setenv
#include <sys/mount.h> // for mount
#include <fstream> // for ofstream
#include <algorithm> // for copy
#include <thread> // for thread
#include <filesystem> // for exists, is_directory
#include <string> // for basic_string
#include <ftxui/component/component.hpp> // for Renderer, Button
#include <ftxui/component/screen_interactive.hpp> // for Component, ScreenI...
#include <ftxui/dom/elements.hpp> // for operator|, size
/* clang-format on */
#include <fmt/ranges.h>
using namespace ftxui;
namespace {
// Set static list of filesystems rather than on-the-fly. Partially as most require additional flags, and
// partially because some don't seem to be viable.
// Set static list of filesystems rather than on-the-fly.
void select_filesystem() noexcept {
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
// prep variables
config_data["fs_opts"] = std::vector<std::string>{};
const std::vector<std::string> menu_entries = {
"btrfs",
"ext3",
"ext4",
"f2fs",
"jfs",
"nilfs2",
"ntfs",
"reiserfs",
"vfat",
"xfs",
};
auto screen = ScreenInteractive::Fullscreen();
std::int32_t selected{};
bool success{};
auto ok_callback = [&] {
const auto& src = menu_entries[static_cast<std::size_t>(selected)];
const auto& lines = utils::make_multiline(src, false, " ");
const auto& file_sys = lines[0];
utils::select_filesystem(file_sys.c_str());
success = true;
screen.ExitLoopClosure()();
};
static constexpr auto filesystem_body = "\nSelect your filesystem\n";
const auto& content_size = size(HEIGHT, LESS_THAN, 10) | size(WIDTH, GREATER_THAN, 40);
tui::detail::menu_widget(menu_entries, ok_callback, &selected, &screen, filesystem_body, {size(HEIGHT, LESS_THAN, 18), content_size});
if (!success) {
utils::select_filesystem("btrfs");
}
}
} // namespace
namespace tui {
void menu_simple() noexcept {
// Prepare
utils::umount_partitions();
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
const auto& device_info = std::get<std::string>(config_data["DEVICE"]);
const auto& fs_name = std::get<std::string>(config_data["FILESYSTEM_NAME"]);
const auto& mount_opts_info = std::get<std::string>(config_data["MOUNT_OPTS"]);
const auto& hostname = std::get<std::string>(config_data["HOSTNAME"]);
const auto& locale = std::get<std::string>(config_data["LOCALE"]);
const auto& xkbmap = std::get<std::string>(config_data["XKBMAP"]);
const auto& timezone = std::get<std::string>(config_data["TIMEZONE"]);
const auto& user_name = std::get<std::string>(config_data["USER_NAME"]);
const auto& user_pass = std::get<std::string>(config_data["USER_PASS"]);
const auto& user_shell = std::get<std::string>(config_data["USER_SHELL"]);
const auto& root_pass = std::get<std::string>(config_data["ROOT_PASS"]);
if (device_info.empty()) {
tui::select_device();
}
tui::auto_partition(false);
// Target FS
if (fs_name.empty()) {
select_filesystem();
} else {
utils::select_filesystem(fs_name);
}
tui::mount_current_partition(true);
/* clang-format on */
utils::generate_fstab("genfstab -U");
if (hostname.empty()) {
tui::set_hostname();
} else {
utils::set_hostname(hostname);
}
if (locale.empty()) {
tui::set_locale();
} else {
utils::set_locale(locale);
}
if (xkbmap.empty()) {
tui::set_xkbmap();
} else {
utils::set_xkbmap(xkbmap);
}
if (timezone.empty()) {
tui::set_timezone();
} else {
utils::set_timezone(timezone);
}
utils::set_hw_clock("utc");
if (root_pass.empty()) {
tui::set_root_password();
} else {
utils::set_root_password(root_pass);
}
if (user_name.empty()) {
tui::create_new_user();
} else {
utils::create_new_user(user_name, user_pass, user_shell);
}
fmt::print("┌{0:─^{5}}┐\n"
"│{1: ^{5}}│\n"
"│{2: ^{5}}│\n"
"│{3: ^{5}}│\n"
"│{4: ^{5}}│\n"
"└{0:─^{5}}┘\n",
"",
fmt::format("Mountpoint: {}", mountpoint),
fmt::format("Your device: {}", device_info),
fmt::format("Filesystem: {}", fs_name),
fmt::format("Filesystem opts: {}", mount_opts_info), 80);
// tui::mount_partitions();
//
// // Install process
// if (!utils::check_mount()) {
// spdlog::error("Your partitions are not mounted");
// }
// tui::install_base();
// tui::install_desktop();
// if (!utils::check_base()) {
// spdlog::error("Base is not installed");
// }
// tui::install_bootloader();
// tui::config_base_menu();
}
} // namespace tui

8
src/simple_tui.hpp Normal file
View File

@ -0,0 +1,8 @@
#ifndef SIMPLE_TUI_HPP
#define SIMPLE_TUI_HPP
namespace tui {
void menu_simple() noexcept;
} // namespace tui
#endif // SIMPLE_TUI_HPP

View File

@ -5,6 +5,7 @@
#include "disk.hpp" #include "disk.hpp"
#include "drivers.hpp" #include "drivers.hpp"
#include "misc.hpp" #include "misc.hpp"
#include "simple_tui.hpp"
#include "utils.hpp" #include "utils.hpp"
#include "widgets.hpp" #include "widgets.hpp"
@ -127,6 +128,7 @@ void generate_fstab() noexcept {
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]); const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
auto screen = ScreenInteractive::Fullscreen(); auto screen = ScreenInteractive::Fullscreen();
std::string fstab_cmd{};
std::int32_t selected{}; std::int32_t selected{};
auto ok_callback = [&] { auto ok_callback = [&] {
if (system_info == "BIOS" && selected == 3) { if (system_info == "BIOS" && selected == 3) {
@ -134,36 +136,17 @@ void generate_fstab() noexcept {
detail::msgbox_widget(FstabErr); detail::msgbox_widget(FstabErr);
return; return;
} }
#ifdef NDEVENV fstab_cmd = menu_entries[static_cast<std::size_t>(selected)];
const auto& src = menu_entries[static_cast<std::size_t>(selected)];
utils::exec(fmt::format(FMT_COMPILE("{0} {1} > {1}/etc/fstab"), src, mountpoint));
spdlog::info("Created fstab file:\n");
utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab >> /tmp/cachyos-install.log"), mountpoint));
#endif
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..");
#ifdef NDEVENV
utils::exec(fmt::format(FMT_COMPILE("sed -i \"s/\\\\{0}//\" {0}/etc/fstab"), mountpoint));
#endif
}
screen.ExitLoopClosure()(); screen.ExitLoopClosure()();
}; };
/* clang-format off */
if (fstab_cmd.empty()) { return; }
/* clang-format on */
utils::generate_fstab(fstab_cmd);
static constexpr auto fstab_body = "\nThe FSTAB file (File System TABle) sets what storage devices\nand partitions are to be mounted, and how they are to be used.\n\nUUID (Universally Unique IDentifier) is recommended.\n\nIf no labels were set for the partitions earlier,\ndevice names will be used for the label option.\n"; static constexpr auto fstab_body = "\nThe FSTAB file (File System TABle) sets what storage devices\nand partitions are to be mounted, and how they are to be used.\n\nUUID (Universally Unique IDentifier) is recommended.\n\nIf no labels were set for the partitions earlier,\ndevice names will be used for the label option.\n";
detail::menu_widget(menu_entries, ok_callback, &selected, &screen, fstab_body); detail::menu_widget(menu_entries, ok_callback, &selected, &screen, fstab_body);
#ifdef NDEVENV
// Edit fstab in case of btrfs subvolumes
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 = utils::make_multiline(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));
}
#endif
} }
// Set system hostname // Set system hostname
@ -178,14 +161,7 @@ void set_hostname() noexcept {
if (hostname.empty()) { return; } if (hostname.empty()) { return; }
/* clang-format on */ /* clang-format on */
#ifdef NDEVENV utils::set_hostname(hostname);
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" > {}/etc/hostname"), hostname, mountpoint));
const auto& cmd = fmt::format(FMT_COMPILE("echo -e \"#<ip-address>\\t<hostname.domain.org>\\t<hostname>\\n127.0.0.1\\tlocalhost.localdomain\\tlocalhost\\t{0}\\n::1\\tlocalhost.localdomain\\tlocalhost\\t{0}\">{1}/etc/hosts"), hostname, mountpoint);
utils::exec(cmd);
#endif
} }
// Set system language // Set system language
@ -210,33 +186,7 @@ void set_locale() noexcept {
if (locale.empty()) { return; } if (locale.empty()) { return; }
/* clang-format on */ /* clang-format on */
#ifdef NDEVENV utils::set_locale(locale);
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
const auto& locale_config_path = fmt::format(FMT_COMPILE("{}/etc/locale.conf"), mountpoint);
const auto& locale_gen_path = fmt::format(FMT_COMPILE("{}/etc/locale.gen"), mountpoint);
static constexpr auto locale_config_part = R"(LANG="{0}"
LC_NUMERIC="{0}"
LC_TIME="{0}"
LC_MONETARY="{0}"
LC_PAPER="{0}"
LC_NAME="{0}"
LC_ADDRESS="{0}"
LC_TELEPHONE="{0}"
LC_MEASUREMENT="{0}"
LC_IDENTIFICATION="{0}"
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));
// Generate locales
utils::arch_chroot("locale-gen", false);
#endif
} }
// Set keymap for X11 // Set keymap for X11
@ -263,13 +213,7 @@ void set_xkbmap() noexcept {
if (!success) { return; } if (!success) { return; }
/* clang-format on */ /* clang-format on */
#ifdef NDEVENV utils::set_xkbmap(xkbmap_choice);
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(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_choice, mountpoint));
#endif
} }
void select_keymap() noexcept { void select_keymap() noexcept {
@ -347,10 +291,8 @@ bool set_timezone() noexcept {
if (!do_set_timezone) { return false; } if (!do_set_timezone) { return false; }
/* clang-format on */ /* clang-format on */
#ifdef NDEVENV utils::set_timezone(fmt::format(FMT_COMPILE("{}/{}"), zone, subzone));
utils::arch_chroot(fmt::format(FMT_COMPILE("ln -sf /usr/share/zoneinfo/{}/{} /etc/localtime"), zone, subzone), false);
#endif
spdlog::info("Timezone is set to {}/{}", zone, subzone);
return true; return true;
} }
@ -360,10 +302,8 @@ void set_hw_clock() noexcept {
const std::vector<std::string> menu_entries{"utc", "localtime"}; const std::vector<std::string> menu_entries{"utc", "localtime"};
std::int32_t selected{}; std::int32_t selected{};
auto ok_callback = [&] { auto ok_callback = [&] {
#ifdef NDEVENV
const auto& clock_type = menu_entries[static_cast<std::size_t>(selected)]; const auto& clock_type = menu_entries[static_cast<std::size_t>(selected)];
utils::arch_chroot(fmt::format(FMT_COMPILE("hwclock --systohc --{}"), clock_type), false); utils::set_hw_clock(clock_type);
#endif
screen.ExitLoopClosure()(); screen.ExitLoopClosure()();
}; };
@ -390,17 +330,7 @@ void set_root_password() noexcept {
detail::msgbox_widget(PassErrBody); detail::msgbox_widget(PassErrBody);
tui::set_root_password(); tui::set_root_password();
} }
utils::set_root_password(pass);
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
std::error_code err{};
utils::exec(fmt::format(FMT_COMPILE("echo -e \"{}\n{}\" > /tmp/.passwd"), pass, confirm));
utils::exec(fmt::format(FMT_COMPILE("arch-chroot {} passwd root < /tmp/.passwd &>/dev/null"), mountpoint));
fs::remove("/tmp/.passwd", err);
#endif
} }
// Create user on the system // Create user on the system
@ -420,12 +350,6 @@ void create_new_user() noexcept {
} }
} }
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
#endif
std::string_view shell{}; std::string_view shell{};
{ {
static constexpr auto DefShell = "\nChoose the default shell.\n"; static constexpr auto DefShell = "\nChoose the default shell.\n";
@ -455,19 +379,8 @@ void create_new_user() noexcept {
screen.ExitLoopClosure()(); screen.ExitLoopClosure()();
}; };
detail::radiolist_widget(radiobox_list, ok_callback, &selected, &screen, {.text = shells_options_body}, {.text_size = nothing}); detail::radiolist_widget(radiobox_list, ok_callback, &selected, &screen, {.text = shells_options_body}, {.text_size = nothing});
#ifdef NDEVENV
if (selected != 1) {
const auto& packages = fmt::format(FMT_COMPILE("cachyos-{}-config"), (selected == 0) ? "zsh" : "fish");
const auto& hostcache = std::get<std::int32_t>(config_data["hostcache"]);
const auto& cmd = (hostcache) ? "pacstrap" : "pacstrap -c";
detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format(FMT_COMPILE("{} {} {} |& tee /tmp/pacstrap.log"), cmd, mountpoint, packages)});
}
#endif
} }
spdlog::info("default shell: [{}]", shell);
// Enter password. This step will only be reached where the loop has been skipped or broken. // Enter password. This step will only be reached where the loop has been skipped or broken.
std::string pass{}; std::string pass{};
static constexpr auto user_pass_body = "Enter password for"; static constexpr auto user_pass_body = "Enter password for";
@ -497,32 +410,7 @@ void create_new_user() noexcept {
detail::infobox_widget("\nCreating User and setting groups...\n"); detail::infobox_widget("\nCreating User and setting groups...\n");
std::this_thread::sleep_for(std::chrono::seconds(2)); std::this_thread::sleep_for(std::chrono::seconds(2));
#ifdef NDEVENV utils::create_new_user(user, pass, shell);
// Create the user, set password, then remove temporary password file
utils::arch_chroot("groupadd sudo", false);
utils::arch_chroot(fmt::format(FMT_COMPILE("groupadd {}"), user), false);
utils::arch_chroot(fmt::format(FMT_COMPILE("useradd {0} -m -g {0} -G sudo,storage,power,network,video,audio,lp,sys,input -s {1}"), user, shell), false);
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));
if (user_check.empty()) {
spdlog::error("User has not been created!");
}
std::error_code err{};
utils::exec(fmt::format(FMT_COMPILE("echo -e \"{}\\n{}\" > /tmp/.passwd"), pass, confirm));
const auto& ret_status = 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);
// Set up basic configuration files and permissions for user
// arch_chroot "cp /etc/skel/.bashrc /home/${USER}"
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));
}
#endif
} }
// Install pkgs from user input // Install pkgs from user input
@ -1441,7 +1329,7 @@ void install_bootloader() noexcept {
} }
// BIOS and UEFI // BIOS and UEFI
void auto_partition() noexcept { void auto_partition(bool interactive) noexcept {
auto* config_instance = Config::instance(); auto* config_instance = Config::instance();
auto& config_data = config_instance->data(); auto& config_data = config_instance->data();
@ -1488,6 +1376,10 @@ void auto_partition() noexcept {
utils::exec(fmt::format(FMT_COMPILE("parted -s {} mkpart primary ext3 513MiB 100% 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));
#endif #endif
/* clang-format off */
if (!interactive) { return; }
/* clang-format on */
// Show created partitions // 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 = utils::exec(fmt::format(FMT_COMPILE("lsblk {} -o NAME,TYPE,FSTYPE,SIZE"), device_info));
detail::msgbox_widget(disk_list, size(HEIGHT, GREATER_THAN, 5)); detail::msgbox_widget(disk_list, size(HEIGHT, GREATER_THAN, 5));
@ -1533,7 +1425,6 @@ bool select_device() noexcept {
// Set static list of filesystems rather than on-the-fly. Partially as most require additional flags, and // Set static list of filesystems rather than on-the-fly. Partially as most require additional flags, and
// partially because some don't seem to be viable. // partially because some don't seem to be viable.
// Set static list of filesystems rather than on-the-fly.
bool select_filesystem() noexcept { bool select_filesystem() noexcept {
auto* config_instance = Config::instance(); auto* config_instance = Config::instance();
auto& config_data = config_instance->data(); auto& config_data = config_instance->data();
@ -1562,42 +1453,7 @@ bool select_filesystem() noexcept {
const auto& src = menu_entries[static_cast<std::size_t>(selected)]; const auto& src = menu_entries[static_cast<std::size_t>(selected)];
const auto& lines = utils::make_multiline(src, false, " "); const auto& lines = utils::make_multiline(src, false, " ");
const auto& file_sys = lines[0]; const auto& file_sys = lines[0];
if (file_sys == "btrfs") { utils::select_filesystem(file_sys.c_str());
config_data["FILESYSTEM"] = "mkfs.btrfs -f";
config_data["fs_opts"] = std::vector<std::string>{"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");
#endif
} else if (file_sys == "ext2") {
config_data["FILESYSTEM"] = "mkfs.ext2 -q";
} else if (file_sys == "ext3") {
config_data["FILESYSTEM"] = "mkfs.ext3 -q";
} else if (file_sys == "ext4") {
config_data["FILESYSTEM"] = "mkfs.ext4 -q";
config_data["fs_opts"] = std::vector<std::string>{"data=journal", "data=writeback", "dealloc", "discard", "noacl", "noatime", "nobarrier", "nodelalloc"};
} else if (file_sys == "f2fs") {
config_data["FILESYSTEM"] = "mkfs.f2fs -q";
config_data["fs_opts"] = std::vector<std::string>{"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");
#endif
} else if (file_sys == "jfs") {
config_data["FILESYSTEM"] = "mkfs.jfs -q";
config_data["fs_opts"] = std::vector<std::string>{"discard", "errors=continue", "errors=panic", "nointegrity"};
} else if (file_sys == "nilfs2") {
config_data["FILESYSTEM"] = "mkfs.nilfs2 -fq";
config_data["fs_opts"] = std::vector<std::string>{"discard", "nobarrier", "errors=continue", "errors=panic", "order=relaxed", "order=strict", "norecovery"};
} else if (file_sys == "ntfs") {
config_data["FILESYSTEM"] = "mkfs.ntfs -q";
} else if (file_sys == "reiserfs") {
config_data["FILESYSTEM"] = "mkfs.reiserfs -q";
config_data["fs_opts"] = std::vector<std::string>{"acl", "nolog", "notail", "replayonly", "user_xattr"};
} else if (file_sys == "vfat") {
config_data["FILESYSTEM"] = "mkfs.vfat -F32";
} else if (file_sys == "xfs") {
config_data["FILESYSTEM"] = "mkfs.xfs -f";
config_data["fs_opts"] = std::vector<std::string>{"discard", "filestreams", "ikeep", "largeio", "noalign", "nobarrier", "norecovery", "noquota", "wsync"};
}
success = true; success = true;
screen.ExitLoopClosure()(); screen.ExitLoopClosure()();
}; };
@ -1625,7 +1481,7 @@ bool select_filesystem() noexcept {
// This subfunction allows for special mounting options to be applied for relevant fs's. // This subfunction allows for special mounting options to be applied for relevant fs's.
// Separate subfunction for neatness. // Separate subfunction for neatness.
void mount_opts() noexcept { void mount_opts(bool force) noexcept {
auto* config_instance = Config::instance(); auto* config_instance = Config::instance();
auto& config_data = config_instance->data(); auto& config_data = config_instance->data();
@ -1657,9 +1513,22 @@ void mount_opts() noexcept {
/* clang-format on */ /* clang-format on */
} }
auto screen = ScreenInteractive::Fullscreen();
auto& mount_opts_info = std::get<std::string>(config_data["MOUNT_OPTS"]); auto& mount_opts_info = std::get<std::string>(config_data["MOUNT_OPTS"]);
auto ok_callback = [&] {
// 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));
};
if (force) {
mount_opts_info = detail::from_checklist_string(fs_opts, fs_opts_state.get());
cleaup_mount_opts(mount_opts_info);
return;
}
auto screen = ScreenInteractive::Fullscreen();
auto ok_callback = [&] {
mount_opts_info = detail::from_checklist_string(fs_opts, fs_opts_state.get()); mount_opts_info = detail::from_checklist_string(fs_opts, fs_opts_state.get());
screen.ExitLoopClosure()(); screen.ExitLoopClosure()();
}; };
@ -1670,10 +1539,7 @@ void mount_opts() noexcept {
static constexpr auto mount_options_body = "\nUse [Space] to de/select the desired mount\noptions and review carefully. Please do not\nselect multiple versions of the same option.\n"; static constexpr auto mount_options_body = "\nUse [Space] to de/select the desired mount\noptions and review carefully. Please do not\nselect multiple versions of the same option.\n";
detail::checklist_widget(fs_opts, ok_callback, fs_opts_state.get(), &screen, mount_options_body, fs_title, {content_size, nothing}); detail::checklist_widget(fs_opts, ok_callback, fs_opts_state.get(), &screen, mount_options_body, fs_title, {content_size, nothing});
cleaup_mount_opts(mount_opts_info);
// Now clean up the file
mount_opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed 's/ /,/g'"), mount_opts_info));
mount_opts_info = utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" | sed '$s/,$//'"), mount_opts_info));
// If mount options selected, confirm choice // If mount options selected, confirm choice
if (!mount_opts_info.empty()) { if (!mount_opts_info.empty()) {
@ -1688,7 +1554,7 @@ void mount_opts() noexcept {
} }
} }
bool mount_current_partition() noexcept { bool mount_current_partition(bool force) noexcept {
auto* config_instance = Config::instance(); auto* config_instance = Config::instance();
auto& config_data = config_instance->data(); auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]); const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
@ -1706,7 +1572,7 @@ bool mount_current_partition() noexcept {
/* clang-format off */ /* clang-format off */
// Get mounting options for appropriate filesystems // Get mounting options for appropriate filesystems
const auto& fs_opts = std::get<std::vector<std::string>>(config_data["fs_opts"]); const auto& fs_opts = std::get<std::vector<std::string>>(config_data["fs_opts"]);
if (!fs_opts.empty()) { mount_opts(); } if (!fs_opts.empty()) { mount_opts(force); }
/* clang-format on */ /* clang-format on */
// TODO: use libmount instead. // TODO: use libmount instead.
@ -1723,7 +1589,10 @@ bool mount_current_partition() noexcept {
spdlog::info("{}", mount_status); spdlog::info("{}", mount_status);
} }
#endif #endif
confirm_mount(fmt::format(FMT_COMPILE("{}{}"), mountpoint, mount_dev));
/* clang-format off */
if (!force) { confirm_mount(fmt::format(FMT_COMPILE("{}{}"), mountpoint, mount_dev)); }
/* clang-format on */
// Identify if mounted partition is type "crypt" (LUKS on LVM, or LUKS alone) // 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 (!utils::exec(fmt::format(FMT_COMPILE("lsblk -lno TYPE {} | grep \"crypt\""), partition)).empty()) {
@ -2828,29 +2697,20 @@ void menu_advanced() noexcept {
detail::menu_widget(menu_entries, ok_callback, &selected, &screen); detail::menu_widget(menu_entries, ok_callback, &selected, &screen);
} }
void menu_simple() noexcept {
// Prepare
utils::umount_partitions();
if (tui::select_device()) {
tui::create_partitions();
}
tui::mount_partitions();
// Install process
if (!utils::check_mount()) {
spdlog::error("Your partitions are not mounted");
}
tui::install_base();
tui::install_desktop();
if (!utils::check_base()) {
spdlog::error("Base is not installed");
}
tui::install_bootloader();
tui::config_base_menu();
}
void init() noexcept { void init() noexcept {
#if 0 auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& menus = std::get<std::int32_t>(config_data["menus"]);
utils::parse_config();
if (menus == 1) {
tui::menu_simple();
return;
} else if (menus == 2) {
tui::menu_advanced();
return;
}
const std::vector<std::string> menu_entries = { const std::vector<std::string> menu_entries = {
"Simple installation", "Simple installation",
"Advanced installation", "Advanced installation",
@ -2878,8 +2738,6 @@ void init() noexcept {
default: default:
break; break;
} }
#endif
tui::menu_advanced();
} }
} // namespace tui } // namespace tui

View File

@ -2,6 +2,15 @@
#define TUI_HPP #define TUI_HPP
namespace tui { namespace tui {
void set_hostname() noexcept;
void set_locale() noexcept;
void set_xkbmap() noexcept;
bool set_timezone() noexcept;
void create_new_user() noexcept;
void set_root_password() noexcept;
void mount_opts(bool force = false) noexcept;
bool mount_current_partition(bool force = false) noexcept;
void auto_partition(bool interactive = true) noexcept;
void create_partitions() noexcept; void create_partitions() noexcept;
bool select_device() noexcept; bool select_device() noexcept;
void init() noexcept; void init() noexcept;

View File

@ -39,6 +39,9 @@
#include <range/v3/view/split.hpp> #include <range/v3/view/split.hpp>
#include <range/v3/view/transform.hpp> #include <range/v3/view/transform.hpp>
#include <rapidjson/document.h>
#include <rapidjson/istreamwrapper.h>
#if defined(__clang__) #if defined(__clang__)
#pragma clang diagnostic pop #pragma clang diagnostic pop
#elif defined(__GNUC__) #elif defined(__GNUC__)
@ -306,6 +309,160 @@ void secure_wipe() noexcept {
#endif #endif
} }
void generate_fstab(const std::string_view& fstab_cmd) noexcept {
spdlog::info("Generating with fstab '{}'", fstab_cmd);
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
utils::exec(fmt::format(FMT_COMPILE("{0} {1} > {1}/etc/fstab"), fstab_cmd, mountpoint));
spdlog::info("Created fstab file:\n");
utils::exec(fmt::format(FMT_COMPILE("cat {}/etc/fstab >> /tmp/cachyos-install.log"), mountpoint));
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));
}
// Edit fstab in case of btrfs subvolumes
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 = utils::make_multiline(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));
}
#endif
}
// Set system hostname
void set_hostname(const std::string_view& hostname) noexcept {
spdlog::info("Setting hostname {}", hostname);
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
utils::exec(fmt::format(FMT_COMPILE("echo \"{}\" > {}/etc/hostname"), hostname, mountpoint));
const auto& cmd = fmt::format(FMT_COMPILE("echo -e \"#<ip-address>\\t<hostname.domain.org>\\t<hostname>\\n127.0.0.1\\tlocalhost.localdomain\\tlocalhost\\t{0}\\n::1\\tlocalhost.localdomain\\tlocalhost\\t{0}\">{1}/etc/hosts"), hostname, mountpoint);
utils::exec(cmd);
#endif
}
// Set system language
void set_locale(const std::string_view& locale) noexcept {
spdlog::info("Selected locale: {}", locale);
#ifdef NDEVENV
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
const auto& locale_config_path = fmt::format(FMT_COMPILE("{}/etc/locale.conf"), mountpoint);
const auto& locale_gen_path = fmt::format(FMT_COMPILE("{}/etc/locale.gen"), mountpoint);
static constexpr auto locale_config_part = R"(LANG="{0}"
LC_NUMERIC="{0}"
LC_TIME="{0}"
LC_MONETARY="{0}"
LC_PAPER="{0}"
LC_NAME="{0}"
LC_ADDRESS="{0}"
LC_TELEPHONE="{0}"
LC_MEASUREMENT="{0}"
LC_IDENTIFICATION="{0}"
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));
// Generate locales
utils::arch_chroot("locale-gen", false);
#endif
}
void set_xkbmap(const std::string_view& xkbmap) noexcept {
spdlog::info("Selected xkbmap: {}", xkbmap);
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(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));
#endif
}
void set_timezone(const std::string_view& timezone) noexcept {
spdlog::info("Timezone is set to {}", timezone);
#ifdef NDEVENV
utils::arch_chroot(fmt::format(FMT_COMPILE("ln -sf /usr/share/zoneinfo/{} /etc/localtime"), timezone), false);
#endif
}
void set_hw_clock(const std::string_view& clock_type) noexcept {
spdlog::info("Clock type is: {}", clock_type);
#ifdef NDEVENV
utils::arch_chroot(fmt::format(FMT_COMPILE("hwclock --systohc --{}"), clock_type), false);
#endif
}
// Create user on the system
void create_new_user(const std::string_view& user, const std::string_view& password, const std::string_view& shell) noexcept {
spdlog::info("default shell: [{}]", shell);
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(config_data["MOUNTPOINT"]);
if (shell.ends_with("zsh") || shell.ends_with("fish")) {
const auto& packages = fmt::format(FMT_COMPILE("cachyos-{}-config"), (shell.ends_with("zsh")) ? "zsh" : "fish");
const auto& hostcache = std::get<std::int32_t>(config_data["hostcache"]);
const auto& cmd = (hostcache) ? "pacstrap" : "pacstrap -c";
tui::detail::follow_process_log_widget({"/bin/sh", "-c", fmt::format(FMT_COMPILE("{} {} {} |& tee /tmp/pacstrap.log"), cmd, mountpoint, packages)});
}
// Create the user, set password, then remove temporary password file
utils::arch_chroot("groupadd sudo", false);
utils::arch_chroot(fmt::format(FMT_COMPILE("groupadd {}"), user), false);
utils::arch_chroot(fmt::format(FMT_COMPILE("useradd {0} -m -g {0} -G sudo,storage,power,network,video,audio,lp,sys,input -s {1}"), user, shell), false);
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));
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);
spdlog::info("create user pwd: {}", ret_status);
fs::remove("/tmp/.passwd", err);
// Set up basic configuration files and permissions for user
// arch_chroot "cp /etc/skel/.bashrc /home/${USER}"
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));
}
#endif
}
// Set password for root user
void set_root_password([[maybe_unused]] const std::string_view& password) noexcept {
#ifdef NDEVENV
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mountpoint = std::get<std::string>(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));
fs::remove("/tmp/.passwd", err);
#endif
}
// Finds all available partitions according to type(s) specified and generates a list // Finds all available partitions according to type(s) specified and generates a list
// of them. This also includes partitions on different devices. // of them. This also includes partitions on different devices.
void find_partitions() noexcept { void find_partitions() noexcept {
@ -751,6 +908,81 @@ vm.vfs_cache_pressure = 50
} }
void parse_config() noexcept { void parse_config() noexcept {
using namespace rapidjson;
// 1. Open file for reading.
static constexpr auto file_path = "settings.json";
std::ifstream ifs{file_path};
if (!ifs.is_open()) {
fmt::print(stderr, "Config not found running with defaults");
return;
}
IStreamWrapper isw{ifs};
// 2. Parse a JSON.
Document doc;
doc.ParseStream(isw);
// Document is a JSON value represents the root of DOM. Root can be either an object or array.
assert(doc.IsObject());
assert(doc.HasMember("menus"));
assert(doc["menus"].IsInt());
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
config_data["menus"] = doc["menus"].GetInt();
if (doc.HasMember("device")) {
assert(doc["device"].IsString());
config_data["DEVICE"] = std::string{doc["device"].GetString()};
}
if (doc.HasMember("fs_name")) {
assert(doc["fs_name"].IsString());
config_data["FILESYSTEM_NAME"] = std::string{doc["fs_name"].GetString()};
}
if (doc.HasMember("mount_opts")) {
assert(doc["mount_opts"].IsString());
config_data["MOUNT_OPTS"] = std::string{doc["mount_opts"].GetString()};
}
if (doc.HasMember("hostname")) {
assert(doc["hostname"].IsString());
config_data["HOSTNAME"] = std::string{doc["hostname"].GetString()};
}
if (doc.HasMember("locale")) {
assert(doc["locale"].IsString());
config_data["LOCALE"] = std::string{doc["locale"].GetString()};
}
if (doc.HasMember("xkbmap")) {
assert(doc["xkbmap"].IsString());
config_data["XKBMAP"] = std::string{doc["xkbmap"].GetString()};
}
if (doc.HasMember("timezone")) {
assert(doc["timezone"].IsString());
config_data["TIMEZONE"] = std::string{doc["timezone"].GetString()};
}
if (doc.HasMember("user_name") && doc.HasMember("user_pass") && doc.HasMember("user_shell")) {
assert(doc["user_name"].IsString());
assert(doc["user_pass"].IsString());
assert(doc["user_shell"].IsString());
config_data["USER_NAME"] = std::string{doc["user_name"].GetString()};
config_data["USER_PASS"] = std::string{doc["user_pass"].GetString()};
config_data["USER_SHELL"] = std::string{doc["user_shell"].GetString()};
}
if (doc.HasMember("root_pass")) {
assert(doc["root_pass"].IsString());
config_data["ROOT_PASS"] = std::string{doc["root_pass"].GetString()};
}
/* /*
using namespace simdjson; using namespace simdjson;

View File

@ -20,6 +20,14 @@ void clear_screen() noexcept;
[[nodiscard]] auto make_multiline(std::vector<std::string>& multiline, bool reverse = false, const std::string_view&& delim = "\n") noexcept -> std::string; [[nodiscard]] auto make_multiline(std::vector<std::string>& multiline, bool reverse = false, const std::string_view&& delim = "\n") noexcept -> std::string;
void inst_needed(const std::string_view& pkg) noexcept; void inst_needed(const std::string_view& pkg) noexcept;
void secure_wipe() noexcept; void secure_wipe() noexcept;
void generate_fstab(const std::string_view& fstab_cmd) noexcept;
void set_hostname(const std::string_view& hostname) noexcept;
void set_locale(const std::string_view& locale) noexcept;
void set_xkbmap(const std::string_view& xkbmap) noexcept;
void set_timezone(const std::string_view& timezone) noexcept;
void set_hw_clock(const std::string_view& clock_type) noexcept;
void create_new_user(const std::string_view& user, const std::string_view& password, const std::string_view& shell) noexcept;
void set_root_password(const std::string_view& password) noexcept;
[[nodiscard]] bool check_mount() noexcept; [[nodiscard]] bool check_mount() noexcept;
[[nodiscard]] bool check_base() noexcept; [[nodiscard]] bool check_base() noexcept;
[[nodiscard]] std::string list_mounted() noexcept; [[nodiscard]] std::string list_mounted() noexcept;

View File

@ -0,0 +1,4 @@
project('rapidjson', 'cpp', version: '1.1.0', license: 'MIT')
rapidjson_inc = include_directories('include')
rapidjson_dep = declare_dependency(include_directories: rapidjson_inc)

View File

@ -0,0 +1,8 @@
[wrap-git]
url = https://github.com/Tencent/rapidjson.git
revision = 232389d4f1012dddec4ef84861face2d2ba85709
patch_directory = rapidjson
[provide]
rapidjson = rapidjson_dep