| // 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. |
| |
| //go:build darwin || dragonfly || freebsd || netbsd || openbsd |
| // +build darwin dragonfly freebsd netbsd openbsd |
| |
| // 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 |
| } |