unix: avoid __getdirentries64 on darwin

Getdirentries is implemented with the __getdirentries64 function
in libSystem.dylib on darwin/{386,amd64}. That function can't be used in
an app store application.

Implement Getdirentries using the underlying
fdopendir/readdir_r/closedir for Go 1.13. The simulation isn't faithful,
and could be slow, but it should handle common cases.

For Go 1.12, fall back to raw syscalls since syscall.syscallPtr needed
to use fdopendir from libSystem.dylib is not available.

Follow CL 168479 and CL 170892 which did the same for syscall in the
stdlib.

Tested on darwin/amd64 with Go 1.11, Go 1.12 and Go 1.13

Fixes golang/go#34400

Change-Id: I631382aaea9ee7e0c4ed09e06ad5427efc620769
Reviewed-on: https://go-review.googlesource.com/c/sys/+/196478
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/unix/darwin_test.go b/unix/darwin_test.go
index 29af36f..659ad21 100644
--- a/unix/darwin_test.go
+++ b/unix/darwin_test.go
@@ -139,7 +139,6 @@
 	{"fstatfs64", libc_fstatfs64_trampoline},
 	{"fsync", libc_fsync_trampoline},
 	{"ftruncate", libc_ftruncate_trampoline},
-	{"__getdirentries64", libc___getdirentries64_trampoline},
 	{"getdtablesize", libc_getdtablesize_trampoline},
 	{"getegid", libc_getegid_trampoline},
 	{"geteuid", libc_geteuid_trampoline},
diff --git a/unix/mkall.sh b/unix/mkall.sh
index 5a22eca..890ec46 100755
--- a/unix/mkall.sh
+++ b/unix/mkall.sh
@@ -212,9 +212,11 @@
 				echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in && gofmt -w zsyscall_$GOOSARCH.go && gofmt -w zsyscall_"$GOOSARCH"_gccgo.go && gofmt -w zsyscall_"$GOOSARCH"_gc.go " ;
 			elif [ "$GOOS" == "darwin" ]; then
 			        # pre-1.12, direct syscalls
-			        echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
+			        echo "$mksyscall -tags $GOOS,$GOARCH,!go1.12 $syscall_goos syscall_darwin_${GOARCH}.1_11.go $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.1_11.go";
 			        # 1.12 and later, syscalls via libSystem
 				echo "$mksyscall -tags $GOOS,$GOARCH,go1.12 $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
+				# 1.13 and later, syscalls via libSystem (including syscallPtr)
+				echo "$mksyscall -tags $GOOS,$GOARCH,go1.13 syscall_darwin.1_13.go |gofmt >zsyscall_$GOOSARCH.1_13.go";
 			else
 				echo "$mksyscall -tags $GOOS,$GOARCH $syscall_goos $GOOSARCH_in |gofmt >zsyscall_$GOOSARCH.go";
 			fi
diff --git a/unix/mkasm_darwin.go b/unix/mkasm_darwin.go
index 4548b99..6f7bb6e 100644
--- a/unix/mkasm_darwin.go
+++ b/unix/mkasm_darwin.go
@@ -17,6 +17,34 @@
 	"strings"
 )
 
