WIP: bees service
[jackhill/guix/guix.git] / nix / libstore / store-api.cc
CommitLineData
36457566
LC
1#include "store-api.hh"
2#include "globals.hh"
3#include "util.hh"
4
5#include <climits>
6
7
8namespace nix {
9
10
11GCOptions::GCOptions()
12{
13 action = gcDeleteDead;
14 ignoreLiveness = false;
15 maxFreed = ULLONG_MAX;
16}
17
18
19bool isInStore(const Path & path)
20{
21 return isInDir(path, settings.nixStore);
22}
23
24
25bool isStorePath(const Path & path)
26{
27 return isInStore(path)
28 && path.find('/', settings.nixStore.size() + 1) == Path::npos;
29}
30
31
32void assertStorePath(const Path & path)
33{
34 if (!isStorePath(path))
8327e733 35 throw Error(format("path `%1%' is not in the store") % path);
36457566
LC
36}
37
38
39Path toStorePath(const Path & path)
40{
41 if (!isInStore(path))
8327e733 42 throw Error(format("path `%1%' is not in the store") % path);
36457566
LC
43 Path::size_type slash = path.find('/', settings.nixStore.size() + 1);
44 if (slash == Path::npos)
45 return path;
46 else
47 return Path(path, 0, slash);
48}
49
50
36457566
LC
51string storePathToName(const Path & path)
52{
53 assertStorePath(path);
54 return string(path, settings.nixStore.size() + 34);
55}
56
57
58void checkStoreName(const string & name)
59{
60 string validChars = "+-._?=";
61 /* Disallow names starting with a dot for possible security
62 reasons (e.g., "." and ".."). */
63 if (string(name, 0, 1) == ".")
76533c52 64 throw Error(format("invalid name: `%1%'") % name);
36457566
LC
65 foreach (string::const_iterator, i, name)
66 if (!((*i >= 'A' && *i <= 'Z') ||
67 (*i >= 'a' && *i <= 'z') ||
68 (*i >= '0' && *i <= '9') ||
69 validChars.find(*i) != string::npos))
70 {
71 throw Error(format("invalid character `%1%' in name `%2%'")
72 % *i % name);
73 }
74}
75
76
77/* Store paths have the following form:
78
79 <store>/<h>-<name>
80
81 where
82
8327e733 83 <store> = the location of the store, usually /gnu/store
36457566
LC
84
85 <name> = a human readable name for the path, typically obtained
86 from the name attribute of the derivation, or the name of the
87 source file from which the store path is created. For derivation
88 outputs other than the default "out" output, the string "-<id>"
89 is suffixed to <name>.
90
91 <h> = base-32 representation of the first 160 bits of a SHA-256
92 hash of <s>; the hash part of the store name
93
94 <s> = the string "<type>:sha256:<h2>:<store>:<name>";
95 note that it includes the location of the store as well as the
96 name to make sure that changes to either of those are reflected
97 in the hash (e.g. you won't get /nix/store/<h>-name1 and
98 /nix/store/<h>-name2 with equal hash parts).
99
100 <type> = one of:
101 "text:<r1>:<r2>:...<rN>"
102 for plain text files written to the store using
103 addTextToStore(); <r1> ... <rN> are the references of the
104 path.
105 "source"
106 for paths copied to the store using addToStore() when recursive
107 = true and hashAlgo = "sha256"
108 "output:<id>"
109 for either the outputs created by derivations, OR paths copied
110 to the store using addToStore() with recursive != true or
111 hashAlgo != "sha256" (in that case "source" is used; it's
112 silly, but it's done that way for compatibility). <id> is the
113 name of the output (usually, "out").
114
115 <h2> = base-16 representation of a SHA-256 hash of:
116 if <type> = "text:...":
117 the string written to the resulting store path
118 if <type> = "source":
119 the serialisation of the path from which this store path is
120 copied, as returned by hashPath()
121 if <type> = "output:out":
122 for non-fixed derivation outputs:
123 the derivation (see hashDerivationModulo() in
124 primops.cc)
125 for paths copied by addToStore() or produced by fixed-output
126 derivations:
127 the string "fixed:out:<rec><algo>:<hash>:", where
128 <rec> = "r:" for recursive (path) hashes, or "" or flat
129 (file) hashes
130 <algo> = "md5", "sha1" or "sha256"
131 <hash> = base-16 representation of the path or flat hash of
132 the contents of the path (or expected contents of the
133 path for fixed-output derivations)
134
135 It would have been nicer to handle fixed-output derivations under
136 "source", e.g. have something like "source:<rec><algo>", but we're
137 stuck with this for now...
138
139 The main reason for this way of computing names is to prevent name
140 collisions (for security). For instance, it shouldn't be feasible
141 to come up with a derivation whose output path collides with the
142 path for a copied source. The former would have a <s> starting with
143 "output:out:", while the latter would have a <2> starting with
144 "source:".
145*/
146
147
148Path makeStorePath(const string & type,
149 const Hash & hash, const string & name)
150{
151 /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
152 string s = type + ":sha256:" + printHash(hash) + ":"
153 + settings.nixStore + ":" + name;
154
155 checkStoreName(name);
156
157 return settings.nixStore + "/"
158 + printHash32(compressHash(hashString(htSHA256, s), 20))
159 + "-" + name;
160}
161
162
163Path makeOutputPath(const string & id,
164 const Hash & hash, const string & name)
165{
166 return makeStorePath("output:" + id, hash,
167 name + (id == "out" ? "" : "-" + id));
168}
169
170
171Path makeFixedOutputPath(bool recursive,
172 HashType hashAlgo, Hash hash, string name)
173{
174 return hashAlgo == htSHA256 && recursive
175 ? makeStorePath("source", hash, name)
176 : makeStorePath("output:out", hashString(htSHA256,
177 "fixed:out:" + (recursive ? (string) "r:" : "") +
178 printHashType(hashAlgo) + ":" + printHash(hash) + ":"),
179 name);
180}
181
182
36457566
LC
183Path computeStorePathForText(const string & name, const string & s,
184 const PathSet & references)
185{
186 Hash hash = hashString(htSHA256, s);
187 /* Stuff the references (if any) into the type. This is a bit
188 hacky, but we can't put them in `s' since that would be
189 ambiguous. */
190 string type = "text";
191 foreach (PathSet::const_iterator, i, references) {
192 type += ":";
193 type += *i;
194 }
195 return makeStorePath(type, hash, name);
196}
197
198
199/* Return a string accepted by decodeValidPathInfo() that
200 registers the specified paths as valid. Note: it's the
201 responsibility of the caller to provide a closure. */
202string StoreAPI::makeValidityRegistration(const PathSet & paths,
203 bool showDerivers, bool showHash)
204{
205 string s = "";
206
207 foreach (PathSet::iterator, i, paths) {
208 s += *i + "\n";
209
210 ValidPathInfo info = queryPathInfo(*i);
211
212 if (showHash) {
213 s += printHash(info.hash) + "\n";
214 s += (format("%1%\n") % info.narSize).str();
215 }
216
217 Path deriver = showDerivers ? info.deriver : "";
218 s += deriver + "\n";
219
220 s += (format("%1%\n") % info.references.size()).str();
221
222 foreach (PathSet::iterator, j, info.references)
223 s += *j + "\n";
224 }
225
226 return s;
227}
228
36457566
LC
229string showPaths(const PathSet & paths)
230{
231 string s;
232 foreach (PathSet::const_iterator, i, paths) {
233 if (s.size() != 0) s += ", ";
234 s += "`" + *i + "'";
235 }
236 return s;
237}
238
239
240void exportPaths(StoreAPI & store, const Paths & paths,
241 bool sign, Sink & sink)
242{
243 foreach (Paths::const_iterator, i, paths) {
244 writeInt(1, sink);
245 store.exportPath(*i, sign, sink);
246 }
247 writeInt(0, sink);
248}
249
20b97819
LC
250Path readStorePath(Source & from)
251{
252 Path path = readString(from);
253 assertStorePath(path);
254 return path;
255}
256
257
258template<class T> T readStorePaths(Source & from)
259{
260 T paths = readStrings<T>(from);
261 foreach (typename T::iterator, i, paths) assertStorePath(*i);
262 return paths;
263}
264
265template PathSet readStorePaths(Source & from);
36457566
LC
266
267}
268
269
270#include "local-store.hh"
271#include "serialise.hh"
36457566
LC
272
273
274namespace nix {
275
276
277std::shared_ptr<StoreAPI> store;
278
279
280std::shared_ptr<StoreAPI> openStore(bool reserveSpace)
281{
20b97819 282 return std::shared_ptr<StoreAPI>(new LocalStore(reserveSpace));
36457566
LC
283}
284
285
286}