1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 10:11:47 +02:00

Stores no longer inherit from their configs

Fix #10766

See that ticket for details.

Progress (I hope!) towards #11139.

Co-Authored-By: Sergei Zimmerman <xokdvium@proton.me>
This commit is contained in:
John Ericson 2025-05-07 17:07:23 -04:00
parent f0f196cef0
commit 934918ba16
48 changed files with 743 additions and 593 deletions

View file

@ -75,6 +75,11 @@ std::string LocalStoreConfig::doc()
;
}
ref<Store> LocalStore::Config::openStore() const
{
return make_ref<LocalStore>(ref{shared_from_this()});
}
struct LocalStore::State::Stmts {
/* Some precompiled SQLite statements. */
SQLiteStmt RegisterValidPath;
@ -97,38 +102,33 @@ struct LocalStore::State::Stmts {
SQLiteStmt AddRealisationReference;
};
LocalStore::LocalStore(
std::string_view scheme,
PathView path,
const Params & params)
: StoreConfig(params)
, LocalFSStoreConfig(path, params)
, LocalStoreConfig(scheme, path, params)
, Store(params)
, LocalFSStore(params)
, dbDir(stateDir + "/db")
, linksDir(realStoreDir + "/.links")
LocalStore::LocalStore(ref<const Config> config)
: Store{*config}
, LocalFSStore{*config}
, config{config}
, dbDir(config->stateDir + "/db")
, linksDir(config->realStoreDir + "/.links")
, reservedPath(dbDir + "/reserved")
, schemaPath(dbDir + "/schema")
, tempRootsDir(stateDir + "/temproots")
, tempRootsDir(config->stateDir + "/temproots")
, fnTempRoots(fmt("%s/%d", tempRootsDir, getpid()))
{
auto state(_state.lock());
state->stmts = std::make_unique<State::Stmts>();
/* Create missing state directories if they don't already exist. */
createDirs(realStoreDir.get());
if (readOnly) {
createDirs(config->realStoreDir.get());
if (config->readOnly) {
experimentalFeatureSettings.require(Xp::ReadOnlyLocalStore);
} else {
makeStoreWritable();
}
createDirs(linksDir);
Path profilesDir = stateDir + "/profiles";
Path profilesDir = config->stateDir + "/profiles";
createDirs(profilesDir);
createDirs(tempRootsDir);
createDirs(dbDir);
Path gcRootsDir = stateDir + "/gcroots";
Path gcRootsDir = config->stateDir + "/gcroots";
if (!pathExists(gcRootsDir)) {
createDirs(gcRootsDir);
createSymlink(profilesDir, gcRootsDir + "/profiles");
@ -136,7 +136,7 @@ LocalStore::LocalStore(
for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) {
createDirs(perUserDir);
if (!readOnly) {
if (!config->readOnly) {
// Skip chmod call if the directory already has the correct permissions (0755).
// This is to avoid failing when the executing user lacks permissions to change the directory's permissions
// even if it would be no-op.
@ -153,16 +153,16 @@ LocalStore::LocalStore(
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
if (!gr)
printError("warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup);
else if (!readOnly) {
else if (!config->readOnly) {
struct stat st;
if (stat(realStoreDir.get().c_str(), &st))
throw SysError("getting attributes of path '%1%'", realStoreDir);
if (stat(config->realStoreDir.get().c_str(), &st))
throw SysError("getting attributes of path '%1%'", config->realStoreDir);
if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
if (chown(realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
throw SysError("changing ownership of path '%1%'", realStoreDir);
if (chmod(realStoreDir.get().c_str(), perm) == -1)
throw SysError("changing permissions on path '%1%'", realStoreDir);
if (chown(config->realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
throw SysError("changing ownership of path '%1%'", config->realStoreDir);
if (chmod(config->realStoreDir.get().c_str(), perm) == -1)
throw SysError("changing permissions on path '%1%'", config->realStoreDir);
}
}
}
@ -170,7 +170,7 @@ LocalStore::LocalStore(
/* Ensure that the store and its parents are not symlinks. */
if (!settings.allowSymlinkedStore) {
std::filesystem::path path = realStoreDir.get();
std::filesystem::path path = config->realStoreDir.get();
std::filesystem::path root = path.root_path();
while (path != root) {
if (std::filesystem::is_symlink(path))
@ -217,12 +217,12 @@ LocalStore::LocalStore(
/* Acquire the big fat lock in shared mode to make sure that no
schema upgrade is in progress. */
if (!readOnly) {
if (!config->readOnly) {
Path globalLockPath = dbDir + "/big-lock";
globalLock = openLockFile(globalLockPath.c_str(), true);
}
if (!readOnly && !lockFile(globalLock.get(), ltRead, false)) {
if (!config->readOnly && !lockFile(globalLock.get(), ltRead, false)) {
printInfo("waiting for the big Nix store lock...");
lockFile(globalLock.get(), ltRead, true);
}
@ -230,7 +230,7 @@ LocalStore::LocalStore(
/* Check the current database schema and if necessary do an
upgrade. */
int curSchema = getSchema();
if (readOnly && curSchema < nixSchemaVersion) {
if (config->readOnly && curSchema < nixSchemaVersion) {
debug("current schema version: %d", curSchema);
debug("supported schema version: %d", nixSchemaVersion);
throw Error(curSchema == 0 ?
@ -378,15 +378,9 @@ LocalStore::LocalStore(
}
LocalStore::LocalStore(const Params & params)
: LocalStore("local", "", params)
{
}
AutoCloseFD LocalStore::openGCLock()
{
Path fnGCLock = stateDir + "/gc.lock";
Path fnGCLock = config->stateDir + "/gc.lock";
auto fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT
#ifndef _WIN32
| O_CLOEXEC
@ -452,17 +446,17 @@ int LocalStore::getSchema()
void LocalStore::openDB(State & state, bool create)
{
if (create && readOnly) {
if (create && config->readOnly) {
throw Error("cannot create database while in read-only mode");
}
if (access(dbDir.c_str(), R_OK | (readOnly ? 0 : W_OK)))
if (access(dbDir.c_str(), R_OK | (config->readOnly ? 0 : W_OK)))
throw SysError("Nix database directory '%1%' is not writable", dbDir);
/* Open the Nix database. */
std::string dbPath = dbDir + "/db.sqlite";
auto & db(state.db);
auto openMode = readOnly ? SQLiteOpenMode::Immutable
auto openMode = config->readOnly ? SQLiteOpenMode::Immutable
: create ? SQLiteOpenMode::Normal
: SQLiteOpenMode::NoCreate;
state.db = SQLite(dbPath, openMode);
@ -575,12 +569,12 @@ void LocalStore::makeStoreWritable()
if (!isRootUser()) return;
/* Check if /nix/store is on a read-only mount. */
struct statvfs stat;
if (statvfs(realStoreDir.get().c_str(), &stat) != 0)
if (statvfs(config->realStoreDir.get().c_str(), &stat) != 0)
throw SysError("getting info about the Nix store mount point");
if (stat.f_flag & ST_RDONLY) {
if (mount(0, realStoreDir.get().c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError("remounting %1% writable", realStoreDir);
if (mount(0, config->realStoreDir.get().c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
throw SysError("remounting %1% writable", config->realStoreDir);
}
#endif
}
@ -920,7 +914,7 @@ StorePathSet LocalStore::querySubstitutablePaths(const StorePathSet & paths)
for (auto & sub : getDefaultSubstituters()) {
if (remaining.empty()) break;
if (sub->storeDir != storeDir) continue;
if (!sub->wantMassQuery) continue;
if (!sub->config.wantMassQuery) continue;
auto valid = sub->queryValidPaths(remaining);
@ -1032,12 +1026,12 @@ const PublicKeys & LocalStore::getPublicKeys()
bool LocalStore::pathInfoIsUntrusted(const ValidPathInfo & info)
{
return requireSigs && !info.checkSignatures(*this, getPublicKeys());
return config->requireSigs && !info.checkSignatures(*this, getPublicKeys());
}
bool LocalStore::realisationIsUntrusted(const Realisation & realisation)
{
return requireSigs && !realisation.checkSignatures(getPublicKeys());
return config->requireSigs && !realisation.checkSignatures(getPublicKeys());
}
void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
@ -1334,7 +1328,7 @@ std::pair<std::filesystem::path, AutoCloseFD> LocalStore::createTempDirInStore()
/* There is a slight possibility that `tmpDir' gets deleted by
the GC between createTempDir() and when we acquire a lock on it.
We'll repeat until 'tmpDir' exists and we've locked it. */
tmpDirFn = createTempDir(realStoreDir, "tmp");
tmpDirFn = createTempDir(config->realStoreDir, "tmp");
tmpDirFd = openDirectory(tmpDirFn);
if (!tmpDirFd) {
continue;
@ -1475,7 +1469,7 @@ LocalStore::VerificationResult LocalStore::verifyAllValidPaths(RepairFlag repair
database and the filesystem) in the loop below, in order to catch
invalid states.
*/
for (auto & i : DirectoryIterator{realStoreDir.to_string()}) {
for (auto & i : DirectoryIterator{config->realStoreDir.get()}) {
checkInterrupt();
try {
storePathsInStoreDir.insert({i.path().filename().string()});
@ -1664,7 +1658,7 @@ void LocalStore::addBuildLog(const StorePath & drvPath, std::string_view log)
auto baseName = drvPath.to_string();
auto logPath = fmt("%s/%s/%s/%s.bz2", logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2));
auto logPath = fmt("%s/%s/%s/%s.bz2", config->logDir, drvsLogDir, baseName.substr(0, 2), baseName.substr(2));
if (pathExists(logPath)) return;
@ -1682,6 +1676,6 @@ std::optional<std::string> LocalStore::getVersion()
return nixVersion;
}
static RegisterStoreImplementation<LocalStore, LocalStoreConfig> regLocalStore;
static RegisterStoreImplementation<LocalStore::Config> regLocalStore;
} // namespace nix