+func writeASMFile(in string, fileName string, buildTags string) {
+	trampolines := map[string]bool{}
+
+	var out bytes.Buffer
+
+	fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
+	fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
+	fmt.Fprintf(&out, "\n")
+	fmt.Fprintf(&out, "// +build %s\n", buildTags)
+	fmt.Fprintf(&out, "\n")
+	fmt.Fprintf(&out, "#include \"textflag.h\"\n")
+	for _, line := range strings.Split(in, "\n") {
+		if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
+			continue
+		}
+		fn := line[5 : len(line)-13]
+		if !trampolines[fn] {
+			trampolines[fn] = true
+			fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
+			fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
+		}
+	}
+	err := ioutil.WriteFile(fileName, out.Bytes(), 0644)
+	if err != nil {
+		log.Fatalf("can't write %s: %s", fileName, err)
+	}
+}
+
 func main() {
 	in1, err := ioutil.ReadFile("syscall_darwin.go")
 	if err != nil {
@@ -33,29 +61,18 @@
 	}
 	in := string(in1) + string(in2) + string(in3)
 
-	trampolines := map[string]bool{}
+	writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.s", arch), "go1.12")
 
-	var out bytes.Buffer
-
-	fmt.Fprintf(&out, "// go run mkasm_darwin.go %s\n", strings.Join(os.Args[1:], " "))
-	fmt.Fprintf(&out, "// Code generated by the command above; DO NOT EDIT.\n")
-	fmt.Fprintf(&out, "\n")
-	fmt.Fprintf(&out, "// +build go1.12\n")
-	fmt.Fprintf(&out, "\n")
-	fmt.Fprintf(&out, "#include \"textflag.h\"\n")
-	for _, line := range strings.Split(in, "\n") {
-		if !strings.HasPrefix(line, "func ") || !strings.HasSuffix(line, "_trampoline()") {
-			continue
-		}
-		fn := line[5 : len(line)-13]
-		if !trampolines[fn] {
-			trampolines[fn] = true
-			fmt.Fprintf(&out, "TEXT ·%s_trampoline(SB),NOSPLIT,$0-0\n", fn)
-			fmt.Fprintf(&out, "\tJMP\t%s(SB)\n", fn)
-		}
-	}
-	err = ioutil.WriteFile(fmt.Sprintf("zsyscall_darwin_%s.s", arch), out.Bytes(), 0644)
+	in1, err = ioutil.ReadFile("syscall_darwin.1_13.go")
 	if err != nil {
-		log.Fatalf("can't write zsyscall_darwin_%s.s: %s", arch, err)
+		log.Fatalf("can't open syscall_darwin.1_13.go: %s", err)
 	}
+	in2, err = ioutil.ReadFile(fmt.Sprintf("zsyscall_darwin_%s.1_13.go", arch))
+	if err != nil {
+		log.Fatalf("can't open zsyscall_darwin_%s.1_13.go: %s", arch, err)
+	}
+
+	in = string(in1) + string(in2)
+
+	writeASMFile(in, fmt.Sprintf("zsyscall_darwin_%s.1_13.s", arch), "go1.13")
 }
diff --git a/unix/mksyscall.go b/unix/mksyscall.go
index e4af942..9e540cc 100644
--- a/unix/mksyscall.go
+++ b/unix/mksyscall.go
@@ -121,7 +121,7 @@
 	}
 
 	libc := false
-	if goos == "darwin" && strings.Contains(buildTags(), ",go1.12") {
+	if goos == "darwin" && (strings.Contains(buildTags(), ",go1.12") || strings.Contains(buildTags(), ",go1.13")) {
 		libc = true
 	}
 	trampolines := map[string]bool{}
@@ -292,11 +292,6 @@
 				asm = "syscall_" + strings.ToLower(asm[:1]) + asm[1:] // internal syscall call
 				sysname = strings.TrimPrefix(sysname, "SYS_")         // remove SYS_
 				sysname = strings.ToLower(sysname)                    // lowercase
-				if sysname == "getdirentries64" {
-					// Special case - libSystem name and
-					// raw syscall name don't match.
-					sysname = "__getdirentries64"
-				}
 				libcFn = sysname
 				sysname = "funcPC(libc_" + sysname + "_trampoline)"
 			}
