// Copyright 2021 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/atomic" "syscall" ) //extern getrandom func libc_getrandom(*byte, uintptr, uint32) uintptr var getrandomUnsupported 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 getrandom system call. func GetRandom(p []byte, flags GetRandomFlag) (n int, err error) { if len(p) == 0 { return 0, nil } if atomic.LoadInt32(&getrandomUnsupported) != 0 { return 0, syscall.ENOSYS } syscall.Entersyscall() r1 := libc_getrandom(&p[0], uintptr(len(p)), uint32(flags)) syscall.Exitsyscall() if r1 == 0 { errno := syscall.GetErrno() if errno == syscall.ENOSYS { atomic.StoreInt32(&getrandomUnsupported, 1) } return 0, errno } return int(r1), nil }