[Bug libstdc++/99430] New: std::filesystem::path: UNC device paths with \\?\… not supported properly
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99430 Bug ID: 99430 Summary: std::filesystem::path: UNC device paths with \\?\… not supported properly Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: moritz at bunkus dot org Target Milestone: --- Created attachment 50317 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50317=edit test case highlighting the issue Paths such as \\?\C:\WINDOWS or \\?\UNC\LOCALHOST\c$\WINDOWS don't work properly with std::filesystem::path (e.g. exists() & is_directory() return false). According to Microsoft's documentation those are valid.[1] The corresponding variants starting with \\.\ seem to fare better (safe for the root name & absolute issues, but I've filed 99333 for that already). boost::filesystem works fine with all of these paths. The attached sample program outputs the following, showing how Boost's & std's implementation differ: - std::filesystem::path for \\?\C:\WINDOWS is_aboslute 0 has_root_path 1 has_root_name 0 exists 0 is_directory 0 boost::filesystem::path for \\?\C:\WINDOWS is_aboslute 1 has_root_path 1 has_root_name 1 exists 1 is_directory 1 std::filesystem::path for \\?\UNC\localhost\c$\WINDOWS is_aboslute 0 has_root_path 1 has_root_name 0 exists 0 is_directory 0 boost::filesystem::path for \\?\UNC\localhost\c$\WINDOWS is_aboslute 1 has_root_path 1 has_root_name 1 exists 1 is_directory 1 std::filesystem::path for \\.\C:\WINDOWS is_aboslute 0 has_root_path 1 has_root_name 0 exists 1 is_directory 1 boost::filesystem::path for \\.\C:\WINDOWS is_aboslute 1 has_root_path 1 has_root_name 1 exists 1 is_directory 1 std::filesystem::path for \\.\UNC\localhost\c$\WINDOWS is_aboslute 0 has_root_path 1 has_root_name 0 exists 1 is_directory 1 boost::filesystem::path for \\.\UNC\localhost\c$\WINDOWS is_aboslute 1 has_root_path 1 has_root_name 1 exists 1 is_directory 1 - gcc mingw 10.2.0 from MXE (cross-compiling from Linux to Windows), Boost 1.74.0 [1] https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats
[Bug libstdc++/99333] std::filesystem::path().is_absolute() thinks UNC paths aren't absolute
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99333 --- Comment #4 from Moritz Bunkus --- Oh right, sorry — I misread your earlier comment.
[Bug libstdc++/99333] std::filesystem::path().is_absolute() thinks UNC paths aren't absolute
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99333 --- Comment #2 from Moritz Bunkus --- The following code tests forward & backward slashes with both std::filesystem (gcc 10.2.0, mingw via MXE) and boost::filesystem (Boost 1.74.0): auto slashes = R"(//server/share/file.txt)"s; auto backslashes = R"(\\server\share\file.txt)"s; std::cout << "std::filesystem::path(" << slashes << ").has_root_name() " << std::filesystem::path{slashes}.has_root_name() << "\n" << "std::filesystem::path(" << backslashes << ").has_root_name() " << std::filesystem::path{backslashes}.has_root_name() << "\n" << "boost::filesystem::path(" << slashes << ").has_root_name() " << boost::filesystem::path{slashes}.has_root_name() << "\n" << "boost::filesystem::path(" << backslashes << ").has_root_name() " << boost::filesystem::path{backslashes}.has_root_name() << "\n"; The output of that snippet is: std::filesystem::path(//server/share/file.txt).has_root_name() 0 std::filesystem::path(\\server\share\file.txt).has_root_name() 0 boost::filesystem::path(//server/share/file.txt).has_root_name() 1 boost::filesystem::path(\\server\share\file.txt).has_root_name() 1 Or to put it differently, std::filesystem doesn't seem to care either way while Boost recognizes both. Note that __CYGWIN__ is not defined with the compiler from MXE! I'm not compiling on Windows. This is a cross-compiler, from Linux to Windows. What is defined are things such as: [0 mosu@sweet-chili ~] x86_64-w64-mingw32.static-g++ -dM -E -x c++ - < /dev/null | sort | grep -E 'WINNT|WIN(32|64)|MINGW' #define __MINGW32__ 1 #define __MINGW64__ 1 #define __WIN32 1 #define __WIN32__ 1 #define _WIN32 1 #define WIN32 1 #define __WIN64 1 #define __WIN64__ 1 #define _WIN64 1 #define WIN64 1 #define __WINNT 1 #define __WINNT__ 1 #define WINNT 1
[Bug libstdc++/99333] New: std::filesystem::path().is_absolute() thinks UNC paths aren't absolute
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99333 Bug ID: 99333 Summary: std::filesystem::path().is_absolute() thinks UNC paths aren't absolute Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: moritz at bunkus dot org Target Milestone: --- Created attachment 50280 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50280=edit test case Compiling with gcc 10.2.0 from the mxe cross compilation environment for Windows. The attached sample program says it all. It shows that std::filesystem::("\\server\share\file.txt").is_absolute() is false and turns std::filesystem::absolute("\\server\share\file.txt") into something like "C:\server\share\file.txt". boost::filesystem::path(…).is_aboslute(), on the other hand, considers UNC paths absolute & leaves them unmodified via boost::filesystem::absolute(…) The test program outputs the following: std::filesystem: original \\disky\mosu\existing_file.txt is_absolute 0 absolute "C:\\disky\\mosu\\existing_file.txt" boost::filesystem: original \\disky\mosu\existing_file.txt is_absolute 1 absolute "\\disky\mosu\existing_file.txt" Compile with something like: x86_64-w64-mingw32.static-g++ -std=c++17 \ -I/home/mosu/prog/video/mingw/cross/usr/x86_64-w64-mingw32.static/include \ -L/home/mosu/prog/video/mingw/cross/usr/x86_64-w64-mingw32.static/lib \ -o std_filesystem_unc_paths_vs_absolute.exe \ std_filesystem_unc_paths_vs_absolute.cpp \ -lboost_filesystem-mt-s-x64 -lboost_system-mt-s-x64
[Bug libstdc++/99311] New: std::filesystem::exists & std::filesystem::create_directories don't work correctly with UNC paths
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99311 Bug ID: 99311 Summary: std::filesystem::exists & std::filesystem::create_directories don't work correctly with UNC paths Product: gcc Version: 10.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: libstdc++ Assignee: unassigned at gcc dot gnu.org Reporter: moritz at bunkus dot org Target Milestone: --- Created attachment 50270 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=50270=edit test case showing the issues These might be two separate issues, but my gut feeling is that they're both due to the same underlying problem, especially if create_directories() uses exists() to determine which components it has to create. Using std::filesystem::exists on a UNC path with mingw 10.20.0 that points to a share (not a file or directory in a share) returns false. For example: • exists() for the existing file "\\server\share\this_exists.txt" returns true proving that the share itself exists & the user has access to it. However, exists() on "\\server\share" (retrieved via ".parent_path()" from the full path) returns false. By comparison, boost::filesystem::exists() returns true for both paths. • Using the same server & same share, trying to create a sub-directory via create_directories() fails. For example, trying to create "\\server\share\this_does_not_exist_yet" fails. Yes, I'm 100% sure that I have write access to the share in question. By comparison, boost::filesystem::create_directories() works fine with such a path. I'll a sample program that shows the problem. Of course you'll have to adjust server & share names. Compiled with gcc 10.20.0 from the mxe project. Command line: x86_64-w64-mingw32.static-g++ -std=c++17 -o std_filesystem_exists_and_create_directories.exe std_filesystem_exists_and_create_directories.cpp The program outputs the following: - sanity check, should be true: 1 should return true but doesn't: 0 directory \\disky\mosu\does-not-exist doesn't exist yet, should be false: 0 tried to create directory \\disky\mosu\does-not-exist, have error code? 1 - The first is the check for the existing file. It does return true, showing that exists() works correctly for existing files. The second line tries exists() for the parent_path() of the file tested in line 1. Of course it should return true, too, but doesn't. The path points to the share. Line three just establishes that the directory really doesn't exist yet. exists() should return false here and does so. Great. Line four shows the result of the create_directories() call, or rather, whether the error_code is indicating an error. It does, which it shouldn't.