syscall: import additional BSD-specific syscall wrappers
authorNikhil Benesch <nikhil.benesch@gmail.com>
Mon, 26 Oct 2020 17:48:32 +0000 (17:48 +0000)
committerIan Lance Taylor <iant@golang.org>
Mon, 26 Oct 2020 22:04:16 +0000 (15:04 -0700)
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.

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/265123

gcc/go/gofrontend/MERGE
libgo/go/syscall/libcall_bsd.go [new file with mode: 0644]
libgo/go/syscall/syscall_netbsd.go

index 3ad6c9633f13cf8b2e3d0a316ee1b9aabcc40dc2..c3a45c8a9591490d695e7ad1645c74c568005e0c 100644 (file)
@@ -1,4 +1,4 @@
-28f3df468666787f83f94220312383a7c267a8ce
+66657f88f820f2b0cab3c1c0a7d8b7f8923af7fb
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/libgo/go/syscall/libcall_bsd.go b/libgo/go/syscall/libcall_bsd.go
new file mode 100644 (file)
index 0000000..f13d3bc
--- /dev/null
@@ -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
+}
index bbc6799e3e6bb4f2705f9a3cff248920cf0b0bb2..c3a79e3275c090d474e8f95e95f53ff44054ef89 100644 (file)
@@ -18,6 +18,34 @@ func direntNamlen(buf []byte) (uint64, bool) {
        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