👷 add btrfs subvolumes

This commit is contained in:
Vladislav Nepogodin 2022-02-14 03:22:19 +04:00
parent 9c6ca2ddf9
commit 5dc58c5745
No known key found for this signature in database
GPG Key ID: B62C3D10C54D5DA9
8 changed files with 130 additions and 33 deletions

View File

@ -22,18 +22,12 @@ include(StaticAnalyzers)
include(Sanitizers)
include(CPM)
find_package(PkgConfig REQUIRED)
pkg_check_modules(
LIBNM
REQUIRED
IMPORTED_TARGET
libnm>=1.10.6)
pkg_check_modules(
GLIBMM
REQUIRED
IMPORTED_TARGET
glibmm-2.4>=2.56.0)
#find_package(PkgConfig REQUIRED)
#pkg_check_modules(
# GLIBMM
# REQUIRED
# IMPORTED_TARGET
# glibmm-2.4>=2.56.0)
CPMAddPackage(
NAME ftxui
@ -80,7 +74,7 @@ endif()
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto")
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fwhole-program")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fwhole-program -fuse-linker-plugin")
endif()
# Link this 'library' to set the c++ standard / compile-time options requested
@ -138,9 +132,9 @@ enable_sanitizers(project_options)
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 simdjson::simdjson cpr::cpr PkgConfig::GLIBMM)
target_link_libraries(test-exec-interactive PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component simdjson::simdjson cpr::cpr PkgConfig::GLIBMM)
target_link_libraries(test-process-tailing PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component simdjson::simdjson cpr::cpr PkgConfig::GLIBMM)
target_link_libraries(${PROJECT_NAME} PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::screen ftxui::dom ftxui::component simdjson::simdjson cpr::cpr)
target_link_libraries(test-exec-interactive PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component simdjson::simdjson cpr::cpr)
target_link_libraries(test-process-tailing PRIVATE project_warnings project_options spdlog::spdlog fmt::fmt ftxui::component simdjson::simdjson cpr::cpr)
if(CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
target_link_libraries(${PROJECT_NAME} PRIVATE range-v3::range-v3)

View File

@ -27,12 +27,16 @@ set(SIMDJSON_DISABLE_DEPRECATED_API ON CACHE INTERNAL "" FORCE)
# Generate compile_commands.json to make it easier to work with clang based tools
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flto")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto")
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -fwhole-program -fuse-linker-plugin")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fwhole-program -fuse-linker-plugin")
endif()
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++") #-static")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")# -static")
option(ENABLE_IPO "Enable Interprocedural Optimization, aka Link Time Optimization (LTO)" OFF)

View File

@ -38,8 +38,7 @@ 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'])
simdjson = dependency('simdjson', version : ['>=1.0.2'], fallback : ['simdjson', 'simdjson_dep'])
cpr = dependency('cpr', version : ['>=1.7.0'], fallback : ['cpr', 'cpr_dep'])
libnm = dependency('libnm', version : ['>=1.10.6'])
glibmm = dependency('glibmm-2.4', version : ['>=2.56.0'])
#glibmm = dependency('glibmm-2.4', version : ['>=2.56.0'])
src_files = files(
'src/view.hpp',
@ -113,13 +112,13 @@ if not is_debug_build
endif
possible_cc_flags += ['-fdata-sections', '-ffunction-sections']
possible_link_flags = ['-Wl,--gc-sections']
possible_link_flags = ['-Wl,--gc-sections', '-static-libgcc', '-static-libstdc++']
add_project_link_arguments(cc.get_supported_link_arguments(possible_link_flags), language : 'cpp')
endif
add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'cpp')
deps = [fmt, spdlog, ftxui, simdjson, cpr, glibmm]
deps = [fmt, spdlog, ftxui, simdjson, cpr]
if cc.get_id() == 'clang'
ranges = dependency('range-v3', version : ['>=0.11.0'])
deps += [ranges]

View File

