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
15
16#include "random"
17#include "system_error"
18
19#ifdef __sun__
20#define rename solaris_headers_are_broken
21#endif
22#if !defined(_WIN32)
23extern "C" {
24#include <errno.h>
25#include <fcntl.h>
26#include <unistd.h>
27}
28#endif // defined(_WIN32)
29_LIBCPP_BEGIN_NAMESPACE_STD
30
31#if defined(_WIN32)
32random_device::random_device(const string&)
33{
34}
35
36random_device::~random_device()
37{
38}
39
40unsigned
41random_device::operator()()
42{
43    unsigned r;
44    errno_t err = rand_s(&r);
45    if (err)
46        __throw_system_error(err, "random_device rand_s failed.");
47    return r;
48}
49#else
50random_device::random_device(const string& __token)
51    : __f_(open(__token.c_str(), O_RDONLY))
52{
53    if (__f_ < 0)
54        __throw_system_error(errno, ("random_device failed to open " + __token).c_str());
55}
56
57random_device::~random_device()
58{
59    close(__f_);
60}
61
62unsigned
63random_device::operator()()
64{
65    unsigned r;
66    size_t n = sizeof(r);
67    char* p = reinterpret_cast<char*>(&r);
68    while (n > 0)
69    {
70        ssize_t s = read(__f_, p, n);
71        if (s == 0)
72            __throw_system_error(ENODATA, "random_device got EOF");
73        if (s == -1)
74        {
75            if (errno != EINTR)
76                __throw_system_error(errno, "random_device got an unexpected error");
77            continue;
78        }
79        n -= static_cast<size_t>(s);
80        p += static_cast<size_t>(s);
81    }
82    return r;
83}
84#endif // defined(_WIN32)
85
86double
87random_device::entropy() const _NOEXCEPT
88{
89    return 0;
90}
91
92_LIBCPP_END_NAMESPACE_STD
93