unix: 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.

Change-Id: I62d38a239a7279fb95c912344bda2830856d4da4
Reviewed-on: https://go-review.googlesource.com/c/sys/+/257497
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>
This commit is contained in:
Tobias Klauser
2020-09-26 10:08:07 +00:00
committed by Tobias Klauser
parent d9f96fdee2
commit 9d91bd6205
19 changed files with 134 additions and 200 deletions
+1 -72
View File
@@ -13,29 +13,10 @@
package unix
import (
"errors"
"syscall"
"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
}
// SockaddrDatalink implements the Sockaddr interface for AF_LINK type sockets.
type SockaddrDatalink struct {
Len uint8
@@ -97,11 +78,6 @@ func direntNamlen(buf []byte) (uint64, bool) {
func PtraceAttach(pid int) (err error) { return ptrace(PT_ATTACH, pid, 0, 0) }
func PtraceDetach(pid int) (err error) { return ptrace(PT_DETACH, pid, 0, 0) }
const (
attrBitMapCount = 5
attrCmnFullpath = 0x08000000
)
type attrList struct {
bitmapCount uint16
_ uint16
@@ -112,54 +88,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, errors.New("attrBuf too small")
}
attrList.bitmapCount = attrBitMapCount
var _p0 *byte
_p0, err = BytePtrFromString(path)
if err != nil {
return nil, err
}
if err := getattrlist(_p0, unsafe.Pointer(&attrList), unsafe.Pointer(&attrBuf[0]), uintptr(len(attrBuf)), int(options)); err != nil {
return nil, err
}
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, errors.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, errors.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
}
//sys getattrlist(path *byte, list unsafe.Pointer, buf unsafe.Pointer, size uintptr, options int) (err error)
//sysnb pipe() (r int, w int, err error)
func Pipe(p []int) (err error) {
@@ -419,6 +347,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
//sys Fpathconf(fd int, name int) (val int, err error)
//sys Fsync(fd int) (err error)
//sys Ftruncate(fd int, length int64) (err error)
//sys Getcwd(buf []byte) (n int, err error)
//sys Getdtablesize() (size int)
//sysnb Getegid() (egid int)
//sysnb Geteuid() (uid int)