diff --git a/unix/syscall_darwin.1_12.go b/unix/syscall_darwin.1_12.go
new file mode 100644
index 0000000..6a15cba
--- /dev/null
+++ b/unix/syscall_darwin.1_12.go
@@ -0,0 +1,29 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin,go1.12,!go1.13
+
+package unix
+
+import (
+	"unsafe"
+)
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	// To implement this using libSystem we'd need syscall_syscallPtr for
+	// fdopendir. However, syscallPtr was only added in Go 1.13, so we fall
+	// back to raw syscalls for this func on Go 1.12.
+	var p unsafe.Pointer
+	if len(buf) > 0 {
+		p = unsafe.Pointer(&buf[0])
+	} else {
+		p = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(p), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		return n, errnoErr(e1)
+	}
+	return n, nil
+}
diff --git a/unix/syscall_darwin.1_13.go b/unix/syscall_darwin.1_13.go
new file mode 100644
index 0000000..24960c3
--- /dev/null
+++ b/unix/syscall_darwin.1_13.go
@@ -0,0 +1,103 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin,go1.13
+
+package unix
+
+import "unsafe"
+
+//sys	closedir(dir uintptr) (err error)
+//sys	readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno)
+
+func fdopendir(fd int) (dir uintptr, err error) {
+	r0, _, e1 := syscall_syscallPtr(funcPC(libc_fdopendir_trampoline), uintptr(fd), 0, 0)
+	dir = uintptr(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_fdopendir_trampoline()
+
+//go:linkname libc_fdopendir libc_fdopendir
+//go:cgo_import_dynamic libc_fdopendir fdopendir "/usr/lib/libSystem.B.dylib"
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	// Simulate Getdirentries using fdopendir/readdir_r/closedir.
+	const ptrSize = unsafe.Sizeof(uintptr(0))
+
+	// We store the number of entries to skip in the seek
+	// offset of fd. See issue #31368.
+	// It's not the full required semantics, but should handle the case
+	// of calling Getdirentries or ReadDirent repeatedly.
+	// It won't handle assigning the results of lseek to *basep, or handle
+	// the directory being edited underfoot.
+	skip, err := Seek(fd, 0, 1 /* SEEK_CUR */)
+	if err != nil {
+		return 0, err
+	}
+
+	// We need to duplicate the incoming file descriptor
+	// because the caller expects to retain control of it, but
+	// fdopendir expects to take control of its argument.
+	// Just Dup'ing the file descriptor is not enough, as the
+	// result shares underlying state. Use Openat to make a really
+	// new file descriptor referring to the same directory.
+	fd2, err := Openat(fd, ".", O_RDONLY, 0)
+	if err != nil {
+		return 0, err
+	}
+	d, err := fdopendir(fd2)
+	if err != nil {
+		Close(fd2)
+		return 0, err
+	}
+	defer closedir(d)
+
+	var cnt int64
+	for {
+		var entry Dirent
+		var entryp *Dirent
+		e := readdir_r(d, &entry, &entryp)
+		if e != 0 {
+			return n, errnoErr(e)
+		}
+		if entryp == nil {
+			break
+		}
+		if skip > 0 {
+			skip--
+			cnt++
+			continue
+		}
+		reclen := int(entry.Reclen)
+		if reclen > len(buf) {
+			// Not enough room. Return for now.
+			// The counter will let us know where we should start up again.
+			// Note: this strategy for suspending in the middle and
+			// restarting is O(n^2) in the length of the directory. Oh well.
+			break
+		}
+		// Copy entry into return buffer.
+		s := struct {
+			ptr unsafe.Pointer
+			siz int
+			cap int
+		}{ptr: unsafe.Pointer(&entry), siz: reclen, cap: reclen}
+		copy(buf, *(*[]byte)(unsafe.Pointer(&s)))
+		buf = buf[reclen:]
+		n += reclen
+		cnt++
+	}
+	// Set the seek offset of the input fd to record
+	// how many files we've already returned.
+	_, err = Seek(fd, cnt, 0 /* SEEK_SET */)
+	if err != nil {
+		return n, err
+	}
+
+	return n, nil
+}
diff --git a/unix/syscall_darwin_386.1_11.go b/unix/syscall_darwin_386.1_11.go
new file mode 100644
index 0000000..6b223f9
--- /dev/null
+++ b/unix/syscall_darwin_386.1_11.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin,386,!go1.12
+
+package unix
+
+//sys  Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
diff --git a/unix/syscall_darwin_386.go b/unix/syscall_darwin_386.go
index cf1bec6..dd756e7 100644
--- a/unix/syscall_darwin_386.go
+++ b/unix/syscall_darwin_386.go
@@ -63,7 +63,6 @@
 //sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
 //sys	Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
 //sys	Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
-//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
 //sys	getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
 //sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
 //sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
diff --git a/unix/syscall_darwin_amd64.1_11.go b/unix/syscall_darwin_amd64.1_11.go
new file mode 100644
index 0000000..68ebd6f
--- /dev/null
+++ b/unix/syscall_darwin_amd64.1_11.go
@@ -0,0 +1,9 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin,amd64,!go1.12
+
+package unix
+
+//sys  Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
diff --git a/unix/syscall_darwin_amd64.go b/unix/syscall_darwin_amd64.go
index 5867ed0..7f148c4 100644
--- a/unix/syscall_darwin_amd64.go
+++ b/unix/syscall_darwin_amd64.go
@@ -63,7 +63,6 @@
 //sys	Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
 //sys	Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) = SYS_FSTATAT64
 //sys	Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
-//sys	Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
 //sys	getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) = SYS_GETFSSTAT64
 //sys	Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
 //sys	Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
diff --git a/unix/syscall_darwin_arm.1_11.go b/unix/syscall_darwin_arm.1_11.go
new file mode 100644
index 0000000..c81510d
--- /dev/null
+++ b/unix/syscall_darwin_arm.1_11.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin,386,!go1.12
+
+package unix
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	return 0, ENOSYS
+}
diff --git a/unix/syscall_darwin_arm.go b/unix/syscall_darwin_arm.go
index e199e12..58be02e 100644
--- a/unix/syscall_darwin_arm.go
+++ b/unix/syscall_darwin_arm.go
@@ -70,7 +70,3 @@
 //sys	Lstat(path string, stat *Stat_t) (err error)
 //sys	Stat(path string, stat *Stat_t) (err error)
 //sys	Statfs(path string, stat *Statfs_t) (err error)
