syscall: import additional BSD-specific syscall wrappers

Import additional code from upstream for handing system
calls on BSD systems. This makes the syscall package on
NetBSD complete enough to compile the standard library.

Updates golang/go#38538.

Change-Id: I15644dbbd78b1acebcaf45b49403f07c929d97ed
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/265123
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Benny Siegert <bsiegert@gmail.com>
diff --git a/libgo/go/syscall/libcall_bsd.go b/libgo/go/syscall/libcall_bsd.go
new file mode 100644
index 0000000..f13d3bc
--- /dev/null
+++ b/libgo/go/syscall/libcall_bsd.go
@@ -0,0 +1,113 @@
+// Copyright 2020 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 dragonfly freebsd netbsd openbsd solaris
+
+// BSD library calls.
+
+package syscall
+
+import (
+	"unsafe"
+)
+
+//sys	sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
+//sysctl(mib *_C_int, miblen uintptr, old *byte, oldlen *uintptr, new *byte, newlen uintptr) _C_int
+
+//sysnb raw_ptrace(request int, pid int, addr uintptr, data uintptr) (err Errno)
+//ptrace(request _C_int, pid Pid_t, addr *byte, data _C_int) _C_int
+
+//sys	paccept(fd int, rsa *RawSockaddrAny, addrlen *Socklen_t, sigmask *_sigset_t, flags int) (nfd int, err error)
+//paccept(s _C_int, rsa *RawSockaddrAny, addrlen *Socklen_t, sigmask *_sigset_t, flags int) _C_int
+
+//sys	Flock(fd int, how int) (err error)
+//flock(fd _C_int, how _C_int) _C_int
+
+func ReadDirent(fd int, buf []byte) (n int, err error) {
+	// Final argument is (basep *uintptr) and the syscall doesn't take nil.
+	// 64 bits should be enough. (32 bits isn't even on 386). Since the
+	// actual system call is getdirentries64, 64 is a good guess.
+	// TODO(rsc): Can we use a single global basep for all calls?
+	var base = (*uintptr)(unsafe.Pointer(new(uint64)))
+	return Getdirentries(fd, buf, base)
+}
+
+func Accept4(fd, flags int) (nfd int, sa Sockaddr, err error) {
+	var rsa RawSockaddrAny
+	var len Socklen_t = SizeofSockaddrAny
+	nfd, err = paccept(fd, &rsa, &len, nil, flags)
+	if err != nil {
+		return
+	}
+	if len > SizeofSockaddrAny {
+		panic("RawSockaddrAny too small")
+	}
+	sa, err = anyToSockaddr(&rsa)
+	if err != nil {
+		Close(nfd)
+		nfd = 0
+	}
+	return
+}
+
+//sysnb	pipe2(p *[2]_C_int, flags int) (err error)
+//pipe2(p *[2]_C_int, flags _C_int) _C_int
+func Pipe2(p []int, flags int) (err error) {
+	if len(p) != 2 {
+		return EINVAL
+	}
+	var pp [2]_C_int
+	err = pipe2(&pp, flags)
+	p[0] = int(pp[0])
+	p[1] = int(pp[1])
+	return
+}
+
+func Sysctl(name string) (value string, err error) {
+	// Translate name to mib number.
+	mib, err := nametomib(name)
+	if err != nil {
+		return "", err
+	}
+
+	// Find size.
+	n := uintptr(0)
+	if err = sysctl(mib, nil, &n, nil, 0); err != nil {
+		return "", err
+	}
+	if n == 0 {
+		return "", nil
+	}
+
+	// Read into buffer of that size.
+	buf := make([]byte, n)
+	if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil {
+		return "", err
+	}
+
+	// Throw away terminating NUL.
+	if n > 0 && buf[n-1] == '\x00' {
+		n--
+	}
+	return string(buf[0:n]), nil
+}
+
+func SysctlUint32(name string) (value uint32, err error) {
+	// Translate name to mib number.
+	mib, err := nametomib(name)
+	if err != nil {
+		return 0, err
+	}
+
+	// Read into buffer of that size.
+	n := uintptr(4)
+	buf := make([]byte, 4)
+	if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil {
+		return 0, err
+	}
+	if n != 4 {
+		return 0, EIO
+	}
+	return *(*uint32)(unsafe.Pointer(&buf[0])), nil
+}
diff --git a/libgo/go/syscall/syscall_netbsd.go b/libgo/go/syscall/syscall_netbsd.go
index bbc6799..c3a79e3 100644
--- a/libgo/go/syscall/syscall_netbsd.go
+++ b/libgo/go/syscall/syscall_netbsd.go
@@ -18,6 +18,34 @@
 	return readInt(buf, unsafe.Offsetof(Dirent{}.Namlen), unsafe.Sizeof(Dirent{}.Namlen))
 }
 
+//sys	Getdents(fd int, buf []byte) (n int, err error)
+//getdents(fd _C_int, buf *byte, nbytes uintptr) _C_int
+
+func Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) {
+	n, err = Getdents(fd, buf)
+	if err != nil || basep == nil {
+		return
+	}
+
+	var off int64
+	off, err = Seek(fd, 0, 1 /* SEEK_CUR */)
+	if err != nil {
+		*basep = ^uintptr(0)
+		return
+	}
+	*basep = uintptr(off)
+	if unsafe.Sizeof(*basep) == 8 {
+		return
+	}
+	if off>>32 != 0 {
+		// We can't stuff the offset back into a uintptr, so any
+		// future calls would be suspect. Generate an error.
+		// EIO is allowed by getdirentries.
+		err = EIO
+	}
+	return
+}
+
 func sysctlNodes(mib []_C_int) (nodes []Sysctlnode, err error) {
 	var olen uintptr