diff options
author | Artemis Tosini <lix@artem.ist> | 2024-08-13 19:39:10 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@localhost> | 2024-08-13 19:39:10 +0000 |
commit | b016eb0895bb6714a4f6530d9a2bb6577ac6c3cf (patch) | |
tree | 43b10a1e56ccb33768338b7858e359d29ffd2529 /src/libutil | |
parent | f9a3bf6ccccf8ac6b1604c1a2980e3a565ae4f44 (diff) | |
parent | 3058029fbafb53563fcc31401546edce258d65ca (diff) |
Merge "libutil: Add bindPath function from libstore" into main
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/meson.build | 2 | ||||
-rw-r--r-- | src/libutil/mount.cc | 43 | ||||
-rw-r--r-- | src/libutil/mount.hh | 16 |
3 files changed, 61 insertions, 0 deletions
diff --git a/src/libutil/meson.build b/src/libutil/meson.build index 4740ea64d..41336874b 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', @@ -86,6 +87,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 |