// { dg-options "-std=gnu++17" } #include <filesystem> #include <iostream> void print_status(std::filesystem::path p) { std::cout << p << " exists? " << std::boolalpha << exists(p) << '\n'; } int main() { print_status("./"); print_status("./nonexistent-path/.."); print_status("./nonexistent-path/../"); } This prints: "./" exists? false "./nonexistent-path/.." exists? true "./nonexistent-path/../" exists? false It seems that mingw's stat() fails for a directory with a trailing slash. It also implicitly resolves .. components, without consideration for whether the previous component exists or not (which seems consistent with DOS commands, e.g. "cd .\kgjhfjfj\.." is equivalent to "cd .", but is not how stat is supposed to work). I'll report these to mingw32-w64 but will need to add workarounds to std::filesystem.
The trailing slash problem is apparently fixed in mingw-w64: https://sourceforge.net/p/mingw-w64/bugs/643/
But that fix looks wrong, it means "file/" will resolve to "file" and that's wrong a for a non-directory, because "file/" should fail. Testcase demonstrating the mingw bugs: #include <sys/stat.h> #include <stdio.h> void print(const char* s, int i, int expected) { printf("%-26s %2d %s\n", s, i, i == expected ? "" : " FAIL"); } void f1() { struct stat st; int i; i = stat(".\\", &st); print("stat(\".\\\")", i, 0); i = stat(".\\nonesuch\\..", &st); print("stat(\".\\nonesuch\\..\")", i, -1); // Trailing slash after a non-directory should fail: i = stat("a.exe\\", &st); print("stat(\"a.exe\\\")", i, -1); // "/." after a non-directory is also wrong: i = stat("a.exe\\.", &st); print("stat(\"a.exe\\.\")", i, -1); // And resolving "/dir/.." after a non-directory is also wrong: i = stat("a.exe\\nonesuch\\..", &st); print("stat(\"a.exe\\nonesuch\\..\")", i, -1); } void f2() { struct _stat st; int i; i = _stat(".\\", &st); print("_stat(\".\\\")", i, 0); i = _stat(".\\nonesuch\\..", &st); print("_stat(\".\\nonesuch\\..\")", i, -1); } void f3() { struct _stat st; int i; i = _wstat(L".\\", &st); print("_wstat(L\".\\\")", i, 0); i = _wstat(L".\\nonesuch\\..", &st); print("_wstat(L\".\\nonesuch\\..\")", i, -1); } int main() { f1(); f2(); f3(); } Output for mingw-w64 5.0 stat(".\") 0 stat(".\nonesuch\..") 0 FAIL stat("a.exe\") 0 FAIL stat("a.exe\.") 0 FAIL stat("a.exe\nonesuch\..") 0 FAIL _stat(".\") -1 FAIL _stat(".\nonesuch\..") 0 FAIL _wstat(L".\") -1 FAIL _wstat(L".\nonesuch\..") 0 FAIL
The "nonexistent-path/.." part is reported as https://sourceforge.net/p/mingw-w64/bugs/782/
This bug is the cause of: FAIL: experimental/filesystem/operations/canonical.cc execution test The trailing slashes in the paths cause the _wstat calls to fail.
(In reply to Jonathan Wakely from comment #4) > This bug is the cause of: > > FAIL: experimental/filesystem/operations/canonical.cc execution test And also: FAIL: experimental/filesystem/operations/temp_directory_path.cc execution test because GetTempPathW always returns a directory with a trailing slash.
(In reply to Jonathan Wakely from comment #3) > The "nonexistent-path/.." part is reported as > https://sourceforge.net/p/mingw-w64/bugs/782/ And is apparently a feature not a bug. That's just how paths work on Windows. Go figure. So the remaining problem is the trailing slash, which is fixed in mingw-w64 v6.0.0, and I have a workaround for.
Author: redi Date: Thu Jan 17 15:31:59 2019 New Revision: 268034 URL: https://gcc.gnu.org/viewcvs?rev=268034&root=gcc&view=rev Log: PR libstdc++/88881 adjust filesystem::status and tests for mingw semantics On Windows stat("foo/bar/../.") will resolve to "foo" even if that is a non-directory and "foo/bar" does not exist. This is the expected behaviour and consistent with boost::filesystem, so don't try to correct it. The only unwanted behaviour is that stat("baz/") fails due to a mingw bug (fixed in mingw-w64 v6.0.0) so add a workaround. PR libstdc++/88881 * src/c++17/fs_ops.cc (canonical(const path&, error_code&)) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Normalize path, to match behaviour of filesystem::exists. (create_directories(const path&, error_code&)): Add assertions. (status(const path&, error_code&)) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Add workaround for bug in _wstat for paths with trailing slash. * testsuite/27_io/filesystem/operations/create_directories.cc: Adjust for expected behaviour on mingw. * testsuite/experimental/filesystem/operations/create_directories.cc: Likewise. * testsuite/27_io/filesystem/operations/temp_directory_path.cc: Use "TMP" instead of "TMPDIR" and clean environment before each test. Do not test permissions on mingw targets. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/src/c++17/fs_ops.cc trunk/libstdc++-v3/testsuite/27_io/filesystem/operations/create_directories.cc trunk/libstdc++-v3/testsuite/27_io/filesystem/operations/temp_directory_path.cc trunk/libstdc++-v3/testsuite/experimental/filesystem/operations/create_directories.cc
fixed on trunk
Author: redi Date: Wed May 29 22:00:53 2019 New Revision: 271755 URL: https://gcc.gnu.org/viewcvs?rev=271755&root=gcc&view=rev Log: PR libstdc++/88881 fix filesystem::symlink_status for Windows The fix for PR 88881 only added a workaround to filesystem::status, but filesystem::symlink_status is also affected by the _wstat bug and needs the same workaround. The recent change to optimize path::parent_path() means that the workaround can be simplified to just use parent_path(). PR libstdc++/88881 * src/c++17/fs_ops.cc [_GLIBCXX_FILESYSTEM_IS_WINDOWS] (status(const path&, error_code&)): Use parent_path() to remove trailing slash. (symlink_status(const path&, error_code&)): Duplicate workaround for bug in _wstat for paths with trailing slash. * testsuite/27_io/filesystem/operations/remove_all.cc: Check path with trailing slash. * testsuite/27_io/filesystem/operations/status.cc: Likewise. * testsuite/27_io/filesystem/operations/symlink_status.cc: Likewise. Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/src/c++17/fs_ops.cc trunk/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc trunk/libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc trunk/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc
Author: redi Date: Fri Jun 14 18:11:22 2019 New Revision: 272304 URL: https://gcc.gnu.org/viewcvs?rev=272304&root=gcc&view=rev Log: PR libstdc++/88881 fix filesystem::symlink_status for Windows The fix for PR 88881 only added a workaround to filesystem::status, but filesystem::symlink_status is also affected by the _wstat bug and needs the same workaround. The recent change to optimize path::parent_path() means that the workaround can be simplified to just use parent_path(). Backport from mainline 2019-05-29 Jonathan Wakely <jwakely@redhat.com> PR libstdc++/88881 * src/c++17/fs_ops.cc [_GLIBCXX_FILESYSTEM_IS_WINDOWS] (status(const path&, error_code&)): Use parent_path() to remove trailing slash. (symlink_status(const path&, error_code&)): Duplicate workaround for bug in _wstat for paths with trailing slash. * testsuite/27_io/filesystem/operations/remove_all.cc: Check path with trailing slash. * testsuite/27_io/filesystem/operations/status.cc: Likewise. * testsuite/27_io/filesystem/operations/symlink_status.cc: Likewise. Modified: branches/gcc-9-branch/libstdc++-v3/ChangeLog branches/gcc-9-branch/libstdc++-v3/src/c++17/fs_ops.cc branches/gcc-9-branch/libstdc++-v3/testsuite/27_io/filesystem/operations/remove_all.cc branches/gcc-9-branch/libstdc++-v3/testsuite/27_io/filesystem/operations/status.cc branches/gcc-9-branch/libstdc++-v3/testsuite/27_io/filesystem/operations/symlink_status.cc
std::filesystem::symlink_status (and functions that use it) also fixed for 9.2
*** Bug 98035 has been marked as a duplicate of this bug. ***
My fix for the trailing slash does: #if _GLIBCXX_FILESYSTEM_IS_WINDOWS #if ! defined __MINGW64_VERSION_MAJOR || __MINGW64_VERSION_MAJOR < 6 // stat() fails if there's a trailing slash (PR 88881) I'm seeing status("./") fail with mingw64 6.0.0 so apparently the workaround is still needed.
It looks like _stat and _wstat were fixed, but not _wstat64 which is what we use.
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:3df5b249b3c81e95cdcb293a388155ae5b168f9e commit r11-7174-g3df5b249b3c81e95cdcb293a388155ae5b168f9e Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Feb 10 16:51:34 2021 +0000 libstdc++: Re-enable workaround for _wstat64 bug [PR 88881] This wasn't fixed upstream for mingw-w64 so we still need the workaround. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/c++17/fs_ops.cc (fs::status): Re-enable workaround.
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:b7210405ed8eb5fd723b2c99960dcc5f0aec89b4 commit r11-7222-gb7210405ed8eb5fd723b2c99960dcc5f0aec89b4 Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Feb 10 16:51:34 2021 +0000 libstdc++: Re-enable workaround for _wstat64 bug, again [PR 88881] I forgot that the workaround is present in both filesystem::status and filesystem::symlink_status. This restores it in the latter. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/c++17/fs_ops.cc (fs::symlink_status): Re-enable workaround.
The releases/gcc-10 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:8455158044503a25ebb044428be2ddc83d2b0473 commit r10-9582-g8455158044503a25ebb044428be2ddc83d2b0473 Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Feb 10 16:51:34 2021 +0000 libstdc++: Re-enable workaround for _wstat64 bug [PR 88881] This wasn't fixed upstream for mingw-w64 so we still need the workaround. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/c++17/fs_ops.cc (fs::status): Re-enable workaround. (cherry picked from commit 3df5b249b3c81e95cdcb293a388155ae5b168f9e)
The releases/gcc-10 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:bad3463f257019946d8b17d6956ca058aef88eae commit r10-9583-gbad3463f257019946d8b17d6956ca058aef88eae Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Feb 10 16:51:34 2021 +0000 libstdc++: Re-enable workaround for _wstat64 bug, again [PR 88881] I forgot that the workaround is present in both filesystem::status and filesystem::symlink_status. This restores it in the latter. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/c++17/fs_ops.cc (fs::symlink_status): Re-enable workaround. (cherry picked from commit b7210405ed8eb5fd723b2c99960dcc5f0aec89b4)
Re-fixed for 10.3 as well
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
The releases/gcc-9 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:1a96bfe35fec4c425d6f5fbb9c539386e39ff3e4 commit r9-9656-g1a96bfe35fec4c425d6f5fbb9c539386e39ff3e4 Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Feb 10 16:51:34 2021 +0000 libstdc++: Re-enable workaround for _wstat64 bug [PR 88881] This wasn't fixed upstream for mingw-w64 so we still need the workaround. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/c++17/fs_ops.cc (fs::status): Re-enable workaround. (cherry picked from commit 3df5b249b3c81e95cdcb293a388155ae5b168f9e)
The releases/gcc-9 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:4178e8c049e4ef366335b661197e53b3efbed877 commit r9-9657-g4178e8c049e4ef366335b661197e53b3efbed877 Author: Jonathan Wakely <jwakely@redhat.com> Date: Wed Feb 10 16:51:34 2021 +0000 libstdc++: Re-enable workaround for _wstat64 bug, again [PR 88881] I forgot that the workaround is present in both filesystem::status and filesystem::symlink_status. This restores it in the latter. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/c++17/fs_ops.cc (fs::symlink_status): Re-enable workaround. (cherry picked from commit b7210405ed8eb5fd723b2c99960dcc5f0aec89b4)
Fixed for 9.5 too.
The master branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:6c96b14a19a9e6c365eacc59868a866b99f9786d commit r13-1365-g6c96b14a19a9e6c365eacc59868a866b99f9786d Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Jun 28 15:56:30 2022 +0100 libstdc++: Fix experimental::filesystem::status on Windows [PR88881] Although the Filesystem TS isn't properly supported on Windows (unlike the C++17 Filesystem lib), most tests do pass. Two of the failures are due to PR 88881 which was only fixed for std::filesystem not the TS. This applies the fix to the TS implementation too. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/filesystem/ops.cc (has_trailing_slash): New helper function. (fs::status): Strip trailing slashes. (fs::symlink_status): Likewise. * testsuite/experimental/filesystem/operations/temp_directory_path.cc: Clean the environment before each test and use TMP instead of TMPDIR so the test passes on Windows.
The releases/gcc-12 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:f3ff78e3db0fc18127dac4fe3eaf113d0c5ddd01 commit r12-8590-gf3ff78e3db0fc18127dac4fe3eaf113d0c5ddd01 Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Jun 28 15:56:30 2022 +0100 libstdc++: Fix experimental::filesystem::status on Windows [PR88881] Although the Filesystem TS isn't properly supported on Windows (unlike the C++17 Filesystem lib), most tests do pass. Two of the failures are due to PR 88881 which was only fixed for std::filesystem not the TS. This applies the fix to the TS implementation too. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/filesystem/ops.cc (has_trailing_slash): New helper function. (fs::status): Strip trailing slashes. (fs::symlink_status): Likewise. * testsuite/experimental/filesystem/operations/temp_directory_path.cc: Clean the environment before each test and use TMP instead of TMPDIR so the test passes on Windows. (cherry picked from commit 6c96b14a19a9e6c365eacc59868a866b99f9786d)
The releases/gcc-11 branch has been updated by Jonathan Wakely <redi@gcc.gnu.org>: https://gcc.gnu.org/g:66e876a91b5d5c1a0c5067f2d8f1d531da3a81f8 commit r11-10161-g66e876a91b5d5c1a0c5067f2d8f1d531da3a81f8 Author: Jonathan Wakely <jwakely@redhat.com> Date: Tue Jun 28 15:56:30 2022 +0100 libstdc++: Fix experimental::filesystem::status on Windows [PR88881] Although the Filesystem TS isn't properly supported on Windows (unlike the C++17 Filesystem lib), most tests do pass. Two of the failures are due to PR 88881 which was only fixed for std::filesystem not the TS. This applies the fix to the TS implementation too. libstdc++-v3/ChangeLog: PR libstdc++/88881 * src/filesystem/ops.cc (has_trailing_slash): New helper function. (fs::status): Strip trailing slashes. (fs::symlink_status): Likewise. * testsuite/experimental/filesystem/operations/temp_directory_path.cc: Clean the environment before each test and use TMP instead of TMPDIR so the test passes on Windows. (cherry picked from commit 6c96b14a19a9e6c365eacc59868a866b99f9786d)