From a573530d500d7c22e27c0727b1f7abcbc0b73e1d Mon Sep 17 00:00:00 2001 From: Nikhil Benesch Date: Mon, 26 Oct 2020 17:48:32 +0000 Subject: [PATCH] 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. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/265123 --- gcc/go/gofrontend/MERGE | 2 +- libgo/go/syscall/libcall_bsd.go | 113 +++++++++++++++++++++++++++++++++++++ libgo/go/syscall/syscall_netbsd.go | 28 +++++++++ 3 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 libgo/go/syscall/libcall_bsd.go diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 3ad6c9633f1..c3a45c8a959 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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 index 00000000000..f13d3bcbe16 --- /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 bbc6799e3e6..c3a79e3275c 100644 --- a/libgo/go/syscall/syscall_netbsd.go +++ b/libgo/go/syscall/syscall_netbsd.go @@ -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 -- 2.11.4.GIT