-
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
-	return 0, ENOSYS
-}
diff --git a/unix/syscall_darwin_arm64.1_11.go b/unix/syscall_darwin_arm64.1_11.go
new file mode 100644
index 0000000..01d4504
--- /dev/null
+++ b/unix/syscall_darwin_arm64.1_11.go
@@ -0,0 +1,11 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build darwin,arm64,!go1.12
+
+package unix
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	return 0, ENOSYS
+}
diff --git a/unix/syscall_darwin_arm64.go b/unix/syscall_darwin_arm64.go
index 2c50ca9..1ee931f 100644
--- a/unix/syscall_darwin_arm64.go
+++ b/unix/syscall_darwin_arm64.go
@@ -72,7 +72,3 @@
 //sys	Lstat(path string, stat *Stat_t) (err error)
 //sys	Stat(path string, stat *Stat_t) (err error)
 //sys	Statfs(path string, stat *Statfs_t) (err error)
-
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
-	return 0, ENOSYS
-}
diff --git a/unix/syscall_darwin_libSystem.go b/unix/syscall_darwin_libSystem.go
index 4b4ae46..f34c86c 100644
--- a/unix/syscall_darwin_libSystem.go
+++ b/unix/syscall_darwin_libSystem.go
@@ -15,6 +15,7 @@
 func syscall_syscall9(fn, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err Errno) // 32-bit only
 func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
 func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
+func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
 
 //go:linkname syscall_syscall syscall.syscall
 //go:linkname syscall_syscall6 syscall.syscall6
@@ -22,6 +23,7 @@
 //go:linkname syscall_syscall9 syscall.syscall9
 //go:linkname syscall_rawSyscall syscall.rawSyscall
 //go:linkname syscall_rawSyscall6 syscall.rawSyscall6
+//go:linkname syscall_syscallPtr syscall.syscallPtr
 
 // Find the entry point for f. See comments in runtime/proc.go for the
 // function of the same name.
diff --git a/unix/zsyscall_darwin_386.1_11.go b/unix/zsyscall_darwin_386.1_11.go
index a7cd331..b42c1cb 100644
--- a/unix/zsyscall_darwin_386.1_11.go
+++ b/unix/zsyscall_darwin_386.1_11.go
@@ -1,4 +1,4 @@
-// go run mksyscall.go -l32 -tags darwin,386,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_386.go
+// go run mksyscall.go -l32 -tags darwin,386,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_386.1_11.go syscall_darwin_386.go
 // Code generated by the command above; see README.md. DO NOT EDIT.
 
 // +build darwin,386,!go1.12
@@ -1666,6 +1666,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
@@ -1739,23 +1756,6 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
-	var _p0 unsafe.Pointer
-	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
-	} else {
-		_p0 = unsafe.Pointer(&_zero)
-	}
-	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
-	n = int(r0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(buf), uintptr(size), uintptr(flags))
 	n = int(r0)
