From 7d3fd4f3c46e57c703128bbabb385424f338d6d9 Mon Sep 17 00:00:00 2001
From: Tobias Klauser <tklauser@distanz.ch>
Date: Fri, 25 Sep 2020 18:06:26 +0200
Subject: [PATCH] syscall: implement Getwd using getcwd from libSystem on
 darwin

Directly wrap the getcwd implementation provided by libSystem.dylib on
darwin and use it to implement Getwd like on the BSDs. This allows to
drop the custom implementation using getAttrList and to merge the
implementation of Getwd for darwin and the BSDs in syscall_bsd.go.

Same as CL 257497 did for golang.org/x/sys/unix

Change-Id: If30390c4c17cd463bb8fdcb5465f40d6fa11f391
Reviewed-on: https://go-review.googlesource.com/c/go/+/257637
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
---
 src/syscall/syscall_bsd.go           | 15 +++++
 src/syscall/syscall_darwin.go        | 85 +---------------------------
 src/syscall/syscall_getwd_bsd.go     | 22 -------
 src/syscall/types_darwin.go          |  6 ++
 src/syscall/zsyscall_darwin_amd64.go | 22 +++++++
 src/syscall/zsyscall_darwin_amd64.s  |  4 +-
 src/syscall/zsyscall_darwin_arm64.go | 22 +++++++
 src/syscall/zsyscall_darwin_arm64.s  |  4 +-
 src/syscall/ztypes_darwin_amd64.go   |  4 ++
 src/syscall/ztypes_darwin_arm64.go   |  4 ++
 10 files changed, 79 insertions(+), 109 deletions(-)
 delete mode 100644 src/syscall/syscall_getwd_bsd.go

diff --git a/src/syscall/syscall_bsd.go b/src/syscall/syscall_bsd.go
index b52de7450ff..1c7ec588bcf 100644
--- a/src/syscall/syscall_bsd.go
+++ b/src/syscall/syscall_bsd.go
@@ -17,6 +17,21 @@ import (
 	"unsafe"
 )
 
+const ImplementsGetwd = true
+
+func Getwd() (string, error) {
+	var buf [pathMax]byte
+	_, err := getcwd(buf[:])
+	if err != nil {
+		return "", err
+	}
+	n := clen(buf[:])
+	if n < 1 {
+		return "", EINVAL
+	}
+	return string(buf[:n]), nil
+}
+
 /*
  * Wrapped
  */
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index c84547c628c..afdadbf8946 100644
--- a/src/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -12,28 +12,7 @@
 
 package syscall
 
