summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hscript/CMakeLists.txt4
-rw-r--r--hscript/network.cc36
-rw-r--r--hscript/script.cc97
3 files changed, 106 insertions, 31 deletions
diff --git a/hscript/CMakeLists.txt b/hscript/CMakeLists.txt
index 9043e2b..d0c5473 100644
--- a/hscript/CMakeLists.txt
+++ b/hscript/CMakeLists.txt
@@ -11,10 +11,12 @@ set(HSCRIPT_INCLUDE
script.hh
)
+find_package(Boost REQUIRED COMPONENTS filesystem)
+
add_library(hscript ${HSCRIPT_SOURCE})
target_compile_features(hscript PRIVATE cxx_nullptr)
target_compile_features(hscript PUBLIC cxx_unicode_literals)
-target_link_libraries(hscript ${BLKID_LIBRARIES} ${LIBUDEV_LIBRARIES} ${PARTED_LIBRARIES})
+target_link_libraries(hscript ${BLKID_LIBRARIES} ${Boost_FILESYSTEM_LIBRARY} ${LIBUDEV_LIBRARIES} ${PARTED_LIBRARIES})
install(TARGETS hscript DESTINATION lib)
install(FILES ${HSCRIPT_INCLUDE} DESTINATION include/hscript)
diff --git a/hscript/network.cc b/hscript/network.cc
index e375385..a47e69e 100644
--- a/hscript/network.cc
+++ b/hscript/network.cc
@@ -265,7 +265,41 @@ bool NetAddress::validate(ScriptOptions opts) const {
}
bool NetAddress::execute(ScriptOptions) const {
- return false;
+ std::ofstream config("/tmp/horizon/netifrc/config_" + this->iface(),
+ std::ios_base::app);
+ if(!config) {
+ output_error("installfile:" + std::to_string(this->lineno()),
+ "netaddress: couldn't write network configuration for "
+ + this->iface());
+ return false;
+ }
+
+ switch(this->type()) {
+ case DHCP:
+ config << "dhcp";
+ break;
+ case SLAAC:
+ /* automatically handled by netifrc */
+ break;
+ case Static:
+ config << this->address() << "/" << std::to_string(this->prefix())
+ << std::endl;
+ break;
+ }
+
+ if(!this->gateway().empty()) {
+ std::ofstream route("/tmp/horizon/netifrc/routes_" + this->iface(),
+ std::ios_base::app);
+ if(!route) {
+ output_error("installfile:" + std::to_string(this->lineno()),
+ "netaddress: couldn't write route configuration for "
+ + this->iface());
+ return false;
+ }
+ route << "default via " << this->gateway() << std::endl;
+ }
+
+ return true;
}
diff --git a/hscript/script.cc b/hscript/script.cc
index d58efb7..0e7e00d 100644
--- a/hscript/script.cc
+++ b/hscript/script.cc
@@ -12,13 +12,12 @@
#include <algorithm>
#include <assert.h>
-#include <cstring> /* strerror */
+#include <boost/filesystem.hpp>
#include <fstream>
#include <iostream>
#include <map>
#include <set>
#include <sstream>
-#include <sys/stat.h> /* mkdir */
#include "script.hh"
#include "disk.hh"
@@ -35,6 +34,8 @@ typedef Horizon::Keys::Key *(*key_parse_fn)(const std::string &, int, int*, int*
using namespace Horizon::Keys;
+namespace fs = boost::filesystem;
+
const std::map<std::string, key_parse_fn> valid_keys = {
{"network", &Network::parseFromData},
{"hostname", &Hostname::parseFromData},
@@ -880,13 +881,13 @@ bool Script::validate() const {
bool Script::execute() const {
bool success;
+ boost::system::error_code ec;
- if(mkdir("/tmp/horizon", S_IRUSR | S_IWUSR | S_IXUSR) != 0) {
- if(errno != EEXIST) {
- output_error("internal", "could not create temporary directory",
- ::strerror(errno));
- return false;
- }
+ if(!fs::exists("/tmp/horizon", ec) &&
+ !fs::create_directory("/tmp/horizon", ec)) {
+ output_error("internal", "could not create temporary directory",
+ ec.message());
+ return false;
}
/* REQ: Runner.Execute.Verify */
@@ -980,6 +981,7 @@ bool Script::execute() const {
<< "ctrl_interface=/var/run/wpa_supplicant" << std::endl
<< "ctrl_interface_group=wheel" << std::endl
<< "update_config=1" << std::endl;
+ wpao.close();
} else {
output_error("internal",
"cannot write wireless networking configuration");
@@ -992,36 +994,73 @@ bool Script::execute() const {
}
}
- std::ifstream wpai("/tmp/horizon/wpa_supplicant.conf");
- if(wpai) {
- if(opts.test(Simulate)) {
+ if(opts.test(Simulate)) {
+ std::ifstream wpai("/tmp/horizon/wpa_supplicant.conf");
+ if(wpai) {
std::cout << "cat >/target/etc/wpa_supplicant/wpa_supplicant.conf "
- << "<<- WPA_EOF" << std::endl;
- std::cout << wpai.rdbuf();
- std::cout << std::endl << "WPA_EOF" << std::endl;
+ << "<<- WPA_EOF" << std::endl
+ << wpai.rdbuf() << std::endl
+ << "WPA_EOF" << std::endl;
} else {
- std::ofstream target_wpa("/target/etc/wpa_supplicant/"
- "wpa_supplicant.conf",
- std::ios_base::trunc);
- if(!target_wpa) {
- output_error("internal", "cannot save wireless networking "
- "configuration to target");
- } else {
- target_wpa << wpai.rdbuf();
- }
+ output_error("internal",
+ "cannot read wireless networking configuration");
}
} else {
- output_error("internal",
- "cannot read wireless networking configuration");
+ fs::copy_file("/tmp/horizon/wpa_supplicant.conf",
+ "/target/etc/wpa_supplicant/wpa_supplicant.conf",
+ fs::copy_option::overwrite_if_exists,
+ ec);
+ if(ec.failed()) {
+ output_error("internal", "cannot save wireless networking "
+ "configuration to target", ec.message());
+ }
}
}
- for(auto &addr : this->internal->addresses) {
- if(!addr->execute(opts)) {
- EXECUTE_FAILURE("net");
- /* "Soft" error. Not fatal. */
+ if(!this->internal->addresses.empty()) {
+ fs::path netifrc_dir("/tmp/horizon/netifrc");
+ if(!fs::exists(netifrc_dir) &&
+ !fs::create_directory(netifrc_dir, ec)) {
+ output_error("internal", "cannot create temporary directory",
+ ec.message());
+ }
+
+ for(auto &addr : this->internal->addresses) {
+ if(!addr->execute(opts)) {
+ EXECUTE_FAILURE("net");
+ /* "Soft" error. Not fatal. */
+ }
+ }
+
+ std::ostringstream conf;
+ for(auto &&var_dent : fs::directory_iterator(netifrc_dir)) {
+ const std::string variable(var_dent.path().filename().string());
+ std::ifstream contents(var_dent.path().string());
+ if(!contents) {
+ output_error("internal", "cannot read network configuration");
+ continue;
+ }
+ conf << variable << "=\"";
+ if(contents.rdbuf()->in_avail()) conf << contents.rdbuf();
+ conf << "\"" << std::endl;
+ }
+
+ if(opts.test(Simulate)) {
+ std::cout << "cat >/target/etc/conf.d/net <<- NETCONF_EOF"
+ << std::endl << conf.str() << std::endl
+ << "NETCONF_EOF" << std::endl;
+ } else {
+ std::ofstream conf_file("/target/etc/conf.d/net",
+ std::ios_base::trunc);
+ if(!conf_file) {
+ output_error("internal", "cannot save network configuration "
+ "to target");
+ } else {
+ conf_file << conf.str();
+ }
}
}
+
if(!this->internal->network->execute(opts)) {
EXECUTE_FAILURE("net");
return false;