diff --git a/unix/zsyscall_darwin_386.1_13.go b/unix/zsyscall_darwin_386.1_13.go
new file mode 100644
index 0000000..e263fbd
--- /dev/null
+++ b/unix/zsyscall_darwin_386.1_13.go
@@ -0,0 +1,41 @@
+// go run mksyscall.go -l32 -tags darwin,386,go1.13 syscall_darwin.1_13.go
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build darwin,386,go1.13
+
+package unix
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+var _ syscall.Errno
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func closedir(dir uintptr) (err error) {
+	_, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_closedir_trampoline()
+
+//go:linkname libc_closedir libc_closedir
+//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
+	r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
+	res = Errno(r0)
+	return
+}
+
+func libc_readdir_r_trampoline()
+
+//go:linkname libc_readdir_r libc_readdir_r
+//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/unix/zsyscall_darwin_386.1_13.s b/unix/zsyscall_darwin_386.1_13.s
new file mode 100644
index 0000000..00da1eb
--- /dev/null
+++ b/unix/zsyscall_darwin_386.1_13.s
@@ -0,0 +1,12 @@
+// go run mkasm_darwin.go 386
+// Code generated by the command above; DO NOT EDIT.
+
+// +build go1.13
+
+#include "textflag.h"
+TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fdopendir(SB)
+TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_closedir(SB)
+TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_readdir_r(SB)
diff --git a/unix/zsyscall_darwin_386.go b/unix/zsyscall_darwin_386.go
index 336212e..603c9f6 100644
--- a/unix/zsyscall_darwin_386.go
+++ b/unix/zsyscall_darwin_386.go
@@ -2424,28 +2424,6 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
-	var _p0 unsafe.Pointer
-	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
-	} else {
-		_p0 = unsafe.Pointer(&_zero)
-	}
-	r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
-	n = int(r0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-func libc___getdirentries64_trampoline()
-
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
 	r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags))
 	n = int(r0)
diff --git a/unix/zsyscall_darwin_386.s b/unix/zsyscall_darwin_386.s
index c6557b1..ece6f67 100644
--- a/unix/zsyscall_darwin_386.s
+++ b/unix/zsyscall_darwin_386.s
@@ -274,8 +274,6 @@
 	JMP	libc_fstatat64(SB)
 TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc___getdirentries64(SB)
 TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getfsstat64(SB)
 TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/unix/zsyscall_darwin_amd64.1_11.go b/unix/zsyscall_darwin_amd64.1_11.go
index 0cba171..38b7cba 100644
--- a/unix/zsyscall_darwin_amd64.1_11.go
+++ b/unix/zsyscall_darwin_amd64.1_11.go
@@ -1,4 +1,4 @@
-// go run mksyscall.go -tags darwin,amd64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_amd64.go
+// go run mksyscall.go -tags darwin,amd64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_amd64.1_11.go syscall_darwin_amd64.go
 // Code generated by the command above; see README.md. DO NOT EDIT.
 
 // +build darwin,amd64,!go1.12