-import (
-	errorspkg "errors"
-	"unsafe"
-)
-
-const ImplementsGetwd = true
-
-func Getwd() (string, error) {
-	buf := make([]byte, 2048)
-	attrs, err := getAttrList(".", attrList{CommonAttr: attrCmnFullpath}, buf, 0)
-	if err == nil && len(attrs) == 1 && len(attrs[0]) >= 2 {
-		wd := string(attrs[0])
-		// Sanity check that it's an absolute path and ends
-		// in a null byte, which we then strip.
-		if wd[0] == '/' && wd[len(wd)-1] == 0 {
-			return wd[:len(wd)-1], nil
-		}
-	}
-	// If pkg/os/getwd.go gets ENOTSUP, it will fall back to the
-	// slow algorithm.
-	return "", ENOTSUP
-}
+import "unsafe"
 
 type SockaddrDatalink struct {
 	Len    uint8
@@ -94,7 +73,6 @@ const (
 	attrBitMapCount = 5
 	attrCmnModtime  = 0x00000400
 	attrCmnAcctime  = 0x00001000
-	attrCmnFullpath = 0x08000000
 )
 
 type attrList struct {
@@ -107,66 +85,6 @@ type attrList struct {
 	Forkattr    uint32
 }
 
-func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (attrs [][]byte, err error) {
-	if len(attrBuf) < 4 {
-		return nil, errorspkg.New("attrBuf too small")
-	}
-	attrList.bitmapCount = attrBitMapCount
-
-	var _p0 *byte
-	_p0, err = BytePtrFromString(path)
-	if err != nil {
-		return nil, err
-	}
-
-	_, _, e1 := syscall6(
-		funcPC(libc_getattrlist_trampoline),
-		uintptr(unsafe.Pointer(_p0)),
-		uintptr(unsafe.Pointer(&attrList)),
-		uintptr(unsafe.Pointer(&attrBuf[0])),
-		uintptr(len(attrBuf)),
-		uintptr(options),
-		0,
-	)
-	if e1 != 0 {
-		return nil, e1
-	}
-	size := *(*uint32)(unsafe.Pointer(&attrBuf[0]))
-
-	// dat is the section of attrBuf that contains valid data,
-	// without the 4 byte length header. All attribute offsets
-	// are relative to dat.
-	dat := attrBuf
-	if int(size) < len(attrBuf) {
-		dat = dat[:size]
-	}
-	dat = dat[4:] // remove length prefix
-
-	for i := uint32(0); int(i) < len(dat); {
-		header := dat[i:]
-		if len(header) < 8 {
-			return attrs, errorspkg.New("truncated attribute header")
-		}
-		datOff := *(*int32)(unsafe.Pointer(&header[0]))
-		attrLen := *(*uint32)(unsafe.Pointer(&header[4]))
-		if datOff < 0 || uint32(datOff)+attrLen > uint32(len(dat)) {
-			return attrs, errorspkg.New("truncated results; attrBuf too small")
-		}
-		end := uint32(datOff) + attrLen
-		attrs = append(attrs, dat[datOff:end])
-		i = end
-		if r := i % 4; r != 0 {
-			i += (4 - r)
-		}
-	}
-	return
-}
-
-func libc_getattrlist_trampoline()
-
-//go:linkname libc_getattrlist libc_getattrlist
-//go:cgo_import_dynamic libc_getattrlist getattrlist "/usr/lib/libSystem.B.dylib"
-
 //sysnb pipe(p *[2]int32) (err error)
 
 func Pipe(p []int) (err error) {
@@ -341,6 +259,7 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
 //sys	fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) = SYS_fcntl
 //sys   unlinkat(fd int, path string, flags int) (err error)
 //sys   openat(fd int, path string, flags int, perm uint32) (fdret int, err error)
+//sys	getcwd(buf []byte) (n int, err error)
 
 func init() {
 	execveDarwin = execve
diff --git a/src/syscall/syscall_getwd_bsd.go b/src/syscall/syscall_getwd_bsd.go
deleted file mode 100644
index b14367936ee..00000000000
--- a/src/syscall/syscall_getwd_bsd.go
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2018 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 dragonfly freebsd netbsd openbsd
-
-package syscall
-
-const ImplementsGetwd = true
-
-func Getwd() (string, error) {
-	var buf [pathMax]byte
-	_, err := getcwd(buf[:])
-	if err != nil {
-		return "", err
-	}
-	n := clen(buf[:])
-	if n < 1 {
-		return "", EINVAL
-	}
-	return string(buf[:n]), nil
-}
diff --git a/src/syscall/types_darwin.go b/src/syscall/types_darwin.go
index d8218d6aea1..7b3a9d23353 100644
--- a/src/syscall/types_darwin.go
+++ b/src/syscall/types_darwin.go
@@ -123,6 +123,12 @@ type Fsid C.struct_fsid
 
 type Dirent C.struct_dirent
 
+// File system limits
+
+const (
+	pathMax = C.PATH_MAX
+)
+
 // Sockets
 
 type RawSockaddrInet4 C.struct_sockaddr_in
diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index 83214de2fbb..093739ebc77 100644
--- a/src/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -1943,6 +1943,28 @@ func libc_openat_trampoline()
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func getcwd(buf []byte) (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(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_getcwd_trampoline()
+
+//go:linkname libc_getcwd libc_getcwd
+//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := syscall(funcPC(libc_fstat64_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
diff --git a/src/syscall/zsyscall_darwin_amd64.s b/src/syscall/zsyscall_darwin_amd64.s
index 23ddbe06c0d..d99656d0282 100644
--- a/src/syscall/zsyscall_darwin_amd64.s
+++ b/src/syscall/zsyscall_darwin_amd64.s
@@ -1,8 +1,6 @@
 // go run mkasm_darwin.go amd64
 // Code generated by the command above; DO NOT EDIT.
 #include "textflag.h"
-TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_getattrlist(SB)
 TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getfsstat(SB)
 TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0
@@ -235,6 +233,8 @@ TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_unlinkat(SB)
 TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_openat(SB)
+TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_getcwd(SB)
 TEXT ·libc_fstat64_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat64(SB)
 TEXT ·libc_fstatfs64_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go
index 0b778398692..0ff642eb254 100644
--- a/src/syscall/zsyscall_darwin_arm64.go
+++ b/src/syscall/zsyscall_darwin_arm64.go
@@ -1943,6 +1943,28 @@ func libc_openat_trampoline()
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func getcwd(buf []byte) (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(funcPC(libc_getcwd_trampoline), uintptr(_p0), uintptr(len(buf)), 0)
+	n = int(r0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+func libc_getcwd_trampoline()
+
+//go:linkname libc_getcwd libc_getcwd
+//go:cgo_import_dynamic libc_getcwd getcwd "/usr/lib/libSystem.B.dylib"
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Fstat(fd int, stat *Stat_t) (err error) {
 	_, _, e1 := syscall(funcPC(libc_fstat_trampoline), uintptr(fd), uintptr(unsafe.Pointer(stat)), 0)
 	if e1 != 0 {
diff --git a/src/syscall/zsyscall_darwin_arm64.s b/src/syscall/zsyscall_darwin_arm64.s
index 7b8b3764a82..214851604a2 100644
--- a/src/syscall/zsyscall_darwin_arm64.s
+++ b/src/syscall/zsyscall_darwin_arm64.s
@@ -1,8 +1,6 @@
 // go run mkasm_darwin.go arm64
 // Code generated by the command above; DO NOT EDIT.
 #include "textflag.h"
-TEXT ·libc_getattrlist_trampoline(SB),NOSPLIT,$0-0
-	JMP	libc_getattrlist(SB)
 TEXT ·libc_getfsstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_getfsstat(SB)
 TEXT ·libc_setattrlist_trampoline(SB),NOSPLIT,$0-0
@@ -235,6 +233,8 @@ TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_unlinkat(SB)
 TEXT ·libc_openat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_openat(SB)
+TEXT ·libc_getcwd_trampoline(SB),NOSPLIT,$0-0
+	JMP	libc_getcwd(SB)
 TEXT ·libc_fstat_trampoline(SB),NOSPLIT,$0-0
 	JMP	libc_fstat(SB)
 TEXT ·libc_fstatfs_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/ztypes_darwin_amd64.go b/src/syscall/ztypes_darwin_amd64.go
index bbd5bec3858..da56f0da22b 100644
--- a/src/syscall/ztypes_darwin_amd64.go
+++ b/src/syscall/ztypes_darwin_amd64.go
@@ -151,6 +151,10 @@ type Dirent struct {
 	Pad_cgo_0 [3]byte
 }
 
+const (
+	pathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
diff --git a/src/syscall/ztypes_darwin_arm64.go b/src/syscall/ztypes_darwin_arm64.go
index e9c8549fa1a..82685ff6591 100644
--- a/src/syscall/ztypes_darwin_arm64.go
+++ b/src/syscall/ztypes_darwin_arm64.go
@@ -151,6 +151,10 @@ type Dirent struct {
 	Pad_cgo_0 [3]byte
 }
 
+const (
+	pathMax = 0x400
+)
+
 type RawSockaddrInet4 struct {
 	Len    uint8
 	Family uint8
-- 
GitLab