summaryrefslogtreecommitdiff
path: root/hscript
diff options
context:
space:
mode:
Diffstat (limited to 'hscript')
-rw-r--r--hscript/disk.cc45
-rw-r--r--hscript/disk.hh18
-rw-r--r--hscript/script.cc25
3 files changed, 84 insertions, 4 deletions
diff --git a/hscript/disk.cc b/hscript/disk.cc
index f0466eb..cbd9517 100644
--- a/hscript/disk.cc
+++ b/hscript/disk.cc
@@ -16,7 +16,7 @@
#include <fstream>
#include <string>
#include <sys/mount.h> /* mount */
-#include <sys/stat.h> /* mkdir */
+#include <sys/stat.h> /* mkdir, stat */
#include <sys/types.h> /* S_* */
#include <unistd.h> /* access */
#include "disk.hh"
@@ -24,6 +24,49 @@
using namespace Horizon::Keys;
+Key *DiskId::parseFromData(const std::string &data, int lineno, int *errors,
+ int *warnings) {
+ std::string block, ident;
+ std::string::size_type block_end = data.find_first_of(' ');
+ if(block_end == std::string::npos) {
+ if(errors) *errors += 1;
+ output_error("installfile:" + std::to_string(lineno),
+ "diskid: expected an identification string",
+ "valid format for diskid is: [block] [id-string]");
+ return nullptr;
+ }
+
+ block = data.substr(0, block_end);
+ ident = data.substr(block_end + 1);
+ return new DiskId(lineno, block, ident);
+}
+
+bool DiskId::validate(ScriptOptions options) const {
+ /* We only validate if running in an Installation Environment. */
+ if(!options.test(InstallEnvironment)) return true;
+
+ /* Unlike 'mount', 'diskid' *does* require that the block device exist
+ * before installation begins. This test is always valid. */
+ struct stat blk_stat;
+ const char *block_c = _block.c_str();
+ if(access(block_c, F_OK) != 0 || stat(block_c, &blk_stat) != 0) {
+ output_error("installfile:" + std::to_string(line),
+ "diskid: error opening device " + _block,
+ strerror(errno));
+ return false;
+ }
+ if(!S_ISBLK(blk_stat.st_mode)) {
+ output_error("installfile:" + std::to_string(line),
+ "diskid: " + _block + " is not a valid block device");
+ return false;
+ }
+ return true;
+}
+
+bool DiskId::execute(ScriptOptions options) const {
+ return false;
+}
+
Key *Mount::parseFromData(const std::string &data, int lineno, int *errors,
int *warnings) {
std::string dev, where, opt;
diff --git a/hscript/disk.hh b/hscript/disk.hh
index d849e2f..02ecb98 100644
--- a/hscript/disk.hh
+++ b/hscript/disk.hh
@@ -19,6 +19,21 @@ namespace Horizon {
namespace Keys {
class DiskId : public Key {
+private:
+ const std::string _block;
+ const std::string _ident;
+
+ DiskId(int _line, const std::string &my_block, const std::string &my_i) :
+ Key(_line), _block(my_block), _ident(my_i) {}
+public:
+ /*! Retrieve the block device that this key identifies. */
+ const std::string device() const { return this->_block; }
+ /*! Retrieve the identification for the block device. */
+ const std::string ident() const { return this->_ident; }
+
+ static Key *parseFromData(const std::string &, int, int*, int*);
+ bool validate(ScriptOptions) const override;
+ bool execute(ScriptOptions) const override;
};
class DiskLabel : public Key {
@@ -60,8 +75,7 @@ public:
/*! Retrieve the mount options for this mount, if any. */
const std::string options() const { return this->_opts; }
- static Key *parseFromData(const std::string &data, int lineno, int *errors,
- int *warnings);
+ static Key *parseFromData(const std::string &, int, int*, int*);
bool validate(ScriptOptions) const override;
bool execute(ScriptOptions) const override;
};
diff --git a/hscript/script.cc b/hscript/script.cc
index f45c5f2..83957f8 100644
--- a/hscript/script.cc
+++ b/hscript/script.cc
@@ -86,6 +86,9 @@ struct Script::ScriptPrivate {
/*! APK repositories */
std::vector< std::unique_ptr<Horizon::Keys::Repository> > repos;
+ /*! Disk identification keys */
+ std::vector< std::unique_ptr<Horizon::Keys::DiskId> > diskids;
+
/*! Store +key_obj+ representing the key +key_name+.
* @param key_name The name of the key that is being stored.
* @param obj The Key object associated with the key.
@@ -164,6 +167,10 @@ struct Script::ScriptPrivate {
std::unique_ptr<Repository> repo(dynamic_cast<Repository *>(obj));
this->repos.push_back(std::move(repo));
return true;
+ } else if(key_name == "diskid") {
+ std::unique_ptr<DiskId> diskid(dynamic_cast<DiskId *>(obj));
+ this->diskids.push_back(std::move(diskid));
+ return true;
} else {
return false;
}
@@ -318,13 +325,29 @@ const Script *Script::load(std::istream &sstream, const ScriptOptions opts) {
bool Script::validate() const {
int failures = 0;
- std::set<std::string> seen_mounts;
+ std::set<std::string> seen_diskids, seen_mounts;
std::map<const std::string, int> seen_iface;
if(!this->internal->network->validate(this->opts)) failures++;
if(!this->internal->hostname->validate(this->opts)) failures++;
if(!this->internal->rootpw->validate(this->opts)) failures++;
+ for(auto &diskid : this->internal->diskids) {
+ if(!diskid->validate(this->opts)) {
+ failures++;
+ continue;
+ }
+
+ /* Runner.Validate.diskid.Unique */
+ if(seen_diskids.find(diskid->device()) != seen_diskids.end()) {
+ failures++;
+ output_error("installfile:" + std::to_string(diskid->lineno()),
+ "diskid: device " + diskid->device() +
+ " has already been identified");
+ }
+ seen_diskids.insert(diskid->device());
+ }
+
for(auto &mount : this->internal->mounts) {
if(!mount->validate(this->opts)) {
failures++;