Commit d9157a96 authored by Steven Hartland's avatar Steven Hartland Committed by Ian Lance Taylor

unix: add custom Sysctl args and methods SysctlUint64, SysctlRaw

Add support for optional sysctl arguments which is required to support
sysctls that require more than the mib identifer args as returned from
nametomib such as kern.proc.pid.

Add SysctlUint64 which allows sysctls that return 64 bit ints to be
queried.

Add SysctlRaw which allows sysctls that return structs or other
unsupported types to be queried.

Change-Id: If0fa23935ee09496f2df210364d8988ccd0f3db6
Reviewed-on: https://go-review.googlesource.com/14955Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent 354f231a
......@@ -450,16 +450,34 @@ func Kevent(kq int, changes, events []Kevent_t, timeout *Timespec) (n int, err e
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) = SYS___SYSCTL
func Sysctl(name string) (value string, err error) {
// sysctlmib translates name to mib number and appends any additional args.
func sysctlmib(name string, args ...int) ([]_C_int, error) {
// Translate name to mib number.
mib, err := nametomib(name)
if err != nil {
return nil, err
}
for _, a := range args {
mib = append(mib, _C_int(a))
}
return mib, nil
}
func Sysctl(name string) (string, error) {
return SysctlArgs(name)
}
func SysctlArgs(name string, args ...int) (string, error) {
mib, err := sysctlmib(name, args...)
if err != nil {
return "", err
}
// Find size.
n := uintptr(0)
if err = sysctl(mib, nil, &n, nil, 0); err != nil {
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
return "", err
}
if n == 0 {
......@@ -468,7 +486,7 @@ func Sysctl(name string) (value string, err error) {
// Read into buffer of that size.
buf := make([]byte, n)
if err = sysctl(mib, &buf[0], &n, nil, 0); err != nil {
if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
return "", err
}
......@@ -479,17 +497,19 @@ func Sysctl(name string) (value string, err error) {
return string(buf[0:n]), nil
}
func SysctlUint32(name string) (value uint32, err error) {
// Translate name to mib number.
mib, err := nametomib(name)
func SysctlUint32(name string) (uint32, error) {
return SysctlUint32Args(name)
}
func SysctlUint32Args(name string, args ...int) (uint32, error) {
mib, err := sysctlmib(name, args...)
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 {
if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
return 0, err
}
if n != 4 {
......@@ -498,6 +518,49 @@ func SysctlUint32(name string) (value uint32, err error) {
return *(*uint32)(unsafe.Pointer(&buf[0])), nil
}
func SysctlUint64(name string, args ...int) (uint64, error) {
mib, err := sysctlmib(name, args...)
if err != nil {
return 0, err
}
n := uintptr(8)
buf := make([]byte, 8)
if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
return 0, err
}
if n != 8 {
return 0, EIO
}
return *(*uint64)(unsafe.Pointer(&buf[0])), nil
}
func SysctlRaw(name string, args ...int) ([]byte, error) {
mib, err := sysctlmib(name, args...)
if err != nil {
return nil, err
}
// Find size.
n := uintptr(0)
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
return nil, err
}
if n == 0 {
return nil, nil
}
// Read into buffer of that size.
buf := make([]byte, n)
if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
return nil, err
}
// The actual call may return less than the original reported required
// size so ensure we deal with that.
return buf[:n], nil
}
//sys utimes(path string, timeval *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error {
......
......@@ -33,3 +33,10 @@ func TestGetfsstat(t *testing.T) {
}
}
}
func TestSysctlRaw(t *testing.T) {
_, err := unix.SysctlRaw("kern.proc.pid", unix.Getpid())
if err != nil {
t.Fatal(err)
}
}
// Copyright 2014 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 freebsd
package unix_test
import (
"testing"
"golang.org/x/sys/unix"
)
func TestSysctUint64(t *testing.T) {
_, err := unix.SysctlUint64("vm.max_kernel_address")
if err != nil {
t.Fatal(err)
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment