From 30b9f32d7a544f50f5e06ef930525d620a028db1 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 28 May 2020 10:05:23 -0500 Subject: image: Put target inside ir_dir, add WIP ISO backend ir_dir used to be the target; now the target is inside ir_dir so backends have the choice of making other directories inside ir_dir if needed. --- image/backends/CMakeLists.txt | 1 + image/backends/iso.cc | 170 ++++++++++++++++++++++++++++++++++++++++++ image/backends/tar.cc | 6 +- 3 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 image/backends/iso.cc (limited to 'image/backends') diff --git a/image/backends/CMakeLists.txt b/image/backends/CMakeLists.txt index 2c79c8e..325fddf 100644 --- a/image/backends/CMakeLists.txt +++ b/image/backends/CMakeLists.txt @@ -1,5 +1,6 @@ set(BACKEND_SRCS basic.cc + iso.cc ) set(BACKEND_LIBS "") 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 +#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); + } + }); +} + +} +} diff --git a/image/backends/tar.cc b/image/backends/tar.cc index 279a11c..f9309a1 100644 --- a/image/backends/tar.cc +++ b/image/backends/tar.cc @@ -81,10 +81,10 @@ public: int fd, r, code = 0; struct stat s; void *buff; + std::string target = this->ir_dir + "/target"; - for(const auto& dent : fs::recursive_directory_iterator(this->ir_dir, - ec)) { - fs::path relpath = dent.path().lexically_relative(this->ir_dir); + for(const auto& dent : fs::recursive_directory_iterator(target, ec)) { + fs::path relpath = dent.path().lexically_relative(target); #define OUTPUT_FAILURE(x) \ output_error("tar backend", "failed to " x " '" + std::string(dent.path()) + "'",\ strerror(errno)); -- cgit v1.2.3-70-g09d2