diff options
author | thegeorg <thegeorg@yandex-team.com> | 2022-08-29 07:42:14 +0300 |
---|---|---|
committer | thegeorg <thegeorg@yandex-team.com> | 2022-08-29 07:42:14 +0300 |
commit | 08b42c5732ff484354c4ca8adba3b002b117d122 (patch) | |
tree | e9757bdde5d9e8a10b187efffacbe8ea9282a0f5 | |
parent | 9f0fa80273f73bc1848572d7bd8a08ad530e438e (diff) | |
download | ydb-08b42c5732ff484354c4ca8adba3b002b117d122.tar.gz |
Update contrib/restricted/boost/filesystem to 1.80.0
25 files changed, 1289 insertions, 579 deletions
diff --git a/contrib/restricted/boost/filesystem/CMakeLists.darwin.txt b/contrib/restricted/boost/filesystem/CMakeLists.darwin.txt new file mode 100644 index 00000000000..167b59b73ef --- /dev/null +++ b/contrib/restricted/boost/filesystem/CMakeLists.darwin.txt @@ -0,0 +1,45 @@ + +# This file was gererated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_library(restricted-boost-filesystem) +target_compile_options(restricted-boost-filesystem PRIVATE + -DBOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF + -Wno-everything +) +target_include_directories(restricted-boost-filesystem PUBLIC + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/include +) +target_link_libraries(restricted-boost-filesystem PUBLIC + contrib-libs-cxxsupp + restricted-boost-assert + restricted-boost-atomic + restricted-boost-config + restricted-boost-container_hash + restricted-boost-core + restricted-boost-detail + restricted-boost-io + restricted-boost-iterator + restricted-boost-range + restricted-boost-smart_ptr + restricted-boost-static_assert + restricted-boost-system + restricted-boost-type_traits +) +target_sources(restricted-boost-filesystem PRIVATE + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/directory.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/exception.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/operations.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/path.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/path_traits.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/portability.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/unique_path.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/utf8_codecvt_facet.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/windows_file_codecvt.cpp +) diff --git a/contrib/restricted/boost/filesystem/CMakeLists.linux.txt b/contrib/restricted/boost/filesystem/CMakeLists.linux.txt new file mode 100644 index 00000000000..476398fbe51 --- /dev/null +++ b/contrib/restricted/boost/filesystem/CMakeLists.linux.txt @@ -0,0 +1,48 @@ + +# This file was gererated by the build system used internally in the Yandex monorepo. +# Only simple modifications are allowed (adding source-files to targets, adding simple properties +# like target_include_directories). These modifications will be ported to original +# ya.make files by maintainers. Any complex modifications which can't be ported back to the +# original buildsystem will not be accepted. + + + +add_library(restricted-boost-filesystem) +target_compile_options(restricted-boost-filesystem PUBLIC + -DBOOST_FILESYSTEM_HAS_POSIX_AT_APIS +) +target_compile_options(restricted-boost-filesystem PRIVATE + -DBOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF + -Wno-everything +) +target_include_directories(restricted-boost-filesystem PUBLIC + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/include +) +target_link_libraries(restricted-boost-filesystem PUBLIC + contrib-libs-cxxsupp + restricted-boost-assert + restricted-boost-atomic + restricted-boost-config + restricted-boost-container_hash + restricted-boost-core + restricted-boost-detail + restricted-boost-io + restricted-boost-iterator + restricted-boost-range + restricted-boost-smart_ptr + restricted-boost-static_assert + restricted-boost-system + restricted-boost-type_traits +) +target_sources(restricted-boost-filesystem PRIVATE + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/directory.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/exception.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/operations.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/path.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/path_traits.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/portability.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/unique_path.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/utf8_codecvt_facet.cpp + ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/windows_file_codecvt.cpp +) diff --git a/contrib/restricted/boost/filesystem/CMakeLists.txt b/contrib/restricted/boost/filesystem/CMakeLists.txt index 167b59b73ef..fc7b1ee73ce 100644 --- a/contrib/restricted/boost/filesystem/CMakeLists.txt +++ b/contrib/restricted/boost/filesystem/CMakeLists.txt @@ -6,40 +6,8 @@ # original buildsystem will not be accepted. - -add_library(restricted-boost-filesystem) -target_compile_options(restricted-boost-filesystem PRIVATE - -DBOOST_FILESYSTEM_NO_CXX20_ATOMIC_REF - -Wno-everything -) -target_include_directories(restricted-boost-filesystem PUBLIC - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/include -) -target_link_libraries(restricted-boost-filesystem PUBLIC - contrib-libs-cxxsupp - restricted-boost-assert - restricted-boost-atomic - restricted-boost-config - restricted-boost-container_hash - restricted-boost-core - restricted-boost-detail - restricted-boost-io - restricted-boost-iterator - restricted-boost-range - restricted-boost-smart_ptr - restricted-boost-static_assert - restricted-boost-system - restricted-boost-type_traits -) -target_sources(restricted-boost-filesystem PRIVATE - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/directory.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/exception.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/operations.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/path.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/path_traits.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/portability.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/unique_path.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/utf8_codecvt_facet.cpp - ${CMAKE_SOURCE_DIR}/contrib/restricted/boost/filesystem/src/windows_file_codecvt.cpp -) +if (APPLE) + include(CMakeLists.darwin.txt) +elseif (UNIX AND NOT APPLE) + include(CMakeLists.linux.txt) +endif() diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp index 2d121e40f1f..10f49a658e9 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/header.hpp @@ -37,6 +37,8 @@ #pragma GCC diagnostic push // unused parameter 'arg' #pragma GCC diagnostic ignored "-Wunused-parameter" +// unused function 'foo' +#pragma GCC diagnostic ignored "-Wunused-function" #endif diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/utf8_codecvt_facet.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/utf8_codecvt_facet.hpp index 0011cc71cff..4df9a7c620d 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/utf8_codecvt_facet.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/detail/utf8_codecvt_facet.hpp @@ -9,6 +9,8 @@ #include <boost/filesystem/config.hpp> +#include <boost/filesystem/detail/header.hpp> + #define BOOST_UTF8_BEGIN_NAMESPACE \ namespace boost { \ namespace filesystem { \ @@ -26,4 +28,6 @@ #undef BOOST_UTF8_END_NAMESPACE #undef BOOST_UTF8_DECL -#endif +#include <boost/filesystem/detail/footer.hpp> + +#endif // BOOST_FILESYSTEM_UTF8_CODECVT_FACET_HPP diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp index 66e1dd9bcbf..68b13638e11 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/directory.hpp @@ -142,8 +142,8 @@ public: bool operator>=(directory_entry const& rhs) const BOOST_NOEXCEPT { return m_path >= rhs.m_path; } private: - BOOST_FILESYSTEM_DECL file_status get_status(system::error_code* ec = 0) const; - BOOST_FILESYSTEM_DECL file_status get_symlink_status(system::error_code* ec = 0) const; + BOOST_FILESYSTEM_DECL file_status get_status(system::error_code* ec = NULL) const; + BOOST_FILESYSTEM_DECL file_status get_symlink_status(system::error_code* ec = NULL) const; private: boost::filesystem::path m_path; @@ -263,6 +263,7 @@ struct dir_itr_imp : public boost::intrusive_ref_counter< dir_itr_imp > { #ifdef BOOST_WINDOWS_API + bool close_handle; unsigned char extra_data_format; std::size_t current_offset; #endif @@ -271,6 +272,7 @@ struct dir_itr_imp : dir_itr_imp() BOOST_NOEXCEPT : #ifdef BOOST_WINDOWS_API + close_handle(false), extra_data_format(0u), current_offset(0u), #endif @@ -284,7 +286,9 @@ struct dir_itr_imp : BOOST_FILESYSTEM_DECL static void operator delete(void* p) BOOST_NOEXCEPT; }; -BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, system::error_code* ec); +struct directory_iterator_params; + +BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, directory_iterator_params* params, system::error_code* ec); BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it, system::error_code* ec); } // namespace detail @@ -304,7 +308,7 @@ class directory_iterator : { friend class boost::iterator_core_access; - friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, system::error_code* ec); + friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, detail::directory_iterator_params* params, system::error_code* ec); friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_increment(directory_iterator& it, system::error_code* ec); public: @@ -314,17 +318,17 @@ public: // separate translation unit dll's, so forward to detail functions explicit directory_iterator(path const& p, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts = directory_options::none) { - detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(opts), 0); + detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(opts), NULL, NULL); } directory_iterator(path const& p, system::error_code& ec) BOOST_NOEXCEPT { - detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(directory_options::none), &ec); + detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(directory_options::none), NULL, &ec); } directory_iterator(path const& p, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts, system::error_code& ec) BOOST_NOEXCEPT { - detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(opts), &ec); + detail::directory_iterator_construct(*this, p, static_cast< unsigned int >(opts), NULL, &ec); } BOOST_DEFAULTED_FUNCTION(directory_iterator(directory_iterator const& that), : m_imp(that.m_imp) {}) @@ -360,7 +364,7 @@ private: return m_imp->dir_entry; } - void increment() { detail::directory_iterator_increment(*this, 0); } + void increment() { detail::directory_iterator_increment(*this, NULL); } bool equal(directory_iterator const& rhs) const BOOST_NOEXCEPT { @@ -516,7 +520,7 @@ public: explicit recursive_directory_iterator(path const& dir_path) { - detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(directory_options::none), 0); + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(directory_options::none), NULL); } recursive_directory_iterator(path const& dir_path, system::error_code& ec) @@ -526,7 +530,7 @@ public: recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts) { - detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), 0); + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), NULL); } recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(directory_options) opts, system::error_code& ec) @@ -538,7 +542,7 @@ public: // Deprecated constructors recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(symlink_option) opts) { - detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), 0); + detail::recursive_directory_iterator_construct(*this, dir_path, static_cast< unsigned int >(opts), NULL); } recursive_directory_iterator(path const& dir_path, BOOST_SCOPED_ENUM_NATIVE(symlink_option) opts, system::error_code& ec) BOOST_NOEXCEPT @@ -592,7 +596,7 @@ public: void pop() { - detail::recursive_directory_iterator_pop(*this, 0); + detail::recursive_directory_iterator_pop(*this, NULL); } void pop(system::error_code& ec) BOOST_NOEXCEPT @@ -639,7 +643,7 @@ private: return *m_imp->m_stack.back(); } - void increment() { detail::recursive_directory_iterator_increment(*this, 0); } + void increment() { detail::recursive_directory_iterator_increment(*this, NULL); } bool equal(recursive_directory_iterator const& rhs) const BOOST_NOEXCEPT { diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp index 484efdaa23e..90eca99e84a 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/file_status.hpp @@ -139,12 +139,12 @@ public: // for VC++, GCC, and probably other compilers, that =default is not used with noexcept // functions. GCC is not even consistent for the same release on different platforms. - BOOST_CONSTEXPR file_status(const file_status& rhs) BOOST_NOEXCEPT : + BOOST_CONSTEXPR file_status(file_status const& rhs) BOOST_NOEXCEPT : m_value(rhs.m_value), m_perms(rhs.m_perms) { } - BOOST_CXX14_CONSTEXPR file_status& operator=(const file_status& rhs) BOOST_NOEXCEPT + BOOST_CXX14_CONSTEXPR file_status& operator=(file_status const& rhs) BOOST_NOEXCEPT { m_value = rhs.m_value; m_perms = rhs.m_perms; diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/fstream.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/fstream.hpp index b70c901602a..124ab398413 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/fstream.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/fstream.hpp @@ -15,6 +15,7 @@ #include <boost/filesystem/config.hpp> #include <boost/filesystem/path.hpp> +#include <cstddef> #include <iosfwd> #include <fstream> @@ -71,7 +72,7 @@ public: public: basic_filebuf< charT, traits >* open(path const& p, std::ios_base::openmode mode) { - return std::basic_filebuf< charT, traits >::open(BOOST_FILESYSTEM_C_STR(p), mode) ? this : 0; + return std::basic_filebuf< charT, traits >::open(BOOST_FILESYSTEM_C_STR(p), mode) ? this : NULL; } }; diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp index 9ccd20d041c..856de7c1a5a 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/operations.hpp @@ -30,8 +30,9 @@ #include <boost/core/scoped_enum.hpp> #include <boost/system/error_code.hpp> #include <boost/cstdint.hpp> -#include <string> +#include <cstddef> #include <ctime> +#include <string> #include <boost/filesystem/detail/header.hpp> // must be the last #include @@ -89,78 +90,78 @@ BOOST_SCOPED_ENUM_DECLARE_END(copy_option) namespace detail { BOOST_FILESYSTEM_DECL -path absolute(path const& p, path const& base, system::error_code* ec = 0); +path absolute(path const& p, path const& base, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -file_status status(path const& p, system::error_code* ec = 0); +file_status status(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -file_status symlink_status(path const& p, system::error_code* ec = 0); +file_status symlink_status(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -bool is_empty(path const& p, system::error_code* ec = 0); +bool is_empty(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path initial_path(system::error_code* ec = 0); +path initial_path(system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path canonical(path const& p, path const& base, system::error_code* ec = 0); +path canonical(path const& p, path const& base, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void copy(path const& from, path const& to, unsigned int options, system::error_code* ec = 0); +void copy(path const& from, path const& to, unsigned int options, system::error_code* ec = NULL); #if !defined(BOOST_FILESYSTEM_NO_DEPRECATED) BOOST_FILESYSTEM_DECL -void copy_directory(path const& from, path const& to, system::error_code* ec = 0); +void copy_directory(path const& from, path const& to, system::error_code* ec = NULL); #endif BOOST_FILESYSTEM_DECL -bool copy_file(path const& from, path const& to, // See ticket #2925 - unsigned int options, system::error_code* ec = 0); // see copy_options for options +bool copy_file(path const& from, path const& to, // See ticket #2925 + unsigned int options, system::error_code* ec = NULL); // see copy_options for options BOOST_FILESYSTEM_DECL -void copy_symlink(path const& existing_symlink, path const& new_symlink, system::error_code* ec = 0); +void copy_symlink(path const& existing_symlink, path const& new_symlink, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -bool create_directories(path const& p, system::error_code* ec = 0); +bool create_directories(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -bool create_directory(path const& p, const path* existing, system::error_code* ec = 0); +bool create_directory(path const& p, const path* existing, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void create_directory_symlink(path const& to, path const& from, system::error_code* ec = 0); +void create_directory_symlink(path const& to, path const& from, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void create_hard_link(path const& to, path const& from, system::error_code* ec = 0); +void create_hard_link(path const& to, path const& from, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void create_symlink(path const& to, path const& from, system::error_code* ec = 0); +void create_symlink(path const& to, path const& from, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path current_path(system::error_code* ec = 0); +path current_path(system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void current_path(path const& p, system::error_code* ec = 0); +void current_path(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -bool equivalent(path const& p1, path const& p2, system::error_code* ec = 0); +bool equivalent(path const& p1, path const& p2, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -boost::uintmax_t file_size(path const& p, system::error_code* ec = 0); +boost::uintmax_t file_size(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -boost::uintmax_t hard_link_count(path const& p, system::error_code* ec = 0); +boost::uintmax_t hard_link_count(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -std::time_t creation_time(path const& p, system::error_code* ec = 0); +std::time_t creation_time(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -std::time_t last_write_time(path const& p, system::error_code* ec = 0); +std::time_t last_write_time(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void last_write_time(path const& p, const std::time_t new_time, system::error_code* ec = 0); +void last_write_time(path const& p, const std::time_t new_time, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void permissions(path const& p, perms prms, system::error_code* ec = 0); +void permissions(path const& p, perms prms, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path read_symlink(path const& p, system::error_code* ec = 0); +path read_symlink(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path relative(path const& p, path const& base, system::error_code* ec = 0); +path relative(path const& p, path const& base, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -bool remove(path const& p, system::error_code* ec = 0); +bool remove(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -boost::uintmax_t remove_all(path const& p, system::error_code* ec = 0); +boost::uintmax_t remove_all(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void rename(path const& old_p, path const& new_p, system::error_code* ec = 0); +void rename(path const& old_p, path const& new_p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -void resize_file(path const& p, uintmax_t size, system::error_code* ec = 0); +void resize_file(path const& p, uintmax_t size, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -space_info space(path const& p, system::error_code* ec = 0); +space_info space(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path system_complete(path const& p, system::error_code* ec = 0); +path system_complete(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path temp_directory_path(system::error_code* ec = 0); +path temp_directory_path(system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path unique_path(path const& p, system::error_code* ec = 0); +path unique_path(path const& p, system::error_code* ec = NULL); BOOST_FILESYSTEM_DECL -path weakly_canonical(path const& p, path const& base, system::error_code* ec = 0); +path weakly_canonical(path const& p, path const& base, system::error_code* ec = NULL); } // namespace detail @@ -447,12 +448,12 @@ inline bool create_directories(path const& p, system::error_code& ec) BOOST_NOEX inline bool create_directory(path const& p) { - return detail::create_directory(p, 0); + return detail::create_directory(p, NULL); } inline bool create_directory(path const& p, system::error_code& ec) BOOST_NOEXCEPT { - return detail::create_directory(p, 0, &ec); + return detail::create_directory(p, NULL, &ec); } inline bool create_directory(path const& p, path const& existing) diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp index 2f06c866e17..0554c987a19 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/path.hpp @@ -209,7 +209,7 @@ public: template< class Source > path(Source const& source, typename boost::enable_if_c< path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value - >::type* = 0) + >::type* = NULL) { path_traits::dispatch(source, m_pathname); } @@ -274,7 +274,7 @@ public: template< class Source > path(Source const& source, codecvt_type const& cvt, typename boost::enable_if_c< path_traits::is_pathable< typename boost::decay< Source >::type >::value && !path_detail::is_native_pathable< Source >::value - >::type* = 0) + >::type* = NULL) { path_traits::dispatch(source, m_pathname, cvt); } @@ -282,7 +282,7 @@ public: path(const value_type* begin, const value_type* end) : m_pathname(begin, end) {} template< class InputIterator > - path(InputIterator begin, InputIterator end, typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator > >::type* = 0) + path(InputIterator begin, InputIterator end, typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator > >::type* = NULL) { if (begin != end) { @@ -295,7 +295,7 @@ public: path(const value_type* begin, const value_type* end, codecvt_type const&) : m_pathname(begin, end) {} template< class InputIterator > - path(InputIterator begin, InputIterator end, codecvt_type const& cvt, typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator > >::type* = 0) + path(InputIterator begin, InputIterator end, codecvt_type const& cvt, typename boost::disable_if< path_detail::is_native_char_ptr< InputIterator > >::type* = NULL) { if (begin != end) { @@ -1183,7 +1183,7 @@ template< typename T > inline typename boost::enable_if< boost::is_same< T, path >, std::size_t >::type hash_value(T const& p) BOOST_NOEXCEPT { #ifdef BOOST_WINDOWS_API - std::size_t seed = 0; + std::size_t seed = 0u; for (typename T::value_type const* it = p.c_str(); *it; ++it) hash_combine(seed, *it == L'/' ? L'\\' : *it); return seed; @@ -1359,14 +1359,14 @@ inline std::wstring path::generic_string< std::wstring >(codecvt_type const& cvt namespace path_traits { // without codecvt inline void convert(const char* from, - const char* from_end, // 0 for null terminated MBCS + const char* from_end, // NULL for null terminated MBCS std::wstring& to) { convert(from, from_end, to, path::codecvt()); } inline void convert(const wchar_t* from, - const wchar_t* from_end, // 0 for null terminated MBCS + const wchar_t* from_end, // NULL for null terminated MBCS std::string& to) { convert(from, from_end, to, path::codecvt()); @@ -1375,13 +1375,13 @@ inline void convert(const wchar_t* from, inline void convert(const char* from, std::wstring& to) { BOOST_ASSERT(!!from); - convert(from, 0, to, path::codecvt()); + convert(from, NULL, to, path::codecvt()); } inline void convert(const wchar_t* from, std::string& to) { BOOST_ASSERT(!!from); - convert(from, 0, to, path::codecvt()); + convert(from, NULL, to, path::codecvt()); } } // namespace path_traits diff --git a/contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp b/contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp index 7f6dea0473f..e4f9b52c0dc 100644 --- a/contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp +++ b/contrib/restricted/boost/filesystem/include/boost/filesystem/path_traits.hpp @@ -147,40 +147,40 @@ inline bool empty(T (&x)[N]) // value types differ ---------------------------------------------------------------// // -// A from_end argument of 0 is less efficient than a known end, so use only if needed +// A from_end argument of NULL is less efficient than a known end, so use only if needed // with codecvt BOOST_FILESYSTEM_DECL void convert(const char* from, - const char* from_end, // 0 for null terminated MBCS + const char* from_end, // NULL for null terminated MBCS std::wstring& to, codecvt_type const& cvt); BOOST_FILESYSTEM_DECL void convert(const wchar_t* from, - const wchar_t* from_end, // 0 for null terminated MBCS + const wchar_t* from_end, // NULL for null terminated MBCS std::string& to, codecvt_type const& cvt); inline void convert(const char* from, std::wstring& to, codecvt_type const& cvt) { BOOST_ASSERT(from); - convert(from, 0, to, cvt); + convert(from, NULL, to, cvt); } inline void convert(const wchar_t* from, std::string& to, codecvt_type const& cvt) { BOOST_ASSERT(from); - convert(from, 0, to, cvt); + convert(from, NULL, to, cvt); } // without codecvt inline void convert(const char* from, - const char* from_end, // 0 for null terminated MBCS + const char* from_end, // NULL for null terminated MBCS std::wstring& to); inline void convert(const wchar_t* from, - const wchar_t* from_end, // 0 for null terminated MBCS + const wchar_t* from_end, // NULL for null terminated MBCS std::string& to); inline void convert(const char* from, std::wstring& to); diff --git a/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp b/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp index 501f78f103c..72db677a09c 100644 --- a/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp +++ b/contrib/restricted/boost/filesystem/src/codecvt_error_category.cpp @@ -22,6 +22,8 @@ #include "private_config.hpp" +#include <boost/filesystem/detail/header.hpp> // must be the last #include + //--------------------------------------------------------------------------------------// namespace boost { @@ -29,6 +31,13 @@ namespace filesystem { namespace { +#if (defined(BOOST_GCC) && BOOST_GCC >= 40600) || defined(BOOST_CLANG) +#pragma GCC diagnostic push +// '(anonymous namespace)::codecvt_error_cat' has virtual functions but non-virtual destructor +// This is not a problem as instances of codecvt_error_cat are never destroyed through a pointer to base. +#pragma GCC diagnostic ignored "-Wnon-virtual-dtor" +#endif + class codecvt_error_cat BOOST_FINAL : public boost::system::error_category { @@ -68,6 +77,10 @@ std::string codecvt_error_cat::message(int ev) const return str; } +#if (defined(BOOST_GCC) && BOOST_GCC >= 40600) || defined(BOOST_CLANG) +#pragma GCC diagnostic pop +#endif + } // unnamed namespace BOOST_FILESYSTEM_DECL boost::system::error_category const& codecvt_error_category() BOOST_NOEXCEPT @@ -103,3 +116,5 @@ const codecvt_error_category_initializer g_codecvt_error_category_initializer; } // namespace filesystem } // namespace boost + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/directory.cpp b/contrib/restricted/boost/filesystem/src/directory.cpp index cbe8319cf03..6a3e1dc7319 100644 --- a/contrib/restricted/boost/filesystem/src/directory.cpp +++ b/contrib/restricted/boost/filesystem/src/directory.cpp @@ -72,6 +72,8 @@ #include "error_handling.hpp" #include "private_config.hpp" +#include <boost/filesystem/detail/header.hpp> // must be the last #include + // BOOST_FILESYSTEM_STATUS_CACHE enables file_status cache in // dir_itr_increment. The config tests are placed here because some of the // macros being tested come from dirent.h. @@ -376,7 +378,7 @@ error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_stat return error_code(); } -error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, fs::path& first_filename, fs::file_status&, fs::file_status&) +error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, directory_iterator_params* params, fs::path& first_filename, fs::file_status&, fs::file_status&) { std::size_t extra_size = 0u; #if defined(BOOST_FILESYSTEM_USE_READDIR_R) @@ -409,7 +411,11 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) flags |= O_NOFOLLOW; +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + int fd = ::openat(params ? params->basedir_fd : AT_FDCWD, dir.c_str(), flags); +#else int fd = ::open(dir.c_str(), flags); +#endif if (BOOST_UNLIKELY(fd < 0)) { const int err = errno; @@ -445,6 +451,11 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: // Force initial readdir call by the caller. This will initialize the actual first filename and statuses. first_filename.assign("."); +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + if (params) + params->iterator_fd = fd; +#endif + imp.swap(pimpl); return error_code(); } @@ -586,7 +597,7 @@ extra_data_format g_extra_data_format = file_directory_information_format; /*! * \brief Extra buffer size for GetFileInformationByHandleEx-based or NtQueryDirectoryFile-based directory iterator. - * + * * Must be large enough to accommodate at least one FILE_DIRECTORY_INFORMATION or *_DIR_INFO struct and one filename. * NTFS, VFAT, exFAT support filenames up to 255 UTF-16/UCS-2 characters. ReFS supports filenames up to 32768 UTF-16 characters. */ @@ -599,7 +610,8 @@ inline system::error_code dir_itr_close(dir_itr_imp& imp) BOOST_NOEXCEPT if (imp.handle != NULL) { - ::CloseHandle(imp.handle); + if (BOOST_LIKELY(imp.close_handle)) + ::CloseHandle(imp.handle); imp.handle = NULL; } @@ -751,54 +763,76 @@ done: return error_code(); } -error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, fs::path& first_filename, fs::file_status& sf, fs::file_status& symlink_sf) +error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, directory_iterator_params* params, fs::path& first_filename, fs::file_status& sf, fs::file_status& symlink_sf) { boost::intrusive_ptr< detail::dir_itr_imp > pimpl(new (dir_itr_extra_size) detail::dir_itr_imp()); if (BOOST_UNLIKELY(!pimpl)) return make_error_code(system::errc::not_enough_memory); - DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; - if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) - flags |= FILE_FLAG_OPEN_REPARSE_POINT; - handle_wrapper h(create_file_handle(dir, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, flags)); - if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) + GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); + + handle_wrapper h; + HANDLE iterator_handle; + bool close_handle = true; + if (params != NULL && params->use_handle != INVALID_HANDLE_VALUE) { - return_last_error: - DWORD error = ::GetLastError(); - return error_code(error, system_category()); + // Operate on externally provided handle, which must be a directory handle + iterator_handle = params->use_handle; + close_handle = params->close_handle; } - - GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); - if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL)) + else { - file_attribute_tag_info info; - BOOL res = get_file_information_by_handle_ex(h.handle, file_attribute_tag_info_class, &info, sizeof(info)); - if (BOOST_UNLIKELY(!res)) - goto return_last_error; - - if (BOOST_UNLIKELY((info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u)) - return make_error_code(system::errc::not_a_directory); - + DWORD flags = FILE_FLAG_BACKUP_SEMANTICS; if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) + flags |= FILE_FLAG_OPEN_REPARSE_POINT; + + iterator_handle = h.handle = create_file_handle(dir, FILE_LIST_DIRECTORY, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, flags); + if (BOOST_UNLIKELY(iterator_handle == INVALID_HANDLE_VALUE)) { - if ((info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u && is_reparse_point_tag_a_symlink(info.ReparseTag)) - return make_error_code(system::errc::too_many_symbolic_link_levels); + return_last_error: + DWORD error = ::GetLastError(); + return error_code(error, system_category()); } - } - else - { - BY_HANDLE_FILE_INFORMATION info; - BOOL res = ::GetFileInformationByHandle(h.handle, &info); - if (BOOST_UNLIKELY(!res)) - goto return_last_error; - if (BOOST_UNLIKELY((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u)) - return make_error_code(system::errc::not_a_directory); + if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL)) + { + file_attribute_tag_info info; + BOOL res = get_file_information_by_handle_ex(iterator_handle, file_attribute_tag_info_class, &info, sizeof(info)); + if (BOOST_UNLIKELY(!res)) + { + // On FAT/exFAT filesystems requesting FILE_ATTRIBUTE_TAG_INFO returns ERROR_INVALID_PARAMETER. See the comment in symlink_status. + DWORD error = ::GetLastError(); + if (error == ERROR_INVALID_PARAMETER || error == ERROR_NOT_SUPPORTED) + goto use_get_file_information_by_handle; - if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) + return error_code(error, system_category()); + } + + if (BOOST_UNLIKELY((info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u)) + return make_error_code(system::errc::not_a_directory); + + if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) + { + if ((info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u && is_reparse_point_tag_a_symlink(info.ReparseTag)) + return make_error_code(system::errc::too_many_symbolic_link_levels); + } + } + else { - if ((info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u && is_reparse_point_a_symlink_ioctl(h.handle)) - return make_error_code(system::errc::too_many_symbolic_link_levels); + use_get_file_information_by_handle: + BY_HANDLE_FILE_INFORMATION info; + BOOL res = ::GetFileInformationByHandle(iterator_handle, &info); + if (BOOST_UNLIKELY(!res)) + goto return_last_error; + + if (BOOST_UNLIKELY((info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u)) + return make_error_code(system::errc::not_a_directory); + + if ((opts & static_cast< unsigned int >(directory_options::_detail_no_follow)) != 0u) + { + if ((info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0u && is_reparse_point_a_symlink_ioctl(h.handle)) + return make_error_code(system::errc::too_many_symbolic_link_levels); + } } } @@ -807,7 +841,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: { case file_id_extd_dir_info_format: { - if (!get_file_information_by_handle_ex(h.handle, file_id_extd_directory_restart_info_class, extra_data, dir_itr_extra_size)) + if (!get_file_information_by_handle_ex(iterator_handle, file_id_extd_directory_restart_info_class, extra_data, dir_itr_extra_size)) { DWORD error = ::GetLastError(); @@ -841,7 +875,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: case file_full_dir_info_format: fallback_to_file_full_dir_info_format: { - if (!get_file_information_by_handle_ex(h.handle, file_full_directory_restart_info_class, extra_data, dir_itr_extra_size)) + if (!get_file_information_by_handle_ex(iterator_handle, file_full_directory_restart_info_class, extra_data, dir_itr_extra_size)) { DWORD error = ::GetLastError(); @@ -870,7 +904,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: case file_id_both_dir_info_format: fallback_to_file_id_both_dir_info: { - if (!get_file_information_by_handle_ex(h.handle, file_id_both_directory_restart_info_class, extra_data, dir_itr_extra_size)) + if (!get_file_information_by_handle_ex(iterator_handle, file_id_both_directory_restart_info_class, extra_data, dir_itr_extra_size)) { DWORD error = ::GetLastError(); @@ -898,7 +932,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: io_status_block iosb; boost::winapi::NTSTATUS_ status = nt_query_directory_file ( - h.handle, + iterator_handle, NULL, // Event NULL, // ApcRoutine NULL, // ApcContext @@ -933,8 +967,10 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: break; } - pimpl->handle = h.handle; + + pimpl->handle = iterator_handle; h.handle = INVALID_HANDLE_VALUE; + pimpl->close_handle = close_handle; done: imp.swap(pimpl); @@ -947,7 +983,8 @@ inline system::error_code dir_itr_close(dir_itr_imp& imp) BOOST_NOEXCEPT { if (imp.handle != NULL) { - ::FindClose(imp.handle); + if (BOOST_LIKELY(imp.close_handle)) + ::FindClose(imp.handle); imp.handle = NULL; } @@ -973,7 +1010,7 @@ done: return error_code(); } -error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, fs::path& first_filename, fs::file_status& sf, fs::file_status& symlink_sf) +error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::path const& dir, unsigned int opts, directory_iterator_params*, fs::path& first_filename, fs::file_status& sf, fs::file_status& symlink_sf) { boost::intrusive_ptr< detail::dir_itr_imp > pimpl(new (static_cast< std::size_t >(0u)) detail::dir_itr_imp()); if (BOOST_UNLIKELY(!pimpl)) @@ -1001,6 +1038,8 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs:: return error_code(error, system_category()); } + pimpl->close_handle = true; + first_filename = data.cFileName; set_file_statuses(data.dwFileAttributes, NULL, first_filename, sf, symlink_sf); @@ -1039,7 +1078,7 @@ dir_itr_imp::~dir_itr_imp() BOOST_NOEXCEPT } BOOST_FILESYSTEM_DECL -void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, system::error_code* ec) +void directory_iterator_construct(directory_iterator& it, path const& p, unsigned int opts, directory_iterator_params* params, system::error_code* ec) { if (BOOST_UNLIKELY(p.empty())) { @@ -1055,7 +1094,7 @@ void directory_iterator_construct(directory_iterator& it, path const& p, unsigne boost::intrusive_ptr< detail::dir_itr_imp > imp; path filename; file_status file_stat, symlink_file_stat; - system::error_code result = dir_itr_create(imp, p, opts, filename, file_stat, symlink_file_stat); + system::error_code result = dir_itr_create(imp, p, opts, params, filename, file_stat, symlink_file_stat); while (true) { @@ -1169,7 +1208,7 @@ void recursive_directory_iterator_construct(recursive_directory_iterator& it, pa ec->clear(); directory_iterator dir_it; - detail::directory_iterator_construct(dir_it, dir_path, opts, ec); + detail::directory_iterator_construct(dir_it, dir_path, opts, NULL, ec); if ((ec && *ec) || dir_it == directory_iterator()) return; @@ -1307,8 +1346,8 @@ inline push_directory_result recursive_directory_iterator_push_directory(detail: file_status symlink_stat; - // if we are not recursing into symlinks, we are going to have to know if the - // stack top is a symlink, so get symlink_status and verify no error occurred + // If we are not recursing into symlinks, we are going to have to know if the + // stack top is a symlink, so get symlink_status and verify no error occurred. if ((imp->m_options & static_cast< unsigned int >(directory_options::follow_directory_symlink)) == 0u || (imp->m_options & static_cast< unsigned int >(directory_options::skip_dangling_symlinks)) != 0u) { @@ -1452,3 +1491,5 @@ void recursive_directory_iterator_increment(recursive_directory_iterator& it, sy } // namespace filesystem } // namespace boost + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/error_handling.hpp b/contrib/restricted/boost/filesystem/src/error_handling.hpp index cd6a72e17fd..97590a87120 100644 --- a/contrib/restricted/boost/filesystem/src/error_handling.hpp +++ b/contrib/restricted/boost/filesystem/src/error_handling.hpp @@ -24,6 +24,8 @@ #include <boost/winapi/error_codes.hpp> #endif +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace boost { namespace filesystem { @@ -86,6 +88,33 @@ typedef boost::winapi::DWORD_ err_t; #if !defined(STATUS_ACCESS_DENIED) #define STATUS_ACCESS_DENIED ((boost::winapi::NTSTATUS_)0xC0000022l) #endif +#if !defined(STATUS_OBJECT_NAME_NOT_FOUND) +#define STATUS_OBJECT_NAME_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC0000034l) +#endif +#if !defined(STATUS_OBJECT_PATH_NOT_FOUND) +#define STATUS_OBJECT_PATH_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC000003Al) +#endif +#if !defined(STATUS_NOT_SUPPORTED) +#define STATUS_NOT_SUPPORTED ((boost::winapi::NTSTATUS_)0xC00000BBl) +#endif +#if !defined(STATUS_BAD_NETWORK_PATH) +#define STATUS_BAD_NETWORK_PATH ((boost::winapi::NTSTATUS_)0xC00000BEl) +#endif +#if !defined(STATUS_DEVICE_DOES_NOT_EXIST) +#define STATUS_DEVICE_DOES_NOT_EXIST ((boost::winapi::NTSTATUS_)0xC00000C0l) +#endif +#if !defined(STATUS_BAD_NETWORK_NAME) +#define STATUS_BAD_NETWORK_NAME ((boost::winapi::NTSTATUS_)0xC00000CCl) +#endif +#if !defined(STATUS_DIRECTORY_NOT_EMPTY) +#define STATUS_DIRECTORY_NOT_EMPTY ((boost::winapi::NTSTATUS_)0xC0000101l) +#endif +#if !defined(STATUS_NOT_A_DIRECTORY) +#define STATUS_NOT_A_DIRECTORY ((boost::winapi::NTSTATUS_)0xC0000103l) +#endif +#if !defined(STATUS_NOT_FOUND) +#define STATUS_NOT_FOUND ((boost::winapi::NTSTATUS_)0xC0000225l) +#endif //! Converts NTSTATUS error codes to Win32 error codes for reporting inline boost::winapi::DWORD_ translate_ntstatus(boost::winapi::NTSTATUS_ status) @@ -104,11 +133,24 @@ inline boost::winapi::DWORD_ translate_ntstatus(boost::winapi::NTSTATUS_ status) case static_cast< boost::winapi::ULONG_ >(STATUS_NO_MORE_FILES): return boost::winapi::ERROR_NO_MORE_FILES_; case static_cast< boost::winapi::ULONG_ >(STATUS_NO_SUCH_DEVICE): + case static_cast< boost::winapi::ULONG_ >(STATUS_DEVICE_DOES_NOT_EXIST): return boost::winapi::ERROR_DEV_NOT_EXIST_; case static_cast< boost::winapi::ULONG_ >(STATUS_NO_SUCH_FILE): + case static_cast< boost::winapi::ULONG_ >(STATUS_OBJECT_NAME_NOT_FOUND): + case static_cast< boost::winapi::ULONG_ >(STATUS_OBJECT_PATH_NOT_FOUND): return boost::winapi::ERROR_FILE_NOT_FOUND_; case static_cast< boost::winapi::ULONG_ >(STATUS_ACCESS_DENIED): return boost::winapi::ERROR_ACCESS_DENIED_; + case static_cast< boost::winapi::ULONG_ >(STATUS_BAD_NETWORK_PATH): + return boost::winapi::ERROR_BAD_NETPATH_; + case static_cast< boost::winapi::ULONG_ >(STATUS_BAD_NETWORK_NAME): + return boost::winapi::ERROR_BAD_NET_NAME_; + case static_cast< boost::winapi::ULONG_ >(STATUS_DIRECTORY_NOT_EMPTY): + return boost::winapi::ERROR_DIR_NOT_EMPTY_; + case static_cast< boost::winapi::ULONG_ >(STATUS_NOT_A_DIRECTORY): + return boost::winapi::ERROR_DIRECTORY_; // The directory name is invalid + case static_cast< boost::winapi::ULONG_ >(STATUS_NOT_FOUND): + return boost::winapi::ERROR_NOT_FOUND_; // map "invalid info class" to "not supported" as this error likely indicates that the kernel does not support what we request case static_cast< boost::winapi::ULONG_ >(STATUS_INVALID_INFO_CLASS): default: @@ -173,4 +215,6 @@ inline bool error(err_t error_num, path const& p1, path const& p2, system::error } // namespace filesystem } // namespace boost +#include <boost/filesystem/detail/footer.hpp> + #endif // BOOST_FILESYSTEM_SRC_ERROR_HANDLING_HPP_ diff --git a/contrib/restricted/boost/filesystem/src/exception.cpp b/contrib/restricted/boost/filesystem/src/exception.cpp index b0480a8b8e6..91ee1c90a9b 100644 --- a/contrib/restricted/boost/filesystem/src/exception.cpp +++ b/contrib/restricted/boost/filesystem/src/exception.cpp @@ -19,7 +19,7 @@ #include "error_handling.hpp" -#include <boost/config/abi_prefix.hpp> // must be the last #include +#include <boost/filesystem/detail/header.hpp> // must be the last #include namespace boost { namespace filesystem { @@ -185,4 +185,4 @@ void emit_error(err_t error_num, path const& p1, path const& p2, system::error_c } // namespace filesystem } // namespace boost -#include <boost/config/abi_suffix.hpp> // pops abi_prefix.hpp pragmas +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/operations.cpp b/contrib/restricted/boost/filesystem/src/operations.cpp index 8d2f0adf963..dd636e90637 100644 --- a/contrib/restricted/boost/filesystem/src/operations.cpp +++ b/contrib/restricted/boost/filesystem/src/operations.cpp @@ -32,18 +32,21 @@ #include <cstddef> #include <cstdlib> // for malloc, free #include <cstring> -#include <cstdio> // for remove, rename -#if defined(__QNXNTO__) // see ticket #5355 -#include <stdio.h> -#endif #include <cerrno> +#include <stdio.h> // for rename + +// Default to POSIX under Emscripten +// If BOOST_FILESYSTEM_EMSCRIPTEN_USE_WASI is set, use WASI instead +#if defined(__wasm) && (!defined(__EMSCRIPTEN__) || defined(BOOST_FILESYSTEM_EMSCRIPTEN_USE_WASI)) +#define BOOST_FILESYSTEM_USE_WASI +#endif #ifdef BOOST_POSIX_API #include <sys/types.h> #include <sys/stat.h> -#if defined(__wasm) +#if defined(BOOST_FILESYSTEM_USE_WASI) // WASI does not have statfs or statvfs. #elif !defined(__APPLE__) && \ (!defined(__OpenBSD__) || BOOST_OS_BSD_OPEN >= BOOST_VERSION_NUMBER(4, 4, 0)) && \ @@ -164,6 +167,8 @@ using std::time_t; #include "error_handling.hpp" #include "private_config.hpp" +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace fs = boost::filesystem; using boost::filesystem::path; using boost::filesystem::filesystem_error; @@ -286,7 +291,7 @@ BOOST_CONSTEXPR_OR_CONST unsigned int symloop_max = bool is_empty_directory(path const& p, error_code* ec) { fs::directory_iterator itr; - detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::none), ec); + detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::none), NULL, ec); return itr == fs::directory_iterator(); } @@ -472,6 +477,130 @@ inline std::size_t get_blksize(struct ::stat const& st) BOOST_NOEXCEPT #endif // defined(BOOST_FILESYSTEM_USE_STATX) +//! status() implementation +file_status status_impl +( + path const& p, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) + , int basedir_fd = AT_FDCWD +#endif +) +{ +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx path_stat; + int err = invoke_statx(basedir_fd, p.c_str(), AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &path_stat); +#elif defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + struct ::stat path_stat; + int err = ::fstatat(basedir_fd, p.c_str(), &path_stat, AT_NO_AUTOMOUNT); +#else + struct ::stat path_stat; + int err = ::stat(p.c_str(), &path_stat); +#endif + + if (err != 0) + { + err = errno; + if (ec) // always report errno, even though some + ec->assign(err, system_category()); // errno values are not status_errors + + if (not_found_error(err)) + return fs::file_status(fs::file_not_found, fs::no_perms); + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", p, error_code(err, system_category()))); + + return fs::file_status(fs::status_error); + } + +#if defined(BOOST_FILESYSTEM_USE_STATX) + if (BOOST_UNLIKELY((path_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::status"); + return fs::file_status(fs::status_error); + } +#endif + + const mode_t mode = get_mode(path_stat); + if (S_ISDIR(mode)) + return fs::file_status(fs::directory_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISREG(mode)) + return fs::file_status(fs::regular_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISBLK(mode)) + return fs::file_status(fs::block_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISCHR(mode)) + return fs::file_status(fs::character_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISFIFO(mode)) + return fs::file_status(fs::fifo_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISSOCK(mode)) + return fs::file_status(fs::socket_file, static_cast< perms >(mode) & fs::perms_mask); + + return fs::file_status(fs::type_unknown); +} + +//! symlink_status() implementation +file_status symlink_status_impl +( + path const& p, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) + , int basedir_fd = AT_FDCWD +#endif +) +{ +#if defined(BOOST_FILESYSTEM_USE_STATX) + struct ::statx path_stat; + int err = invoke_statx(basedir_fd, p.c_str(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &path_stat); +#elif defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + struct ::stat path_stat; + int err = ::fstatat(basedir_fd, p.c_str(), &path_stat, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT); +#else + struct ::stat path_stat; + int err = ::lstat(p.c_str(), &path_stat); +#endif + + if (err != 0) + { + err = errno; + if (ec) // always report errno, even though some + ec->assign(err, system_category()); // errno values are not status_errors + + if (not_found_error(err)) // these are not errors + return fs::file_status(fs::file_not_found, fs::no_perms); + + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::symlink_status", p, error_code(err, system_category()))); + + return fs::file_status(fs::status_error); + } + +#if defined(BOOST_FILESYSTEM_USE_STATX) + if (BOOST_UNLIKELY((path_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) + { + emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::symlink_status"); + return fs::file_status(fs::status_error); + } +#endif + + const mode_t mode = get_mode(path_stat); + if (S_ISREG(mode)) + return fs::file_status(fs::regular_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISDIR(mode)) + return fs::file_status(fs::directory_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISLNK(mode)) + return fs::file_status(fs::symlink_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISBLK(mode)) + return fs::file_status(fs::block_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISCHR(mode)) + return fs::file_status(fs::character_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISFIFO(mode)) + return fs::file_status(fs::fifo_file, static_cast< perms >(mode) & fs::perms_mask); + if (S_ISSOCK(mode)) + return fs::file_status(fs::socket_file, static_cast< perms >(mode) & fs::perms_mask); + + return fs::file_status(fs::type_unknown); +} + //! Flushes buffered data and attributes written to the file to permanent storage inline int full_sync(int fd) { @@ -611,130 +740,144 @@ typedef int copy_file_data_t(int infile, int outfile, uintmax_t size, std::size_ //! Pointer to the actual implementation of the copy_file_data implementation copy_file_data_t* copy_file_data = ©_file_data_read_write; +#if defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + +//! copy_file_data wrapper that tests if a read/write loop must be used for a given filesystem +template< typename CopyFileData > +int check_fs_type(int infile, int outfile, uintmax_t size, std::size_t blksize); + +#endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) + #if defined(BOOST_FILESYSTEM_USE_SENDFILE) -//! copy_file implementation that uses sendfile loop. Requires sendfile to support file descriptors. -int copy_file_data_sendfile(int infile, int outfile, uintmax_t size, std::size_t blksize) +struct copy_file_data_sendfile { - // sendfile will not send more than this amount of data in one call - BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u; - uintmax_t offset = 0u; - while (offset < size) - { - uintmax_t size_left = size - offset; - std::size_t size_to_copy = max_batch_size; - if (size_left < static_cast< uintmax_t >(max_batch_size)) - size_to_copy = static_cast< std::size_t >(size_left); - ssize_t sz = ::sendfile(outfile, infile, NULL, size_to_copy); - if (BOOST_UNLIKELY(sz < 0)) + //! copy_file implementation that uses sendfile loop. Requires sendfile to support file descriptors. + static int impl(int infile, int outfile, uintmax_t size, std::size_t blksize) + { + // sendfile will not send more than this amount of data in one call + BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u; + uintmax_t offset = 0u; + while (offset < size) { - int err = errno; - if (err == EINTR) - continue; - - if (offset == 0u) + uintmax_t size_left = size - offset; + std::size_t size_to_copy = max_batch_size; + if (size_left < static_cast< uintmax_t >(max_batch_size)) + size_to_copy = static_cast< std::size_t >(size_left); + ssize_t sz = ::sendfile(outfile, infile, NULL, size_to_copy); + if (BOOST_UNLIKELY(sz < 0)) { - // sendfile may fail with EINVAL if the underlying filesystem does not support it - if (err == EINVAL) - { - fallback_to_read_write: - return copy_file_data_read_write(infile, outfile, size, blksize); - } + int err = errno; + if (err == EINTR) + continue; - if (err == ENOSYS) + if (offset == 0u) { - filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_read_write); - goto fallback_to_read_write; + // sendfile may fail with EINVAL if the underlying filesystem does not support it + if (err == EINVAL) + { + fallback_to_read_write: + return copy_file_data_read_write(infile, outfile, size, blksize); + } + + if (err == ENOSYS) + { + filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_read_write); + goto fallback_to_read_write; + } } + + return err; } - return err; + offset += sz; } - offset += sz; + return 0; } - - return 0; -} +}; #endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) #if defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) -//! copy_file implementation that uses copy_file_range loop. Requires copy_file_range to support cross-filesystem copying. -int copy_file_data_copy_file_range(int infile, int outfile, uintmax_t size, std::size_t blksize) +struct copy_file_data_copy_file_range { - // Although copy_file_range does not document any particular upper limit of one transfer, still use some upper bound to guarantee - // that size_t is not overflown in case if off_t is larger and the file size does not fit in size_t. - BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u; - uintmax_t offset = 0u; - while (offset < size) - { - uintmax_t size_left = size - offset; - std::size_t size_to_copy = max_batch_size; - if (size_left < static_cast< uintmax_t >(max_batch_size)) - size_to_copy = static_cast< std::size_t >(size_left); - // Note: Use syscall directly to avoid depending on libc version. copy_file_range is added in glibc 2.27. - // uClibc-ng does not have copy_file_range as of the time of this writing (the latest uClibc-ng release is 1.0.33). - loff_t sz = ::syscall(__NR_copy_file_range, infile, (loff_t*)NULL, outfile, (loff_t*)NULL, size_to_copy, (unsigned int)0u); - if (BOOST_UNLIKELY(sz < 0)) + //! copy_file implementation that uses copy_file_range loop. Requires copy_file_range to support cross-filesystem copying. + static int impl(int infile, int outfile, uintmax_t size, std::size_t blksize) + { + // Although copy_file_range does not document any particular upper limit of one transfer, still use some upper bound to guarantee + // that size_t is not overflown in case if off_t is larger and the file size does not fit in size_t. + BOOST_CONSTEXPR_OR_CONST std::size_t max_batch_size = 0x7ffff000u; + uintmax_t offset = 0u; + while (offset < size) { - int err = errno; - if (err == EINTR) - continue; - - if (offset == 0u) + uintmax_t size_left = size - offset; + std::size_t size_to_copy = max_batch_size; + if (size_left < static_cast< uintmax_t >(max_batch_size)) + size_to_copy = static_cast< std::size_t >(size_left); + // Note: Use syscall directly to avoid depending on libc version. copy_file_range is added in glibc 2.27. + // uClibc-ng does not have copy_file_range as of the time of this writing (the latest uClibc-ng release is 1.0.33). + loff_t sz = ::syscall(__NR_copy_file_range, infile, (loff_t*)NULL, outfile, (loff_t*)NULL, size_to_copy, (unsigned int)0u); + if (BOOST_UNLIKELY(sz < 0)) { - // copy_file_range may fail with EINVAL if the underlying filesystem does not support it. - // In some RHEL/CentOS 7.7-7.8 kernel versions, copy_file_range on NFSv4 is also known to return EOPNOTSUPP - // if the remote server does not support COPY, despite that it is not a documented error code. - // See https://patchwork.kernel.org/project/linux-nfs/patch/20190411183418.4510-1-olga.kornievskaia@gmail.com/ - // and https://bugzilla.redhat.com/show_bug.cgi?id=1783554. - if (err == EINVAL || err == EOPNOTSUPP) + int err = errno; + if (err == EINTR) + continue; + + if (offset == 0u) { + // copy_file_range may fail with EINVAL if the underlying filesystem does not support it. + // In some RHEL/CentOS 7.7-7.8 kernel versions, copy_file_range on NFSv4 is also known to return EOPNOTSUPP + // if the remote server does not support COPY, despite that it is not a documented error code. + // See https://patchwork.kernel.org/project/linux-nfs/patch/20190411183418.4510-1-olga.kornievskaia@gmail.com/ + // and https://bugzilla.redhat.com/show_bug.cgi?id=1783554. + if (err == EINVAL || err == EOPNOTSUPP) + { #if !defined(BOOST_FILESYSTEM_USE_SENDFILE) - fallback_to_read_write: + fallback_to_read_write: #endif - return copy_file_data_read_write(infile, outfile, size, blksize); - } + return copy_file_data_read_write(infile, outfile, size, blksize); + } - if (err == EXDEV) - { + if (err == EXDEV) + { #if defined(BOOST_FILESYSTEM_USE_SENDFILE) - fallback_to_sendfile: - return copy_file_data_sendfile(infile, outfile, size, blksize); + fallback_to_sendfile: + return copy_file_data_sendfile::impl(infile, outfile, size, blksize); #else - goto fallback_to_read_write; + goto fallback_to_read_write; #endif - } + } - if (err == ENOSYS) - { + if (err == ENOSYS) + { #if defined(BOOST_FILESYSTEM_USE_SENDFILE) - filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_sendfile); - goto fallback_to_sendfile; + filesystem::detail::atomic_store_relaxed(copy_file_data, &check_fs_type< copy_file_data_sendfile >); + goto fallback_to_sendfile; #else - filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_read_write); - goto fallback_to_read_write; + filesystem::detail::atomic_store_relaxed(copy_file_data, ©_file_data_read_write); + goto fallback_to_read_write; #endif + } } + + return err; } - return err; + offset += sz; } - offset += sz; + return 0; } - - return 0; -} +}; #endif // defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) #if defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) //! copy_file_data wrapper that tests if a read/write loop must be used for a given filesystem -template< copy_file_data_t* CopyFileData > +template< typename CopyFileData > int check_fs_type(int infile, int outfile, uintmax_t size, std::size_t blksize) { { @@ -768,7 +911,7 @@ int check_fs_type(int infile, int outfile, uintmax_t size, std::size_t blksize) } } - return CopyFileData(infile, outfile, size, blksize); + return CopyFileData::impl(infile, outfile, size, blksize); } #endif // defined(BOOST_FILESYSTEM_USE_SENDFILE) || defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) @@ -784,14 +927,14 @@ inline void init_copy_file_data_impl(unsigned int major_ver, unsigned int minor_ #if defined(BOOST_FILESYSTEM_USE_SENDFILE) // sendfile started accepting file descriptors as the target in Linux 2.6.33 if (major_ver > 2u || (major_ver == 2u && (minor_ver > 6u || (minor_ver == 6u && patch_ver >= 33u)))) - cfd = &check_fs_type< ©_file_data_sendfile >; + cfd = &check_fs_type< copy_file_data_sendfile >; #endif #if defined(BOOST_FILESYSTEM_USE_COPY_FILE_RANGE) // Although copy_file_range appeared in Linux 4.5, it did not support cross-filesystem copying until 5.3. // copy_file_data_copy_file_range will fallback to copy_file_data_sendfile if copy_file_range returns EXDEV. if (major_ver > 4u || (major_ver == 4u && minor_ver >= 5u)) - cfd = &check_fs_type< ©_file_data_copy_file_range >; + cfd = &check_fs_type< copy_file_data_copy_file_range >; #endif filesystem::detail::atomic_store_relaxed(copy_file_data, cfd); @@ -827,16 +970,28 @@ const syscall_initializer syscall_init; #endif // defined(linux) || defined(__linux) || defined(__linux__) //! remove() implementation -inline bool remove_impl(path const& p, fs::file_type type, error_code* ec) +inline bool remove_impl +( + path const& p, + fs::file_type type, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , int basedir_fd = AT_FDCWD +#endif +) { if (type == fs::file_not_found) return false; int res; +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + res = ::unlinkat(basedir_fd, p.c_str(), type == fs::directory_file ? AT_REMOVEDIR : 0); +#else if (type == fs::directory_file) res = ::rmdir(p.c_str()); else res = ::unlink(p.c_str()); +#endif if (res != 0) { @@ -860,7 +1015,7 @@ inline bool remove_impl(path const& p, error_code* ec) // to remove them. error_code local_ec; - fs::file_type type = fs::detail::symlink_status(p, &local_ec).type(); + fs::file_type type = fs::detail::symlink_status_impl(p, &local_ec).type(); if (BOOST_UNLIKELY(type == fs::status_error)) { if (!ec) @@ -874,15 +1029,35 @@ inline bool remove_impl(path const& p, error_code* ec) } //! remove_all() implementation -uintmax_t remove_all_impl(path const& p, error_code* ec) +uintmax_t remove_all_impl +( + path const& p, + error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , int basedir_fd = AT_FDCWD +#endif +) { +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + fs::detail::directory_iterator_params params; + params.basedir_fd = basedir_fd; + params.iterator_fd = -1; +#endif + error_code dit_create_ec; for (unsigned int attempt = 0u; attempt < remove_all_directory_replaced_retry_count; ++attempt) { fs::file_type type; { error_code local_ec; - type = fs::detail::symlink_status(p, &local_ec).type(); + type = fs::detail::symlink_status_impl + ( + p, + &local_ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , basedir_fd +#endif + ).type(); if (type == fs::file_not_found) return 0u; @@ -901,7 +1076,19 @@ uintmax_t remove_all_impl(path const& p, error_code* ec) if (type == fs::directory_file) // but not a directory symlink { fs::directory_iterator itr; - fs::detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::_detail_no_follow), &dit_create_ec); + fs::detail::directory_iterator_construct + ( + itr, + p, + static_cast< unsigned int >(directory_options::_detail_no_follow), +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + ¶ms, +#else + NULL, +#endif + &dit_create_ec + ); + if (BOOST_UNLIKELY(!!dit_create_ec)) { if (dit_create_ec == error_code(ENOTDIR, system_category())) @@ -926,7 +1113,18 @@ uintmax_t remove_all_impl(path const& p, error_code* ec) const fs::directory_iterator end_dit; while (itr != end_dit) { - count += fs::detail::remove_all_impl(itr->path(), ec); + count += fs::detail::remove_all_impl + ( +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + itr->path().filename(), +#else + itr->path(), +#endif + ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , params.iterator_fd +#endif + ); if (ec && *ec) return static_cast< uintmax_t >(-1); @@ -936,7 +1134,15 @@ uintmax_t remove_all_impl(path const& p, error_code* ec) } } - count += fs::detail::remove_impl(p, type, ec); + count += fs::detail::remove_impl + ( + p, + type, + ec +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + , basedir_fd +#endif + ); if (ec && *ec) return static_cast< uintmax_t >(-1); @@ -1088,6 +1294,7 @@ SetFileInformationByHandle_t* set_file_information_by_handle_api = NULL; GetFileInformationByHandleEx_t* get_file_information_by_handle_ex_api = NULL; #if !defined(UNDER_CE) +NtCreateFile_t* nt_create_file_api = NULL; NtQueryDirectoryFile_t* nt_query_directory_file_api = NULL; #endif // !defined(UNDER_CE) @@ -1129,6 +1336,7 @@ 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")); } @@ -1235,6 +1443,74 @@ inline void to_FILETIME(std::time_t t, FILETIME& ft) BOOST_NOEXCEPT } // unnamed namespace +#if !defined(UNDER_CE) + +//! The flag indicates whether OBJ_DONT_REPARSE flag is not supported by the kernel +static bool g_no_obj_dont_reparse = false; + +//! Creates a file handle for a file relative to a previously opened base directory. The file path must be relative and in preferred format. +boost::winapi::NTSTATUS_ nt_create_file_handle_at(HANDLE& out, HANDLE basedir_handle, boost::filesystem::path const& p, ULONG FileAttributes, ACCESS_MASK DesiredAccess, ULONG ShareMode, ULONG CreateDisposition, ULONG CreateOptions) +{ + NtCreateFile_t* nt_create_file = filesystem::detail::atomic_load_relaxed(nt_create_file_api); + if (BOOST_UNLIKELY(!nt_create_file)) + return STATUS_NOT_IMPLEMENTED; + + unicode_string obj_name = {}; + obj_name.Buffer = const_cast< wchar_t* >(p.c_str()); + obj_name.Length = obj_name.MaximumLength = static_cast< USHORT >(p.size() * sizeof(wchar_t)); + + object_attributes obj_attrs = {}; + obj_attrs.Length = sizeof(obj_attrs); + obj_attrs.RootDirectory = basedir_handle; + obj_attrs.ObjectName = &obj_name; + + obj_attrs.Attributes = OBJ_CASE_INSENSITIVE; + if ((CreateOptions & FILE_OPEN_REPARSE_POINT) != 0u && !filesystem::detail::atomic_load_relaxed(g_no_obj_dont_reparse)) + obj_attrs.Attributes |= OBJ_DONT_REPARSE; + + io_status_block iosb; + boost::winapi::NTSTATUS_ status = nt_create_file + ( + &out, + DesiredAccess, + &obj_attrs, + &iosb, + NULL, // AllocationSize + FileAttributes, + ShareMode, + CreateDisposition, + CreateOptions, + NULL, // EaBuffer + 0u // EaLength + ); + + if (BOOST_UNLIKELY(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); + obj_attrs.Attributes &= ~static_cast< ULONG >(OBJ_DONT_REPARSE); + + status = nt_create_file + ( + &out, + DesiredAccess, + &obj_attrs, + &iosb, + NULL, // AllocationSize + FileAttributes, + ShareMode, + CreateDisposition, + CreateOptions, + NULL, // EaBuffer + 0u // EaLength + ); + } + + return status; +} + +#endif // !defined(UNDER_CE) + bool is_reparse_point_a_symlink_ioctl(HANDLE h) { boost::scoped_ptr< reparse_data_buffer_with_storage > buf(new reparse_data_buffer_with_storage); @@ -1252,7 +1528,13 @@ namespace { inline bool is_reparse_point_a_symlink(path const& p) { - handle_wrapper h(create_file_handle(p, 0u, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + handle_wrapper h(create_file_handle( + p, + FILE_READ_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) return false; @@ -1278,9 +1560,8 @@ inline std::size_t get_full_path_name(path const& src, std::size_t len, wchar_t* return static_cast< std::size_t >(::GetFullPathNameW(src.c_str(), static_cast< DWORD >(len), buf, p)); } -inline fs::file_status process_status_failure(path const& p, error_code* ec) +inline fs::file_status process_status_failure(DWORD errval, path const& p, error_code* ec) { - DWORD errval = ::GetLastError(); if (ec) // always report errval, even though some ec->assign(errval, system_category()); // errval values are not status_errors @@ -1299,6 +1580,129 @@ inline fs::file_status process_status_failure(path const& p, error_code* ec) return fs::file_status(fs::status_error); } +inline fs::file_status process_status_failure(path const& p, error_code* ec) +{ + return process_status_failure(::GetLastError(), p, ec); +} + +//! (symlink_)status() by handle implementation +fs::file_status status_by_handle(HANDLE h, path const& p, error_code* ec) +{ + fs::file_type ftype; + DWORD attrs; + GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); + if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL)) + { + file_attribute_tag_info info; + BOOL res = get_file_information_by_handle_ex(h, file_attribute_tag_info_class, &info, sizeof(info)); + if (BOOST_UNLIKELY(!res)) + { + // On FAT/exFAT filesystems requesting FILE_ATTRIBUTE_TAG_INFO returns ERROR_INVALID_PARAMETER. + // Presumably, this is because these filesystems don't support reparse points, so ReparseTag + // cannot be returned. Also check ERROR_NOT_SUPPORTED for good measure. Fall back to the legacy + // code path in this case. + DWORD err = ::GetLastError(); + if (err == ERROR_INVALID_PARAMETER || err == ERROR_NOT_SUPPORTED) + goto use_get_file_information_by_handle; + + return process_status_failure(err, p, ec); + } + + attrs = info.FileAttributes; + + if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) + { + ftype = is_reparse_point_tag_a_symlink(info.ReparseTag) ? fs::symlink_file : fs::reparse_file; + goto done; + } + } + else + { + use_get_file_information_by_handle: + BY_HANDLE_FILE_INFORMATION info; + BOOL res = ::GetFileInformationByHandle(h, &info); + if (BOOST_UNLIKELY(!res)) + return process_status_failure(p, ec); + + attrs = info.dwFileAttributes; + + if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) + { + ftype = is_reparse_point_a_symlink_ioctl(h) ? fs::symlink_file : fs::reparse_file; + goto done; + } + } + + ftype = (attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs::directory_file : fs::regular_file; + +done: + return fs::file_status(ftype, make_permissions(p, attrs)); +} + +//! symlink_status() implementation +fs::file_status symlink_status_impl(path const& p, error_code* ec) +{ + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, // dwDesiredAccess; attributes only + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, // lpSecurityAttributes + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + + if (h.handle == INVALID_HANDLE_VALUE) + { + // For some system files and folders like "System Volume Information" CreateFileW fails + // with ERROR_ACCESS_DENIED. GetFileAttributesW succeeds for such files, so try that. + // Though this will only help if the file is not a reparse point (symlink or not). + DWORD err = ::GetLastError(); + if (err == ERROR_ACCESS_DENIED) + { + DWORD attrs = ::GetFileAttributesW(p.c_str()); + if (attrs != INVALID_FILE_ATTRIBUTES) + { + if ((attrs & FILE_ATTRIBUTE_REPARSE_POINT) == 0u) + return fs::file_status((attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs::directory_file : fs::regular_file, make_permissions(p, attrs)); + } + else + { + err = ::GetLastError(); + } + } + + return process_status_failure(err, p, ec); + } + + return detail::status_by_handle(h.handle, p, ec); +} + +//! status() implementation +fs::file_status status_impl(path const& p, error_code* ec) +{ + // We should first test if the file is a symlink or a reparse point. Resolving some reparse + // points by opening the file may fail, and status() should return file_status(reparse_file) in this case. + // Which is what symlink_status() returns. + fs::file_status st(detail::symlink_status_impl(p, ec)); + if (st.type() == symlink_file) + { + // Resolve the symlink + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, // dwDesiredAccess; attributes only + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, // lpSecurityAttributes + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + if (h.handle == INVALID_HANDLE_VALUE) + return process_status_failure(p, ec); + + st = detail::status_by_handle(h.handle, p, ec); + } + + return st; +} + //! remove() implementation for Windows XP and older bool remove_nt5_impl(path const& p, DWORD attrs, error_code* ec) { @@ -1354,32 +1758,19 @@ bool remove_nt5_impl(path const& p, DWORD attrs, error_code* ec) return true; } -//! remove() implementation for Windows Vista and newer -bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec) +//! remove() by handle implementation for Windows Vista and newer +DWORD remove_nt6_by_handle(HANDLE handle, remove_impl_type impl) { - handle_wrapper h(create_file_handle(p, DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); - DWORD err; - if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) - { - err = ::GetLastError(); - - return_error: - if (!not_found_error(err)) - emit_error(err, p, ec, "boost::filesystem::remove"); - - return false; - } - GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); SetFileInformationByHandle_t* set_file_information_by_handle = filesystem::detail::atomic_load_relaxed(set_file_information_by_handle_api); + DWORD err = 0u; switch (impl) { case remove_disp_ex_flag_ignore_readonly: { file_disposition_info_ex info; info.Flags = FILE_DISPOSITION_FLAG_DELETE | FILE_DISPOSITION_FLAG_POSIX_SEMANTICS | FILE_DISPOSITION_FLAG_IGNORE_READONLY_ATTRIBUTE; - BOOL res = set_file_information_by_handle(h.handle, file_disposition_info_ex_class, &info, sizeof(info)); + BOOL res = set_file_information_by_handle(handle, file_disposition_info_ex_class, &info, sizeof(info)); if (BOOST_LIKELY(!!res)) break; @@ -1392,7 +1783,7 @@ bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec) } else { - goto return_error; + break; } } BOOST_FALLTHROUGH; @@ -1401,40 +1792,46 @@ bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec) { file_disposition_info_ex info; info.Flags = FILE_DISPOSITION_FLAG_DELETE | FILE_DISPOSITION_FLAG_POSIX_SEMANTICS; - BOOL res = set_file_information_by_handle(h.handle, file_disposition_info_ex_class, &info, sizeof(info)); + BOOL res = set_file_information_by_handle(handle, file_disposition_info_ex_class, &info, sizeof(info)); if (BOOST_LIKELY(!!res)) + { + err = 0u; break; + } err = ::GetLastError(); if (err == ERROR_ACCESS_DENIED) { // Check if the file is read-only and reset the attribute file_basic_info basic_info; - res = get_file_information_by_handle_ex(h.handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + res = get_file_information_by_handle_ex(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); if (BOOST_UNLIKELY(!res || (basic_info.FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)) - goto return_error; // return ERROR_ACCESS_DENIED + break; // return ERROR_ACCESS_DENIED basic_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; - res = set_file_information_by_handle(h.handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + res = set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); if (BOOST_UNLIKELY(!res)) { err = ::GetLastError(); - goto return_error; + break; } // Try to set the flag again - res = set_file_information_by_handle(h.handle, file_disposition_info_ex_class, &info, sizeof(info)); + res = set_file_information_by_handle(handle, file_disposition_info_ex_class, &info, sizeof(info)); if (BOOST_LIKELY(!!res)) + { + err = 0u; break; + } err = ::GetLastError(); // Try to restore the read-only flag basic_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; - set_file_information_by_handle(h.handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); - goto return_error; + break; } else if (BOOST_UNLIKELY(err == ERROR_INVALID_PARAMETER || err == ERROR_INVALID_FUNCTION || err == ERROR_NOT_SUPPORTED)) { @@ -1444,7 +1841,7 @@ bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec) } else { - goto return_error; + break; } } BOOST_FALLTHROUGH; @@ -1453,54 +1850,89 @@ bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec) { file_disposition_info info; info.DeleteFile = true; - BOOL res = set_file_information_by_handle(h.handle, file_disposition_info_class, &info, sizeof(info)); + BOOL res = set_file_information_by_handle(handle, file_disposition_info_class, &info, sizeof(info)); if (BOOST_LIKELY(!!res)) + { + err = 0u; break; + } err = ::GetLastError(); if (err == ERROR_ACCESS_DENIED) { // Check if the file is read-only and reset the attribute file_basic_info basic_info; - res = get_file_information_by_handle_ex(h.handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + res = get_file_information_by_handle_ex(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); if (BOOST_UNLIKELY(!res || (basic_info.FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)) - goto return_error; // return ERROR_ACCESS_DENIED + break; // return ERROR_ACCESS_DENIED basic_info.FileAttributes &= ~FILE_ATTRIBUTE_READONLY; - res = set_file_information_by_handle(h.handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + res = set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); if (BOOST_UNLIKELY(!res)) { err = ::GetLastError(); - goto return_error; + break; } // Try to set the flag again - res = set_file_information_by_handle(h.handle, file_disposition_info_class, &info, sizeof(info)); + res = set_file_information_by_handle(handle, file_disposition_info_class, &info, sizeof(info)); if (BOOST_LIKELY(!!res)) + { + err = 0u; break; + } err = ::GetLastError(); // Try to restore the read-only flag basic_info.FileAttributes |= FILE_ATTRIBUTE_READONLY; - set_file_information_by_handle(h.handle, file_basic_info_class, &basic_info, sizeof(basic_info)); + set_file_information_by_handle(handle, file_basic_info_class, &basic_info, sizeof(basic_info)); } - goto return_error; + break; } } + return err; +} + +//! remove() implementation for Windows Vista and newer +inline bool remove_nt6_impl(path const& p, remove_impl_type impl, error_code* ec) +{ + handle_wrapper h(create_file_handle( + p, + DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + DWORD err = 0u; + if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) + { + err = ::GetLastError(); + + return_error: + if (!not_found_error(err)) + emit_error(err, p, ec, "boost::filesystem::remove"); + + return false; + } + + err = fs::detail::remove_nt6_by_handle(h.handle, impl); + if (BOOST_UNLIKELY(err != 0u)) + goto return_error; + return true; } //! remove() implementation inline bool remove_impl(path const& p, error_code* ec) { - remove_impl_type impl = filesystem::detail::atomic_load_relaxed(g_remove_impl_type); + remove_impl_type impl = fs::detail::atomic_load_relaxed(g_remove_impl_type); if (BOOST_LIKELY(impl != remove_nt5)) { - return remove_nt6_impl(p, impl, ec); + return fs::detail::remove_nt6_impl(p, impl, ec); } else { @@ -1514,14 +1946,131 @@ inline bool remove_impl(path const& p, error_code* ec) return false; } - return remove_nt5_impl(p, attrs, ec); + return fs::detail::remove_nt5_impl(p, attrs, ec); } } -//! remove_all() implementation -uintmax_t remove_all_impl(path const& p, error_code* ec) +#if !defined(UNDER_CE) + +//! remove_all() by handle implementation for Windows Vista and newer +uintmax_t remove_all_nt6_by_handle(HANDLE h, path const& p, error_code* ec) +{ + error_code local_ec; + fs::file_status st(fs::detail::status_by_handle(h, p, &local_ec)); + if (BOOST_UNLIKELY(st.type() == fs::status_error)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all", p, local_ec)); + + *ec = local_ec; + return static_cast< uintmax_t >(-1); + } + + uintmax_t count = 0u; + if (st.type() == fs::directory_file) + { + local_ec.clear(); + + fs::directory_iterator itr; + directory_iterator_params params; + params.use_handle = h; + params.close_handle = false; // the caller will close the handle + fs::detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::_detail_no_follow), ¶ms, &local_ec); + if (BOOST_UNLIKELY(!!local_ec)) + { + if (!ec) + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::remove_all", p, local_ec)); + + *ec = local_ec; + return static_cast< uintmax_t >(-1); + } + + NtCreateFile_t* nt_create_file = filesystem::detail::atomic_load_relaxed(nt_create_file_api); + const fs::directory_iterator end_dit; + while (itr != end_dit) + { + fs::path nested_path(itr->path()); + handle_wrapper hh; + if (BOOST_LIKELY(nt_create_file != NULL)) + { + // Note: WinAPI methods like CreateFileW implicitly request SYNCHRONIZE access but NtCreateFile doesn't. + // Without SYNCHRONIZE access querying file attributes via GetFileInformationByHandleEx fails with ERROR_ACCESS_DENIED. + boost::winapi::NTSTATUS_ status = nt_create_file_handle_at + ( + hh.handle, + h, + nested_path.filename(), + 0u, // FileAttributes + FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + FILE_OPEN, + FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_REPARSE_POINT + ); + + if (!NT_SUCCESS(status)) + { + if (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) + { + goto next_entry; + } + + DWORD err = translate_ntstatus(status); + emit_error(err, nested_path, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + } + else + { + hh.handle = create_file_handle( + nested_path, + FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT); + + if (BOOST_UNLIKELY(hh.handle == INVALID_HANDLE_VALUE)) + { + DWORD err = ::GetLastError(); + if (not_found_error(err)) + goto next_entry; + + emit_error(err, nested_path, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + } + + count += fs::detail::remove_all_nt6_by_handle(hh.handle, nested_path, ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + + next_entry: + fs::detail::directory_iterator_increment(itr, ec); + if (ec && *ec) + return static_cast< uintmax_t >(-1); + } + } + + DWORD err = fs::detail::remove_nt6_by_handle(h, fs::detail::atomic_load_relaxed(g_remove_impl_type)); + if (BOOST_UNLIKELY(err != 0u)) + { + emit_error(err, p, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + + ++count; + return count; +} + +#endif // !defined(UNDER_CE) + +//! remove_all() implementation for Windows XP and older +uintmax_t remove_all_nt5_impl(path const& p, error_code* ec) { - remove_impl_type impl = filesystem::detail::atomic_load_relaxed(g_remove_impl_type); error_code dit_create_ec; for (unsigned int attempt = 0u; attempt < remove_all_directory_replaced_retry_count; ++attempt) { @@ -1542,7 +2091,7 @@ uintmax_t remove_all_impl(path const& p, error_code* ec) if (recurse) { fs::directory_iterator itr; - fs::detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::_detail_no_follow), &dit_create_ec); + fs::detail::directory_iterator_construct(itr, p, static_cast< unsigned int >(directory_options::_detail_no_follow), NULL, &dit_create_ec); if (BOOST_UNLIKELY(!!dit_create_ec)) { if (dit_create_ec == make_error_condition(system::errc::not_a_directory) || @@ -1561,7 +2110,7 @@ uintmax_t remove_all_impl(path const& p, error_code* ec) const fs::directory_iterator end_dit; while (itr != end_dit) { - count += remove_all_impl(itr->path(), ec); + count += fs::detail::remove_all_nt5_impl(itr->path(), ec); if (ec && *ec) return static_cast< uintmax_t >(-1); @@ -1571,11 +2120,7 @@ uintmax_t remove_all_impl(path const& p, error_code* ec) } } - bool removed; - if (BOOST_LIKELY(impl != remove_nt5)) - removed = remove_nt6_impl(p, impl, ec); - else - removed = remove_nt5_impl(p, attrs, ec); + bool removed = fs::detail::remove_nt5_impl(p, attrs, ec); if (ec && *ec) return static_cast< uintmax_t >(-1); @@ -1590,6 +2135,38 @@ uintmax_t remove_all_impl(path const& p, error_code* ec) return static_cast< uintmax_t >(-1); } +//! remove_all() implementation +inline uintmax_t remove_all_impl(path const& p, error_code* ec) +{ +#if !defined(UNDER_CE) + remove_impl_type impl = fs::detail::atomic_load_relaxed(g_remove_impl_type); + if (BOOST_LIKELY(impl != remove_nt5)) + { + handle_wrapper h(create_file_handle( + p, + FILE_LIST_DIRECTORY | DELETE | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + + if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) + { + DWORD err = ::GetLastError(); + if (not_found_error(err)) + return 0u; + + emit_error(err, p, ec, "boost::filesystem::remove_all"); + return static_cast< uintmax_t >(-1); + } + + return fs::detail::remove_all_nt6_by_handle(h.handle, p, ec); + } +#endif // !defined(UNDER_CE) + + return fs::detail::remove_all_nt5_impl(p, ec); +} + inline BOOL resize_file_impl(const wchar_t* p, uintmax_t size) { handle_wrapper h(CreateFileW(p, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)); @@ -1836,7 +2413,7 @@ path canonical(path const& p, path const& base, system::error_code* ec) } system::error_code local_ec; - file_status st(detail::status(source, &local_ec)); + file_status st(detail::status_impl(source, &local_ec)); if (st.type() == fs::file_not_found) { @@ -1890,7 +2467,7 @@ path canonical(path const& p, path const& base, system::error_code* ec) if (!result.is_absolute()) continue; - st = detail::symlink_status(result, ec); + st = detail::symlink_status_impl(result, ec); if (ec && *ec) goto return_empty_path; @@ -1964,16 +2541,19 @@ void copy(path const& from, path const& to, unsigned int options, system::error_ ((options & static_cast< unsigned int >(copy_options::create_symlinks)) != 0u) + ((options & static_cast< unsigned int >(copy_options::create_hard_links)) != 0u)) <= 1); + if (ec) + ec->clear(); + file_status from_stat; if ((options & (static_cast< unsigned int >(copy_options::copy_symlinks) | static_cast< unsigned int >(copy_options::skip_symlinks) | static_cast< unsigned int >(copy_options::create_symlinks))) != 0u) { - from_stat = detail::symlink_status(from, ec); + from_stat = detail::symlink_status_impl(from, ec); } else { - from_stat = detail::status(from, ec); + from_stat = detail::status_impl(from, ec); } if (ec && *ec) @@ -2044,11 +2624,11 @@ void copy(path const& from, path const& to, unsigned int options, system::error_ if ((options & (static_cast< unsigned int >(copy_options::skip_symlinks) | static_cast< unsigned int >(copy_options::create_symlinks))) != 0u) { - to_stat = detail::symlink_status(to, &local_ec); + to_stat = detail::symlink_status_impl(to, &local_ec); } else { - to_stat = detail::status(to, &local_ec); + to_stat = detail::status_impl(to, &local_ec); } // Note: local_ec may be set by (symlink_)status() even in some non-fatal situations, e.g. when the file does not exist. @@ -2082,11 +2662,11 @@ void copy(path const& from, path const& to, unsigned int options, system::error_ if ((options & (static_cast< unsigned int >(copy_options::skip_symlinks) | static_cast< unsigned int >(copy_options::create_symlinks))) != 0u) { - to_stat = detail::symlink_status(to, &local_ec); + to_stat = detail::symlink_status_impl(to, &local_ec); } else { - to_stat = detail::status(to, &local_ec); + to_stat = detail::status_impl(to, &local_ec); } // Note: ec may be set by (symlink_)status() even in some non-fatal situations, e.g. when the file does not exist. @@ -2109,7 +2689,7 @@ void copy(path const& from, path const& to, unsigned int options, system::error_ if ((options & static_cast< unsigned int >(copy_options::recursive)) != 0u || options == 0u) { fs::directory_iterator itr; - detail::directory_iterator_construct(itr, from, static_cast< unsigned int >(directory_options::none), ec); + detail::directory_iterator_construct(itr, from, static_cast< unsigned int >(directory_options::none), NULL, ec); if (ec && *ec) return; @@ -2205,7 +2785,7 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod } mode_t to_mode = from_mode; -#if !defined(__wasm) +#if !defined(BOOST_FILESYSTEM_USE_WASI) // Enable writing for the newly created files. Having write permission set is important e.g. for NFS, // which checks the file permission on the server, even if the client's file descriptor supports writing. to_mode |= S_IWUSR; @@ -2324,7 +2904,7 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod if (BOOST_UNLIKELY(err != 0)) goto fail; // err already contains the error code -#if !defined(__wasm) +#if !defined(BOOST_FILESYSTEM_USE_WASI) // If we created a new file with an explicitly added S_IWUSR permission, // we may need to update its mode bits to match the source file. if (to_mode != from_mode) @@ -2373,7 +2953,7 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod // Create handle_wrappers here so that CloseHandle calls don't clobber error code returned by GetLastError handle_wrapper hw_from, hw_to; - hw_from.handle = create_file_handle(from.c_str(), 0u, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS); + hw_from.handle = create_file_handle(from.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS); FILETIME lwt_from; if (hw_from.handle == INVALID_HANDLE_VALUE) @@ -2384,15 +2964,15 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod return false; } - if (!::GetFileTime(hw_from.handle, 0, 0, &lwt_from)) + if (!::GetFileTime(hw_from.handle, NULL, NULL, &lwt_from)) goto fail_last_error; - hw_to.handle = create_file_handle(to.c_str(), 0u, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS); + hw_to.handle = create_file_handle(to.c_str(), FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS); if (hw_to.handle != INVALID_HANDLE_VALUE) { FILETIME lwt_to; - if (!::GetFileTime(hw_to.handle, 0, 0, &lwt_to)) + if (!::GetFileTime(hw_to.handle, NULL, NULL, &lwt_to)) goto fail_last_error; ULONGLONG tfrom = (static_cast< ULONGLONG >(lwt_from.dwHighDateTime) << 32) | static_cast< ULONGLONG >(lwt_from.dwLowDateTime); @@ -2512,7 +3092,7 @@ bool create_directories(path const& p, system::error_code* ec) { if (!fname.empty() && fname != dot_p && fname != dot_dot_p) { - file_status existing_status = detail::status(parent, &local_ec); + file_status existing_status = detail::status_impl(parent, &local_ec); if (existing_status.type() == directory_file) { @@ -2760,7 +3340,7 @@ void create_symlink(path const& to, path const& from, error_code* ec) BOOST_FILESYSTEM_DECL path current_path(error_code* ec) { -#if defined(UNDER_CE) || defined(__wasm) +#if defined(UNDER_CE) || defined(BOOST_FILESYSTEM_USE_WASI) // Windows CE has no current directory, so everything's relative to the root of the directory tree. // WASI also does not support current path. emit_error(BOOST_ERROR_NOT_SUPPORTED, ec, "boost::filesystem::current_path"); @@ -2830,7 +3410,7 @@ path current_path(error_code* ec) BOOST_FILESYSTEM_DECL void current_path(path const& p, system::error_code* ec) { -#if defined(UNDER_CE) || defined(__wasm) +#if defined(UNDER_CE) || defined(BOOST_FILESYSTEM_USE_WASI) emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::current_path"); #else error(!BOOST_SET_CURRENT_DIRECTORY(p.c_str()) ? BOOST_ERRNO : 0, p, ec, "boost::filesystem::current_path"); @@ -2894,23 +3474,21 @@ bool equivalent(path const& p1, path const& p2, system::error_code* ec) // been retrieved. // p2 is done first, so any error reported is for p1 - handle_wrapper h2( - create_file_handle( - p2.c_str(), - 0u, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS)); - - handle_wrapper h1( - create_file_handle( - p1.c_str(), - 0u, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS)); + handle_wrapper h2(create_file_handle( + p2.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); + + handle_wrapper h1(create_file_handle( + p1.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); if (BOOST_UNLIKELY(h1.handle == INVALID_HANDLE_VALUE || h2.handle == INVALID_HANDLE_VALUE)) { @@ -3044,8 +3622,13 @@ uintmax_t hard_link_count(path const& p, system::error_code* ec) #else // defined(BOOST_POSIX_API) - handle_wrapper h( - create_file_handle(p.c_str(), 0u, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)); + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) { @@ -3166,8 +3749,13 @@ std::time_t creation_time(path const& p, system::error_code* ec) #else // defined(BOOST_POSIX_API) - handle_wrapper hw( - create_file_handle(p.c_str(), 0u, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)); + handle_wrapper hw(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); if (BOOST_UNLIKELY(hw.handle == INVALID_HANDLE_VALUE)) { @@ -3219,8 +3807,13 @@ std::time_t last_write_time(path const& p, system::error_code* ec) #else // defined(BOOST_POSIX_API) - handle_wrapper hw( - create_file_handle(p.c_str(), 0u, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)); + handle_wrapper hw(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); if (BOOST_UNLIKELY(hw.handle == INVALID_HANDLE_VALUE)) { @@ -3247,7 +3840,7 @@ void last_write_time(path const& p, const std::time_t new_time, system::error_co #if defined(BOOST_POSIX_API) -#if _POSIX_C_SOURCE >= 200809L +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) struct timespec times[2] = {}; @@ -3262,7 +3855,7 @@ void last_write_time(path const& p, const std::time_t new_time, system::error_co return; } -#else // _POSIX_C_SOURCE >= 200809L +#else // defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) struct ::stat st; if (BOOST_UNLIKELY(::stat(p.c_str(), &st) < 0)) @@ -3272,17 +3865,22 @@ void last_write_time(path const& p, const std::time_t new_time, system::error_co } ::utimbuf buf; - buf.actime = st.st_atime; // utime()updates access time too:-( + buf.actime = st.st_atime; // utime() updates access time too :-( buf.modtime = new_time; if (BOOST_UNLIKELY(::utime(p.c_str(), &buf) < 0)) emit_error(BOOST_ERRNO, p, ec, "boost::filesystem::last_write_time"); -#endif // _POSIX_C_SOURCE >= 200809L +#endif // defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) #else // defined(BOOST_POSIX_API) - handle_wrapper hw( - create_file_handle(p.c_str(), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS)); + handle_wrapper hw(create_file_handle( + p.c_str(), + FILE_WRITE_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS)); if (BOOST_UNLIKELY(hw.handle == INVALID_HANDLE_VALUE)) { @@ -3294,7 +3892,7 @@ void last_write_time(path const& p, const std::time_t new_time, system::error_co FILETIME lwt; to_FILETIME(new_time, lwt); - if (BOOST_UNLIKELY(!::SetFileTime(hw.handle, 0, 0, &lwt))) + if (BOOST_UNLIKELY(!::SetFileTime(hw.handle, NULL, NULL, &lwt))) goto fail; #endif // defined(BOOST_POSIX_API) @@ -3316,11 +3914,11 @@ void permissions(path const& p, perms prms, system::error_code* ec) if ((prms & add_perms) && (prms & remove_perms)) // precondition failed return; -#if defined(__wasm) +#if defined(BOOST_FILESYSTEM_USE_WASI) emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::permissions"); #elif defined(BOOST_POSIX_API) error_code local_ec; - file_status current_status((prms & symlink_perms) ? fs::symlink_status(p, local_ec) : fs::status(p, local_ec)); + file_status current_status((prms & symlink_perms) ? detail::symlink_status_impl(p, &local_ec) : detail::status_impl(p, &local_ec)); if (local_ec) { if (!ec) @@ -3346,11 +3944,12 @@ void permissions(path const& p, perms prms, system::error_code* ec) // "http://man7.org/linux/man-pages/man7/symlink.7.html" // - See the fchmodat() Linux man page: // "http://man7.org/linux/man-pages/man2/fchmodat.2.html" -#if defined(AT_FDCWD) && defined(AT_SYMLINK_NOFOLLOW) && \ +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) && \ !(defined(__SUNPRO_CC) || defined(__sun) || defined(sun)) && \ !(defined(linux) || defined(__linux) || defined(__linux__)) && \ !(defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101000) && \ !(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 80000) && \ + !(defined(__rtems__)) && \ !(defined(__QNX__) && (_NTO_VERSION <= 700)) if (::fchmodat(AT_FDCWD, p.c_str(), mode_cast(prms), !(prms & symlink_perms) ? 0 : AT_SYMLINK_NOFOLLOW)) #else // fallback if fchmodat() not supported @@ -3445,8 +4044,13 @@ path read_symlink(path const& p, system::error_code* ec) #else - handle_wrapper h( - create_file_handle(p.c_str(), 0u, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); + handle_wrapper h(create_file_handle( + p.c_str(), + FILE_READ_ATTRIBUTES, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); DWORD error; if (BOOST_UNLIKELY(h.handle == INVALID_HANDLE_VALUE)) @@ -3460,7 +4064,7 @@ path read_symlink(path const& p, system::error_code* ec) boost::scoped_ptr< reparse_data_buffer_with_storage > buf(new reparse_data_buffer_with_storage); DWORD sz = 0u; - if (BOOST_UNLIKELY(!::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, 0, 0, buf.get(), sizeof(*buf), &sz, 0))) + if (BOOST_UNLIKELY(!::DeviceIoControl(h.handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buf.get(), sizeof(*buf), &sz, NULL))) { error = ::GetLastError(); goto return_error; @@ -3575,7 +4179,7 @@ space_info space(path const& p, error_code* ec) if (ec) ec->clear(); -#if defined(__wasm) +#if defined(BOOST_FILESYSTEM_USE_WASI) emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::space"); @@ -3594,7 +4198,7 @@ space_info space(path const& p, error_code* ec) // GetDiskFreeSpaceExW requires a directory path, which is unlike statvfs, which accepts any file. // To work around this, test if the path refers to a directory and use the parent directory if not. error_code local_ec; - file_status status = detail::status(p, &local_ec); + file_status status = detail::status_impl(p, &local_ec); if (status.type() == fs::status_error || status.type() == fs::file_not_found) { fail_local_ec: @@ -3611,7 +4215,7 @@ space_info space(path const& p, error_code* ec) if (ec && *ec) return info; - status = detail::symlink_status(p, &local_ec); + status = detail::symlink_status_impl(p, &local_ec); if (status.type() == fs::status_error) goto fail_local_ec; if (is_symlink(status)) @@ -3654,106 +4258,7 @@ file_status status(path const& p, error_code* ec) if (ec) ec->clear(); -#if defined(BOOST_POSIX_API) - -#if defined(BOOST_FILESYSTEM_USE_STATX) - struct ::statx path_stat; - int err = invoke_statx(AT_FDCWD, p.c_str(), AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &path_stat); -#else - struct ::stat path_stat; - int err = ::stat(p.c_str(), &path_stat); -#endif - - if (err != 0) - { - err = errno; - if (ec) // always report errno, even though some - ec->assign(err, system_category()); // errno values are not status_errors - - if (not_found_error(err)) - return fs::file_status(fs::file_not_found, fs::no_perms); - - if (!ec) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", p, error_code(err, system_category()))); - - return fs::file_status(fs::status_error); - } - -#if defined(BOOST_FILESYSTEM_USE_STATX) - if (BOOST_UNLIKELY((path_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) - { - emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::status"); - return fs::file_status(fs::status_error); - } -#endif - - const mode_t mode = get_mode(path_stat); - if (S_ISDIR(mode)) - return fs::file_status(fs::directory_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISREG(mode)) - return fs::file_status(fs::regular_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISBLK(mode)) - return fs::file_status(fs::block_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISCHR(mode)) - return fs::file_status(fs::character_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISFIFO(mode)) - return fs::file_status(fs::fifo_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISSOCK(mode)) - return fs::file_status(fs::socket_file, static_cast< perms >(mode) & fs::perms_mask); - return fs::file_status(fs::type_unknown); - -#else // defined(BOOST_POSIX_API) - - // We should first test if the file is a symlink or a reparse point. Resolving some reparse - // points by opening the file may fail, and status() should return file_status(reparse_file) in this case. - // Which is what symlink_status() returns. - fs::file_status st(detail::symlink_status(p, ec)); - if (st.type() == symlink_file) - { - // Resolve the symlink - handle_wrapper h( - create_file_handle( - p.c_str(), - 0u, // dwDesiredAccess; attributes only - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, // lpSecurityAttributes - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS)); - - if (h.handle == INVALID_HANDLE_VALUE) - { - return_status_failure: - return process_status_failure(p, ec); - } - - DWORD attrs; - GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); - if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL)) - { - file_attribute_tag_info info; - BOOL res = get_file_information_by_handle_ex(h.handle, file_attribute_tag_info_class, &info, sizeof(info)); - if (BOOST_UNLIKELY(!res)) - goto return_status_failure; - - attrs = info.FileAttributes; - } - else - { - BY_HANDLE_FILE_INFORMATION info; - BOOL res = ::GetFileInformationByHandle(h.handle, &info); - if (BOOST_UNLIKELY(!res)) - goto return_status_failure; - - attrs = info.dwFileAttributes; - } - - st.permissions(make_permissions(p, attrs)); - st.type((attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs::directory_file : fs::regular_file); - } - - return st; - -#endif // defined(BOOST_POSIX_API) + return detail::status_impl(p, ec); } BOOST_FILESYSTEM_DECL @@ -3762,106 +4267,7 @@ file_status symlink_status(path const& p, error_code* ec) if (ec) ec->clear(); -#if defined(BOOST_POSIX_API) - -#if defined(BOOST_FILESYSTEM_USE_STATX) - struct ::statx path_stat; - int err = invoke_statx(AT_FDCWD, p.c_str(), AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT, STATX_TYPE | STATX_MODE, &path_stat); -#else - struct ::stat path_stat; - int err = ::lstat(p.c_str(), &path_stat); -#endif - - if (err != 0) - { - err = errno; - if (ec) // always report errno, even though some - ec->assign(err, system_category()); // errno values are not status_errors - - if (not_found_error(err)) // these are not errors - return fs::file_status(fs::file_not_found, fs::no_perms); - - if (!ec) - BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::symlink_status", p, error_code(err, system_category()))); - - return fs::file_status(fs::status_error); - } - -#if defined(BOOST_FILESYSTEM_USE_STATX) - if (BOOST_UNLIKELY((path_stat.stx_mask & (STATX_TYPE | STATX_MODE)) != (STATX_TYPE | STATX_MODE))) - { - emit_error(BOOST_ERROR_NOT_SUPPORTED, p, ec, "boost::filesystem::symlink_status"); - return fs::file_status(fs::status_error); - } -#endif - - const mode_t mode = get_mode(path_stat); - if (S_ISREG(mode)) - return fs::file_status(fs::regular_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISDIR(mode)) - return fs::file_status(fs::directory_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISLNK(mode)) - return fs::file_status(fs::symlink_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISBLK(mode)) - return fs::file_status(fs::block_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISCHR(mode)) - return fs::file_status(fs::character_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISFIFO(mode)) - return fs::file_status(fs::fifo_file, static_cast< perms >(mode) & fs::perms_mask); - if (S_ISSOCK(mode)) - return fs::file_status(fs::socket_file, static_cast< perms >(mode) & fs::perms_mask); - return fs::file_status(fs::type_unknown); - -#else // defined(BOOST_POSIX_API) - - handle_wrapper h( - create_file_handle( - p.c_str(), - 0u, // dwDesiredAccess; attributes only - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, // lpSecurityAttributes - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT)); - - if (h.handle == INVALID_HANDLE_VALUE) - { - return_status_failure: - return process_status_failure(p, ec); - } - - DWORD attrs; - fs::perms permissions; - GetFileInformationByHandleEx_t* get_file_information_by_handle_ex = filesystem::detail::atomic_load_relaxed(get_file_information_by_handle_ex_api); - if (BOOST_LIKELY(get_file_information_by_handle_ex != NULL)) - { - file_attribute_tag_info info; - BOOL res = get_file_information_by_handle_ex(h.handle, file_attribute_tag_info_class, &info, sizeof(info)); - if (BOOST_UNLIKELY(!res)) - goto return_status_failure; - - attrs = info.FileAttributes; - permissions = make_permissions(p, attrs); - - if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) - return is_reparse_point_tag_a_symlink(info.ReparseTag) ? fs::file_status(fs::symlink_file, permissions) : fs::file_status(fs::reparse_file, permissions); - } - else - { - BY_HANDLE_FILE_INFORMATION info; - BOOL res = ::GetFileInformationByHandle(h.handle, &info); - if (BOOST_UNLIKELY(!res)) - goto return_status_failure; - - attrs = info.dwFileAttributes; - permissions = make_permissions(p, attrs); - - if (attrs & FILE_ATTRIBUTE_REPARSE_POINT) - return is_reparse_point_a_symlink_ioctl(h.handle) ? fs::file_status(fs::symlink_file, permissions) : fs::file_status(fs::reparse_file, permissions); - } - - return (attrs & FILE_ATTRIBUTE_DIRECTORY) ? fs::file_status(fs::directory_file, permissions) : fs::file_status(fs::regular_file, permissions); - -#endif // defined(BOOST_POSIX_API) + return detail::symlink_status_impl(p, ec); } // contributed by Jeff Flinn @@ -3893,7 +4299,7 @@ path temp_directory_path(system::error_code* ec) return p; } - file_status status = detail::status(p, ec); + file_status status = detail::status_impl(p, ec); if (BOOST_UNLIKELY(ec && *ec)) return path(); if (BOOST_UNLIKELY(!is_directory(status))) @@ -3969,7 +4375,7 @@ path temp_directory_path(system::error_code* ec) path p(buf.get()); p.remove_trailing_separator(); - file_status status = detail::status(p, ec); + file_status status = detail::status_impl(p, ec); if (ec && *ec) return path(); if (!is_directory(status)) @@ -4028,7 +4434,7 @@ path weakly_canonical(path const& p, path const& base, system::error_code* ec) path head(p); for (; !head.empty(); --itr) { - file_status head_status = detail::status(head, &local_ec); + file_status head_status = detail::status_impl(head, &local_ec); if (BOOST_UNLIKELY(head_status.type() == fs::status_error)) { if (!ec) @@ -4069,7 +4475,7 @@ path weakly_canonical(path const& p, path const& base, system::error_code* ec) head /= p_elem; } - file_status head_status = detail::status(head, &local_ec); + file_status head_status = detail::status_impl(head, &local_ec); if (BOOST_UNLIKELY(head_status.type() == fs::status_error)) { if (!ec) @@ -4138,3 +4544,5 @@ path weakly_canonical(path const& p, path const& base, system::error_code* ec) } // namespace detail } // namespace filesystem } // namespace boost + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/path.cpp b/contrib/restricted/boost/filesystem/src/path.cpp index f6cb3ba9a16..27b32e57c52 100644 --- a/contrib/restricted/boost/filesystem/src/path.cpp +++ b/contrib/restricted/boost/filesystem/src/path.cpp @@ -40,6 +40,8 @@ #include "atomic_tools.hpp" #include "private_config.hpp" +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace fs = boost::filesystem; using boost::filesystem::path; @@ -1678,3 +1680,5 @@ BOOST_FILESYSTEM_DECL path const& dot_dot_path() } // namespace detail } // namespace filesystem } // namespace boost + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/path_traits.cpp b/contrib/restricted/boost/filesystem/src/path_traits.cpp index d882ad89a08..aa4b8815f7b 100644 --- a/contrib/restricted/boost/filesystem/src/path_traits.cpp +++ b/contrib/restricted/boost/filesystem/src/path_traits.cpp @@ -22,6 +22,8 @@ #include <cwchar> // for wcslen #include <cstddef> +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace pt = boost::filesystem::path_traits; namespace fs = boost::filesystem; namespace bs = boost::system; @@ -195,3 +197,5 @@ void convert(const wchar_t* from, } // namespace path_traits } // namespace filesystem } // namespace boost + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/portability.cpp b/contrib/restricted/boost/filesystem/src/portability.cpp index 43e63b074ec..8e0e2e5d98d 100644 --- a/contrib/restricted/boost/filesystem/src/portability.cpp +++ b/contrib/restricted/boost/filesystem/src/portability.cpp @@ -17,6 +17,8 @@ #include <cstring> // SGI MIPSpro compilers need this #include <string> +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace boost { namespace filesystem { @@ -77,3 +79,5 @@ BOOST_FILESYSTEM_DECL bool portable_file_name(std::string const& name) } // namespace filesystem } // namespace boost + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/posix_tools.hpp b/contrib/restricted/boost/filesystem/src/posix_tools.hpp index 52426d4a36a..52cd87b0a02 100644 --- a/contrib/restricted/boost/filesystem/src/posix_tools.hpp +++ b/contrib/restricted/boost/filesystem/src/posix_tools.hpp @@ -19,10 +19,25 @@ #include <unistd.h> #endif +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace boost { namespace filesystem { namespace detail { +//! Platform-specific parameters for directory iterator construction +struct directory_iterator_params +{ +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + //! File descriptor of the base directory relative to which to interpret relative paths + int basedir_fd; +#endif +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + //! File descriptor of the directory over which the iterator iterates + int iterator_fd; +#endif +}; + /*! * Closes a file descriptor and returns the result, similar to close(2). Unlike close(2), guarantees that the file descriptor is closed even if EINTR error happens. * @@ -61,4 +76,6 @@ inline int close_fd(int fd) } // namespace filesystem } // namespace boost +#include <boost/filesystem/detail/footer.hpp> + #endif // BOOST_FILESYSTEM_SRC_POSIX_TOOLS_HPP_ diff --git a/contrib/restricted/boost/filesystem/src/unique_path.cpp b/contrib/restricted/boost/filesystem/src/unique_path.cpp index 4815ca43698..f0bc6058cb2 100644 --- a/contrib/restricted/boost/filesystem/src/unique_path.cpp +++ b/contrib/restricted/boost/filesystem/src/unique_path.cpp @@ -95,6 +95,8 @@ #include "atomic_tools.hpp" #include "error_handling.hpp" +#include <boost/filesystem/detail/header.hpp> // must be the last #include + #if defined(BOOST_POSIX_API) // At least Mac OS X 10.6 and older doesn't support O_CLOEXEC #ifndef O_CLOEXEC @@ -325,3 +327,5 @@ path unique_path(path const& model, system::error_code* ec) } // namespace detail } // namespace filesystem } // namespace boost + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/utf8_codecvt_facet.cpp b/contrib/restricted/boost/filesystem/src/utf8_codecvt_facet.cpp index f7f9f7ef583..7e5939bb718 100644 --- a/contrib/restricted/boost/filesystem/src/utf8_codecvt_facet.cpp +++ b/contrib/restricted/boost/filesystem/src/utf8_codecvt_facet.cpp @@ -7,6 +7,8 @@ #include <boost/filesystem/config.hpp> +#include <boost/filesystem/detail/header.hpp> + #define BOOST_UTF8_BEGIN_NAMESPACE \ namespace boost { \ namespace filesystem { \ @@ -23,3 +25,5 @@ #undef BOOST_UTF8_BEGIN_NAMESPACE #undef BOOST_UTF8_END_NAMESPACE #undef BOOST_UTF8_DECL + +#include <boost/filesystem/detail/footer.hpp> diff --git a/contrib/restricted/boost/filesystem/src/windows_file_codecvt.cpp b/contrib/restricted/boost/filesystem/src/windows_file_codecvt.cpp index 56d1d1d7b3b..f86ba5111b9 100644 --- a/contrib/restricted/boost/filesystem/src/windows_file_codecvt.cpp +++ b/contrib/restricted/boost/filesystem/src/windows_file_codecvt.cpp @@ -19,6 +19,8 @@ #include <windows.h> +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace boost { namespace filesystem { namespace detail { @@ -65,4 +67,6 @@ std::codecvt_base::result windows_file_codecvt::do_out( } // namespace filesystem } // namespace boost +#include <boost/filesystem/detail/footer.hpp> + #endif // BOOST_WINDOWS_API diff --git a/contrib/restricted/boost/filesystem/src/windows_file_codecvt.hpp b/contrib/restricted/boost/filesystem/src/windows_file_codecvt.hpp index fbcf670b114..917dc2182fe 100644 --- a/contrib/restricted/boost/filesystem/src/windows_file_codecvt.hpp +++ b/contrib/restricted/boost/filesystem/src/windows_file_codecvt.hpp @@ -19,6 +19,8 @@ #include <cwchar> // std::mbstate_t #include <locale> +#include <boost/filesystem/detail/header.hpp> // must be the last #include + namespace boost { namespace filesystem { namespace detail { @@ -63,6 +65,8 @@ protected: } // namespace filesystem } // namespace boost +#include <boost/filesystem/detail/footer.hpp> + #endif // BOOST_WINDOWS_API #endif // BOOST_FILESYSTEM_WINDOWS_FILE_CODECVT_HPP diff --git a/contrib/restricted/boost/filesystem/src/windows_tools.hpp b/contrib/restricted/boost/filesystem/src/windows_tools.hpp index 469be041ec2..8a2de7f0c9f 100644 --- a/contrib/restricted/boost/filesystem/src/windows_tools.hpp +++ b/contrib/restricted/boost/filesystem/src/windows_tools.hpp @@ -21,6 +21,8 @@ #include <windows.h> +#include <boost/filesystem/detail/header.hpp> // must be the last #include + #ifndef IO_REPARSE_TAG_MOUNT_POINT #define IO_REPARSE_TAG_MOUNT_POINT (0xA0000003L) #endif @@ -83,6 +85,18 @@ inline bool is_reparse_point_tag_a_symlink(ULONG reparse_point_tag) #if !defined(UNDER_CE) +//! Platform-specific parameters for directory iterator construction +struct directory_iterator_params +{ + //! Handle of the directory to iterate over. If not \c INVALID_HANDLE_VALUE, the directory path is ignored. + HANDLE use_handle; + /*! + * If \c use_handle is not \c INVALID_HANDLE_VALUE, specifies whether the directory iterator should close the handle upon destruction. + * If \c false, the handle must remain valid for the lifetime of the iterator. + */ + bool close_handle; +}; + //! IO_STATUS_BLOCK definition from Windows SDK. struct io_status_block { @@ -102,6 +116,69 @@ struct unicode_string PWSTR Buffer; }; +//! OBJECT_ATTRIBUTES definition from Windows SDK +struct object_attributes +{ + ULONG Length; + HANDLE RootDirectory; + unicode_string* ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +}; + +#ifndef OBJ_CASE_INSENSITIVE +#define OBJ_CASE_INSENSITIVE 0x00000040 +#endif +#ifndef OBJ_DONT_REPARSE +#define OBJ_DONT_REPARSE 0x00001000 +#endif + +#ifndef FILE_SUPERSEDE +#define FILE_SUPERSEDE 0x00000000 +#endif +#ifndef FILE_OPEN +#define FILE_OPEN 0x00000001 +#endif +#ifndef FILE_CREATE +#define FILE_CREATE 0x00000002 +#endif +#ifndef FILE_OPEN_IF +#define FILE_OPEN_IF 0x00000003 +#endif +#ifndef FILE_OVERWRITE +#define FILE_OVERWRITE 0x00000004 +#endif +#ifndef FILE_OVERWRITE_IF +#define FILE_OVERWRITE_IF 0x00000005 +#endif + +#ifndef FILE_DIRECTORY_FILE +#define FILE_DIRECTORY_FILE 0x00000001 +#endif +#ifndef FILE_OPEN_FOR_BACKUP_INTENT +#define FILE_OPEN_FOR_BACKUP_INTENT 0x00004000 +#endif +#ifndef FILE_OPEN_REPARSE_POINT +#define FILE_OPEN_REPARSE_POINT 0x00200000 +#endif + +//! NtCreateFile signature. Available since Windows 2000 (probably). +typedef boost::winapi::NTSTATUS_ (NTAPI NtCreateFile_t)( + /*out*/ PHANDLE FileHandle, + /*in*/ ACCESS_MASK DesiredAccess, + /*in*/ object_attributes* ObjectAttributes, + /*out*/ io_status_block* IoStatusBlock, + /*in, optional*/ PLARGE_INTEGER AllocationSize, + /*in*/ ULONG FileAttributes, + /*in*/ ULONG ShareAccess, + /*in*/ ULONG CreateDisposition, + /*in*/ ULONG CreateOptions, + /*in, optional*/ PVOID EaBuffer, + /*in*/ ULONG EaLength); + +extern NtCreateFile_t* nt_create_file_api; + //! PIO_APC_ROUTINE definition from Windows SDK typedef VOID (NTAPI* pio_apc_routine) (PVOID ApcContext, io_status_block* IoStatusBlock, ULONG Reserved); @@ -113,17 +190,17 @@ enum file_information_class //! NtQueryDirectoryFile signature. Available since Windows NT 4.0 (probably). typedef boost::winapi::NTSTATUS_ (NTAPI NtQueryDirectoryFile_t)( - /*in*/ HANDLE FileHandle, - /*in, optional*/ HANDLE Event, - /*in, optional*/ pio_apc_routine ApcRoutine, - /*in, optional*/ PVOID ApcContext, - /*out*/ io_status_block* IoStatusBlock, - /*out*/ PVOID FileInformation, - /*in*/ ULONG Length, - /*in*/ file_information_class FileInformationClass, - /*in*/ BOOLEAN ReturnSingleEntry, - /*in, optional*/ unicode_string* FileName, - /*in*/ BOOLEAN RestartScan); + /*in*/ HANDLE FileHandle, + /*in, optional*/ HANDLE Event, + /*in, optional*/ pio_apc_routine ApcRoutine, + /*in, optional*/ PVOID ApcContext, + /*out*/ io_status_block* IoStatusBlock, + /*out*/ PVOID FileInformation, + /*in*/ ULONG Length, + /*in*/ file_information_class FileInformationClass, + /*in*/ BOOLEAN ReturnSingleEntry, + /*in, optional*/ unicode_string* FileName, + /*in*/ BOOLEAN RestartScan); extern NtQueryDirectoryFile_t* nt_query_directory_file_api; @@ -182,8 +259,15 @@ inline HANDLE create_file_handle(boost::filesystem::path const& p, DWORD dwDesir return ::CreateFileW(p.c_str(), dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile); } +#if !defined(UNDER_CE) +//! Creates a file handle for a file relative to a previously opened base directory. The file path must be relative and in preferred format. +boost::winapi::NTSTATUS_ nt_create_file_handle_at(HANDLE& out, HANDLE basedir_handle, boost::filesystem::path const& p, ULONG FileAttributes, ACCESS_MASK DesiredAccess, ULONG ShareMode, ULONG CreateDisposition, ULONG CreateOptions); +#endif // !defined(UNDER_CE) + } // namespace detail } // namespace filesystem } // namespace boost +#include <boost/filesystem/detail/footer.hpp> + #endif // BOOST_FILESYSTEM_SRC_WINDOWS_TOOLS_HPP_ |