reflink_copy_linux.go 944 B

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253
  1. package docker
  2. // FIXME: This could be easily rewritten in pure Go
  3. /*
  4. #include <sys/ioctl.h>
  5. #include <linux/fs.h>
  6. #include <errno.h>
  7. // See linux.git/fs/btrfs/ioctl.h
  8. #define BTRFS_IOCTL_MAGIC 0x94
  9. #define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int)
  10. int
  11. btrfs_reflink(int fd_out, int fd_in)
  12. {
  13. int res;
  14. res = ioctl(fd_out, BTRFS_IOC_CLONE, fd_in);
  15. if (res < 0)
  16. return errno;
  17. return 0;
  18. }
  19. */
  20. import "C"
  21. import (
  22. "io"
  23. "os"
  24. "syscall"
  25. )
  26. // FIXME: Move this to btrfs package?
  27. func BtrfsReflink(fd_out, fd_in uintptr) error {
  28. res := C.btrfs_reflink(C.int(fd_out), C.int(fd_in))
  29. if res != 0 {
  30. return syscall.Errno(res)
  31. }
  32. return nil
  33. }
  34. func CopyFile(dstFile, srcFile *os.File) error {
  35. err := BtrfsReflink(dstFile.Fd(), srcFile.Fd())
  36. if err == nil {
  37. return nil
  38. }
  39. // Fall back to normal copy
  40. // FIXME: Check the return of Copy and compare with dstFile.Stat().Size
  41. _, err = io.Copy(dstFile, srcFile)
  42. return err
  43. }