diff options
author | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2020-03-11 11:44:42 -0500 |
---|---|---|
committer | A. Wilcox <AWilcox@Wilcox-Tech.com> | 2020-03-11 11:44:42 -0500 |
commit | b8f4ce3bdb1f3ea76eef1c0c4fd7dd5d29259336 (patch) | |
tree | a95e0ccf5242a2c1a52b118dd04138a64d3f7546 | |
parent | bcff79985ebe4c2d09eda749a99a005dc65b6b52 (diff) | |
download | horizon-b8f4ce3bdb1f3ea76eef1c0c4fd7dd5d29259336.tar.gz horizon-b8f4ce3bdb1f3ea76eef1c0c4fd7dd5d29259336.tar.bz2 horizon-b8f4ce3bdb1f3ea76eef1c0c4fd7dd5d29259336.tar.xz horizon-b8f4ce3bdb1f3ea76eef1c0c4fd7dd5d29259336.zip |
hscript: Make target directory configurable
This is the first step towards creating images using Horizon.
-rw-r--r-- | hscript/disk.cc | 15 | ||||
-rw-r--r-- | hscript/meta.cc | 81 | ||||
-rw-r--r-- | hscript/network.cc | 6 | ||||
-rw-r--r-- | hscript/script.cc | 9 | ||||
-rw-r--r-- | hscript/script.hh | 6 | ||||
-rw-r--r-- | hscript/script_e.cc | 122 | ||||
-rw-r--r-- | hscript/script_i.hh | 3 | ||||
-rw-r--r-- | hscript/user.cc | 30 |
8 files changed, 165 insertions, 107 deletions
diff --git a/hscript/disk.cc b/hscript/disk.cc index e1111f6..1f6d3b3 100644 --- a/hscript/disk.cc +++ b/hscript/disk.cc @@ -783,7 +783,8 @@ bool Mount::validate() const { } bool Mount::execute() const { - const std::string actual_mount = "/target" + this->mountpoint(); + const std::string actual_mount(script->targetDirectory() + + this->mountpoint()); const char *fstype = nullptr; #ifdef HAS_INSTALL_ENV error_code ec; @@ -853,24 +854,26 @@ bool Mount::execute() const { "defaults" : this->options()); if(script->options().test(Simulate)) { if(this->mountpoint() == "/") { - std::cout << "mkdir -p /target/etc" << std::endl; + std::cout << "mkdir -p " << script->targetDirectory() << "/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; + << " >> " << script->targetDirectory() << "/etc/fstab" + << std::endl; } #ifdef HAS_INSTALL_ENV else { if(this->mountpoint() == "/") { - fs::create_directory("/target/etc", ec); + fs::create_directory(script->targetDirectory() + "/etc", ec); if(ec) { output_error("installfile:" + std::to_string(this->lineno()), "mount: failed to create /etc for target", ec.message()); return false; } - fs::permissions("/target/etc", rwxr_xr_x, + fs::permissions(script->targetDirectory() + "/etc", rwxr_xr_x, #if defined(FS_IS_STDCXX) fs::perm_options::replace, #endif @@ -881,7 +884,7 @@ bool Mount::execute() const { ec.message()); } } - std::ofstream fstab_f("/target/etc/fstab"); + std::ofstream fstab_f(script->targetDirectory() + "/etc/fstab"); if(!fstab_f) { output_error("installfile:" + std::to_string(this->lineno()), "mount: failure opening /etc/fstab for writing"); diff --git a/hscript/meta.cc b/hscript/meta.cc index bfaabb3..8fedb32 100644 --- a/hscript/meta.cc +++ b/hscript/meta.cc @@ -109,12 +109,13 @@ bool Hostname::execute() const { output_info("installfile:" + std::to_string(this->lineno()), "hostname: write '" + actual + "' to /etc/hostname"); if(script->options().test(Simulate)) { - std::cout << "printf '%s' " << actual << " > /target/etc/hostname" - << std::endl; + std::cout << "printf '%s' " << actual << " > " + << script->targetDirectory() << "/etc/hostname" << std::endl; } #ifdef HAS_INSTALL_ENV else { - std::ofstream hostname_f("/target/etc/hostname", std::ios_base::trunc); + std::ofstream hostname_f(script->targetDirectory() + "/etc/hostname", + std::ios_base::trunc); if(!hostname_f) { output_error("installfile:" + std::to_string(this->lineno()), "hostname: could not open /etc/hostname for writing"); @@ -131,23 +132,26 @@ bool Hostname::execute() const { output_info("installfile:" + std::to_string(this->lineno()), "hostname: set domain name '" + domain + "'"); if(script->options().test(Simulate)) { - std::cout << "mkdir -p /target/etc/conf.d" << std::endl; + std::cout << "mkdir -p " << script->targetDirectory() + << "/etc/conf.d" << std::endl; std::cout << "printf 'dns_domain_lo=\"" << domain - << "\"\\" << "n' >> /target/etc/conf.d/net" << std::endl; + << "\"\\" << "n' >> " << script->targetDirectory() + << "/etc/conf.d/net" << std::endl; } #ifdef HAS_INSTALL_ENV else { - if(!fs::exists("/target/etc/conf.d")) { + if(!fs::exists(script->targetDirectory() + "/etc/conf.d")) { error_code ec; - fs::create_directory("/target/etc/conf.d", ec); + fs::create_directory(script->targetDirectory() + + "/etc/conf.d", ec); if(ec) { output_error("installfile:" + std::to_string(line), "hostname: could not create /etc/conf.d " "directory", ec.message()); } } - std::ofstream net_conf_f("/target/etc/conf.d/net", - std::ios_base::app); + std::ofstream net_conf_f(script->targetDirectory() + + "/etc/conf.d/net", std::ios_base::app); if(!net_conf_f) { output_error("installfile:" + std::to_string(this->lineno()), "hostname: could not open /etc/conf.d/net for " @@ -199,12 +203,14 @@ bool Arch::execute() const { if(script->options().test(Simulate)) { std::cout << "printf '" << this->value() << "\\" << "n'" - << " > /target/etc/apk/arch" << std::endl; + << " > " << script->targetDirectory() << "/etc/apk/arch" + << std::endl; return true; } #ifdef HAS_INSTALL_ENV - std::ofstream arch_f("/target/etc/apk/arch", std::ios_base::trunc); + std::ofstream arch_f(script->targetDirectory() + "/etc/apk/arch", + std::ios_base::trunc); if(!arch_f) { output_error("installfile:" + std::to_string(line), "arch: cannot write target CPU architecture information"); @@ -334,20 +340,21 @@ bool Language::execute() const { if(script->options().test(Simulate)) { std::cout << "printf '#!/bin/sh\\" << "nexport LANG=\"%s\"\\" << "n' " - << this->value() << " > /target/etc/profile.d/language.sh" - << std::endl - << "chmod a+x /target/etc/profile.d/language.sh" - << std::endl; + << this->value() << " > " << script->targetDirectory() + << "/etc/profile.d/00-language.sh" << std::endl + << "chmod a+x " << script->targetDirectory() + << "/etc/profile.d/00-language.sh" << std::endl; return true; } #ifdef HAS_INSTALL_ENV - const char *lang_path = "/target/etc/profile.d/language.sh"; + std::string lang_path = script->targetDirectory() + + "/etc/profile.d/00-language.sh"; std::ofstream lang_f(lang_path, std::ios_base::trunc); error_code ec; if(!lang_f) { output_error("installfile:" + std::to_string(this->lineno()), - "language: could not open /etc/profile.d/language.sh " + "language: could not open /etc/profile.d/00-language.sh " "for writing"); return false; } @@ -358,7 +365,7 @@ bool Language::execute() const { fs::permissions(lang_path, rwxr_xr_x, ec); if(ec) { output_error("installfile:" + std::to_string(this->lineno()), - "language: could not set /etc/profile.d/language.sh " + "language: could not set /etc/profile.d/00-language.sh " "as executable", ec.message()); return false; } @@ -402,15 +409,15 @@ BACKSPACE=guess" "keymap: setting system keyboard map to " + _value); if(script->options().test(Simulate)) { - std::cout << "cat >/target/etc/default/keyboard <<-KEYCONF" - << std::endl; + std::cout << "cat >" << script->targetDirectory() + << "/etc/default/keyboard <<-KEYCONF" << std::endl; std::cout << conf << std::endl; std::cout << "KEYCONF" << std::endl; return true; } #ifdef HAS_INSTALL_ENV - std::ofstream keyconf("/target/etc/default/keyboard", + std::ofstream keyconf(script->targetDirectory() + "/etc/default/keyboard", std::ios_base::trunc); if(!keyconf) { output_error("installfile:" + std::to_string(line), @@ -494,19 +501,23 @@ bool Timezone::execute() const { if(script->options().test(Simulate)) { /* If the target doesn't have tzdata installed, copy the zoneinfo from * the Horizon environment. */ - std::cout << "([ -f /target/usr/share/zoneinfo/" << this->value() + std::cout << "([ -f " << script->targetDirectory() + << "/usr/share/zoneinfo/" << this->value() << " ] && ln -s /usr/share/zoneinfo/" << this->value() - << " /target/etc/localtime) || cp /usr/share/zoneinfo/" - << this->value() << " /target/etc/localtime" << std::endl; + << " " << script->targetDirectory() << "/etc/localtime) || " + << "cp /usr/share/zoneinfo/" << this->value() + << " " << script->targetDirectory() << "/etc/localtime" + << std::endl; return true; } #ifdef HAS_INSTALL_ENV std::string zi_path = "/usr/share/zoneinfo/" + this->value(); - std::string target_zi = "/target" + zi_path; + std::string target_zi = script->targetDirectory() + zi_path; + std::string target_lt = script->targetDirectory() + "/etc/localtime"; error_code ec; if(fs::exists(target_zi, ec)) { - fs::create_symlink(zi_path, "/target/etc/localtime", ec); + fs::create_symlink(zi_path, target_lt, ec); if(ec) { output_error("installfile:" + std::to_string(this->lineno()), "timezone: failed to create symbolic link", @@ -517,7 +528,7 @@ bool Timezone::execute() const { } else { /* The target doesn't have tzdata installed. We copy the zoneinfo * file from the Horizon environment to the target. */ - fs::copy_file(zi_path, "/target/etc/localtime", ec); + fs::copy_file(zi_path, target_lt, ec); if(ec) { output_error("installfile:" + std::to_string(this->lineno()), "timezone: failed to prepare target environment", @@ -554,13 +565,14 @@ bool Repository::execute() const { "repository: write '" + this->value() + "' to /etc/apk/repositories"); if(script->options().test(Simulate)) { - std::cout << "echo '" << this->value() << - "' >> /target/etc/apk/repositories" << std::endl; + std::cout << "echo '" << this->value() + << "' >> " << script->targetDirectory() + << "/etc/apk/repositories" << std::endl; return true; } #ifdef HAS_INSTALL_ENV - std::ofstream repo_f("/target/etc/apk/repositories", + std::ofstream repo_f(script->targetDirectory() + "/etc/apk/repositories", std::ios_base::app); if(!repo_f) { output_error("installfile:" + std::to_string(this->lineno()), @@ -598,13 +610,14 @@ bool SigningKey::execute() const { /* everything after the last / in the value is the filename */ const std::string name(_value.substr(_value.find_last_of('/') + 1)); - const std::string target("/target/etc/apk/keys/" + name); + const std::string target_dir(script->targetDirectory() + "/etc/apk/keys/"); + const std::string target(target_dir + name); output_info("installfile:" + std::to_string(line), "signingkey: trusting " + name + " for repository signing"); if(script->options().test(Simulate)) { - std::cout << "mkdir -p /target/etc/apk/keys" << std::endl; + std::cout << "mkdir -p " << target_dir << std::endl; if(_value[0] == '/') { std::cout << "cp " << _value << " " << target << std::endl; } else { @@ -615,8 +628,8 @@ bool SigningKey::execute() const { #ifdef HAS_INSTALL_ENV error_code ec; - if(!fs::exists("/target/etc/apk/keys")) { - fs::create_directory("/target/etc/apk/keys", ec); + if(!fs::exists(target_dir)) { + fs::create_directory(target_dir, ec); if(ec) { output_error("installfile:" + std::to_string(line), "signingkey: could not initialise target repository " diff --git a/hscript/network.cc b/hscript/network.cc index 3741b0c..1750a60 100644 --- a/hscript/network.cc +++ b/hscript/network.cc @@ -347,12 +347,14 @@ Key *Nameserver::parseFromData(const std::string &data, int lineno, bool Nameserver::execute() const { if(script->options().test(Simulate)) { std::cout << "printf 'nameserver %s\\" << "n' " << _value - << " >>/target/etc/resolv.conf" << std::endl; + << " >>" << script->targetDirectory() << "/etc/resolv.conf" + << std::endl; return true; } #ifdef HAS_INSTALL_ENV - std::ofstream resolvconf("/target/etc/resolv.conf", std::ios_base::app); + std::ofstream resolvconf(script->targetDirectory() + "/etc/resolv.conf", + std::ios_base::app); if(!resolvconf) { output_error("installfile:" + std::to_string(line), "nameserver: couldn't write configuration to target"); diff --git a/hscript/script.cc b/hscript/script.cc index 9073e04..7db3ed0 100644 --- a/hscript/script.cc +++ b/hscript/script.cc @@ -168,6 +168,7 @@ bool Script::ScriptPrivate::store_key(const std::string &key_name, Key *obj, Script::Script() { internal = new ScriptPrivate; + internal->target = "/target"; } Script::~Script() { @@ -319,6 +320,14 @@ const Script *Script::load(std::istream &sstream, } /* LCOV_EXCL_START */ +const std::string Script::targetDirectory() const { + return this->internal->target; +} + +void Script::setTargetDirectory(const std::string &dir) { + this->internal->target = dir; +} + const Keys::Key *Script::getOneValue(std::string name) const { if(name == "network") { return this->internal->network.get(); diff --git a/hscript/script.hh b/hscript/script.hh index 8cf6c2a..e664f58 100644 --- a/hscript/script.hh +++ b/hscript/script.hh @@ -80,6 +80,12 @@ public: /*! Executes the HorizonScript. */ bool execute() const; + /*! Retrieve the current target directory. */ + const std::string targetDirectory() const; + + /*! Set the current target directory. */ + void setTargetDirectory(const std::string &dir); + /*! Retrieve the value of a specified key in this HorizonScript. * @param name The name of the key to retrieve. * @return The key object, if one exists. nullptr if the key has not been diff --git a/hscript/script_e.cc b/hscript/script_e.cc index 8360b28..ea430dc 100644 --- a/hscript/script_e.cc +++ b/hscript/script_e.cc @@ -28,25 +28,23 @@ namespace Horizon { static bool icon_dir_created = false; -void maybe_create_icon_dir(ScriptOptions opts) { +void maybe_create_icon_dir(ScriptOptions opts, const std::string &target) { if(icon_dir_created) return; icon_dir_created = true; + const std::string icon_dir(target + "/var/lib/AccountsService/icons"); + if(opts.test(Simulate)) { - std::cout << "mkdir -p /target/var/lib/AccountsService/icons" - << std::endl - << "chown root:root /target/var/lib/AccountsService/icons" - << std::endl - << "chmod 775 /target/var/lib/AccountsService/icons" - << std::endl; + std::cout << "mkdir -p " << icon_dir << std::endl + << "chown root:root " << icon_dir << std::endl + << "chmod 775 " << icon_dir << std::endl; return; } #ifdef HAS_INSTALL_ENV else { error_code ec; - if(!fs::exists("/target/var/lib/AccountsService/icons", ec)) { - fs::create_directories("/target/var/lib/AccountsService/icons", - ec); + if(!fs::exists(icon_dir, ec)) { + fs::create_directories(icon_dir, ec); if(ec) { output_error("internal", "couldn't create icon dir", ec.message()); @@ -60,6 +58,7 @@ bool Script::execute() const { bool success; error_code ec; std::set<std::string> ifaces; + const std::string targ_etc(targetDirectory() + "/etc"); /* assume create_directory will give us the error if removal fails */ if(fs::exists("/tmp/horizon", ec)) { @@ -167,12 +166,12 @@ bool Script::execute() const { /* REQ: Runner.Execute.repository */ if(opts.test(Simulate)) { - std::cout << "mkdir -p /target/etc/apk" << std::endl; + std::cout << "mkdir -p " << targ_etc << "/apk" << std::endl; } #ifdef HAS_INSTALL_ENV else { - if(!fs::exists("/target/etc/apk", ec)) { - fs::create_directory("/target/etc/apk", ec); + if(!fs::exists(targ_etc + "/apk", ec)) { + fs::create_directory(targ_etc + "/apk", ec); if(ec) { output_error("internal", "failed to initialise APK"); EXECUTE_FAILURE("pre-metadata"); @@ -221,7 +220,8 @@ bool Script::execute() const { if(opts.test(Simulate)) { std::ifstream wpai("/tmp/horizon/wpa_supplicant.conf"); if(wpai) { - std::cout << "cat >/target/etc/wpa_supplicant/wpa_supplicant.conf " + std::cout << "cat >" << targetDirectory() + << "/etc/wpa_supplicant/wpa_supplicant.conf " << "<<- WPA_EOF" << std::endl << wpai.rdbuf() << std::endl << "WPA_EOF" << std::endl; @@ -232,11 +232,12 @@ bool Script::execute() const { } #ifdef HAS_INSTALL_ENV else { - if(!fs::exists("/target/etc/wpa_supplicant", ec)) { - fs::create_directory("/target/etc/wpa_supplicant", ec); + const std::string wpa_dir(targ_etc + "/wpa_supplicant"); + if(!fs::exists(wpa_dir, ec)) { + fs::create_directory(wpa_dir, ec); } fs::copy_file("/tmp/horizon/wpa_supplicant.conf", - "/target/etc/wpa_supplicant/wpa_supplicant.conf", + wpa_dir + "/wpa_supplicant.conf", fs_overwrite, ec); if(ec) { output_error("internal", "cannot save wireless networking " @@ -280,21 +281,21 @@ bool Script::execute() const { } if(opts.test(Simulate)) { - std::cout << "mkdir -p /target/etc/conf.d" << std::endl; - std::cout << "cat >>/target/etc/conf.d/net <<- NETCONF_EOF" + std::cout << "mkdir -p " << targ_etc << "/conf.d" << std::endl; + std::cout << "cat >>/" << targ_etc << "/conf.d/net <<- NETCONF_EOF" << std::endl << conf.str() << std::endl << "NETCONF_EOF" << std::endl; } #ifdef HAS_INSTALL_ENV else { - if(!fs::exists("/target/etc/conf.d")) { - fs::create_directory("/target/etc/conf.d", ec); + if(!fs::exists(targ_etc + "/conf.d")) { + fs::create_directory(targ_etc + "/conf.d", ec); if(ec) { output_error("internal", "could not create /etc/conf.d " "directory", ec.message()); } } - std::ofstream conf_file("/target/etc/conf.d/net", + std::ofstream conf_file(targ_etc + "/conf.d/net", std::ios_base::app); if(!conf_file) { output_error("internal", "cannot save network configuration " @@ -320,11 +321,11 @@ bool Script::execute() const { const std::string domain(hostname.substr(dot + 1)); if(opts.test(Simulate)) { std::cout << "printf 'domain " << domain << "\\" - << "n >>/target/etc/resolv.conf" << std::endl; + << "n >>" << targ_etc << "/resolv.conf" << std::endl; } #ifdef HAS_INSTALL_ENV else { - std::ofstream resolvconf("/target/etc/resolv.conf", + std::ofstream resolvconf(targ_etc + "/resolv.conf", std::ios_base::app); if(!resolvconf) { output_error("internal", "failed to open resolv.conf"); @@ -338,14 +339,14 @@ bool Script::execute() const { if(dhcp) { if(opts.test(Simulate)) { - std::cout << "mv /target/etc/resolv.conf " - << "/target/etc/resolv.conf.head" << std::endl; + std::cout << "mv " << targ_etc << "/resolv.conf " + << targ_etc << "/resolv.conf.head" << std::endl; } #ifdef HAS_INSTALL_ENV else { - if(fs::exists("/target/etc/resolv.conf", ec)) { - fs::rename("/target/etc/resolv.conf", - "/target/etc/resolv.conf.head", ec); + if(fs::exists(targ_etc + "/resolv.conf", ec)) { + fs::rename(targ_etc + "/resolv.conf", + targ_etc + "/resolv.conf.head", ec); if(ec) { output_error("internal", "cannot save nameserver configuration", @@ -366,20 +367,22 @@ bool Script::execute() const { if(opts.test(Simulate)) { if(do_wpa) { - std::cout << "cp /target/etc/wpa_supplicant/wpa_supplicant.conf " + std::cout << "cp " << targ_etc + << "/wpa_supplicant/wpa_supplicant.conf " << "/etc/wpa_supplicant/wpa_supplicant.conf" << std::endl; } - std::cout << "cp /target/etc/conf.d/net /etc/conf.d/net" + std::cout << "cp " << targ_etc << "/conf.d/net /etc/conf.d/net" << std::endl; if(!internal->nses.empty()) { - std::cout << "cp /target/etc/resolv.conf* /etc/" << std::endl; + std::cout << "cp " << targ_etc << "/resolv.conf* /etc/" + << std::endl; } } #ifdef HAS_INSTALL_ENV else { if(do_wpa) { - fs::copy_file("/target/etc/wpa_supplicant/wpa_supplicant.conf", + fs::copy_file(targ_etc + "/wpa_supplicant/wpa_supplicant.conf", "/etc/wpa_supplicant/wpa_supplicant.conf", fs_overwrite, ec); if(ec) { @@ -388,7 +391,7 @@ bool Script::execute() const { EXECUTE_FAILURE("network"); } } - fs::copy_file("/target/etc/conf.d/net", "/etc/conf.d/net", + fs::copy_file(targ_etc + "/conf.d/net", "/etc/conf.d/net", fs_overwrite, ec); if(ec) { output_error("internal", "cannot use networking configuration " @@ -409,10 +412,10 @@ bool Script::execute() const { } if(!internal->nses.empty()) { if(dhcp) { - fs::copy_file("/target/etc/resolv.conf.head", + fs::copy_file(targ_etc + "/resolv.conf.head", "/etc/resolv.conf.head", ec); } else { - fs::copy_file("/target/etc/resolv.conf", + fs::copy_file(targ_etc + "/resolv.conf", "/etc/resolv.conf", ec); } @@ -439,11 +442,13 @@ bool Script::execute() const { /* REQ: Runner.Execute.pkginstall.APKDB */ output_info("internal", "initialising APK"); if(opts.test(Simulate)) { - std::cout << "apk --root /target --initdb add" << std::endl; + std::cout << "/sbin/apk --root " << targetDirectory() << " --initdb add" + << std::endl; } #ifdef HAS_INSTALL_ENV else { - if(system("apk --root /target --initdb add") != 0) { + if(run_command("/sbin/apk", + {"--root", targetDirectory(), "--initdb", "add"}) != 0) { EXECUTE_FAILURE("pkginstall"); return false; } @@ -457,22 +462,31 @@ bool Script::execute() const { /* REQ: Runner.Execute.pkginstall */ output_info("internal", "installing packages to target"); - std::ostringstream pkg_list; - for(auto &pkg : this->internal->packages) { - pkg_list << pkg << " "; - } if(opts.test(Simulate)) { - std::cout << "apk --root /target update" << std::endl; - std::cout << "apk --root /target add " << pkg_list.str() << std::endl; + std::ostringstream pkg_list; + for(auto &pkg : this->internal->packages) { + pkg_list << pkg << " "; + } + + std::cout << "apk --root " << targetDirectory() << " update" + << std::endl; + std::cout << "apk --root " << targetDirectory() << " add " + << pkg_list.str() << std::endl; } #ifdef HAS_INSTALL_ENV else { - if(system("apk --root /target update") != 0) { + if(run_command("/sbin/apk", + {"--root", targetDirectory(), "update"}) != 0) { EXECUTE_FAILURE("pkginstall"); return false; } - std::string apk_invoc = "apk --root /target add " + pkg_list.str(); - if(system(apk_invoc.c_str()) != 0) { + + std::vector<std::string> params = {"--root", targetDirectory(), "add"}; + std::copy(this->internal->packages.begin(), + this->internal->packages.end(), + params.end()); + + if(run_command("/sbin/apk", params) != 0) { EXECUTE_FAILURE("pkginstall"); return false; } @@ -489,24 +503,24 @@ bool Script::execute() const { /* REQ: Runner.Execute.netaddress.OpenRC */ if(opts.test(Simulate)) { for(auto &iface : ifaces) { - std::cout << "ln -s /etc/init.d/net.lo /target/etc/init.d/net." - << iface << std::endl; + std::cout << "ln -s /etc/init.d/net.lo " << targ_etc + << "/init.d/net." << iface << std::endl; std::cout << "ln -s /etc/init.d/net." << iface - << " /target/etc/runlevels/default/net." << iface - << std::endl; + << " " << targ_etc << "/runlevels/default/net." + << iface << std::endl; } } #ifdef HAS_INSTALL_ENV else { for(auto &iface : ifaces) { fs::create_symlink("/etc/init.d/net.lo", - "/target/etc/init.d/net." + iface, ec); + targ_etc + "/init.d/net." + iface, ec); if(ec) { output_error("internal", "could not set up networking on " + iface, ec.message()); } else { fs::create_symlink("/etc/init.d/net." + iface, - "/target/etc/runlevels/default/net." + + targ_etc + "/runlevels/default/net." + iface, ec); if(ec) { output_error("internal", "could not auto-start " @@ -544,7 +558,7 @@ bool Script::execute() const { } } if(acct.second->icon) { - maybe_create_icon_dir(opts); + maybe_create_icon_dir(opts, targetDirectory()); EXECUTE_OR_FAIL("usericon", acct.second->icon) } } diff --git a/hscript/script_i.hh b/hscript/script_i.hh index 9d854eb..0ed362e 100644 --- a/hscript/script_i.hh +++ b/hscript/script_i.hh @@ -38,6 +38,9 @@ struct UserDetail { }; struct Script::ScriptPrivate { + /*! Determines the target directory (usually /target) */ + std::string target; + /*! Determines whether or not to enable networking. */ std::unique_ptr<Network> network; /*! The target system's hostname. */ diff --git a/hscript/user.cc b/hscript/user.cc index 82d627c..81deafd 100644 --- a/hscript/user.cc +++ b/hscript/user.cc @@ -143,17 +143,21 @@ bool RootPassphrase::execute() const { if(script->options().test(Simulate)) { std::cout << "(printf '" << root_line << "\\" << "n'; " - << "cat /target/etc/shadow | sed '1d') > /tmp/shadow" + << "cat " << script->targetDirectory() << "/etc/shadow |" + << "sed '1d') > /tmp/shadow" << std::endl - << "mv /tmp/shadow /target/etc/shadow" << std::endl - << "chown root:shadow /target/etc/shadow" << std::endl - << "chmod 640 /target/etc/shadow" << std::endl; + << "mv /tmp/shadow " << script->targetDirectory() + << "/etc/shadow" << std::endl + << "chown root:shadow " << script->targetDirectory() + << "/etc/shadow" << std::endl + << "chmod 640 " << script->targetDirectory() + << "/etc/shadow" << std::endl; return true; } #ifdef HAS_INSTALL_ENV /* This was tested on gwyn during development. */ - std::ifstream old_shadow("/target/etc/shadow"); + std::ifstream old_shadow(script->targetDirectory() + "/etc/shadow"); if(!old_shadow) { output_error("installfile:" + std::to_string(this->lineno()), "rootpw: cannot open existing shadow file"); @@ -175,7 +179,8 @@ bool RootPassphrase::execute() const { old_shadow.close(); - std::ofstream new_shadow("/target/etc/shadow", std::ios_base::trunc); + std::ofstream new_shadow(script->targetDirectory() + "/etc/shadow", + std::ios_base::trunc); if(!new_shadow) { output_error("installfile:" + std::to_string(this->lineno()), "rootpw: cannot replace target shadow file"); @@ -349,9 +354,10 @@ bool UserIcon::validate() const { } bool UserIcon::execute() const { - const std::string as_path("/target/var/lib/AccountsService/icons/" + - _username); - const std::string face_path("/target/home/" + _username + "/.face"); + const std::string as_path(script->targetDirectory() + + "/var/lib/AccountsService/icons/" + _username); + const std::string face_path(script->targetDirectory() + "/home/" + + _username + "/.face"); output_info("installfile:" + std::to_string(line), "usericon: setting avatar for " + _username); @@ -363,8 +369,10 @@ bool UserIcon::execute() const { std::cout << "curl -LO " << as_path << " " << _icon_path << std::endl; } - std::cout << "cp " << as_path << " " << face_path << ".icon" << std::endl; - std::cout << "chown $(hscript-printowner /target/home/" << _username + std::cout << "cp " << as_path << " " << face_path << ".icon" + << std::endl; + std::cout << "chown $(hscript-printowner " << script->targetDirectory() + << "/home/" << _username << ") " << face_path << ".icon" << std::endl; std::cout << "ln -s .face.icon " << face_path << std::endl; return true; |