aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2015-09-16 23:50:28 +0100
committerJonathan Wakely <redi@gcc.gnu.org>2015-09-16 23:50:28 +0100
commit30362998612b17c3e016d0fc8f0b3b2ead666927 (patch)
tree3efd38e818c1d151333d9c0bfb7b3869ca9cec23 /libstdc++-v3
parent4ec39494ac756ee9525371d2225f55f18200d8e0 (diff)
downloadgcc-30362998612b17c3e016d0fc8f0b3b2ead666927.zip
gcc-30362998612b17c3e016d0fc8f0b3b2ead666927.tar.gz
gcc-30362998612b17c3e016d0fc8f0b3b2ead666927.tar.bz2
Implement filesystem::canonical() without realpath
PR libstdc++/67173 * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check _XOPEN_VERSION and PATH_MAX for _GLIBCXX_USE_REALPATH. * config.h.in: Regenerate. * configure: Regenerate. * src/filesystem/ops.cc: (canonical) [!_GLIBCXX_USE_REALPATH]: Add alternative implementation. * testsuite/experimental/filesystem/operations/canonical.cc: New. * testsuite/experimental/filesystem/operations/exists.cc: Add more tests. * testsuite/experimental/filesystem/operations/absolute.cc: Add test variables. * testsuite/experimental/filesystem/operations/copy.cc: Likewise. * testsuite/experimental/filesystem/operations/current_path.cc: Likewise. * testsuite/experimental/filesystem/operations/file_size.cc: Likewise. * testsuite/experimental/filesystem/operations/status.cc: Likewise. * testsuite/experimental/filesystem/operations/temp_directory_path.cc: Likewise. From-SVN: r227836
Diffstat (limited to 'libstdc++-v3')
-rw-r--r--libstdc++-v3/ChangeLog22
-rw-r--r--libstdc++-v3/acinclude.m417
-rw-r--r--libstdc++-v3/config.h.in2
-rwxr-xr-xlibstdc++-v3/configure30
-rw-r--r--libstdc++-v3/src/filesystem/ops.cc99
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/canonical.cc77
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc17
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc4
13 files changed, 262 insertions, 26 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index d425f49..b8c1184 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,25 @@
+2015-09-16 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/67173
+ * acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check _XOPEN_VERSION
+ and PATH_MAX for _GLIBCXX_USE_REALPATH.
+ * config.h.in: Regenerate.
+ * configure: Regenerate.
+ * src/filesystem/ops.cc: (canonical) [!_GLIBCXX_USE_REALPATH]: Add
+ alternative implementation.
+ * testsuite/experimental/filesystem/operations/canonical.cc: New.
+ * testsuite/experimental/filesystem/operations/exists.cc: Add more
+ tests.
+ * testsuite/experimental/filesystem/operations/absolute.cc: Add test
+ variables.
+ * testsuite/experimental/filesystem/operations/copy.cc: Likewise.
+ * testsuite/experimental/filesystem/operations/current_path.cc:
+ Likewise.
+ * testsuite/experimental/filesystem/operations/file_size.cc: Likewise.
+ * testsuite/experimental/filesystem/operations/status.cc: Likewise.
+ * testsuite/experimental/filesystem/operations/temp_directory_path.cc:
+ Likewise.
+
2015-09-11 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/67173
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 64c9b7e..c133c25 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -3947,13 +3947,24 @@ dnl
AC_MSG_CHECKING([for realpath])
AC_CACHE_VAL(glibcxx_cv_realpath, [dnl
GCC_TRY_COMPILE_OR_LINK(
- [#include <stdlib.h>],
- [char *tmp = realpath((const char*)NULL, (char*)NULL);],
+ [
+ #include <stdlib.h>
+ #include <unistd.h>
+ ],
+ [
+ #if _XOPEN_VERSION < 500
+ #error
+ #elif _XOPEN_VERSION >= 700 || defined(PATH_MAX)
+ char *tmp = realpath((const char*)NULL, (char*)NULL);
+ #else
+ #error
+ #endif
+ ],
[glibcxx_cv_realpath=yes],
[glibcxx_cv_realpath=no])
])
if test $glibcxx_cv_realpath = yes; then
- AC_DEFINE(_GLIBCXX_USE_REALPATH, 1, [Define if realpath is available in <stdlib.h>.])
+ AC_DEFINE(_GLIBCXX_USE_REALPATH, 1, [Define if usable realpath is available in <stdlib.h>.])
fi
AC_MSG_RESULT($glibcxx_cv_realpath)
dnl
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index cc7a21e..58eef93 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -883,7 +883,7 @@
of TR1 (Chapter 5.1). */
#undef _GLIBCXX_USE_RANDOM_TR1
-/* Define if realpath is available in <stdlib.h>. */
+/* Define if usable realpath is available in <stdlib.h>. */
#undef _GLIBCXX_USE_REALPATH
/* Defined if sched_yield is available. */
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index 6d35f30..dea0a2d 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -79178,11 +79178,22 @@ else
if test x$gcc_no_link = xyes; then
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdlib.h>
+
+ #include <stdlib.h>
+ #include <unistd.h>
+
int
main ()
{
-char *tmp = realpath((const char*)NULL, (char*)NULL);
+
+ #if _XOPEN_VERSION < 500
+ #error
+ #elif _XOPEN_VERSION >= 700 || defined(PATH_MAX)
+ char *tmp = realpath((const char*)NULL, (char*)NULL);
+ #else
+ #error
+ #endif
+
;
return 0;
}
@@ -79199,11 +79210,22 @@ else
fi
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
-#include <stdlib.h>
+
+ #include <stdlib.h>
+ #include <unistd.h>
+
int
main ()
{
-char *tmp = realpath((const char*)NULL, (char*)NULL);
+
+ #if _XOPEN_VERSION < 500
+ #error
+ #elif _XOPEN_VERSION >= 700 || defined(PATH_MAX)
+ char *tmp = realpath((const char*)NULL, (char*)NULL);
+ #else
+ #error
+ #endif
+
;
return 0;
}
diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc
index cefb927..b5c8eb9 100644
--- a/libstdc++-v3/src/filesystem/ops.cc
+++ b/libstdc++-v3/src/filesystem/ops.cc
@@ -96,23 +96,98 @@ namespace
fs::path
fs::canonical(const path& p, const path& base, error_code& ec)
{
- path can;
+ const path pa = absolute(p, base);
+ path result;
#ifdef _GLIBCXX_USE_REALPATH
- char* buffer = nullptr;
-#if defined(__SunOS_5_10) && defined(PATH_MAX)
- buffer = (char*)::malloc(PATH_MAX);
-#endif
- if (char_ptr rp = char_ptr{::realpath(absolute(p, base).c_str(), buffer)})
+ char_ptr buf{ nullptr };
+# if _XOPEN_VERSION < 700
+ // Not safe to call realpath(path, NULL)
+ buf.reset( (char*)::malloc(PATH_MAX) );
+# endif
+ if (char* rp = ::realpath(pa.c_str(), buf.get()))
{
- can.assign(rp.get());
+ if (buf == nullptr)
+ buf.reset(rp);
+ result.assign(rp);
ec.clear();
+ return result;
+ }
+ if (errno != ENAMETOOLONG)
+ {
+ ec.assign(errno, std::generic_category());
+ return result;
}
- else
- ec.assign(errno, std::generic_category());
-#else
- ec = std::make_error_code(std::errc::not_supported);
#endif
- return can;
+
+ auto fail = [&ec, &result](int e) mutable {
+ if (!ec.value())
+ ec.assign(e, std::generic_category());
+ result.clear();
+ };
+
+ if (!exists(pa, ec))
+ {
+ fail(ENOENT);
+ return result;
+ }
+ // else we can assume no unresolvable symlink loops
+
+ result = pa.root_path();
+
+ deque<path> cmpts;
+ for (auto& f : pa.relative_path())
+ cmpts.push_back(f);
+
+ while (!cmpts.empty())
+ {
+ path f = std::move(cmpts.front());
+ cmpts.pop_front();
+
+ if (f.compare(".") == 0)
+ {
+ if (!is_directory(result, ec))
+ {
+ fail(ENOTDIR);
+ break;
+ }
+ }
+ else if (f.compare("..") == 0)
+ {
+ auto parent = result.parent_path();
+ if (parent.empty())
+ result = pa.root_path();
+ else
+ result.swap(parent);
+ }
+ else
+ {
+ result /= f;
+
+ if (is_symlink(result, ec))
+ {
+ path link = read_symlink(result, ec);
+ if (!ec.value())
+ {
+ if (link.is_absolute())
+ {
+ result = link.root_path();
+ link = link.relative_path();
+ }
+ else
+ result.remove_filename();
+
+ cmpts.insert(cmpts.begin(), link.begin(), link.end());
+ }
+ }
+
+ if (ec.value() || !exists(result, ec))
+ {
+ fail(ENOENT);
+ break;
+ }
+ }
+ }
+ return result;
}
fs::path
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc
index 14625b5..f7507f5 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/absolute.cc
@@ -29,6 +29,8 @@ using std::experimental::filesystem::path;
void
test01()
{
+ bool test __attribute__((unused)) = false;
+
for (const path& p : __gnu_test::test_paths)
VERIFY( absolute(p).is_absolute() );
}
@@ -36,6 +38,8 @@ test01()
void
test02()
{
+ bool test __attribute__((unused)) = false;
+
path p1("/");
VERIFY( absolute(p1) == p1 );
VERIFY( absolute(p1, "/bar") == p1 );
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/canonical.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/canonical.cc
new file mode 100644
index 0000000..d752feb
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/canonical.cc
@@ -0,0 +1,77 @@
+// Copyright (C) 2015 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++11 -lstdc++fs" }
+// { dg-require-filesystem-ts "" }
+
+#include <experimental/filesystem>
+#include <testsuite_hooks.h>
+#include <testsuite_fs.h>
+
+namespace fs = std::experimental::filesystem;
+
+void
+test01()
+{
+ bool test __attribute__((unused)) = false;
+
+ std::error_code ec;
+ auto p = __gnu_test::nonexistent_path();
+ canonical( p, ec );
+ VERIFY( ec );
+
+ p = fs::current_path();
+ canonical( p, ec );
+ VERIFY( !ec );
+
+ p = "/";
+ p = canonical( p, ec );
+ VERIFY( p == "/" );
+ VERIFY( !ec );
+
+ p = "/.";
+ p = canonical( p, ec );
+ VERIFY( p == "/" );
+ VERIFY( !ec );
+
+ p = "/..";
+ p = canonical( p, ec );
+ VERIFY( p == "/" );
+ VERIFY( !ec );
+
+ p = "/../.././.";
+ p = canonical( p, ec );
+ VERIFY( p == "/" );
+ VERIFY( !ec );
+
+ p = "/dev/stdin";
+ if (exists(p))
+ {
+ auto p2 = canonical(p);
+ if (is_symlink(p))
+ VERIFY( p != p2 );
+ else
+ VERIFY( p == p2 );
+ VERIFY( canonical(p2) == p2 );
+ }
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc
index 2410c80..35d49f0 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc
@@ -29,6 +29,8 @@ using std::experimental::filesystem::path;
void
test01()
{
+ bool test __attribute__((unused)) = false;
+
for (const path& p : __gnu_test::test_paths)
VERIFY( absolute(p).is_absolute() );
}
@@ -36,6 +38,8 @@ test01()
void
test02()
{
+ bool test __attribute__((unused)) = false;
+
path p1("/");
VERIFY( absolute(p1) == p1 );
VERIFY( absolute(p1, "/bar") == p1 );
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc
index c242ac0..81ade73 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/current_path.cc
@@ -29,6 +29,8 @@ namespace fs = std::experimental::filesystem;
void
test01()
{
+ bool test __attribute__((unused)) = false;
+
fs::path dot(".");
fs::path cwd = fs::current_path();
std::error_code ec;
@@ -39,6 +41,8 @@ test01()
void
test02()
{
+ bool test __attribute__((unused)) = false;
+
auto oldwd = fs::current_path();
auto tmpdir = fs::temp_directory_path();
current_path(tmpdir);
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc
index 0f1e5aa..dba4a6f 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/exists.cc
@@ -20,32 +20,37 @@
#include <experimental/filesystem>
#include <testsuite_hooks.h>
+#include <testsuite_fs.h>
using std::experimental::filesystem::path;
void
test01()
{
+ bool test __attribute__((unused)) = false;
+
VERIFY( exists(path{"/"}) );
VERIFY( exists(path{"/."}) );
VERIFY( exists(path{"."}) );
+ VERIFY( exists(path{".."}) );
+ VERIFY( exists(std::experimental::filesystem::current_path()) );
}
void
test02()
{
- path rel{"xXxXx"};
- while (exists(rel))
- rel /= "x";
+ bool test __attribute__((unused)) = false;
+
+ path rel = __gnu_test::nonexistent_path();
VERIFY( !exists(rel) );
}
void
test03()
{
- path abs{"/xXxXx"};
- while (exists(abs))
- abs /= "x";
+ bool test __attribute__((unused)) = false;
+
+ path abs = absolute(__gnu_test::nonexistent_path());
VERIFY( !exists(abs) );
}
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc
index 04fa7bb..7603064 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/file_size.cc
@@ -27,6 +27,8 @@ namespace fs = std::experimental::filesystem;
void
test01()
{
+ bool test __attribute__((unused)) = false;
+
std::error_code ec;
size_t size = fs::file_size(".", ec);
VERIFY( ec == std::errc::is_a_directory );
@@ -45,6 +47,8 @@ test01()
void
test02()
{
+ bool test __attribute__((unused)) = false;
+
fs::path p = __gnu_test::nonexistent_path();
std::error_code ec;
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc
index 2c54494..0f1730d 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/status.cc
@@ -27,6 +27,8 @@ namespace fs = std::experimental::filesystem;
void
test01()
{
+ bool test __attribute__((unused)) = false;
+
std::error_code ec;
fs::file_status st1 = fs::status(".", ec);
VERIFY( !ec );
@@ -39,6 +41,8 @@ test01()
void
test02()
{
+ bool test __attribute__((unused)) = false;
+
fs::path p = __gnu_test::nonexistent_path();
std::error_code ec;
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc
index 2aacd1c..bd9b6ad 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/temp_directory_path.cc
@@ -37,6 +37,8 @@ namespace fs = std::experimental::filesystem;
void
test01()
{
+ bool test __attribute__((unused)) = false;
+
clean_env();
if (!fs::exists("/tmp"))
@@ -53,6 +55,8 @@ test01()
void
test02()
{
+ bool test __attribute__((unused)) = false;
+
clean_env();
if (::setenv("TMPDIR", __gnu_test::nonexistent_path().string().c_str(), 1))