From 6a67556f7192108d612560992e97a14b0fe16a22 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 19 Oct 2006 16:09:24 +0000 Subject: * 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. --- src/libstore/build.cc | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/libstore') diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 647671036de1..2388d008f4cf 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 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 -- cgit 1.4.1