@@ -1666,6 +1666,23 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	var _p0 unsafe.Pointer
+	if len(buf) > 0 {
+		_p0 = unsafe.Pointer(&buf[0])
+	} else {
+		_p0 = unsafe.Pointer(&_zero)
+	}
+	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
 	var _p0 unsafe.Pointer
 	if len(mib) > 0 {
@@ -1739,23 +1756,6 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
-	var _p0 unsafe.Pointer
-	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
-	} else {
-		_p0 = unsafe.Pointer(&_zero)
-	}
-	r0, _, e1 := Syscall6(SYS_GETDIRENTRIES64, uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
-	n = int(r0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
 	r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(buf), uintptr(size), uintptr(flags))
 	n = int(r0)
diff --git a/unix/zsyscall_darwin_amd64.1_13.go b/unix/zsyscall_darwin_amd64.1_13.go
new file mode 100644
index 0000000..314042a
--- /dev/null
+++ b/unix/zsyscall_darwin_amd64.1_13.go
@@ -0,0 +1,41 @@
+// go run mksyscall.go -tags darwin,amd64,go1.13 syscall_darwin.1_13.go
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build darwin,amd64,go1.13
+
+package unix
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+var _ syscall.Errno
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func closedir(dir uintptr) (err error) {
+	_, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_closedir_trampoline()
+
+//go:linkname libc_closedir libc_closedir
+//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
+	r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
+	res = Errno(r0)
+	return
+}
+
+func libc_readdir_r_trampoline()
+
+//go:linkname libc_readdir_r libc_readdir_r
+//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/unix/zsyscall_darwin_amd64.1_13.s b/unix/zsyscall_darwin_amd64.1_13.s
new file mode 100644
index 0000000..d671e83
--- /dev/null
+++ b/unix/zsyscall_darwin_amd64.1_13.s
@@ -0,0 +1,12 @@
+// go run mkasm_darwin.go amd64
+// Code generated by the command above; DO NOT EDIT.
+
+// +build go1.13
+
+#include "textflag.h"
+TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fdopendir(SB)
+TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_closedir(SB)
+TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_readdir_r(SB)
diff --git a/unix/zsyscall_darwin_amd64.go b/unix/zsyscall_darwin_amd64.go
index b44f628..fda478e 100644
--- a/unix/zsyscall_darwin_amd64.go
+++ b/unix/zsyscall_darwin_amd64.go
@@ -2424,28 +2424,6 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
-	var _p0 unsafe.Pointer
-	if len(buf) > 0 {
-		_p0 = unsafe.Pointer(&buf[0])
-	} else {
-		_p0 = unsafe.Pointer(&_zero)
-	}
-	r0, _, e1 := syscall_syscall6(funcPC(libc___getdirentries64_trampoline), uintptr(fd), uintptr(_p0), uintptr(len(buf)), uintptr(unsafe.Pointer(basep)), 0, 0)
-	n = int(r0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-func libc___getdirentries64_trampoline()
-
-//go:linkname libc___getdirentries64 libc___getdirentries64
-//go:cgo_import_dynamic libc___getdirentries64 __getdirentries64 "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func getfsstat(buf unsafe.Pointer, size uintptr, flags int) (n int, err error) {
 	r0, _, e1 := syscall_syscall(funcPC(libc_getfsstat64_trampoline), uintptr(buf), uintptr(size), uintptr(flags))
 	n = int(r0)
diff --git a/unix/zsyscall_darwin_amd64.s b/unix/zsyscall_darwin_amd64.s
index ad410cf..7c4d590 100644
--- a/unix/zsyscall_darwin_amd64.s
+++ b/unix/zsyscall_darwin_amd64.s
@@ -274,8 +274,6 @@
 	JMP	libc_fstatat64(SB)
 TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstatfs64(SB)
-TEXT ·libc___getdirentries64_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc___getdirentries64(SB)
 TEXT ·libc_getfsstat64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getfsstat64(SB)
 TEXT ·libc_lstat64_trampoline(SB),NOSPLIT,$0-0
diff --git a/unix/zsyscall_darwin_arm.1_11.go b/unix/zsyscall_darwin_arm.1_11.go
index d646e6a..abb6918 100644
--- a/unix/zsyscall_darwin_arm.1_11.go
+++ b/unix/zsyscall_darwin_arm.1_11.go
@@ -1,4 +1,4 @@
-// go run mksyscall.go -l32 -tags darwin,arm,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm.go
+// go run mksyscall.go -l32 -tags darwin,arm,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm.1_11.go syscall_darwin_arm.go
 // Code generated by the command above; see README.md. DO NOT EDIT.
 
 // +build darwin,arm,!go1.12
diff --git a/unix/zsyscall_darwin_arm.1_13.go b/unix/zsyscall_darwin_arm.1_13.go
new file mode 100644
index 0000000..f519ce9
--- /dev/null
+++ b/unix/zsyscall_darwin_arm.1_13.go
@@ -0,0 +1,41 @@
+// go run mksyscall.go -l32 -tags darwin,arm,go1.13 syscall_darwin.1_13.go
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build darwin,arm,go1.13
+
+package unix
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+var _ syscall.Errno
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func closedir(dir uintptr) (err error) {
+	_, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_closedir_trampoline()
+
+//go:linkname libc_closedir libc_closedir
+//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
+	r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
+	res = Errno(r0)
+	return
+}
+
+func libc_readdir_r_trampoline()
+
+//go:linkname libc_readdir_r libc_readdir_r
+//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/unix/zsyscall_darwin_arm.1_13.s b/unix/zsyscall_darwin_arm.1_13.s
new file mode 100644
index 0000000..488e557
--- /dev/null
+++ b/unix/zsyscall_darwin_arm.1_13.s
@@ -0,0 +1,12 @@
+// go run mkasm_darwin.go arm
+// Code generated by the command above; DO NOT EDIT.
+
+// +build go1.13
+
+#include "textflag.h"
+TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fdopendir(SB)
+TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_closedir(SB)
+TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_readdir_r(SB)
diff --git a/unix/zsyscall_darwin_arm.s b/unix/zsyscall_darwin_arm.s
index 66af9f4..5bebb1b 100644
--- a/unix/zsyscall_darwin_arm.s
+++ b/unix/zsyscall_darwin_arm.s
@@ -40,8 +40,6 @@
 	JMP	libc_sendmsg(SB)
 TEXT ·libc_kevent_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_kevent(SB)
-TEXT ·libc___sysctl_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc___sysctl(SB)
 TEXT ·libc_utimes_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_utimes(SB)
 TEXT ·libc_futimes_trampoline(SB),NOSPLIT,$0-0
@@ -106,6 +104,8 @@
 	JMP	libc_chown(SB)
 TEXT ·libc_chroot_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_chroot(SB)
+TEXT ·libc_clock_gettime_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_clock_gettime(SB)
 TEXT ·libc_close_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_close(SB)
 TEXT ·libc_dup_trampoline(SB),NOSPLIT,$0-0
diff --git a/unix/zsyscall_darwin_arm64.1_11.go b/unix/zsyscall_darwin_arm64.1_11.go
index e839262..b75c11d 100644
--- a/unix/zsyscall_darwin_arm64.1_11.go
+++ b/unix/zsyscall_darwin_arm64.1_11.go
@@ -1,4 +1,4 @@
-// go run mksyscall.go -tags darwin,arm64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm64.go
+// go run mksyscall.go -tags darwin,arm64,!go1.12 syscall_bsd.go syscall_darwin.go syscall_darwin_arm64.1_11.go syscall_darwin_arm64.go
 // Code generated by the command above; see README.md. DO NOT EDIT.
 
 // +build darwin,arm64,!go1.12
diff --git a/unix/zsyscall_darwin_arm64.1_13.go b/unix/zsyscall_darwin_arm64.1_13.go
new file mode 100644
index 0000000..d64e6c8
--- /dev/null
+++ b/unix/zsyscall_darwin_arm64.1_13.go
@@ -0,0 +1,41 @@
+// go run mksyscall.go -tags darwin,arm64,go1.13 syscall_darwin.1_13.go
+// Code generated by the command above; see README.md. DO NOT EDIT.
+
+// +build darwin,arm64,go1.13
+
+package unix
+
+import (
+	"syscall"
+	"unsafe"
+)
+
+var _ syscall.Errno
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func closedir(dir uintptr) (err error) {
+	_, _, e1 := syscall_syscall(funcPC(libc_closedir_trampoline), uintptr(dir), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_closedir_trampoline()
+
+//go:linkname libc_closedir libc_closedir
+//go:cgo_import_dynamic libc_closedir closedir "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func readdir_r(dir uintptr, entry *Dirent, result **Dirent) (res Errno) {
+	r0, _, _ := syscall_syscall(funcPC(libc_readdir_r_trampoline), uintptr(dir), uintptr(unsafe.Pointer(entry)), uintptr(unsafe.Pointer(result)))
+	res = Errno(r0)
+	return
+}
+
+func libc_readdir_r_trampoline()
+
+//go:linkname libc_readdir_r libc_readdir_r
+//go:cgo_import_dynamic libc_readdir_r readdir_r "/usr/lib/libSystem.B.dylib"
diff --git a/unix/zsyscall_darwin_arm64.1_13.s b/unix/zsyscall_darwin_arm64.1_13.s
new file mode 100644
index 0000000..b29dabb
--- /dev/null
+++ b/unix/zsyscall_darwin_arm64.1_13.s
@@ -0,0 +1,12 @@
+// go run mkasm_darwin.go arm64
+// Code generated by the command above; DO NOT EDIT.
+
+// +build go1.13
+
+#include "textflag.h"
+TEXT ·libc_fdopendir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_fdopendir(SB)
+TEXT ·libc_closedir_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_closedir(SB)
+TEXT ·libc_readdir_r_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_readdir_r(SB)