Added a workaround for GetFileInformationByHandleEx error in dir iterator.

Reproduce the workaround for GetFileInformationByHandleEx returning
ERROR_INVALID_PARAMETER when querying FILE_ATTRIBUTE_TAG_INFO on FAT/exFAT
filesystems in directory iterator construction.

Fixes https://github.com/boostorg/filesystem/issues/237.
This commit is contained in:
Andrey Semashev
2022-05-15 17:20:24 +03:00
parent 15249ba87b
commit 1f2e37cae5
3 changed files with 19 additions and 3 deletions

View File

@@ -42,7 +42,7 @@
<h2>1.80.0</h2>
<ul>
<li>On Windows, added a fallback implementation for querying file attributes in case if the file cannot be opened with <code>ERROR_ACCESS_DENIED</code> error. This may allow <code>status</code> and <code>symlink_status</code> to succeed for system files and directories that are not reparse points or symlinks. (<a href="https://github.com/boostorg/filesystem/issues/234">#234</a>)</li>
<li>On Windows, added a workaround for <code>status</code> and <code>symlink_status</code> reporting that files do not exist on FAT/exFAT filesystems. (<a href="https://github.com/boostorg/filesystem/issues/236">#236</a>)</li>
<li>On Windows, added a workaround for FAT/exFAT filesystems that produce <code>ERROR_INVALID_PARAMETER</code> when querying file attributes. This affected <code>status</code> and <code>symlink_status</code>, which reported that files do not exist, and directory iterators, which failed to construct, as well as other dependent operations. (<a href="https://github.com/boostorg/filesystem/issues/236">#236</a>, <a href="https://github.com/boostorg/filesystem/issues/237">#237</a>)</li>
</ul>
<h2>1.79.0</h2>

View File

@@ -774,7 +774,14 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
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;
{
// 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;
return error_code(error, system_category());
}
if (BOOST_UNLIKELY((info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0u))
return make_error_code(system::errc::not_a_directory);
@@ -787,6 +794,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
}
else
{
use_get_file_information_by_handle:
BY_HANDLE_FILE_INFORMATION info;
BOOL res = ::GetFileInformationByHandle(h.handle, &info);
if (BOOST_UNLIKELY(!res))

View File

@@ -3770,12 +3770,20 @@ file_status status(path const& p, error_code* ec)
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;
{
// See the comment in symlink_status
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;
}
else
{
use_get_file_information_by_handle:
BY_HANDLE_FILE_INFORMATION info;
BOOL res = ::GetFileInformationByHandle(h.handle, &info);
if (BOOST_UNLIKELY(!res))