github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/internal/syscall/unix/getrandom_netbsd.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package unix
     6  
     7  import (
     8  	"sync"
     9  	"sync/atomic"
    10  	"syscall"
    11  	"unsafe"
    12  )
    13  
    14  // NetBSD getrandom system call number.
    15  const getrandomTrap uintptr = 91
    16  
    17  var getrandomUnsupported atomic.Bool
    18  
    19  // GetRandomFlag is a flag supported by the getrandom system call.
    20  type GetRandomFlag uintptr
    21  
    22  // GetRandom calls the getrandom system call.
    23  func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
    24  	if len(p) == 0 {
    25  		return 0, nil
    26  	}
    27  	if getrandomUnsupported.Load() {
    28  		return 0, syscall.ENOSYS
    29  	}
    30  	// getrandom(2) was added in NetBSD 10.0
    31  	if getOSRevision() < 1000000000 {
    32  		getrandomUnsupported.Store(true)
    33  		return 0, syscall.ENOSYS
    34  	}
    35  	r1, _, errno := syscall.Syscall(getrandomTrap,
    36  		uintptr(unsafe.Pointer(&p[0])),
    37  		uintptr(len(p)),
    38  		uintptr(flags))
    39  	if errno != 0 {
    40  		if errno == syscall.ENOSYS {
    41  			getrandomUnsupported.Store(true)
    42  		}
    43  		return 0, errno
    44  	}
    45  	return int(r1), nil
    46  }
    47  
    48  var (
    49  	osrevisionOnce sync.Once
    50  	osrevision     uint32
    51  )
    52  
    53  func getOSRevision() uint32 {
    54  	osrevisionOnce.Do(func() { osrevision, _ = syscall.SysctlUint32("kern.osrevision") })
    55  	return osrevision
    56  }