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