// 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.

//go:build dragonfly || freebsd || linux || solaris

package sysrand

import (
	
	
	
	
	
)

func read( []byte) error {
	// Linux, DragonFly, and illumos don't have a limit on the buffer size.
	// FreeBSD has a limit of IOSIZE_MAX, which seems to be either INT_MAX or
	// SSIZE_MAX. 2^31-1 is a safe and high enough value to use for all of them.
	//
	// Note that Linux returns "a maximum of 32Mi-1 bytes", but that will only
	// result in a short read, not an error. Short reads can also happen above
	// 256 bytes due to signals. Reads up to 256 bytes are guaranteed not to
	// return short (and not to return an error IF THE POOL IS INITIALIZED) on
	// at least Linux, FreeBSD, DragonFly, and Oracle Solaris, but we don't make
	// use of that.
	 := math.MaxInt32

	// Oracle Solaris has a limit of 133120 bytes. Very specific.
	//
	//    The getrandom() and getentropy() functions fail if: [...]
	//
	//    - bufsz is <= 0 or > 133120, when GRND_RANDOM is not set
	//
	// https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html
	if runtime.GOOS == "solaris" {
		 = 133120
	}

	for len() > 0 {
		 := len()
		if  >  {
			 = 
		}
		,  := unix.GetRandom([:], 0)
		if errors.Is(, syscall.ENOSYS) {
			// If getrandom(2) is not available, presumably on Linux versions
			// earlier than 3.17, fall back to reading from /dev/urandom.
			return urandomRead()
		}
		if errors.Is(, syscall.EINTR) {
			// If getrandom(2) is blocking, either because it is waiting for the
			// entropy pool to become initialized or because we requested more
			// than 256 bytes, it might get interrupted by a signal.
			continue
		}
		if  != nil {
			return 
		}
		 = [:]
	}
	return nil
}