Use urandom / rtlgenrandom
[lsnes.git] / src / library / crandom.cpp
bloba6be2e01b65c4da72bf0a6814a944a2a45c5934a
1 #include "crandom.hpp"
2 #include <stdexcept>
3 #include <iostream>
5 #if defined(_WIN32) || defined(_WIN64)
6 #include <windows.h>
8 namespace
10 typedef BOOLEAN (WINAPI *rtlgenrandom_t)(PVOID buf, ULONG buflen);
11 HMODULE advapi;
12 rtlgenrandom_t rtlgenrandom_fn;
15 namespace crandom
17 void init()
19 if(rtlgenrandom_fn) return;
20 advapi = LoadLibraryA("advapi32.dll");
21 if(!advapi)
22 throw std::runtime_error("Can't load advapi32.dll");
23 rtlgenrandom_fn = (rtlgenrandom_t)GetProcAddress(advapi, "SystemFunction036");
24 if(!rtlgenrandom_fn)
25 throw std::runtime_error("Can't find rtlgenrandom");
28 void generate(void* buffer, size_t buffersize)
30 if(!rtlgenrandom_fn)
31 init();
32 while(!rtlgenrandom_fn(buffer, buffersize));
36 #else
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <cerrno>
41 namespace
43 int fd = -1;
44 void try_file(const char* name)
46 int err = 0;
47 while(fd < 0 && err != ENOENT && err != ENXIO) {
48 fd = open(name, O_RDONLY);
49 if(fd < 0) err = errno;
54 namespace crandom
56 void init()
58 if(fd < 0) try_file("/dev/urandom");
59 if(fd < 0) try_file("/dev/random");
60 if(fd < 0) throw std::runtime_error("Can't open /dev/urandom");
63 void generate(void* buffer, size_t buffersize)
65 if(fd < 0)
66 init();
67 size_t out = 0;
68 while(out < buffersize) {
69 ssize_t r = read(fd, (char*)buffer + out, buffersize - out);
70 if(r > 0) out += r;
75 #endif