diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index d806a9130a..2c49ecd051 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -1,5 +1,5 @@ #include "nixexpr.hh" -#include "storeexpr.hh" +#include "derivations.hh" #include "nixexpr-ast.hh" diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 12cc272f71..9335ee3138 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -1,4 +1,4 @@ -#include "normalise.hh" +#include "build.hh" #include "eval.hh" #include "globals.hh" #include "nixexpr-ast.hh" diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 40750779c5..b032b25595 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -55,7 +55,7 @@ void checkStoreNotSymlink(Path path) } -void initStoreExprHelpers(); +void initDerivationsHelpers(); /* Initialize and reorder arguments, then call the actual argument @@ -105,7 +105,7 @@ static void initAndRun(int argc, char * * argv) if (lt != "") setLogType(lt); /* ATerm stuff. !!! find a better place to put this */ - initStoreExprHelpers(); + initDerivationsHelpers(); /* Put the arguments in a vector. */ Strings args, remaining; diff --git a/src/libstore/Makefile.am b/src/libstore/Makefile.am index 7e0f32d1f8..37d2f82b48 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 similarity index 95% rename from src/libstore/normalise.cc rename to src/libstore/build.cc index 090794ba57..60e72c9dc1 100644 --- a/src/libstore/normalise.cc +++ b/src/libstore/build.cc @@ -5,13 +5,11 @@ #include #include -#include #include #include #include -#include -#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 allReferences; + map 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 similarity index 94% rename from src/libstore/normalise.hh rename to src/libstore/build.hh index 96f546aaaa..bfc0157330 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 similarity index 86% rename from src/libstore/storeexpr-ast.def rename to src/libstore/derivations-ast.def index fa7d0387d6..2dce8de12c 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 similarity index 97% rename from src/libstore/storeexpr.cc rename to src/libstore/derivations.cc index a9240130e7..2f37c66fb6 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 similarity index 94% rename from src/libstore/storeexpr.hh rename to src/libstore/derivations.hh index c7b35f8ebe..c264981d26 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 b6fb66d29c..4f33065054 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 diff --git a/src/libstore/gc.hh b/src/libstore/gc.hh index 1ada419da4..d1ca5c63e4 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 2757a061ec..c585a9aeac 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 01c724b918..49a9d27342 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -2,7 +2,10 @@ #include #include +#include +#include #include +#include #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 65c3baf98a..239493a88b 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); diff --git a/src/nix-env/main.cc b/src/nix-env/main.cc index d332108cc5..b64bc281af 100644 --- a/src/nix-env/main.cc +++ b/src/nix-env/main.cc @@ -1,7 +1,7 @@ #include "profiles.hh" #include "names.hh" #include "globals.hh" -#include "normalise.hh" +#include "build.hh" #include "shared.hh" #include "parser.hh" #include "eval.hh" diff --git a/src/nix-instantiate/main.cc b/src/nix-instantiate/main.cc index 7decc2259c..0deaab36d0 100644 --- a/src/nix-instantiate/main.cc +++ b/src/nix-instantiate/main.cc @@ -2,7 +2,7 @@ #include #include "globals.hh" -#include "normalise.hh" +#include "build.hh" #include "shared.hh" #include "eval.hh" #include "parser.hh" diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index 67473a81f4..8fead9c0c6 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -1,5 +1,5 @@ #include "dotgraph.hh" -#include "normalise.hh" +#include "build.hh" #if 0 diff --git a/src/nix-store/dotgraph.hh b/src/nix-store/dotgraph.hh index ef389b30d3..9effa5a884 100644 --- a/src/nix-store/dotgraph.hh +++ b/src/nix-store/dotgraph.hh @@ -1,7 +1,7 @@ #ifndef __DOTGRAPH_H #define __DOTGRAPH_H -#include "storeexpr.hh" +#include "util.hh" void printDotGraph(const PathSet & roots); diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index 7c86395a64..f8ddfd5d78 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -1,7 +1,7 @@ #include #include "globals.hh" -#include "normalise.hh" +#include "build.hh" #include "gc.hh" #include "archive.hh" #include "shared.hh" @@ -187,7 +187,7 @@ static void opValidPath(Strings opFlags, Strings opArgs) createStoreTransaction(txn); for (Strings::iterator i = opArgs.begin(); i != opArgs.end(); ++i) - registerValidPath(txn, *i); + registerValidPath(txn, *i, hashPath(htSHA256, *i)); txn.commit(); }