gnu: guix: Update to 846403e.
[jackhill/guix/guix.git] / nix / libstore / store-api.cc
1 #include "store-api.hh"
2 #include "globals.hh"
3 #include "util.hh"
4
5 #include <climits>
6
7
8 namespace nix {
9
10
11 GCOptions::GCOptions()
12 {
13 action = gcDeleteDead;
14 ignoreLiveness = false;
15 maxFreed = ULLONG_MAX;
16 }
17
18
19 bool isInStore(const Path & path)
20 {
21 return isInDir(path, settings.nixStore);
22 }
23
24
25 bool isStorePath(const Path & path)
26 {
27 return isInStore(path)
28 && path.find('/', settings.nixStore.size() + 1) == Path::npos;
29 }
30
31
32 void assertStorePath(const Path & path)
33 {
34 if (!isStorePath(path))
35 throw Error(format("path `%1%' is not in the store") % path);
36 }
37
38
39 Path toStorePath(const Path & path)
40 {
41 if (!isInStore(path))
42 throw Error(format("path `%1%' is not in the store") % path);
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
51 string storePathToName(const Path & path)
52 {
53 assertStorePath(path);
54 return string(path, settings.nixStore.size() + 34);
55 }
56
57
58 void 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) == ".")
64 throw Error(format("invalid name: `%1%'") % name);
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
83 <store> = the location of the store, usually /gnu/store
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
148 Path 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
163 Path 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
171 Path 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
183 Path 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. */
202 string 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
229 string 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
240 void 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
250 Path readStorePath(Source & from)
251 {
252 Path path = readString(from);
253 assertStorePath(path);
254 return path;
255 }
256
257
258 template<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
265 template PathSet readStorePaths(Source & from);
266
267 }
268
269
270 #include "local-store.hh"
271 #include "serialise.hh"
272
273
274 namespace nix {
275
276
277 std::shared_ptr<StoreAPI> store;
278
279
280 std::shared_ptr<StoreAPI> openStore(bool reserveSpace)
281 {
282 return std::shared_ptr<StoreAPI>(new LocalStore(reserveSpace));
283 }
284
285
286 }