#include "nix/util/archive.hh" #include "nix/util/posix-source-accessor.hh" #include "nix/store/store-api.hh" #include "nix/store/local-fs-store.hh" #include "nix/store/globals.hh" #include "nix/util/compression.hh" #include "nix/store/derivations.hh" namespace nix { Path LocalFSStoreConfig::getDefaultStateDir() { return settings.nixStateDir; } Path LocalFSStoreConfig::getDefaultLogDir() { return settings.nixLogDir; } LocalFSStoreConfig::LocalFSStoreConfig(PathView rootDir, const Params & params) : StoreConfig(params) // Default `?root` from `rootDir` if non set // FIXME don't duplicate description once we don't have root setting , rootDir{ this, !rootDir.empty() && params.count("root") == 0 ? (std::optional{rootDir}) : std::nullopt, "root", "Directory prefixed to all other paths."} { } LocalFSStore::LocalFSStore(const Config & config) : Store{static_cast(*this)} , config{config} { } struct LocalStoreAccessor : PosixSourceAccessor { ref store; bool requireValidPath; LocalStoreAccessor(ref store, bool requireValidPath) : PosixSourceAccessor(std::filesystem::path{store->config.realStoreDir.get()}) , store(store) , requireValidPath(requireValidPath) { } void requireStoreObject(const CanonPath & path) { auto [storePath, rest] = store->toStorePath(store->storeDir + path.abs()); if (requireValidPath && !store->isValidPath(storePath)) throw InvalidPath("path '%1%' is not a valid store path", store->printStorePath(storePath)); } std::optional maybeLstat(const CanonPath & path) override { /* Also allow `path` to point to the entire store, which is needed for resolving symlinks. */ if (path.isRoot()) return Stat{.type = tDirectory}; requireStoreObject(path); return PosixSourceAccessor::maybeLstat(path); } DirEntries readDirectory(const CanonPath & path) override { requireStoreObject(path); return PosixSourceAccessor::readDirectory(path); } void readFile(const CanonPath & path, Sink & sink, std::function sizeCallback) override { requireStoreObject(path); return PosixSourceAccessor::readFile(path, sink, sizeCallback); } std::string readLink(const CanonPath & path) override { requireStoreObject(path); return PosixSourceAccessor::readLink(path); } }; ref LocalFSStore::getFSAccessor(bool requireValidPath) { return make_ref( ref(std::dynamic_pointer_cast(shared_from_this())), requireValidPath); } std::shared_ptr LocalFSStore::getFSAccessor(const StorePath & path, bool requireValidPath) { auto absPath = std::filesystem::path{config.realStoreDir.get()} / path.to_string(); if (requireValidPath) { /* Only return non-null if the store object is a fully-valid member of the store. */ if (!isValidPath(path)) return nullptr; } else { /* Return non-null as long as the some file system data exists, even if the store object is not fully registered. */ if (!pathExists(absPath)) return nullptr; } return std::make_shared(std::move(absPath)); } void LocalFSStore::narFromPath(const StorePath & path, Sink & sink) { if (!isValidPath(path)) throw Error("path '%s' is not valid", printStorePath(path)); dumpPath(getRealStoreDir() + std::string(printStorePath(path), storeDir.size()), sink); } const std::string LocalFSStore::drvsLogDir = "drvs"; std::optional LocalFSStore::getBuildLogExact(const StorePath & path) { auto baseName = path.to_string(); for (int j = 0; j < 2; j++) { Path logPath = j == 0 ? fmt("%s/%s/%s/%s", config.logDir.get(), drvsLogDir, baseName.substr(0, 2), baseName.substr(2)) : fmt("%s/%s/%s", config.logDir.get(), drvsLogDir, baseName); Path logBz2Path = logPath + ".bz2"; if (pathExists(logPath)) return readFile(logPath); else if (pathExists(logBz2Path)) { try { return decompress("bzip2", readFile(logBz2Path)); } catch (Error &) { } } } return std::nullopt; } } // namespace nix