about summary refs log tree commit diff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2005-01-19T16·39+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2005-01-19T16·39+0000
commit96de272b48f8e9bdabffddb699ed4f2292d4f1d7 (patch)
tree6121797dd02605b2f01e2c28de0bef54e7446e8b /src/libstore
parentef5f254a55a2d6db09d3d0549ed45701558027e0 (diff)
* Renamed `normalise.cc' -> `build.cc', `storeexprs.cc' ->
  `derivations.cc', etc.
* Store the SHA-256 content hash of store paths in the database after
  they have been built/added.  This is so that we can check whether
  the store has been messed with (a la `rpm --verify').
* When registering path validity, verify that the closure property
  holds.

Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/Makefile.am14
-rw-r--r--src/libstore/build.cc (renamed from src/libstore/normalise.cc)72
-rw-r--r--src/libstore/build.hh (renamed from src/libstore/normalise.hh)8
-rw-r--r--src/libstore/derivations-ast.def (renamed from src/libstore/storeexpr-ast.def)2
-rw-r--r--src/libstore/derivations.cc (renamed from src/libstore/storeexpr.cc)6
-rw-r--r--src/libstore/derivations.hh (renamed from src/libstore/storeexpr.hh)6
-rw-r--r--src/libstore/gc.cc2
-rw-r--r--src/libstore/gc.hh2
-rw-r--r--src/libstore/misc.cc2
-rw-r--r--src/libstore/store.cc72
-rw-r--r--src/libstore/store.hh20
11 files changed, 118 insertions, 88 deletions
diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am
index 7e0f32d1f836..37d2f82b4833 100644
--- a/src/libstore/Makefile.am
+++ b/src/libstore/Makefile.am
@@ -1,18 +1,18 @@
 noinst_LIBRARIES = libstore.a
 
 libstore_a_SOURCES = \
- store.cc store.hh storeexpr.cc storeexpr.hh \
- normalise.cc misc.cc normalise.hh \
+ store.cc store.hh derivations.cc derivations.hh \
+ build.cc misc.cc build.hh \
  globals.cc globals.hh db.cc db.hh \
  references.cc references.hh pathlocks.cc pathlocks.hh \
- gc.cc gc.hh storeexpr-ast.hh
+ gc.cc gc.hh derivations-ast.hh
 
-EXTRA_DIST = storeexpr-ast.def storeexpr-ast.cc
+EXTRA_DIST = derivations-ast.def derivations-ast.cc
 
 AM_CXXFLAGS = -Wall \
  -I.. ${bdb_include} ${aterm_include} -I../libutil
 
-storeexpr-ast.cc storeexpr-ast.hh: ../aterm-helper.pl storeexpr-ast.def
-	$(perl) ../aterm-helper.pl storeexpr-ast.hh storeexpr-ast.cc < storeexpr-ast.def
+derivations-ast.cc derivations-ast.hh: ../aterm-helper.pl derivations-ast.def
+	$(perl) ../aterm-helper.pl derivations-ast.hh derivations-ast.cc < derivations-ast.def
 
-storeexpr.cc: storeexpr-ast.hh
\ No newline at end of file
+derivations.cc: derivations-ast.hh
\ No newline at end of file
diff --git a/src/libstore/normalise.cc b/src/libstore/build.cc
index 090794ba57bb..60e72c9dc195 100644
--- a/src/libstore/normalise.cc
+++ b/src/libstore/build.cc
@@ -5,13 +5,11 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
-#include <sys/time.h>
 #include <fcntl.h>
 #include <unistd.h>
 #include <errno.h>
-#include <utime.h>
 
-#include "normalise.hh"
+#include "build.hh"
 #include "references.hh"
 #include "pathlocks.hh"
 #include "globals.hh"
@@ -285,60 +283,6 @@ const char * * strings2CharPtrs(const Strings & ss)
 }
 
 
