diff --git a/Makefile b/Makefile index ef42e5d..200fd1b 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ PACKAGE = nullinitrd -VERSION = 1.0.0 +VERSION = 1.1 -include .config CXX ?= g++ CXXFLAGS = -std=c++17 -Wall -Wextra -O2 -DVERSION=\"$(VERSION)\" @@ -20,7 +20,7 @@ endif SRCDIR = src OBJDIR = obj BINDIR = bin -GEN_SOURCES = $(SRCDIR)/main.cpp $(SRCDIR)/config.cpp $(SRCDIR)/generator.cpp $(SRCDIR)/hooks.cpp $(SRCDIR)/utils.cpp +GEN_SOURCES = $(SRCDIR)/main.cpp $(SRCDIR)/config.cpp $(SRCDIR)/generator.cpp $(SRCDIR)/hooks.cpp $(SRCDIR)/utils.cpp $(SRCDIR)/logger/log.cpp GEN_OBJECTS = $(GEN_SOURCES:$(SRCDIR)/%.cpp=$(OBJDIR)/%.o) GEN_TARGET = $(BINDIR)/$(PACKAGE) INIT_SOURCE = $(SRCDIR)/init.cpp @@ -42,12 +42,10 @@ $(INIT_TARGET): $(INIT_OBJECT) | $(BINDIR) $(CXX) $(INIT_OBJECT) -o $@ -static strip $@ -$(OBJDIR)/%.o: $(SRCDIR)/%.cpp | $(OBJDIR) +$(OBJDIR)/%.o: $(SRCDIR)/%.cpp + @mkdir -p $(dir $@) $(CXX) $(CXXFLAGS) -c $< -o $@ -$(OBJDIR): - mkdir -p $(OBJDIR) - $(BINDIR): mkdir -p $(BINDIR) diff --git a/src/config.cpp b/src/config.cpp index 90c940c..59ff71e 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -1,7 +1,7 @@ #include "config.hpp" #include #include -#include +#include Config::Config(const std::string& path) : compression("zstd"), @@ -11,10 +11,24 @@ Config::Config(const std::string& path) parse_file(path); } +/* + * Parse a config file, write the defaults to it if not found. + */ void Config::parse_file(const std::string& path) { std::ifstream file(path); if (!file.is_open()) { - throw std::runtime_error(":: [!] cannot open config file: " + path); + // create the default config in const std::string& path + mkdir("/etc/nullinitrd", 0755); + std::ofstream configfile; + configfile.open(path); + configfile << "CONFIG_STATIC=y\n"; + configfile << "CONFIG_DEBUG=n\n"; + configfile << "CONFIG_LTO=y\n"; + configfile << "CONFIG_FEATURE_LVM=n\n"; + configfile << "CONFIG_FEATURE_LUKS=n\n"; + configfile << "CONFIG_FEATURE_MDADM=n\n"; + configfile << "CONFIG_FEATURE_BTRFS=n\n"; + configfile << "CONFIG_FEATURE_ZFS=n\n"; } std::string line; @@ -56,6 +70,12 @@ std::string Config::get(const std::string& key, const std::string& default_val) return it != config_map.end() ? it->second : default_val; } +/* + * Get a boolean value from the config, return a bool. + * Arguments: + * const std::string& key - key to check + * bool default_val - use this value if empty + */ bool Config::get_bool(const std::string& key, bool default_val) const { auto val = get(key, ""); if (val.empty()) return default_val; @@ -74,6 +94,10 @@ std::vector Config::get_list(const std::string& key) const { return result; } +/* Check if a feature is enabled, return a boolean. + * Arguments: + * const std::string& feature - the feat to check for + */ bool Config::is_enabled(const std::string& feature) const { return features.count(feature) > 0; } diff --git a/src/generator.cpp b/src/generator.cpp index 75a840c..9417bc2 100644 --- a/src/generator.cpp +++ b/src/generator.cpp @@ -1,5 +1,6 @@ #include "generator.hpp" #include "hooks.hpp" +#include "logger/log.hpp" #include #include #include @@ -12,7 +13,7 @@ Generator::Generator(const Config& cfg, const std::string& kernel_ver, bool v) char tmpl[] = "/tmp/nullinitrd.XXXXXX"; char* tmp = mkdtemp(tmpl); if (!tmp) { - throw std::runtime_error(":: [!] failed to create temp directory"); + throw std::runtime_error("failed to create temp directory"); } chmod(tmp, 0755); work_dir = tmp; @@ -26,15 +27,23 @@ Generator::Generator(const Config& cfg, const std::string& kernel_ver, bool v) }; } +/* + * Helper to create a directory. + * Arguments: + * const fs::path& path - directory to create + */ void Generator::create_directory(const fs::path& path) { if (verbose) { - std::cout << ":: creating dir: " << path << std::endl; + log_info("creating dir: " + path.string()); } fs::create_directories(path); } +/* + * Creates the strucutre of the initramfs. + */ void Generator::create_structure() { - std::cout << ":: creating structure..." << std::endl; + log_info("creating structure..."); create_directory(work_dir / "usr/bin"); create_directory(work_dir / "usr/lib"); create_directory(work_dir / "usr/lib64"); @@ -53,8 +62,11 @@ void Generator::create_structure() { } } +/* + * Create UsrMerge symlinks. + */ void Generator::create_symlinks() { - std::cout << ":: creating symlinks..." << std::endl; + log_info("creating symlinks..."); auto safe_symlink = [this](const char* target, const fs::path& link) { if (fs::exists(link) || fs::is_symlink(link)) fs::remove(link); fs::create_symlink(target, link); @@ -65,9 +77,15 @@ void Generator::create_symlinks() { safe_symlink("usr/lib64", work_dir / "lib64"); } +/* + * Helper to copy a file. + * Arguments: + * const fs::path& src - source path + * const fs::path& dst - destination path + */ void Generator::copy_file(const fs::path& src, const fs::path& dst) { if (verbose) { - std::cout << ":: copying " << src << " -> " << dst << std::endl; + log_info("copying " + src.string() + " -> " + dst.string()); } fs::create_directories(dst.parent_path()); fs::copy_file(src, dst, fs::copy_options::overwrite_existing); @@ -77,6 +95,12 @@ void Generator::copy_file(const fs::path& src, const fs::path& dst) { } } +/* + * Helper to find a program. + * Returns a std::string (path of the found binary), "" if not found. + * Arguments: + * const std::string& name - program to find + */ std::string Generator::find_binary(const std::string& name) { std::vector paths = { "/usr/local/sbin", "/usr/local/bin", @@ -135,7 +159,7 @@ void Generator::copy_binary_with_deps(const std::string& binary) { std::string bin_path = find_binary(binary); if (bin_path.empty()) { if (verbose) { - std::cerr << ":: [?] binary not found: " << binary << std::endl; + log_warning("binary not found: " + binary); } return; } @@ -164,7 +188,7 @@ void Generator::copy_binary_with_deps(const std::string& binary) { } void Generator::copy_binaries() { - std::cout << ":: copying binaries..." << std::endl; + log_info("copying binaries..."); copy_binary_with_deps("kmod"); fs::path kmod_dst = work_dir / "usr/bin/kmod"; @@ -254,7 +278,7 @@ void Generator::copy_module(const std::string& module) { fs::create_directories(dst.parent_path()); if (needs_decompress) { if (verbose) { - std::cout << ":: decompressing " << src << " -> " << dst << std::endl; + log_info("decompressing " + src.string() + " -> " + dst.string()); } std::string full_cmd = decompress_cmd + " '" + mod_file + "' > '" + dst.string() + "'"; system(full_cmd.c_str()); @@ -267,8 +291,11 @@ void Generator::copy_module(const std::string& module) { pclose(pipe); } +/* + * Copy kernel modules. + */ void Generator::copy_modules() { - std::cout << ":: copying kernel modules..." << std::endl; + log_info("copying kernel modules..."); create_directory(work_dir / "usr/lib/modules" / kernel_version); std::vector modules_to_copy; @@ -285,10 +312,10 @@ void Generator::copy_modules() { copy_module(mod); } - std::cout << ":: generating module dependencies..." << std::endl; + log_info("generating module dependencies..."); std::string depmod_cmd = "depmod -b " + work_dir.string() + " " + kernel_version; if (system(depmod_cmd.c_str()) != 0) { - std::cerr << ":: [!] depmod failed, falling back to copying modules.dep" << std::endl; + log_warning("depmod failed, falling back to copying modules.dep"); std::string dep_src = "/usr/lib/modules/" + kernel_version + "/modules.dep"; if (fs::exists(dep_src)) { copy_file(dep_src, work_dir / "usr/lib/modules" / kernel_version / "modules.dep"); @@ -301,7 +328,7 @@ void Generator::copy_modules() { } void Generator::create_init() { - std::cout << ":: installing init..." << std::endl; + log_info("installing init..."); std::vector init_paths = { "/usr/share/nullinitrd/init", @@ -318,7 +345,7 @@ void Generator::create_init() { } if (init_src.empty()) { - throw std::runtime_error(":: [!] init binary not found"); + throw std::runtime_error("init binary not found"); } fs::path init_dst = work_dir / "init"; @@ -326,14 +353,22 @@ void Generator::create_init() { chmod(init_dst.c_str(), 0755); } +/* + * Run hooks. + */ void Generator::run_hooks() { - std::cout << ":: running hooks..." << std::endl; + log_info("running hooks..."); HookManager hook_mgr(config, work_dir, kernel_version, verbose); for (const auto& hook : config.hooks) { hook_mgr.run_hook(hook); } } +/* + * Find the compression command to use. + * Return the command to use, ofc. + * Defaults to zstd -19 -T0. + */ std::string Generator::get_compression_cmd() { if (config.compression == "gzip") return "gzip -9"; if (config.compression == "bzip2") return "bzip2 -9"; @@ -345,14 +380,22 @@ std::string Generator::get_compression_cmd() { return "zstd -19 -T0"; } +/* + * Pack the initramfs. + * Arguments: + * const std::string& output - output file + */ void Generator::pack(const std::string& output) { - std::cout << ":: packing initramfs..." << std::endl; + log_info("packing initramfs..."); std::string cpio_cmd = "cd " + work_dir.string() + " && find . | cpio -o -H newc 2>/dev/null"; std::string compress_cmd = get_compression_cmd(); std::string full_cmd = cpio_cmd + " | " + compress_cmd + " > " + output; int ret = system(full_cmd.c_str()); if (ret != 0) { - throw std::runtime_error(":: [!] failed to pack initramfs"); + throw std::runtime_error("failed to pack initramfs"); } fs::remove_all(work_dir); + if (fs::exists(output)) { + throw std::runtime_error("failed to pack initramfs"); + } } diff --git a/src/hooks.cpp b/src/hooks.cpp index 5e7e6bd..2aac6d9 100644 --- a/src/hooks.cpp +++ b/src/hooks.cpp @@ -1,4 +1,5 @@ #include "hooks.hpp" +#include "logger/log.hpp" #include #include #include @@ -7,24 +8,30 @@ HookManager::HookManager(const Config& cfg, const fs::path& work, : config(cfg), work_dir(work), kernel_version(kver), verbose(v) {} void HookManager::run_script(const fs::path& script) { - std::cout << ":: [#] " << script << std::endl; - std::string cmd = "NULLINITRD_WORKDIR=" + work_dir.string() + + log_job(std::string("[#] ") + script.string()); + std::string cmd = "NULLINITRD_WORKDIR=" + work_dir.string() + " NULLINITRD_KERNEL=" + kernel_version + " " + script.string(); - + int ret = system(cmd.c_str()); if (ret != 0) { - std::cerr << ":: [?] hook " << script << " exited with code " << ret << std::endl; + log_warning(std::string("hook ") + script.string() + " exited with code " + std::to_string(ret)); } } +/* + * Find a hook in /usr/[local]/share/nullinitrd/hooks or /etc/nullinitrd/hooks, + * return false if not found or true if found. + * Arguments: + * const std::string& hook_name - the hook to find + */ bool HookManager::find_and_run(const std::string& hook_name) { std::vector search_paths = { "/etc/nullinitrd/hooks", "/usr/share/nullinitrd/hooks", "/usr/local/share/nullinitrd/hooks" }; - + for (const auto& path : search_paths) { fs::path hook_path = fs::path(path) / hook_name; if (fs::exists(hook_path)) { @@ -35,14 +42,17 @@ bool HookManager::find_and_run(const std::string& hook_name) { } } } - + return false; } +/* + * Run a hook. + * Arguments: + * const std::string& hook_name - name of the hook + */ void HookManager::run_hook(const std::string& hook_name) { if (!find_and_run(hook_name)) { - if (verbose) { - std::cerr << ":: [?] hook not found: " << hook_name << std::endl; - } + log_warning("hook not found: " + hook_name); } } diff --git a/src/init.cpp b/src/init.cpp index 3ea6009..073fb11 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -11,9 +11,8 @@ #include #include #include - -#define MSG(x) write(STDOUT_FILENO, x, sizeof(x) - 1) -#define ERR(x) write(STDERR_FILENO, x, sizeof(x) - 1) +#include +#include "logger/log_init.hpp" static char cmdline[4096]; static char root_dev[256] = "/dev/sda1"; @@ -25,31 +24,24 @@ static bool verbose = false; static char modules_to_load[4096] = ""; -static void print_str(const char *s) { - write(STDOUT_FILENO, s, strlen(s)); -} - -static void print_num(int n) { - char buf[16]; - snprintf(buf, sizeof(buf), "%d", n); - print_str(buf); -} - +/* + * Enter infinite sleep after a critical error occurs + * TODO: add a recovery shell + */ static void panic(const char *msg) { - ERR(":: PANIC: "); - write(STDERR_FILENO, msg, strlen(msg)); - ERR("\n:: dropping to infinite sleep\n"); + char buf[512]; + snprintf(buf, sizeof(buf), "PANIC: %s", msg); + log_init_err(buf); + log_init_err("dropping to infinite sleep"); for (;;) sleep(3600); } static void do_mount(const char *src, const char *tgt, const char *type, unsigned long flags, const void *data) { mkdir(tgt, 0755); if (mount(src, tgt, type, flags, data) < 0 && errno != EBUSY) { - ERR(":: mount failed: "); - write(STDERR_FILENO, tgt, strlen(tgt)); - ERR(" ("); - print_str(strerror(errno)); - ERR(")\n"); + char buf[512]; + snprintf(buf, sizeof(buf), "mount failed: %s (%s)", tgt, strerror(errno)); + log_init_err(buf); } } @@ -78,9 +70,7 @@ static void parse_cmdline() { if (cmdline[n-1] == '\n') cmdline[n-1] = '\0'; if (verbose) { - MSG(":: cmdline: "); - print_str(cmdline); - MSG("\n"); + log_init_info(std::string("cmdline: ").append(cmdline).c_str()); } char *p = cmdline; @@ -121,12 +111,15 @@ static void parse_cmdline() { } } +/* + * Load kernel modules. + */ static void load_modules() { - MSG(":: loading modules\n"); + log_init_job("loading modules"); struct utsname uts; if (uname(&uts) < 0) { - ERR(":: uname failed\n"); + log_init_err("uname failed"); return; } @@ -135,7 +128,7 @@ static void load_modules() { struct stat st; if (stat(moddir, &st) < 0) { - MSG(":: module dir not found, skipping\n"); + log_init_info("module dir not found, skipping"); return; } @@ -160,9 +153,9 @@ static void load_modules() { }; if (run_command("/usr/bin/modprobe", argv) == 0) { if (verbose) { - MSG(":: loaded: "); - print_str(default_modules[i]); - MSG("\n"); + char buf[256]; + snprintf(buf, sizeof(buf), "loaded: %s", default_modules[i]); + log_init_info(buf); } loaded++; } @@ -183,9 +176,9 @@ static void load_modules() { }; if (run_command("/usr/bin/modprobe", argv) == 0) { if (verbose) { - MSG(":: loaded: "); - print_str(mod); - MSG("\n"); + char buf[256]; + snprintf(buf, sizeof(buf), "loaded: %s", mod); + log_init_info(buf); } loaded++; } @@ -193,11 +186,16 @@ static void load_modules() { } } - MSG(":: loaded "); - print_num(loaded); - MSG(" modules\n"); + { + char buf[64]; + snprintf(buf, sizeof(buf), "loaded %d modules", loaded); + log_init_info(buf); + } } +/* + * TODO: find NVMe support + */ static char *resolve_device(char *dev) { static char resolved[256]; @@ -220,9 +218,7 @@ static char *resolve_device(char *dev) { snprintf(link, sizeof(link), "/dev/disk/%s/%s", type, val); if (verbose) { - MSG(":: resolving: "); - print_str(link); - MSG("\n"); + log_init_info(std::string("resolving: ").append(link).c_str()); } for (int i = 0; i < 30; i++) { @@ -238,15 +234,18 @@ static char *resolve_device(char *dev) { return resolved; } } - MSG(":: waiting for root device...\n"); + log_init_job("waiting for root device..."); sleep(1); } - ERR(":: failed to resolve device\n"); + log_init_err("failed to resolve device"); } return dev; } +/* + * Switch root. + */ static void switch_root() { chdir("/mnt/root"); mount(".", "/", nullptr, MS_MOVE, nullptr); @@ -255,7 +254,7 @@ static void switch_root() { } int main() { - MSG(":: nullinitrd\n"); + log_init_job("nullinitrd"); do_mount("proc", "/proc", "proc", MS_NOSUID | MS_NOEXEC | MS_NODEV, nullptr); do_mount("sysfs", "/sys", "sysfs", MS_NOSUID | MS_NOEXEC | MS_NODEV, nullptr); @@ -267,18 +266,18 @@ int main() { load_modules(); if (root_delay > 0) { - MSG(":: waiting "); - print_num(root_delay); - MSG("s for root device\n"); + char buf[64]; + snprintf(buf, sizeof(buf), "waiting %ds for root device", root_delay); + log_init_job(buf); sleep(root_delay); } char *dev = resolve_device(root_dev); - MSG(":: mounting root: "); - print_str(dev); - MSG(" ("); - print_str(root_type); - MSG(")\n"); + { + char buf[512]; + snprintf(buf, sizeof(buf), "mounting root: %s (%s)", dev, root_type); + log_init_job(buf); + } mkdir("/mnt/root", 0755); unsigned long mflags = 0; @@ -287,21 +286,21 @@ int main() { for (int i = 0; i < 30; i++) { if (mount(dev, "/mnt/root", root_type, mflags, nullptr) == 0) break; if (i == 29) { - ERR(":: mount error: "); - print_str(strerror(errno)); - ERR("\n"); + char buf[256]; + snprintf(buf, sizeof(buf), "mount error: %s", strerror(errno)); + log_init_err(buf); panic("failed to mount root filesystem"); } if (verbose) { - MSG(":: mount failed: "); - print_str(strerror(errno)); - MSG("\n"); + char buf[256]; + snprintf(buf, sizeof(buf), "mount failed: %s", strerror(errno)); + log_init_info(buf); } - MSG(":: retrying root mount...\n"); + log_init_job("retrying root mount..."); sleep(1); } - MSG(":: switching root\n"); + log_init_job("switching root"); umount("/proc"); umount("/sys"); umount("/dev"); @@ -309,9 +308,7 @@ int main() { switch_root(); - MSG(":: exec "); - print_str(init_path); - MSG("\n"); + log_init_job(std::string("exec ").append(init_path).c_str()); char *argv[] = {init_path, nullptr}; char *envp[] = { @@ -322,9 +319,11 @@ int main() { }; execve(init_path, argv, envp); - ERR(":: execve failed: "); - print_str(strerror(errno)); - ERR("\n"); + { + char buf[256]; + snprintf(buf, sizeof(buf), "execve failed: %s", strerror(errno)); + log_init_err(buf); + } panic("failed to execute init"); return 1; diff --git a/src/logger/log.cpp b/src/logger/log.cpp new file mode 100644 index 0000000..ccf093f --- /dev/null +++ b/src/logger/log.cpp @@ -0,0 +1,47 @@ +#include +#include + +/* + * Print a job message. + * Arguments: + * std::string msg - message to print + */ +void log_job(std::string msg) { + std::cout << "\e[94;1m::\e[0m \e[1m" << msg << "\e[0m\n"; +} + +/* + * Print an info message. + * Arguments: + * std::string msg - message to print + */ +void log_info(std::string msg) { + std::cout << "\e[34m *\e[0m " << msg << "\e[0m\n"; +} + +/* + * Print a warning message. + * Arguments: + * std::string msg - message to print + */ +void log_warning(std::string msg) { + std::cout << "\e[33m !\e[0m " << msg << "\e[0m\n"; +} + +/* + * Print an error message. + * Arguments: + * std::string msg - message to print + */ +void log_error(std::string msg) { + std::cout << "\e[31m x\e[0m " << msg << "\e[0m\n"; +} + +/* + * Print a success message. + * Arguments: + * std::string msg - message to print + */ +void log_done(std::string msg) { + std::cout << "\e[32;1m::\e[0m " << msg << "\e[0m\n"; +} diff --git a/src/logger/log.hpp b/src/logger/log.hpp new file mode 100644 index 0000000..3a60dbd --- /dev/null +++ b/src/logger/log.hpp @@ -0,0 +1,8 @@ +#pragma once +#include + +void log_job(std::string msg); +void log_info(std::string msg); +void log_warning(std::string msg); +void log_error(std::string msg); +void log_done(std::string msg); diff --git a/src/logger/log_init.hpp b/src/logger/log_init.hpp new file mode 100644 index 0000000..11456ce --- /dev/null +++ b/src/logger/log_init.hpp @@ -0,0 +1,39 @@ +#pragma once +#include +#include + +/* + * Early print. + * TODO: fix the output borked, printing smth like: + * ::Space is missing *No newline?::Just broken + */ + +static inline void log_init_job(const char *msg) { + write(STDOUT_FILENO, "\e[94;1m::\e[0m ", 13); + write(STDOUT_FILENO, msg, strlen(msg)); + write(STDOUT_FILENO, "\e[0m\n", 4); +} + +static inline void log_init_info(const char *msg) { + write(STDOUT_FILENO, "\e[34;1m *\e[0m ", 12); + write(STDOUT_FILENO, msg, strlen(msg)); + write(STDOUT_FILENO, "\e[0m\n", 4); +} + +static inline void log_init_warn(const char *msg) { + write(STDOUT_FILENO, "\e[33;1m !\e[0m ", 12); + write(STDOUT_FILENO, msg, strlen(msg)); + write(STDOUT_FILENO, "\e[0m\n", 4); +} + +static inline void log_init_err(const char *msg) { + write(STDERR_FILENO, "\e[31;1m x\e[0m ", 12); + write(STDERR_FILENO, msg, strlen(msg)); + write(STDERR_FILENO, "\e[0m\n", 4); +} + +static inline void log_init_done(const char *msg) { + write(STDOUT_FILENO, "\e[32;1m \xe2\x9c\x93\e[0m ", 14); + write(STDOUT_FILENO, msg, strlen(msg)); + write(STDOUT_FILENO, "\e[0m\n", 4); +} diff --git a/src/main.cpp b/src/main.cpp index 5caac49..4a85453 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,13 +12,23 @@ #include "generator.hpp" #include "hooks.hpp" #include "utils.hpp" +#include "logger/log.hpp" + namespace fs = std::filesystem; + +/* Print the current version of nullinitrd. */ void print_version() { - std::cout << ":: nullinitrd v" << VERSION << std::endl; - std::cout << ":: NULL's Modular Initramfs Generator." << std::endl; + log_job("nullinitrd v" VERSION); + log_job("NULL's Modular Initramfs Generator."); } +/* + * Print usage + * Arguments: + * const char* prog - the program name, use with argv[0] + */ void print_usage(const char* prog) { + std::cout << "nullinitrd - initramfs generator" << std::endl << std::endl; std::cout << "Usage: " << prog << " [OPTIONS]" << std::endl; std::cout << "Options:" << std::endl; std::cout << " -o, --output FILE Output initramfs file" << std::endl; @@ -60,11 +70,11 @@ int main(int argc, char* argv[]) { output_file = "/boot/initrd.img"; } - std::cout << ":: nullinitrd" << std::endl; - std::cout << ":: linux " << kernel_version << std::endl; - std::cout << ":: output -> " << output_file << std::endl; - std::cout << ":: building initramfs..." << std::endl; + log_job("nullinitrd"); + log_info("linux " + kernel_version); + log_info("writing output to " + output_file); try { + log_job("generating initrd"); Config cfg(config_file); Generator gen(cfg, kernel_version, verbose); gen.create_structure(); @@ -74,9 +84,9 @@ int main(int argc, char* argv[]) { gen.create_init(); gen.run_hooks(); gen.pack(output_file); - std::cout << ":: initramfs generated successfully: " << output_file << std::endl; + log_done("initramfs generated successfully: " + output_file); } catch (const std::exception& e) { - std::cerr << ":: [!] " << e.what() << std::endl; + log_error(e.what()); return 1; } diff --git a/src/utils.cpp b/src/utils.cpp index 676fe74..3403ad3 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -2,7 +2,12 @@ #include #include #include + namespace utils { + +/* + * Return the current kernel version, "" if not found. + */ std::string get_kernel_version() { struct utsname buf; if (uname(&buf) == 0) { @@ -11,11 +16,22 @@ std::string get_kernel_version() { return ""; } +/* + * Check if a command is installed. + * Arguments: + * const std::string& cmd - command to check for + */ bool command_exists(const std::string& cmd) { std::string check = "command -v " + cmd + " >/dev/null 2>&1"; return system(check.c_str()) == 0; } + +/* + * Execute a command. + * Arguments: + * const std::string& cmd - command to execute + */ std::string execute_command(const std::string& cmd) { std::array buffer; std::string result; @@ -24,7 +40,7 @@ std::string execute_command(const std::string& cmd) { while (fgets(buffer.data(), buffer.size(), pipe) != nullptr) { result += buffer.data(); } - + pclose(pipe); return result; }