| 306 | #endif // defined(linux) || defined(__linux) || defined(__linux__) |
| 307 | |
| 308 | BOOST_FILESYSTEM_DECL |
| 309 | path unique_path(path const& model, system::error_code* ec) |
| 310 | { |
| 311 | // This function used wstring for fear of misidentifying |
| 312 | // a part of a multibyte character as a percent sign. |
| 313 | // However, double byte encodings only have 80-FF as lead |
| 314 | // bytes and 40-7F as trailing bytes, whereas % is 25. |
| 315 | // So, use string on POSIX and avoid conversions. |
| 316 | |
| 317 | path::string_type s(model.native()); |
| 318 | |
| 319 | char ran[16] = {}; // init to avoid clang static analyzer message |
| 320 | // see ticket #8954 |
| 321 | BOOST_CONSTEXPR_OR_CONST unsigned int max_nibbles = 2u * sizeof(ran); // 4-bits per nibble |
| 322 | |
| 323 | unsigned int nibbles_used = max_nibbles; |
| 324 | for (path::string_type::size_type i = 0, n = s.size(); i < n; ++i) |
| 325 | { |
| 326 | if (s[i] == percent) // digit request |
| 327 | { |
| 328 | if (nibbles_used == max_nibbles) |
| 329 | { |
| 330 | system_crypt_random(ran, sizeof(ran), ec); |
| 331 | if (ec && *ec) |
| 332 | return path(); |
| 333 | nibbles_used = 0; |
| 334 | } |
| 335 | unsigned int c = ran[nibbles_used / 2u]; |
| 336 | c >>= 4u * (nibbles_used++ & 1u); // if odd, shift right 1 nibble |
| 337 | s[i] = hex[c & 0xf]; // convert to hex digit and replace |
| 338 | } |
| 339 | } |
| 340 | |
| 341 | if (ec) |
| 342 | ec->clear(); |
| 343 | |
| 344 | return s; |
| 345 | } |
| 346 | |
| 347 | } // namespace detail |
| 348 | } // namespace filesystem |