-/* "Fix", or canonicalise, the meta-data of the files in a store path
-   after it has been built.  In particular:
-   - the last modification date on each file is set to 0 (i.e.,
-     00:00:00 1/1/1970 UTC)
-   - the permissions are set of 444 or 555 (i.e., read-only with or
-     without execute permission; setuid bits etc. are cleared)
-   - the owner and group are set to the Nix user and group, if we're
-     in a setuid Nix installation
-*/
-void canonicalisePathMetaData(const Path & path)
-{
-    checkInterrupt();
-
-    struct stat st;
-    if (lstat(path.c_str(), &st))
-	throw SysError(format("getting attributes of path `%1%'") % path);
-
-    if (!S_ISLNK(st.st_mode)) {
-
-        /* Mask out all type related bits. */
-        mode_t mode = st.st_mode & ~S_IFMT;
-        
-        if (mode != 0444 && mode != 0555) {
-            mode = (st.st_mode & S_IFMT)
-                 | 0444
-                 | (st.st_mode & S_IXUSR ? 0111 : 0);
-            if (chmod(path.c_str(), mode) == -1)
-                throw SysError(format("changing mode of `%1%' to %2$o") % path % mode);
-        }
-
-        if (st.st_uid != getuid() || st.st_gid != getgid()) {
-            if (chown(path.c_str(), getuid(), getgid()) == -1)
-                throw SysError(format("changing owner/group of `%1%' to %2%/%3%")
-                    % path % getuid() % getgid());
-        }
-
-        if (st.st_mtime != 0) {
-            struct utimbuf utimbuf;
-            utimbuf.actime = st.st_atime;
-            utimbuf.modtime = 0;
-            if (utime(path.c_str(), &utimbuf) == -1) 
-                throw SysError(format("changing modification time of `%1%'") % path);
-        }
-
-    }
-
-    if (S_ISDIR(st.st_mode)) {
-        Strings names = readDirectory(path);
-	for (Strings::iterator i = names.begin(); i != names.end(); ++i)
-	    canonicalisePathMetaData(path + "/" + *i);
-    }
-}
-
-
 
 //////////////////////////////////////////////////////////////////////
 
@@ -1041,6 +985,7 @@ void DerivationGoal::computeClosure()
         format("determining closure for `%1%'") % drvPath);
 
     map<Path, PathSet> allReferences;
+    map<Path, Hash> contentHashes;
     
     /* Check whether the output paths were created, and grep each
        output path to determine what other paths it references.  Also make all
@@ -1109,6 +1054,12 @@ void DerivationGoal::computeClosure()
         }
 
         allReferences[path] = references;
+
+        /* 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
+           if we could combine this with filterReferences(). */
+        contentHashes[path] = hashPath(htSHA256, path);
     }
 
     /* Register each output path as valid, and register the sets of
@@ -1127,7 +1078,8 @@ void DerivationGoal::computeClosure()
     for (DerivationOutputs::iterator i = drv.outputs.begin(); 
          i != drv.outputs.end(); ++i)
     {
-        registerValidPath(txn, i->second.path);
+        registerValidPath(txn, i->second.path,
+            contentHashes[i->second.path]);
         setReferences(txn, i->second.path,
             allReferences[i->second.path]);
     }
@@ -1460,9 +1412,11 @@ void SubstitutionGoal::finished()
 
     canonicalisePathMetaData(storePath);
 
+    Hash contentHash = hashPath(htSHA256, storePath);
+
     Transaction txn;
     createStoreTransaction(txn);
-    registerValidPath(txn, storePath);
+    registerValidPath(txn, storePath, contentHash);
     txn.commit();
 
     outputLock->setDeletion(true);
diff --git a/src/libstore/normalise.hh b/src/libstore/build.hh
index 96f546aaaa07..bfc0157330f7 100644
--- a/src/libstore/normalise.hh
+++ b/src/libstore/build.hh
@@ -1,7 +1,7 @@
-#ifndef __NORMALISE_H
-#define __NORMALISE_H
+#ifndef __BUILD_H
+#define __BUILD_H
 
-#include "storeexpr.hh"
+#include "derivations.hh"
 
 /* Perform the specified derivations, if necessary.  That is, do
    whatever is necessary to create the output paths of the derivation.
@@ -44,4 +44,4 @@ void computeFSClosure(const Path & storePath,
 void storePathRequisites(const Path & storePath,
     bool includeOutputs, PathSet & paths);
 
-#endif /* !__NORMALISE_H */
+#endif /* !__BUILD_H */
diff --git a/src/libstore/storeexpr-ast.def b/src/libstore/derivations-ast.def
index fa7d0387d6dc..2dce8de12c01 100644
--- a/src/libstore/storeexpr-ast.def
+++ b/src/libstore/derivations-ast.def
@@ -1,4 +1,4 @@
-init initStoreExprHelpers
+init initDerivationsHelpers
 
 Derive | ATermList ATermList ATermList string string ATermList ATermList | ATerm |
 
