rand/noise.c (noise_devrandom): Use new Linux system call `getrandom'.
[catacomb] / rand / noise.c
index 6458f92..b59fd8a 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "config.h"
 
+#include <errno.h>
 #include <setjmp.h>
 #include <signal.h>
 #include <stdio.h>
 #  include <grp.h>
 #endif
 
+#if defined(HAVE_LINUX_RANDOM_H)
+#  include <linux/random.h>
+#  include <sys/syscall.h>
+#endif
+
 #include <mLib/bits.h>
 #include <mLib/mdup.h>
 #include <mLib/sel.h>
@@ -167,6 +173,22 @@ int noise_devrandom(rand_pool *r)
   struct timeval tv = { 0, 0 };
 #endif
 
+#if defined(HAVE_LINUX_RANDOM_H) &&                                    \
+    defined(GRND_NONBLOCK) &&                                          \
+    defined(SYS_getrandom)
+  /* --- Use the new shinies if available --- */
+
+  while (n < sizeof(buf)) {
+    if ((len = syscall(SYS_getrandom, buf + n, sizeof(buf) - n,
+                      GRND_NONBLOCK)) <= 0) {
+      if (errno == ENOSYS) break;
+      else goto done;
+    }
+    n += len;
+  }
+  if (n == sizeof(buf)) goto win;
+#endif
+
 #ifdef __linux__
   /* --- Don't take from `/dev/urandom' if `/dev/random' would block --- */