| // 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. |
| |
| package syscall |
| |
| import ( |
| "runtime" |
| "sync/atomic" |
| stdsyscall "syscall" |
| "unsafe" |
| ) |
| |
| var randomTrap = map[string]uintptr{ |
| "386": 355, |
| "amd64": 318, |
| "arm": 384, |
| "ppc64": 359, |
| "ppc64le": 359, |
| }[runtime.GOARCH] |
| |
| var randomUnsupported int32 // atomic |
| |
| // GetRandomFlag is a flag supported by the getrandom system call. |
| type GetRandomFlag uintptr |
| |
| const ( |
| // GRND_NONBLOCK means return EAGAIN rather than blocking. |
| GRND_NONBLOCK GetRandomFlag = 0x0001 |
| |
| // GRND_RANDOM means use the /dev/random pool instead of /dev/urandom. |
| GRND_RANDOM GetRandomFlag = 0x0002 |
| ) |
| |
| // GetRandom calls the Linux getrandom system call. |
| // See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=c6e9d6f38894798696f23c8084ca7edbf16ee895 |
| func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) { |
| if randomTrap == 0 { |
| return 0, stdsyscall.ENOSYS |
| } |
| if len(p) == 0 { |
| return 0, nil |
| } |
| if atomic.LoadInt32(&randomUnsupported) != 0 { |
| return 0, stdsyscall.ENOSYS |
| } |
| r1, _, errno := stdsyscall.Syscall(randomTrap, |
| uintptr(unsafe.Pointer(&p[0])), |
| uintptr(len(p)), |
| uintptr(flags)) |
| if errno != 0 { |
| if errno == stdsyscall.ENOSYS { |
| atomic.StoreInt32(&randomUnsupported, 1) |
| } |
| return 0, errno |
| } |
| return int(r1), nil |
| } |