diff --git a/src/libstore/storeexpr.cc b/src/libstore/derivations.cc
index a9240130e755..2f37c66fb60d 100644
--- a/src/libstore/storeexpr.cc
+++ b/src/libstore/derivations.cc
@@ -1,9 +1,9 @@
-#include "storeexpr.hh"
+#include "derivations.hh"
 #include "globals.hh"
 #include "store.hh"
 
-#include "storeexpr-ast.hh"
-#include "storeexpr-ast.cc"
+#include "derivations-ast.hh"
+#include "derivations-ast.cc"
 
 
 Hash hashTerm(ATerm t)
diff --git a/src/libstore/storeexpr.hh b/src/libstore/derivations.hh
index c7b35f8ebe45..c264981d265c 100644
--- a/src/libstore/storeexpr.hh
+++ b/src/libstore/derivations.hh
@@ -1,5 +1,5 @@
-#ifndef __STOREEXPR_H
-#define __STOREEXPR_H
+#ifndef __DERIVATIONS_H
+#define __DERIVATIONS_H
 
 #include "aterm.hh"
 #include "store.hh"
@@ -59,4 +59,4 @@ ATerm unparseDerivation(const Derivation & drv);
 bool isDerivation(const string & fileName);
 
 
-#endif /* !__STOREEXPR_H */
+#endif /* !__DERIVATIONS_H */
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index b6fb66d29cfe..4f3306505440 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -1,5 +1,5 @@
-#include "normalise.hh"
 #include "globals.hh"
+#include "gc.hh"
 
 
 #include <sys/types.h>
diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh
index 1ada419da439..d1ca5c63e4d0 100644
--- a/src/libstore/gc.hh
+++ b/src/libstore/gc.hh
@@ -1,7 +1,7 @@
 #ifndef __GC_H
 #define __GC_H
 
-#include "storeexpr.hh"
+#include "util.hh"
 
 
 /* Determine the set of "live" store paths, given a set of root store
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 2757a061ece2..c585a9aeac5c 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -1,4 +1,4 @@
-#include "normalise.hh"
+#include "build.hh"
 
 
 Derivation derivationFromPath(const Path & drvPath)
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index 01c724b918ae..49a9d273422d 100644
--- a/src/libstore/store.cc
+++ b/src/libstore/store.cc
@@ -2,7 +2,10 @@
 #include <algorithm>
 
 #include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
+#include <utime.h>
 
 #include "store.hh"
 #include "globals.hh"
@@ -181,6 +184,51 @@ void assertStorePath(const Path & path)
 }
 
 
+void canonicalisePathMetaData(const Path & path)
+{
+    checkInterrupt();
+
+    struct stat st;
+    if (lstat(path.c_str(), &st))
+	throw SysError(format("getting attributes of path `%1%'") % path);
+
+    if (!S_ISLNK(st.st_mode)) {
+
+        /* Mask out all type related bits. */
+        mode_t mode = st.st_mode & ~S_IFMT;
+        
+        if (mode != 0444 && mode != 0555) {
+            mode = (st.st_mode & S_IFMT)
+                 | 0444
+                 | (st.st_mode & S_IXUSR ? 0111 : 0);
+            if (chmod(path.c_str(), mode) == -1)
+                throw SysError(format("changing mode of `%1%' to %2$o") % path % mode);
+        }
+
+        if (st.st_uid != getuid() || st.st_gid != getgid()) {
+            if (chown(path.c_str(), getuid(), getgid()) == -1)
+                throw SysError(format("changing owner/group of `%1%' to %2%/%3%")
+                    % path % getuid() % getgid());
+        }
+
+        if (st.st_mtime != 0) {
+            struct utimbuf utimbuf;
+            utimbuf.actime = st.st_atime;
+            utimbuf.modtime = 0;
+            if (utime(path.c_str(), &utimbuf) == -1) 
+                throw SysError(format("changing modification time of `%1%'") % path);
+        }
+
+    }
+
+    if (S_ISDIR(st.st_mode)) {
+        Strings names = readDirectory(path);
+	for (Strings::iterator i = names.begin(); i != names.end(); ++i)
+	    canonicalisePathMetaData(path + "/" + *i);
+    }
+}
+
+
 static bool isValidPathTxn(const Path & path, const Transaction & txn)
 {
     string s;
@@ -318,12 +366,24 @@ void clearSubstitutes()
 }
 
 
