<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr">On Fri, Jul 10, 2026 at 1:34 PM Jonathan Wakely <<a href="mailto:jwakely@redhat.com">jwakely@redhat.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Do not set errno in the helper functions __open_for_stat and<br>
__check_handle_type, because those are used from std::filesystem APIs<br>
which should set a std::error_code instead of changing errno. Move<br>
setting errno into the Windows-specific __stat_windows function and<br>
change the helper functions to use a std::error_code parameter instead.<br></blockquote><div>This simplifies a lot. Thanks. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Also simplify the Windows implementation of fs::read_symlink by moving<br>
the error handling for non-symlinks into windows_read_symlink_handle.<br>
<br>
libstdc++-v3/ChangeLog:<br>
<br>
* src/c++17/fs_ops.cc (windows_read_symlink_handle): Use<br>
__detail::__is_handle_symlink and report an error for<br>
non-symlinks.<br>
(filesystem::read_symlink): Remove error handling for<br>
non-symlinks.<br>
* src/filesystem/ops-common.h (__detail::__open_for_stat): Use<br>
std::error_code parameter to report errors instead of setting<br>
errno.<br>
(__detail::__check_handle_type): Likewise.<br>
(__detail::__is_handle_symlink): Likewise.<br>
(__detail::__stat_windows): Pass std::error_code to helper<br>
functions and set errno to report errors.<br>
---<br>
<br>
Tested x86_64-linux and x86_64-w64-mingw32 cross with Wine testing.<br>
<br>
libstdc++-v3/src/c++17/fs_ops.cc | 26 ++++++---------<br>
libstdc++-v3/src/filesystem/ops-common.h | 41 +++++++++++++-----------<br>
2 files changed, 32 insertions(+), 35 deletions(-)<br>
<br>
diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc<br>
index 81bffc7b1513..31f5abfa6fc7 100644<br>
--- a/libstdc++-v3/src/c++17/fs_ops.cc<br>
+++ b/libstdc++-v3/src/c++17/fs_ops.cc<br>
@@ -1257,6 +1257,13 @@ namespace<br>
std::error_code& ec,<br>
fs::path& result)<br>
{<br>
+ if (!fs::__detail::__is_handle_symlink(link_handle.handle, ec))<br>
+ {<br>
+ if (!ec)<br>
+ ec.assign(EINVAL, std::generic_category()); // not a symlink<br>
+ return;<br>
+ }<br>
+<br>
PREPARSE_DATA_BUFFER reparse_buffer = nullptr;<br>
std::unique_ptr<char[]> big_buffer;<br>
<br>
@@ -1374,23 +1381,8 @@ fs::path fs::read_symlink(const path& p, error_code& ec)<br>
#elif defined(_GLIBCXX_FILESYSTEM_IS_WINDOWS) \<br>
&& defined(SYMBOLIC_LINK_FLAG_DIRECTORY)<br>
auto_win_file_handle link_handle(p.c_str(), ec, false);<br>
- if (!link_handle)<br>
- return result;<br>
-<br>
- int is_symlink = __detail::__is_handle_symlink(link_handle.handle);<br>
- if (is_symlink == -1)<br>
- {<br>
- ec = __last_system_error();<br>
- return result;<br>
- }<br>
-<br>
- if (!is_symlink)<br>
- {<br>
- ec.assign(EINVAL, std::generic_category());<br>
- return result;<br>
- }<br>
-<br>
- windows_read_symlink_handle(link_handle, ec, result);<br>
+ if (link_handle)<br>
+ windows_read_symlink_handle(link_handle, ec, result);<br>
#else<br>
ec = std::make_error_code(std::errc::function_not_supported);<br>
#endif<br>
diff --git a/libstdc++-v3/src/filesystem/ops-common.h b/libstdc++-v3/src/filesystem/ops-common.h<br>
index cdb4a1ca0ca8..df610b74e402 100644<br>
--- a/libstdc++-v3/src/filesystem/ops-common.h<br>
+++ b/libstdc++-v3/src/filesystem/ops-common.h<br>
@@ -113,7 +113,9 @@ namespace __detail<br>
<br>
using stat_type = struct ::__stat64;<br>
<br>
- inline HANDLE __open_for_stat(const wchar_t* path, bool following_symlinks)<br>
+ inline HANDLE<br>
+ __open_for_stat(const wchar_t* path, bool following_symlinks,<br>
+ std::error_code& ec)<br>
{<br>
constexpr auto share_flags<br>
= FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE;<br>
@@ -124,10 +126,7 @@ namespace __detail<br>
= CreateFileW(path, 0, share_flags, 0, OPEN_EXISTING, file_flags, 0);<br>
<br>
if (handle == INVALID_HANDLE_VALUE)<br>
- {<br>
- // CreateFileW does not set errno.<br>
- errno = std::__last_system_error().default_error_condition().value();<br>
- }<br>
+ ec = std::__last_system_error();<br>
<br>
return handle;<br>
}<br>
@@ -138,14 +137,15 @@ namespace __detail<br>
// to a symlink or directory, then fix the result of _fstat64 accordingly.<br>
enum class FileType { Err = -1, Dir = S_IFDIR, Link = S_IFLNK, Other = 0 };<br>
<br>
- inline FileType __check_handle_type(HANDLE handle, bool following_symlinks)<br>
+ inline FileType<br>
+ __check_handle_type(HANDLE handle, bool following_symlinks, error_code& ec)<br>
{<br>
#ifdef SYMBOLIC_LINK_FLAG_DIRECTORY<br>
FILE_ATTRIBUTE_TAG_INFO type_info;<br>
if (!GetFileInformationByHandleEx(handle, FileAttributeTagInfo,<br>
&type_info, sizeof(type_info)))<br>
{<br>
- errno = std::__last_system_error().default_error_condition().value();<br>
+ ec = std::__last_system_error();<br>
return FileType::Err;<br>
}<br>
// A directory symlink has both DIRECTORY and REPARSE_POINT set,<br>
@@ -160,32 +160,37 @@ namespace __detail<br>
return FileType::Other;<br>
}<br>
<br>
- // -1 error, 0 not a symlink, 1 a symlink<br>
- inline int __is_handle_symlink(HANDLE handle)<br>
+ // If no error occurs and `handle` represents a symlink, returns true.<br>
+ // Otherwise, returns false. Sets `ec` if an error occurred.<br>
+ inline bool __is_handle_symlink(HANDLE handle, std::error_code& ec)<br>
{<br>
- FileType type = __check_handle_type(handle, false);<br>
- if (type == FileType::Err)<br>
- return -1;<br>
- return type == FileType::Link;<br>
+ return __check_handle_type(handle, false, ec) == FileType::Link;<br>
}<br>
<br>
- inline int __stat_windows(const wchar_t* path, stat_type* buffer,<br>
- bool following_symlinks)<br>
+ inline int<br>
+ __stat_windows(const wchar_t* path, stat_type* buffer,<br>
+ bool following_symlinks)<br>
{<br>
- HANDLE handle = __open_for_stat(path, following_symlinks);<br>
+ std::error_code ec;<br>
+ HANDLE handle = __open_for_stat(path, following_symlinks, ec);<br>
if (handle == INVALID_HANDLE_VALUE)<br>
- return -1;<br>
+ {<br>
+ errno = ec.default_error_condition().value();<br>
+ return -1;<br>
+ }<br>
// Manually check for directory or symlink, because _fstat does not.<br>
- FileType type = __check_handle_type(handle, following_symlinks);<br>
+ FileType type = __check_handle_type(handle, following_symlinks, ec);<br>
if (type == FileType::Err)<br>
{<br>
CloseHandle(handle);<br>
+ errno = ec.default_error_condition().value();<br>
return -1;<br>
}<br>
int fd = ::_open_osfhandle((intptr_t)handle, _O_RDONLY);<br>
if (fd == -1)<br>
{<br>
CloseHandle(handle);<br>
+ errno = ec.default_error_condition().value();<br>
return -1;<br>
}<br>
int stat_result = ::_fstat64(fd, buffer);<br>
-- <br>
2.55.0<br>
<br>
</blockquote></div></div>