* 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.
This commit is contained in:
Eelco Dolstra 2006-10-19 16:09:24 +00:00
parent daa8f85fcd
commit 6a67556f71
1 changed files with 31 additions and 0 deletions

View File

@ -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() void DerivationGoal::computeClosure()
{ {
map<Path, PathSet> allReferences; map<Path, PathSet> allReferences;
@ -1442,6 +1462,17 @@ void DerivationGoal::computeClosure()
allReferences[path] = references; 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 /* Hash the contents of the path. The hash is stored in the
database so that we can verify later on whether nobody has database so that we can verify later on whether nobody has
messed with the store. !!! inefficient: it would be nice messed with the store. !!! inefficient: it would be nice