1
// filesystem system_crypt_random.cpp ------------------------------------------------//
3
// Copyright Beman Dawes 2010
5
// Distributed under the Boost Software License, Version 1.0.
6
// See http://www.boost.org/LICENSE_1_0.txt
8
// Library home page: http://www.boost.org/libs/filesystem
10
//--------------------------------------------------------------------------------------//
12
#include <boost/config.hpp>
13
#if !defined( BOOST_NO_STD_WSTRING )
14
// Boost.Filesystem V3 and later requires std::wstring support.
15
// During the transition to V3, libraries are compiled with both V2 and V3 sources.
16
// On old compilers that don't support V3 anyhow, we just skip everything so the compile
17
// will succeed and the library can be built.
19
// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
20
// the library is being built (possibly exporting rather than importing code)
21
#define BOOST_FILESYSTEM_SOURCE
23
#ifndef BOOST_SYSTEM_NO_DEPRECATED
24
# define BOOST_SYSTEM_NO_DEPRECATED
27
#include <boost/filesystem/v3/operations.hpp>
29
# ifdef BOOST_POSIX_API
31
# else // BOOST_WINDOWS_API
33
# include <wincrypt.h>
34
# pragma comment(lib, "Advapi32.lib")
39
void fail(int err, boost::system::error_code* ec)
42
BOOST_FILESYSTEM_THROW( boost::system::system_error(err,
43
boost::system::system_category(),
44
"boost::filesystem::unique_path"));
46
ec->assign(err, boost::system::system_category());
50
void system_crypt_random(void* buf, std::size_t len, boost::system::error_code* ec)
52
# ifdef BOOST_POSIX_API
54
int file = open("/dev/urandom", O_RDONLY);
57
file = open("/dev/random", O_RDONLY);
65
size_t bytes_read = 0;
66
while (bytes_read < len)
68
ssize_t n = read(file, buf, len - bytes_read);
76
buf = static_cast<char*>(buf) + n;
81
# else // BOOST_WINDOWS_API
86
if (!::CryptAcquireContextW(&handle, 0, 0, PROV_RSA_FULL, 0))
88
errval = ::GetLastError();
89
if (errval == NTE_BAD_KEYSET)
91
if (!::CryptAcquireContextW(&handle, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET))
93
errval = ::GetLastError();
101
BOOL gen_ok = ::CryptGenRandom(handle, len, static_cast<unsigned char*>(buf));
103
errval = ::GetLastError();
104
::CryptReleaseContext(handle, 0);
113
} // unnamed namespace
115
namespace boost { namespace filesystem3 { namespace detail {
117
BOOST_FILESYSTEM_DECL
118
path unique_path(const path& model, system::error_code* ec)
120
std::wstring s (model.wstring()); // std::string ng for MBCS encoded POSIX
121
const wchar_t hex[] = L"0123456789abcdef";
122
const int n_ran = 16;
123
const int max_nibbles = 2 * n_ran; // 4-bits per nibble
126
int nibbles_used = max_nibbles;
127
for(std::wstring::size_type i=0; i < s.size(); ++i)
129
if (s[i] == L'%') // digit request
131
if (nibbles_used == max_nibbles)
133
system_crypt_random(ran, sizeof(ran), ec);
138
int c = ran[nibbles_used/2];
139
c >>= 4 * (nibbles_used++ & 1); // if odd, shift right 1 nibble
140
s[i] = hex[c & 0xf]; // convert to hex digit and replace
144
if (ec != 0) ec->clear();
151
#endif // no wide character support