1 #include "store-api.hh"
2 #include "archive.hh"
3 #include "worker-protocol.hh"
4
5 #include <algorithm>
6
7 namespace nix {
8
9 struct HashAndWriteSink : Sink
10 {
11 Sink & writeSink;
12 HashSink hashSink;
HashAndWriteSinknix::HashAndWriteSink13 HashAndWriteSink(Sink & writeSink) : writeSink(writeSink), hashSink(htSHA256)
14 {
15 }
operator ()nix::HashAndWriteSink16 virtual void operator () (const unsigned char * data, size_t len)
17 {
18 writeSink(data, len);
19 hashSink(data, len);
20 }
currentHashnix::HashAndWriteSink21 Hash currentHash()
22 {
23 return hashSink.currentHash().first;
24 }
25 };
26
exportPaths(const Paths & paths,Sink & sink)27 void Store::exportPaths(const Paths & paths, Sink & sink)
28 {
29 Paths sorted = topoSortPaths(PathSet(paths.begin(), paths.end()));
30 std::reverse(sorted.begin(), sorted.end());
31
32 std::string doneLabel("paths exported");
33 //logger->incExpected(doneLabel, sorted.size());
34
35 for (auto & path : sorted) {
36 //Activity act(*logger, lvlInfo, format("exporting path '%s'") % path);
37 sink << 1;
38 exportPath(path, sink);
39 //logger->incProgress(doneLabel);
40 }
41
42 sink << 0;
43 }
44
exportPath(const Path & path,Sink & sink)45 void Store::exportPath(const Path & path, Sink & sink)
46 {
47 auto info = queryPathInfo(path);
48
49 HashAndWriteSink hashAndWriteSink(sink);
50
51 narFromPath(path, hashAndWriteSink);
52
53 /* Refuse to export paths that have changed. This prevents
54 filesystem corruption from spreading to other machines.
55 Don't complain if the stored hash is zero (unknown). */
56 Hash hash = hashAndWriteSink.currentHash();
57 if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
58 throw Error(format("hash of path '%1%' has changed from '%2%' to '%3%'!") % path
59 % info->narHash.to_string() % hash.to_string());
60
61 hashAndWriteSink << exportMagic << path << info->references << info->deriver << 0;
62 }
63
importPaths(Source & source,std::shared_ptr<FSAccessor> accessor,CheckSigsFlag checkSigs)64 Paths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> accessor, CheckSigsFlag checkSigs)
65 {
66 Paths res;
67 while (true) {
68 auto n = readNum<uint64_t>(source);
69 if (n == 0) break;
70 if (n != 1) throw Error("input doesn't look like something created by 'nix-store --export'");
71
72 /* Extract the NAR from the source. */
73 TeeSink tee(source);
74 parseDump(tee, tee.source);
75
76 uint32_t magic = readInt(source);
77 if (magic != exportMagic)
78 throw Error("Nix archive cannot be imported; wrong format");
79
80 ValidPathInfo info;
81
82 info.path = readStorePath(*this, source);
83
84 //Activity act(*logger, lvlInfo, format("importing path '%s'") % info.path);
85
86 info.references = readStorePaths<PathSet>(*this, source);
87
88 info.deriver = readString(source);
89 if (info.deriver != "") assertStorePath(info.deriver);
90
91 info.narHash = hashString(htSHA256, *tee.source.data);
92 info.narSize = tee.source.data->size();
93
94 // Ignore optional legacy signature.
95 if (readInt(source) == 1)
96 readString(source);
97
98 addToStore(info, tee.source.data, NoRepair, checkSigs, accessor);
99
100 res.push_back(info.path);
101 }
102
103 return res;
104 }
105
106 }
107