1 : #include "store-api.hh"
2 : #include "globals.hh"
3 : #include "util.hh"
4 :
5 : #include <limits.h>
6 :
7 :
8 : /* Needed for some ancient environments. */
9 : #ifndef ULLONG_MAX
10 : #define ULLONG_MAX 18446744073709551615
11 : #endif
12 :
13 :
14 : namespace nix {
15 :
16 :
17 23 : GCOptions::GCOptions()
18 : {
19 23 : action = gcDeleteDead;
20 23 : ignoreLiveness = false;
21 23 : maxFreed = ULLONG_MAX;
22 23 : maxLinks = 0;
23 23 : useAtime = false;
24 23 : maxAtime = (time_t) -1;
25 23 : }
26 :
27 :
28 19372 : bool isInStore(const Path & path)
29 : {
30 : return path[0] == '/'
31 : && string(path, 0, nixStore.size()) == nixStore
32 : && path.size() >= nixStore.size() + 2
33 19372 : && path[nixStore.size()] == '/';
34 : }
35 :
36 :
37 17573 : bool isStorePath(const Path & path)
38 : {
39 : return isInStore(path)
40 17573 : && path.find('/', nixStore.size() + 1) == Path::npos;
41 : }
42 :
43 :
44 9381 : void assertStorePath(const Path & path)
45 : {
46 9381 : if (!isStorePath(path))
47 0 : throw Error(format("path `%1%' is not in the Nix store") % path);
48 9381 : }
49 :
50 :
51 543 : Path toStorePath(const Path & path)
52 : {
53 543 : if (!isInStore(path))
54 0 : throw Error(format("path `%1%' is not in the Nix store") % path);
55 543 : Path::size_type slash = path.find('/', nixStore.size() + 1);
56 543 : if (slash == Path::npos)
57 536 : return path;
58 : else
59 7 : return Path(path, 0, slash);
60 : }
61 :
62 :
63 133 : Path followLinksToStore(const Path & _path)
64 : {
65 133 : Path path = absPath(_path);
66 16 : while (!isInStore(path)) {
67 16 : if (!isLink(path)) break;
68 16 : string target = readLink(path);
69 16 : path = absPath(target, dirOf(path));
70 : }
71 133 : if (!isInStore(path))
72 0 : throw Error(format("path `%1%' is not in the Nix store") % path);
73 0 : return path;
74 : }
75 :
76 :
77 133 : Path followLinksToStorePath(const Path & path)
78 : {
79 133 : return toStorePath(followLinksToStore(path));
80 : }
81 :
82 :
83 771 : void checkStoreName(const string & name)
84 : {
85 771 : string validChars = "+-._?=";
86 : /* Disallow names starting with a dot for possible security
87 : reasons (e.g., "." and ".."). */
88 1542 : if (string(name, 0, 1) == ".")
89 0 : throw Error(format("illegal name: `%1%'") % name);
90 13214 : for (string::const_iterator i = name.begin(); i != name.end(); ++i)
91 12443 : if (!((*i >= 'A' && *i <= 'Z') ||
92 : (*i >= 'a' && *i <= 'z') ||
93 : (*i >= '0' && *i <= '9') ||
94 : validChars.find(*i) != string::npos))
95 : {
96 : throw Error(format("invalid character `%1%' in name `%2%'")
97 0 : % *i % name);
98 771 : }
99 771 : }
100 :
101 :
102 : Path makeStorePath(const string & type,
103 592 : const Hash & hash, const string & suffix)
104 : {
105 : /* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
106 : string s = type + ":sha256:" + printHash(hash) + ":"
107 592 : + nixStore + ":" + suffix;
108 :
109 592 : checkStoreName(suffix);
110 :
111 : return nixStore + "/"
112 : + printHash32(compressHash(hashString(htSHA256, s), 20))
113 592 : + "-" + suffix;
114 : }
115 :
116 :
117 : Path makeFixedOutputPath(bool recursive,
118 28 : string hashAlgo, Hash hash, string name)
119 : {
120 : /* !!! copy/paste from primops.cc */
121 : Hash h = hashString(htSHA256, "fixed:out:"
122 : + (recursive ? (string) "r:" : "") + hashAlgo + ":"
123 : + printHash(hash) + ":"
124 28 : + "");
125 56 : return makeStorePath("output:out", h, name);
126 : }
127 :
128 :
129 : std::pair<Path, Hash> computeStorePathForPath(const Path & srcPath,
130 165 : bool fixed, bool recursive, string hashAlgo, PathFilter & filter)
131 : {
132 165 : Hash h = hashPath(htSHA256, srcPath, filter);
133 :
134 165 : string baseName = baseNameOf(srcPath);
135 :
136 165 : Path dstPath;
137 :
138 165 : if (fixed) {
139 16 : HashType ht(parseHashType(hashAlgo));
140 16 : Hash h2 = recursive ? hashPath(ht, srcPath, filter) : hashFile(ht, srcPath);
141 16 : dstPath = makeFixedOutputPath(recursive, hashAlgo, h2, baseName);
142 : }
143 :
144 149 : else dstPath = makeStorePath("source", h, baseName);
145 :
146 165 : return std::pair<Path, Hash>(dstPath, h);
147 : }
148 :
149 :
150 : Path computeStorePathForText(const string & suffix, const string & s,
151 236 : const PathSet & references)
152 : {
153 236 : Hash hash = hashString(htSHA256, s);
154 : /* Stuff the references (if any) into the type. This is a bit
155 : hacky, but we can't put them in `s' since that would be
156 : ambiguous. */
157 236 : string type = "text";
158 812 : for (PathSet::const_iterator i = references.begin(); i != references.end(); ++i) {
159 340 : type += ":";
160 340 : type += *i;
161 : }
162 236 : return makeStorePath(type, hash, suffix);
163 : }
164 :
165 :
166 : /* Return a string accepted by decodeValidPathInfo() that
167 : registers the specified paths as valid. Note: it's the
168 : responsibility of the caller to provide a closure. */
169 : string makeValidityRegistration(const PathSet & paths,
170 1 : bool showDerivers, bool showHash)
171 : {
172 1 : string s = "";
173 :
174 4 : for (PathSet::iterator i = paths.begin(); i != paths.end(); ++i) {
175 2 : s += *i + "\n";
176 :
177 2 : if (showHash)
178 0 : s += printHash(store->queryPathHash(*i)) + "\n";
179 :
180 2 : Path deriver = showDerivers ? store->queryDeriver(*i) : "";
181 2 : s += deriver + "\n";
182 :
183 2 : PathSet references;
184 2 : store->queryReferences(*i, references);
185 :
186 2 : s += (format("%1%\n") % references.size()).str();
187 :
188 3 : for (PathSet::iterator j = references.begin();
189 : j != references.end(); ++j)
190 1 : s += *j + "\n";
191 : }
192 :
193 0 : return s;
194 : }
195 :
196 :
197 5004 : ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven)
198 : {
199 5004 : ValidPathInfo info;
200 5004 : getline(str, info.path);
201 5004 : if (str.eof()) { info.path = ""; return info; }
202 5001 : if (hashGiven) {
203 0 : string s;
204 0 : getline(str, s);
205 0 : info.hash = parseHash(htSHA256, s);
206 : }
207 5001 : getline(str, info.deriver);
208 5001 : string s; int n;
209 5001 : getline(str, s);
210 5001 : if (!string2Int(s, n)) throw Error("number expected");
211 20002 : while (n--) {
212 10000 : getline(str, s);
213 10000 : info.references.insert(s);
214 : }
215 5001 : if (!str || str.eof()) throw Error("missing input");
216 5001 : return info;
217 : }
218 :
219 :
220 257 : string showPaths(const PathSet & paths)
221 : {
222 257 : string s;
223 514 : for (PathSet::const_iterator i = paths.begin();
224 : i != paths.end(); ++i)
225 : {
226 257 : if (s.size() != 0) s += ", ";
227 257 : s += "`" + *i + "'";
228 : }
229 0 : return s;
230 : }
231 :
232 :
233 : }
234 :
235 :
236 : #include "local-store.hh"
237 : #include "serialise.hh"
238 : #include "remote-store.hh"
239 :
240 :
241 : namespace nix {
242 :
243 :
244 1151 : boost::shared_ptr<StoreAPI> store;
245 :
246 :
247 420 : boost::shared_ptr<StoreAPI> openStore()
248 : {
249 420 : if (getEnv("NIX_REMOTE") == "")
250 328 : return boost::shared_ptr<StoreAPI>(new LocalStore());
251 : else
252 92 : return boost::shared_ptr<StoreAPI>(new RemoteStore());
253 : }
254 :
255 0 :
256 1106 : }
|