getrandom.mx raw
1 // Copyright 2021 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 //go:build dragonfly || freebsd || linux
6
7 package unix
8
9 import (
10 "sync/atomic"
11 "syscall"
12 "unsafe"
13 )
14
15 //go:linkname vgetrandom runtime.vgetrandom
16 //go:noescape
17 func vgetrandom(p []byte, flags uint32) (ret int, supported bool)
18
19 var getrandomUnsupported atomic.Bool
20
21 // GetRandomFlag is a flag supported by the getrandom system call.
22 type GetRandomFlag uintptr
23
24 // GetRandom calls the getrandom system call.
25 func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) {
26 ret, supported := vgetrandom(p, uint32(flags))
27 if supported {
28 if ret < 0 {
29 return 0, syscall.Errno(-ret)
30 }
31 return ret, nil
32 }
33 if getrandomUnsupported.Load() {
34 return 0, syscall.ENOSYS
35 }
36 r1, _, errno := syscall.Syscall(getrandomTrap,
37 uintptr(unsafe.Pointer(unsafe.SliceData(p))),
38 uintptr(len(p)),
39 uintptr(flags))
40 if errno != 0 {
41 if errno == syscall.ENOSYS {
42 getrandomUnsupported.Store(true)
43 }
44 return 0, errno
45 }
46 return int(r1), nil
47 }
48