1 | // |
2 | // Copyright (c) 2018 Andrey Semashev |
3 | // |
4 | // Distributed under the Boost Software License, Version 1.0. |
5 | // (See accompanying file LICENSE_1_0.txt or copy at |
6 | // https://www.boost.org/LICENSE_1_0.txt) |
7 | // |
8 | // getrandom() capable platforms |
9 | // |
10 | |
11 | #include <boost/config.hpp> |
12 | #include <boost/throw_exception.hpp> |
13 | #include <boost/predef/library/c/gnu.h> |
14 | #include <cerrno> |
15 | #include <cstddef> |
16 | |
17 | #if !defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_IMPL_GETRANDOM) && !defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_DISABLE_LIBC_WRAPPER) |
18 | #if BOOST_LIB_C_GNU >= BOOST_VERSION_NUMBER(2, 25, 0) |
19 | #define BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_HAS_LIBC_WRAPPER |
20 | #elif defined(__has_include) |
21 | #if __has_include(<sys/random.h>) |
22 | #define BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_HAS_LIBC_WRAPPER |
23 | #endif |
24 | #endif |
25 | #endif // !defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_IMPL_GETRANDOM) && !defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_DISABLE_LIBC_WRAPPER) |
26 | |
27 | #if defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_HAS_LIBC_WRAPPER) |
28 | #include <sys/random.h> |
29 | #else |
30 | #include <stddef.h> // ssize_t |
31 | #endif |
32 | |
33 | namespace boost { |
34 | namespace uuids { |
35 | namespace detail { |
36 | |
37 | class random_provider_base |
38 | { |
39 | public: |
40 | //! Obtain entropy and place it into a memory location |
41 | //! \param[in] buf the location to write entropy |
42 | //! \param[in] siz the number of bytes to acquire |
43 | void get_random_bytes(void *buf, std::size_t siz) |
44 | { |
45 | std::size_t offset = 0; |
46 | while (offset < siz) |
47 | { |
48 | ssize_t sz = get_random(buf: static_cast< char* >(buf) + offset, size: siz - offset, flags: 0u); |
49 | |
50 | if (BOOST_UNLIKELY(sz < 0)) |
51 | { |
52 | int err = errno; |
53 | if (err == EINTR) |
54 | continue; |
55 | BOOST_THROW_EXCEPTION(entropy_error(err, "getrandom" )); |
56 | } |
57 | |
58 | offset += sz; |
59 | } |
60 | } |
61 | |
62 | private: |
63 | static ssize_t get_random(void *buf, std::size_t size, unsigned int flags) |
64 | { |
65 | #if defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_IMPL_GETRANDOM) |
66 | return BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_IMPL_GETRANDOM(buf, size, flags); |
67 | #elif defined(BOOST_UUID_RANDOM_PROVIDER_GETRANDOM_HAS_LIBC_WRAPPER) |
68 | return ::getrandom(buffer: buf, length: size, flags: flags); |
69 | #else |
70 | return ::syscall(SYS_getrandom, buf, size, flags); |
71 | #endif |
72 | } |
73 | }; |
74 | |
75 | } // detail |
76 | } // uuids |
77 | } // boost |
78 | |