]>
git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/filesystem/src/unique_path.cpp
1 // filesystem unique_path.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 // define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
13 // the library is being built (possibly exporting rather than importing code)
14 #define BOOST_FILESYSTEM_SOURCE
16 #ifndef BOOST_SYSTEM_NO_DEPRECATED
17 # define BOOST_SYSTEM_NO_DEPRECATED
20 #include <boost/filesystem/operations.hpp>
23 # ifdef BOOST_POSIX_API
25 # ifdef BOOST_HAS_UNISTD_H
28 # else // BOOST_WINDOWS_API
30 # include <wincrypt.h>
32 # pragma comment(lib, "Advapi32.lib")
38 void fail(int err
, boost::system::error_code
* ec
)
41 BOOST_FILESYSTEM_THROW( boost::system::system_error(err
,
42 boost::system::system_category(),
43 "boost::filesystem::unique_path"));
45 ec
->assign(err
, boost::system::system_category());
49 #ifdef BOOST_WINDOWS_API
51 int acquire_crypt_handle(HCRYPTPROV
& handle
)
53 if (::CryptAcquireContextW(&handle
, 0, 0, PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
56 int errval
= ::GetLastError();
57 if (errval
!= NTE_BAD_KEYSET
)
60 if (::CryptAcquireContextW(&handle
, 0, 0, PROV_RSA_FULL
, CRYPT_NEWKEYSET
| CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
63 errval
= ::GetLastError();
64 // Another thread could have attempted to create the keyset at the same time.
65 if (errval
!= NTE_EXISTS
)
68 if (::CryptAcquireContextW(&handle
, 0, 0, PROV_RSA_FULL
, CRYPT_VERIFYCONTEXT
| CRYPT_SILENT
))
71 return ::GetLastError();
76 void system_crypt_random(void* buf
, std::size_t len
, boost::system::error_code
* ec
)
78 # ifdef BOOST_POSIX_API
80 int file
= open("/dev/urandom", O_RDONLY
);
83 file
= open("/dev/random", O_RDONLY
);
91 size_t bytes_read
= 0;
92 while (bytes_read
< len
)
94 ssize_t n
= read(file
, buf
, len
- bytes_read
);
102 buf
= static_cast<char*>(buf
) + n
;
107 # else // BOOST_WINDOWS_API
110 int errval
= acquire_crypt_handle(handle
);
114 BOOL gen_ok
= ::CryptGenRandom(handle
, len
, static_cast<unsigned char*>(buf
));
116 errval
= ::GetLastError();
117 ::CryptReleaseContext(handle
, 0);
126 } // unnamed namespace
128 namespace boost
{ namespace filesystem
{ namespace detail
{
130 BOOST_FILESYSTEM_DECL
131 path
unique_path(const path
& model
, system::error_code
* ec
)
133 std::wstring
s (model
.wstring()); // std::string ng for MBCS encoded POSIX
134 const wchar_t hex
[] = L
"0123456789abcdef";
135 char ran
[] = "123456789abcdef"; // init to avoid clang static analyzer message
137 assert(sizeof(ran
) == 16);
138 const int max_nibbles
= 2 * sizeof(ran
); // 4-bits per nibble
140 int nibbles_used
= max_nibbles
;
141 for(std::wstring::size_type i
=0; i
< s
.size(); ++i
)
143 if (s
[i
] == L
'%') // digit request
145 if (nibbles_used
== max_nibbles
)
147 system_crypt_random(ran
, sizeof(ran
), ec
);
152 int c
= ran
[nibbles_used
/2];
153 c
>>= 4 * (nibbles_used
++ & 1); // if odd, shift right 1 nibble
154 s
[i
] = hex
[c
& 0xf]; // convert to hex digit and replace
158 if (ec
!= 0) ec
->clear();