9141 " |
9141 " |
9142 ! |
9142 ! |
9143 |
9143 |
9144 randomBytesInto:bufferOrInteger |
9144 randomBytesInto:bufferOrInteger |
9145 "If bufferOrInteger is a String or a ByteArray, |
9145 "If bufferOrInteger is a String or a ByteArray, |
9146 fill a given buffer with random bytes from the RtlGenRandom function |
9146 fill a given buffer with random bytes from the RtlGenRandom function |
9147 and answer the buffer. |
9147 and answer the buffer. |
9148 |
9148 |
9149 If bufferOrInteger is a SmallInteger, |
9149 If bufferOrInteger is a SmallInteger, |
9150 return this many bytes (max 4) as a SmallInteger. |
9150 return this many bytes (max 4) as a SmallInteger. |
9151 |
9151 |
9152 Return nil on error (may raise PrimitiveFailure, too). |
9152 Return nil on error (may raise PrimitiveFailure, too). |
9153 |
9153 |
9154 NOTE: This is a private interface, please use RandomGenerator!!" |
9154 NOTE: This is a private interface, please use RandomGenerator!!" |
9155 |
9155 |
9156 %{ |
9156 %{ |
9157 #if defined(LINUX) && defined(USE_GETRANDOM) |
9157 #if defined(LINUX) |
9158 # include <linux/random.h> |
9158 # include <sys/syscall.h> |
9159 # if defined(GRND_RANDOM) && defined(GRND_NONBLOCK) |
9159 # if defined(SYS_getrandom) // getrandom(2) is upported starting with linux 3.17 (2014-10-05) |
9160 // getrandom(2) is upported starting with linux 3.17 |
9160 |
9161 |
9161 # if 1 || !(defined(__GLIBC__) && __GLIBC_PREREQ(2, 23)) |
9162 int wanted, cnt, gotSoFar = 0; |
9162 // getrandom() appears first in GLIBC 2.23 |
|
9163 // but we define it here until this GLIBC has been deployed on all linux distributions |
|
9164 // used by our customers |
|
9165 |
|
9166 inline int getrandom(void *buf, size_t buflen, unsigned int flags) { |
|
9167 syscall(SYS_getrandom, buf, buflen, flags); |
|
9168 } |
|
9169 # endif |
|
9170 |
|
9171 size_t wanted, cnt, gotSoFar = 0; |
9163 char *buffer; |
9172 char *buffer; |
9164 |
9173 |
9165 if (__isSmallInteger(bufferOrInteger) && (wanted = __smallIntegerVal(bufferOrInteger) <= 4)) { |
9174 if (__isSmallInteger(bufferOrInteger) |
9166 int buf = 0; |
9175 && ((wanted = __smallIntegerVal(bufferOrInteger)) <= sizeof(INT))) { |
9167 |
9176 INT buf = 0; |
9168 do { |
9177 |
9169 cnt = getrandom(&buf + gotSoFar, wanted - gotSoFar, 0); |
9178 do { |
9170 if (cnt < 0) { |
9179 cnt = getrandom(&buf + gotSoFar, wanted - gotSoFar, 0); |
9171 if (errno != EINTR && errno != EAGAIN) |
9180 if (cnt < 0) { |
9172 goto error; |
9181 // this should not happen, since getrandom <= 256 bytes |
9173 } else { |
9182 // is guaranteed not to interrupt when fetching from zhe urandom pool |
9174 gotSoFar = gotSoFar + cnt; |
9183 if (errno != EINTR && errno != EAGAIN) |
9175 } |
9184 goto error; |
9176 } while (gotSoFar < wanted); |
9185 } else { |
9177 RETURN(__mkSmallInteger(buf)); |
9186 gotSoFar = gotSoFar + cnt; |
|
9187 } |
|
9188 } while (gotSoFar < wanted); |
|
9189 RETURN(__mkSmallInteger(buf & _MAX_INT)); |
9178 } else if (__isByteArray(bufferOrInteger)) { |
9190 } else if (__isByteArray(bufferOrInteger)) { |
9179 wanted = __byteArraySize(bufferOrInteger); |
9191 wanted = __byteArraySize(bufferOrInteger); |
9180 buffer = __byteArrayVal(bufferOrInteger); |
9192 buffer = __byteArrayVal(bufferOrInteger); |
9181 } else if (__isString(bufferOrInteger)) { |
9193 } else if (__isString(bufferOrInteger)) { |
9182 wanted = __stringSize(bufferOrInteger); |
9194 wanted = __stringSize(bufferOrInteger); |
9183 buffer = __stringVal(bufferOrInteger); |
9195 buffer = __stringVal(bufferOrInteger); |
9184 } else |
9196 } else |
9185 goto error; |
9197 goto error; |
9186 |
9198 |
9187 do { |
9199 do { |
9188 cnt = getrandom(buffer + gotSoFar, wanted - gotSoFar, 0); |
9200 cnt = getrandom(buffer + gotSoFar, wanted - gotSoFar, 0); |
9189 if (cnt < 0) { |
9201 if (cnt < 0) { |
9190 if (errno != EINTR && errno != EAGAIN) |
9202 if (errno != EINTR && errno != EAGAIN) |
9191 goto error; |
9203 goto error; |
9192 buffer = __isByteArray(bufferOrInteger) ? |
9204 buffer = __isByteArray(bufferOrInteger) ? |
9193 __byteArrayVal(bufferOrInteger) : __stringVal(bufferOrInteger); |
9205 __byteArrayVal(bufferOrInteger) : __stringVal(bufferOrInteger); |
9194 } else { |
9206 } else { |
9195 gotSoFar = gotSoFar + cnt; |
9207 gotSoFar = gotSoFar + cnt; |
9196 } |
9208 } |
9197 } while (gotSoFar < wanted); |
9209 } while (gotSoFar < wanted); |
9198 RETURN(bufferOrInteger); |
9210 RETURN(bufferOrInteger); |
9199 |
9211 # endif // SYS_getrandom |
9200 # endif // GRND_RANDOM |
|
9201 #endif |
9212 #endif |
9202 error: ; |
9213 error: ; |
9203 %}. |
9214 %}. |
9204 |
9215 |
9205 ^ self primitiveFailed. |
9216 ^ self primitiveFailed. |
9206 |
9217 |
9207 " |
9218 " |
9208 self randomBytesInto:2. |
9219 self randomBytesInto:1. |
9209 self randomBytesInto:(ByteArray new:16). |
9220 self randomBytesInto:2. |
9210 self randomBytesInto:(String new:16). |
9221 self randomBytesInto:4. |
|
9222 self randomBytesInto:8. |
|
9223 self randomBytesInto:(ByteArray new:16). |
|
9224 self randomBytesInto:(String new:16). |
9211 " |
9225 " |
9212 ! |
9226 ! |
9213 |
9227 |
9214 setEnvironment:aKeyStringOrSymbol to:aString |
9228 setEnvironment:aKeyStringOrSymbol to:aString |
9215 "put a string to the environment. |
9229 "put a string to the environment. |