summaryrefslogtreecommitdiff
path: root/image/backends/iso.cc
diff options
context:
space:
mode:
Diffstat (limited to 'image/backends/iso.cc')
-rw-r--r--image/backends/iso.cc170
1 files changed, 170 insertions, 0 deletions
diff --git a/image/backends/iso.cc b/image/backends/iso.cc
new file mode 100644
index 0000000..b1d4c43
--- /dev/null
+++ b/image/backends/iso.cc
@@ -0,0 +1,170 @@
+/*
+ * iso.cc - Implementation of the CD image Horizon Image Creation backend
+ * image, the image processing utilities for
+ * Project Horizon
+ *
+ * Copyright (c) 2020 Adélie Linux and contributors. All rights reserved.
+ * This code is licensed under the AGPL 3.0 license, as noted in the
+ * LICENSE-code file in the root directory of this repository.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+#include <fstream>
+#include "basic.hh"
+#include "hscript/util.hh"
+#include "util/filesystem.hh"
+#include "util/output.hh"
+
+namespace Horizon {
+namespace Image {
+
+class CDBackend : public BasicBackend {
+public:
+ enum CDError {
+ COMMAND_MISSING = 1,
+ FS_ERROR,
+ COMMAND_ERROR
+ };
+
+ explicit CDBackend(std::string ir, std::string out)
+ : BasicBackend(ir, out) {};
+
+ int prepare() override {
+ error_code ec;
+
+ output_info("CD backend", "probing SquashFS tools version...");
+ if(run_command("mksquashfs", {"-version"}) != 0) {
+ output_error("CD backend", "SquashFS tools are not present");
+ return COMMAND_MISSING;
+ }
+
+ /* REQ: ISO.1 */
+ if(fs::exists(this->ir_dir, ec)) {
+ output_info("CD backend", "removing old IR tree", this->ir_dir);
+ fs::remove_all(this->ir_dir, ec);
+ if(ec) {
+ output_warning("CD backend", "could not remove IR tree",
+ ec.message());
+ /* we can _try_ to proceed anyway... */
+ }
+ }
+
+ /* REQ: ISO.2 */
+ fs::create_directory(this->ir_dir, ec);
+ if(ec && ec.value() != EEXIST) {
+ output_error("CD backend", "could not create IR directory",
+ ec.message());
+ return FS_ERROR;
+ }
+
+ /* REQ: ISO.2 */
+ fs::create_directory(this->ir_dir + "/cdroot", ec);
+ if(ec && ec.value() != EEXIST) {
+ output_error("CD backend", "could not create ISO directory",
+ ec.message());
+ return FS_ERROR;
+ }
+
+ /* REQ: ISO.2 */
+ fs::create_directory(this->ir_dir + "/target", ec);
+ if(ec && ec.value() != EEXIST) {
+ output_error("CD backend", "could not create target directory",
+ ec.message());
+ return FS_ERROR;
+ }
+
+ /* REQ: ISO.4 */
+ fs::create_directories(this->ir_dir + "/target/etc/default", ec);
+ if(ec && ec.value() != EEXIST) {
+ output_error("CD backend", "could not create target config dir",
+ ec.message());
+ return FS_ERROR;
+ }
+
+ /* REQ: ISO.4 */
+ std::ofstream grub(this->ir_dir + "/target/etc/default/grub");
+ grub << "ADELIE_MANUAL_CONFIG=1" << std::endl;
+ if(grub.fail() || grub.bad()) {
+ output_error("CD backend", "failed to configure GRUB");
+ return FS_ERROR;
+ }
+ grub.close();
+
+ return 0;
+ }
+
+ int create() override {
+ std::string my_arch;
+ std::ifstream archstream(this->ir_dir + "/target/etc/apk/arch");
+ const std::string target = this->ir_dir + "/target";
+ const std::string cdpath = this->ir_dir + "/cdroot";
+ archstream >> my_arch;
+
+ /* REQ: ISO.7 */
+ fs::create_directory(target + "/target");
+ fs::create_directories(target + "/media/live");
+
+ /* REQ: ISO.9 */
+ std::ofstream mtab(target + "/etc/conf.d/mtab");
+ if(!mtab) {
+ output_error("CD backend", "failed to open mtab configuration");
+ return FS_ERROR;
+ }
+ mtab << "mtab_is_file=no" << std::endl;
+ if(mtab.fail() || mtab.bad()) {
+ output_error("CD backend", "failed to write mtab configuration");
+ return FS_ERROR;
+ }
+ mtab.close();
+
+ /* REQ: ISO.10 */
+ const std::string targetsi = target + "/etc/runlevels/sysinit/";
+ fs::create_symlink("/etc/init.d/udev", targetsi + "udev");
+ fs::create_symlink("/etc/init.d/udev-trigger",
+ targetsi + "udev-trigger");
+ fs::create_symlink("/etc/init.d/lvmetad", targetsi + "lvmetad");
+
+ const std::string squashpath = cdpath + "/" + my_arch + ".squashfs";
+
+ /* REQ: ISO.22 */
+ {
+ std::ofstream exclude(this->ir_dir + "/exclude.list");
+ exclude << "dev/*" << std::endl
+ << "proc/*" << std::endl
+ << "sys/*" << std::endl;
+ if(exclude.fail() || exclude.bad()) {
+ output_error("CD backend", "failed to write exclusion list");
+ return FS_ERROR;
+ }
+ exclude.flush();
+ exclude.close();
+ }
+
+ /* REQ: ISO.22 */
+ if(run_command("mksquashfs", {target, squashpath, "-noappend",
+ "-wildcards", "-ef",
+ this->ir_dir + "/exclude.list"}) != 0) {
+ output_error("CD backend", "failed to create SquashFS");
+ return COMMAND_ERROR;
+ }
+ return 0;
+ }
+
+ int finalise() override {
+ return 0;
+ }
+};
+
+__attribute__((constructor(400)))
+void register_cd_backend() {
+ BackendManager::register_backend(
+ {"iso", "Create a CD image (.iso)",
+ [](std::string ir_dir, std::string out_path) {
+ return new CDBackend(ir_dir, out_path);
+ }
+ });
+}
+
+}
+}