Make the store directory a member variable of Store

This commit is contained in:
Eelco Dolstra 2016-06-01 14:49:12 +02:00
parent 1b5b654fe2
commit 7850d3d279
35 changed files with 315 additions and 296 deletions

View file

@ -11,7 +11,6 @@ makefiles = \
src/nix-env/local.mk \
src/nix-daemon/local.mk \
src/nix-collect-garbage/local.mk \
src/download-via-ssh/local.mk \
src/nix-prefetch-url/local.mk \
perl/local.mk \
scripts/local.mk \
@ -22,6 +21,7 @@ makefiles = \
misc/emacs/local.mk \
doc/manual/local.mk \
tests/local.mk
#src/download-via-ssh/local.mk \
GLOBAL_CXXFLAGS += -std=c++11 -g -Wall

View file

@ -161,8 +161,7 @@ SV * topoSortPaths(...)
SV * followLinksToStorePath(char * path)
CODE:
try {
store();
RETVAL = newSVpv(followLinksToStorePath(path).c_str(), 0);
RETVAL = newSVpv(store()->followLinksToStorePath(path).c_str(), 0);
} catch (Error & e) {
croak("%s", e.what());
}
@ -289,7 +288,7 @@ SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
PPCODE:
try {
HashType ht = parseHashType(algo);
Path path = makeFixedOutputPath(recursive, ht,
Path path = store()->makeFixedOutputPath(recursive, ht,
parseHash16or32(ht, hash), name);
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
} catch (Error & e) {

View file

@ -341,7 +341,7 @@ Path EvalState::checkSourcePath(const Path & path_)
/* To support import-from-derivation, allow access to anything in
the store. FIXME: only allow access to paths that have been
constructed by this evaluation. */
if (isInStore(path)) return path;
if (store->isInStore(path)) return path;
#if 0
/* Hack to support the chroot dependencies of corepkgs (see
@ -1517,7 +1517,7 @@ string EvalState::copyPathToStore(PathSet & context, const Path & path)
dstPath = srcToStore[path];
else {
dstPath = settings.readOnlyMode
? computeStorePathForPath(checkSourcePath(path)).first
? store->computeStorePathForPath(checkSourcePath(path)).first
: store->addToStore(baseNameOf(path), checkSourcePath(path), true, htSHA256, defaultPathFilter, repair);
srcToStore[path] = dstPath;
printMsg(lvlChatty, format("copied source %1% -> %2%")

View file

@ -50,7 +50,7 @@ void EvalState::realiseContext(const PathSet & context)
for (auto & i : context) {
std::pair<string, string> decoded = decodeContext(i);
Path ctx = decoded.first;
assert(isStorePath(ctx));
assert(store->isStorePath(ctx));
if (!store->isValidPath(ctx))
throw InvalidPathError(ctx);
if (!decoded.second.empty() && nix::isDerivation(ctx))
@ -82,7 +82,7 @@ static void prim_scopedImport(EvalState & state, const Pos & pos, Value * * args
path = state.checkSourcePath(path);
if (isStorePath(path) && state.store->isValidPath(path) && isDerivation(path)) {
if (state.store->isStorePath(path) && state.store->isValidPath(path) && isDerivation(path)) {
Derivation drv = readDerivation(path);
Value & w = *state.allocValue();
state.mkAttrs(w, 3 + drv.outputs.size());
@ -624,7 +624,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
outputHash = printHash(h);
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
Path outPath = makeFixedOutputPath(outputHashRecursive, ht, h, drvName);
Path outPath = state.store->makeFixedOutputPath(outputHashRecursive, ht, h, drvName);
drv.env["out"] = outPath;
drv.outputs["out"] = DerivationOutput(outPath, outputHashAlgo, outputHash);
}
@ -646,7 +646,7 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
for (auto & i : drv.outputs)
if (i.second.path == "") {
Path outPath = makeOutputPath(i.first, h, drvName);
Path outPath = state.store->makeOutputPath(i.first, h, drvName);
drv.env[i.first] = outPath;
i.second.path = outPath;
}
@ -702,10 +702,10 @@ static void prim_storePath(EvalState & state, const Pos & pos, Value * * args, V
/* Resolve symlinks in path, unless path itself is a symlink
directly in the store. The latter condition is necessary so
e.g. nix-push does the right thing. */
if (!isStorePath(path)) path = canonPath(path, true);
if (!isInStore(path))
if (!state.store->isStorePath(path)) path = canonPath(path, true);
if (!state.store->isInStore(path))
throw EvalError(format("path %1% is not in the Nix store, at %2%") % path % pos);
Path path2 = toStorePath(path);
Path path2 = state.store->toStorePath(path);
if (!settings.readOnlyMode)
state.store->ensurePath(path2);
context.insert(path2);
@ -897,7 +897,7 @@ static void prim_toFile(EvalState & state, const Pos & pos, Value * * args, Valu
}
Path storePath = settings.readOnlyMode
? computeStorePathForText(name, contents, refs)
? state.store->computeStorePathForText(name, contents, refs)
: state.store->addTextToStore(name, contents, refs, state.repair);
/* Note: we don't need to add `context' to the context of the
@ -963,7 +963,7 @@ static void prim_filterSource(EvalState & state, const Pos & pos, Value * * args
path = state.checkSourcePath(path);
Path dstPath = settings.readOnlyMode
? computeStorePathForPath(path, true, htSHA256, filter).first
? state.store->computeStorePathForPath(path, true, htSHA256, filter).first
: state.store->addToStore(baseNameOf(path), path, true, htSHA256, filter, state.repair);
mkString(v, dstPath, {dstPath});
@ -1765,7 +1765,7 @@ void EvalState::createBaseEnv()
mkString(v, nixVersion);
addConstant("__nixVersion", v);
mkString(v, settings.nixStore);
mkString(v, store->storeDir);
addConstant("__storeDir", v);
/* Language version. This should be increased every time a new

View file

@ -14,8 +14,9 @@
namespace nix {
BinaryCacheStore::BinaryCacheStore(const StoreParams & params)
: compression(get(params, "compression", "xz"))
BinaryCacheStore::BinaryCacheStore(const Params & params)
: Store(params)
, compression(get(params, "compression", "xz"))
{
auto secretKeyFile = get(params, "secret-key", "");
if (secretKeyFile != "")
@ -32,7 +33,7 @@ void BinaryCacheStore::init()
auto cacheInfo = getFile(cacheInfoFile);
if (!cacheInfo) {
upsertFile(cacheInfoFile, "StoreDir: " + settings.nixStore + "\n");
upsertFile(cacheInfoFile, "StoreDir: " + storeDir + "\n");
} else {
for (auto & line : tokenizeString<Strings>(*cacheInfo, "\n")) {
size_t colon = line.find(':');
@ -40,9 +41,9 @@ void BinaryCacheStore::init()
auto name = line.substr(0, colon);
auto value = trim(line.substr(colon + 1, std::string::npos));
if (name == "StoreDir") {
if (value != settings.nixStore)
if (value != storeDir)
throw Error(format("binary cache %s is for Nix stores with prefix %s, not %s")
% getUri() % value % settings.nixStore);
% getUri() % value % storeDir);
} else if (name == "WantMassQuery") {
wantMassQuery_ = value == "1";
} else if (name == "Priority") {
@ -181,7 +182,7 @@ std::shared_ptr<ValidPathInfo> BinaryCacheStore::queryPathInfoUncached(const Pat
auto data = getFile(narInfoFile);
if (!data) return 0;
auto narInfo = make_ref<NarInfo>(*data, narInfoFile);
auto narInfo = make_ref<NarInfo>(*this, *data, narInfoFile);
stats.narInfoRead++;
@ -249,7 +250,7 @@ struct BinaryCacheStoreAccessor : public FSAccessor
{
auto path = canonPath(path_);
auto storePath = toStorePath(path);
auto storePath = store->toStorePath(path);
std::string restPath = std::string(path, storePath.size());
if (!store->isValidPath(storePath))

View file

@ -21,7 +21,7 @@ private:
protected:
BinaryCacheStore(const StoreParams & params);
BinaryCacheStore(const Params & params);
[[noreturn]] void notImpl();

View file

@ -1442,7 +1442,7 @@ void DerivationGoal::buildDone()
#if HAVE_STATVFS
unsigned long long required = 8ULL * 1024 * 1024; // FIXME: make configurable
struct statvfs st;
if (statvfs(settings.nixStore.c_str(), &st) == 0 &&
if (statvfs(worker.store.storeDir.c_str(), &st) == 0 &&
(unsigned long long) st.f_bavail * st.f_bsize < required)
diskFull = true;
if (statvfs(tmpDir.c_str(), &st) == 0 &&
@ -1701,7 +1701,7 @@ void DerivationGoal::startBuilder()
shouldn't care, but this is useful for purity checking (e.g.,
the compiler or linker might only want to accept paths to files
in the store or in the build directory). */
env["NIX_STORE"] = settings.nixStore;
env["NIX_STORE"] = worker.store.storeDir;
/* The maximum number of cores to utilize for parallel building. */
env["NIX_BUILD_CORES"] = (format("%d") % settings.buildCores).str();
@ -1784,10 +1784,10 @@ void DerivationGoal::startBuilder()
/* Check that the store path is valid. */
Path storePath = *i++;
if (!isInStore(storePath))
if (!worker.store.isInStore(storePath))
throw BuildError(format("exportReferencesGraph contains a non-store path %1%")
% storePath);
storePath = toStorePath(storePath);
storePath = worker.store.toStorePath(storePath);
if (!worker.store.isValidPath(storePath))
throw BuildError(format("exportReferencesGraph contains an invalid path %1%")
% storePath);
@ -1838,7 +1838,7 @@ void DerivationGoal::startBuilder()
string defaultChrootDirs;
#if __linux__
if (isInStore(BASH_PATH))
if (worker.store.isInStore(BASH_PATH))
defaultChrootDirs = "/bin/sh=" BASH_PATH;
#endif
@ -1867,8 +1867,8 @@ void DerivationGoal::startBuilder()
/* Add the closure of store paths to the chroot. */
PathSet closure;
for (auto & i : dirsInChroot)
if (isInStore(i.second))
worker.store.computeFSClosure(toStorePath(i.second), closure);
if (worker.store.isInStore(i.second))
worker.store.computeFSClosure(worker.store.toStorePath(i.second), closure);
for (auto & i : closure)
dirsInChroot[i] = i;
@ -1953,7 +1953,7 @@ void DerivationGoal::startBuilder()
can be bind-mounted). !!! As an extra security
precaution, make the fake Nix store only writable by the
build user. */
Path chrootStoreDir = chrootRootDir + settings.nixStore;
Path chrootStoreDir = chrootRootDir + worker.store.storeDir;
createDirs(chrootStoreDir);
chmod_(chrootStoreDir, 01775);
@ -2408,7 +2408,7 @@ void DerivationGoal::runChild()
/* And we want the store in there regardless of how empty dirsInChroot. We include the innermost
path component this time, since it's typically /nix/store and we care about that. */
Path cur = settings.nixStore;
Path cur = worker.store.storeDir;
while (cur.compare("/") != 0) {
ancestry.insert(cur);
cur = dirOf(cur);
@ -2532,12 +2532,12 @@ void DerivationGoal::runChild()
/* Parse a list of reference specifiers. Each element must either be
a store path, or the symbolic name of the output of the derivation
(such as `out'). */
PathSet parseReferenceSpecifiers(const BasicDerivation & drv, string attr)
PathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, string attr)
{
PathSet result;
Paths paths = tokenizeString<Paths>(attr);
for (auto & i : paths) {
if (isStorePath(i))
if (store.isStorePath(i))
result.insert(i);
else if (drv.outputs.find(i) != drv.outputs.end())
result.insert(drv.outputs.find(i)->second.path);
@ -2660,7 +2660,7 @@ void DerivationGoal::registerOutputs()
the derivation to its content-addressed location. */
Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath);
if (buildMode == bmHash) {
Path dest = makeFixedOutputPath(recursive, ht, h2, drv->env["name"]);
Path dest = worker.store.makeFixedOutputPath(recursive, ht, h2, drv->env["name"]);
printMsg(lvlError, format("build produced path %1% with %2% hash %3%")
% dest % printHashType(ht) % printHash16or32(h2));
if (worker.store.isValidPath(dest))
@ -2733,7 +2733,7 @@ void DerivationGoal::registerOutputs()
auto checkRefs = [&](const string & attrName, bool allowed, bool recursive) {
if (drv->env.find(attrName) == drv->env.end()) return;
PathSet spec = parseReferenceSpecifiers(*drv, get(drv->env, attrName));
PathSet spec = parseReferenceSpecifiers(worker.store, *drv, get(drv->env, attrName));
PathSet used;
if (recursive) {
@ -2965,9 +2965,9 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
Path DerivationGoal::addHashRewrite(const Path & path)
{
string h1 = string(path, settings.nixStore.size() + 1, 32);
string h1 = string(path, worker.store.storeDir.size() + 1, 32);
string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32);
Path p = settings.nixStore + "/" + h2 + string(path, settings.nixStore.size() + 33);
Path p = worker.store.storeDir + "/" + h2 + string(path, worker.store.storeDir.size() + 33);
deletePath(p);
assert(path.size() == p.size());
rewritesToTmp[h1] = h2;

View file

@ -26,7 +26,6 @@ void builtinFetchurl(const BasicDerivation & drv)
if (out == drv.env.end()) throw Error("attribute url missing");
Path storePath = out->second;
assertStorePath(storePath);
auto unpack = drv.env.find("unpack");
if (unpack != drv.env.end() && unpack->second == "1") {

View file

@ -81,7 +81,7 @@ Path writeDerivation(ref<Store> store,
string suffix = name + drvExtension;
string contents = drv.unparse();
return settings.readOnlyMode
? computeStorePathForText(suffix, contents, references)
? store->computeStorePathForText(suffix, contents, references)
: store->addTextToStore(suffix, contents, references, repair);
}
@ -336,7 +336,7 @@ PathSet BasicDerivation::outputPaths() const
}
Source & operator >> (Source & in, BasicDerivation & drv)
Source & readDerivation(Source & in, Store & store, BasicDerivation & drv)
{
drv.outputs.clear();
auto nr = readInt(in);
@ -344,11 +344,11 @@ Source & operator >> (Source & in, BasicDerivation & drv)
auto name = readString(in);
DerivationOutput o;
in >> o.path >> o.hashAlgo >> o.hash;
assertStorePath(o.path);
store.assertStorePath(o.path);
drv.outputs[name] = o;
}
drv.inputSrcs = readStorePaths<PathSet>(in);
drv.inputSrcs = readStorePaths<PathSet>(store, in);
in >> drv.platform >> drv.builder;
drv.args = readStrings<Strings>(in);

View file

@ -114,7 +114,7 @@ bool wantOutput(const string & output, const std::set<string> & wanted);
struct Source;
struct Sink;
Source & operator >> (Source & in, BasicDerivation & drv);
Source & readDerivation(Source & in, Store & store, BasicDerivation & drv);
Sink & operator << (Sink & out, const BasicDerivation & drv);
}

View file

@ -101,11 +101,11 @@ Paths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> accessor,
ValidPathInfo info;
info.path = readStorePath(source);
info.path = readStorePath(*this, source);
Activity act(*logger, lvlInfo, format("importing path %s") % info.path);
info.references = readStorePaths<PathSet>(source);
info.references = readStorePaths<PathSet>(*this, source);
info.deriver = readString(source);
if (info.deriver != "") assertStorePath(info.deriver);

View file

@ -204,7 +204,7 @@ typedef std::shared_ptr<AutoCloseFD> FDPtr;
typedef list<FDPtr> FDs;
static void readTempRoots(PathSet & tempRoots, FDs & fds)
static void readTempRoots(Store & store, PathSet & tempRoots, FDs & fds)
{
/* Read the `temproots' directory for per-process temporary root
files. */
@ -251,7 +251,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds)
while ((end = contents.find((char) 0, pos)) != string::npos) {
Path root(contents, pos, end - pos);
debug(format("got temporary root %1%") % root);
assertStorePath(root);
store.assertStorePath(root);
tempRoots.insert(root);
pos = end + 1;
}
@ -304,7 +304,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
}
else if (type == DT_REG) {
Path storePath = settings.nixStore + "/" + baseNameOf(path);
Path storePath = storeDir + "/" + baseNameOf(path);
if (isStorePath(storePath) && isValidPath(storePath))
roots[path] = storePath;
}
@ -594,7 +594,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
{
GCState state(results);
state.options = options;
state.trashDir = settings.nixStore + "/trash";
state.trashDir = storeDir + "/trash";
state.gcKeepOutputs = settings.gcKeepOutputs;
state.gcKeepDerivations = settings.gcKeepDerivations;
@ -635,7 +635,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
per-process temporary root files. So after this point no paths
can be added to the set of temporary roots. */
FDs fds;
readTempRoots(state.tempRoots, fds);
readTempRoots(*this, state.tempRoots, fds);
state.roots.insert(state.tempRoots.begin(), state.tempRoots.end());
/* After this point the set of roots or temporary roots cannot
@ -675,8 +675,8 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
try {
AutoCloseDir dir = opendir(settings.nixStore.c_str());
if (!dir) throw SysError(format("opening directory %1%") % settings.nixStore);
AutoCloseDir dir = opendir(storeDir.c_str());
if (!dir) throw SysError(format("opening directory %1%") % storeDir);
/* Read the store and immediately delete all paths that
aren't valid. When using --max-freed etc., deleting
@ -690,7 +690,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
checkInterrupt();
string name = dirent->d_name;
if (name == "." || name == "..") continue;
Path path = settings.nixStore + "/" + name;
Path path = storeDir + "/" + name;
if (isStorePath(path) && isValidPath(path))
entries.push_back(path);
else

View file

@ -18,7 +18,7 @@ private:
public:
HttpBinaryCacheStore(
const StoreParams & params, const Path & _cacheUri)
const Params & params, const Path & _cacheUri)
: BinaryCacheStore(params)
, cacheUri(_cacheUri)
, downloaders(
@ -45,7 +45,7 @@ public:
} catch (UploadToHTTP &) {
throw Error(format("%s does not appear to be a binary cache") % cacheUri);
}
diskCache->createCache(cacheUri, wantMassQuery_, priority);
diskCache->createCache(cacheUri, storeDir, wantMassQuery_, priority);
}
}
@ -91,7 +91,7 @@ protected:
};
static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params)
const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store>
{
if (std::string(uri, 0, 7) != "http://" &&

View file

@ -13,7 +13,7 @@ private:
public:
LocalBinaryCacheStore(
const StoreParams & params, const Path & binaryCacheDir)
const Params & params, const Path & binaryCacheDir)
: BinaryCacheStore(params)
, binaryCacheDir(binaryCacheDir)
{
@ -45,7 +45,7 @@ protected:
if (entry.name.size() != 40 ||
!hasSuffix(entry.name, ".narinfo"))
continue;
paths.insert(settings.nixStore + "/" + entry.name.substr(0, entry.name.size() - 8));
paths.insert(storeDir + "/" + entry.name.substr(0, entry.name.size() - 8));
}
return paths;
@ -59,7 +59,7 @@ void LocalBinaryCacheStore::init()
BinaryCacheStore::init();
if (diskCache && !diskCache->cacheExists(getUri()))
diskCache->createCache(getUri(), wantMassQuery_, priority);
diskCache->createCache(getUri(), storeDir, wantMassQuery_, priority);
}
static void atomicWrite(const Path & path, const std::string & s)
@ -93,7 +93,7 @@ std::shared_ptr<std::string> LocalBinaryCacheStore::getFile(const std::string &
}
static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params)
const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store>
{
if (std::string(uri, 0, 7) != "file://") return 0;

View file

@ -12,7 +12,7 @@ struct LocalStoreAccessor : public FSAccessor
void assertStore(const Path & path)
{
Path storePath = toStorePath(path);
Path storePath = store->toStorePath(path);
if (!store->isValidPath(storePath))
throw Error(format("path %1% is not a valid store path") % storePath);
}

View file

@ -36,26 +36,9 @@
namespace nix {
void checkStoreNotSymlink()
{
if (getEnv("NIX_IGNORE_SYMLINK_STORE") == "1") return;
Path path = settings.nixStore;
struct stat st;
while (path != "/") {
if (lstat(path.c_str(), &st))
throw SysError(format("getting status of %1%") % path);
if (S_ISLNK(st.st_mode))
throw Error(format(
"the path %1% is a symlink; "
"this is not allowed for the Nix store and its parent directories")
% path);
path = dirOf(path);
}
}
LocalStore::LocalStore()
: linksDir(settings.nixStore + "/.links")
LocalStore::LocalStore(const Params & params)
: LocalFSStore(params)
, linksDir(storeDir + "/.links")
, reservedPath(settings.nixDBPath + "/reserved")
, schemaPath(settings.nixDBPath + "/schema")
, requireSigs(settings.get("signed-binary-caches", std::string("")) != "") // FIXME: rename option
@ -69,7 +52,7 @@ LocalStore::LocalStore()
}
/* Create missing state directories if they don't already exist. */
createDirs(settings.nixStore);
createDirs(storeDir);
makeStoreWritable();
createDirs(linksDir);
Path profilesDir = settings.nixStateDir + "/profiles";
@ -99,19 +82,33 @@ LocalStore::LocalStore()
% settings.buildUsersGroup);
else {
struct stat st;
if (stat(settings.nixStore.c_str(), &st))
throw SysError(format("getting attributes of path %1%") % settings.nixStore);
if (stat(storeDir.c_str(), &st))
throw SysError(format("getting attributes of path %1%") % storeDir);
if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1)
throw SysError(format("changing ownership of path %1%") % settings.nixStore);
if (chmod(settings.nixStore.c_str(), perm) == -1)
throw SysError(format("changing permissions on path %1%") % settings.nixStore);
if (chown(storeDir.c_str(), 0, gr->gr_gid) == -1)
throw SysError(format("changing ownership of path %1%") % storeDir);
if (chmod(storeDir.c_str(), perm) == -1)
throw SysError(format("changing permissions on path %1%") % storeDir);
}
}
}
checkStoreNotSymlink();
/* Ensure that the store and its parents are not symlinks. */
if (getEnv("NIX_IGNORE_SYMLINK_STORE") != "1") {
Path path = storeDir;
struct stat st;
while (path != "/") {
if (lstat(path.c_str(), &st))
throw SysError(format("getting status of %1%") % path);
if (S_ISLNK(st.st_mode))
throw Error(format(
"the path %1% is a symlink; "
"this is not allowed for the Nix store and its parent directories")
% path);
path = dirOf(path);
}
}
/* We can't open a SQLite database if the disk is full. Since
this prevents the garbage collector from running when it's most
@ -351,15 +348,15 @@ void LocalStore::makeStoreWritable()
if (getuid() != 0) return;
/* Check if /nix/store is on a read-only mount. */
struct statvfs stat;
if (statvfs(settings.nixStore.c_str(), &stat) != 0)
if (statvfs(storeDir.c_str(), &stat) != 0)
throw SysError("getting info about the Nix store mount point");
if (stat.f_flag & ST_RDONLY) {
if (unshare(CLONE_NEWNS) == -1)
throw SysError("setting up a private mount namespace");
if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError(format("remounting %1% writable") % settings.nixStore);
if (mount(0, storeDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError(format("remounting %1% writable") % storeDir);
}
#endif
}
@ -771,7 +768,7 @@ Path LocalStore::queryPathFromHashPart(const string & hashPart)
{
if (hashPart.size() != storePathHashLen) throw Error("invalid hash part");
Path prefix = settings.nixStore + "/" + hashPart;
Path prefix = storeDir + "/" + hashPart;
return retrySQLite<Path>([&]() {
auto state(_state.lock());
@ -1071,7 +1068,7 @@ Path LocalStore::createTempDirInStore()
/* There is a slight possibility that `tmpDir' gets deleted by
the GC between createTempDir() and addTempRoot(), so repeat
until `tmpDir' exists. */
tmpDir = createTempDir(settings.nixStore);
tmpDir = createTempDir(storeDir);
addTempRoot(tmpDir);
} while (!pathExists(tmpDir));
return tmpDir;
@ -1111,7 +1108,7 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
AutoCloseFD fdGCLock = openGCLock(ltWrite);
PathSet store;
for (auto & i : readDirectory(settings.nixStore)) store.insert(i.name);
for (auto & i : readDirectory(storeDir)) store.insert(i.name);
/* Check whether all valid paths actually exist. */
printMsg(lvlInfo, "checking path existence...");
@ -1275,7 +1272,7 @@ void LocalStore::upgradeStore7()
{
if (getuid() != 0) return;
printMsg(lvlError, "removing immutable bits from the Nix store (this may take a while)...");
makeMutable(settings.nixStore);
makeMutable(storeDir);
}
#else

View file

@ -85,7 +85,7 @@ public:
/* Initialise the local store, upgrading the schema if
necessary. */
LocalStore();
LocalStore(const Params & params);
~LocalStore();

View file

@ -1,7 +1,6 @@
#include "nar-info-disk-cache.hh"
#include "sync.hh"
#include "sqlite.hh"
#include "globals.hh"
#include <sqlite3.h>
@ -54,11 +53,17 @@ public:
/* How long negative lookups are valid. */
const int ttlNegative = 3600;
struct Cache
{
int id;
Path storeDir;
};
struct State
{
SQLite db;
SQLiteStmt insertCache, queryCache, insertNAR, queryNAR, insertNARExistence, queryNARExistence;
std::map<std::string, int> caches;
std::map<std::string, Cache> caches;
};
Sync<State> _state;
@ -106,22 +111,22 @@ public:
"select exist, timestamp from NARExistence where cache = ? and storePath = ?");
}
int uriToInt(State & state, const std::string & uri)
Cache & getCache(State & state, const std::string & uri)
{
auto i = state.caches.find(uri);
if (i == state.caches.end()) abort();
return i->second;
}
void createCache(const std::string & uri, bool wantMassQuery, int priority) override
void createCache(const std::string & uri, const Path & storeDir, bool wantMassQuery, int priority) override
{
auto state(_state.lock());
// FIXME: race
state->insertCache.use()(uri)(time(0))(settings.nixStore)(wantMassQuery)(priority).exec();
state->insertCache.use()(uri)(time(0))(storeDir)(wantMassQuery)(priority).exec();
assert(sqlite3_changes(state->db) == 1);
state->caches[uri] = sqlite3_last_insert_rowid(state->db);
state->caches[uri] = Cache{(int) sqlite3_last_insert_rowid(state->db), storeDir};
}
bool cacheExists(const std::string & uri) override
@ -134,7 +139,7 @@ public:
auto queryCache(state->queryCache.use()(uri));
if (queryCache.next()) {
state->caches[uri] = queryCache.getInt(0);
state->caches[uri] = Cache{(int) queryCache.getInt(0), queryCache.getStr(1)};
return true;
}
@ -146,9 +151,9 @@ public:
{
auto state(_state.lock());
auto queryNAR(state->queryNAR.use()
(uriToInt(*state, uri))
(hashPart));
auto & cache(getCache(*state, uri));
auto queryNAR(state->queryNAR.use()(cache.id)(hashPart));
if (!queryNAR.next())
// FIXME: check NARExistence
@ -159,7 +164,7 @@ public:
// FIXME: implement TTL.
auto namePart = queryNAR.getStr(2);
narInfo->path = settings.nixStore + "/" +
narInfo->path = cache.storeDir + "/" +
hashPart + (namePart.empty() ? "" : "-" + namePart);
narInfo->url = queryNAR.getStr(3);
narInfo->compression = queryNAR.getStr(4);
@ -169,9 +174,9 @@ public:
narInfo->narHash = parseHash(queryNAR.getStr(7));
narInfo->narSize = queryNAR.getInt(8);
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(9), " "))
narInfo->references.insert(settings.nixStore + "/" + r);
narInfo->references.insert(cache.storeDir + "/" + r);
if (!queryNAR.isNull(10))
narInfo->deriver = settings.nixStore + "/" + queryNAR.getStr(10);
narInfo->deriver = cache.storeDir + "/" + queryNAR.getStr(10);
for (auto & sig : tokenizeString<Strings>(queryNAR.getStr(11), " "))
narInfo->sigs.insert(sig);
@ -184,6 +189,8 @@ public:
{
auto state(_state.lock());
auto & cache(getCache(*state, uri));
if (info) {
auto narInfo = std::dynamic_pointer_cast<NarInfo>(info);
@ -191,7 +198,7 @@ public:
assert(hashPart == storePathToHash(info->path));
state->insertNAR.use()
(uriToInt(*state, uri))
(cache.id)
(hashPart)
(storePathToName(info->path))
(narInfo ? narInfo->url : "", narInfo != 0)

View file

@ -10,7 +10,8 @@ class NarInfoDiskCache
public:
typedef enum { oValid, oInvalid, oUnknown } Outcome;
virtual void createCache(const std::string & uri, bool wantMassQuery, int priority) = 0;
virtual void createCache(const std::string & uri, const Path & storeDir,
bool wantMassQuery, int priority) = 0;
virtual bool cacheExists(const std::string & uri) = 0;

View file

@ -3,7 +3,7 @@
namespace nix {
NarInfo::NarInfo(const std::string & s, const std::string & whence)
NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence)
{
auto corrupt = [&]() {
throw Error("NAR info file %1% is corrupt");
@ -32,7 +32,7 @@ NarInfo::NarInfo(const std::string & s, const std::string & whence)
std::string value(s, colon + 2, eol - colon - 2);
if (name == "StorePath") {
if (!isStorePath(value)) corrupt();
if (!store.isStorePath(value)) corrupt();
path = value;
}
else if (name == "URL")
@ -53,14 +53,14 @@ NarInfo::NarInfo(const std::string & s, const std::string & whence)
auto refs = tokenizeString<Strings>(value, " ");
if (!references.empty()) corrupt();
for (auto & r : refs) {
auto r2 = settings.nixStore + "/" + r;
if (!isStorePath(r2)) corrupt();
auto r2 = store.storeDir + "/" + r;
if (!store.isStorePath(r2)) corrupt();
references.insert(r2);
}
}
else if (name == "Deriver") {
auto p = settings.nixStore + "/" + value;
if (!isStorePath(p)) corrupt();
auto p = store.storeDir + "/" + value;
if (!store.isStorePath(p)) corrupt();
deriver = p;
}
else if (name == "System")

View file

@ -16,7 +16,7 @@ struct NarInfo : ValidPathInfo
NarInfo() { }
NarInfo(const ValidPathInfo & info) : ValidPathInfo(info) { }
NarInfo(const std::string & s, const std::string & whence);
NarInfo(const Store & store, const std::string & s, const std::string & whence);
std::string to_string() const;
};

View file

@ -184,7 +184,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : "");
Path tempLink = (format("%1%/.tmp-link-%2%-%3%")
% settings.nixStore % getpid() % rand()).str();
% storeDir % getpid() % rand()).str();
if (link(linkPath.c_str(), tempLink.c_str()) == -1) {
if (errno == EMLINK) {

View file

@ -21,26 +21,27 @@
namespace nix {
Path readStorePath(Source & from)
Path readStorePath(Store & store, Source & from)
{
Path path = readString(from);
assertStorePath(path);
store.assertStorePath(path);
return path;
}
template<class T> T readStorePaths(Source & from)
template<class T> T readStorePaths(Store & store, Source & from)
{
T paths = readStrings<T>(from);
for (auto & i : paths) assertStorePath(i);
for (auto & i : paths) store.assertStorePath(i);
return paths;
}
template PathSet readStorePaths(Source & from);
template PathSet readStorePaths(Store & store, Source & from);
RemoteStore::RemoteStore(size_t maxConnections)
: connections(make_ref<Pool<Connection>>(
RemoteStore::RemoteStore(const Params & params, size_t maxConnections)
: LocalFSStore(params)
, connections(make_ref<Pool<Connection>>(
maxConnections,
[this]() { return openConnection(); },
[](const ref<Connection> & r) { return r->to.good() && r->from.good(); }
@ -168,7 +169,7 @@ PathSet RemoteStore::queryValidPaths(const PathSet & paths)
} else {
conn->to << wopQueryValidPaths << paths;
conn->processStderr();
return readStorePaths<PathSet>(conn->from);
return readStorePaths<PathSet>(*this, conn->from);
}
}
@ -178,7 +179,7 @@ PathSet RemoteStore::queryAllValidPaths()
auto conn(connections->get());
conn->to << wopQueryAllValidPaths;
conn->processStderr();
return readStorePaths<PathSet>(conn->from);
return readStorePaths<PathSet>(*this, conn->from);
}
@ -196,7 +197,7 @@ PathSet RemoteStore::querySubstitutablePaths(const PathSet & paths)
} else {
conn->to << wopQuerySubstitutablePaths << paths;
conn->processStderr();
return readStorePaths<PathSet>(conn->from);
return readStorePaths<PathSet>(*this, conn->from);
}
}
@ -220,7 +221,7 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
if (reply == 0) continue;
info.deriver = readString(conn->from);
if (info.deriver != "") assertStorePath(info.deriver);
info.references = readStorePaths<PathSet>(conn->from);
info.references = readStorePaths<PathSet>(*this, conn->from);
info.downloadSize = readLongLong(conn->from);
info.narSize = GET_PROTOCOL_MINOR(conn->daemonVersion) >= 7 ? readLongLong(conn->from) : 0;
infos[i] = info;
@ -232,11 +233,11 @@ void RemoteStore::querySubstitutablePathInfos(const PathSet & paths,
conn->processStderr();
unsigned int count = readInt(conn->from);
for (unsigned int n = 0; n < count; n++) {
Path path = readStorePath(conn->from);
Path path = readStorePath(*this, conn->from);
SubstitutablePathInfo & info(infos[path]);
info.deriver = readString(conn->from);
if (info.deriver != "") assertStorePath(info.deriver);
info.references = readStorePaths<PathSet>(conn->from);
info.references = readStorePaths<PathSet>(*this, conn->from);
info.downloadSize = readLongLong(conn->from);
info.narSize = readLongLong(conn->from);
}
@ -266,7 +267,7 @@ std::shared_ptr<ValidPathInfo> RemoteStore::queryPathInfoUncached(const Path & p
info->deriver = readString(conn->from);
if (info->deriver != "") assertStorePath(info->deriver);
info->narHash = parseHash(htSHA256, readString(conn->from));
info->references = readStorePaths<PathSet>(conn->from);
info->references = readStorePaths<PathSet>(*this, conn->from);
info->registrationTime = readInt(conn->from);
info->narSize = readLongLong(conn->from);
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 16) {
@ -283,7 +284,7 @@ void RemoteStore::queryReferrers(const Path & path,
auto conn(connections->get());
conn->to << wopQueryReferrers << path;
conn->processStderr();
PathSet referrers2 = readStorePaths<PathSet>(conn->from);
PathSet referrers2 = readStorePaths<PathSet>(*this, conn->from);
referrers.insert(referrers2.begin(), referrers2.end());
}
@ -293,7 +294,7 @@ PathSet RemoteStore::queryValidDerivers(const Path & path)
auto conn(connections->get());
conn->to << wopQueryValidDerivers << path;
conn->processStderr();
return readStorePaths<PathSet>(conn->from);
return readStorePaths<PathSet>(*this, conn->from);
}
@ -302,7 +303,7 @@ PathSet RemoteStore::queryDerivationOutputs(const Path & path)
auto conn(connections->get());
conn->to << wopQueryDerivationOutputs << path;
conn->processStderr();
return readStorePaths<PathSet>(conn->from);
return readStorePaths<PathSet>(*this, conn->from);
}
@ -363,7 +364,7 @@ Path RemoteStore::addToStore(const string & name, const Path & _srcPath,
throw;
}
return readStorePath(conn->from);
return readStorePath(*this, conn->from);
}
@ -376,7 +377,7 @@ Path RemoteStore::addTextToStore(const string & name, const string & s,
conn->to << wopAddTextToStore << name << s << references;
conn->processStderr();
return readStorePath(conn->from);
return readStorePath(*this, conn->from);
}
@ -465,7 +466,7 @@ Roots RemoteStore::findRoots()
Roots result;
while (count--) {
Path link = readString(conn->from);
Path target = readStorePath(conn->from);
Path target = readStorePath(*this, conn->from);
result[link] = target;
}
return result;

View file

@ -22,7 +22,7 @@ class RemoteStore : public LocalFSStore
{
public:
RemoteStore(size_t maxConnections = std::numeric_limits<size_t>::max());
RemoteStore(const Params & params, size_t maxConnections = std::numeric_limits<size_t>::max());
/* Implementations of abstract store API methods. */

View file

@ -47,7 +47,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
Stats stats;
S3BinaryCacheStoreImpl(
const StoreParams & params, const std::string & bucketName)
const Params & params, const std::string & bucketName)
: S3BinaryCacheStore(params)
, bucketName(bucketName)
, config(makeConfig())
@ -95,7 +95,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
BinaryCacheStore::init();
diskCache->createCache(getUri(), wantMassQuery_, priority);
diskCache->createCache(getUri(), storeDir, wantMassQuery_, priority);
}
}
@ -232,7 +232,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
for (auto object : contents) {
auto & key = object.GetKey();
if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue;
paths.insert(settings.nixStore + "/" + key.substr(0, key.size() - 8));
paths.insert(storeDir + "/" + key.substr(0, key.size() - 8));
}
marker = res.GetNextMarker();
@ -244,7 +244,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
};
static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params)
const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store>
{
if (std::string(uri, 0, 5) != "s3://") return 0;

View file

@ -10,7 +10,7 @@ class S3BinaryCacheStore : public BinaryCacheStore
{
protected:
S3BinaryCacheStore(const StoreParams & params)
S3BinaryCacheStore(const Params & params)
: BinaryCacheStore(params)
{ }

View file

@ -8,32 +8,32 @@
namespace nix {
bool isInStore(const Path & path)
bool Store::isInStore(const Path & path) const
{
return isInDir(path, settings.nixStore);
return isInDir(path, storeDir);
}
bool isStorePath(const Path & path)
bool Store::isStorePath(const Path & path) const
{
return isInStore(path)
&& path.size() >= settings.nixStore.size() + 1 + storePathHashLen
&& path.find('/', settings.nixStore.size() + 1) == Path::npos;
&& path.size() >= storeDir.size() + 1 + storePathHashLen
&& path.find('/', storeDir.size() + 1) == Path::npos;
}
void assertStorePath(const Path & path)
void Store::assertStorePath(const Path & path) const
{
if (!isStorePath(path))
throw Error(format("path %1% is not in the Nix store") % path);
}
Path toStorePath(const Path & path)
Path Store::toStorePath(const Path & path) const
{
if (!isInStore(path))
throw Error(format("path %1% is not in the Nix store") % path);
Path::size_type slash = path.find('/', settings.nixStore.size() + 1);
Path::size_type slash = path.find('/', storeDir.size() + 1);
if (slash == Path::npos)
return path;
else
@ -41,7 +41,7 @@ Path toStorePath(const Path & path)
}
Path followLinksToStore(const Path & _path)
Path Store::followLinksToStore(const Path & _path) const
{
Path path = absPath(_path);
while (!isInStore(path)) {
@ -55,7 +55,7 @@ Path followLinksToStore(const Path & _path)
}
Path followLinksToStorePath(const Path & path)
Path Store::followLinksToStorePath(const Path & path) const
{
return toStorePath(followLinksToStore(path));
}
@ -63,18 +63,17 @@ Path followLinksToStorePath(const Path & path)
string storePathToName(const Path & path)
{
assertStorePath(path);
auto l = settings.nixStore.size() + 1 + storePathHashLen;
assert(path.size() >= l);
return path.size() == l ? "" : string(path, l + 1);
auto base = baseNameOf(path);
assert(base.size() == storePathHashLen || (base.size() > storePathHashLen && base[storePathHashLen] == '-'));
return base.size() == storePathHashLen ? "" : string(base, storePathHashLen + 1);
}
string storePathToHash(const Path & path)
{
assertStorePath(path);
assert(path.size() >= settings.nixStore.size() + 1 + storePathHashLen);
return string(path, settings.nixStore.size() + 1, storePathHashLen);
auto base = baseNameOf(path);
assert(base.size() >= storePathHashLen);
return string(base, 0, storePathHashLen);
}
@ -168,31 +167,31 @@ void checkStoreName(const string & name)
*/
Path makeStorePath(const string & type,
const Hash & hash, const string & name)
Path Store::makeStorePath(const string & type,
const Hash & hash, const string & name) const
{
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
string s = type + ":sha256:" + printHash(hash) + ":"
+ settings.nixStore + ":" + name;
+ storeDir + ":" + name;
checkStoreName(name);
return settings.nixStore + "/"
return storeDir + "/"
+ printHash32(compressHash(hashString(htSHA256, s), 20))
+ "-" + name;
}
Path makeOutputPath(const string & id,
const Hash & hash, const string & name)
Path Store::makeOutputPath(const string & id,
const Hash & hash, const string & name) const
{
return makeStorePath("output:" + id, hash,
name + (id == "out" ? "" : "-" + id));
}
Path makeFixedOutputPath(bool recursive,
HashType hashAlgo, Hash hash, string name)
Path Store::makeFixedOutputPath(bool recursive,
HashType hashAlgo, Hash hash, string name) const
{
return hashAlgo == htSHA256 && recursive
? makeStorePath("source", hash, name)
@ -203,8 +202,8 @@ Path makeFixedOutputPath(bool recursive,
}
std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
bool recursive, HashType hashAlgo, PathFilter & filter)
std::pair<Path, Hash> Store::computeStorePathForPath(const Path & srcPath,
bool recursive, HashType hashAlgo, PathFilter & filter) const
{
HashType ht(hashAlgo);
Hash h = recursive ? hashPath(ht, srcPath, filter).first : hashFile(ht, srcPath);
@ -214,8 +213,8 @@ std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
}
Path computeStorePathForText(const string & name, const string & s,
const PathSet & references)
Path Store::computeStorePathForText(const string & name, const string & s,
const PathSet & references) const
{
Hash hash = hashString(htSHA256, s);
/* Stuff the references (if any) into the type. This is a bit
@ -230,6 +229,12 @@ Path computeStorePathForText(const string & name, const string & s,
}
Store::Store(const Params & params)
: storeDir(settings.nixStore)
{
}
std::string Store::getUri()
{
return "";
@ -465,7 +470,7 @@ RegisterStoreImplementation::Implementations * RegisterStoreImplementation::impl
ref<Store> openStoreAt(const std::string & uri_)
{
auto uri(uri_);
StoreParams params;
Store::Params params;
auto q = uri.find('?');
if (q != std::string::npos) {
for (auto s : tokenizeString<Strings>(uri.substr(q + 1), "&")) {
@ -492,7 +497,7 @@ ref<Store> openStore()
static RegisterStoreImplementation regStore([](
const std::string & uri, const StoreParams & params)
const std::string & uri, const Store::Params & params)
-> std::shared_ptr<Store>
{
enum { mDaemon, mLocal, mAuto } mode;
@ -512,8 +517,8 @@ static RegisterStoreImplementation regStore([](
}
return mode == mDaemon
? std::shared_ptr<Store>(std::make_shared<RemoteStore>())
: std::shared_ptr<Store>(std::make_shared<LocalStore>());
? std::shared_ptr<Store>(std::make_shared<RemoteStore>(params))
: std::shared_ptr<Store>(std::make_shared<LocalStore>(params));
});

View file

@ -177,6 +177,12 @@ class NarInfoDiskCache;
class Store : public std::enable_shared_from_this<Store>
{
public:
typedef std::map<std::string, std::string> Params;
const Path storeDir;
protected:
struct State
@ -188,12 +194,71 @@ protected:
std::shared_ptr<NarInfoDiskCache> diskCache;
Store(const Params & params);
public:
virtual ~Store() { }
virtual std::string getUri() = 0;
/* Return true if path is in the Nix store (but not the Nix
store itself). */
bool isInStore(const Path & path) const;
/* Return true if path is a store path, i.e. a direct child of
the Nix store. */
bool isStorePath(const Path & path) const;
/* Throw an exception if path is not a store path. */
void assertStorePath(const Path & path) const;
/* Chop off the parts after the top-level store name, e.g.,
/nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
Path toStorePath(const Path & path) const;
/* Follow symlinks until we end up with a path in the Nix store. */
Path followLinksToStore(const Path & path) const;
/* Same as followLinksToStore(), but apply toStorePath() to the
result. */
Path followLinksToStorePath(const Path & path) const;
/* Constructs a unique store path name. */
Path makeStorePath(const string & type,
const Hash & hash, const string & name) const;
Path makeOutputPath(const string & id,
const Hash & hash, const string & name) const;
Path makeFixedOutputPath(bool recursive,
HashType hashAlgo, Hash hash, string name) const;
/* This is the preparatory part of addToStore() and
addToStoreFixed(); it computes the store path to which srcPath
is to be copied. Returns the store path and the cryptographic
hash of the contents of srcPath. */
std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter) const;
/* Preparatory part of addTextToStore().
!!! Computation of the path should take the references given to
addTextToStore() into account, otherwise we have a (relatively
minor) security hole: a caller can register a source file with
bogus references. If there are too many references, the path may
not be garbage collected when it has to be (not really a problem,
the caller could create a root anyway), or it may be garbage
collected when it shouldn't be (more serious).
Hashing the references would solve this (bogus references would
simply yield a different store path, so other users wouldn't be
affected), but it has some backwards compatibility issues (the
hashing scheme changes), so I'm not doing that for now. */
Path computeStorePathForText(const string & name, const string & s,
const PathSet & references) const;
/* Check whether a path is valid. */
bool isValidPath(const Path & path);
@ -429,80 +494,26 @@ protected:
class LocalFSStore : public Store
{
protected:
using Store::Store;
public:
void narFromPath(const Path & path, Sink & sink) override;
ref<FSAccessor> getFSAccessor() override;
};
/* !!! These should be part of the store API, I guess. */
/* Throw an exception if `path' is not directly in the Nix store. */
void assertStorePath(const Path & path);
bool isInStore(const Path & path);
bool isStorePath(const Path & path);
/* Extract the name part of the given store path. */
string storePathToName(const Path & path);
/* Extract the hash part of the given store path. */
string storePathToHash(const Path & path);
/* Check whether name is a valid store path name part, i.e. contains
only the characters [a-zA-Z0-9\+\-\.\_\?\=] and doesn't start with
a dot. */
void checkStoreName(const string & name);
/* Chop off the parts after the top-level store name, e.g.,
/nix/store/abcd-foo/bar => /nix/store/abcd-foo. */
Path toStorePath(const Path & path);
/* Follow symlinks until we end up with a path in the Nix store. */
Path followLinksToStore(const Path & path);
/* Same as followLinksToStore(), but apply toStorePath() to the
result. */
Path followLinksToStorePath(const Path & path);
/* Constructs a unique store path name. */
Path makeStorePath(const string & type,
const Hash & hash, const string & name);
Path makeOutputPath(const string & id,
const Hash & hash, const string & name);
Path makeFixedOutputPath(bool recursive,
HashType hashAlgo, Hash hash, string name);
/* This is the preparatory part of addToStore() and addToStoreFixed();
it computes the store path to which srcPath is to be copied.
Returns the store path and the cryptographic hash of the
contents of srcPath. */
std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
bool recursive = true, HashType hashAlgo = htSHA256,
PathFilter & filter = defaultPathFilter);
/* Preparatory part of addTextToStore().
!!! Computation of the path should take the references given to
addTextToStore() into account, otherwise we have a (relatively
minor) security hole: a caller can register a source file with
bogus references. If there are too many references, the path may
not be garbage collected when it has to be (not really a problem,
the caller could create a root anyway), or it may be garbage
collected when it shouldn't be (more serious).
Hashing the references would solve this (bogus references would
simply yield a different store path, so other users wouldn't be
affected), but it has some backwards compatibility issues (the
hashing scheme changes), so I'm not doing that for now. */
Path computeStorePathForText(const string & name, const string & s,
const PathSet & references);
/* Copy a path from one store to another. */
void copyStorePath(ref<Store> srcStore, ref<Store> dstStore,
const Path & storePath, bool repair = false);
@ -542,10 +553,8 @@ std::list<ref<Store>> getDefaultSubstituters();
/* Store implementation registration. */
typedef std::map<std::string, std::string> StoreParams;
typedef std::function<std::shared_ptr<Store>(
const std::string & uri, const StoreParams & params)> OpenStore;
const std::string & uri, const Store::Params & params)> OpenStore;
struct RegisterStoreImplementation
{

View file

@ -56,8 +56,8 @@ typedef enum {
#define STDERR_ERROR 0x63787470
Path readStorePath(Source & from);
template<class T> T readStorePaths(Source & from);
Path readStorePath(Store & store, Source & from);
template<class T> T readStorePaths(Store & store, Source & from);
}

View file

@ -176,7 +176,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
connection. */
Path path = readString(from);
startWork();
assertStorePath(path);
store->assertStorePath(path);
bool result = store->isValidPath(path);
stopWork();
to << result;
@ -184,7 +184,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopQueryValidPaths: {
PathSet paths = readStorePaths<PathSet>(from);
PathSet paths = readStorePaths<PathSet>(*store, from);
startWork();
PathSet res = store->queryValidPaths(paths);
stopWork();
@ -193,7 +193,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopHasSubstitutes: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
startWork();
PathSet res = store->querySubstitutablePaths({path});
stopWork();
@ -202,7 +202,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopQuerySubstitutablePaths: {
PathSet paths = readStorePaths<PathSet>(from);
PathSet paths = readStorePaths<PathSet>(*store, from);
startWork();
PathSet res = store->querySubstitutablePaths(paths);
stopWork();
@ -211,7 +211,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopQueryPathHash: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
startWork();
auto hash = store->queryPathInfo(path)->narHash;
stopWork();
@ -223,7 +223,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopQueryReferrers:
case wopQueryValidDerivers:
case wopQueryDerivationOutputs: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
startWork();
PathSet paths;
if (op == wopQueryReferences)
@ -239,7 +239,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopQueryDerivationOutputNames: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
startWork();
StringSet names;
names = store->queryDerivationOutputNames(path);
@ -249,7 +249,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopQueryDeriver: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
startWork();
auto deriver = store->queryPathInfo(path)->deriver;
stopWork();
@ -302,7 +302,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopAddTextToStore: {
string suffix = readString(from);
string s = readString(from);
PathSet refs = readStorePaths<PathSet>(from);
PathSet refs = readStorePaths<PathSet>(*store, from);
startWork();
Path path = store->addTextToStore(suffix, s, refs);
stopWork();
@ -311,7 +311,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopExportPath: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
readInt(from); // obsolete
startWork();
TunnelSink sink(to);
@ -331,7 +331,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopBuildPaths: {
PathSet drvs = readStorePaths<PathSet>(from);
PathSet drvs = readStorePaths<PathSet>(*store, from);
BuildMode mode = bmNormal;
if (GET_PROTOCOL_MINOR(clientVersion) >= 15) {
mode = (BuildMode)readInt(from);
@ -349,9 +349,9 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopBuildDerivation: {
Path drvPath = readStorePath(from);
Path drvPath = readStorePath(*store, from);
BasicDerivation drv;
from >> drv;
readDerivation(from, *store, drv);
BuildMode buildMode = (BuildMode) readInt(from);
startWork();
if (!trusted)
@ -363,7 +363,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopEnsurePath: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
startWork();
store->ensurePath(path);
stopWork();
@ -372,7 +372,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopAddTempRoot: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
startWork();
store->addTempRoot(path);
stopWork();
@ -410,7 +410,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
case wopCollectGarbage: {
GCOptions options;
options.action = (GCOptions::GCAction) readInt(from);
options.pathsToDelete = readStorePaths<PathSet>(from);
options.pathsToDelete = readStorePaths<PathSet>(*store, from);
options.ignoreLiveness = readInt(from);
options.maxFreed = readLongLong(from);
readInt(from); // obsolete field
@ -486,7 +486,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopQuerySubstitutablePathInfos: {
PathSet paths = readStorePaths<PathSet>(from);
PathSet paths = readStorePaths<PathSet>(*store, from);
startWork();
SubstitutablePathInfos infos;
store->querySubstitutablePathInfos(paths, infos);
@ -508,7 +508,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopQueryPathInfo: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
std::shared_ptr<const ValidPathInfo> info;
startWork();
try {
@ -553,7 +553,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
}
case wopAddSignatures: {
Path path = readStorePath(from);
Path path = readStorePath(*store, from);
StringSet sigs = readStrings<StringSet>(from);
startWork();
if (!trusted)
@ -607,7 +607,7 @@ static void processConnection(bool trusted)
#endif
/* Open the store. */
auto store = make_ref<LocalStore>();
auto store = make_ref<LocalStore>(Store::Params()); // FIXME: get params from somewhere
stopWork();
to.flush();

View file

@ -387,7 +387,7 @@ static void queryInstSources(EvalState & state,
case srcStorePaths: {
for (auto & i : args) {
Path path = followLinksToStorePath(i);
Path path = state.store->followLinksToStorePath(i);
string name = baseNameOf(path);
string::size_type dash = name.find('-');
@ -742,7 +742,7 @@ static void uninstallDerivations(Globals & globals, Strings & selectors,
for (auto & j : selectors)
/* !!! the repeated calls to followLinksToStorePath()
are expensive, should pre-compute them. */
if ((isPath(j) && i.queryOutPath() == followLinksToStorePath(j))
if ((isPath(j) && i.queryOutPath() == globals.state->store->followLinksToStorePath(j))
|| DrvName(j).matches(drvName))
{
printMsg(lvlInfo, format("uninstalling %1%") % i.name);

View file

@ -146,7 +146,7 @@ int main(int argc, char * * argv)
Path storePath;
if (args.size() == 2) {
expectedHash = parseHash16or32(ht, args[1]);
storePath = makeFixedOutputPath(unpack, ht, expectedHash, name);
storePath = store->makeFixedOutputPath(unpack, ht, expectedHash, name);
if (store->isValidPath(storePath))
hash = expectedHash;
else
@ -197,7 +197,7 @@ int main(int argc, char * * argv)
into the Nix store. */
storePath = store->addToStore(name, tmpFile, unpack, ht);
assert(storePath == makeFixedOutputPath(unpack, ht, hash, name));
assert(storePath == store->makeFixedOutputPath(unpack, ht, hash, name));
}
if (!printPath)

View file

@ -124,7 +124,7 @@ static void opRealise(Strings opFlags, Strings opArgs)
Paths paths;
for (auto & i : opArgs) {
DrvPathWithOutputs p = parseDrvPathWithOutputs(i);
paths.push_back(makeDrvPathWithOutputs(followLinksToStorePath(p.first), p.second));
paths.push_back(makeDrvPathWithOutputs(store->followLinksToStorePath(p.first), p.second));
}
unsigned long long downloadSize, narSize;
@ -207,7 +207,7 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs)
string name = *i++;
cout << format("%1%\n") %
makeFixedOutputPath(recursive, hashAlgo,
store->makeFixedOutputPath(recursive, hashAlgo,
parseHash16or32(hashAlgo, hash), name);
}
@ -315,7 +315,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qOutputs: {
for (auto & i : opArgs) {
i = followLinksToStorePath(i);
i = store->followLinksToStorePath(i);
if (forceRealise) realisePath(i);
Derivation drv = store->derivationFromPath(i);
for (auto & j : drv.outputs)
@ -330,7 +330,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qReferrersClosure: {
PathSet paths;
for (auto & i : opArgs) {
PathSet ps = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
PathSet ps = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : ps) {
if (query == qRequisites) store->computeFSClosure(j, paths, false, includeOutputs);
else if (query == qReferences) {
@ -350,7 +350,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qDeriver:
for (auto & i : opArgs) {
Path deriver = store->queryPathInfo(followLinksToStorePath(i))->deriver;
Path deriver = store->queryPathInfo(store->followLinksToStorePath(i))->deriver;
cout << format("%1%\n") %
(deriver == "" ? "unknown-deriver" : deriver);
}
@ -358,7 +358,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qBinding:
for (auto & i : opArgs) {
Path path = useDeriver(followLinksToStorePath(i));
Path path = useDeriver(store->followLinksToStorePath(i));
Derivation drv = store->derivationFromPath(path);
StringPairs::iterator j = drv.env.find(bindingName);
if (j == drv.env.end())
@ -371,7 +371,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qHash:
case qSize:
for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : paths) {
auto info = store->queryPathInfo(j);
if (query == qHash) {
@ -386,14 +386,14 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qTree: {
PathSet done;
for (auto & i : opArgs)
printTree(followLinksToStorePath(i), "", "", done);
printTree(store->followLinksToStorePath(i), "", "", done);
break;
}
case qGraph: {
PathSet roots;
for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
printDotGraph(ref<Store>(store), roots);
@ -403,7 +403,7 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qXml: {
PathSet roots;
for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
roots.insert(paths.begin(), paths.end());
}
printXmlGraph(ref<Store>(store), roots);
@ -412,14 +412,14 @@ static void opQuery(Strings opFlags, Strings opArgs)
case qResolve: {
for (auto & i : opArgs)
cout << format("%1%\n") % followLinksToStorePath(i);
cout << format("%1%\n") % store->followLinksToStorePath(i);
break;
}
case qRoots: {
PathSet referrers;
for (auto & i : opArgs) {
PathSet paths = maybeUseOutputs(followLinksToStorePath(i), useOutput, forceRealise);
PathSet paths = maybeUseOutputs(store->followLinksToStorePath(i), useOutput, forceRealise);
for (auto & j : paths)
store->computeFSClosure(j, referrers, true,
settings.gcKeepOutputs, settings.gcKeepDerivations);
@ -479,7 +479,7 @@ static void opReadLog(Strings opFlags, Strings opArgs)
RunPager pager;
for (auto & i : opArgs) {
Path path = useDeriver(followLinksToStorePath(i));
Path path = useDeriver(store->followLinksToStorePath(i));
string baseName = baseNameOf(path);
bool found = false;
@ -599,7 +599,7 @@ static void opCheckValidity(Strings opFlags, Strings opArgs)
else throw UsageError(format("unknown flag %1%") % i);
for (auto & i : opArgs) {
Path path = followLinksToStorePath(i);
Path path = store->followLinksToStorePath(i);
if (!store->isValidPath(path)) {
if (printInvalid)
cout << format("%1%\n") % path;
@ -662,7 +662,7 @@ static void opDelete(Strings opFlags, Strings opArgs)
else throw UsageError(format("unknown flag %1%") % i);
for (auto & i : opArgs)
options.pathsToDelete.insert(followLinksToStorePath(i));
options.pathsToDelete.insert(store->followLinksToStorePath(i));
GCResults results;
PrintFreed freed(true, results);
@ -761,7 +761,7 @@ static void opVerifyPath(Strings opFlags, Strings opArgs)
int status = 0;
for (auto & i : opArgs) {
Path path = followLinksToStorePath(i);
Path path = store->followLinksToStorePath(i);
printMsg(lvlTalkative, format("checking path %1%...") % path);
auto info = store->queryPathInfo(path);
HashSink sink(info->narHash.type);
@ -787,7 +787,7 @@ static void opRepairPath(Strings opFlags, Strings opArgs)
throw UsageError("no flags expected");
for (auto & i : opArgs) {
Path path = followLinksToStorePath(i);
Path path = store->followLinksToStorePath(i);
ensureLocalStore()->repairPath(path);
}
}
@ -847,7 +847,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdQueryValidPaths: {
bool lock = readInt(in);
bool substitute = readInt(in);
PathSet paths = readStorePaths<PathSet>(in);
PathSet paths = readStorePaths<PathSet>(*store, in);
if (lock && writeAllowed)
for (auto & path : paths)
store->addTempRoot(path);
@ -879,7 +879,7 @@ static void opServe(Strings opFlags, Strings opArgs)
}
case cmdQueryPathInfos: {
PathSet paths = readStorePaths<PathSet>(in);
PathSet paths = readStorePaths<PathSet>(*store, in);
// !!! Maybe we want a queryPathInfos?
for (auto & i : paths) {
try {
@ -896,7 +896,7 @@ static void opServe(Strings opFlags, Strings opArgs)
}
case cmdDumpStorePath:
dumpPath(readStorePath(in), out);
dumpPath(readStorePath(*store, in), out);
break;
case cmdImportPaths: {
@ -908,7 +908,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdExportPaths: {
readInt(in); // obsolete
Paths sorted = store->topoSortPaths(readStorePaths<PathSet>(in));
Paths sorted = store->topoSortPaths(readStorePaths<PathSet>(*store, in));
reverse(sorted.begin(), sorted.end());
store->exportPaths(sorted, out);
break;
@ -917,7 +917,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdBuildPaths: { /* Used by build-remote.pl. */
if (!writeAllowed) throw Error("building paths is not allowed");
PathSet paths = readStorePaths<PathSet>(in);
PathSet paths = readStorePaths<PathSet>(*store, in);
getBuildSettings();
@ -936,9 +936,9 @@ static void opServe(Strings opFlags, Strings opArgs)
if (!writeAllowed) throw Error("building paths is not allowed");
Path drvPath = readStorePath(in); // informational only
Path drvPath = readStorePath(*store, in); // informational only
BasicDerivation drv;
in >> drv;
readDerivation(in, *store, drv);
getBuildSettings();
@ -952,7 +952,7 @@ static void opServe(Strings opFlags, Strings opArgs)
case cmdQueryClosure: {
bool includeOutputs = readInt(in);
PathSet paths = readStorePaths<PathSet>(in);
PathSet paths = readStorePaths<PathSet>(*store, in);
PathSet closure;
for (auto & i : paths)
store->computeFSClosure(i, closure, false, includeOutputs);

View file

@ -102,7 +102,7 @@ void StorePathsCommand::run(ref<Store> store)
else {
for (auto & storePath : storePaths)
storePath = followLinksToStorePath(storePath);
storePath = store->followLinksToStorePath(storePath);
if (recursive) {
PathSet closure;

View file

@ -17,7 +17,7 @@ UserEnvElems MixInstallables::evalInstallables(ref<Store> store)
if (std::string(installable, 0, 1) == "/") {
if (isStorePath(installable)) {
if (store->isStorePath(installable)) {
if (isDerivation(installable)) {
UserEnvElem elem;