diff options
author | robot-contrib <[email protected]> | 2024-12-17 07:25:06 +0300 |
---|---|---|
committer | robot-contrib <[email protected]> | 2024-12-17 07:47:50 +0300 |
commit | ea02bc3d382abec44b915e46fc1180d422ec6a7b (patch) | |
tree | d99855e0dcad2e617739468f541cb0176dbfb441 | |
parent | f441f2b31a6b0ffc68514b7423f0611f84ae51cd (diff) |
Update contrib/restricted/boost/filesystem to 1.87.0
commit_hash:4ae470ee0a64c2c69b2319fd92c4178fa8790ab2
5 files changed, 176 insertions, 146 deletions
diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp index 416c0737881..4cd81a2e733 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/path_traits.hpp @@ -25,6 +25,7 @@ #include <boost/assert.hpp> #include <boost/system/error_category.hpp> #include <boost/iterator/is_iterator.hpp> +#include <boost/filesystem/detail/type_traits/negation.hpp> #include <boost/filesystem/detail/type_traits/conjunction.hpp> #if defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) #include <boost/filesystem/detail/type_traits/disjunction.hpp> @@ -48,6 +49,7 @@ namespace filesystem { BOOST_FILESYSTEM_DECL system::error_category const& codecvt_error_category() noexcept; +class path; class directory_entry; namespace detail { @@ -501,9 +503,8 @@ no_type check_convertible(...); } // namespace is_convertible_to_path_source_impl -//! The type trait indicates whether the type has a conversion path to one of the path source types template< typename T > -struct is_convertible_to_path_source : +struct check_is_convertible_to_path_source : public std::integral_constant< bool, sizeof(is_convertible_to_path_source_impl::check_convertible(std::declval< T const& >())) == sizeof(yes_type) @@ -511,6 +512,25 @@ struct is_convertible_to_path_source : { }; +/*! + * \brief The type trait indicates whether the type has a conversion path to one of the path source types. + * + * \note The type trait returns `false` if the type is convertible to `path`. This prevents testing other + * conversion paths and forces the conversion to `path` to be chosen instead, to invoke a non-template + * member of `path` accepting a `path` argument. + */ +template< typename T > +struct is_convertible_to_path_source : + public std::integral_constant< + bool, + detail::conjunction< + detail::negation< std::is_convertible< T, path > >, + check_is_convertible_to_path_source< T > + >::value + > +{ +}; + #else // !defined(BOOST_FILESYSTEM_DETAIL_CXX23_STRING_VIEW_HAS_IMPLICIT_RANGE_CTOR) // Note: We use separate checks for convertibility to std::string_view and other types to avoid ambiguity with an implicit range constructor @@ -529,7 +549,7 @@ no_type check_convertible(...); } // namespace is_convertible_to_std_string_view_impl template< typename T > -struct is_convertible_to_std_string_view : +struct check_is_convertible_to_std_string_view : public std::integral_constant< bool, sizeof(is_convertible_to_std_string_view_impl::check_convertible(std::declval< T const& >())) == sizeof(yes_type) @@ -553,7 +573,7 @@ no_type check_convertible(...); } // namespace is_convertible_to_path_source_non_std_string_view_impl template< typename T > -struct is_convertible_to_path_source_non_std_string_view : +struct check_is_convertible_to_path_source_non_std_string_view : public std::integral_constant< bool, sizeof(is_convertible_to_path_source_non_std_string_view_impl::check_convertible(std::declval< T const& >())) == sizeof(yes_type) @@ -561,14 +581,23 @@ struct is_convertible_to_path_source_non_std_string_view : { }; -//! The type trait indicates whether the type has a conversion path to one of the path source types +/*! + * \brief The type trait indicates whether the type has a conversion path to one of the path source types. + * + * \note The type trait returns `false` if the type is convertible to `path`. This prevents testing other + * conversion paths and forces the conversion to `path` to be chosen instead, to invoke a non-template + * member of `path` accepting a `path` argument. + */ template< typename T > struct is_convertible_to_path_source : public std::integral_constant< bool, - detail::disjunction< - is_convertible_to_std_string_view< T >, - is_convertible_to_path_source_non_std_string_view< T > + detail::conjunction< + detail::negation< std::is_convertible< T, path > >, + detail::disjunction< + check_is_convertible_to_std_string_view< T >, + check_is_convertible_to_path_source_non_std_string_view< T > + > >::value > { @@ -704,7 +733,7 @@ BOOST_FORCEINLINE typename Callback::result_type dispatch_convertible_sv_impl(st template< typename Source, typename Callback > BOOST_FORCEINLINE typename std::enable_if< - !is_convertible_to_std_string_view< typename std::remove_cv< Source >::type >::value, + !check_is_convertible_to_std_string_view< typename std::remove_cv< Source >::type >::value, typename Callback::result_type >::type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = nullptr) { @@ -714,7 +743,7 @@ BOOST_FORCEINLINE typename std::enable_if< template< typename Source, typename Callback > BOOST_FORCEINLINE typename std::enable_if< - is_convertible_to_std_string_view< typename std::remove_cv< Source >::type >::value, + check_is_convertible_to_std_string_view< typename std::remove_cv< Source >::type >::value, typename Callback::result_type >::type dispatch_convertible(Source const& source, Callback cb, const codecvt_type* cvt = nullptr) { diff --git a/contrib/restricted/boost/filesystem/src/directory.cpp b/contrib/restricted/boost/filesystem/src/directory.cpp index 576a460dd3d..113fef893bf 100644 --- a/contrib/restricted/boost/filesystem/src/directory.cpp +++ b/contrib/restricted/boost/filesystem/src/directory.cpp @@ -270,7 +270,8 @@ inline system::error_code dir_itr_close(dir_itr_imp& imp) noexcept // Obtains a file descriptor from the directory iterator inline int dir_itr_fd(dir_itr_imp const& imp, system::error_code& ec) { - int fd = ::dirfd(static_cast< DIR* >(imp.handle)); + // Note: dirfd is a macro on FreeBSD 9 and older + const int fd = dirfd(static_cast< DIR* >(imp.handle)); if (BOOST_UNLIKELY(fd < 0)) { int err = errno; @@ -362,7 +363,7 @@ int readdir_select_impl(dir_itr_imp& imp, struct dirent** result); typedef int readdir_impl_t(dir_itr_imp& imp, struct dirent** result); -//! Pointer to the actual implementation of the copy_file_data implementation +//! Pointer to the actual implementation of readdir readdir_impl_t* readdir_impl_ptr = &readdir_select_impl; void init_readdir_impl() @@ -799,7 +800,7 @@ system::error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::f if (!NT_SUCCESS(status)) { dir_itr_close(imp); - if (status == STATUS_NO_MORE_FILES) + if (BOOST_NTSTATUS_EQ(status, STATUS_NO_MORE_FILES)) goto done; return system::error_code(translate_ntstatus(status), system::system_category()); @@ -1047,7 +1048,7 @@ system::error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& i // causes a ERROR_FILE_NOT_FOUND error returned from FindFirstFileW // (which is presumably equivalent to STATUS_NO_SUCH_FILE) which we // do not consider an error. It is treated as eof instead. - if (status == STATUS_NO_MORE_FILES || status == STATUS_NO_SUCH_FILE) + if (BOOST_NTSTATUS_EQ(status, STATUS_NO_MORE_FILES) || BOOST_NTSTATUS_EQ(status, STATUS_NO_SUCH_FILE)) goto done; return error_code(translate_ntstatus(status), system_category()); @@ -1520,7 +1521,7 @@ void recursive_directory_iterator_increment(recursive_directory_iterator& it, sy { symlink_ft = detail::status_by_handle(direntry_handle.get(), dir_it->path(), &ec).type(); } - else if (status == STATUS_NOT_IMPLEMENTED) + else if (BOOST_NTSTATUS_EQ(status, STATUS_NOT_IMPLEMENTED)) { symlink_ft = dir_it->symlink_file_type(ec); } @@ -1615,7 +1616,7 @@ void recursive_directory_iterator_increment(recursive_directory_iterator& it, sy { goto get_file_type_by_handle; } - else if (status == STATUS_NOT_IMPLEMENTED) + else if (BOOST_NTSTATUS_EQ(status, STATUS_NOT_IMPLEMENTED)) { ft = dir_it->file_type(ec); } diff --git a/contrib/restricted/boost/filesystem/src/error_handling.hpp b/contrib/restricted/boost/filesystem/src/error_handling.hpp index a83d92e9762..a335756d140 100644 --- a/contrib/restricted/boost/filesystem/src/error_handling.hpp +++ b/contrib/restricted/boost/filesystem/src/error_handling.hpp @@ -51,6 +51,10 @@ typedef boost::winapi::DWORD_ err_t; #define BOOST_ERROR_ALREADY_EXISTS boost::winapi::ERROR_ALREADY_EXISTS_ #define BOOST_ERROR_NOT_SUPPORTED boost::winapi::ERROR_NOT_SUPPORTED_ +// STATUS_* constants defined in ntstatus.h in some SDKs are defined as DWORDs, and NTSTATUS is LONG. +// This results in signed/unsigned mismatch warnings emitted by gcc and clang. Consider that a platform bug. +#define BOOST_NTSTATUS_EQ(x, y) static_cast< boost::winapi::ULONG_ >(x) == static_cast< boost::winapi::ULONG_ >(y) + // Note: Legacy MinGW doesn't have ntstatus.h and doesn't define NTSTATUS error codes other than STATUS_SUCCESS. #if !defined(NT_SUCCESS) #define NT_SUCCESS(Status) (((boost::winapi::NTSTATUS_)(Status)) >= 0) @@ -171,8 +175,9 @@ inline boost::winapi::DWORD_ translate_ntstatus(boost::winapi::NTSTATUS_ status) //! Tests if the NTSTATUS indicates that the file is not found inline bool not_found_ntstatus(boost::winapi::NTSTATUS_ status) noexcept { - return status == STATUS_NO_SUCH_FILE || status == STATUS_OBJECT_NAME_NOT_FOUND || status == STATUS_OBJECT_PATH_NOT_FOUND || - status == STATUS_BAD_NETWORK_PATH || status == STATUS_BAD_NETWORK_NAME; + return BOOST_NTSTATUS_EQ(status, STATUS_NO_SUCH_FILE) || BOOST_NTSTATUS_EQ(status, STATUS_OBJECT_NAME_NOT_FOUND) || + BOOST_NTSTATUS_EQ(status, STATUS_OBJECT_PATH_NOT_FOUND) || BOOST_NTSTATUS_EQ(status, STATUS_BAD_NETWORK_PATH) || + BOOST_NTSTATUS_EQ(status, STATUS_BAD_NETWORK_NAME); } #endif diff --git a/contrib/restricted/boost/filesystem/src/operations.cpp b/contrib/restricted/boost/filesystem/src/operations.cpp index e2fa2354516..cb31c50c68c 100644 --- a/contrib/restricted/boost/filesystem/src/operations.cpp +++ b/contrib/restricted/boost/filesystem/src/operations.cpp @@ -263,11 +263,11 @@ namespace { // The number of retries remove_all should make if it detects that the directory it is about to enter has been replaced with a symlink or a regular file BOOST_CONSTEXPR_OR_CONST unsigned int remove_all_directory_replaced_retry_count = 5u; -#if defined(BOOST_POSIX_API) - // Size of a small buffer for a path that can be placed on stack, in character code units BOOST_CONSTEXPR_OR_CONST std::size_t small_path_size = 1024u; +#if defined(BOOST_POSIX_API) + // Absolute maximum path length, in character code units, that we're willing to accept from various system calls. // This value is arbitrary, it is supposed to be a hard limit to avoid memory exhaustion // in some of the algorithms below in case of some corrupted or maliciously broken filesystem. @@ -805,7 +805,7 @@ int copy_file_data_read_write(int infile, int outfile, uintmax_t size, std::size typedef int copy_file_data_t(int infile, int outfile, uintmax_t size, std::size_t blksize); -//! Pointer to the actual implementation of the copy_file_data implementation +//! Pointer to the actual implementation of copy_file_data copy_file_data_t* copy_file_data = ©_file_data_read_write; #if defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) @@ -1401,12 +1401,12 @@ BOOST_FILESYSTEM_INIT_FUNC init_winapi_func_ptrs() boost::winapi::HMODULE_ h = boost::winapi::GetModuleHandleW(L"kernel32.dll"); if (BOOST_LIKELY(!!h)) { - GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = (GetFileInformationByHandleEx_t*)boost::winapi::get_proc_address(h, "GetFileInformationByHandleEx"); + GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = boost::winapi::get_proc_address<GetFileInformationByHandleEx_t*>(h, "GetFileInformationByHandleEx"); filesystem::detail::atomic_store_relaxed(get_file_information_by_handle_ex_api, get_file_information_by_handle_ex); - SetFileInformationByHandle_t* set_file_information_by_handle = (SetFileInformationByHandle_t*)boost::winapi::get_proc_address(h, "SetFileInformationByHandle"); + SetFileInformationByHandle_t* set_file_information_by_handle = boost::winapi::get_proc_address<SetFileInformationByHandle_t*>(h, "SetFileInformationByHandle"); filesystem::detail::atomic_store_relaxed(set_file_information_by_handle_api, set_file_information_by_handle); - filesystem::detail::atomic_store_relaxed(create_hard_link_api, (CreateHardLinkW_t*)boost::winapi::get_proc_address(h, "CreateHardLinkW")); - filesystem::detail::atomic_store_relaxed(create_symbolic_link_api, (CreateSymbolicLinkW_t*)boost::winapi::get_proc_address(h, "CreateSymbolicLinkW")); + filesystem::detail::atomic_store_relaxed(create_hard_link_api, boost::winapi::get_proc_address<CreateHardLinkW_t*>(h, "CreateHardLinkW")); + filesystem::detail::atomic_store_relaxed(create_symbolic_link_api, boost::winapi::get_proc_address<CreateSymbolicLinkW_t*>(h, "CreateSymbolicLinkW")); if (get_file_information_by_handle_ex && set_file_information_by_handle) { @@ -1419,8 +1419,8 @@ BOOST_FILESYSTEM_INIT_FUNC init_winapi_func_ptrs() h = boost::winapi::GetModuleHandleW(L"ntdll.dll"); if (BOOST_LIKELY(!!h)) { - filesystem::detail::atomic_store_relaxed(nt_create_file_api, (NtCreateFile_t*)boost::winapi::get_proc_address(h, "NtCreateFile")); - filesystem::detail::atomic_store_relaxed(nt_query_directory_file_api, (NtQueryDirectoryFile_t*)boost::winapi::get_proc_address(h, "NtQueryDirectoryFile")); + filesystem::detail::atomic_store_relaxed(nt_create_file_api, boost::winapi::get_proc_address<NtCreateFile_t*>(h, "NtCreateFile")); + filesystem::detail::atomic_store_relaxed(nt_query_directory_file_api, boost::winapi::get_proc_address<NtQueryDirectoryFile_t*>(h, "NtQueryDirectoryFile")); } init_directory_iterator_impl(); @@ -1559,7 +1559,7 @@ boost::winapi::NTSTATUS_ nt_create_file_handle_at { NtCreateFile_t* nt_create_file = filesystem::detail::atomic_load_relaxed(nt_create_file_api); if (BOOST_UNLIKELY(!nt_create_file)) - return STATUS_NOT_IMPLEMENTED; + return static_cast< boost::winapi::NTSTATUS_ >(STATUS_NOT_IMPLEMENTED); unicode_string obj_name = {}; obj_name.Buffer = const_cast< wchar_t* >(p.c_str()); @@ -1591,7 +1591,7 @@ boost::winapi::NTSTATUS_ nt_create_file_handle_at 0u // EaLength ); - if (BOOST_UNLIKELY(status == STATUS_INVALID_PARAMETER && (obj_attrs.Attributes & OBJ_DONT_REPARSE) != 0u)) + if (BOOST_UNLIKELY(BOOST_NTSTATUS_EQ(status, STATUS_INVALID_PARAMETER) && (obj_attrs.Attributes & OBJ_DONT_REPARSE) != 0u)) { // OBJ_DONT_REPARSE is supported since Windows 10, retry without it filesystem::detail::atomic_store_relaxed(g_no_obj_dont_reparse, true); @@ -2383,7 +2383,7 @@ inline path convert_nt_path_to_win32_path(const wchar_t* nt_path, std::size_t si ( // Check if the following is a drive letter ( - detail::is_letter(nt_path[pos]) && nt_path[pos + 1u] == colon && + nt_path[pos + 1u] == colon && detail::is_letter(nt_path[pos]) && ((size - pos) == 2u || detail::is_directory_separator(nt_path[pos + 2u])) ) || // Check for an "incorrect" syntax for UNC path junction points @@ -2565,15 +2565,11 @@ path absolute_v4(path const& p, path const& base, system::error_code* ec) return res; } -BOOST_FILESYSTEM_DECL -path canonical_v3(path const& p, path const& base, system::error_code* ec) +namespace { + +inline path canonical_common(path& source, system::error_code* ec) { - path source(detail::absolute_v3(p, base, ec)); - if (ec && *ec) - { - return_empty_path: - return path(); - } +#if defined(BOOST_POSIX_API) system::error_code local_ec; file_status st(detail::status_impl(source, &local_ec)); @@ -2590,7 +2586,9 @@ path canonical_v3(path const& p, path const& base, system::error_code* ec) BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::canonical", source, local_ec)); *ec = local_ec; - goto return_empty_path; + + return_empty_path: + return path(); } path root(source.root_path()); @@ -2602,6 +2600,8 @@ path canonical_v3(path const& p, path const& base, system::error_code* ec) { for (path::iterator itr(source.begin()), end(source.end()); itr != end; path_algorithms::increment_v4(itr)) { + if (itr->empty()) + continue; if (path_algorithms::compare_v4(*itr, dot_p) == 0) continue; if (path_algorithms::compare_v4(*itr, dot_dot_p) == 0) @@ -2624,12 +2624,6 @@ path canonical_v3(path const& p, path const& base, system::error_code* ec) path_algorithms::append_v4(result, *itr); - // If we don't have an absolute path yet then don't check symlink status. - // This avoids checking "C:" which is "the current directory on drive C" - // and hence not what we want to check/resolve here. - if (!result.is_absolute()) - continue; - st = detail::symlink_status_impl(result, ec); if (ec && *ec) goto return_empty_path; @@ -2656,7 +2650,7 @@ path canonical_v3(path const& p, path const& base, system::error_code* ec) if (path_algorithms::compare_v4(*itr, dot_p) != 0) path_algorithms::append_v4(link, *itr); } - source = link; + source = std::move(link); root = source.root_path(); } else // link is relative @@ -2672,7 +2666,7 @@ path canonical_v3(path const& p, path const& base, system::error_code* ec) if (path_algorithms::compare_v4(*itr, dot_p) != 0) path_algorithms::append_v4(new_source, *itr); } - source = new_source; + source = std::move(new_source); } // symlink causes scan to be restarted @@ -2688,131 +2682,132 @@ path canonical_v3(path const& p, path const& base, system::error_code* ec) BOOST_ASSERT_MSG(result.is_absolute(), "canonical() implementation error; please report"); return result; -} -BOOST_FILESYSTEM_DECL -path canonical_v4(path const& p, path const& base, system::error_code* ec) -{ - path source(detail::absolute_v4(p, base, ec)); - if (ec && *ec) - { - return_empty_path: - return path(); - } +#else // defined(BOOST_POSIX_API) - system::error_code local_ec; - file_status st(detail::status_impl(source, &local_ec)); + unique_handle h(create_file_handle( + source.c_str(), + FILE_READ_ATTRIBUTES | FILE_READ_EA, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, // lpSecurityAttributes + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); - if (st.type() == fs::file_not_found) - { - local_ec = system::errc::make_error_code(system::errc::no_such_file_or_directory); - goto fail_local_ec; - } - else if (local_ec) + DWORD err; + if (!h) { - fail_local_ec: - if (!ec) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::canonical", source, local_ec)); + err = ::GetLastError(); - *ec = local_ec; - goto return_empty_path; + fail_err: + emit_error(err, source, ec, "boost::filesystem::canonical"); + return path(); } - path root(source.root_path()); - path const& dot_p = dot_path(); - path const& dot_dot_p = dot_dot_path(); - unsigned int symlinks_allowed = symloop_max; - path result; + WCHAR path_small_buf[small_path_size]; + std::unique_ptr< WCHAR[] > path_large_buf; + WCHAR* path_buf = path_small_buf; + DWORD path_buf_size = sizeof(path_small_buf) / sizeof(*path_small_buf); + DWORD flags = FILE_NAME_NORMALIZED; + DWORD path_len; + while (true) { - for (path::iterator itr(source.begin()), end(source.end()); itr != end; path_algorithms::increment_v4(itr)) + path_len = ::GetFinalPathNameByHandleW(h.get(), path_buf, path_buf_size, flags); + if (path_len > 0) { - if (path_algorithms::compare_v4(*itr, dot_p) == 0) - continue; - if (path_algorithms::compare_v4(*itr, dot_dot_p) == 0) - { - if (path_algorithms::compare_v4(result, root) != 0) - result.remove_filename_and_trailing_separators(); - continue; - } + if (path_len < path_buf_size) + break; - if (itr->size() == 1u && detail::is_directory_separator(itr->native()[0])) + // The buffer is not large enough, path_len is the required buffer size, including the terminating zero + path_large_buf.reset(new WCHAR[path_len]); + path_buf = path_large_buf.get(); + path_buf_size = path_len; + } + else + { + err = ::GetLastError(); + if (BOOST_UNLIKELY(err == ERROR_PATH_NOT_FOUND && (flags & VOLUME_NAME_NT) == 0u)) { - // Convert generic separator returned by the iterator for the root directory to - // the preferred separator. This is important on Windows, as in some cases, - // like paths for network shares and cloud storage mount points GetFileAttributesW - // will return "file not found" if the path contains forward slashes. - result += path::preferred_separator; - // We don't need to check for a symlink after adding a separator. + // Drive letter does not exist for the file, obtain an NT path for it + flags |= VOLUME_NAME_NT; continue; } - path_algorithms::append_v4(result, *itr); - - // If we don't have an absolute path yet then don't check symlink status. - // This avoids checking "C:" which is "the current directory on drive C" - // and hence not what we want to check/resolve here. - if (!result.is_absolute()) - continue; - - st = detail::symlink_status_impl(result, ec); - if (ec && *ec) - goto return_empty_path; + goto fail_err; + } + } - if (is_symlink(st)) + path result; + if ((flags & VOLUME_NAME_NT) == 0u) + { + // If the input path did not contain a long path prefix, convert + // "\\?\X:" to "X:" and "\\?\UNC\" to "\\". Otherwise, preserve the prefix. + const path::value_type* source_str = source.c_str(); + if (source.size() < 4u || + source_str[0] != path::preferred_separator || + source_str[1] != path::preferred_separator || + source_str[2] != questionmark || + source_str[3] != path::preferred_separator) + { + if (path_len >= 6u && + path_buf[0] == path::preferred_separator && + path_buf[1] == path::preferred_separator && + path_buf[2] == questionmark && + path_buf[3] == path::preferred_separator) { - if (symlinks_allowed == 0) - { - local_ec = system::errc::make_error_code(system::errc::too_many_symbolic_link_levels); - goto fail_local_ec; - } - - --symlinks_allowed; - - path link(detail::read_symlink(result, ec)); - if (ec && *ec) - goto return_empty_path; - result.remove_filename_and_trailing_separators(); - - if (link.is_absolute()) + if (path_buf[5] == colon && detail::is_letter(path_buf[4])) { - for (path_algorithms::increment_v4(itr); itr != end; path_algorithms::increment_v4(itr)) - { - if (path_algorithms::compare_v4(*itr, dot_p) != 0) - path_algorithms::append_v4(link, *itr); - } - source = link; - root = source.root_path(); + path_buf += 4; + path_len -= 4u; } - else // link is relative + else if (path_len >= 8u && + (path_buf[4] == L'U' || path_buf[4] == L'u') && + (path_buf[5] == L'N' || path_buf[5] == L'n') && + (path_buf[6] == L'C' || path_buf[6] == L'c') && + path_buf[7] == path::preferred_separator) { - link.remove_trailing_separator(); - if (path_algorithms::compare_v4(link, dot_p) == 0) - continue; - - path new_source(result); - path_algorithms::append_v4(new_source, link); - for (path_algorithms::increment_v4(itr); itr != end; path_algorithms::increment_v4(itr)) - { - if (path_algorithms::compare_v4(*itr, dot_p) != 0) - path_algorithms::append_v4(new_source, *itr); - } - source = new_source; + path_buf += 6; + path_len -= 6u; + path_buf[0] = path::preferred_separator; } - - // symlink causes scan to be restarted - goto restart_scan; } } - break; - - restart_scan: - result.clear(); + result.assign(path_buf, path_buf + path_len); + } + else + { + // Convert NT path to a Win32 path + result.assign(L"\\\\?\\GLOBALROOT"); + result.concat(path_buf, path_buf + path_len); } BOOST_ASSERT_MSG(result.is_absolute(), "canonical() implementation error; please report"); return result; + +#endif // defined(BOOST_POSIX_API) +} + +} // unnamed namespace + +BOOST_FILESYSTEM_DECL +path canonical_v3(path const& p, path const& base, system::error_code* ec) +{ + path source(detail::absolute_v3(p, base, ec)); + if (ec && *ec) + return path(); + + return detail::canonical_common(source, ec); +} + +BOOST_FILESYSTEM_DECL +path canonical_v4(path const& p, path const& base, system::error_code* ec) +{ + path source(detail::absolute_v4(p, base, ec)); + if (ec && *ec) + return path(); + + return detail::canonical_common(source, ec); } BOOST_FILESYSTEM_DECL diff --git a/contrib/restricted/boost/filesystem/ya.make b/contrib/restricted/boost/filesystem/ya.make index f468ba49800..b576f8c67f4 100644 --- a/contrib/restricted/boost/filesystem/ya.make +++ b/contrib/restricted/boost/filesystem/ya.make @@ -6,9 +6,9 @@ LICENSE(BSL-1.0) LICENSE_TEXTS(.yandex_meta/licenses.list.txt) -VERSION(1.86.0) +VERSION(1.87.0) -ORIGINAL_SOURCE(https://github.com/boostorg/filesystem/archive/boost-1.86.0.tar.gz) +ORIGINAL_SOURCE(https://github.com/boostorg/filesystem/archive/boost-1.87.0.tar.gz) PEERDIR( contrib/restricted/boost/assert |