From e854c5364abef3398cc6f840b98f2207276eeea9 Mon Sep 17 00:00:00 2001 From: Raito Bezarius Date: Sat, 26 Jul 2025 23:00:21 +0200 Subject: [PATCH] libutil/mount: accept copy flags for bind path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sometimes, `bindPath` will detect the source is a symlink and we are not using the new mount API which support symlinks (kernel ≥ 5.12 IIRC?). In those instances, we copy the inode to the target. But some callers may want to follow the symlink in such circumstances, we add a new default argument to the previous value and let caller decide for themselves. Change-Id: I8505b613fc614ce539eb89258fbbb7eaecebe23b Signed-off-by: Raito Bezarius --- lix/libutil/mount.cc | 6 +++--- lix/libutil/mount.hh | 11 +++++++++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/lix/libutil/mount.cc b/lix/libutil/mount.cc index 495344208..830c2c538 100644 --- a/lix/libutil/mount.cc +++ b/lix/libutil/mount.cc @@ -7,7 +7,8 @@ namespace nix { -void bindPath(const Path & source, const Path & target, bool optional) { +void bindPath(const Path & source, const Path & target, bool optional, CopyFileFlags flags) +{ debug("bind mounting '%1%' to '%2%'", source, target); auto bindMount = [&]() { @@ -30,14 +31,13 @@ void bindPath(const Path & source, const Path & target, bool optional) { } else if (S_ISLNK(st.st_mode)) { // Symlinks can (apparently) not be bind-mounted, so just copy it createDirs(dirOf(target)); - copyFile(source, target, {}); + copyFile(source, target, flags); } else { createDirs(dirOf(target)); writeFile(target, ""); bindMount(); } } - } #endif diff --git a/lix/libutil/mount.hh b/lix/libutil/mount.hh index 6c8e55c23..fbc5ca107 100644 --- a/lix/libutil/mount.hh +++ b/lix/libutil/mount.hh @@ -2,6 +2,7 @@ ///@file #include "lix/libutil/types.hh" +#include "lix/libutil/file-system.hh" #if __linux__ namespace nix { @@ -9,8 +10,14 @@ namespace nix { /** * Bind-mount file or directory from `source` to `destination`. * If source does not exist this will fail unless `optional` is set + * + * If `source` is a symlink, it will perform a copy instead of a bind mount + * because symlinks cannot be bind mounted on all versions of the Linux kernel. + * + * If a copy is performed, extra flags to the copy can be passed using `flags`. */ -void bindPath(const Path & source, const Path & target, bool optional = false); - +void bindPath( + const Path & source, const Path & target, bool optional = false, CopyFileFlags flags = {} +); } #endif