summaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/filesystem/src/unique_path.cpp
diff options
context:
space:
mode:
authorrobot-contrib <[email protected]>2022-08-26 11:41:38 +0300
committerrobot-contrib <[email protected]>2022-08-26 11:41:38 +0300
commit76a1e556daf2542e3b3d55d7971cc1ed0abb1f50 (patch)
treec9603488e24fef3c6715a36b7962b27cb43f0c60 /contrib/restricted/boost/filesystem/src/unique_path.cpp
parent559b3483fff94291f600c59ad6782cc6338d7dad (diff)
Update contrib/restricted/boost/filesystem and contrib/restricted/boost/io to 1.79.0
Diffstat (limited to 'contrib/restricted/boost/filesystem/src/unique_path.cpp')
-rw-r--r--contrib/restricted/boost/filesystem/src/unique_path.cpp378
1 files changed, 271 insertions, 107 deletions
diff --git a/contrib/restricted/boost/filesystem/src/unique_path.cpp b/contrib/restricted/boost/filesystem/src/unique_path.cpp
index 1b05c83944b..4815ca43698 100644
--- a/contrib/restricted/boost/filesystem/src/unique_path.cpp
+++ b/contrib/restricted/boost/filesystem/src/unique_path.cpp
@@ -1,163 +1,327 @@
// filesystem unique_path.cpp --------------------------------------------------------//
// Copyright Beman Dawes 2010
+// Copyright Andrey Semashev 2020
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
// Library home page: http://www.boost.org/libs/filesystem
-//--------------------------------------------------------------------------------------//
+//--------------------------------------------------------------------------------------//
-// define BOOST_FILESYSTEM_SOURCE so that <boost/filesystem/config.hpp> knows
-// the library is being built (possibly exporting rather than importing code)
-#define BOOST_FILESYSTEM_SOURCE
+#include "platform_config.hpp"
-#ifndef BOOST_SYSTEM_NO_DEPRECATED
-# define BOOST_SYSTEM_NO_DEPRECATED
+#include <boost/predef/library/c/cloudabi.h>
+#include <boost/predef/os/bsd/open.h>
+#include <boost/predef/os/bsd/free.h>
+
+#ifdef BOOST_POSIX_API
+
+#include <cerrno>
+#include <stddef.h>
+#include <fcntl.h>
+#ifdef BOOST_HAS_UNISTD_H
+#include <unistd.h>
+#endif
+
+#if !defined(BOOST_FILESYSTEM_DISABLE_ARC4RANDOM)
+#if BOOST_OS_BSD_OPEN >= BOOST_VERSION_NUMBER(2, 1, 0) || \
+ BOOST_OS_BSD_FREE >= BOOST_VERSION_NUMBER(8, 0, 0) || \
+ BOOST_LIB_C_CLOUDABI
+#include <stdlib.h>
+#define BOOST_FILESYSTEM_HAS_ARC4RANDOM
+#endif
+#endif // !defined(BOOST_FILESYSTEM_DISABLE_ARC4RANDOM)
+
+#if !defined(BOOST_FILESYSTEM_DISABLE_GETRANDOM)
+#if (defined(__linux__) || defined(__linux) || defined(linux)) && \
+ (!defined(__ANDROID__) || __ANDROID_API__ >= 28)
+#include <sys/syscall.h>
+#if defined(SYS_getrandom)
+#define BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL
+#endif // defined(SYS_getrandom)
+#if defined(__has_include)
+#if __has_include(<sys/random.h>)
+#define BOOST_FILESYSTEM_HAS_GETRANDOM
+#endif
+#elif defined(__GLIBC__)
+#if __GLIBC_PREREQ(2, 25)
+#define BOOST_FILESYSTEM_HAS_GETRANDOM
+#endif
+#endif // BOOST_FILESYSTEM_HAS_GETRANDOM definition
+#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM)
+#include <sys/random.h>
+#endif
+#endif // (defined(__linux__) || defined(__linux) || defined(linux)) && (!defined(__ANDROID__) || __ANDROID_API__ >= 28)
+#endif // !defined(BOOST_FILESYSTEM_DISABLE_GETRANDOM)
+
+#include "posix_tools.hpp"
+
+#else // BOOST_WINDOWS_API
+
+// We use auto-linking below to help users of static builds of Boost.Filesystem to link to whatever Windows SDK library we selected.
+// The dependency information is currently not exposed in CMake config files generated by Boost.Build (https://github.com/boostorg/boost_install/issues/18),
+// which makes it non-trivial for users to discover the libraries they need. This feature is deprecated and may be removed in the future,
+// when the situation with CMake config files improves.
+// Note that the library build system is the principal source of linking the library, which must work regardless of auto-linking.
+#include <boost/predef/platform.h>
+#include <boost/winapi/basic_types.hpp>
+
+#if defined(BOOST_FILESYSTEM_HAS_BCRYPT) // defined on the command line by the project
+#include <boost/winapi/error_codes.hpp>
+#include <boost/winapi/bcrypt.hpp>
+#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER)
+#pragma comment(lib, "bcrypt.lib")
+#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER)
+#else // defined(BOOST_FILESYSTEM_HAS_BCRYPT)
+#include <boost/winapi/crypt.hpp>
+#include <boost/winapi/get_last_error.hpp>
+#if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER)
+#if !defined(_WIN32_WCE)
+#pragma comment(lib, "advapi32.lib")
+#else
+#pragma comment(lib, "coredll.lib")
#endif
+#endif // !defined(BOOST_FILESYSTEM_NO_DEPRECATED) && defined(_MSC_VER)
+#endif // defined(BOOST_FILESYSTEM_HAS_BCRYPT)
+#endif // BOOST_POSIX_API
+
+#include <cstddef>
+#include <boost/filesystem/config.hpp>
#include <boost/filesystem/operations.hpp>
-#include <cassert>
-
-# ifdef BOOST_POSIX_API
-# include <fcntl.h>
-# ifdef BOOST_HAS_UNISTD_H
-# include <unistd.h>
-# endif
-# else // BOOST_WINDOWS_API
-# include <windows.h>
-# include <wincrypt.h>
-# ifdef _MSC_VER
-# pragma comment(lib, "Advapi32.lib")
-# endif
-# endif
+#include "private_config.hpp"
+#include "atomic_tools.hpp"
+#include "error_handling.hpp"
+
+#if defined(BOOST_POSIX_API)
+// At least Mac OS X 10.6 and older doesn't support O_CLOEXEC
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+#endif // defined(BOOST_POSIX_API)
+
+namespace boost {
+namespace filesystem {
+namespace detail {
namespace {
-void fail(int err, boost::system::error_code* ec)
+#if defined(BOOST_POSIX_API) && !defined(BOOST_FILESYSTEM_HAS_ARC4RANDOM)
+
+//! Fills buffer with cryptographically random data obtained from /dev/(u)random
+int fill_random_dev_random(void* buf, std::size_t len)
{
- if (ec == 0)
- BOOST_FILESYSTEM_THROW( boost::system::system_error(err,
- boost::system::system_category(),
- "boost::filesystem::unique_path"));
+ int file = ::open("/dev/urandom", O_RDONLY | O_CLOEXEC);
+ if (file == -1)
+ {
+ file = ::open("/dev/random", O_RDONLY | O_CLOEXEC);
+ if (file == -1)
+ return errno;
+ }
- ec->assign(err, boost::system::system_category());
- return;
+ std::size_t bytes_read = 0u;
+ while (bytes_read < len)
+ {
+ ssize_t n = ::read(file, buf, len - bytes_read);
+ if (BOOST_UNLIKELY(n == -1))
+ {
+ int err = errno;
+ if (err == EINTR)
+ continue;
+ close_fd(file);
+ return err;
+ }
+ bytes_read += n;
+ buf = static_cast< char* >(buf) + n;
+ }
+
+ close_fd(file);
+ return 0;
}
-#ifdef BOOST_WINDOWS_API
+#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL)
+
+typedef int fill_random_t(void* buf, std::size_t len);
+
+//! Pointer to the implementation of fill_random.
+fill_random_t* fill_random = &fill_random_dev_random;
-int acquire_crypt_handle(HCRYPTPROV& handle)
+//! Fills buffer with cryptographically random data obtained from getrandom()
+int fill_random_getrandom(void* buf, std::size_t len)
{
- if (::CryptAcquireContextW(&handle, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
+ std::size_t bytes_read = 0u;
+ while (bytes_read < len)
+ {
+#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM)
+ ssize_t n = ::getrandom(buf, len - bytes_read, 0u);
+#else
+ ssize_t n = ::syscall(SYS_getrandom, buf, len - bytes_read, 0u);
+#endif
+ if (BOOST_UNLIKELY(n < 0))
+ {
+ const int err = errno;
+ if (err == EINTR)
+ continue;
+
+ if (err == ENOSYS && bytes_read == 0u)
+ {
+ filesystem::detail::atomic_store_relaxed(fill_random, &fill_random_dev_random);
+ return fill_random_dev_random(buf, len);
+ }
+
+ return err;
+ }
+
+ bytes_read += n;
+ buf = static_cast< char* >(buf) + n;
+ }
+
return 0;
+}
- int errval = ::GetLastError();
- if (errval != NTE_BAD_KEYSET)
- return errval;
+#endif // defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL)
- if (::CryptAcquireContextW(&handle, 0, 0, PROV_RSA_FULL, CRYPT_NEWKEYSET | CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- return 0;
+#endif // defined(BOOST_POSIX_API) && !defined(BOOST_FILESYSTEM_HAS_ARC4RANDOM)
+
+void system_crypt_random(void* buf, std::size_t len, boost::system::error_code* ec)
+{
+#if defined(BOOST_POSIX_API)
- errval = ::GetLastError();
- // Another thread could have attempted to create the keyset at the same time.
- if (errval != NTE_EXISTS)
- return errval;
+#if defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL)
- if (::CryptAcquireContextW(&handle, 0, 0, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
- return 0;
+ int err = filesystem::detail::atomic_load_relaxed(fill_random)(buf, len);
+ if (BOOST_UNLIKELY(err != 0))
+ emit_error(err, ec, "boost::filesystem::unique_path");
- return ::GetLastError();
-}
+#elif defined(BOOST_FILESYSTEM_HAS_ARC4RANDOM)
+
+ arc4random_buf(buf, len);
+
+#else
+
+ int err = fill_random_dev_random(buf, len);
+ if (BOOST_UNLIKELY(err != 0))
+ emit_error(err, ec, "boost::filesystem::unique_path");
#endif
-void system_crypt_random(void* buf, std::size_t len, boost::system::error_code* ec)
-{
-# ifdef BOOST_POSIX_API
+#else // defined(BOOST_POSIX_API)
- int file = open("/dev/urandom", O_RDONLY);
- if (file == -1)
- {
- file = open("/dev/random", O_RDONLY);
- if (file == -1)
+#if defined(BOOST_FILESYSTEM_HAS_BCRYPT)
+
+ boost::winapi::BCRYPT_ALG_HANDLE_ handle;
+ boost::winapi::NTSTATUS_ status = boost::winapi::BCryptOpenAlgorithmProvider(&handle, boost::winapi::BCRYPT_RNG_ALGORITHM_, NULL, 0);
+ if (BOOST_UNLIKELY(status != 0))
{
- fail(errno, ec);
- return;
+ fail:
+ emit_error(translate_ntstatus(status), ec, "boost::filesystem::unique_path");
+ return;
}
- }
- size_t bytes_read = 0;
- while (bytes_read < len)
- {
- ssize_t n = read(file, buf, len - bytes_read);
- if (n == -1)
+ status = boost::winapi::BCryptGenRandom(handle, static_cast< boost::winapi::PUCHAR_ >(buf), static_cast< boost::winapi::ULONG_ >(len), 0);
+
+ boost::winapi::BCryptCloseAlgorithmProvider(handle, 0);
+
+ if (BOOST_UNLIKELY(status != 0))
+ goto fail;
+
+#else // defined(BOOST_FILESYSTEM_HAS_BCRYPT)
+
+ boost::winapi::HCRYPTPROV_ handle;
+ boost::winapi::DWORD_ err = 0u;
+ if (BOOST_UNLIKELY(!boost::winapi::CryptAcquireContextW(&handle, NULL, NULL, boost::winapi::PROV_RSA_FULL_, boost::winapi::CRYPT_VERIFYCONTEXT_ | boost::winapi::CRYPT_SILENT_)))
{
- close(file);
- fail(errno, ec);
- return;
+ err = boost::winapi::GetLastError();
+
+ fail:
+ emit_error(err, ec, "boost::filesystem::unique_path");
+ return;
}
- bytes_read += n;
- buf = static_cast<char*>(buf) + n;
- }
- close(file);
+ boost::winapi::BOOL_ gen_ok = boost::winapi::CryptGenRandom(handle, static_cast< boost::winapi::DWORD_ >(len), static_cast< boost::winapi::BYTE_* >(buf));
-# else // BOOST_WINDOWS_API
+ if (BOOST_UNLIKELY(!gen_ok))
+ err = boost::winapi::GetLastError();
- HCRYPTPROV handle;
- int errval = acquire_crypt_handle(handle);
+ boost::winapi::CryptReleaseContext(handle, 0);
- if (!errval)
- {
- BOOL gen_ok = ::CryptGenRandom(handle, len, static_cast<unsigned char*>(buf));
- if (!gen_ok)
- errval = ::GetLastError();
- ::CryptReleaseContext(handle, 0);
- }
+ if (BOOST_UNLIKELY(!gen_ok))
+ goto fail;
- if (!errval) return;
+#endif // defined(BOOST_FILESYSTEM_HAS_BCRYPT)
- fail(errval, ec);
-# endif
+#endif // defined(BOOST_POSIX_API)
}
-} // unnamed namespace
+#ifdef BOOST_WINDOWS_API
+BOOST_CONSTEXPR_OR_CONST wchar_t hex[] = L"0123456789abcdef";
+BOOST_CONSTEXPR_OR_CONST wchar_t percent = L'%';
+#else
+BOOST_CONSTEXPR_OR_CONST char hex[] = "0123456789abcdef";
+BOOST_CONSTEXPR_OR_CONST char percent = '%';
+#endif
+
+} // unnamed namespace
+
+#if defined(linux) || defined(__linux) || defined(__linux__)
+
+//! Initializes fill_random implementation pointer
+void init_fill_random_impl(unsigned int major_ver, unsigned int minor_ver, unsigned int patch_ver)
+{
+#if defined(BOOST_FILESYSTEM_HAS_INIT_PRIORITY) && \
+ (defined(BOOST_FILESYSTEM_HAS_GETRANDOM) || defined(BOOST_FILESYSTEM_HAS_GETRANDOM_SYSCALL))
+ fill_random_t* fr = &fill_random_dev_random;
+
+ if (major_ver > 3u || (major_ver == 3u && minor_ver >= 17u))
+ fr = &fill_random_getrandom;
+
+ filesystem::detail::atomic_store_relaxed(fill_random, fr);
+#endif
+}
-namespace boost { namespace filesystem { namespace detail {
+#endif // defined(linux) || defined(__linux) || defined(__linux__)
BOOST_FILESYSTEM_DECL
-path unique_path(const path& model, system::error_code* ec)
+path unique_path(path const& model, system::error_code* ec)
{
- std::wstring s (model.wstring()); // std::string ng for MBCS encoded POSIX
- const wchar_t hex[] = L"0123456789abcdef";
- char ran[] = "123456789abcdef"; // init to avoid clang static analyzer message
- // see ticket #8954
- assert(sizeof(ran) == 16);
- const int max_nibbles = 2 * sizeof(ran); // 4-bits per nibble
-
- int nibbles_used = max_nibbles;
- for(std::wstring::size_type i=0; i < s.size(); ++i)
- {
- if (s[i] == L'%') // digit request
+ // This function used wstring for fear of misidentifying
+ // a part of a multibyte character as a percent sign.
+ // However, double byte encodings only have 80-FF as lead
+ // bytes and 40-7F as trailing bytes, whereas % is 25.
+ // So, use string on POSIX and avoid conversions.
+
+ path::string_type s(model.native());
+
+ char ran[16] = {}; // init to avoid clang static analyzer message
+ // see ticket #8954
+ BOOST_CONSTEXPR_OR_CONST unsigned int max_nibbles = 2u * sizeof(ran); // 4-bits per nibble
+
+ unsigned int nibbles_used = max_nibbles;
+ for (path::string_type::size_type i = 0, n = s.size(); i < n; ++i)
{
- if (nibbles_used == max_nibbles)
- {
- system_crypt_random(ran, sizeof(ran), ec);
- if (ec != 0 && *ec)
- return "";
- nibbles_used = 0;
- }
- int c = ran[nibbles_used/2];
- c >>= 4 * (nibbles_used++ & 1); // if odd, shift right 1 nibble
- s[i] = hex[c & 0xf]; // convert to hex digit and replace
+ if (s[i] == percent) // digit request
+ {
+ if (nibbles_used == max_nibbles)
+ {
+ system_crypt_random(ran, sizeof(ran), ec);
+ if (ec && *ec)
+ return path();
+ nibbles_used = 0;
+ }
+ unsigned int c = ran[nibbles_used / 2u];
+ c >>= 4u * (nibbles_used++ & 1u); // if odd, shift right 1 nibble
+ s[i] = hex[c & 0xf]; // convert to hex digit and replace
+ }
}
- }
- if (ec != 0) ec->clear();
+ if (ec)
+ ec->clear();
- return s;
+ return s;
}
-}}}
+} // namespace detail
+} // namespace filesystem
+} // namespace boost