For a directory symlink, I think the type of the file depends on whether you call stat or lstat. For stat, the type should be a directory. For lstat, it should be a symlink. So I think your __check_handle_type should work for stat, but I can't exactly tell what would happen when it gets called from lstat.
Anyways, I am struggling to make the cross-compiler, but hopefully tomorrow I'll follow this tutorial: https://sourceforge.net/p/mingw-w64/wiki2/Build%20a%20native%20Windows%2064-bit%20gcc%20from%20Linux%20%28including%20cross-compiler%29/ up to the end of step 3, and then I will be able to run make check-compile. On Thu, Jun 25, 2026 at 3:26 PM Jonathan Wakely <[email protected]> wrote: > On Thu, 25 Jun 2026 at 18:34, Jonathan Wakely <[email protected]> wrote: > > > > On Thu, 25 Jun 2026 at 17:52, Jonathan Wakely <[email protected]> > wrote: > > > > > > On Wed, 24 Jun 2026 at 23:54, Adam Wood <[email protected]> > wrote: > > > > > > > > > > > > > > > > On Wed, Jun 24, 2026 at 2:38 PM Jonathan Wakely <[email protected]> > wrote: > > > >> > > > >> On Wed, 4 Mar 2026 at 23:17, Adam Wood <[email protected]> > wrote: > > > >> > > > > >> > > > > >> > > > > >> > On Wed, Mar 4, 2026 at 9:14 AM Jonathan Wakely < > [email protected]> wrote: > > > >> >> > > > >> >> On Mon, 16 Feb 2026 at 22:42, Adam Wood < > [email protected]> wrote: > > > >> >> > > > > >> >> > Tested on x86_64-w64-mingw32 on Windows 11. > > > >> >> > > > > >> >> > The changes in v4 make sure the new symlink functions are only > defined/enabled > > > >> >> > on versions of Windows with symlink support. > > > >> >> > > > > >> >> > Because path resolution may be different between Windows and > POSIX when a > > > >> >> > dotdot follows a symlink, I also made some edits to tests > involving that > > > >> >> > specific case. I removed my changes to fs::absolute and > > > >> >> > fs::canonical because I was misplaced and was trying to force > Windows to > > > >> >> > act like POSIX in that specific case. > > > >> >> > > > > >> >> > Finally, I dealt with the issue that creating symlinks with > the unprivileged > > > >> >> > flag returns an error in earlier versions of Windows by just > trying again > > > >> >> > if ERROR_INVALID_PARAMETER occurs without the unpriviledged > flag. This > > > >> >> > is how MSVC STL does it as well. > > > >> >> > > > > >> >> > The patch does not support junctions or mount points. > > > >> >> > > > >> >> Hi Adam, > > > >> >> > > > >> >> Thanks for the new patch. I'm still reviewing it, but I see these > > > >> >> tests failing using a mingw-w64 cross compiler and testing under > Wine: > > > >> >> > > > >> >> > /home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/1.cc:27: > > > >> >> void test_successful_copy(const std::filesystem::__cxx11::path&, > bool > > > >> >> (*)(const std::filesystem::__cxx11::path&)): Assertion > > > >> >> 'is_some_file_type(p2)' failed. > > > >> >> FAIL: > /home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/27_io/filesystem/operations/copy_symlink/1.cc > > > >> >> > > > >> >> > /home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc:36: > > > >> >> void test01(): Assertion 'st1.type() == fs::file_type::directory' > > > >> >> failed. > > > >> >> FAIL: > /home/jwakely/src/gcc/gcc/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc > > > >> >> > > > >> >> Do these PASS for you on real Windows? > > > >> >> > > > >> > Those tests all PASS on my Windows 11 VM. > > > >> > > > >> I've installed a Windows 11 VM. I built all the filesystem tests > using > > > >> a mingw-w64 cross compiler and ran the tests under Wine. For each > test > > > >> that PASSed before your changes and FAILed with your patch, I copied > > > >> the .exe to the Windows VM and ran it there, and they also FAILed on > > > >> the VM. So this doesn't seem to be a problem with Wine, the tests > FAIL > > > >> for Windows 11 too. > > > > > > > > > > > > I've been compiling the tests entirely within the Windows VM and > msys2 terminal. I'll try this method and see if I can fix this. > > > > > > I've debugged it a bit and the problem is that > > > symlink_status(".").type() is returning file_type::regular not > > > file_type::directory. > > > > > > After the call to _fstat64 the stat buffer has st_mode = 33206, so > > > S_ISREG(st_mode) is true. > > > > > > I don't think _ops_osfhandle works for directories, I think it can > > > only handle regular files, pipes, and character devices. So I think > > > your __stat_windows function needs to check for a directory before it > > > opens the file descriptor to pass to _fstat64. > > > > I think this fixes some of the failing tests: > > > > enum class FileType { Err = -1, Dir = S_IFDIR, Link = S_IFLNK, Other = > 0 }; > > > > // -1 error, 0 not a directory or symlink, otherwise S_IFDIR or S_IFLNK. > > inline FileType __check_handle_type(HANDLE handle) > > { > > #ifdef SYMBOLIC_LINK_FLAG_DIRECTORY > > FILE_ATTRIBUTE_TAG_INFO type_info; > > if (!GetFileInformationByHandleEx(handle, FileAttributeTagInfo, > > &type_info, sizeof(type_info))) > > { > > errno = > std::__last_system_error().default_error_condition().value(); > > return FileType::Err; > > } > > if (type_info.FileAttributes & FILE_ATTRIBUTE_DIRECTORY) > > return FileType::Dir; > > if (type_info.FileAttributes & FILE_ATTRIBUTE_REPARSE_POINT > > && type_info.ReparseTag == IO_REPARSE_TAG_SYMLINK) > > return FileType::Link; > > A directory symlink has both DIRECTORY and REPARSE_POINT set in > FileAttributes, so to detect a symlinks we need to check for that > first. So I've switched the order of the checks in my local build, and > that fixes a few more of the failing tests. > > > #endif > > return FileType::Other; > > } > > > > // -1 error, 0 not a symlink, 1 a symlink > > inline int __is_handle_symlink(HANDLE handle) > > { > > if (FileType type = __check_handle_type(handle); type != > FileType::Err) > > return type == FileType::Link; > > return -1; > > } > > > > inline int __stat_windows(const wchar_t* path, stat_type* buffer, > > bool following_symlinks) > > { > > HANDLE handle = __open_for_stat(path, following_symlinks); > > if (handle == INVALID_HANDLE_VALUE) > > return -1; > > // Manually check for directory or symlink, because _fstat does not. > > FileType type = __check_handle_type(handle); > > if (type == FileType::Err) > > { > > CloseHandle(handle); > > return -1; > > } > > int fd = ::_open_osfhandle((intptr_t)handle, _O_RDONLY); > > if (fd == -1) > > { > > CloseHandle(handle); > > return -1; > > } > > int stat_result = ::_fstat64(fd, buffer); > > if (type != FileType::Other) > > { > > // Clear the previous file type. > > buffer->st_mode &= ~S_IFMT; > > buffer->st_mode |= (::mode_t)type; > > } > > ::_close(fd); > > return stat_result; > > } > > > > i.e. replace __is_handle_symlink with __check_handle_type which checks > > for directories and symlinks and returns either S_IFDIR or S_IFLNK. > > Then define __is_handle_symlink in terms of that new function. > > > > I'm still seeing other regressions though. > >