@ -75,9 +75,9 @@ bool luks_open() noexcept {
utils::find_partitions();
// Filter out partitions that don't contain crypt device
const auto& ignore_part = utils::list_non_crypt();
/*const auto& ignore_part = utils::list_non_crypt();
/* const auto& parts = utils::make_multiline(ignore_part);
const auto& parts = utils::make_multiline(ignore_part);
for (const auto& part : parts) {
utils::delete_partition_in_list(part);
}*/

View File

@ -16,6 +16,75 @@ namespace fs = std::filesystem;
namespace utils {
void btrfs_create_subvols([[maybe_unused]] const disk_part& disk, const std::string_view& mode) noexcept {
/* clang-format off */
if (mode.empty()) { return; }
/* clang-format on */
#ifdef NDEVENV
// save mount options and name of the root partition
utils::exec("mount | grep \"on /mnt \" | grep -Po '(?<=\\().*(?=\\))' > /tmp/.root_mount_options");
// utils::exec("lsblk -lno MOUNTPOINT,NAME | awk '/^\\/mnt / {print $2}' > /tmp/.root_partition");
if (mode == "manual") {
// Create subvolumes manually
std::string subvols{"@ @home @cache"};
static constexpr auto subvols_body = "\nInput names of the subvolumes separated by spaces.\nThe first one will be used for mounting /.\n";
if (!tui::detail::inputbox_widget(subvols, subvols_body, size(ftxui::HEIGHT, ftxui::GREATER_THAN, 4))) {
return;
}
const auto& saved_path = fs::current_path();
fs::current_path("/mnt");
auto subvol_list = utils::make_multiline(subvols, false, " ");
for (const auto& subvol : subvol_list) {
utils::exec(fmt::format(FMT_COMPILE("btrfs subvolume create {}"), 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));
// Remove the first subvolume from the subvolume list
subvol_list.erase(subvol_list.begin());
// Loop to mount all created subvolumes
for (const auto& subvol : subvol_list) {
std::string mountp{"/home"};
const auto& mountp_body = fmt::format(FMT_COMPILE("\nInput mountpoint of the subvolume {}\nas it would appear in installed system\n(without prepending /mnt).\n"), subvol);
if (!tui::detail::inputbox_widget(mountp, mountp_body, size(ftxui::HEIGHT, ftxui::GREATER_THAN, 4))) {
return;
}
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));
}
return;
}
static constexpr auto content = "\nThis creates subvolumes:\n@ for /,\n@home for /home,\n@cache for /var/cache.\n";
const auto& do_create = tui::detail::yesno_widget(content, size(ftxui::HEIGHT, ftxui::LESS_THAN, 15) | size(ftxui::WIDTH, ftxui::LESS_THAN, 75));
/* clang-format off */
if (!do_create) { return; }
/* clang-format on */
// Create subvolumes automatically
const auto& saved_path = fs::current_path();
fs::current_path("/mnt");
utils::exec("btrfs subvolume create @", true);
utils::exec("btrfs subvolume create @home", true);
utils::exec("btrfs subvolume create @cache", true);
// utils::exec("btrfs subvolume create @snapshots", 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));
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));
#endif
}
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));
@ -36,7 +105,7 @@ void mount_existing_subvols(const disk_part& disk) noexcept {
// Ask for mountpoint
const auto& content = fmt::format(FMT_COMPILE("\nInput mountpoint of the subvolume {}\nas it would appear in installed system\n(without prepending /mnt).\n"), subvol);
std::string mountpoint{"/"};
if (!tui::detail::inputbox_widget(mountpoint, content, size(ftxui::HEIGHT, ftxui::LESS_THAN, 9) | size(ftxui::WIDTH, ftxui::LESS_THAN, 30))) {
if (!tui::tui::detail::inputbox_widget(mountpoint, content, size(ftxui::HEIGHT, ftxui::LESS_THAN, 9) | size(ftxui::WIDTH, ftxui::LESS_THAN, 30))) {
return;
}
const auto& mount_dir{fmt::format(FMT_COMPILE("/mnt/{}"), mountpoint)};

View File

@ -6,11 +6,14 @@
namespace utils {
struct disk_part {
const std::string_view root;
const std::string_view part;
const std::string_view root{};
const std::string_view part{};
const std::string_view mount_opts{};
};
void mount_existing_subvols(const disk_part& partition) noexcept;
void btrfs_create_subvols(const disk_part& disk, const std::string_view& mode) noexcept;
void mount_existing_subvols(const disk_part& disk) noexcept;
} // namespace utils
#endif // DISK_HPP

View File

@ -133,6 +133,33 @@ bool exit_done() noexcept {
#endif
}
void btrfs_subvolumes() noexcept {
const std::vector<std::string> menu_entries = {
"automatic",
"manual",
};
auto screen = ScreenInteractive::Fullscreen();
std::int32_t selected{};
std::string btrfsvols_mode{};
auto ok_callback = [&] {
btrfsvols_mode = menu_entries[static_cast<std::size_t>(selected)];
screen.ExitLoopClosure()();
};
static constexpr auto btrfsvols_body = "\nAutomatic mode\nis designed to allow integration\nwith snapper, non-recursive snapshots,\nseparating system and user data and\nrestoring snapshots without losing data.\n";
/* clang-format off */
detail::menu_widget(menu_entries, ok_callback, &selected, &screen, btrfsvols_body);
if (btrfsvols_mode.empty()) { return; }
/* clang-format on */
auto* config_instance = Config::instance();
auto& config_data = config_instance->data();
const auto& mount_opts_info = std::get<std::string>(config_data["MOUNT_OPTS"]);
const auto& root_part = std::get<std::string>(config_data["ROOT_PART"]);
utils::btrfs_create_subvols({.root = root_part, .mount_opts = mount_opts_info}, btrfsvols_mode);
}
// Function will not allow incorrect UUID type for installed system.
void generate_fstab() noexcept {
const std::vector<std::string> menu_entries = {
@ -1809,16 +1836,17 @@ void mount_partitions() noexcept {
const auto& subvolumes_formated = 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
if (existing_subvolumes) {
utils::mount_existing_subvols({root_part, part});
}
/* clang-format off */
if (existing_subvolumes) { utils::mount_existing_subvols({root_part, part}); }
/* clang-format on */
} else {
// No subvolumes present. Make some new ones
const auto& create_subvolumes = detail::yesno_widget("\nWould you like to create subvolumes in it? \n", size(HEIGHT, LESS_THAN, 15) | size(WIDTH, LESS_THAN, 75));
/* clang-format on */
if (create_subvolumes) {
spdlog::debug("Implement me!");
// utils::btrfs_subvolumes({root_part, part});
tui::btrfs_subvolumes();
}
/* clang-format on */
}
}
}

View File

@ -74,7 +74,7 @@ namespace utils {
bool is_connected() noexcept {
#ifdef NDEVENV
/* clang-format off */
auto r = cpr::Get(cpr::Url{"https://www.google.com"},
auto r = cpr::Get(cpr::Url{"https://cachyos.org"},
cpr::Timeout{1000});
/* clang-format on */
return cpr::status::is_success(static_cast<std::int32_t>(r.status_code)) || cpr::status::is_redirect(static_cast<std::int32_t>(r.status_code));