[Bug libstdc++/99430] New: std::filesystem::path: UNC device paths with \\?\… not supported properly

2021-03-06 Thread moritz at bunkus dot org via Gcc-bugs
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

2021-03-02 Thread moritz at bunkus dot org via Gcc-bugs
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

2021-03-02 Thread moritz at bunkus dot org via Gcc-bugs
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

2021-03-01 Thread moritz at bunkus dot org via Gcc-bugs
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

2021-02-28 Thread moritz at bunkus dot org via Gcc-bugs
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.