diff --git a/btrfs.go b/btrfs.go index 4477f86..b5e8497 100644 --- a/btrfs.go +++ b/btrfs.go @@ -11,6 +11,10 @@ import ( const SuperMagic = 0x9123683E +func CloneFile(dst, src *os.File) error { + return iocClone(dst, src) +} + func Open(path string, ro bool) (*FS, error) { if ok, err := IsSubVolume(path); err != nil { return nil, err diff --git a/btrfs_test.go b/btrfs_test.go index e09abe1..067f4fc 100644 --- a/btrfs_test.go +++ b/btrfs_test.go @@ -2,6 +2,7 @@ package btrfs import ( "github.com/dennwc/btrfs/test" + "io" "os" "path/filepath" "testing" @@ -95,3 +96,41 @@ func TestCompression(t *testing.T) { t.Fatalf("unexpected compression returned: %q", string(c)) } } + +func TestCloneFile(t *testing.T) { + dir, closer := btrfstest.New(t, sizeDef) + defer closer() + + f1, err := os.Create(filepath.Join(dir, "1.dat")) + if err != nil { + t.Fatal(err) + } + defer f1.Close() + + const data = "btrfs_test" + _, err = f1.WriteString(data) + if err != nil { + t.Fatal(err) + } + + f2, err := os.Create(filepath.Join(dir, "2.dat")) + if err != nil { + t.Fatal(err) + } + defer f2.Close() + + err = CloneFile(f2, f1) + if err != nil { + t.Fatal(err) + } + + buf := make([]byte, len(data)) + n, err := f2.Read(buf) + if err != nil && err != io.EOF { + t.Fatal(err) + } + buf = buf[:n] + if string(buf) != data { + t.Fatalf("wrong data returned: %q", string(buf)) + } +} diff --git a/ioctl_h.go b/ioctl_h.go index e460c89..11021c5 100644 --- a/ioctl_h.go +++ b/ioctl_h.go @@ -631,8 +631,8 @@ func iocSync(f *os.File) error { return ioctl.Do(f, _BTRFS_IOC_SYNC, nil) } -func iocClone(f *os.File, out *int32) error { - return ioctl.Do(f, _BTRFS_IOC_CLONE, out) +func iocClone(dst, src *os.File) error { + return ioctl.Ioctl(dst, _BTRFS_IOC_CLONE, src.Fd()) } func iocAddDev(f *os.File, out *btrfs_ioctl_vol_args) error {