//!build +unix

package cowutils

import (
	"errors"
	"os"

	"golang.org/x/sys/unix"
)

// reflink performs the actual reflink action without worrying about fallback
func reflink(dst, src *os.File) error {
	srcFd := int(src.Fd())
	dstFd := int(dst.Fd())

	err := unix.IoctlFileClone(dstFd, srcFd)

	if err != nil && errors.Is(err, unix.ENOTSUP) {
		return ErrNotSupported
	}

	return err
}

func reflinkRange(dst, src *os.File, dstOffset, srcOffset, n int64) error {
	srcFd := int(src.Fd())
	dstFd := int(dst.Fd())

	req := &unix.FileCloneRange{
		Src_fd:      int64(srcFd),
		Src_offset:  uint64(srcOffset),
		Src_length:  uint64(n),
		Dest_offset: uint64(dstOffset),
	}

	err := unix.IoctlFileCloneRange(dstFd, req)
	if err != nil && errors.Is(err, unix.ENOTSUP) {
		return ErrNotSupported
	}

	return err
}

func copyFileRange(dst, src *os.File, dstOffset, srcOffset, n int64) (int64, error) {
	srcFd := int(src.Fd())
	dstFd := int(dst.Fd())

	resN, err := unix.CopyFileRange(srcFd, &srcOffset, dstFd, &dstOffset, int(n), 0)

	return int64(resN), err

}