-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added a missing case for __std_is_file_not_found()
.
#5381
base: main
Are you sure you want to change the base?
Added a missing case for __std_is_file_not_found()
.
#5381
Conversation
I noticed some rather peculiar behavior regarding the Win32 API `GetFileAttributesExW()`. Specifically, I found that upon calling this function with an invalid path (in my case, a remote URI) in two separate applications, both would fail as expected. What is interesting is that - for some inexplicable reason - the error code returned by `GetLastError()` differed between these two applications. Specifically, it was always either one of the following: * `ERROR_INVALID_NAME`: The file name, directory name, or volume label syntax is incorrect. * `ERROR_BAD_PATHNAME`: The specified path is invalid. When this occurred, I was making use of the throwing `std::filesystem::exists()` overload. So, you could imagine my surprise when this function threw an exception on one of the applications and returned `false` as expected on the other. I have not spent any real time investigating the cause for this difference in behavior myself. In any case, though, it is clear that the `__std_is_file_not_found()` function should have returned `true` when given an `__std_win_error` value corresponding to either of the two error codes. This commit thus modifies the `__std_is_file_not_found()` function to take into consideration an additional Win32 error code: `ERROR_BAD_PATHNAME`. Prior to this commit, this value did not have a unique value assigned to it in the `__std_win_error` `enum class`. Thus, a new value by the name of `__std_win_error::_Bad_pathname` was also added in this commit.
…::URI::read()`. There appears to be a bug in the MSVC STL implementation of `std::filesystem::exists()` in which the mechanism used to determine whether or not a given file is found (that is, the `__std_is_file_not_found()` function, although that is not a part of the C++ Standard) does not consider every possible relevant Win32 error code which could be returned by `GetFileAttributesExW()`. (This issue has been documented in a pull request at microsoft/STL#5381.) This commit implements a work around for that issue by modifying the `rocky::URI::read()` function to use the non-throwing variant of `std::filesystem::exists()` in order to determine whether the URI returned from `rocky::URI::full()` represents an existing file in the local filesystem. This variant of the function will return `false` if the specified `std::filesystem::path` does not represent an existing object in the filesystem, just like the throwing variant. In addition, it will also return `false` if an error prevented the function from determining whether or not the file exists; this effectively handles the fact that the MSVC STL does not currently respect the `ERROR_BAD_PATHNAME` Win32 error code.
Sounds a lot like #4844 and #5077.
We probably don't need to understand the root cause in order to merge this change, but are there any interesting differences between the systems? For example, are they running different OSes, like the Win11 24H2 changes above? |
Both applications were running on the same system, which is running Windows 11 24H2, as you suspect. I don't really know what could cause the difference in behavior, honestly. I am a bit busy at work right now, so I wouldn't be able to investigate it until a little later. |
This comment was marked as resolved.
This comment was marked as resolved.
Aha, I believe you've fixed DevCom-10825862 VSO-2345522 " With VS 2022 17.14 Preview 2, I repro:
#include <filesystem>
#include <print>
using namespace std;
int main() {
try {
println("_MSVC_STL_UPDATE: {}", _MSVC_STL_UPDATE);
const bool b = filesystem::exists(R"(https://example.com/bogus/path)");
println("{}", b);
} catch (const filesystem::filesystem_error& e) {
println("{}", e.what());
}
}
I observe that your fix is effective:
Awesome! 😻 |
I noticed some rather peculiar behavior regarding the Win32 API
GetFileAttributesExW()
. Specifically, I found that upon calling this function with an invalid path (in my case, a remote URI) in two separate applications, both would fail as expected. What is interesting is that - for some inexplicable reason - the error code returned byGetLastError()
differed between these two applications. Specifically, it was always either one of the following:ERROR_INVALID_NAME
: The file name, directory name, or volume label syntax is incorrect.ERROR_BAD_PATHNAME
: The specified path is invalid.When this occurred, I was making use of the throwing
std::filesystem::exists()
overload. So, you could imagine my surprise when this function threw an exception on one of the applications and returnedfalse
as expected on the other. I have not spent any real time investigating the cause for this difference in behavior myself. In any case, though, it is clear that the__std_is_file_not_found()
function should have returnedtrue
when given an__std_win_error
value corresponding to either of the two error codes.This commit thus modifies the
__std_is_file_not_found()
function to take into consideration an additional Win32 error code:ERROR_BAD_PATHNAME
. Prior to this commit, this value did not have a unique value assigned to it in the__std_win_error
enum class
. Thus, a new value by the name of__std_win_error::_Bad_pathname
was also added in this commit.