From 76c0e85929dc747288a8fe66a7bb77673cf2aa7e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sat, 14 Feb 2004 21:44:18 +0000 Subject: [PATCH] * The environment variable NIX_ROOT can now be set to execute Nix in a chroot() environment. * A operation `--validpath' to register path validity. Useful for bootstrapping in a pure Nix environment. * Safety checks: ensure that files involved in store operations are in the store. --- src/libmain/shared.cc | 7 +++++++ src/libstore/store.cc | 38 +++++++++++++++++++++++++++++--------- src/nix-store/help.txt | 6 ++++-- src/nix-store/main.cc | 31 ++++++++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 12 deletions(-) diff --git a/src/libmain/shared.cc b/src/libmain/shared.cc index 32f4f8124..ec639052b 100644 --- a/src/libmain/shared.cc +++ b/src/libmain/shared.cc @@ -22,6 +22,13 @@ void sigintHandler(int signo) processor. */ static void initAndRun(int argc, char * * argv) { + char * root = getenv("NIX_ROOT"); + + if (root) { + if (chroot(root) != 0) + throw SysError(format("changing root to `%1%'") % root); + } + /* Setup Nix paths. */ nixStore = NIX_STORE_DIR; nixDataDir = NIX_DATA_DIR; diff --git a/src/libstore/store.cc b/src/libstore/store.cc index 4cd77796e..d85b0608f 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -157,6 +157,22 @@ void copyPath(const Path & src, const Path & dst) } +static bool isInStore(const Path & path) +{ + return path[0] == '/' + && Path(path, 0, nixStore.size()) == nixStore + && path.size() > nixStore.size() + 1 + && path[nixStore.size()] == '/'; +} + + +static void assertStorePath(const Path & path) +{ + if (!isInStore(path)) + throw Error(format("path `%1%' is not in the Nix store") % path); +} + + static bool isValidPathTxn(const Path & path, const Transaction & txn) { string s; @@ -182,6 +198,9 @@ static bool isUsablePathTxn(const Path & path, const Transaction & txn) void registerSuccessor(const Transaction & txn, const Path & srcPath, const Path & sucPath) { + assertStorePath(srcPath); + assertStorePath(sucPath); + if (!isUsablePathTxn(sucPath, txn)) throw Error( format("path `%1%' cannot be a successor, since it is not usable") % sucPath); @@ -223,6 +242,9 @@ Paths queryPredecessors(const Path & sucPath) void registerSubstitute(const Path & srcPath, const Path & subPath) { + assertStorePath(srcPath); + assertStorePath(subPath); + if (!isValidPathTxn(subPath, noTxn)) throw Error( format("path `%1%' cannot be a substitute, since it is not valid") % subPath); @@ -262,6 +284,7 @@ Paths querySubstitutes(const Path & srcPath) void registerValidPath(const Transaction & txn, const Path & _path) { Path path(canonPath(_path)); + assertStorePath(path); debug(format("registering path `%1%'") % path); nixDB.setString(txn, dbValidPaths, path, ""); } @@ -312,13 +335,6 @@ static void invalidatePath(const Path & path, Transaction & txn) } -static bool isInPrefix(const string & path, const string & _prefix) -{ - string prefix = canonPath(_prefix + "/"); - return string(path, 0, prefix.size()) == prefix; -} - - Path addToStore(const Path & _srcPath) { Path srcPath(absPath(_srcPath)); @@ -355,6 +371,8 @@ Path addToStore(const Path & _srcPath) void addTextToStore(const Path & dstPath, const string & s) { + assertStorePath(dstPath); + if (!isValidPath(dstPath)) { PathSet lockPaths; @@ -378,8 +396,7 @@ void deleteFromStore(const Path & _path) { Path path(canonPath(_path)); - if (!isInPrefix(path, nixStore)) - throw Error(format("path `%1%' is not in the store") % path); + assertStorePath(path); Transaction txn(nixDB); invalidatePath(path, txn); @@ -402,6 +419,9 @@ void verifyStore() if (!pathExists(path)) { printMsg(lvlError, format("path `%1%' disappeared") % path); invalidatePath(path, txn); + } else if (!isInStore(path)) { + printMsg(lvlError, format("path `%1%' is not in the Nix store") % path); + invalidatePath(path, txn); } else validPaths.insert(path); } diff --git a/src/nix-store/help.txt b/src/nix-store/help.txt index d7f977025..a3dcdebb6 100644 --- a/src/nix-store/help.txt +++ b/src/nix-store/help.txt @@ -9,8 +9,10 @@ Operations: --add / -A: copy a path to the Nix store --query / -q: query information - --successor: register a successor expression - --substitute: register a substitute expression + --successor: register a successor expression (dangerous!) + --substitute: register a substitute expression (dangerous!) + --validpath: register path validity (dangerous!) + --isvalid: check path validity --dump: dump a path as a Nix archive --restore: restore a path from a Nix archive diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index 078618a5d..4be8e8f44 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -185,6 +185,30 @@ static void opSubstitute(Strings opFlags, Strings opArgs) } +static void opValidPath(Strings opFlags, Strings opArgs) +{ + if (!opFlags.empty()) throw UsageError("unknown flag"); + + Transaction txn; + createStoreTransaction(txn); + for (Strings::iterator i = opArgs.begin(); + i != opArgs.end(); ++i) + registerValidPath(txn, *i); + txn.commit(); +} + + +static void opIsValid(Strings opFlags, Strings opArgs) +{ + if (!opFlags.empty()) throw UsageError("unknown flag"); + + for (Strings::iterator i = opArgs.begin(); + i != opArgs.end(); ++i) + if (!isValidPath(*i)) + throw Error(format("path `%1%' is not valid") % *i); +} + + /* A sink that writes dump output to stdout. */ struct StdoutSink : DumpSink { @@ -273,6 +297,10 @@ void run(Strings args) op = opSuccessor; else if (arg == "--substitute") op = opSubstitute; + else if (arg == "--validpath") + op = opValidPath; + else if (arg == "--isvalid") + op = opIsValid; else if (arg == "--dump") op = opDump; else if (arg == "--restore") @@ -292,7 +320,8 @@ void run(Strings args) if (!op) throw UsageError("no operation specified"); - openDB(); + if (op != opDump && op != opRestore) /* !!! hack */ + openDB(); op(opFlags, opArgs); }