unix: add Darwin support for clonefile syscalls

This commit adds support for three Darwin-specific calls that accelerate
the copying of files:

* clonefile()
* clonefileat()
* fclonefileat()

Fixes golang/go#41366

Change-Id: I7e6c525fc23d8474ea85feff24314d3d672d87ed
Reviewed-on: https://go-review.googlesource.com/c/sys/+/254757
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Tobias Klauser <tobias.klauser@gmail.com>
diff --git a/unix/syscall_darwin.go b/unix/syscall_darwin.go
index e2a05ee..eddcf3a 100644
--- a/unix/syscall_darwin.go
+++ b/unix/syscall_darwin.go
@@ -401,6 +401,8 @@
 //sys	Chroot(path string) (err error)
 //sys	ClockGettime(clockid int32, time *Timespec) (err error)
 //sys	Close(fd int) (err error)
+//sys	Clonefile(src string, dst string, flags int) (err error)
+//sys	Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error)
 //sys	Dup(fd int) (nfd int, err error)
 //sys	Dup2(from int, to int) (err error)
 //sys	Exchangedata(path1 string, path2 string, options int) (err error)
@@ -412,6 +414,7 @@
 //sys	Fchmodat(dirfd int, path string, mode uint32, flags int) (err error)
 //sys	Fchown(fd int, uid int, gid int) (err error)
 //sys	Fchownat(dirfd int, path string, uid int, gid int, flags int) (err error)
+//sys	Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error)
 //sys	Flock(fd int, how int) (err error)
 //sys	Fpathconf(fd int, name int) (val int, err error)
 //sys	Fsync(fd int) (err error)
diff --git a/unix/syscall_darwin_test.go b/unix/syscall_darwin_test.go
index 65691d5..149992c 100644
--- a/unix/syscall_darwin_test.go
+++ b/unix/syscall_darwin_test.go
@@ -4,6 +4,18 @@
 
 package unix_test
 
+import (
+	"bytes"
+	"io/ioutil"
+	"os"
+	"path"
+	"testing"
+
+	"golang.org/x/sys/unix"
+)
+
+var testData = []byte("This is a test\n")
+
 // stringsFromByteSlice converts a sequence of attributes to a []string.
 // On Darwin, each entry is a NULL-terminated string.
 func stringsFromByteSlice(buf []byte) []string {
@@ -17,3 +29,152 @@
 	}
 	return result
 }
