From a0289c73875a9cf5731d4a1d5a9d5d625226c02f Mon Sep 17 00:00:00 2001 From: Martin Kuschnik Date: Fri, 12 Jan 2024 18:35:16 +0100 Subject: [PATCH 1/5] Adjusted _Open_dir to fix behavior of filesystem::is_empty and filesystem::directory_iterator with empty volumes --- stl/inc/filesystem | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index a2abcecd464..2d84bfdcd25 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -2505,6 +2505,8 @@ namespace filesystem { _EXPORT_STD enum class directory_options { none = 0, follow_directory_symlink = 1, skip_permission_denied = 2 }; _BITMASK_OPS(_EXPORT_STD, directory_options) + _EXPORT_STD _NODISCARD inline bool exists(const path& _Target); + struct _Dir_enum_impl { _NODISCARD static __std_win_error _Advance_and_reset_if_no_more_files(shared_ptr<_Dir_enum_impl>& _Ptr) { auto& _Impl = *_Ptr; @@ -2537,14 +2539,14 @@ namespace filesystem { } _NODISCARD static __std_win_error _Open_dir( - path& _Path, const directory_options _Options_arg, _Find_file_handle& _Dir, __std_fs_find_data& _Data) { + const path& _Path, const directory_options _Options_arg, _Find_file_handle& _Dir, __std_fs_find_data& _Data) { const size_t _Null_term_len = _CSTD wcslen(_Path.c_str()); if (_Null_term_len == 0 || _Null_term_len != _Path.native().size()) { return __std_win_error::_File_not_found; } - _Path /= L"*"sv; - auto _Error = _Dir._Open(_Path.c_str(), &_Data); + const path _Path_spec = _Path / L"*"sv; + auto _Error = _Dir._Open(_Path_spec.c_str(), &_Data); if (_Error == __std_win_error::_Success) { return _Skip_dots(_Dir._Handle, _Data); } @@ -2552,6 +2554,9 @@ namespace filesystem { if (_Error == __std_win_error::_Access_denied && _Bitmask_includes_any(_Options_arg, directory_options::skip_permission_denied)) { _Error = __std_win_error::_No_more_files; + } else if (_Error == __std_win_error::_File_not_found + && exists(_Path)) { + _Error = __std_win_error::_No_more_files; } return _Error; From a4b0a2f9a37c1fecfecfc3c584fae6672e4d0d41 Mon Sep 17 00:00:00 2001 From: Martin Kuschnik Date: Fri, 12 Jan 2024 19:28:12 +0100 Subject: [PATCH 2/5] adjusted format --- stl/inc/filesystem | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index 2d84bfdcd25..db39416543c 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -2538,15 +2538,15 @@ namespace filesystem { return __std_win_error::_Success; } - _NODISCARD static __std_win_error _Open_dir( - const path& _Path, const directory_options _Options_arg, _Find_file_handle& _Dir, __std_fs_find_data& _Data) { + _NODISCARD static __std_win_error _Open_dir(const path& _Path, const directory_options _Options_arg, + _Find_file_handle& _Dir, __std_fs_find_data& _Data) { const size_t _Null_term_len = _CSTD wcslen(_Path.c_str()); if (_Null_term_len == 0 || _Null_term_len != _Path.native().size()) { return __std_win_error::_File_not_found; } const path _Path_spec = _Path / L"*"sv; - auto _Error = _Dir._Open(_Path_spec.c_str(), &_Data); + auto _Error = _Dir._Open(_Path_spec.c_str(), &_Data); if (_Error == __std_win_error::_Success) { return _Skip_dots(_Dir._Handle, _Data); } @@ -2554,8 +2554,7 @@ namespace filesystem { if (_Error == __std_win_error::_Access_denied && _Bitmask_includes_any(_Options_arg, directory_options::skip_permission_denied)) { _Error = __std_win_error::_No_more_files; - } else if (_Error == __std_win_error::_File_not_found - && exists(_Path)) { + } else if (_Error == __std_win_error::_File_not_found && exists(_Path)) { _Error = __std_win_error::_No_more_files; } From eda53fad9ef729adf330341bdd250f647970d50e Mon Sep 17 00:00:00 2001 From: Martin Kuschnik Date: Fri, 12 Jan 2024 21:56:02 +0100 Subject: [PATCH 3/5] fixed unit tests --- stl/inc/filesystem | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index db39416543c..b1ab2d6a117 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -2538,15 +2538,15 @@ namespace filesystem { return __std_win_error::_Success; } - _NODISCARD static __std_win_error _Open_dir(const path& _Path, const directory_options _Options_arg, + _NODISCARD static __std_win_error _Open_dir(path& _Path, const directory_options _Options_arg, _Find_file_handle& _Dir, __std_fs_find_data& _Data) { const size_t _Null_term_len = _CSTD wcslen(_Path.c_str()); if (_Null_term_len == 0 || _Null_term_len != _Path.native().size()) { return __std_win_error::_File_not_found; } - const path _Path_spec = _Path / L"*"sv; - auto _Error = _Dir._Open(_Path_spec.c_str(), &_Data); + _Path /= L"*"sv; + auto _Error = _Dir._Open(_Path.c_str(), &_Data); if (_Error == __std_win_error::_Success) { return _Skip_dots(_Dir._Handle, _Data); } @@ -2554,7 +2554,7 @@ namespace filesystem { if (_Error == __std_win_error::_Access_denied && _Bitmask_includes_any(_Options_arg, directory_options::skip_permission_denied)) { _Error = __std_win_error::_No_more_files; - } else if (_Error == __std_win_error::_File_not_found && exists(_Path)) { + } else if (_Error == __std_win_error::_File_not_found && exists(std::wstring_view(_Path.c_str(), _Path.native().length() - 1))) { _Error = __std_win_error::_No_more_files; } From bb05e7512db60f42f47b3a099018627d37c26b39 Mon Sep 17 00:00:00 2001 From: Martin Kuschnik Date: Fri, 12 Jan 2024 22:15:53 +0100 Subject: [PATCH 4/5] adjusted format --- stl/inc/filesystem | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index b1ab2d6a117..9762c2ba8af 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -2538,15 +2538,15 @@ namespace filesystem { return __std_win_error::_Success; } - _NODISCARD static __std_win_error _Open_dir(path& _Path, const directory_options _Options_arg, - _Find_file_handle& _Dir, __std_fs_find_data& _Data) { + _NODISCARD static __std_win_error _Open_dir( + path& _Path, const directory_options _Options_arg, _Find_file_handle& _Dir, __std_fs_find_data& _Data) { const size_t _Null_term_len = _CSTD wcslen(_Path.c_str()); if (_Null_term_len == 0 || _Null_term_len != _Path.native().size()) { return __std_win_error::_File_not_found; } _Path /= L"*"sv; - auto _Error = _Dir._Open(_Path.c_str(), &_Data); + auto _Error = _Dir._Open(_Path.c_str(), &_Data); if (_Error == __std_win_error::_Success) { return _Skip_dots(_Dir._Handle, _Data); } @@ -2554,7 +2554,8 @@ namespace filesystem { if (_Error == __std_win_error::_Access_denied && _Bitmask_includes_any(_Options_arg, directory_options::skip_permission_denied)) { _Error = __std_win_error::_No_more_files; - } else if (_Error == __std_win_error::_File_not_found && exists(std::wstring_view(_Path.c_str(), _Path.native().length() - 1))) { + } else if (_Error == __std_win_error::_File_not_found + && exists(std::wstring_view(_Path.c_str(), _Path.native().length() - 1))) { _Error = __std_win_error::_No_more_files; } From 423e27a23355268b44677987f3748fde11f3bd24 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 16 Jan 2024 16:21:15 -0800 Subject: [PATCH 5/5] Code review feedback. --- stl/inc/filesystem | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index 9762c2ba8af..4b2ad4ce9b8 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -2505,7 +2505,7 @@ namespace filesystem { _EXPORT_STD enum class directory_options { none = 0, follow_directory_symlink = 1, skip_permission_denied = 2 }; _BITMASK_OPS(_EXPORT_STD, directory_options) - _EXPORT_STD _NODISCARD inline bool exists(const path& _Target); + _EXPORT_STD _NODISCARD inline bool exists(const path& _Target, error_code& _Ec) noexcept; struct _Dir_enum_impl { _NODISCARD static __std_win_error _Advance_and_reset_if_no_more_files(shared_ptr<_Dir_enum_impl>& _Ptr) { @@ -2545,6 +2545,7 @@ namespace filesystem { return __std_win_error::_File_not_found; } + const path _Original_path = _Path; _Path /= L"*"sv; auto _Error = _Dir._Open(_Path.c_str(), &_Data); if (_Error == __std_win_error::_Success) { @@ -2554,9 +2555,13 @@ namespace filesystem { if (_Error == __std_win_error::_Access_denied && _Bitmask_includes_any(_Options_arg, directory_options::skip_permission_denied)) { _Error = __std_win_error::_No_more_files; - } else if (_Error == __std_win_error::_File_not_found - && exists(std::wstring_view(_Path.c_str(), _Path.native().length() - 1))) { - _Error = __std_win_error::_No_more_files; + } else if (_Error == __std_win_error::_File_not_found) { + error_code _Ignored; // When exists() returns true, that implies that the error_code is successful. + // When exists() returns false, we don't want to interfere with _Open_dir()'s behavior, + // as it's going to return __std_win_error::_File_not_found. + if (_STD filesystem::exists(_Original_path, _Ignored)) { + _Error = __std_win_error::_No_more_files; // Handle empty volumes, see GH-4291 + } } return _Error;