diff --git a/config/has_fdopendir_nofollow.cpp b/config/has_fdopendir_nofollow.cpp index 009a73084..0c8c26867 100644 --- a/config/has_fdopendir_nofollow.cpp +++ b/config/has_fdopendir_nofollow.cpp @@ -16,5 +16,6 @@ int main() { int fd = open(".", O_DIRECTORY | O_RDONLY | O_NOFOLLOW); DIR* dir = fdopendir(fd); - return dir != 0; + int internal_fd = dirfd(dir); + return dir != 0 && internal_fd >= 0; } diff --git a/doc/release_history.html b/doc/release_history.html index 9bb2c140e..dfb859afe 100644 --- a/doc/release_history.html +++ b/doc/release_history.html @@ -50,6 +50,7 @@

1.85.0

  • weakly_canonical now produces an absolute path if the input path is relative and contains no elements that exist in the filesystem. (#300)
  • Added a new copy_options::ignore_attribute_errors option for copy_file and copy operations. The new option allows to ignore possible errors while copying file attributes. (#179)
  • On Linux, copy_file backends based on sendfile and copy_file_range system calls will attempt to preallocate storage for the target file. This may reduce filesystem fragmentation and provide early error indication if there is not enough free space. Not all filesystems support this feature; file copying proceeds if storage preallocation is not supported.
  • +
  • On POSIX systems that support fdopendir, openat and related APIs defined in POSIX.1-2008, recursive_directory_iterator now uses these APIs internally. This makes directory iteration more resilient to concurrent modifications of the filesystem.
  • Removed APIs that were previously declared deprecated. In particular, path and recursive_directory_iterator member functions, is_regular, copy_directory, symbolic_link_exists, complete, copy_option, symlink_option, as well as boost/filesystem/convenience.hpp and boost/filesystem/path_traits.hpp headers were removed. Possible replacements for the removed components are mentioned in Deprecated names and features section.
  • Support for path construction, assignment and appending from container types (e.g. std::vector<char>) is now disabled by default. Users can still enable this functionality by defining BOOST_FILESYSTEM_DEPRECATED. This functionality remains deprecated and will be completely removed in a future release.
  • diff --git a/include/boost/filesystem/directory.hpp b/include/boost/filesystem/directory.hpp index d3c0235d7..821b1a97b 100644 --- a/include/boost/filesystem/directory.hpp +++ b/include/boost/filesystem/directory.hpp @@ -55,6 +55,7 @@ enum class directory_options : unsigned int BOOST_BITMASK(directory_options) class directory_iterator; +class recursive_directory_iterator; namespace detail { @@ -63,6 +64,12 @@ struct directory_iterator_params; BOOST_FILESYSTEM_DECL void directory_iterator_construct(directory_iterator& it, path const& p, directory_options opts, directory_iterator_params* params, system::error_code* ec); BOOST_FILESYSTEM_DECL void directory_iterator_increment(directory_iterator& it, system::error_code* ec); +struct recur_dir_itr_imp; + +BOOST_FILESYSTEM_DECL void recursive_directory_iterator_construct(recursive_directory_iterator& it, path const& dir_path, directory_options opts, system::error_code* ec); +BOOST_FILESYSTEM_DECL void recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec); +BOOST_FILESYSTEM_DECL void recursive_directory_iterator_pop(recursive_directory_iterator& it, system::error_code* ec); + } // namespace detail //--------------------------------------------------------------------------------------// @@ -80,6 +87,8 @@ class directory_entry friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, directory_options 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); + friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec); + public: typedef boost::filesystem::path::value_type value_type; // enables class path ctor taking directory_entry @@ -660,6 +669,8 @@ class directory_iterator : friend BOOST_FILESYSTEM_DECL void detail::directory_iterator_construct(directory_iterator& it, path const& p, directory_options 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); + friend BOOST_FILESYSTEM_DECL void detail::recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec); + public: directory_iterator() noexcept {} // creates the "end" iterator @@ -808,8 +819,6 @@ namespace filesystem { // // //--------------------------------------------------------------------------------------// -class recursive_directory_iterator; - namespace detail { struct recur_dir_itr_imp : @@ -822,10 +831,6 @@ struct recur_dir_itr_imp : explicit recur_dir_itr_imp(directory_options opts) noexcept : m_options(opts) {} }; -BOOST_FILESYSTEM_DECL void recursive_directory_iterator_construct(recursive_directory_iterator& it, path const& dir_path, directory_options opts, system::error_code* ec); -BOOST_FILESYSTEM_DECL void recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec); -BOOST_FILESYSTEM_DECL void recursive_directory_iterator_pop(recursive_directory_iterator& it, system::error_code* ec); - } // namespace detail //--------------------------------------------------------------------------------------// diff --git a/src/directory.cpp b/src/directory.cpp index 8fae44baa..0383502d2 100644 --- a/src/directory.cpp +++ b/src/directory.cpp @@ -175,6 +175,23 @@ inline system::error_code dir_itr_close(dir_itr_imp& imp) noexcept return error_code(); } +#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + +// Obtains a file descriptor from the directory iterator +inline int dir_itr_fd(dir_itr_imp const& imp, system::error_code& ec) +{ + int fd = ::dirfd(static_cast< DIR* >(imp.handle)); + if (BOOST_UNLIKELY(fd < 0)) + { + int err = errno; + ec = system::error_code(err, system::system_category()); + } + + return fd; +} + +#endif // defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) + #if defined(BOOST_FILESYSTEM_USE_READDIR_R) // Obtains maximum length of a path, not including the terminating zero @@ -1020,6 +1037,21 @@ void directory_iterator_construct(directory_iterator& it, path const& p, directo try { +#if defined(BOOST_POSIX_API) && defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + path dir_path; + if (params) + { + dir_path = params->basedir; + path_algorithms::append_v4(dir_path, p); + } + else + { + dir_path = p; + } +#else + path const& dir_path = p; +#endif + boost::intrusive_ptr< detail::dir_itr_imp > imp; path filename; file_status file_stat, symlink_file_stat; @@ -1049,7 +1081,7 @@ void directory_iterator_construct(directory_iterator& it, path const& p, directo && (filename_str[1] == static_cast< path::string_type::value_type >('\0') || (filename_str[1] == path::dot && filename_str[2] == static_cast< path::string_type::value_type >('\0'))))) { - path full_path(p); + path full_path(dir_path); path_algorithms::append_v4(full_path, filename); imp->dir_entry.assign_with_status ( @@ -1251,99 +1283,152 @@ void recursive_directory_iterator_pop(recursive_directory_iterator& it, system:: } } -namespace { - -enum push_directory_result -{ - directory_not_pushed = 0u, - directory_pushed = 1u, - keep_depth = 1u << 1 -}; - -// Returns: true if push occurs, otherwise false. Always returns false on error. -inline push_directory_result recursive_directory_iterator_push_directory(detail::recur_dir_itr_imp* imp, system::error_code& ec) noexcept +BOOST_FILESYSTEM_DECL +void recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec) { - push_directory_result result = directory_not_pushed; - try + enum push_directory_result : unsigned int { - // Discover if the iterator is for a directory that needs to be recursed into, - // taking symlinks and options into account. + directory_not_pushed = 0u, + directory_pushed = 1u, + keep_depth = 1u << 1u + }; - if ((imp->m_options & directory_options::_detail_no_push) != directory_options::none) + struct local + { + //! Attempts to descend into a directory + static push_directory_result push_directory(detail::recur_dir_itr_imp* imp, system::error_code& ec) { - imp->m_options &= ~directory_options::_detail_no_push; - return result; - } + push_directory_result result = directory_not_pushed; + try + { + // Discover if the iterator is for a directory that needs to be recursed into, + // taking symlinks and options into account. - file_type symlink_ft = status_error; + if ((imp->m_options & directory_options::_detail_no_push) != directory_options::none) + { + imp->m_options &= ~directory_options::_detail_no_push; + return result; + } - // 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 & directory_options::follow_directory_symlink) == directory_options::none || - (imp->m_options & directory_options::skip_dangling_symlinks) != directory_options::none) - { - symlink_ft = imp->m_stack.back()->symlink_file_type(ec); - if (ec) - return result; - } + file_type symlink_ft = status_error; - // Logic for following predicate was contributed by Daniel Aarno to handle cyclic - // symlinks correctly and efficiently, fixing ticket #5652. - // if (((m_options & directory_options::follow_directory_symlink) == directory_options::follow_directory_symlink - // || !is_symlink(m_stack.back()->symlink_status())) - // && is_directory(m_stack.back()->status())) ... - // The predicate code has since been rewritten to pass error_code arguments, - // per ticket #5653. +#if defined(BOOST_POSIX_API) && defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + int parentdir_fd = -1; + path dir_it_filename; +#endif - if ((imp->m_options & directory_options::follow_directory_symlink) != directory_options::none || symlink_ft != symlink_file) - { - file_type ft = imp->m_stack.back()->file_type(ec); - if (BOOST_UNLIKELY(!!ec)) - { - if (ec == make_error_condition(system::errc::no_such_file_or_directory) && symlink_ft == symlink_file && - (imp->m_options & (directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks)) == (directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks)) + // 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 & directory_options::follow_directory_symlink) == directory_options::none || + (imp->m_options & directory_options::skip_dangling_symlinks) != directory_options::none) { - // Skip dangling symlink and continue iteration on the current depth level - ec = error_code(); - } +#if defined(BOOST_POSIX_API) && defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + directory_iterator const& dir_it = imp->m_stack.back(); + if (filesystem::type_present(dir_it->m_symlink_status)) + { + symlink_ft = dir_it->m_symlink_status.type(); + } + else + { + parentdir_fd = dir_itr_fd(*dir_it.m_imp, ec); + if (ec) + return result; + + dir_it_filename = detail::path_algorithms::filename_v4(dir_it->path()); + + symlink_ft = detail::symlink_status_impl(dir_it_filename, &ec, parentdir_fd).type(); + if (ec) + return result; + } - return result; - } +#else + symlink_ft = imp->m_stack.back()->symlink_file_type(ec); + if (ec) + return result; +#endif + } - if (ft != directory_file) - return result; + // Logic for following predicate was contributed by Daniel Aarno to handle cyclic + // symlinks correctly and efficiently, fixing ticket #5652. + // if (((m_options & directory_options::follow_directory_symlink) == directory_options::follow_directory_symlink + // || !is_symlink(m_stack.back()->symlink_status())) + // && is_directory(m_stack.back()->status())) ... + // The predicate code has since been rewritten to pass error_code arguments, + // per ticket #5653. - if (BOOST_UNLIKELY((imp->m_stack.size() - 1u) >= static_cast< std::size_t >((std::numeric_limits< int >::max)()))) - { - // We cannot let depth to overflow - ec = make_error_code(system::errc::value_too_large); - // When depth overflow happens, avoid popping the current directory iterator - // and attempt to continue iteration on the current depth. - result = keep_depth; - return result; + if ((imp->m_options & directory_options::follow_directory_symlink) != directory_options::none || symlink_ft != symlink_file) + { + directory_iterator const& dir_it = imp->m_stack.back(); + +#if defined(BOOST_POSIX_API) && defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + if (parentdir_fd < 0) + { + parentdir_fd = dir_itr_fd(*dir_it.m_imp, ec); + if (ec) + return result; + + dir_it_filename = detail::path_algorithms::filename_v4(dir_it->path()); + } + + file_type ft = status_error; + if (filesystem::type_present(dir_it->m_status)) + ft = dir_it->m_status.type(); + else + ft = detail::status_impl(dir_it_filename, &ec, parentdir_fd).type(); +#else + file_type ft = dir_it->file_type(ec); +#endif + if (BOOST_UNLIKELY(!!ec)) + { + if (ec == make_error_condition(system::errc::no_such_file_or_directory) && symlink_ft == symlink_file && + (imp->m_options & (directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks)) == (directory_options::follow_directory_symlink | directory_options::skip_dangling_symlinks)) + { + // Skip dangling symlink and continue iteration on the current depth level + ec = system::error_code(); + } + + return result; + } + + if (ft != directory_file) + return result; + + if (BOOST_UNLIKELY((imp->m_stack.size() - 1u) >= static_cast< std::size_t >((std::numeric_limits< int >::max)()))) + { + // We cannot let depth to overflow + ec = make_error_code(system::errc::value_too_large); + // When depth overflow happens, avoid popping the current directory iterator + // and attempt to continue iteration on the current depth. + result = keep_depth; + return result; + } + +#if defined(BOOST_POSIX_API) && defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + detail::directory_iterator_params params; + params.basedir = dir_it->path().parent_path(); + params.basedir_fd = parentdir_fd; + params.iterator_fd = -1; + directory_iterator next; + detail::directory_iterator_construct(next, dir_it_filename, imp->m_options, ¶ms, &ec); +#else + directory_iterator next(dir_it->path(), imp->m_options, ec); +#endif + if (!ec && next != directory_iterator()) + { + imp->m_stack.push_back(std::move(next)); // may throw + return directory_pushed; + } + } } - - directory_iterator next(imp->m_stack.back()->path(), imp->m_options, ec); - if (!ec && next != directory_iterator()) + catch (std::bad_alloc&) { - imp->m_stack.push_back(std::move(next)); // may throw - return directory_pushed; + ec = make_error_code(system::errc::not_enough_memory); } - } - } - catch (std::bad_alloc&) - { - ec = make_error_code(system::errc::not_enough_memory); - } - - return result; -} -} // namespace + return result; + } + }; -BOOST_FILESYSTEM_DECL -void recursive_directory_iterator_increment(recursive_directory_iterator& it, system::error_code* ec) -{ BOOST_ASSERT_MSG(!it.is_end(), "increment() on end recursive_directory_iterator"); detail::recur_dir_itr_imp* const imp = it.m_imp.get(); @@ -1353,7 +1438,7 @@ void recursive_directory_iterator_increment(recursive_directory_iterator& it, sy system::error_code local_ec; // if various conditions are met, push a directory_iterator into the iterator stack - push_directory_result push_result = recursive_directory_iterator_push_directory(imp, local_ec); + push_directory_result push_result = local::push_directory(imp, local_ec); if (push_result == directory_pushed) return; @@ -1373,7 +1458,7 @@ void recursive_directory_iterator_increment(recursive_directory_iterator& it, sy system::error_code increment_ec; directory_iterator& dir_it = imp->m_stack.back(); detail::directory_iterator_increment(dir_it, &increment_ec); - if (!increment_ec && dir_it != directory_iterator()) + if (!increment_ec && !dir_it.is_end()) goto on_error_return; } @@ -1407,7 +1492,7 @@ void recursive_directory_iterator_increment(recursive_directory_iterator& it, sy if (BOOST_UNLIKELY(!!local_ec)) goto on_error; - if (dir_it != directory_iterator()) + if (!dir_it.is_end()) break; imp->m_stack.pop_back(); diff --git a/src/operations.cpp b/src/operations.cpp index 728e10243..f1f1e9540 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -477,13 +477,15 @@ inline std::size_t get_blksize(struct ::stat const& st) noexcept #endif // defined(BOOST_FILESYSTEM_USE_STATX) +} // namespace + //! status() implementation file_status status_impl ( path const& p, - error_code* ec + system::error_code* ec #if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) - , int basedir_fd = AT_FDCWD + , int basedir_fd #endif ) { @@ -501,14 +503,14 @@ file_status status_impl 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 (ec) // always report errno, even though some + ec->assign(err, system::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()))); + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::status", p, system::error_code(err, system::system_category()))); return fs::file_status(fs::status_error); } @@ -542,9 +544,9 @@ file_status status_impl file_status symlink_status_impl ( path const& p, - error_code* ec + system::error_code* ec #if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) - , int basedir_fd = AT_FDCWD + , int basedir_fd #endif ) { @@ -562,14 +564,14 @@ file_status symlink_status_impl 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 (ec) // always report errno, even though some + ec->assign(err, system::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()))); + BOOST_FILESYSTEM_THROW(filesystem_error("boost::filesystem::symlink_status", p, system::error_code(err, system::system_category()))); return fs::file_status(fs::status_error); } @@ -601,6 +603,8 @@ file_status symlink_status_impl return fs::file_status(fs::type_unknown); } +namespace { + //! Flushes buffered data and attributes written to the file to permanent storage inline int full_sync(int fd) { @@ -1099,14 +1103,25 @@ 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 + , int parentdir_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.basedir_fd = parentdir_fd; params.iterator_fd = -1; + + fs::path remove_path; + if (parentdir_fd != AT_FDCWD) + { + params.basedir = p.parent_path(); + remove_path = path_algorithms::filename_v4(p); + } + else + { + remove_path = p; + } #endif error_code dit_create_ec; @@ -1115,14 +1130,11 @@ uintmax_t remove_all_impl fs::file_type type; { error_code local_ec; - 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 + type = fs::detail::symlink_status_impl(remove_path, &local_ec, parentdir_fd).type(); +#else + type = fs::detail::symlink_status_impl(p, &local_ec).type(); #endif - ).type(); if (type == fs::file_not_found) return 0u; @@ -1141,18 +1153,11 @@ uintmax_t remove_all_impl if (type == fs::directory_file) // but not a directory symlink { fs::directory_iterator itr; - fs::detail::directory_iterator_construct - ( - itr, - p, - directory_options::_detail_no_follow, #if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) - ¶ms, + fs::detail::directory_iterator_construct(itr, remove_path, directory_options::_detail_no_follow, ¶ms, &dit_create_ec); #else - nullptr, + fs::detail::directory_iterator_construct(itr, p, directory_options::_detail_no_follow, nullptr, &dit_create_ec); #endif - &dit_create_ec - ); if (BOOST_UNLIKELY(!!dit_create_ec)) { @@ -1180,11 +1185,7 @@ uintmax_t remove_all_impl { count += fs::detail::remove_all_impl ( -#if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) - path_algorithms::filename_v4(itr->path()), -#else itr->path(), -#endif ec #if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) , params.iterator_fd @@ -1199,15 +1200,11 @@ uintmax_t remove_all_impl } } - count += fs::detail::remove_impl - ( - p, - type, - ec #if defined(BOOST_FILESYSTEM_HAS_FDOPENDIR_NOFOLLOW) && defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) - , basedir_fd + count += fs::detail::remove_impl(remove_path, type, ec, parentdir_fd); +#else + count += fs::detail::remove_impl(p, type, ec); #endif - ); if (ec && *ec) return static_cast< uintmax_t >(-1); diff --git a/src/posix_tools.hpp b/src/posix_tools.hpp index 52cd87b0a..d62001674 100644 --- a/src/posix_tools.hpp +++ b/src/posix_tools.hpp @@ -18,7 +18,11 @@ #ifdef BOOST_HAS_UNISTD_H #include #endif +#include +#include +#include +#include #include // must be the last #include namespace boost { @@ -29,6 +33,8 @@ namespace detail { struct directory_iterator_params { #if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) + //! Base directory path, relative to which to interpret relative paths. Must be empty if basedir_fd is AT_FDCWD. + path basedir; //! File descriptor of the base directory relative to which to interpret relative paths int basedir_fd; #endif @@ -72,6 +78,26 @@ inline int close_fd(int fd) #endif } +//! status() implementation +file_status status_impl +( + path const& p, + system::error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) + , int basedir_fd = AT_FDCWD +#endif +); + +//! symlink_status() implementation +file_status symlink_status_impl +( + path const& p, + system::error_code* ec +#if defined(BOOST_FILESYSTEM_HAS_POSIX_AT_APIS) || defined(BOOST_FILESYSTEM_USE_STATX) + , int basedir_fd = AT_FDCWD +#endif +); + } // namespace detail } // namespace filesystem } // namespace boost diff --git a/src/windows_tools.hpp b/src/windows_tools.hpp index c954be7cf..4fa8e228a 100644 --- a/src/windows_tools.hpp +++ b/src/windows_tools.hpp @@ -90,7 +90,7 @@ inline bool is_reparse_point_tag_a_symlink(ULONG reparse_point_tag) //! 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 of the directory to iterate over. If not \c INVALID_HANDLE_VALUE, the directory path is only used to generate paths returned by the iterator. HANDLE use_handle; /*! * If \c use_handle is not \c INVALID_HANDLE_VALUE, specifies whether the directory iterator should close the handle upon destruction.