From 774b92439863cf3a4db85ccef39448c007de5d64 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Tue, 18 Feb 2025 23:03:30 +0100 Subject: [PATCH] Add a storeFS accessor for paths resulting from IFD Hopefully fixes #11503. --- src/libexpr/eval.cc | 18 +++++++----------- src/libexpr/eval.hh | 28 +++++++++++++++++----------- src/libexpr/paths.cc | 7 +++++++ src/libexpr/primops.cc | 17 ++++------------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 29daabe49..efffc69f1 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -255,6 +255,12 @@ EvalState::EvalState( throw RestrictedPathError("access to absolute path '%1%' is forbidden %2%", path, modeInformation); })) : getFSSourceAccessor()) + , storeFS( + makeMountedSourceAccessor( + { + {CanonPath::root, makeEmptySourceAccessor()}, + {CanonPath(store->storeDir), makeFSSourceAccessor(dirOf(store->toRealPath(StorePath::dummy)))} + })) , corepkgsFS(make_ref()) , internalFS(make_ref()) , derivationInternal{corepkgsFS->addFile( @@ -422,16 +428,6 @@ void EvalState::checkURI(const std::string & uri) } -Path EvalState::toRealPath(const Path & path, const NixStringContext & context) -{ - // FIXME: check whether 'path' is in 'context'. - return - !context.empty() && store->isInStore(path) - ? store->toRealPath(path) - : path; -} - - Value * EvalState::addConstant(const std::string & name, Value & v, Constant info) { Value * v2 = allocValue(); @@ -2432,7 +2428,7 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext auto path = coerceToString(pos, v, context, errorCtx, false, false, true).toOwned(); if (path == "" || path[0] != '/') error("string '%1%' doesn't represent an absolute path", path).withTrace(pos, errorCtx).debugThrow(); - return rootPath(CanonPath(path)); + return stringWithContextToPath(path, context); } diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh index 767578343..6a601a587 100644 --- a/src/libexpr/eval.hh +++ b/src/libexpr/eval.hh @@ -250,6 +250,11 @@ public: */ const ref rootFS; + /** + * The accessor for the store. + */ + const ref storeFS; + /** * The in-memory filesystem for paths. */ @@ -389,6 +394,18 @@ public: */ SourcePath rootPath(PathView path); + /** + * Convert `s` to a path. If `context` is not empty, the resulting + * path will use the `storeFS` accessor; otherwise it will use + * `rootFS`. When using a chroot store, this allows us to + * distinguish between store paths resulting from + * import-from-derivation and sources stored in the actual + * /nix/store. + */ + SourcePath stringWithContextToPath( + std::string_view s, + const NixStringContext & context); + /** * Allow access to a path. */ @@ -412,17 +429,6 @@ public: void checkURI(const std::string & uri); - /** - * When using a diverted store and 'path' is in the Nix store, map - * 'path' to the diverted location (e.g. /nix/store/foo is mapped - * to /home/alice/my-nix/nix/store/foo). However, this is only - * done if the context is not empty, since otherwise we're - * probably trying to read from the actual /nix/store. This is - * intended to distinguish between import-from-derivation and - * sources stored in the actual /nix/store. - */ - Path toRealPath(const Path & path, const NixStringContext & context); - /** * Parse a Nix expression from the specified file. */ diff --git a/src/libexpr/paths.cc b/src/libexpr/paths.cc index 50d0d9895..ea28b5a7e 100644 --- a/src/libexpr/paths.cc +++ b/src/libexpr/paths.cc @@ -1,4 +1,5 @@ #include "eval.hh" +#include "store-api.hh" namespace nix { @@ -12,4 +13,10 @@ SourcePath EvalState::rootPath(PathView path) return {rootFS, CanonPath(absPath(path))}; } +SourcePath EvalState::stringWithContextToPath(std::string_view s, const NixStringContext & context) +{ + auto path = CanonPath(s); + return !context.empty() ? SourcePath{storeFS, std::move(path)} : rootPath(std::move(path)); +} + } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 51d2991e7..88d09e563 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -143,10 +143,9 @@ static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, st auto path = state.coerceToPath(noPos, v, context, "while realising the context of a path"); try { - if (!context.empty() && path.accessor == state.rootFS) { + if (!context.empty() && path.accessor == state.storeFS) { auto rewrites = state.realiseContext(context); - auto realPath = state.toRealPath(rewriteStrings(path.path.abs(), rewrites), context); - path = {path.accessor, CanonPath(realPath)}; + path = {path.accessor, CanonPath(rewriteStrings(path.path.abs(), rewrites))}; } return resolveSymlinks ? path.resolveSymlinks(*resolveSymlinks) : path; } catch (Error & e) { @@ -2481,19 +2480,11 @@ static void addPath( try { StorePathSet refs; - if (path.accessor == state.rootFS && state.store->isInStore(path.path.abs())) { + if (path.accessor == state.storeFS && state.store->isInStore(path.path.abs())) { // FIXME: handle CA derivation outputs (where path needs to // be rewritten to the actual output). auto rewrites = state.realiseContext(context); - path = {state.rootFS, CanonPath(state.toRealPath(rewriteStrings(path.path.abs(), rewrites), context))}; - - try { - auto [storePath, subPath] = state.store->toStorePath(path.path.abs()); - // FIXME: we should scanForReferences on the path before adding it - refs = state.store->queryPathInfo(storePath)->references; - path = {state.rootFS, CanonPath(state.store->toRealPath(storePath) + subPath)}; - } catch (Error &) { // FIXME: should be InvalidPathError - } + path = {path.accessor, CanonPath(rewriteStrings(path.path.abs(), rewrites))}; } std::unique_ptr filter;