diff mbox series

PR libstdc++/88884 fix filesystem::absolute("//") for mingw

Message ID 20190117153232.GA26986@redhat.com
State New
Headers show
Series PR libstdc++/88884 fix filesystem::absolute("//") for mingw | expand

Commit Message

Jonathan Wakely Jan. 17, 2019, 3:32 p.m. UTC
PR libstdc++/88884
	* src/c++17/fs_ops.cc (absolute(const path&, error_code&)): Do nothing
	if the path is already absolute.
	[_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Normalize root-directory.
	[!_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Pass error_code to current_path.

Tested x86_64-linux and x86_64-w64-mingw32, committed to trunk.
commit c008f75f5be810a9c6788680b7ee4816ccbaae9c
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Jan 17 13:44:47 2019 +0000

    PR libstdc++/88884 fix filesystem::absolute("//") for mingw
    
            PR libstdc++/88884
            * src/c++17/fs_ops.cc (absolute(const path&, error_code&)): Do nothing
            if the path is already absolute.
            [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Normalize root-directory.
            [!_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Pass error_code to current_path.
diff mbox series

Patch

diff --git a/libstdc++-v3/src/c++17/fs_ops.cc b/libstdc++-v3/src/c++17/fs_ops.cc
index 5f8be5b7848..c4b99fb36ce 100644
--- a/libstdc++-v3/src/c++17/fs_ops.cc
+++ b/libstdc++-v3/src/c++17/fs_ops.cc
@@ -85,14 +85,35 @@  fs::absolute(const path& p, error_code& ec)
       ec = make_error_code(std::errc::no_such_file_or_directory);
       return ret;
     }
+  ec.clear();
+  if (p.is_absolute())
+    {
+      ret = p;
+      return ret;
+    }
+
 #ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
-  const wstring& s = p.native();
+  wstring_view s = p.native();
+
+  if (p.has_root_directory()) // implies !p.has_root_name()
+    {
+      // GetFullPathNameW("//") gives unwanted result (PR 88884).
+      // If there are multiple directory separators at the start,
+      // skip all but the last of them.
+      const auto pos = s.find_first_not_of(L"/\\");
+      __glibcxx_assert(pos != 0);
+      s.remove_prefix(std::min(s.length(), pos) - 1);
+    }
+
+  // s must be null-terminated
+  __glibcxx_assert(!s.empty() && s.back() == 0);
+
   uint32_t len = 1024;
   wstring buf;
   do
     {
       buf.resize(len);
-      len = GetFullPathNameW(s.c_str(), len, buf.data(), nullptr);
+      len = GetFullPathNameW(s.data(), len, buf.data(), nullptr);
     }
   while (len > buf.size());
 
@@ -100,13 +121,11 @@  fs::absolute(const path& p, error_code& ec)
     ec.assign((int)GetLastError(), std::system_category());
   else
     {
-      ec.clear();
       buf.resize(len);
       ret = std::move(buf);
     }
 #else
-  ec.clear();
-  ret = current_path();
+  ret = current_path(ec);
   ret /= p;
 #endif
   return ret;