Skip to content

Commit

Permalink
Added more Windows error codes as indication for unsupported dir info…
Browse files Browse the repository at this point in the history
… class.

Also extracted the check for the error codes to a separate function for
easier maintenance.

Closes #286.
  • Loading branch information
Lastique committed May 13, 2023
1 parent 396eef1 commit 615881f
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 20 deletions.
2 changes: 1 addition & 1 deletion doc/release_history.html
Expand Up @@ -42,7 +42,7 @@
<h2>1.83.0</h2>
<ul>
<li>Generic <code>path</code> comparison operators are now more restricted to avoid potential ambiguities when user's code contains a <code>using namespace boost::filesystem;</code> directive. (<a href="https://github.com/boostorg/filesystem/issues/285">#285</a>)</li>
<li>On Windows, added another workaround for SMBv1 shares. Previously, creating a directory iterator over a directory in an SMBv1 share could fail with error code <code>ERROR_INVALID_LEVEL</code>. (<a href="https://github.com/boostorg/filesystem/issues/284">#284</a>)</li>
<li>On Windows, added more workarounds for errors returned by various filesystems when creating a directory iterator. (<a href="https://github.com/boostorg/filesystem/issues/284">#284</a>, <a href="https://github.com/boostorg/filesystem/issues/286">#286</a>)</li>
</ul>

<h2>1.82.0</h2>
Expand Down
44 changes: 25 additions & 19 deletions src/directory.cpp
Expand Up @@ -734,6 +734,28 @@ error_code dir_itr_increment(dir_itr_imp& imp, fs::path& filename, fs::file_stat
return error_code();
}

//! Returns \c true if the error code indicates that the OS or the filesystem does not support a particular directory info class
inline bool is_dir_info_class_not_supported(DWORD error)
{
// Some mounted filesystems may not support FILE_ID_128 identifiers, which will cause
// GetFileInformationByHandleEx(FileIdExtdDirectoryRestartInfo) return ERROR_INVALID_PARAMETER,
// even though in general the operation is supported by the kernel. SMBv1 returns a special error
// code ERROR_INVALID_LEVEL in this case.
// Some other filesystems also don't implement other info classes and return ERROR_INVALID_PARAMETER
// (e.g. see https://github.com/boostorg/filesystem/issues/266), ERROR_GEN_FAILURE, ERROR_INVALID_FUNCTION
// or ERROR_INTERNAL_ERROR (https://github.com/boostorg/filesystem/issues/286). Treat these error codes
// as "non-permanent", even though ERROR_INVALID_PARAMETER is also returned if GetFileInformationByHandleEx
// in general does not support a certain info class. Worst case, we will make extra syscalls on directory
// iterator construction.
// Also note that Wine returns ERROR_CALL_NOT_IMPLEMENTED for unimplemented info classes, and
// up until 7.21 it didn't implement FileIdExtdDirectoryRestartInfo and FileFullDirectoryRestartInfo.
// (https://bugs.winehq.org/show_bug.cgi?id=53590)
return error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER ||
error == ERROR_INVALID_LEVEL || error == ERROR_CALL_NOT_IMPLEMENTED ||
error == ERROR_GEN_FAILURE || error == ERROR_INVALID_FUNCTION ||
error == ERROR_INTERNAL_ERROR;
}

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());
Expand Down Expand Up @@ -816,23 +838,9 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
{
DWORD error = ::GetLastError();

if (error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER ||
error == ERROR_INVALID_LEVEL || error == ERROR_CALL_NOT_IMPLEMENTED)
if (is_dir_info_class_not_supported(error))
{
// Fall back to file_full_dir_info_format.
// Note that some mounted filesystems may not support FILE_ID_128 identifiers, which will cause
// GetFileInformationByHandleEx(FileIdExtdDirectoryRestartInfo) return ERROR_INVALID_PARAMETER,
// even though in general the operation is supported by the kernel. SMBv1 returns a special error
// code ERROR_INVALID_LEVEL in this case. So don't downgrade to FileFullDirectoryRestartInfo
// permanently for such error codes - only for this particular iterator.
// Some other filesystems also don't implement other info classes and also return ERROR_INVALID_PARAMETER
// (e.g. see https://github.com/boostorg/filesystem/issues/266), so generally treat this error code
// as "non-permanent", even though it is also returned if GetFileInformationByHandleEx in general
// does not support a certain info class. Worst case, we will make extra syscalls on directory iterator
// construction.
// Also note that Wine returns ERROR_CALL_NOT_IMPLEMENTED for unimplemented info classes, and
// up until 7.21 it didn't implement FileIdExtdDirectoryRestartInfo and FileFullDirectoryRestartInfo.
// (https://bugs.winehq.org/show_bug.cgi?id=53590)
if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED)
filesystem::detail::atomic_store_relaxed(g_extra_data_format, file_full_dir_info_format);
goto fallback_to_file_full_dir_info_format;
Expand Down Expand Up @@ -860,8 +868,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
{
DWORD error = ::GetLastError();

if (error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER ||
error == ERROR_INVALID_LEVEL || error == ERROR_CALL_NOT_IMPLEMENTED)
if (is_dir_info_class_not_supported(error))
{
// Fall back to file_id_both_dir_info
if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED)
Expand Down Expand Up @@ -891,8 +898,7 @@ error_code dir_itr_create(boost::intrusive_ptr< detail::dir_itr_imp >& imp, fs::
{
DWORD error = ::GetLastError();

if (error == ERROR_NOT_SUPPORTED || error == ERROR_INVALID_PARAMETER ||
error == ERROR_INVALID_LEVEL || error == ERROR_CALL_NOT_IMPLEMENTED)
if (is_dir_info_class_not_supported(error))
{
// Fall back to file_directory_information
if (error == ERROR_NOT_SUPPORTED || error == ERROR_CALL_NOT_IMPLEMENTED)
Expand Down

0 comments on commit 615881f

Please sign in to comment.