forked from lix-project/lix
* 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:
parent
6f5a5ea5ea
commit
76c0e85929
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue