summaryrefslogtreecommitdiffstats
path: root/lib/randutils.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/randutils.c')
-rw-r--r--lib/randutils.c64
1 files changed, 46 insertions, 18 deletions
diff --git a/lib/randutils.c b/lib/randutils.c
index 7d85dc841..5cd1c9976 100644
--- a/lib/randutils.c
+++ b/lib/randutils.c
@@ -95,27 +95,39 @@ int random_get_fd(void)
*/
void random_get_bytes(void *buf, size_t nbytes)
{
- size_t i;
unsigned char *cp = (unsigned char *)buf;
+ size_t i, n = nbytes;
+ int lose_counter = 0;
#ifdef HAVE_GETRANDOM
- errno = 0;
- while (getrandom(buf, nbytes, 0) != (ssize_t)nbytes) {
- if (errno == EINTR)
+ while (n > 0) {
+ int x;
+
+ errno = 0;
+ x = getrandom(cp, n, 0);
+ if (x > 0) { /* success */
+ n -= x;
+ cp += x;
+ lose_counter = 0;
+ } else if (errno == ENOSYS) { /* kernel without getrandom() */
+ break;
+ } else {
+ if (lose_counter++ > 16) /* entropy problem? */
+ break;
continue;
- break;
+ }
}
+
if (errno == ENOSYS)
+#endif
+
/*
- * We've been built against headers that support getrandom,
- * but the running kernel does not.
- * Fallback to reading from /dev/{u,}random as before
+ * We've been built against headers that support getrandom, but the
+ * running kernel does not. Fallback to reading from /dev/{u,}random
+ * as before
*/
-#endif
{
- size_t n = nbytes;
int fd = random_get_fd();
- int lose_counter = 0;
if (fd >= 0) {
while (n > 0) {
@@ -153,7 +165,6 @@ void random_get_bytes(void *buf, size_t nbytes)
sizeof(ul_jrand_seed)-sizeof(unsigned short));
}
#endif
-
return;
}
@@ -181,15 +192,32 @@ const char *random_tell_source(void)
}
#ifdef TEST_PROGRAM_RANDUTILS
-int main(int argc __attribute__ ((__unused__)),
- char *argv[] __attribute__ ((__unused__)))
+int main(int argc, char *argv[])
{
- unsigned int v, i;
+ size_t i, n;
+ int64_t *vp, v;
+ char *buf;
+ size_t bufsz;
+
+ n = argc == 1 ? 16 : atoi(argv[1]);
- /* generate and print 10 random numbers */
- for (i = 0; i < 10; i++) {
+ printf("Multiple random calls:\n");
+ for (i = 0; i < n; i++) {
random_get_bytes(&v, sizeof(v));
- printf("%d\n", v);
+ printf("#%02zu: %25ju\n", i, v);
+ }
+
+
+ printf("One random call:\n");
+ bufsz = n * sizeof(*vp);
+ buf = malloc(bufsz);
+ if (!buf)
+ err(EXIT_FAILURE, "failed to allocate buffer");
+
+ random_get_bytes(buf, bufsz);
+ for (i = 0; i < n; i++) {
+ vp = (int64_t *) (buf + (i * sizeof(*vp)));
+ printf("#%02zu: %25ju\n", i, *vp);
}
return EXIT_SUCCESS;