aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-10-19 16:09:24 +0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-10-19 16:09:24 +0000
commit6a67556f7192108d612560992e97a14b0fe16a22 (patch)
tree2ca8124849c212d018f8fc6865b3bec696260717
parentdaa8f85fcd3d5d7c48a51305818e05bee866b936 (diff)
* Special derivation attribute `allowedReferences' that causes Nix to
check that the references of the output of a derivation are in the specified set. For instance, allowedReferences = []; specifies that the output cannot have any references. (This is useful, for instance, for the generation of bootstrap binaries for stdenv-linux, which must not have any references for purity). It could also be used to guard against undesired runtime dependencies, e.g., {gcc, dynlib}: derivation { ... allowedReferences = [dynlib]; } says that the output can refer to the path of `dynlib' but not `gcc'. A `forbiddedReferences' attribute would be more useful for this, though.
-rw-r--r--src/libstore/build.cc31
1 files changed, 31 insertions, 0 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 647671036..2388d008f 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1349,6 +1349,26 @@ void DerivationGoal::startBuilder()
}
+/* Parse a list of reference specifiers. Each element must either be
+ a store path, or the symbolic name of the output of the derivation
+ (such as `out'). */
+PathSet parseReferenceSpecifiers(const Derivation & drv, string attr)
+{
+ PathSet result;
+ Paths paths = tokenizeString(attr);
+ for (Strings::iterator i = paths.begin(); i != paths.end(); ++i) {
+ if (isStorePath(*i))
+ result.insert(*i);
+ else if (drv.outputs.find(*i) != drv.outputs.end())
+ result.insert(drv.outputs.find(*i)->second.path);
+ else throw Error(
+ format("derivation contains an illegal reference specifier `%1%'")
+ % *i);
+ }
+ return result;
+}
+
+
void DerivationGoal::computeClosure()
{
map<Path, PathSet> allReferences;
@@ -1442,6 +1462,17 @@ void DerivationGoal::computeClosure()
allReferences[path] = references;
+ /* If the derivation specifies an `allowedReferences'
+ attribute (containing a list of paths that the output may
+ refer to), check that all references are in that list. !!!
+ allowedReferences should really be per-output. */
+ if (drv.env.find("allowedReferences") != drv.env.end()) {
+ PathSet allowed = parseReferenceSpecifiers(drv, drv.env["allowedReferences"]);
+ for (PathSet::iterator i = references.begin(); i != references.end(); ++i)
+ if (allowed.find(*i) == allowed.end())
+ throw Error(format("output is not allowed to refer to path `%1%'") % *i);
+ }
+
/* Hash the contents of the path. The hash is stored in the
database so that we can verify later on whether nobody has
messed with the store. !!! inefficient: it would be nice