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 "namespaces.hh"
|
||||||
#include "child.hh"
|
#include "child.hh"
|
||||||
#include "unix-domain-socket.hh"
|
#include "unix-domain-socket.hh"
|
||||||
|
#include "mount.hh"
|
||||||
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
@ -386,39 +387,6 @@ void LocalDerivationGoal::cleanupPostOutputsRegisteredModeNonCheck()
|
||||||
cleanupPostOutputsRegisteredModeCheck();
|
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()
|
void LocalDerivationGoal::startBuilder()
|
||||||
{
|
{
|
||||||
if ((buildUser && buildUser->getUIDCount() != 1)
|
if ((buildUser && buildUser->getUIDCount() != 1)
|
||||||
|
@ -1321,7 +1289,7 @@ void LocalDerivationGoal::addDependency(const StorePath & path)
|
||||||
Path target = chrootRootDir + worker.store.printStorePath(path);
|
Path target = chrootRootDir + worker.store.printStorePath(path);
|
||||||
|
|
||||||
if (pathExists(target)) {
|
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);
|
debug("bind-mounting %s -> %s", target, source);
|
||||||
throw Error("store path '%s' already exists in the sandbox", worker.store.printStorePath(path));
|
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)
|
if (setns(sandboxMountNamespace.get(), 0) == -1)
|
||||||
throw SysError("entering sandbox mount namespace");
|
throw SysError("entering sandbox mount namespace");
|
||||||
|
|
||||||
doBind(source, target);
|
bindPath(source, target);
|
||||||
|
|
||||||
_exit(0);
|
_exit(0);
|
||||||
});
|
});
|
||||||
|
@ -2117,7 +2085,7 @@ void LocalDerivationGoal::runChild()
|
||||||
chmodPath(dst, 0555);
|
chmodPath(dst, 0555);
|
||||||
} else
|
} else
|
||||||
#endif
|
#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. */
|
/* Bind a new instance of procfs on /proc. */
|
||||||
|
@ -2156,8 +2124,8 @@ void LocalDerivationGoal::runChild()
|
||||||
} else {
|
} else {
|
||||||
if (errno != EINVAL)
|
if (errno != EINVAL)
|
||||||
throw SysError("mounting /dev/pts");
|
throw SysError("mounting /dev/pts");
|
||||||
doBind("/dev/pts", chrootRootDir + "/dev/pts");
|
bindPath("/dev/pts", chrootRootDir + "/dev/pts");
|
||||||
doBind("/dev/ptmx", chrootRootDir + "/dev/ptmx");
|
bindPath("/dev/ptmx", chrootRootDir + "/dev/ptmx");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ libutil_sources = files(
|
||||||
'hilite.cc',
|
'hilite.cc',
|
||||||
'json-utils.cc',
|
'json-utils.cc',
|
||||||
'logging.cc',
|
'logging.cc',
|
||||||
|
'mount.cc',
|
||||||
'namespaces.cc',
|
'namespaces.cc',
|
||||||
'position.cc',
|
'position.cc',
|
||||||
'print-elided.cc',
|
'print-elided.cc',
|
||||||
|
@ -84,6 +85,7 @@ libutil_headers = files(
|
||||||
'logging-json.hh',
|
'logging-json.hh',
|
||||||
'lru-cache.hh',
|
'lru-cache.hh',
|
||||||
'monitor-fd.hh',
|
'monitor-fd.hh',
|
||||||
|
'mount.hh',
|
||||||
'namespaces.hh',
|
'namespaces.hh',
|
||||||
'pool.hh',
|
'pool.hh',
|
||||||
'position.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