libutil: Add bindPath function from libstore
bindPath/doBind is a useful function in build that is used in several parts of LocalDerivationGoal. Moving this function makes it easier to split LocalDerivationGoal implementation between several files. Change-Id: Ic5a0768479c153c1aa3ed425f12604b20bbf0f42
This commit is contained in:
parent
6abad7cb23
commit
3058029fba
4 changed files with 67 additions and 38 deletions
|
@ -17,6 +17,7 @@
|
|||
#include "namespaces.hh"
|
||||
#include "child.hh"
|
||||
#include "unix-domain-socket.hh"
|
||||
#include "mount.hh"
|
||||
|
||||
#include <regex>
|
||||
#include <queue>
|
||||
|
@ -386,39 +387,6 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
|
|||
cleanupPostOutputsRegisteredModeCheck();
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
static void doBind(const Path & source, const Path & target, bool optional = false) {
|
||||
debug("bind mounting '%1%' to '%2%'", source, target);
|
||||
|
||||
auto bindMount = [&]() {
|
||||
if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
|
||||
throw SysError("bind mount from '%1%' to '%2%' failed", source, target);
|
||||
};
|
||||
|
||||
auto maybeSt = maybeLstat(source);
|
||||
if (!maybeSt) {
|
||||
if (optional)
|
||||
return;
|
||||
else
|
||||
throw SysError("getting attributes of path '%1%'", source);
|
||||
}
|
||||
auto st = *maybeSt;
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
createDirs(target);
|
||||
bindMount();
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
// Symlinks can (apparently) not be bind-mounted, so just copy it
|
||||
createDirs(dirOf(target));
|
||||
copyFile(source, target, {});
|
||||
} else {
|
||||
createDirs(dirOf(target));
|
||||
writeFile(target, "");
|
||||
bindMount();
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
void LocalDerivationGoal::startBuilder()
|
||||
{
|
||||
if ((buildUser && buildUser->getUIDCount() != 1)
|
||||
|
@ -1321,7 +1289,7 @@ void LocalDerivationGoal::addDependency(const StorePath & path)
|
|||
Path target = chrootRootDir + worker.store.printStorePath(path);
|
||||
|
||||
if (pathExists(target)) {
|
||||
// There is a similar debug message in doBind, so only run it in this block to not have double messages.
|
||||
// There is a similar debug message in bindPath, so only run it in this block to not have double messages.
|
||||
debug("bind-mounting %s -> %s", target, source);
|
||||
throw Error("store path '%s' already exists in the sandbox", worker.store.printStorePath(path));
|
||||
}
|
||||
|
@ -1338,7 +1306,7 @@ void LocalDerivationGoal::addDependency(const StorePath & path)
|
|||
if (setns(sandboxMountNamespace.get(), 0) == -1)
|
||||
throw SysError("entering sandbox mount namespace");
|
||||
|
||||
doBind(source, target);
|
||||
bindPath(source, target);
|
||||
|
||||
_exit(0);
|
||||
});
|
||||
|
@ -2117,7 +2085,7 @@ void LocalDerivationGoal::runChild()
|
|||
chmodPath(dst, 0555);
|
||||
} else
|
||||
#endif
|
||||
doBind(i.second.source, chrootRootDir + i.first, i.second.optional);
|
||||
bindPath(i.second.source, chrootRootDir + i.first, i.second.optional);
|
||||
}
|
||||
|
||||
/* Bind a new instance of procfs on /proc. */
|
||||
|
@ -2156,8 +2124,8 @@ void LocalDerivationGoal::runChild()
|
|||
} else {
|
||||
if (errno != EINVAL)
|
||||
throw SysError("mounting /dev/pts");
|
||||
doBind("/dev/pts", chrootRootDir + "/dev/pts");
|
||||
doBind("/dev/ptmx", chrootRootDir + "/dev/ptmx");
|
||||
bindPath("/dev/pts", chrootRootDir + "/dev/pts");
|
||||
bindPath("/dev/ptmx", chrootRootDir + "/dev/ptmx");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ libutil_sources = files(
|
|||
'hilite.cc',
|
||||
'json-utils.cc',
|
||||
'logging.cc',
|
||||
'mount.cc',
|
||||
'namespaces.cc',
|
||||
'position.cc',
|
||||
'print-elided.cc',
|
||||
|
@ -84,6 +85,7 @@ libutil_headers = files(
|
|||
'logging-json.hh',
|
||||
'lru-cache.hh',
|
||||
'monitor-fd.hh',
|
||||
'mount.hh',
|
||||
'namespaces.hh',
|
||||
'pool.hh',
|
||||
'position.hh',
|
||||
|
|
43
src/libutil/mount.cc
Normal file
43
src/libutil/mount.cc
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "mount.hh"
|
||||
#include "error.hh"
|
||||
#include "file-system.hh"
|
||||
#include "logging.hh"
|
||||
#if __linux__
|
||||
#include <sys/mount.h>
|
||||
|
||||
namespace nix {
|
||||
|
||||
void bindPath(const Path & source, const Path & target, bool optional) {
|
||||
debug("bind mounting '%1%' to '%2%'", source, target);
|
||||
|
||||
auto bindMount = [&]() {
|
||||
if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
|
||||
throw SysError("bind mount from '%1%' to '%2%' failed", source, target);
|
||||
};
|
||||
|
||||
auto maybeSt = maybeLstat(source);
|
||||
if (!maybeSt) {
|
||||
if (optional)
|
||||
return;
|
||||
else
|
||||
throw SysError("getting attributes of path '%1%'", source);
|
||||
}
|
||||
auto st = *maybeSt;
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
createDirs(target);
|
||||
bindMount();
|
||||
} else if (S_ISLNK(st.st_mode)) {
|
||||
// Symlinks can (apparently) not be bind-mounted, so just copy it
|
||||
createDirs(dirOf(target));
|
||||
copyFile(source, target, {});
|
||||
} else {
|
||||
createDirs(dirOf(target));
|
||||
writeFile(target, "");
|
||||
bindMount();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
16
src/libutil/mount.hh
Normal file
16
src/libutil/mount.hh
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "types.hh"
|
||||
|
||||
#if __linux__
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* Bind-mount file or directory from `source` to `destination`.
|
||||
* If source does not exist this will fail unless `optional` is set
|
||||
*/
|
||||
void bindPath(const Path & source, const Path & target, bool optional = false);
|
||||
|
||||
}
|
||||
#endif
|
Loading…
Reference in a new issue