]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR libstdc++/79283 fix filesystem::read_symlink for /proc
authorJonathan Wakely <jwakely@redhat.com>
Fri, 5 Jan 2018 22:47:42 +0000 (22:47 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 5 Jan 2018 22:47:42 +0000 (22:47 +0000)
Backport from mainline
2017-10-25  Jonathan Wakely  <jwakely@redhat.com>

PR libstdc++/79283
* src/filesystem/ops.cc (read_symlink): Handle st_size being zero.

From-SVN: r256294

libstdc++-v3/ChangeLog
libstdc++-v3/src/filesystem/ops.cc

index 63fcb50596f2786ac1df275e809802ad50a9ad3d..67e67763cd1ca3f8a3b91eec139859a7daf93ad0 100644 (file)
@@ -1,3 +1,11 @@
+2018-01-05  Jonathan Wakely  <jwakely@redhat.com>
+
+       Backport from mainline
+       2017-10-25  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/79283
+       * src/filesystem/ops.cc (read_symlink): Handle st_size being zero.
+
 2017-12-14  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/59568
index 0dcb1b410fc0f3053afe61056a67f89457ff1195..b242c04e1c38fb8c600a9db49cddb78a36b16607 100644 (file)
@@ -1199,26 +1199,45 @@ fs::read_symlink(const path& p)
 
 fs::path fs::read_symlink(const path& p, error_code& ec)
 {
+  path result;
 #ifdef _GLIBCXX_HAVE_SYS_STAT_H
   stat_type st;
   if (::lstat(p.c_str(), &st))
     {
       ec.assign(errno, std::generic_category());
-      return {};
+      return result;
     }
-  std::string buf(st.st_size, '\0');
-  ssize_t len = ::readlink(p.c_str(), &buf.front(), buf.size());
-  if (len == -1)
+  std::string buf(st.st_size ? st.st_size + 1 : 128, '\0');
+  do
     {
-      ec.assign(errno, std::generic_category());
-      return {};
+      ssize_t len = ::readlink(p.c_str(), &buf.front(), buf.size());
+      if (len == -1)
+       {
+         ec.assign(errno, std::generic_category());
+         return result;
+       }
+      else if (len == (ssize_t)buf.size())
+       {
+         if (buf.size() > 4096)
+           {
+             ec.assign(ENAMETOOLONG, std::generic_category());
+             return result;
+           }
+         buf.resize(buf.size() * 2);
+       }
+      else
+       {
+         buf.resize(len);
+         result.assign(buf);
+         ec.clear();
+         break;
+       }
     }
-  ec.clear();
-  return path{buf.data(), buf.data()+len};
+  while (true);
 #else
   ec = std::make_error_code(std::errc::not_supported);
-  return {};
 #endif
+  return result;
 }