From 9c6cfb13f2f419aa344439bbba83379216c6cfe6 Mon Sep 17 00:00:00 2001 From: Marat Radchenko Date: Sun, 9 Jul 2023 16:34:12 +0300 Subject: [PATCH] Add support for bind-mounts on Darwin Signed-off-by: Marat Radchenko --- core/mount/mount.go | 2 +- core/mount/mount_darwin.go | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/core/mount/mount.go b/core/mount/mount.go index e8e0fe31c086..6b8f08a71863 100644 --- a/core/mount/mount.go +++ b/core/mount/mount.go @@ -27,7 +27,7 @@ import ( ) // HasBindMounts This is a flag to conditionally disable code that relies on working bind-mount support, so such code is easier to find across codebase. -const HasBindMounts = runtime.GOOS != "darwin" && runtime.GOOS != "openbsd" +const HasBindMounts = runtime.GOOS != "openbsd" // Mount is the lingua franca of containerd. A mount represents a // serialized mount syscall. Components either emit or consume mounts. diff --git a/core/mount/mount_darwin.go b/core/mount/mount_darwin.go index f319d69707d0..d98ea654e54f 100644 --- a/core/mount/mount_darwin.go +++ b/core/mount/mount_darwin.go @@ -16,9 +16,39 @@ package mount -import "github.com/containerd/errdefs" +import ( + "fmt" + "os/exec" +) // Mount to the provided target. func (m *Mount) mount(target string) error { - return errdefs.ErrNotImplemented + var commandName string + if m.Type == "bind" { + // macOS doesn't natively support bindfs/nullfs + // The way to emulate it is via FUSE fs named "bindfs" + commandName = "bindfs" + } else { + commandName = fmt.Sprintf("mount_%s", m.Type) + } + + var args []string + for _, option := range m.Options { + if option == "rbind" { + // On one side, rbind is not supported by macOS mounting tools + // On the other, bindfs works as if rbind is enabled anyway + continue + } + + args = append(args, "-o", option) + } + args = append(args, m.Source, target) + + cmd := exec.Command(commandName, args...) + output, err := cmd.CombinedOutput() + if err != nil { + return fmt.Errorf("%s [%v] failed: %q: %w", commandName, args, string(output), err) + } + + return nil }