diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index e3f22a9c9e..ed948cf4e5 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -625,29 +625,10 @@ Path LocalStore::_addToStore(bool fixed, bool recursive, Path srcPath(absPath(_srcPath)); debug(format("adding `%1%' to the store") % srcPath); - Hash h(htSHA256); - { - SwitchToOriginalUser sw; - h = hashPath(htSHA256, srcPath); - } - - string baseName = baseNameOf(srcPath); - - Path dstPath; - - if (fixed) { - - HashType ht(parseHashType(hashAlgo)); - Hash h2(ht); - { - SwitchToOriginalUser sw; - h2 = recursive ? hashPath(ht, srcPath) : hashFile(ht, srcPath); - } - - dstPath = makeFixedOutputPath(recursive, hashAlgo, h2, baseName); - } - - else dstPath = makeStorePath("source", h, baseName); + std::pair pr = + computeStorePathForPath(fixed, recursive, hashAlgo, srcPath); + Path & dstPath(pr.first); + Hash & h(pr.second); if (!readOnlyMode) addTempRoot(dstPath); @@ -698,9 +679,7 @@ Path LocalStore::addToStoreFixed(bool recursive, string hashAlgo, const Path & s Path LocalStore::addTextToStore(const string & suffix, const string & s, const PathSet & references) { - Hash hash = hashString(htSHA256, s); - - Path dstPath = makeStorePath("text", hash, suffix); + Path dstPath = computeStorePathForText(suffix, s); if (!readOnlyMode) addTempRoot(dstPath); diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index ce09ddada0..e04bb67139 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -3,6 +3,7 @@ #include "remote-store.hh" #include "worker-protocol.hh" #include "archive.hh" +#include "globals.hh" #include #include @@ -124,6 +125,12 @@ void RemoteStore::queryReferrers(const Path & path, Path RemoteStore::addToStore(const Path & srcPath) { + if (readOnlyMode) { + /* No sense in making a round trip, we can just compute the + path here. */ + return computeStorePathForPath(false, false, "", srcPath).first; + } + writeInt(wopAddToStore, to); writeString(baseNameOf(srcPath), to); dumpPath(srcPath, to); @@ -135,13 +142,29 @@ Path RemoteStore::addToStore(const Path & srcPath) Path RemoteStore::addToStoreFixed(bool recursive, string hashAlgo, const Path & srcPath) { - throw Error("not implemented 6"); + if (readOnlyMode) { + /* No sense in making a round trip, we can just compute the + path here. */ + return computeStorePathForPath(true, recursive, hashAlgo, srcPath).first; + } + + writeInt(wopAddToStoreFixed, to); + writeString(baseNameOf(srcPath), to); + writeInt(recursive ? 1 : 0, to); + writeString(hashAlgo, to); + dumpPath(srcPath, to); + Path path = readString(from); + return path; } Path RemoteStore::addTextToStore(const string & suffix, const string & s, const PathSet & references) { + if (readOnlyMode) { + return computeStorePathForText(suffix, s); + } + writeInt(wopAddTextToStore, to); writeString(suffix, to); writeString(s, to); diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index f1e7c35620..e00f01bfd4 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -92,7 +92,45 @@ Path makeFixedOutputPath(bool recursive, return makeStorePath("output:out", h, name); } - + +std::pair computeStorePathForPath(bool fixed, bool recursive, + string hashAlgo, const Path & srcPath) +{ + Hash h(htSHA256); + { + SwitchToOriginalUser sw; + h = hashPath(htSHA256, srcPath); + } + + string baseName = baseNameOf(srcPath); + + Path dstPath; + + if (fixed) { + + HashType ht(parseHashType(hashAlgo)); + Hash h2(ht); + { + SwitchToOriginalUser sw; + h2 = recursive ? hashPath(ht, srcPath) : hashFile(ht, srcPath); + } + + dstPath = makeFixedOutputPath(recursive, hashAlgo, h2, baseName); + } + + else dstPath = makeStorePath("source", h, baseName); + + return std::pair(dstPath, h); +} + + +Path computeStorePathForText(const string & suffix, const string & s) +{ + Hash hash = hashString(htSHA256, s); + return makeStorePath("text", hash, suffix); +} + + } diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 31e8152e86..cbf2f7ef29 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -54,12 +54,12 @@ public: /* Queries the set of outgoing FS references for a store path. The result is not cleared. */ - virtual void queryReferences(const Path & storePath, + virtual void queryReferences(const Path & path, PathSet & references) = 0; /* Queries the set of incoming FS references for a store path. The result is not cleared. */ - virtual void queryReferrers(const Path & storePath, + virtual void queryReferrers(const Path & path, PathSet & referrers) = 0; /* Copy the contents of a path to the store and register the @@ -88,7 +88,7 @@ public: /* Ensure that a path is valid. If it is not currently valid, it may be made valid by running a substitute (if defined for the path). */ - virtual void ensurePath(const Path & storePath) = 0; + virtual void ensurePath(const Path & path) = 0; }; @@ -115,6 +115,30 @@ Path makeFixedOutputPath(bool recursive, string 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 computeStorePathForPath(bool fixed, bool recursive, + string hashAlgo, const Path & srcPath); + +/* 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 & suffix, const string & s); + + /* For now, there is a single global store API object, but we'll purify that in the future. */ extern boost::shared_ptr store; diff --git a/src/nix-worker/main.cc b/src/nix-worker/main.cc index 8ac69561f0..5d57dd6b62 100644 --- a/src/nix-worker/main.cc +++ b/src/nix-worker/main.cc @@ -37,11 +37,15 @@ void processConnection(Source & from, Sink & to) debug("greeting exchanged"); bool quit = false; + + unsigned int opCount = 0; do { WorkerOp op = (WorkerOp) readInt(from); + opCount++; + switch (op) { case wopQuit: @@ -75,13 +79,26 @@ void processConnection(Source & from, Sink & to) break; } - case wopAddToStore: { + case wopAddToStore: + case wopAddToStoreFixed: { /* !!! uberquick hack */ string baseName = readString(from); + bool recursive = false; + string hashAlgo; + if (op == wopAddToStoreFixed) { + recursive = readInt(from) == 1; + hashAlgo = readString(from); + } + Path tmp = createTempDir(); Path tmp2 = tmp + "/" + baseName; restorePath(tmp2, from); - writeString(store->addToStore(tmp2), to); + + if (op == wopAddToStoreFixed) + writeString(store->addToStoreFixed(recursive, hashAlgo, tmp2), to); + else + writeString(store->addToStore(tmp2), to); + deletePath(tmp); break; } @@ -113,6 +130,8 @@ void processConnection(Source & from, Sink & to) } } while (!quit); + + printMsg(lvlError, format("%1% worker operations") % opCount); }