1//===-------------------------- random.cpp --------------------------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is dual licensed under the MIT and the University of Illinois Open 6// Source Licenses. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#if defined(_WIN32) 11// Must be defined before including stdlib.h to enable rand_s(). 12#define _CRT_RAND_S 13#include <stdio.h> 14#endif // defined(_WIN32) 15 16#include "random" 17#include "system_error" 18 19#if defined(__sun__) 20#define rename solaris_headers_are_broken 21#endif // defined(__sun__) 22#if !defined(_WIN32) 23#include <fcntl.h> 24#include <unistd.h> 25#endif // !defined(_WIN32) 26#include <errno.h> 27#if defined(_LIBCPP_USING_NACL_RANDOM) 28#include <nacl/nacl_random.h> 29#endif // defined(_LIBCPP_USING_NACL_RANDOM) 30 31_LIBCPP_BEGIN_NAMESPACE_STD 32 33#if defined(_WIN32) 34 35random_device::random_device(const string&) 36{ 37} 38 39random_device::~random_device() 40{ 41} 42 43unsigned 44random_device::operator()() 45{ 46 unsigned r; 47 errno_t err = rand_s(&r); 48 if (err) 49 __throw_system_error(err, "random_device rand_s failed."); 50 return r; 51} 52 53#elif defined(_LIBCPP_USING_NACL_RANDOM) 54 55random_device::random_device(const string& __token) 56{ 57 if (__token != "/dev/urandom") 58 __throw_system_error(ENOENT, ("random device not supported " + __token).c_str()); 59 int error = nacl_secure_random_init(); 60 if (error) 61 __throw_system_error(error, ("random device failed to open " + __token).c_str()); 62} 63 64random_device::~random_device() 65{ 66} 67 68unsigned 69random_device::operator()() 70{ 71 unsigned r; 72 size_t n = sizeof(r); 73 char* p = reinterpret_cast<char*>(&r); 74 size_t bytes_written; 75 int error = nacl_secure_random(&r, n, &bytes_written); 76 if (error != 0) 77 __throw_system_error(error, "random_device failed getting bytes"); 78 else if (bytes_written != n) 79 __throw_runtime_error("random_device failed to obtain enough bytes"); 80 return r; 81} 82 83#else // !defined(_WIN32) && !defined(_LIBCPP_USING_NACL_RANDOM) 84 85random_device::random_device(const string& __token) 86 : __f_(open(__token.c_str(), O_RDONLY)) 87{ 88 if (__f_ < 0) 89 __throw_system_error(errno, ("random_device failed to open " + __token).c_str()); 90} 91 92random_device::~random_device() 93{ 94 close(__f_); 95} 96 97unsigned 98random_device::operator()() 99{ 100 unsigned r; 101 size_t n = sizeof(r); 102 char* p = reinterpret_cast<char*>(&r); 103 while (n > 0) 104 { 105 ssize_t s = read(__f_, p, n); 106 if (s == 0) 107 __throw_system_error(ENODATA, "random_device got EOF"); 108 if (s == -1) 109 { 110 if (errno != EINTR) 111 __throw_system_error(errno, "random_device got an unexpected error"); 112 continue; 113 } 114 n -= static_cast<size_t>(s); 115 p += static_cast<size_t>(s); 116 } 117 return r; 118} 119 120#endif // defined(_WIN32) || defined(_LIBCPP_USING_NACL_RANDOM) 121 122double 123random_device::entropy() const _NOEXCEPT 124{ 125 return 0; 126} 127 128_LIBCPP_END_NAMESPACE_STD 129