aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorArtemis Tosini <me@artem.ist>2024-07-27 19:40:40 +0000
committerArtemis Tosini <me@artem.ist>2024-07-27 19:40:40 +0000
commit3058029fbafb53563fcc31401546edce258d65ca (patch)
tree584d5933d9c3a050520b10afff9c17254c4a7497 /src/libutil
parent6abad7cb238c5c7bf59a83bed55e7590c544fc2e (diff)
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
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/meson.build2
-rw-r--r--src/libutil/mount.cc43
-rw-r--r--src/libutil/mount.hh16
3 files changed, 61 insertions, 0 deletions
diff --git a/src/libutil/meson.build b/src/libutil/meson.build
index c860e7e00..731521bbb 100644
--- a/src/libutil/meson.build
+++ b/src/libutil/meson.build
@@ -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',
diff --git a/src/libutil/mount.cc b/src/libutil/mount.cc
new file mode 100644
index 000000000..025ced5b9
--- /dev/null
+++ b/src/libutil/mount.cc
@@ -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
diff --git a/src/libutil/mount.hh b/src/libutil/mount.hh
new file mode 100644
index 000000000..59e2218be
--- /dev/null
+++ b/src/libutil/mount.hh
@@ -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