diff options
Diffstat (limited to 'nix/libstore')
-rw-r--r-- | nix/libstore/build.cc | 171 | ||||
-rw-r--r-- | nix/libstore/gc.cc | 6 | ||||
-rw-r--r-- | nix/libstore/local-store.cc | 31 | ||||
-rw-r--r-- | nix/libstore/local-store.hh | 2 | ||||
-rw-r--r-- | nix/libstore/optimise-store.cc | 1 | ||||
-rw-r--r-- | nix/libstore/pathlocks.cc | 2 | ||||
-rw-r--r-- | nix/libstore/remote-store.cc | 17 | ||||
-rw-r--r-- | nix/libstore/remote-store.hh | 29 | ||||
-rw-r--r-- | nix/libstore/store-api.hh | 24 | ||||
-rw-r--r-- | nix/libstore/worker-protocol.hh | 3 |
10 files changed, 154 insertions, 132 deletions
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc index 009fcb2c0c..85a818ba94 100644 --- a/nix/libstore/build.cc +++ b/nix/libstore/build.cc @@ -38,6 +38,9 @@ #if HAVE_SYS_MOUNT_H #include <sys/mount.h> #endif +#if HAVE_SYS_SYSCALL_H +#include <sys/syscall.h> +#endif #if HAVE_SCHED_H #include <sched.h> #endif @@ -48,7 +51,7 @@ #include <linux/fs.h> #endif -#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS) +#define CHROOT_ENABLED HAVE_CHROOT && HAVE_UNSHARE && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS) && defined(SYS_pivot_root) #if CHROOT_ENABLED #include <sys/socket.h> @@ -414,19 +417,6 @@ static void commonChildInit(Pipe & logPipe) close(fdDevNull); } - -/* Convert a string list to an array of char pointers. Careful: the - string list should outlive the array. */ -const char * * strings2CharPtrs(const Strings & ss) -{ - const char * * arr = new const char * [ss.size() + 1]; - const char * * p = arr; - foreach (Strings::const_iterator, i, ss) *p++ = i->c_str(); - *p = 0; - return arr; -} - - /* Restore default handling of SIGPIPE, otherwise some programs will randomly say "Broken pipe". */ static void restoreSIGPIPE() @@ -764,7 +754,7 @@ private: typedef void (DerivationGoal::*GoalState)(); GoalState state; - /* Stuff we need to pass to initChild(). */ + /* Stuff we need to pass to runChild(). */ typedef map<Path, Path> DirsInChroot; // maps target path to source path DirsInChroot dirsInChroot; typedef map<string, string> Environment; @@ -828,8 +818,8 @@ private: /* Start building a derivation. */ void startBuilder(); - /* Initialise the builder's process. */ - void initChild(); + /* Run the builder's process. */ + void runChild(); friend int childEntry(void *); @@ -1612,7 +1602,7 @@ void chmod_(const Path & path, mode_t mode) int childEntry(void * arg) { - ((DerivationGoal *) arg)->initChild(); + ((DerivationGoal *) arg)->runChild(); return 1; } @@ -1759,37 +1749,11 @@ void DerivationGoal::startBuilder() /* Change ownership of the temporary build directory. */ if (chown(tmpDir.c_str(), buildUser.getUID(), buildUser.getGID()) == -1) - throw SysError(format("cannot change ownership of `%1%'") % tmpDir); + throw SysError(format("cannot change ownership of '%1%'") % tmpDir); + } - /* Check that the Nix store has the appropriate permissions, - i.e., owned by root and mode 1775 (sticky bit on so that - the builder can create its output but not mess with the - outputs of other processes). */ - struct stat st; - if (stat(settings.nixStore.c_str(), &st) == -1) - throw SysError(format("cannot stat `%1%'") % settings.nixStore); - if (!(st.st_mode & S_ISVTX) || - ((st.st_mode & S_IRWXG) != S_IRWXG) || - (st.st_gid != buildUser.getGID())) - throw Error(format( - "builder does not have write permission to `%2%'; " - "try `chgrp %1% %2%; chmod 1775 %2%'") - % buildUser.getGID() % settings.nixStore); - } - - - /* Are we doing a chroot build? Note that fixed-output - derivations are never done in a chroot, mainly so that - functions like fetchurl (which needs a proper /etc/resolv.conf) - work properly. Purity checking for fixed-output derivations - is somewhat pointless anyway. */ useChroot = settings.useChroot; - if (fixedOutput) useChroot = false; - - /* Hack to allow derivations to disable chroot builds. */ - if (get(drv.env, "__noChroot") == "1") useChroot = false; - if (useChroot) { #if CHROOT_ENABLED /* Create a temporary directory in which we set up the chroot @@ -1804,6 +1768,12 @@ void DerivationGoal::startBuilder() printMsg(lvlChatty, format("setting up chroot environment in `%1%'") % chrootRootDir); + if (mkdir(chrootRootDir.c_str(), 0750) == -1) + throw SysError(format("cannot create ‘%1%’") % chrootRootDir); + + if (chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1) + throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir); + /* Create a writable /tmp in the chroot. Many builders need this. (Of course they should really respect $TMPDIR instead.) */ @@ -1830,7 +1800,8 @@ void DerivationGoal::startBuilder() % (buildUser.enabled() ? buildUser.getGID() : getgid())).str()); /* Create /etc/hosts with localhost entry. */ - writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n"); + if (!fixedOutput) + writeFile(chrootRootDir + "/etc/hosts", "127.0.0.1 localhost\n"); /* Bind-mount a user-configurable set of directories from the host file system. */ @@ -1853,8 +1824,12 @@ void DerivationGoal::startBuilder() can be bind-mounted). !!! As an extra security precaution, make the fake Nix store only writable by the build user. */ - createDirs(chrootRootDir + settings.nixStore); - chmod_(chrootRootDir + settings.nixStore, 01777); + Path chrootStoreDir = chrootRootDir + settings.nixStore; + createDirs(chrootStoreDir); + chmod_(chrootStoreDir, 01775); + + if (chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1) + throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir); foreach (PathSet::iterator, i, inputPaths) { struct stat st; @@ -1963,14 +1938,17 @@ void DerivationGoal::startBuilder() */ #if CHROOT_ENABLED if (useChroot) { - char stack[32 * 1024]; - pid = clone(childEntry, stack + sizeof(stack) - 8, - CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD, this); + char stack[32 * 1024]; + int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | SIGCHLD; + if (!fixedOutput) flags |= CLONE_NEWNET; + pid = clone(childEntry, stack + sizeof(stack) - 8, flags, this); + if (pid == -1) + throw SysError("cloning builder process"); } else #endif { pid = fork(); - if (pid == 0) initChild(); + if (pid == 0) runChild(); } if (pid == -1) throw SysError("unable to fork"); @@ -1993,7 +1971,7 @@ void DerivationGoal::startBuilder() } -void DerivationGoal::initChild() +void DerivationGoal::runChild() { /* Warning: in the child we should absolutely not make any SQLite calls! */ @@ -2022,9 +2000,11 @@ void DerivationGoal::initChild() /* Set the hostname etc. to fixed values. */ char hostname[] = "localhost"; - sethostname(hostname, sizeof(hostname)); + if (sethostname(hostname, sizeof(hostname)) == -1) + throw SysError("cannot set host name"); char domainname[] = "(none)"; // kernel default - setdomainname(domainname, sizeof(domainname)); + if (setdomainname(domainname, sizeof(domainname)) == -1) + throw SysError("cannot set domain name"); /* Make all filesystems private. This is necessary because subtrees may have been mounted as "shared" @@ -2042,12 +2022,17 @@ void DerivationGoal::initChild() throw SysError(format("unable to make filesystem `%1%' private") % fs); } + /* Bind-mount chroot directory to itself, to treat it as a + different filesystem from /, as needed for pivot_root. */ + if (mount(chrootRootDir.c_str(), chrootRootDir.c_str(), 0, MS_BIND, 0) == -1) + throw SysError(format("unable to bind mount ‘%1%’") % chrootRootDir); + /* Set up a nearly empty /dev, unless the user asked to bind-mount the host /dev. */ + Strings ss; if (dirsInChroot.find("/dev") == dirsInChroot.end()) { createDirs(chrootRootDir + "/dev/shm"); createDirs(chrootRootDir + "/dev/pts"); - Strings ss; ss.push_back("/dev/full"); #ifdef __linux__ if (pathExists("/dev/kvm")) @@ -2058,13 +2043,24 @@ void DerivationGoal::initChild() ss.push_back("/dev/tty"); ss.push_back("/dev/urandom"); ss.push_back("/dev/zero"); - foreach (Strings::iterator, i, ss) dirsInChroot[*i] = *i; createSymlink("/proc/self/fd", chrootRootDir + "/dev/fd"); createSymlink("/proc/self/fd/0", chrootRootDir + "/dev/stdin"); createSymlink("/proc/self/fd/1", chrootRootDir + "/dev/stdout"); createSymlink("/proc/self/fd/2", chrootRootDir + "/dev/stderr"); } + /* Fixed-output derivations typically need to access the + network, so give them access to /etc/resolv.conf and so + on. */ + if (fixedOutput) { + ss.push_back("/etc/resolv.conf"); + ss.push_back("/etc/nsswitch.conf"); + ss.push_back("/etc/services"); + ss.push_back("/etc/hosts"); + } + + for (auto & i : ss) dirsInChroot[i] = i; + /* Bind-mount all the directories from the "host" filesystem that we want in the chroot environment. */ @@ -2114,13 +2110,26 @@ void DerivationGoal::initChild() chmod_(chrootRootDir + "/dev/pts/ptmx", 0666); } - /* Do the chroot(). Below we do a chdir() to the - temporary build directory to make sure the current - directory is in the chroot. (Actually the order - doesn't matter, since due to the bind mount tmpDir and - tmpRootDit/tmpDir are the same directories.) */ - if (chroot(chrootRootDir.c_str()) == -1) - throw SysError(format("cannot change root directory to `%1%'") % chrootRootDir); + /* Do the chroot(). */ + if (chdir(chrootRootDir.c_str()) == -1) + throw SysError(format("cannot change directory to '%1%'") % chrootRootDir); + + if (mkdir("real-root", 0) == -1) + throw SysError("cannot create real-root directory"); + +#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old)) + if (pivot_root(".", "real-root") == -1) + throw SysError(format("cannot pivot old root directory onto '%1%'") % (chrootRootDir + "/real-root")); +#undef pivot_root + + if (chroot(".") == -1) + throw SysError(format("cannot change root directory to '%1%'") % chrootRootDir); + + if (umount2("real-root", MNT_DETACH) == -1) + throw SysError("cannot unmount real root filesystem"); + + if (rmdir("real-root") == -1) + throw SysError("cannot remove real-root directory"); } #endif @@ -2159,11 +2168,7 @@ void DerivationGoal::initChild() Strings envStrs; foreach (Environment::const_iterator, i, env) envStrs.push_back(rewriteHashes(i->first + "=" + i->second, rewritesToTmp)); - const char * * envArr = strings2CharPtrs(envStrs); - - Path program = drv.builder.c_str(); - std::vector<const char *> args; /* careful with c_str()! */ - string user; /* must be here for its c_str()! */ + auto envArr = stringsToCharPtrs(envStrs); /* If we are running in `build-users' mode, then switch to the user we allocated above. Make sure that we drop all root @@ -2189,29 +2194,25 @@ void DerivationGoal::initChild() } /* Fill in the arguments. */ + Strings args; string builderBasename = baseNameOf(drv.builder); - args.push_back(builderBasename.c_str()); - foreach (Strings::iterator, i, drv.args) { - auto re = rewriteHashes(*i, rewritesToTmp); - auto cstr = new char[re.length()+1]; - std::strcpy(cstr, re.c_str()); - - args.push_back(cstr); - } - args.push_back(0); + args.push_back(builderBasename); + foreach (Strings::iterator, i, drv.args) + args.push_back(rewriteHashes(*i, rewritesToTmp)); + auto argArr = stringsToCharPtrs(args); restoreSIGPIPE(); /* Indicate that we managed to set up the build environment. */ - writeToStderr("\n"); + writeFull(STDERR_FILENO, "\n"); /* Execute the program. This should not return. */ - execve(program.c_str(), (char * *) &args[0], (char * *) envArr); + execve(drv.builder.c_str(), (char * *) &argArr[0], (char * *) &envArr[0]); throw SysError(format("executing `%1%'") % drv.builder); } catch (std::exception & e) { - writeToStderr("while setting up the build environment: " + string(e.what()) + "\n"); + writeFull(STDERR_FILENO, "while setting up the build environment: " + string(e.what()) + "\n"); _exit(1); } @@ -2526,7 +2527,7 @@ void DerivationGoal::handleChildOutput(int fd, const string & data) BZ2_bzWrite(&err, bzLogFile, (unsigned char *) data.data(), data.size()); if (err != BZ_OK) throw Error(format("cannot write to compressed log file (BZip2 error = %1%)") % err); } else if (fdLogFile != -1) - writeFull(fdLogFile, (unsigned char *) data.data(), data.size()); + writeFull(fdLogFile, data); } if (hook && fd == hook->fromHook.readSide) @@ -2836,7 +2837,7 @@ void SubstitutionGoal::tryToRun() args.push_back("--substitute"); args.push_back(storePath); args.push_back(destPath); - const char * * argArr = strings2CharPtrs(args); + auto argArr = stringsToCharPtrs(args); /* Fork the substitute program. */ pid = startProcess([&]() { @@ -2846,7 +2847,7 @@ void SubstitutionGoal::tryToRun() if (dup2(outPipe.writeSide, STDOUT_FILENO) == -1) throw SysError("cannot dup output pipe into stdout"); - execv(sub.c_str(), (char * *) argArr); + execv(sub.c_str(), (char * *) &argArr[0]); throw SysError(format("executing `%1%'") % sub); }); diff --git a/nix/libstore/gc.cc b/nix/libstore/gc.cc index f98e02c1e2..34768324c2 100644 --- a/nix/libstore/gc.cc +++ b/nix/libstore/gc.cc @@ -96,7 +96,7 @@ Path addPermRoot(StoreAPI & store, const Path & _storePath, "(are you running nix-build inside the store?)") % gcRoot); if (indirect) { - /* Don't clobber the the link if it already exists and doesn't + /* Don't clobber the link if it already exists and doesn't point to the Nix store. */ if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot)))) throw Error(format("cannot create symlink `%1%'; already exists") % gcRoot); @@ -191,7 +191,7 @@ void LocalStore::addTempRoot(const Path & path) lockFile(fdTempRoots, ltWrite, true); string s = path + '\0'; - writeFull(fdTempRoots, (const unsigned char *) s.data(), s.size()); + writeFull(fdTempRoots, s); /* Downgrade to a read lock. */ debug(format("downgrading to read lock on `%1%'") % fnTempRoots); @@ -231,7 +231,7 @@ static void readTempRoots(PathSet & tempRoots, FDs & fds) if (lockFile(*fd, ltWrite, false)) { printMsg(lvlError, format("removing stale temporary roots file `%1%'") % path); unlink(path.c_str()); - writeFull(*fd, (const unsigned char *) "d", 1); + writeFull(*fd, "d"); continue; } diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc index a115f65847..630cb80c41 100644 --- a/nix/libstore/local-store.cc +++ b/nix/libstore/local-store.cc @@ -254,22 +254,25 @@ LocalStore::LocalStore(bool reserveSpace) Path perUserDir = profilesDir + "/per-user"; createDirs(perUserDir); if (chmod(perUserDir.c_str(), 01777) == -1) - throw SysError(format("could not set permissions on `%1%' to 1777") % perUserDir); + throw SysError(format("could not set permissions on '%1%' to 1777") % perUserDir); + + mode_t perm = 01775; struct group * gr = getgrnam(settings.buildUsersGroup.c_str()); if (!gr) throw Error(format("the group `%1%' specified in `build-users-group' does not exist") % settings.buildUsersGroup); - - struct stat st; - if (stat(settings.nixStore.c_str(), &st)) - throw SysError(format("getting attributes of path `%1%'") % settings.nixStore); - - if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != 01775) { - if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1) - throw SysError(format("changing ownership of path `%1%'") % settings.nixStore); - if (chmod(settings.nixStore.c_str(), 01775) == -1) - throw SysError(format("changing permissions on path `%1%'") % settings.nixStore); + else { + struct stat st; + if (stat(settings.nixStore.c_str(), &st)) + throw SysError(format("getting attributes of path '%1%'") % settings.nixStore); + + if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) { + if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1) + throw SysError(format("changing ownership of path '%1%'") % settings.nixStore); + if (chmod(settings.nixStore.c_str(), perm) == -1) + throw SysError(format("changing permissions on path '%1%'") % settings.nixStore); + } } } @@ -499,7 +502,7 @@ void LocalStore::makeStoreWritable() if (unshare(CLONE_NEWNS) == -1) throw SysError("setting up a private mount namespace"); - if (mount(0, settings.nixStore.c_str(), 0, MS_REMOUNT | MS_BIND, 0) == -1) + if (mount(0, settings.nixStore.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) throw SysError(format("remounting %1% writable") % settings.nixStore); } #endif @@ -1404,7 +1407,7 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name, } -Path LocalStore::addToStore(const Path & _srcPath, +Path LocalStore::addToStore(const string & name, const Path & _srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, bool repair) { Path srcPath(absPath(_srcPath)); @@ -1419,7 +1422,7 @@ Path LocalStore::addToStore(const Path & _srcPath, else sink.s = readFile(srcPath); - return addToStoreFromDump(sink.s, baseNameOf(srcPath), recursive, hashAlgo, repair); + return addToStoreFromDump(sink.s, name, recursive, hashAlgo, repair); } diff --git a/nix/libstore/local-store.hh b/nix/libstore/local-store.hh index e0aabdba42..819f59327a 100644 --- a/nix/libstore/local-store.hh +++ b/nix/libstore/local-store.hh @@ -130,7 +130,7 @@ public: void querySubstitutablePathInfos(const PathSet & paths, SubstitutablePathInfos & infos); - Path addToStore(const Path & srcPath, + Path addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter, bool repair = false); diff --git a/nix/libstore/optimise-store.cc b/nix/libstore/optimise-store.cc index 8ba9d1a263..c62b8e451b 100644 --- a/nix/libstore/optimise-store.cc +++ b/nix/libstore/optimise-store.cc @@ -4,6 +4,7 @@ #include "local-store.hh" #include "globals.hh" +#include <cstdlib> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> diff --git a/nix/libstore/pathlocks.cc b/nix/libstore/pathlocks.cc index b858ed238d..830858ff8d 100644 --- a/nix/libstore/pathlocks.cc +++ b/nix/libstore/pathlocks.cc @@ -33,7 +33,7 @@ void deleteLockFile(const Path & path, int fd) other processes waiting on this lock that the lock is stale (deleted). */ unlink(path.c_str()); - writeFull(fd, (const unsigned char *) "d", 1); + writeFull(fd, "d"); /* Note that the result of unlink() is ignored; removing the lock file is an optimisation, not a necessity. */ } diff --git a/nix/libstore/remote-store.cc b/nix/libstore/remote-store.cc index 448d9b6bc1..0539bbe127 100644 --- a/nix/libstore/remote-store.cc +++ b/nix/libstore/remote-store.cc @@ -10,6 +10,7 @@ #include <sys/stat.h> #include <sys/socket.h> #include <sys/un.h> +#include <errno.h> #include <fcntl.h> #include <iostream> @@ -109,7 +110,7 @@ void RemoteStore::connectToDaemon() applications... */ AutoCloseFD fdPrevDir = open(".", O_RDONLY); if (fdPrevDir == -1) throw SysError("couldn't open current directory"); - chdir(dirOf(socketPath).c_str()); + if (chdir(dirOf(socketPath).c_str()) == -1) throw SysError(format("couldn't change to directory of ‘%1%’") % socketPath); Path socketPathRel = "./" + baseNameOf(socketPath); struct sockaddr_un addr; @@ -384,7 +385,7 @@ Path RemoteStore::queryPathFromHashPart(const string & hashPart) } -Path RemoteStore::addToStore(const Path & _srcPath, +Path RemoteStore::addToStore(const string & name, const Path & _srcPath, bool recursive, HashType hashAlgo, PathFilter & filter, bool repair) { if (repair) throw Error("repairing is not supported when building through the Nix daemon"); @@ -394,7 +395,7 @@ Path RemoteStore::addToStore(const Path & _srcPath, Path srcPath(absPath(_srcPath)); writeInt(wopAddToStore, to); - writeString(baseNameOf(srcPath), to); + writeString(name, to); /* backwards compatibility hack */ writeInt((hashAlgo == htSHA256 && recursive) ? 0 : 1, to); writeInt(recursive ? 1 : 0, to); @@ -584,6 +585,16 @@ void RemoteStore::optimiseStore() readInt(from); } +bool RemoteStore::verifyStore(bool checkContents, bool repair) +{ + openConnection(); + writeInt(wopVerifyStore, to); + writeInt(checkContents, to); + writeInt(repair, to); + processStderr(); + return readInt(from) != 0; +} + void RemoteStore::processStderr(Sink * sink, Source * source) { to.flush(); diff --git a/nix/libstore/remote-store.hh b/nix/libstore/remote-store.hh index 98774c10b3..030120db40 100644 --- a/nix/libstore/remote-store.hh +++ b/nix/libstore/remote-store.hh @@ -21,15 +21,15 @@ public: RemoteStore(); ~RemoteStore(); - + /* Implementations of abstract store API methods. */ - + bool isValidPath(const Path & path); PathSet queryValidPaths(const PathSet & paths); - + PathSet queryAllValidPaths(); - + ValidPathInfo queryPathInfo(const Path & path); Hash queryPathHash(const Path & path); @@ -39,21 +39,21 @@ public: void queryReferrers(const Path & path, PathSet & referrers); Path queryDeriver(const Path & path); - + PathSet queryValidDerivers(const Path & path); PathSet queryDerivationOutputs(const Path & path); - + StringSet queryDerivationOutputNames(const Path & path); Path queryPathFromHashPart(const string & hashPart); - + PathSet querySubstitutablePaths(const PathSet & paths); - + void querySubstitutablePathInfos(const PathSet & paths, SubstitutablePathInfos & infos); - - Path addToStore(const Path & srcPath, + + Path addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter, bool repair = false); @@ -64,7 +64,7 @@ public: Sink & sink); Paths importPaths(bool requireSignature, Source & source); - + void buildPaths(const PathSet & paths, BuildMode buildMode); void ensurePath(const Path & path); @@ -72,19 +72,20 @@ public: void addTempRoot(const Path & path); void addIndirectRoot(const Path & path); - + void syncWithGC(); - + Roots findRoots(); void collectGarbage(const GCOptions & options, GCResults & results); - + PathSet queryFailedPaths(); void clearFailedPaths(const PathSet & paths); void optimiseStore(); + bool verifyStore(bool checkContents, bool repair); private: AutoCloseFD fdSocket; FdSink to; diff --git a/nix/libstore/store-api.hh b/nix/libstore/store-api.hh index 3109f100ef..3764f3e542 100644 --- a/nix/libstore/store-api.hh +++ b/nix/libstore/store-api.hh @@ -54,7 +54,7 @@ struct GCOptions }; -struct GCResults +struct GCResults { /* Depending on the action, the GC roots, or the paths that would be or have been deleted. */ @@ -82,7 +82,7 @@ struct SubstitutablePathInfo typedef std::map<Path, SubstitutablePathInfo> SubstitutablePathInfos; -struct ValidPathInfo +struct ValidPathInfo { Path path; Path deriver; @@ -100,13 +100,13 @@ typedef list<ValidPathInfo> ValidPathInfos; enum BuildMode { bmNormal, bmRepair, bmCheck }; -class StoreAPI +class StoreAPI { public: virtual ~StoreAPI() { } - /* Check whether a path is valid. */ + /* Check whether a path is valid. */ virtual bool isValidPath(const Path & path) = 0; /* Query which of the given paths is valid. */ @@ -118,7 +118,7 @@ public: /* Query information about a valid path. */ virtual ValidPathInfo queryPathInfo(const Path & path) = 0; - /* Query the hash of a valid path. */ + /* Query the hash of a valid path. */ virtual Hash queryPathHash(const Path & path) = 0; /* Query the set of outgoing FS references for a store path. The @@ -150,7 +150,7 @@ public: /* Query the full store path given the hash part of a valid store path, or "" if the path doesn't exist. */ virtual Path queryPathFromHashPart(const string & hashPart) = 0; - + /* Query which of the given paths have substitutes. */ virtual PathSet querySubstitutablePaths(const PathSet & paths) = 0; @@ -159,12 +159,12 @@ public: info, it's omitted from the resulting ‘infos’ map. */ virtual void querySubstitutablePathInfos(const PathSet & paths, SubstitutablePathInfos & infos) = 0; - + /* Copy the contents of a path to the store and register the validity the resulting path. The resulting path is returned. The function object `filter' can be used to exclude files (see libutil/archive.hh). */ - virtual Path addToStore(const Path & srcPath, + virtual Path addToStore(const string & name, const Path & srcPath, bool recursive = true, HashType hashAlgo = htSHA256, PathFilter & filter = defaultPathFilter, bool repair = false) = 0; @@ -254,6 +254,10 @@ public: /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ virtual void optimiseStore() = 0; + + /* Check the integrity of the Nix store. Returns true if errors + remain. */ + virtual bool verifyStore(bool checkContents, bool repair) = 0; }; @@ -267,7 +271,7 @@ bool isStorePath(const Path & path); /* Extract the name part of the given store path. */ string storePathToName(const Path & path); - + void checkStoreName(const string & name); @@ -288,7 +292,7 @@ Path followLinksToStorePath(const Path & path); /* Constructs a unique store path name. */ Path makeStorePath(const string & type, const Hash & hash, const string & name); - + Path makeOutputPath(const string & id, const Hash & hash, const string & name); diff --git a/nix/libstore/worker-protocol.hh b/nix/libstore/worker-protocol.hh index 4b040b77ce..d037d7402e 100644 --- a/nix/libstore/worker-protocol.hh +++ b/nix/libstore/worker-protocol.hh @@ -42,7 +42,8 @@ typedef enum { wopQueryValidPaths = 31, wopQuerySubstitutablePaths = 32, wopQueryValidDerivers = 33, - wopOptimiseStore = 34 + wopOptimiseStore = 34, + wopVerifyStore = 35 } WorkerOp; |