-void registerValidPath(const Transaction & txn, const Path & _path)
+void registerValidPath(const Transaction & txn,
+    const Path & _path, const Hash & hash)
 {
     Path path(canonPath(_path));
     assertStorePath(path);
+
+    assert(hash.type == htSHA256);
+    
     debug(format("registering path `%1%'") % path);
-    nixDB.setString(txn, dbValidPaths, path, "");
+    nixDB.setString(txn, dbValidPaths, path, "sha256:" + printHash(hash));
+
+    /* Check that all referenced paths are also valid. */
+    Paths references;
+    nixDB.queryStrings(txn, dbReferences, path, references);
+    for (Paths::iterator i = references.begin(); i != references.end(); ++i)
+        if (!isValidPathTxn(*i, txn))
+            throw Error(format("cannot register path `%1%' as valid, since its reference `%2%' is invalid")
+                % path % *i);
 }
 
 
@@ -385,10 +445,10 @@ Path addToStore(const Path & _srcPath)
                 throw Error(format("contents of `%1%' changed while copying it to `%2%' (%3% -> %4%)")
                     % srcPath % dstPath % printHash(h) % printHash(h2));
 
-            makePathReadOnly(dstPath);
+            canonicalisePathMetaData(dstPath);
             
             Transaction txn(nixDB);
-            registerValidPath(txn, dstPath);
+            registerValidPath(txn, dstPath, h);
             txn.commit();
         }
 
@@ -417,10 +477,10 @@ Path addTextToStore(const string & suffix, const string & s)
 
             writeStringToFile(dstPath, s);
 
-            makePathReadOnly(dstPath);
+            canonicalisePathMetaData(dstPath);
             
             Transaction txn(nixDB);
-            registerValidPath(txn, dstPath);
+            registerValidPath(txn, dstPath, hashPath(htSHA256, dstPath));
             txn.commit();
         }
 
diff --git a/src/libstore/store.hh b/src/libstore/store.hh
index 65c3baf98af6..239493a88b3f 100644
--- a/src/libstore/store.hh
+++ b/src/libstore/store.hh
@@ -51,12 +51,28 @@ Substitutes querySubstitutes(const Path & srcPath);
 /* Deregister all substitutes. */
 void clearSubstitutes();
 
-/* Register the validity of a path. */
-void registerValidPath(const Transaction & txn, const Path & path);
+/* Register the validity of a path, i.e., that `path' exists, that the
+   paths referenced by it exists, and in the case of an output path of
+   a derivation, that it has been produced by a succesful execution of
+   the derivation (or something equivalent).  Also register the hash
+   of the file system contents of the path.  The hash must be a
+   SHA-256 hash. */
+void registerValidPath(const Transaction & txn,
+    const Path & path, const Hash & hash);
 
 /* Throw an exception if `path' is not directly in the Nix store. */
 void assertStorePath(const Path & path);
 
+/* "Fix", or canonicalise, the meta-data of the files in a store path
+   after it has been built.  In particular:
+   - the last modification date on each file is set to 0 (i.e.,
+     00:00:00 1/1/1970 UTC)
+   - the permissions are set of 444 or 555 (i.e., read-only with or
+     without execute permission; setuid bits etc. are cleared)
+   - the owner and group are set to the Nix user and group, if we're
+     in a setuid Nix installation. */
+void canonicalisePathMetaData(const Path & path);
+
 /* Checks whether a path is valid. */ 
 bool isValidPath(const Path & path);