blob: c83e3b21a5ee8524e30c1a652d790dedeb8da12d [file] [log] [blame]
// Copyright 2023 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.
package unix
import (
"sync"
"sync/atomic"
"syscall"
"unsafe"
)
// NetBSD getrandom system call number.
const getrandomTrap uintptr = 91
var getrandomUnsupported atomic.Bool
// GetRandomFlag is a flag supported by the getrandom system call.
type GetRandomFlag uintptr
// GetRandom calls the getrandom system call.
func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
if len(p) == 0 {
return 0, nil
}
if getrandomUnsupported.Load() {
return 0, syscall.ENOSYS
}
// getrandom(2) was added in NetBSD 10.0
if getOSRevision() < 1000000000 {
getrandomUnsupported.Store(true)
return 0, syscall.ENOSYS
}
r1, _, errno := syscall.Syscall(getrandomTrap,
uintptr(unsafe.Pointer(&p[0])),
uintptr(len(p)),
uintptr(flags))
if errno != 0 {
if errno == syscall.ENOSYS {
getrandomUnsupported.Store(true)
}
return 0, errno
}
return int(r1), nil
}
var (
osrevisionOnce sync.Once
osrevision uint32
)
func getOSRevision() uint32 {
osrevisionOnce.Do(func() { osrevision, _ = syscall.SysctlUint32("kern.osrevision") })
return osrevision
}