PR libstdc++/88884 fix filesystem::absolute("//") for mingw
authorJonathan Wakely <jwakely@redhat.com>
Thu, 17 Jan 2019 15:32:05 +0000 (15:32 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 17 Jan 2019 15:32:05 +0000 (15:32 +0000)
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.

From-SVN: r268035

libstdc++-v3/ChangeLog
libstdc++-v3/src/c++17/fs_ops.cc

index 62d5db8b4e820ad7c383e1d887ffd6a8ede90e53..1be8354aeca54ea91383878aa8b4f4535adf45c7 100644 (file)
@@ -1,5 +1,11 @@
 2019-01-17  Jonathan Wakely  <jwakely@redhat.com>
 
+       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.
+
        PR libstdc++/88881
        * src/c++17/fs_ops.cc (canonical(const path&, error_code&))
        [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Normalize path, to match behaviour
index 5f8be5b78481666f78687d18050b4091aba128fa..c4b99fb36ce52e4c91a8934a8a8221fa25466375 100644 (file)
@@ -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;