* 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.
This commit is contained in:
Eelco Dolstra 2004-02-14 21:44:18 +00:00
parent 6f5a5ea5ea
commit 76c0e85929
4 changed files with 70 additions and 12 deletions

View file

@ -22,6 +22,13 @@ void sigintHandler(int signo)
processor. */ processor. */
static void initAndRun(int argc, char * * argv) 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. */ /* Setup Nix paths. */
nixStore = NIX_STORE_DIR; nixStore = NIX_STORE_DIR;
nixDataDir = NIX_DATA_DIR; nixDataDir = NIX_DATA_DIR;

View file

@ -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) static bool isValidPathTxn(const Path & path, const Transaction & txn)
{ {
string s; string s;
@ -182,6 +198,9 @@ static bool isUsablePathTxn(const Path & path, const Transaction & txn)
void registerSuccessor(const Transaction & txn, void registerSuccessor(const Transaction & txn,
const Path & srcPath, const Path & sucPath) const Path & srcPath, const Path & sucPath)
{ {
assertStorePath(srcPath);
assertStorePath(sucPath);
if (!isUsablePathTxn(sucPath, txn)) throw Error( if (!isUsablePathTxn(sucPath, txn)) throw Error(
format("path `%1%' cannot be a successor, since it is not usable") format("path `%1%' cannot be a successor, since it is not usable")
% sucPath); % sucPath);
@ -223,6 +242,9 @@ Paths queryPredecessors(const Path & sucPath)
void registerSubstitute(const Path & srcPath, const Path & subPath) void registerSubstitute(const Path & srcPath, const Path & subPath)
{ {
assertStorePath(srcPath);
assertStorePath(subPath);
if (!isValidPathTxn(subPath, noTxn)) throw Error( if (!isValidPathTxn(subPath, noTxn)) throw Error(
format("path `%1%' cannot be a substitute, since it is not valid") format("path `%1%' cannot be a substitute, since it is not valid")
% subPath); % subPath);
@ -262,6 +284,7 @@ Paths querySubstitutes(const Path & srcPath)
void registerValidPath(const Transaction & txn, const Path & _path) void registerValidPath(const Transaction & txn, const Path & _path)
{ {
Path path(canonPath(_path)); Path path(canonPath(_path));
assertStorePath(path);
debug(format("registering path `%1%'") % path); debug(format("registering path `%1%'") % path);
nixDB.setString(txn, dbValidPaths, 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 addToStore(const Path & _srcPath)
{ {
Path srcPath(absPath(_srcPath)); Path srcPath(absPath(_srcPath));
@ -355,6 +371,8 @@ Path addToStore(const Path & _srcPath)
void addTextToStore(const Path & dstPath, const string & s) void addTextToStore(const Path & dstPath, const string & s)
{ {
assertStorePath(dstPath);
if (!isValidPath(dstPath)) { if (!isValidPath(dstPath)) {
PathSet lockPaths; PathSet lockPaths;
@ -378,8 +396,7 @@ void deleteFromStore(const Path & _path)
{ {
Path path(canonPath(_path)); Path path(canonPath(_path));
if (!isInPrefix(path, nixStore)) assertStorePath(path);
throw Error(format("path `%1%' is not in the store") % path);
Transaction txn(nixDB); Transaction txn(nixDB);
invalidatePath(path, txn); invalidatePath(path, txn);
@ -402,6 +419,9 @@ void verifyStore()
if (!pathExists(path)) { if (!pathExists(path)) {
printMsg(lvlError, format("path `%1%' disappeared") % path); printMsg(lvlError, format("path `%1%' disappeared") % path);
invalidatePath(path, txn); invalidatePath(path, txn);
} else if (!isInStore(path)) {
printMsg(lvlError, format("path `%1%' is not in the Nix store") % path);
invalidatePath(path, txn);
} else } else
validPaths.insert(path); validPaths.insert(path);
} }

View file

@ -9,8 +9,10 @@ Operations:
--add / -A: copy a path to the Nix store --add / -A: copy a path to the Nix store
--query / -q: query information --query / -q: query information
--successor: register a successor expression --successor: register a successor expression (dangerous!)
--substitute: register a substitute expression --substitute: register a substitute expression (dangerous!)
--validpath: register path validity (dangerous!)
--isvalid: check path validity
--dump: dump a path as a Nix archive --dump: dump a path as a Nix archive
--restore: restore a path from a Nix archive --restore: restore a path from a Nix archive

View file

@ -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. */ /* A sink that writes dump output to stdout. */
struct StdoutSink : DumpSink struct StdoutSink : DumpSink
{ {
@ -273,6 +297,10 @@ void run(Strings args)
op = opSuccessor; op = opSuccessor;
else if (arg == "--substitute") else if (arg == "--substitute")
op = opSubstitute; op = opSubstitute;
else if (arg == "--validpath")
op = opValidPath;
else if (arg == "--isvalid")
op = opIsValid;
else if (arg == "--dump") else if (arg == "--dump")
op = opDump; op = opDump;
else if (arg == "--restore") else if (arg == "--restore")
@ -292,7 +320,8 @@ void run(Strings args)
if (!op) throw UsageError("no operation specified"); if (!op) throw UsageError("no operation specified");
openDB(); if (op != opDump && op != opRestore) /* !!! hack */
openDB();
op(opFlags, opArgs); op(opFlags, opArgs);
} }