From cd52d492ec08810fa0ba2425d5e01618a2e8741a Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Thu, 2 Apr 2020 21:41:11 -0500 Subject: image: Truly dynamic backend registration This allows one backend to provide multiple types. For example, our TarBackend can provide optional .gz, .bz2, and .xz compression. --- image/CMakeLists.txt | 3 +- image/backends/CMakeLists.txt | 16 +++++- image/backends/basic.cc | 6 +-- image/backends/basic.hh | 4 +- image/backends/tar.cc | 114 ++++++++++++++++++++++++++++++++++++++++++ image/creator.cc | 10 ++++ 6 files changed, 143 insertions(+), 10 deletions(-) create mode 100644 image/backends/tar.cc (limited to 'image') diff --git a/image/CMakeLists.txt b/image/CMakeLists.txt index cbee674..775d38e 100644 --- a/image/CMakeLists.txt +++ b/image/CMakeLists.txt @@ -5,8 +5,7 @@ add_subdirectory(backends) set(IMG_SRCS creator.cc - ${BACKEND_SRCS} ) add_executable(hscript-image ${IMG_SRCS}) -target_link_libraries(hscript-image hscript ${Boost_LIBRARIES}) +target_link_libraries(hscript-image hscript hi-backends ${Boost_LIBRARIES}) install(TARGETS hscript-image DESTINATION bin) diff --git a/image/backends/CMakeLists.txt b/image/backends/CMakeLists.txt index f3c7f5d..726d4eb 100644 --- a/image/backends/CMakeLists.txt +++ b/image/backends/CMakeLists.txt @@ -1,4 +1,16 @@ set(BACKEND_SRCS - ${CMAKE_CURRENT_SOURCE_DIR}/basic.cc - PARENT_SCOPE + basic.cc ) + +set(BACKEND_LIBS "") + +find_package(LibArchive) + +if(LibArchive_FOUND) + list(APPEND BACKEND_SRCS tar.cc) + list(APPEND BACKEND_LIBS ${LibArchive_LIBRARIES}) +endif() + +add_library(hi-backends ${BACKEND_SRCS}) +target_link_libraries(hi-backends ${BACKEND_LIBS}) +install(TARGETS hi-backends DESTINATION lib) diff --git a/image/backends/basic.cc b/image/backends/basic.cc index bec3e41..0aa1afa 100644 --- a/image/backends/basic.cc +++ b/image/backends/basic.cc @@ -15,10 +15,8 @@ namespace Horizon { namespace Image { -std::vector known_backends = { - {"tar", "Create a tarball (.tar)", [](std::string, std::string){ return nullptr; } }, - {"squashfs", "Create a SquashFS image (.squashfs)", [](std::string, std::string){ return nullptr; } } -}; +std::vector known_backends +__attribute__ ((init_priority(200))); const std::vector BackendManager::available_backends() { return known_backends; diff --git a/image/backends/basic.hh b/image/backends/basic.hh index 95b94ae..d57a9ac 100644 --- a/image/backends/basic.hh +++ b/image/backends/basic.hh @@ -47,9 +47,9 @@ public: /*! The intermediate directory which contains the sysroot the image * should contain. */ - const std::string &ir_dir; + const std::string ir_dir; /*! The path at which to write the image. */ - const std::string &out_path; + const std::string out_path; }; struct BackendDescriptor { diff --git a/image/backends/tar.cc b/image/backends/tar.cc new file mode 100644 index 0000000..d4ed584 --- /dev/null +++ b/image/backends/tar.cc @@ -0,0 +1,114 @@ +/* + * tar.cc - Implementation of the tarball 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 "util/output.hh" + +namespace Horizon { +namespace Image { + +class TarBackend : public BasicBackend { +public: + enum CompressionType { + None, + GZip, + BZip2, + XZ + }; + +private: + CompressionType comp; + struct archive *a; + +public: + TarBackend(std::string ir, std::string out, CompressionType _c = None) + : BasicBackend(ir, out), comp(_c) {}; + + int prepare() override { + int res; + + a = archive_write_new(); + archive_write_set_format_pax_restricted(a); + + switch(comp) { + case None: + break; + case GZip: + archive_write_add_filter_gzip(a); + break; + case BZip2: + archive_write_add_filter_bzip2(a); + break; + case XZ: + archive_write_add_filter_xz(a); + break; + } + + res = archive_write_open_filename(a, this->out_path.c_str()) < ARCHIVE_OK; + if(res < ARCHIVE_OK) { + if(res < ARCHIVE_WARN) { + output_error("tar backend", archive_error_string(a)); + return res; + } else { + output_warning("tar backend", archive_error_string(a)); + } + } + + return 0; + } + + int create() override { + return 0; + } + + int finalise() override { + archive_write_close(a); + archive_write_free(a); + + return 0; + } +}; + +__attribute__((constructor(400))) +void register_tar_backend() { + BackendManager::register_backend( + {"tar", "Create a tarball (.tar)", + [](std::string ir_dir, std::string out_path) { + return new TarBackend(ir_dir, out_path); + } + }); + + BackendManager::register_backend( + {"tgz", "Create a tarball with GZ compression (.tar.gz)", + [](std::string ir_dir, std::string out_path) { + return new TarBackend(ir_dir, out_path, TarBackend::GZip); + } + }); + + BackendManager::register_backend( + {"tbz", "Create a tarball with BZip2 compression (.tar.bz2)", + [](std::string ir_dir, std::string out_path) { + return new TarBackend(ir_dir, out_path, TarBackend::BZip2); + } + }); + + BackendManager::register_backend( + {"txz", "Create a tarball with XZ compression (.tar.xz)", + [](std::string ir_dir, std::string out_path) { + return new TarBackend(ir_dir, out_path, TarBackend::XZ); + } + }); +} + +} +} diff --git a/image/creator.cc b/image/creator.cc index b16504a..805e13b 100644 --- a/image/creator.cc +++ b/image/creator.cc @@ -112,6 +112,14 @@ int main(int argc, char *argv[]) { output_path = vm["output"].as(); } + /* Announce our presence */ + std::cout << "HorizonScript Image Creation Utility version " << VERSTR + << std::endl + << "Copyright (c) 2020 Adélie Linux and contributors." + << std::endl + << "This software is licensed to you under the AGPL 3.0, " + << "unless otherwise noted." << std::endl << std::endl; + /* Load the proper backend. */ for(const auto &candidate : BackendManager::available_backends()) { if(candidate.type_code == type_code) { @@ -142,6 +150,8 @@ int main(int argc, char *argv[]) { } else { int ret; + my_script->setTargetDirectory(ir_dir); + if(!my_script->execute()) { exit_code = EXIT_FAILURE; goto trouble; -- cgit v1.2.3-60-g2f50