lix/src/libstore/export-import.cc
2016-10-07 18:13:40 +02:00

132 lines
3.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "store-api.hh"
#include "archive.hh"
#include "worker-protocol.hh"
#include <algorithm>
namespace nix {
struct HashAndWriteSink : Sink
{
Sink & writeSink;
HashSink hashSink;
HashAndWriteSink(Sink & writeSink) : writeSink(writeSink), hashSink(htSHA256)
{
}
virtual void operator () (const unsigned char * data, size_t len)
{
writeSink(data, len);
hashSink(data, len);
}
Hash currentHash()
{
return hashSink.currentHash().first;
}
};
void Store::exportPaths(const Paths & paths, Sink & sink)
{
Paths sorted = topoSortPaths(PathSet(paths.begin(), paths.end()));
std::reverse(sorted.begin(), sorted.end());
std::string doneLabel("paths exported");
logger->incExpected(doneLabel, sorted.size());
for (auto & path : sorted) {
Activity act(*logger, lvlInfo, format("exporting path %s") % path);
sink << 1;
exportPath(path, sink);
logger->incProgress(doneLabel);
}
sink << 0;
}
void Store::exportPath(const Path & path, Sink & sink)
{
auto info = queryPathInfo(path);
HashAndWriteSink hashAndWriteSink(sink);
narFromPath(path, hashAndWriteSink);
/* Refuse to export paths that have changed. This prevents
filesystem corruption from spreading to other machines.
Don't complain if the stored hash is zero (unknown). */
Hash hash = hashAndWriteSink.currentHash();
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
throw Error(format("hash of path %1% has changed from %2% to %3%!") % path
% printHash(info->narHash) % printHash(hash));
hashAndWriteSink << exportMagic << path << info->references << info->deriver << 0;
}
struct TeeSource : Source
{
Source & readSource;
ref<std::string> data;
TeeSource(Source & readSource)
: readSource(readSource)
, data(make_ref<std::string>())
{
}
size_t read(unsigned char * data, size_t len)
{
size_t n = readSource.read(data, len);
this->data->append((char *) data, n);
return n;
}
};
struct NopSink : ParseSink
{
};
Paths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> accessor, bool dontCheckSigs)
{
Paths res;
while (true) {
unsigned long long n = readLongLong(source);
if (n == 0) break;
if (n != 1) throw Error("input doesn't look like something created by nix-store --export");
/* Extract the NAR from the source. */
TeeSource tee(source);
NopSink sink;
parseDump(sink, tee);
uint32_t magic = readInt(source);
if (magic != exportMagic)
throw Error("Nix archive cannot be imported; wrong format");
ValidPathInfo info;
info.path = readStorePath(*this, source);
Activity act(*logger, lvlInfo, format("importing path %s") % info.path);
info.references = readStorePaths<PathSet>(*this, source);
info.deriver = readString(source);
if (info.deriver != "") assertStorePath(info.deriver);
info.narHash = hashString(htSHA256, *tee.data);
info.narSize = tee.data->size();
// Ignore optional legacy signature.
if (readInt(source) == 1)
readString(source);
addToStore(info, *tee.data, false, dontCheckSigs);
if (accessor)
addPathToAccessor(ref<FSAccessor>(accessor), info.path, tee.data);
res.push_back(info.path);
}
return res;
}
}