Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/c++/src/random.cpp
12346 views
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
#include <__config>
11
12
#if defined(_LIBCPP_USING_WIN32_RANDOM)
13
// Must be defined before including stdlib.h to enable rand_s().
14
#define _CRT_RAND_S
15
#endif // defined(_LIBCPP_USING_WIN32_RANDOM)
16
17
#include "random"
18
#include "system_error"
19
20
#if defined(__sun__)
21
#define rename solaris_headers_are_broken
22
#endif // defined(__sun__)
23
24
#include <errno.h>
25
#include <stdio.h>
26
#include <stdlib.h>
27
28
#if defined(_LIBCPP_USING_GETENTROPY)
29
#include <sys/random.h>
30
#elif defined(_LIBCPP_USING_DEV_RANDOM)
31
#include <fcntl.h>
32
#include <unistd.h>
33
#elif defined(_LIBCPP_USING_NACL_RANDOM)
34
#include <nacl/nacl_random.h>
35
#endif
36
37
38
_LIBCPP_BEGIN_NAMESPACE_STD
39
40
#if defined(_LIBCPP_USING_GETENTROPY)
41
42
random_device::random_device(const string& __token)
43
{
44
if (__token != "/dev/urandom")
45
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
46
}
47
48
random_device::~random_device()
49
{
50
}
51
52
unsigned
53
random_device::operator()()
54
{
55
unsigned r;
56
size_t n = sizeof(r);
57
int err = getentropy(&r, n);
58
if (err)
59
__throw_system_error(errno, "random_device getentropy failed");
60
return r;
61
}
62
63
#elif defined(_LIBCPP_USING_ARC4_RANDOM)
64
65
random_device::random_device(const string& __token)
66
{
67
if (__token != "/dev/urandom")
68
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
69
}
70
71
random_device::~random_device()
72
{
73
}
74
75
unsigned
76
random_device::operator()()
77
{
78
return arc4random();
79
}
80
81
#elif defined(_LIBCPP_USING_DEV_RANDOM)
82
83
random_device::random_device(const string& __token)
84
: __f_(open(__token.c_str(), O_RDONLY))
85
{
86
if (__f_ < 0)
87
__throw_system_error(errno, ("random_device failed to open " + __token).c_str());
88
}
89
90
random_device::~random_device()
91
{
92
close(__f_);
93
}
94
95
unsigned
96
random_device::operator()()
97
{
98
unsigned r;
99
size_t n = sizeof(r);
100
char* p = reinterpret_cast<char*>(&r);
101
while (n > 0)
102
{
103
ssize_t s = read(__f_, p, n);
104
if (s == 0)
105
__throw_system_error(ENODATA, "random_device got EOF");
106
if (s == -1)
107
{
108
if (errno != EINTR)
109
__throw_system_error(errno, "random_device got an unexpected error");
110
continue;
111
}
112
n -= static_cast<size_t>(s);
113
p += static_cast<size_t>(s);
114
}
115
return r;
116
}
117
118
#elif defined(_LIBCPP_USING_NACL_RANDOM)
119
120
random_device::random_device(const string& __token)
121
{
122
if (__token != "/dev/urandom")
123
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
124
int error = nacl_secure_random_init();
125
if (error)
126
__throw_system_error(error, ("random device failed to open " + __token).c_str());
127
}
128
129
random_device::~random_device()
130
{
131
}
132
133
unsigned
134
random_device::operator()()
135
{
136
unsigned r;
137
size_t n = sizeof(r);
138
size_t bytes_written;
139
int error = nacl_secure_random(&r, n, &bytes_written);
140
if (error != 0)
141
__throw_system_error(error, "random_device failed getting bytes");
142
else if (bytes_written != n)
143
__throw_runtime_error("random_device failed to obtain enough bytes");
144
return r;
145
}
146
147
#elif defined(_LIBCPP_USING_WIN32_RANDOM)
148
149
random_device::random_device(const string& __token)
150
{
151
if (__token != "/dev/urandom")
152
__throw_system_error(ENOENT, ("random device not supported " + __token).c_str());
153
}
154
155
random_device::~random_device()
156
{
157
}
158
159
unsigned
160
random_device::operator()()
161
{
162
unsigned r;
163
errno_t err = rand_s(&r);
164
if (err)
165
__throw_system_error(err, "random_device rand_s failed.");
166
return r;
167
}
168
169
#else
170
#error "Random device not implemented for this architecture"
171
#endif
172
173
double
174
random_device::entropy() const _NOEXCEPT
175
{
176
return 0;
177
}
178
179
_LIBCPP_END_NAMESPACE_STD
180
181