summaryrefslogtreecommitdiffstats
path: root/libblkid/randutils.c
diff options
context:
space:
mode:
authorbigbiff bigbiff <bigbiff@teamw.in>2013-02-23 02:55:50 +0100
committerbigbiff bigbiff <bigbiff@teamw.in>2013-02-25 15:06:46 +0100
commite60683a0d553b6488c564863f4e48954944fb0f8 (patch)
tree9364f97cb88b7c1359f5f06dfb32150a78168c31 /libblkid/randutils.c
parentFix building of updater for 4.2 environment (diff)
downloadandroid_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar
android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.gz
android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.bz2
android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.lz
android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.xz
android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.tar.zst
android_bootable_recovery-e60683a0d553b6488c564863f4e48954944fb0f8.zip
Diffstat (limited to '')
-rw-r--r--libblkid/randutils.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/libblkid/randutils.c b/libblkid/randutils.c
new file mode 100644
index 000000000..80893d3db
--- /dev/null
+++ b/libblkid/randutils.c
@@ -0,0 +1,125 @@
+/*
+ * General purpose random utilities
+ *
+ * Based on libuuid code.
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include <sys/syscall.h>
+
+#include "randutils.h"
+
+#ifdef HAVE_TLS
+#define THREAD_LOCAL static __thread
+#else
+#define THREAD_LOCAL static
+#endif
+
+#if defined(__linux__) && defined(__NR_gettid) && defined(HAVE_JRAND48)
+#define DO_JRAND_MIX
+THREAD_LOCAL unsigned short ul_jrand_seed[3];
+#endif
+
+int random_get_fd(void)
+{
+ int i, fd;
+ struct timeval tv;
+
+ gettimeofday(&tv, 0);
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
+ if (fd >= 0) {
+ i = fcntl(fd, F_GETFD);
+ if (i >= 0)
+ fcntl(fd, F_SETFD, i | FD_CLOEXEC);
+ }
+ srand((getpid() << 16) ^ getuid() ^ tv.tv_sec ^ tv.tv_usec);
+
+#ifdef DO_JRAND_MIX
+ ul_jrand_seed[0] = getpid() ^ (tv.tv_sec & 0xFFFF);
+ ul_jrand_seed[1] = getppid() ^ (tv.tv_usec & 0xFFFF);
+ ul_jrand_seed[2] = (tv.tv_sec ^ tv.tv_usec) >> 16;
+#endif
+ /* Crank the random number generator a few times */
+ gettimeofday(&tv, 0);
+ for (i = (tv.tv_sec ^ tv.tv_usec) & 0x1F; i > 0; i--)
+ rand();
+ return fd;
+}
+
+
+/*
+ * Generate a stream of random nbytes into buf.
+ * Use /dev/urandom if possible, and if not,
+ * use glibc pseudo-random functions.
+ */
+void random_get_bytes(void *buf, size_t nbytes)
+{
+ size_t i, n = nbytes;
+ int fd = random_get_fd();
+ int lose_counter = 0;
+ unsigned char *cp = (unsigned char *) buf;
+
+ if (fd >= 0) {
+ while (n > 0) {
+ ssize_t x = read(fd, cp, n);
+ if (x <= 0) {
+ if (lose_counter++ > 16)
+ break;
+ continue;
+ }
+ n -= x;
+ cp += x;
+ lose_counter = 0;
+ }
+
+ close(fd);
+ }
+
+ /*
+ * We do this all the time, but this is the only source of
+ * randomness if /dev/random/urandom is out to lunch.
+ */
+ for (cp = buf, i = 0; i < nbytes; i++)
+ *cp++ ^= (rand() >> 7) & 0xFF;
+
+#ifdef DO_JRAND_MIX
+ {
+ unsigned short tmp_seed[3];
+
+ memcpy(tmp_seed, ul_jrand_seed, sizeof(tmp_seed));
+ ul_jrand_seed[2] = ul_jrand_seed[2] ^ syscall(__NR_gettid);
+ for (cp = buf, i = 0; i < nbytes; i++)
+ *cp++ ^= (jrand48(tmp_seed) >> 7) & 0xFF;
+ memcpy(ul_jrand_seed, tmp_seed,
+ sizeof(ul_jrand_seed)-sizeof(unsigned short));
+ }
+#endif
+
+ return;
+}
+
+#ifdef TEST_PROGRAM
+int main(int argc __attribute__ ((__unused__)),
+ char *argv[] __attribute__ ((__unused__)))
+{
+ unsigned int v, i;
+
+ /* generate and print 10 random numbers */
+ for (i = 0; i < 10; i++) {
+ random_get_bytes(&v, sizeof(v));
+ printf("%d\n", v);
+ }
+
+ return EXIT_SUCCESS;
+}
+#endif /* TEST_PROGRAM */