--- a/UnixOperatingSystem.st Mon Mar 14 18:43:51 2016 +0100
+++ b/UnixOperatingSystem.st Mon Mar 14 18:44:38 2016 +0100
@@ -9143,61 +9143,72 @@
randomBytesInto:bufferOrInteger
"If bufferOrInteger is a String or a ByteArray,
- fill a given buffer with random bytes from the RtlGenRandom function
- and answer the buffer.
+ fill a given buffer with random bytes from the RtlGenRandom function
+ and answer the buffer.
If bufferOrInteger is a SmallInteger,
- return this many bytes (max 4) as a SmallInteger.
+ return this many bytes (max 4) as a SmallInteger.
Return nil on error (may raise PrimitiveFailure, too).
NOTE: This is a private interface, please use RandomGenerator!!"
%{
-#if defined(LINUX) && defined(USE_GETRANDOM)
-# include <linux/random.h>
-# if defined(GRND_RANDOM) && defined(GRND_NONBLOCK)
- // getrandom(2) is upported starting with linux 3.17
-
- int wanted, cnt, gotSoFar = 0;
+#if defined(LINUX)
+# include <sys/syscall.h>
+# if defined(SYS_getrandom) // getrandom(2) is upported starting with linux 3.17 (2014-10-05)
+
+# if 1 || !(defined(__GLIBC__) && __GLIBC_PREREQ(2, 23))
+ // getrandom() appears first in GLIBC 2.23
+ // but we define it here until this GLIBC has been deployed on all linux distributions
+ // used by our customers
+
+ inline int getrandom(void *buf, size_t buflen, unsigned int flags) {
+ syscall(SYS_getrandom, buf, buflen, flags);
+ }
+# endif
+
+ size_t wanted, cnt, gotSoFar = 0;
char *buffer;
- if (__isSmallInteger(bufferOrInteger) && (wanted = __smallIntegerVal(bufferOrInteger) <= 4)) {
- int buf = 0;
-
- do {
- cnt = getrandom(&buf + gotSoFar, wanted - gotSoFar, 0);
- if (cnt < 0) {
- if (errno != EINTR && errno != EAGAIN)
- goto error;
- } else {
- gotSoFar = gotSoFar + cnt;
- }
- } while (gotSoFar < wanted);
- RETURN(__mkSmallInteger(buf));
+ if (__isSmallInteger(bufferOrInteger)
+ && ((wanted = __smallIntegerVal(bufferOrInteger)) <= sizeof(INT))) {
+ INT buf = 0;
+
+ do {
+ cnt = getrandom(&buf + gotSoFar, wanted - gotSoFar, 0);
+ if (cnt < 0) {
+ // this should not happen, since getrandom <= 256 bytes
+ // is guaranteed not to interrupt when fetching from zhe urandom pool
+ if (errno != EINTR && errno != EAGAIN)
+ goto error;
+ } else {
+ gotSoFar = gotSoFar + cnt;
+ }
+ } while (gotSoFar < wanted);
+ RETURN(__mkSmallInteger(buf & _MAX_INT));
} else if (__isByteArray(bufferOrInteger)) {
- wanted = __byteArraySize(bufferOrInteger);
- buffer = __byteArrayVal(bufferOrInteger);
+ wanted = __byteArraySize(bufferOrInteger);
+ buffer = __byteArrayVal(bufferOrInteger);
} else if (__isString(bufferOrInteger)) {
- wanted = __stringSize(bufferOrInteger);
- buffer = __stringVal(bufferOrInteger);
+ wanted = __stringSize(bufferOrInteger);
+ buffer = __stringVal(bufferOrInteger);
} else
- goto error;
+ goto error;
do {
- cnt = getrandom(buffer + gotSoFar, wanted - gotSoFar, 0);
- if (cnt < 0) {
- if (errno != EINTR && errno != EAGAIN)
- goto error;
- buffer = __isByteArray(bufferOrInteger) ?
- __byteArrayVal(bufferOrInteger) : __stringVal(bufferOrInteger);
- } else {
- gotSoFar = gotSoFar + cnt;
- }
+ cnt = getrandom(buffer + gotSoFar, wanted - gotSoFar, 0);
+ if (cnt < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ goto error;
+ buffer = __isByteArray(bufferOrInteger) ?
+ __byteArrayVal(bufferOrInteger) : __stringVal(bufferOrInteger);
+ } else {
+ gotSoFar = gotSoFar + cnt;
+ }
} while (gotSoFar < wanted);
RETURN(bufferOrInteger);
-
-# endif // GRND_RANDOM
+# endif // SYS_getrandom
#endif
error: ;
%}.
@@ -9205,9 +9216,12 @@
^ self primitiveFailed.
"
- self randomBytesInto:2.
- self randomBytesInto:(ByteArray new:16).
- self randomBytesInto:(String new:16).
+ self randomBytesInto:1.
+ self randomBytesInto:2.
+ self randomBytesInto:4.
+ self randomBytesInto:8.
+ self randomBytesInto:(ByteArray new:16).
+ self randomBytesInto:(String new:16).
"
!