From 593301e2a40119d4861a6167cf808187ae255035 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Mon, 14 Oct 2019 13:37:47 -0500 Subject: hscript: Implement Mount::execute fully, including fstab manipulation --- CMakeLists.txt | 1 + hscript/CMakeLists.txt | 1 + hscript/disk.cc | 78 ++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3a8619..16f9f58 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ project(Horizon LANGUAGES CXX VERSION 0.1.0) +pkg_check_modules(BLKID REQUIRED blkid) pkg_check_modules(LIBUDEV REQUIRED libudev) pkg_check_modules(PARTED REQUIRED libparted) find_library(BCNM_LIBRARY REQUIRED wpactrl PATH_SUFFIXES bcnm) diff --git a/hscript/CMakeLists.txt b/hscript/CMakeLists.txt index 845ee82..60ca8a9 100644 --- a/hscript/CMakeLists.txt +++ b/hscript/CMakeLists.txt @@ -15,6 +15,7 @@ set(HSCRIPT_INCLUDE add_library(hscript SHARED ${HSCRIPT_SOURCE}) target_compile_features(hscript PRIVATE cxx_nullptr) target_compile_features(hscript PUBLIC cxx_unicode_literals) +target_link_libraries(hscript ${BLKID_LIBRARIES}) install(TARGETS hscript DESTINATION lib) install(FILES ${HSCRIPT_INCLUDE} DESTINATION include/hscript) diff --git a/hscript/disk.cc b/hscript/disk.cc index 8720b0b..f0466eb 100644 --- a/hscript/disk.cc +++ b/hscript/disk.cc @@ -11,8 +11,14 @@ */ #include +#include /* blkid_get_tag_value */ +#include /* strerror */ +#include #include -#include +#include /* mount */ +#include /* mkdir */ +#include /* S_* */ +#include /* access */ #include "disk.hh" #include "util/output.hh" @@ -77,19 +83,79 @@ bool Mount::validate(ScriptOptions options) const { bool Mount::execute(ScriptOptions options) const { const std::string actual_mount = "/target" + this->mountpoint(); + const char *fstype = nullptr; + /* We have to get the filesystem for the node. */ + if(options.test(Simulate)) { + fstype = "auto"; + } else { + fstype = blkid_get_tag_value(nullptr, "TYPE", this->device().c_str()); + if(fstype == nullptr) { + output_error("installfile:" + std::to_string(this->lineno()), + "mount: cannot determine filesystem type for device", + this->device()); + return false; + } + } + + output_info("installfile:" + std::to_string(this->lineno()), + "mount: mounting " + this->device() + " on " + + this->mountpoint()); if(options.test(Simulate)) { - output_info("installfile:" + std::to_string(this->lineno()), - "mount: mounting " + this->device() + " on " + - this->mountpoint()); std::cout << "mount "; if(!this->options().empty()) { std::cout << "-o " << this->options() << " "; } std::cout << this->device() << " " << actual_mount << std::endl; - return true; + } else { + /* mount */ + if(mount(this->device().c_str(), actual_mount.c_str(), fstype, 0, + this->options().c_str()) != 0) { + output_warning("installfile:" + std::to_string(this->lineno()), + "mount: error mounting " + this->mountpoint() + + "with options; retrying without", strerror(errno)); + if(mount(this->device().c_str(), actual_mount.c_str(), fstype, 0, + nullptr) != 0) { + output_error("installfile:" + std::to_string(this->lineno()), + "mount: error mounting " + this->mountpoint() + + "without options", strerror(errno)); + return false; + } + } + } + + /* Handle fstab. We're guaranteed to have a /target since mount has + * already ran and /target is the first mount done. + */ + output_info("installfile:" + std::to_string(this->lineno()), + "mount: adding " + this->mountpoint() + " to /etc/fstab"); + char pass = (this->mountpoint() == "/" ? '1' : '0'); + const std::string fstab_opts = (this->options().empty() ? + "defaults" : this->options()); + if(options.test(Simulate)) { + if(this->mountpoint() == "/") { + std::cout << "mkdir -p /target/etc" << std::endl; + } + std::cout << "printf '%s\\t%s\\t%s\\t%s\\t0\\t" << pass << "\\" + << "n' " << this->device() << " " << this->mountpoint() + << " " << fstype << " " << fstab_opts + << " >> /target/etc/fstab" << std::endl; + } else { + if(this->mountpoint() == "/") { + /* failure of mkdir will be handled in the !fstab_f case */ + mkdir("/target/etc", + S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + } + std::ofstream fstab_f("/target/etc/fstab"); + if(!fstab_f) { + output_error("installfile:" + std::to_string(this->lineno()), + "mount: failure opening /etc/fstab for writing"); + return false; + } + fstab_f << this->device() << "\t" << this->mountpoint() << "\t" + << fstype << "\t" << fstab_opts << "\t0\t" << pass + << std::endl; } - /* mount */ return true; } -- cgit v1.2.3-60-g2f50