]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* boost uuid/detail/random_provider_posix implementation |
2 | * | |
3 | * Copyright Jens Maurer 2000 | |
4 | * Copyright 2007 Andy Tompkins. | |
5 | * Copyright Steven Watanabe 2010-2011 | |
6 | * Copyright 2017 James E. King III | |
7 | * | |
8 | * Distributed under the Boost Software License, Version 1.0. (See | |
9 | * accompanying file LICENSE_1_0.txt or copy at | |
92f5a8d4 | 10 | * https://www.boost.org/LICENSE_1_0.txt) |
11fdf7f2 TL |
11 | * |
12 | * $Id$ | |
13 | */ | |
14 | ||
92f5a8d4 | 15 | #include <boost/config.hpp> |
11fdf7f2 | 16 | #include <boost/core/ignore_unused.hpp> |
92f5a8d4 | 17 | #include <boost/move/core.hpp> |
11fdf7f2 TL |
18 | #include <boost/throw_exception.hpp> |
19 | #include <boost/uuid/entropy_error.hpp> | |
20 | #include <cerrno> | |
92f5a8d4 | 21 | #include <cstddef> |
11fdf7f2 TL |
22 | #include <fcntl.h> // open |
23 | #include <sys/stat.h> | |
24 | #include <sys/types.h> | |
25 | #if defined(BOOST_HAS_UNISTD_H) | |
26 | #include <unistd.h> | |
27 | #endif | |
28 | ||
29 | #ifndef BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_CLOSE | |
30 | #define BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_CLOSE ::close | |
31 | #endif | |
32 | #ifndef BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_OPEN | |
33 | #define BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_OPEN ::open | |
34 | #endif | |
35 | #ifndef BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_READ | |
36 | #define BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_READ ::read | |
37 | #endif | |
38 | ||
39 | namespace boost { | |
40 | namespace uuids { | |
41 | namespace detail { | |
42 | ||
43 | class random_provider_base | |
44 | { | |
92f5a8d4 TL |
45 | BOOST_MOVABLE_BUT_NOT_COPYABLE(random_provider_base) |
46 | ||
47 | public: | |
11fdf7f2 | 48 | random_provider_base() |
92f5a8d4 | 49 | : fd_(-1) |
11fdf7f2 TL |
50 | { |
51 | int flags = O_RDONLY; | |
52 | #if defined(O_CLOEXEC) | |
53 | flags |= O_CLOEXEC; | |
54 | #endif | |
55 | fd_ = BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_OPEN("/dev/urandom", flags); | |
56 | ||
92f5a8d4 | 57 | if (BOOST_UNLIKELY(-1 == fd_)) |
11fdf7f2 TL |
58 | { |
59 | int err = errno; | |
60 | BOOST_THROW_EXCEPTION(entropy_error(err, "open /dev/urandom")); | |
61 | } | |
62 | } | |
63 | ||
92f5a8d4 TL |
64 | random_provider_base(BOOST_RV_REF(random_provider_base) that) BOOST_NOEXCEPT : fd_(that.fd_) |
65 | { | |
66 | that.fd_ = -1; | |
67 | } | |
68 | ||
69 | random_provider_base& operator= (BOOST_RV_REF(random_provider_base) that) BOOST_NOEXCEPT | |
70 | { | |
71 | destroy(); | |
72 | fd_ = that.fd_; | |
73 | that.fd_ = -1; | |
74 | return *this; | |
75 | } | |
76 | ||
11fdf7f2 TL |
77 | ~random_provider_base() BOOST_NOEXCEPT |
78 | { | |
92f5a8d4 | 79 | destroy(); |
11fdf7f2 TL |
80 | } |
81 | ||
82 | //! Obtain entropy and place it into a memory location | |
83 | //! \param[in] buf the location to write entropy | |
84 | //! \param[in] siz the number of bytes to acquire | |
92f5a8d4 | 85 | void get_random_bytes(void *buf, std::size_t siz) |
11fdf7f2 | 86 | { |
92f5a8d4 TL |
87 | std::size_t offset = 0; |
88 | while (offset < siz) | |
11fdf7f2 TL |
89 | { |
90 | ssize_t sz = BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_READ( | |
91 | fd_, static_cast<char *>(buf) + offset, siz - offset); | |
92 | ||
92f5a8d4 | 93 | if (BOOST_UNLIKELY(sz < 0)) |
11fdf7f2 TL |
94 | { |
95 | int err = errno; | |
92f5a8d4 TL |
96 | if (err == EINTR) |
97 | continue; | |
11fdf7f2 TL |
98 | BOOST_THROW_EXCEPTION(entropy_error(err, "read")); |
99 | } | |
100 | ||
101 | offset += sz; | |
92f5a8d4 TL |
102 | } |
103 | } | |
11fdf7f2 | 104 | |
92f5a8d4 TL |
105 | private: |
106 | void destroy() BOOST_NOEXCEPT | |
107 | { | |
108 | if (fd_ >= 0) | |
109 | { | |
110 | boost::ignore_unused(BOOST_UUID_RANDOM_PROVIDER_POSIX_IMPL_CLOSE(fd_)); | |
111 | } | |
11fdf7f2 TL |
112 | } |
113 | ||
92f5a8d4 | 114 | private: |
11fdf7f2 TL |
115 | int fd_; |
116 | }; | |
117 | ||
118 | } // detail | |
119 | } // uuids | |
120 | } // boost |