+
+func createTestFile(t *testing.T, dir string) (f *os.File, cleanup func() error) {
+	file, err := ioutil.TempFile(dir, "TestClonefile")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	_, err = file.Write(testData)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = file.Close()
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	return file, func() error {
+		return os.Remove(file.Name())
+	}
+}
+
+func TestClonefile(t *testing.T) {
+	file, cleanup := createTestFile(t, "")
+	defer cleanup()
+
+	clonedName := file.Name() + "-cloned"
+	err := unix.Clonefile(file.Name(), clonedName, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Remove(clonedName)
+
+	clonedData, err := ioutil.ReadFile(clonedName)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !bytes.Equal(testData, clonedData) {
+		t.Errorf("Clonefile: got %q, expected %q", clonedData, testData)
+	}
+}
+
+func TestClonefileatWithCwd(t *testing.T) {
+	file, cleanup := createTestFile(t, "")
+	defer cleanup()
+
+	clonedName := file.Name() + "-cloned"
+	err := unix.Clonefileat(unix.AT_FDCWD, file.Name(), unix.AT_FDCWD, clonedName, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	defer os.Remove(clonedName)
+
+	clonedData, err := ioutil.ReadFile(clonedName)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !bytes.Equal(testData, clonedData) {
+		t.Errorf("Clonefileat: got %q, expected %q", clonedData, testData)
+	}
+}
+
+func TestClonefileatWithRelativePaths(t *testing.T) {
+	srcDir, err := ioutil.TempDir("", "src")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(srcDir)
+
+	dstDir, err := ioutil.TempDir("", "dest")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.RemoveAll(dstDir)
+
+	srcFd, err := unix.Open(srcDir, unix.O_RDONLY|unix.O_DIRECTORY, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer unix.Close(srcFd)
+
+	dstFd, err := unix.Open(dstDir, unix.O_RDONLY|unix.O_DIRECTORY, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer unix.Close(dstFd)
+
+	srcFile, cleanup := createTestFile(t, srcDir)
+	defer cleanup()
+
+	dstFile, err := ioutil.TempFile(dstDir, "TestClonefileat")
+	if err != nil {
+		t.Fatal(err)
+	}
+	err = os.Remove(dstFile.Name())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	src := path.Base(srcFile.Name())
+	dst := path.Base(dstFile.Name())
+	err = unix.Clonefileat(srcFd, src, dstFd, dst, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	clonedData, err := ioutil.ReadFile(dstFile.Name())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !bytes.Equal(testData, clonedData) {
+		t.Errorf("Clonefileat: got %q, expected %q", clonedData, testData)
+	}
+}
+
+func TestFclonefileat(t *testing.T) {
+	file, cleanup := createTestFile(t, "")
+	defer cleanup()
+
+	fd, err := unix.Open(file.Name(), unix.O_RDONLY, 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer unix.Close(fd)
+
+	dstFile, err := ioutil.TempFile("", "TestFclonefileat")
+	if err != nil {
+		t.Fatal(err)
+	}
+	os.Remove(dstFile.Name())
+
+	err = unix.Fclonefileat(fd, unix.AT_FDCWD, dstFile.Name(), 0)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	clonedData, err := ioutil.ReadFile(dstFile.Name())
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if !bytes.Equal(testData, clonedData) {
+		t.Errorf("Fclonefileat: got %q, expected %q", clonedData, testData)
+	}
+}
diff --git a/unix/zsyscall_darwin_386.go b/unix/zsyscall_darwin_386.go
index e2ffb3b..3976147 100644
--- a/unix/zsyscall_darwin_386.go
+++ b/unix/zsyscall_darwin_386.go
@@ -958,6 +958,56 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Clonefile(src string, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall(funcPC(libc_clonefile_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefile_trampoline()
+
+//go:linkname libc_clonefile libc_clonefile
+//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_clonefileat_trampoline), uintptr(srcDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefileat_trampoline()
+
+//go:linkname libc_clonefileat libc_clonefileat
+//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0)
 	nfd = int(r0)
@@ -1146,6 +1196,26 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_fclonefileat_trampoline), uintptr(srcDirfd), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_fclonefileat_trampoline()
+
+//go:linkname libc_fclonefileat libc_fclonefileat
+//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Flock(fd int, how int) (err error) {
 	_, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0)
 	if e1 != 0 {
diff --git a/unix/zsyscall_darwin_386.s b/unix/zsyscall_darwin_386.s
index 6836a41..961058d 100644
--- a/unix/zsyscall_darwin_386.s
+++ b/unix/zsyscall_darwin_386.s
@@ -110,6 +110,10 @@
 	JMP	libc_clock_gettime(SB)
 TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_close(SB)
+TEXT ·libc_clonefile_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefile(SB)
+TEXT ·libc_clonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefileat(SB)
 TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_dup(SB)
 TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
@@ -132,6 +136,8 @@
 	JMP	libc_fchown(SB)
 TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fchownat(SB)
+TEXT ·libc_fclonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fclonefileat(SB)
 TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_flock(SB)
 TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0
@@ -164,6 +170,8 @@
 	JMP	libc_getrusage(SB)
 TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getsid(SB)
+TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_gettimeofday(SB)
 TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getuid(SB)
 TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0
@@ -266,8 +274,6 @@
 	JMP	libc_munmap(SB)
 TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_ptrace(SB)
-TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_gettimeofday(SB)
 TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat64(SB)
 TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/unix/zsyscall_darwin_amd64.go b/unix/zsyscall_darwin_amd64.go
index c67e336..e253f43 100644
--- a/unix/zsyscall_darwin_amd64.go
+++ b/unix/zsyscall_darwin_amd64.go
@@ -958,6 +958,56 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Clonefile(src string, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall(funcPC(libc_clonefile_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefile_trampoline()
+
+//go:linkname libc_clonefile libc_clonefile
+//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_clonefileat_trampoline), uintptr(srcDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefileat_trampoline()
+
+//go:linkname libc_clonefileat libc_clonefileat
+//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0)
 	nfd = int(r0)
@@ -1146,6 +1196,26 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_fclonefileat_trampoline), uintptr(srcDirfd), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_fclonefileat_trampoline()
+
+//go:linkname libc_fclonefileat libc_fclonefileat
+//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Flock(fd int, how int) (err error) {
 	_, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0)
 	if e1 != 0 {
diff --git a/unix/zsyscall_darwin_amd64.s b/unix/zsyscall_darwin_amd64.s
index a3fdf09..b8be24c 100644
--- a/unix/zsyscall_darwin_amd64.s
+++ b/unix/zsyscall_darwin_amd64.s
@@ -110,6 +110,10 @@
 	JMP	libc_clock_gettime(SB)
 TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_close(SB)
+TEXT ·libc_clonefile_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefile(SB)
+TEXT ·libc_clonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefileat(SB)
 TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_dup(SB)
 TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
@@ -132,6 +136,8 @@
 	JMP	libc_fchown(SB)
 TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fchownat(SB)
+TEXT ·libc_fclonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fclonefileat(SB)
 TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_flock(SB)
 TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0
@@ -164,6 +170,8 @@
 	JMP	libc_getrusage(SB)
 TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getsid(SB)
+TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_gettimeofday(SB)
 TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getuid(SB)
 TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0
@@ -266,8 +274,6 @@
 	JMP	libc_munmap(SB)
 TEXT ·libc_ptrace_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_ptrace(SB)
-TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_gettimeofday(SB)
 TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat64(SB)
 TEXT ·libc_fstatat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/unix/zsyscall_darwin_arm.go b/unix/zsyscall_darwin_arm.go
index b759757..be2e283 100644
--- a/unix/zsyscall_darwin_arm.go
+++ b/unix/zsyscall_darwin_arm.go
@@ -958,6 +958,56 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Clonefile(src string, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall(funcPC(libc_clonefile_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefile_trampoline()
+
+//go:linkname libc_clonefile libc_clonefile
+//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_clonefileat_trampoline), uintptr(srcDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefileat_trampoline()
+
+//go:linkname libc_clonefileat libc_clonefileat
+//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0)
 	nfd = int(r0)
@@ -1146,6 +1196,26 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_fclonefileat_trampoline), uintptr(srcDirfd), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_fclonefileat_trampoline()
+
+//go:linkname libc_fclonefileat libc_fclonefileat
+//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Flock(fd int, how int) (err error) {
 	_, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0)
 	if e1 != 0 {
diff --git a/unix/zsyscall_darwin_arm.s b/unix/zsyscall_darwin_arm.s
index b67f518..403c21f 100644
--- a/unix/zsyscall_darwin_arm.s
+++ b/unix/zsyscall_darwin_arm.s
@@ -110,6 +110,10 @@
 	JMP	libc_clock_gettime(SB)
 TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_close(SB)
+TEXT ·libc_clonefile_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefile(SB)
+TEXT ·libc_clonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefileat(SB)
 TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_dup(SB)
 TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
@@ -132,6 +136,8 @@
 	JMP	libc_fchown(SB)
 TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fchownat(SB)
+TEXT ·libc_fclonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fclonefileat(SB)
 TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_flock(SB)
 TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0
@@ -164,6 +170,8 @@
 	JMP	libc_getrusage(SB)
 TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getsid(SB)
+TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_gettimeofday(SB)
 TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getuid(SB)
 TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0
@@ -264,8 +272,6 @@
 	JMP	libc_mmap(SB)
 TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_munmap(SB)
-TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_gettimeofday(SB)
 TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat(SB)
 TEXT ·libc_fstatat_trampoline(SB),NOSPLIT,$0-0
diff --git a/unix/zsyscall_darwin_arm64.go b/unix/zsyscall_darwin_arm64.go
index b288612..34976a4 100644
--- a/unix/zsyscall_darwin_arm64.go
+++ b/unix/zsyscall_darwin_arm64.go
@@ -958,6 +958,56 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Clonefile(src string, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall(funcPC(libc_clonefile_trampoline), uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flags))
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefile_trampoline()
+
+//go:linkname libc_clonefile libc_clonefile
+//go:cgo_import_dynamic libc_clonefile clonefile "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func Clonefileat(srcDirfd int, src string, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(src)
+	if err != nil {
+		return
+	}
+	var _p1 *byte
+	_p1, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_clonefileat_trampoline), uintptr(srcDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p1)), uintptr(flags), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_clonefileat_trampoline()
+
+//go:linkname libc_clonefileat libc_clonefileat
+//go:cgo_import_dynamic libc_clonefileat clonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Dup(fd int) (nfd int, err error) {
 	r0, _, e1 := syscall_syscall(funcPC(libc_dup_trampoline), uintptr(fd), 0, 0)
 	nfd = int(r0)
@@ -1146,6 +1196,26 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Fclonefileat(srcDirfd int, dstDirfd int, dst string, flags int) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(dst)
+	if err != nil {
+		return
+	}
+	_, _, e1 := syscall_syscall6(funcPC(libc_fclonefileat_trampoline), uintptr(srcDirfd), uintptr(dstDirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_fclonefileat_trampoline()
+
+//go:linkname libc_fclonefileat libc_fclonefileat
+//go:cgo_import_dynamic libc_fclonefileat fclonefileat "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Flock(fd int, how int) (err error) {
 	_, _, e1 := syscall_syscall(funcPC(libc_flock_trampoline), uintptr(fd), uintptr(how), 0)
 	if e1 != 0 {
diff --git a/unix/zsyscall_darwin_arm64.s b/unix/zsyscall_darwin_arm64.s
index 40cce1b..abe7b6e 100644
--- a/unix/zsyscall_darwin_arm64.s
+++ b/unix/zsyscall_darwin_arm64.s
@@ -110,6 +110,10 @@
 	JMP	libc_clock_gettime(SB)
 TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_close(SB)
+TEXT ·libc_clonefile_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefile(SB)
+TEXT ·libc_clonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clonefileat(SB)
 TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_dup(SB)
 TEXT ·libc_dup2_trampoline(SB),NOSPLIT,$0-0
@@ -132,6 +136,8 @@
 	JMP	libc_fchown(SB)
 TEXT ·libc_fchownat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fchownat(SB)
+TEXT ·libc_fclonefileat_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fclonefileat(SB)
 TEXT ·libc_flock_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_flock(SB)
 TEXT ·libc_fpathconf_trampoline(SB),NOSPLIT,$0-0
@@ -164,6 +170,8 @@
 	JMP	libc_getrusage(SB)
 TEXT ·libc_getsid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getsid(SB)
+TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_gettimeofday(SB)
 TEXT ·libc_getuid_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getuid(SB)
 TEXT ·libc_issetugid_trampoline(SB),NOSPLIT,$0-0
@@ -264,8 +272,6 @@
 	JMP	libc_mmap(SB)
 TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_munmap(SB)
-TEXT ·libc_gettimeofday_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_gettimeofday(SB)
 TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat(SB)
 TEXT ·libc_fstatat_trampoline(SB),NOSPLIT,$0-0