UnixOperatingSystem.st
changeset 19361 650e52cb3ec8
parent 19191 d7c92ebd54bf
child 19406 faccbadf3034
child 19424 7f6cdbefb9f5
equal deleted inserted replaced
19360:5b112fdb68be 19361:650e52cb3ec8
  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.