gnu: guix: Update to 846403e.
[jackhill/guix/guix.git] / nix / libstore / gc.cc
1 #include "globals.hh"
2 #include "misc.hh"
3 #include "local-store.hh"
4
5 #include <functional>
6 #include <queue>
7 #include <algorithm>
8
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <unistd.h>
14 #include <climits>
15
16
17 namespace nix {
18
19
20 static string gcLockName = "gc.lock";
21 static string tempRootsDir = "temproots";
22 static string gcRootsDir = "gcroots";
23
24
25 /* Acquire the global GC lock. This is used to prevent new build
26 processes from starting after the temporary root files have been
27 read. To be precise: when they try to create a new temporary root
28 file, they will block until the garbage collector has finished /
29 yielded the GC lock. */
30 int LocalStore::openGCLock(LockType lockType)
31 {
32 Path fnGCLock = (format("%1%/%2%")
33 % settings.nixStateDir % gcLockName).str();
34
35 debug(format("acquiring global GC lock `%1%'") % fnGCLock);
36
37 AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT, 0600);
38 if (fdGCLock == -1)
39 throw SysError(format("opening global GC lock `%1%'") % fnGCLock);
40 closeOnExec(fdGCLock);
41
42 if (!lockFile(fdGCLock, lockType, false)) {
43 printMsg(lvlError, format("waiting for the big garbage collector lock..."));
44 lockFile(fdGCLock, lockType, true);
45 }
46
47 /* !!! Restrict read permission on the GC root. Otherwise any
48 process that can open the file for reading can DoS the
49 collector. */
50
51 return fdGCLock.borrow();
52 }
53
54
55 static void makeSymlink(const Path & link, const Path & target)
56 {
57 /* Create directories up to `gcRoot'. */
58 createDirs(dirOf(link));
59
60 /* Create the new symlink. */
61 Path tempLink = (format("%1%.tmp-%2%-%3%")
62 % link % getpid() % rand()).str();
63 createSymlink(target, tempLink);
64
65 /* Atomically replace the old one. */
66 if (rename(tempLink.c_str(), link.c_str()) == -1)
67 throw SysError(format("cannot rename `%1%' to `%2%'")
68 % tempLink % link);
69 }
70
71
72 void LocalStore::syncWithGC()
73 {
74 AutoCloseFD fdGCLock = openGCLock(ltRead);
75 }
76
77
78 void LocalStore::addIndirectRoot(const Path & path)
79 {
80 string hash = printHash32(hashString(htSHA1, path));
81 Path realRoot = canonPath((format("%1%/%2%/auto/%3%")
82 % settings.nixStateDir % gcRootsDir % hash).str());
83 makeSymlink(realRoot, path);
84 }
85
86
87 Path addPermRoot(StoreAPI & store, const Path & _storePath,
88 const Path & _gcRoot, bool indirect, bool allowOutsideRootsDir)
89 {
90 Path storePath(canonPath(_storePath));
91 Path gcRoot(canonPath(_gcRoot));
92 assertStorePath(storePath);
93
94 if (isInStore(gcRoot))
95 throw Error(format(
96 "creating a garbage collector root (%1%) in the store is forbidden "
97 "(are you running nix-build inside the store?)") % gcRoot);
98
99 if (indirect) {
100 /* Don't clobber the link if it already exists and doesn't
101 point to the store. */
102 if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
103 throw Error(format("cannot create symlink `%1%'; already exists") % gcRoot);
104 makeSymlink(gcRoot, storePath);
105 store.addIndirectRoot(gcRoot);
106 }
107
108 else {
109 if (!allowOutsideRootsDir) {
110 Path rootsDir = canonPath((format("%1%/%2%") % settings.nixStateDir % gcRootsDir).str());
111
112 if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
113 throw Error(format(
114 "path `%1%' is not a valid garbage collector root; "
115 "it's not in the directory `%2%'")
116 % gcRoot % rootsDir);
117 }
118
119 if (baseNameOf(gcRoot) == baseNameOf(storePath))
120 writeFile(gcRoot, "");
121 else
122 makeSymlink(gcRoot, storePath);
123 }
124
125 /* Check that the root can be found by the garbage collector.
126 !!! This can be very slow on machines that have many roots.
127 Instead of reading all the roots, it would be more efficient to
128 check if the root is in a directory in or linked from the
129 gcroots directory. */
130 if (settings.checkRootReachability) {
131 Roots roots = store.findRoots();
132 if (roots.find(gcRoot) == roots.end())
133 printMsg(lvlError,
134 format(
135 "warning: `%1%' is not in a directory where the garbage collector looks for roots; "
136 "therefore, `%2%' might be removed by the garbage collector")
137 % gcRoot % storePath);
138 }
139
140 /* Grab the global GC root, causing us to block while a GC is in
141 progress. This prevents the set of permanent roots from
142 increasing while a GC is in progress. */
143 store.syncWithGC();
144
145 return gcRoot;
146 }
147
148
149 void LocalStore::addTempRoot(const Path & path)
150 {
151 /* Create the temporary roots file for this process. */
152 if (fdTempRoots == -1) {
153
154 while (1) {
155 Path dir = (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str();
156 createDirs(dir);
157
158 fnTempRoots = (format("%1%/%2%")
159 % dir % getpid()).str();
160
161 AutoCloseFD fdGCLock = openGCLock(ltRead);
162
163 if (pathExists(fnTempRoots))
164 /* It *must* be stale, since there can be no two
165 processes with the same pid. */
166 unlink(fnTempRoots.c_str());
167
168 fdTempRoots = openLockFile(fnTempRoots, true);
169
170 fdGCLock.close();
171
172 debug(format("acquiring read lock on `%1%'") % fnTempRoots);
173 lockFile(fdTempRoots, ltRead, true);
174
175 /* Check whether the garbage collector didn't get in our
176 way. */
177 struct stat st;
178 if (fstat(fdTempRoots, &st) == -1)
179 throw SysError(format("statting `%1%'") % fnTempRoots);
180 if (st.st_size == 0) break;
181
182 /* The garbage collector deleted this file before we could
183 get a lock. (It won't delete the file after we get a
184 lock.) Try again. */
185 }
186
187 }
188
189 /* Upgrade the lock to a write lock. This will cause us to block
190 if the garbage collector is holding our lock. */
191 debug(format("acquiring write lock on `%1%'") % fnTempRoots);
192 lockFile(fdTempRoots, ltWrite, true);
193
194 string s = path + '\0';
195 writeFull(fdTempRoots, s);
196
197 /* Downgrade to a read lock. */
198 debug(format("downgrading to read lock on `%1%'") % fnTempRoots);
199 lockFile(fdTempRoots, ltRead, true);
200 }
201
202
203 typedef std::shared_ptr<AutoCloseFD> FDPtr;
204 typedef list<FDPtr> FDs;
205
206
207 static void readTempRoots(PathSet & tempRoots, FDs & fds)
208 {
209 /* Read the `temproots' directory for per-process temporary root
210 files. */
211 DirEntries tempRootFiles = readDirectory(
212 (format("%1%/%2%") % settings.nixStateDir % tempRootsDir).str());
213
214 for (auto & i : tempRootFiles) {
215 Path path = (format("%1%/%2%/%3%") % settings.nixStateDir % tempRootsDir % i.name).str();
216
217 debug(format("reading temporary root file `%1%'") % path);
218 FDPtr fd(new AutoCloseFD(open(path.c_str(), O_RDWR, 0666)));
219 if (*fd == -1) {
220 /* It's okay if the file has disappeared. */
221 if (errno == ENOENT) continue;
222 throw SysError(format("opening temporary roots file `%1%'") % path);
223 }
224
225 /* This should work, but doesn't, for some reason. */
226 //FDPtr fd(new AutoCloseFD(openLockFile(path, false)));
227 //if (*fd == -1) continue;
228
229 /* Try to acquire a write lock without blocking. This can
230 only succeed if the owning process has died. In that case
231 we don't care about its temporary roots. */
232 if (lockFile(*fd, ltWrite, false)) {
233 printMsg(lvlError, format("removing stale temporary roots file `%1%'") % path);
234 unlink(path.c_str());
235 writeFull(*fd, "d");
236 continue;
237 }
238
239 /* Acquire a read lock. This will prevent the owning process
240 from upgrading to a write lock, therefore it will block in
241 addTempRoot(). */
242 debug(format("waiting for read lock on `%1%'") % path);
243 lockFile(*fd, ltRead, true);
244
245 /* Read the entire file. */
246 string contents = readFile(*fd);
247
248 /* Extract the roots. */
249 string::size_type pos = 0, end;
250
251 while ((end = contents.find((char) 0, pos)) != string::npos) {
252 Path root(contents, pos, end - pos);
253 debug(format("got temporary root `%1%'") % root);
254 assertStorePath(root);
255 tempRoots.insert(root);
256 pos = end + 1;
257 }
258
259 fds.push_back(fd); /* keep open */
260 }
261 }
262
263
264 static void foundRoot(StoreAPI & store,
265 const Path & path, const Path & target, Roots & roots)
266 {
267 Path storePath = toStorePath(target);
268 if (store.isValidPath(storePath))
269 roots[path] = storePath;
270 else
271 printMsg(lvlInfo, format("skipping invalid root from `%1%' to `%2%'") % path % storePath);
272 }
273
274
275 static void findRoots(StoreAPI & store, const Path & path, unsigned char type, Roots & roots)
276 {
277 try {
278
279 if (type == DT_UNKNOWN)
280 type = getFileType(path);
281
282 if (type == DT_DIR) {
283 for (auto & i : readDirectory(path))
284 findRoots(store, path + "/" + i.name, i.type, roots);
285 }
286
287 else if (type == DT_LNK) {
288 Path target = readLink(path);
289 if (isInStore(target))
290 foundRoot(store, path, target, roots);
291
292 /* Handle indirect roots. */
293 else {
294 target = absPath(target, dirOf(path));
295 if (!pathExists(target)) {
296 if (isInDir(path, settings.nixStateDir + "/" + gcRootsDir + "/auto")) {
297 printMsg(lvlInfo, format("removing stale link from `%1%' to `%2%'") % path % target);
298 unlink(path.c_str());
299 }
300 } else {
301 struct stat st2 = lstat(target);
302 if (!S_ISLNK(st2.st_mode)) return;
303 Path target2 = readLink(target);
304 if (isInStore(target2)) foundRoot(store, target, target2, roots);
305 }
306 }
307 }
308
309 else if (type == DT_REG) {
310 Path storePath = settings.nixStore + "/" + baseNameOf(path);
311 if (store.isValidPath(storePath))
312 roots[path] = storePath;
313 }
314
315 }
316
317 catch (SysError & e) {
318 /* We only ignore permanent failures. */
319 if (e.errNo == EACCES || e.errNo == ENOENT || e.errNo == ENOTDIR)
320 printMsg(lvlInfo, format("cannot read potential root `%1%'") % path);
321 else
322 throw;
323 }
324 }
325
326
327 Roots LocalStore::findRoots()
328 {
329 Roots roots;
330
331 /* Process direct roots in {gcroots,manifests,profiles}. */
332 nix::findRoots(*this, settings.nixStateDir + "/" + gcRootsDir, DT_UNKNOWN, roots);
333 if (pathExists(settings.nixStateDir + "/manifests"))
334 nix::findRoots(*this, settings.nixStateDir + "/manifests", DT_UNKNOWN, roots);
335 nix::findRoots(*this, settings.nixStateDir + "/profiles", DT_UNKNOWN, roots);
336
337 return roots;
338 }
339
340
341 static void addAdditionalRoots(StoreAPI & store, PathSet & roots)
342 {
343 debug(format("executing `%1% gc --list-busy' to find additional roots")
344 % settings.guixProgram);
345
346 const Strings args = { "gc", "--list-busy" };
347 string result = runProgram(settings.guixProgram, false, args);
348
349 StringSet paths = tokenizeString<StringSet>(result, "\n");
350
351 foreach (StringSet::iterator, i, paths) {
352 if (isInStore(*i)) {
353 Path path = toStorePath(*i);
354 if (roots.find(path) == roots.end() && store.isValidPath(path)) {
355 debug(format("got additional root `%1%'") % path);
356 roots.insert(path);
357 }
358 }
359 }
360 }
361
362
363 struct GCLimitReached { };
364
365
366 struct LocalStore::GCState
367 {
368 GCOptions options;
369 GCResults & results;
370 PathSet roots;
371 PathSet tempRoots;
372 PathSet dead;
373 PathSet alive;
374 bool gcKeepOutputs;
375 bool gcKeepDerivations;
376 unsigned long long bytesInvalidated;
377 bool moveToTrash = true;
378 Path trashDir;
379 bool shouldDelete;
380 GCState(GCResults & results_) : results(results_), bytesInvalidated(0) { }
381 };
382
383
384 bool LocalStore::isActiveTempFile(const GCState & state,
385 const Path & path, const string & suffix)
386 {
387 return hasSuffix(path, suffix)
388 && state.tempRoots.find(string(path, 0, path.size() - suffix.size())) != state.tempRoots.end();
389 }
390
391
392 void LocalStore::deleteGarbage(GCState & state, const Path & path)
393 {
394 unsigned long long bytesFreed;
395
396 /* When deduplication is on, store items always have at least two links:
397 the one at PATH, and one in /gnu/store/.links. In that case, increase
398 bytesFreed when PATH has two or fewer links. */
399 size_t linkThreshold =
400 (settings.autoOptimiseStore && isStorePath(path)) ? 2 : 1;
401
402 deletePath(path, bytesFreed, linkThreshold);
403 state.results.bytesFreed += bytesFreed;
404 }
405
406
407 void LocalStore::deletePathRecursive(GCState & state, const Path & path)
408 {
409 checkInterrupt();
410
411 unsigned long long size = 0;
412
413 if (isValidPath(path)) {
414 PathSet referrers;
415 queryReferrers(path, referrers);
416 foreach (PathSet::iterator, i, referrers)
417 if (*i != path) deletePathRecursive(state, *i);
418 size = queryPathInfo(path).narSize;
419 invalidatePathChecked(path);
420 }
421
422 struct stat st;
423 if (lstat(path.c_str(), &st)) {
424 if (errno == ENOENT) return;
425 throw SysError(format("getting status of %1%") % path);
426 }
427
428 if (state.options.maxFreed != ULLONG_MAX) {
429 auto freed = state.results.bytesFreed + state.bytesInvalidated;
430 double fraction = ((double) freed) / (double) state.options.maxFreed;
431 unsigned int percentage = (fraction > 1. ? 1. : fraction) * 100.;
432 printMsg(lvlInfo, format("[%1%%%] deleting '%2%'") % percentage % path);
433 } else {
434 auto freed = state.results.bytesFreed + state.bytesInvalidated;
435 freed /= 1024ULL * 1024ULL;
436 printMsg(lvlInfo, format("[%1% MiB] deleting '%2%'") % freed % path);
437 }
438
439 state.results.paths.insert(path);
440
441 /* If the path is not a regular file or symlink, move it to the
442 trash directory. The move is to ensure that later (when we're
443 not holding the global GC lock) we can delete the path without
444 being afraid that the path has become alive again. Otherwise
445 delete it right away. */
446 if (state.moveToTrash && S_ISDIR(st.st_mode)) {
447 // Estimate the amount freed using the narSize field. FIXME:
448 // if the path was not valid, need to determine the actual
449 // size.
450 try {
451 if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
452 throw SysError(format("making `%1%' writable") % path);
453 Path tmp = state.trashDir + "/" + baseNameOf(path);
454 if (rename(path.c_str(), tmp.c_str()))
455 throw SysError(format("unable to rename `%1%' to `%2%'") % path % tmp);
456 state.bytesInvalidated += size;
457 } catch (SysError & e) {
458 /* In a Docker container, rename(2) returns EXDEV when the source
459 and destination are not both on the "top layer". See:
460 https://bugs.gnu.org/41607 */
461 if (e.errNo == ENOSPC || e.errNo == EXDEV) {
462 printMsg(lvlInfo, format("note: can't create move `%1%': %2%") % path % e.msg());
463 deleteGarbage(state, path);
464 }
465 }
466 } else
467 deleteGarbage(state, path);
468
469 if (state.results.bytesFreed + state.bytesInvalidated > state.options.maxFreed) {
470 printMsg(lvlInfo, format("deleted or invalidated more than %1% bytes; stopping") % state.options.maxFreed);
471 throw GCLimitReached();
472 }
473 }
474
475
476 bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & path)
477 {
478 if (visited.find(path) != visited.end()) return false;
479
480 if (state.alive.find(path) != state.alive.end()) {
481 return true;
482 }
483
484 if (state.dead.find(path) != state.dead.end()) {
485 return false;
486 }
487
488 if (state.roots.find(path) != state.roots.end()) {
489 printMsg(lvlDebug, format("cannot delete `%1%' because it's a root") % path);
490 state.alive.insert(path);
491 return true;
492 }
493
494 visited.insert(path);
495
496 if (!isValidPath(path)) return false;
497
498 PathSet incoming;
499
500 /* Don't delete this path if any of its referrers are alive. */
501 queryReferrers(path, incoming);
502
503 /* If gc-keep-derivations is set and this is a derivation, then
504 don't delete the derivation if any of the outputs are alive. */
505 if (state.gcKeepDerivations && isDerivation(path)) {
506 PathSet outputs = queryDerivationOutputs(path);
507 foreach (PathSet::iterator, i, outputs)
508 if (isValidPath(*i) && queryDeriver(*i) == path)
509 incoming.insert(*i);
510 }
511
512 /* If gc-keep-outputs is set, then don't delete this path if there
513 are derivers of this path that are not garbage. */
514 if (state.gcKeepOutputs) {
515 PathSet derivers = queryValidDerivers(path);
516 foreach (PathSet::iterator, i, derivers)
517 incoming.insert(*i);
518 }
519
520 foreach (PathSet::iterator, i, incoming)
521 if (*i != path)
522 if (canReachRoot(state, visited, *i)) {
523 state.alive.insert(path);
524 return true;
525 }
526
527 return false;
528 }
529
530
531 void LocalStore::tryToDelete(GCState & state, const Path & path)
532 {
533 checkInterrupt();
534
535 if (path == linksDir || path == state.trashDir) return;
536
537 startNest(nest, lvlDebug, format("considering whether to delete `%1%'") % path);
538
539 if (!isValidPath(path)) {
540 /* A lock file belonging to a path that we're building right
541 now isn't garbage. */
542 if (isActiveTempFile(state, path, ".lock")) return;
543
544 /* Don't delete .chroot directories for derivations that are
545 currently being built. */
546 if (isActiveTempFile(state, path, ".chroot")) return;
547 }
548
549 PathSet visited;
550
551 if (canReachRoot(state, visited, path)) {
552 printMsg(lvlDebug, format("cannot delete `%1%' because it's still reachable") % path);
553 } else {
554 /* No path we visited was a root, so everything is garbage.
555 But we only delete ‘path’ and its referrers here so that
556 ‘nix-store --delete’ doesn't have the unexpected effect of
557 recursing into derivations and outputs. */
558 state.dead.insert(visited.begin(), visited.end());
559 if (state.shouldDelete)
560 deletePathRecursive(state, path);
561 }
562 }
563
564
565 /* Unlink all files in /nix/store/.links that have a link count of 1,
566 which indicates that there are no other links and so they can be
567 safely deleted. FIXME: race condition with optimisePath(): we
568 might see a link count of 1 just before optimisePath() increases
569 the link count. */
570 void LocalStore::removeUnusedLinks(const GCState & state)
571 {
572 AutoCloseDir dir = opendir(linksDir.c_str());
573 if (!dir) throw SysError(format("opening directory `%1%'") % linksDir);
574
575 long long actualSize = 0, unsharedSize = 0;
576
577 struct dirent * dirent;
578 while (errno = 0, dirent = readdir(dir)) {
579 checkInterrupt();
580 string name = dirent->d_name;
581 if (name == "." || name == "..") continue;
582 Path path = linksDir + "/" + name;
583
584 #ifdef HAVE_STATX
585 # define st_size stx_size
586 # define st_nlink stx_nlink
587 static int statx_flags = AT_SYMLINK_NOFOLLOW | AT_STATX_DONT_SYNC;
588 struct statx st;
589
590 if (statx(AT_FDCWD, path.c_str(), statx_flags,
591 STATX_SIZE | STATX_NLINK, &st) == -1) {
592 if (errno == EINVAL) {
593 /* Old 3.10 kernels (CentOS 7) don't support
594 AT_STATX_DONT_SYNC, so try again without it. */
595 statx_flags &= ~AT_STATX_DONT_SYNC;
596 if (statx(AT_FDCWD, path.c_str(), statx_flags,
597 STATX_SIZE | STATX_NLINK, &st) == -1)
598 throw SysError(format("statting `%1%'") % path);
599 } else {
600 throw SysError(format("statting `%1%'") % path);
601 }
602 }
603 #else
604 struct stat st;
605 if (lstat(path.c_str(), &st) == -1)
606 throw SysError(format("statting `%1%'") % path);
607 #endif
608
609 if (st.st_nlink != 1) {
610 actualSize += st.st_size;
611 unsharedSize += (st.st_nlink - 1) * st.st_size;
612 continue;
613 }
614
615 printMsg(lvlTalkative, format("deleting unused link `%1%'") % path);
616
617 if (unlink(path.c_str()) == -1)
618 throw SysError(format("deleting `%1%'") % path);
619
620 state.results.bytesFreed += st.st_size;
621 #undef st_size
622 #undef st_nlink
623 }
624
625 struct stat st;
626 if (stat(linksDir.c_str(), &st) == -1)
627 throw SysError(format("statting `%1%'") % linksDir);
628 long long overhead = st.st_size;
629
630 printMsg(lvlInfo, format("note: currently hard linking saves %.2f MiB")
631 % ((unsharedSize - actualSize - overhead) / (1024.0 * 1024.0)));
632 }
633
634
635 void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
636 {
637 GCState state(results);
638 state.options = options;
639 state.trashDir = settings.nixStore + "/trash";
640 state.gcKeepOutputs = settings.gcKeepOutputs;
641 state.gcKeepDerivations = settings.gcKeepDerivations;
642
643 /* Using `--ignore-liveness' with `--delete' can have unintended
644 consequences if `gc-keep-outputs' or `gc-keep-derivations' are
645 true (the garbage collector will recurse into deleting the
646 outputs or derivers, respectively). So disable them. */
647 if (options.action == GCOptions::gcDeleteSpecific && options.ignoreLiveness) {
648 state.gcKeepOutputs = false;
649 state.gcKeepDerivations = false;
650 }
651
652 state.shouldDelete = options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific;
653
654 /* Acquire the global GC root. This prevents
655 a) New roots from being added.
656 b) Processes from creating new temporary root files. */
657 AutoCloseFD fdGCLock = openGCLock(ltWrite);
658
659 /* Find the roots. Since we've grabbed the GC lock, the set of
660 permanent roots cannot increase now. */
661 printMsg(lvlError, format("finding garbage collector roots..."));
662 Roots rootMap = options.ignoreLiveness ? Roots() : findRoots();
663
664 foreach (Roots::iterator, i, rootMap) state.roots.insert(i->second);
665
666 /* Add additional roots returned by 'guix gc --list-busy'. This is
667 typically used to add running programs to the set of roots (to prevent
668 them from being garbage collected). */
669 if (!options.ignoreLiveness)
670 addAdditionalRoots(*this, state.roots);
671
672 /* Read the temporary roots. This acquires read locks on all
673 per-process temporary root files. So after this point no paths
674 can be added to the set of temporary roots. */
675 FDs fds;
676 readTempRoots(state.tempRoots, fds);
677 state.roots.insert(state.tempRoots.begin(), state.tempRoots.end());
678
679 /* After this point the set of roots or temporary roots cannot
680 increase, since we hold locks on everything. So everything
681 that is not reachable from `roots' is garbage. */
682
683 if (state.shouldDelete) {
684 if (pathExists(state.trashDir)) deleteGarbage(state, state.trashDir);
685 try {
686 createDirs(state.trashDir);
687 } catch (SysError & e) {
688 if (e.errNo == ENOSPC) {
689 printMsg(lvlInfo, format("note: can't create trash directory: %1%") % e.msg());
690 state.moveToTrash = false;
691 }
692 }
693 }
694
695 /* Now either delete all garbage paths, or just the specified
696 paths (for gcDeleteSpecific). */
697
698 if (options.action == GCOptions::gcDeleteSpecific) {
699
700 foreach (PathSet::iterator, i, options.pathsToDelete) {
701 assertStorePath(*i);
702 tryToDelete(state, *i);
703 if (state.dead.find(*i) == state.dead.end())
704 throw Error(format("cannot delete path `%1%' since it is still alive") % *i);
705 }
706
707 } else if (options.maxFreed > 0) {
708
709 if (state.shouldDelete)
710 printMsg(lvlError, format("deleting garbage..."));
711 else
712 printMsg(lvlError, format("determining live/dead paths..."));
713
714 try {
715
716 AutoCloseDir dir = opendir(settings.nixStore.c_str());
717 if (!dir) throw SysError(format("opening directory `%1%'") % settings.nixStore);
718
719 /* Read the store and immediately delete all paths that
720 aren't valid. When using --max-freed etc., deleting
721 invalid paths is preferred over deleting unreachable
722 paths, since unreachable paths could become reachable
723 again. We don't use readDirectory() here so that GCing
724 can start faster. */
725 Paths entries;
726 struct dirent * dirent;
727 while (errno = 0, dirent = readdir(dir)) {
728 checkInterrupt();
729 string name = dirent->d_name;
730 if (name == "." || name == "..") continue;
731 Path path = settings.nixStore + "/" + name;
732 if (isValidPath(path))
733 entries.push_back(path);
734 else
735 tryToDelete(state, path);
736 }
737
738 dir.close();
739
740 /* Now delete the unreachable valid paths. Randomise the
741 order in which we delete entries to make the collector
742 less biased towards deleting paths that come
743 alphabetically first (e.g. /nix/store/000...). This
744 matters when using --max-freed etc. */
745 vector<Path> entries_(entries.begin(), entries.end());
746 random_shuffle(entries_.begin(), entries_.end());
747
748 foreach (vector<Path>::iterator, i, entries_)
749 tryToDelete(state, *i);
750
751 } catch (GCLimitReached & e) {
752 }
753 }
754
755 if (state.options.action == GCOptions::gcReturnLive) {
756 state.results.paths = state.alive;
757 return;
758 }
759
760 if (state.options.action == GCOptions::gcReturnDead) {
761 state.results.paths = state.dead;
762 return;
763 }
764
765 /* Allow other processes to add to the store from here on. */
766 fdGCLock.close();
767 fds.clear();
768
769 /* Delete the trash directory. */
770 printMsg(lvlInfo, format("deleting `%1%'") % state.trashDir);
771 deleteGarbage(state, state.trashDir);
772
773 /* Clean up the links directory. */
774 if (options.action == GCOptions::gcDeleteDead || options.action == GCOptions::gcDeleteSpecific) {
775 printMsg(lvlError, format("deleting unused links..."));
776 removeUnusedLinks(state);
777 }
778
779 /* While we're at it, vacuum the database. */
780 //if (options.action == GCOptions::gcDeleteDead) vacuumDB();
781 }
782
783
784 }