M src/config.cpp => src/config.cpp +10 -20
@@ 42,7 42,6 @@ extern "C" {
})
-// TODO: propagate no-longer-variance
static std::string get_host() {
if(auto host = std::getenv("KLAPKI_HOST"))
return host;
@@ 67,7 66,7 @@ static std::variant<std::string_view, std::string> get_wisom_root() {
return std::string_view{"/etc/klapki/"};
}
-static std::variant<std::pair<dev_t, const char *>, std::string> find_esp() {
+static std::variant<std::string_view, std::string> find_esp() {
const char * esp = "/boot/efi";
struct stat boot;
@@ 89,23 88,13 @@ static std::variant<std::pair<dev_t, const char *>, std::string> find_esp() {
if(boot.st_dev == boot_efi.st_dev)
return fmt::format("find_esp(): {}: not a mount point?", esp);
- return std::pair{boot_efi.st_dev, esp};
-}
-
-
-// TODO: make into a string_view
-const char * klapki::config::host() const noexcept {
- return std::visit([](auto && h) { return h.data(); }, this->host_raw);
-}
-
-const char * klapki::config::wisdom_root() const noexcept {
- return std::visit([](auto && w) { return w.data(); }, this->wisdom_root_raw);
+ return std::string_view{esp};
}
std::string klapki::config::news_efi_dir() const {
// TODO: rethink this potentially
- return fmt::format("\\klapki\\{}\\", std::getenv("KLAPKI_EFI_ROOT") ?: this->host());
+ return fmt::format("\\klapki\\{}\\", std::getenv("KLAPKI_EFI_ROOT") ?: this->host);
}
@@ 132,12 121,13 @@ std::variant<klapki::config, std::string> klapki::config::read(const char ** arg
case 'h':
return fmt::format("klapki {}\n"
- "Usage: {} [-vh]… [op [arg…]]…\n"
+ "Usage: {} [-vEnh]… [op [arg…]]…\n"
"\n"
- "-v\tVerbose operation\n"
- "-E\tIncrease libefivar verbosity level\n"
- "-n\tDon't commit\n"
- "-h\tShow this help\n"
+ "Flags:\n"
+ " -v\tVerbose operation\n"
+ " -E\tIncrease libefivar verbosity level\n"
+ " -n\tDon't commit\n"
+ " -h\tShow this help\n"
"\n"
"Recognised ops:\n"
"\tdump\n"
@@ 170,5 160,5 @@ std::variant<klapki::config, std::string> klapki::config::read(const char ** arg
if(ops.empty())
fmt::print("{}: no operations given, committing cleanly instead.\n", argv0); // TODO: remove this maybe?
- return config{argv0, verbose, commit, TRY(find_esp()), std::move(ops), get_host(), get_wisom_root()};
+ return config{argv0, get_host(), verbose, commit, TRY(find_esp()), std::move(ops), get_wisom_root()};
}
M src/config.hpp => src/config.hpp +9 -13
@@ 34,16 34,14 @@
namespace klapki {
struct config {
const char * argv0;
- const char * host() const noexcept;
- const char * wisdom_root() const noexcept;
+ std::string host;
+ constexpr std::string_view wisdom_root() const noexcept;
bool verbose;
bool commit;
/// Tries /boot/efi, or /boot if that doesn't exist. Must be a mount-point.
- // TODO: nobody's using the device part now
- std::pair<dev_t, const char *> esp;
+ std::string_view esp;
std::vector<ops::op_t> ops;
- std::variant<std::string_view, std::string> host_raw;
std::variant<std::string_view, std::string> wisdom_root_raw;
std::string news_efi_dir() const;
@@ 53,19 51,17 @@ namespace klapki {
}
+constexpr std::string_view klapki::config::wisdom_root() const noexcept {
+ return std::visit([](auto && w) { return std::string_view{w}; }, this->wisdom_root_raw);
+}
+
template <>
struct fmt::formatter<klapki::config> {
constexpr auto parse(format_parse_context & ctx) { return ctx.begin(); }
template <typename FormatContext>
auto format(const klapki::config & cfg, FormatContext & ctx) {
- return format_to(ctx.out(),
- "Host : {}\n"
- "Wisdom : {}\n"
- "Verbose: {}\n"
- "Commit : {}\n"
- "ESP : {}:{} ({})\n"
- "Ops : {}",
- cfg.host(), cfg.wisdom_root(), cfg.verbose, cfg.commit, major(cfg.esp.first), minor(cfg.esp.first), cfg.esp.second, klapki::mops{cfg.ops});
+ return format_to(ctx.out(), "config{{ host: \"{}\", wisdom: \"{}\", verbose: {}, commit: {}, ESP: {}, ops: [{}] }}", //
+ cfg.host, cfg.wisdom_root(), cfg.verbose, cfg.commit, cfg.esp, klapki::mops{cfg.ops});
}
};
M src/context_commit.cpp => src/context_commit.cpp +5 -5
@@ 82,9 82,9 @@ std::optional<std::string> klapki::context::context::commit(const config & cfg,
close(fd);
}};
{
- auto esp_fd = open(cfg.esp.second, O_RDONLY | O_DIRECTORY | O_PATH);
+ auto esp_fd = open(cfg.esp.data(), O_RDONLY | O_DIRECTORY | O_PATH);
if(esp_fd < 0)
- return fmt::format("Couldn't open ESP ({}): {}\n", cfg.esp.second, strerror(errno));
+ return fmt::format("Couldn't open ESP ({}): {}\n", cfg.esp, strerror(errno));
quickscope_wrapper esp_fd_deleter{[&] { close(esp_fd); }};
for(auto && kern : this->our_kernels)
@@ 108,15 108,15 @@ std::optional<std::string> klapki::context::context::commit(const config & cfg,
for(auto slash_idx = dir.find('/'); slash_idx != std::string::npos; slash_idx = dir.find('/', slash_idx + 1)) {
dir[slash_idx] = '\0';
if(mkdirat(esp_fd, dir.c_str(), 0755) < 0 && errno != EEXIST)
- return fmt::format("Couldn't create {} under ESP ({}): {}\n", dir.c_str(), cfg.esp.second, strerror(errno));
+ return fmt::format("Couldn't create {} under ESP ({}): {}\n", dir.c_str(), cfg.esp, strerror(errno));
dir[slash_idx] = '/';
}
if(mkdirat(esp_fd, dir.c_str(), 0755) < 0 && errno != EEXIST)
- return fmt::format("Couldn't create {} under ESP ({}): {}\n", dir, cfg.esp.second, strerror(errno));
+ return fmt::format("Couldn't create {} under ESP ({}): {}\n", dir, cfg.esp, strerror(errno));
auto fd = openat(esp_fd, dir.c_str(), O_RDONLY | O_DIRECTORY | O_PATH);
if(fd < 0)
- return fmt::format("Couldn't open {} under ESP ({}): {}\n", dir, cfg.esp.second, strerror(errno));
+ return fmt::format("Couldn't open {} under ESP ({}): {}\n", dir, cfg.esp, strerror(errno));
esp_dirs.emplace(kern.second.image_path.first, fd);
}
}
M src/context_save.cpp => src/context_save.cpp +1 -15
@@ 40,8 40,6 @@ static constexpr bool isslash(char c) {
std::optional<std::string> klapki::context::context::save(const config & cfg, state::state & state) {
- // const auto esp_blockdev = fmt::format("/dev/block/{}:0", major(cfg.esp.first));
-
for(auto && [bootnum, kern] : this->our_kernels) {
auto skern = std::find_if(std::begin(state.statecfg.wanted_entries), std::end(state.statecfg.wanted_entries),
[bn = bootnum](auto && skern) { return skern.bootnum_hint == bn; });
@@ 51,8 49,7 @@ std::optional<std::string> klapki::context::context::save(const config & cfg, st
if(bent == std::end(state.entries))
throw __func__;
- auto image_path =
- fmt::format("{}/{}{}{}", cfg.esp.second, kern.image_path.first, isslash(kern.image_path.first.back()) ? "" : "\\", kern.image_path.second);
+ auto image_path = fmt::format("{}/{}{}{}", cfg.esp, kern.image_path.first, isslash(kern.image_path.first.back()) ? "" : "\\", kern.image_path.second);
image_path.erase(std::remove_if(std::begin(image_path), std::end(image_path),
[prev = false](auto c) mutable {
auto cur = isslash(c);
@@ 71,17 68,6 @@ std::optional<std::string> klapki::context::context::save(const config & cfg, st
do {
devpath.resize(devpath.size() + 512);
- // extern ssize_t efi_generate_file_device_path_from_esp(uint8_t *buf,
- // ssize_t size,
- // const char *devpath,
- // int partition,
- // const char *relpath,
- // uint32_t options, ...)
- // if(auto size = efi_generate_file_device_path_from_esp(devpath.data(), devpath.size(), //
- // esp_blockdev.c_str(), minor(cfg.esp.first), //
- // image_path.c_str(), //
- // 0);
-
// extern ssize_t efi_generate_file_device_path(uint8_t *buf, ssize_t size,
// const char * const filepath,
// uint32_t options, ...)
M src/context_state.cpp => src/context_state.cpp +2 -5
@@ 48,11 48,8 @@ struct fmt::formatter<sha_f> {
std::variant<klapki::state::state, std::string> klapki::context::resolve_state_context(const state::state & input_state) {
std::map<std::uint16_t, state::boot_entry> entries{input_state.entries};
- // TODO: parallellise this
- // [02:06] ((наб *)(войд)())(): argh fuck
- // [02:07] ((наб *)(войд)())(): libc++12 from the LLVM repo doesn't have a working <execution>
- // [02:08] Griwes: lmao the only actually shipping and actually working <execution> in existence is the one in the NVHPC toolkit :vv:
- // [02:08] Griwes: ...well, maybe msvc has something, can't remember if they shipped yet
+ // When measured (KVM, amd64 on amd64, Xeon E5645 @ 2.40GHz, 6 vCPUs), this took 23`636ns all told for 14 SHAs (+outlier at 207`817);
+ // multithreading is much much more expensive: 2`633`277.86ns on same dataset when spawning a std::thread per.
std::for_each(std::begin(entries), std::end(entries),
[](auto & bent) { SHA1(bent.second.load_option.get(), bent.second.load_option_len, bent.second.load_option_sha); });
M src/main.cpp => src/main.cpp +1 -1
@@ 51,7 51,7 @@ namespace klapki {
fmt::print("{}\n", cfg);
- const auto input_state = TRY(2, state::state::load(cfg.argv0, cfg.host()));
+ const auto input_state = TRY(2, state::state::load(cfg.argv0, cfg.host.c_str()));
auto output_state = TRY(3, context::resolve_state_context(input_state));
M src/state.cpp => src/state.cpp +8 -7
@@ 60,8 60,8 @@ static bool is_boot_order(const efi_guid_t & guid, const char * name) noexcept {
return guid == efi_guid_global && !std::strcmp(name, "BootOrder");
}
-static bool is_our_config(const efi_guid_t & guid, const char * name, const char * us) noexcept {
- return guid == klapki::efi_guid_klapki && !std::strcmp(name, us);
+static bool is_our_config(const efi_guid_t & guid, const char * name, std::string_view us) noexcept {
+ return guid == klapki::efi_guid_klapki && name == us;
}
template <class F>
@@ 86,21 86,22 @@ static int get_boot_order(klapki::state::boot_order_flat & bord) {
}
static int get_boot_entry(std::map<std::uint16_t, klapki::state::boot_entry> & bents, std::uint16_t num) {
- // TODO: sprintf() and avoid an allocation instead?
- return get_efi_data(efi_guid_global, fmt::format("Boot{:04X}", num).c_str(), [&](auto && data, auto size, auto attr) {
+ char name[4 + 4 + 1]{};
+ fmt::format_to(name, "Boot{:04X}", num);
+ return get_efi_data(efi_guid_global, name, [&](auto && data, auto size, auto attr) {
bents.emplace(num, klapki::state::boot_entry{std::move(data), size, {}, attr});
return 0;
});
}
-static int get_our_config(klapki::state::stated_config & statecfg, const char * us) {
- return get_efi_data(klapki::efi_guid_klapki, us,
+static int get_our_config(klapki::state::stated_config & statecfg, std::string_view us) {
+ return get_efi_data(klapki::efi_guid_klapki, us.data(),
// TODO: error recovery; flag to ignore? force?
[&](auto && data, auto size, auto) { return klapki::state::stated_config::parse(statecfg, data.get(), size); });
}
-std::variant<klapki::state::state, std::string> klapki::state::state::load(const char * argv0, const char * us) {
+std::variant<klapki::state::state, std::string> klapki::state::state::load(const char * argv0, std::string_view us) {
if(!efi_variables_supported())
return fmt::format("{}: EFI not supported?", argv0);
M src/state.hpp => src/state.hpp +1 -1
@@ 93,7 93,7 @@ namespace klapki::state {
std::optional<std::string> commit(const config & cfg, const state & original_state);
- static std::variant<state, std::string> load(const char * argv0, const char * us);
+ static std::variant<state, std::string> load(const char * argv0, std::string_view us);
};
}
M src/state_commit.cpp => src/state_commit.cpp +1 -1
@@ 45,7 45,7 @@ std::optional<std::string> klapki::state::state::commit(const config & cfg, cons
auto statecfg_raw = this->statecfg.serialise();
- if(efi_set_variable(klapki::efi_guid_klapki, cfg.host(), statecfg_raw.data(), statecfg_raw.size(),
+ if(efi_set_variable(klapki::efi_guid_klapki, cfg.host.c_str(), statecfg_raw.data(), statecfg_raw.size(),
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, 0600) < 0)
return fmt::format("Couldn't write new state config: {}", strerror(errno));
}