UnixOperatingSystem.st
changeset 19361 650e52cb3ec8
parent 19191 d7c92ebd54bf
child 19406 faccbadf3034
child 19424 7f6cdbefb9f5
--- 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).
     "
 !