about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2006-10-19T16·09+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2006-10-19T16·09+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 647671036d..2388d008f4 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