pkg/fileutils: add ReflinkOrCopy()

Add a function to copy via reflink if possible or fall back to the
normal io.Copy().
c/image uses this function internally[1] however I like to export this
and use it in podman and I think this package here in c/storage is the
most logical location for it. Note compared to the c/image version I am
calling unix.IoctlFileClone() directly instead of the raw syscall
function.

[1] https://github.com/containers/image/tree/main/internal/reflink

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger 2025-02-07 15:43:29 +01:00
parent 5a2ca6ab27
commit 3f4b77d388
No known key found for this signature in database
GPG Key ID: EB145DD938A3CAF2
2 changed files with 35 additions and 0 deletions

View File

@ -0,0 +1,20 @@
package fileutils
import (
"io"
"os"
"golang.org/x/sys/unix"
)
// ReflinkOrCopy attempts to reflink the source to the destination fd.
// If reflinking fails or is unsupported, it falls back to io.Copy().
func ReflinkOrCopy(src, dst *os.File) error {
err := unix.IoctlFileClone(int(dst.Fd()), int(src.Fd()))
if err == nil {
return nil
}
_, err = io.Copy(dst, src)
return err
}

View File

@ -0,0 +1,15 @@
//go:build !linux
package fileutils
import (
"io"
"os"
)
// ReflinkOrCopy attempts to reflink the source to the destination fd.
// If reflinking fails or is unsupported, it falls back to io.Copy().
func ReflinkOrCopy(src, dst *os.File) error {
_, err := io.Copy(dst, src)
return err
}