+2019-01-16 Jonathan Wakely <jwakely@redhat.com>
+
+ * config/abi/pre/gnu.ver (GLIBCXX_3.4.26): Add exports for fstream
+ constructors and open members taking wide strings. Fix patterns for
+ filesystem::path members to match wstring_view parameters. Add
+ exports for shared_ptr members used by directory iterators.
+ * src/c++17/fs_ops.cc (remove(const path&, error_code&)): Clear the
+ error code parameter if the file doesn't exist.
+ * src/filesystem/ops.cc (remove(const path&, error_code&)):
+ Likewise.
+ * testsuite/27_io/filesystem/operations/canonical.cc: Fix expected
+ values for mingw targets, where "/" is not an absolute path. Do not
+ test symlinks on mingw targets.
+ * testsuite/experimental/filesystem/operations/canonical.cc: Likewise.
+ * testsuite/27_io/filesystem/operations/copy.cc: Do not test symlinks
+ on mingw targets.
+ * testsuite/experimental/filesystem/operations/copy.cc: Likewise.
+ * testsuite/27_io/filesystem/operations/create_directories.cc: Check
+ that each component of the path is created.
+ * testsuite/experimental/filesystem/operations/create_directories.cc:
+ Likewise.
+ * testsuite/27_io/filesystem/operations/exists.cc: Do not test
+ permissions on mingw targets.
+ * testsuite/experimental/filesystem/operations/exists.cc: Likewise.
+ * testsuite/27_io/filesystem/operations/is_empty.cc: Likewise.
+ * testsuite/experimental/filesystem/operations/is_empty.cc: Likewise.
+ * testsuite/27_io/filesystem/operations/permissions.cc: XFAIL for
+ mingw targets.
+ * testsuite/experimental/filesystem/operations/permissions.cc:
+ Likewise.
+ * testsuite/27_io/filesystem/operations/remove.cc: Do not test
+ symlinks or permissions on mingw targets.
+ * testsuite/experimental/filesystem/operations/remove.cc: Likewise.
+ * testsuite/27_io/filesystem/operations/remove_all.cc: Do not test
+ symlinks on mingw targets.
+ * testsuite/experimental/filesystem/operations/remove_all.cc:
+ Likewise.
+ * testsuite/27_io/filesystem/operations/status.cc: Do not test
+ permissions on mingw targets.
+ * testsuite/27_io/filesystem/operations/weakly_canonical.cc: Do not
+ test symlinks on mingw targets.
+ * testsuite/experimental/filesystem/operations/space.cc: Fix test
+ for mingw targets.
+
2019-02-14 Ulrich Drepper <drepper@redhat.com>
PR libstdc++/88738
_ZNSt13basic_istreamIwSt11char_traitsIwEE6ignoreExt;
# std::basic_filebuf::open(const wchar_t*, openmode)
_ZNSt13basic_filebufI[cw]St11char_traitsI[cw]EE4openEPKwSt13_Ios_Openmode;
+ _ZNSt13basic_fstreamI[cw]St11char_traitsI[cw]EEC[12]EPKwSt13_Ios_Openmode;
+ _ZNSt13basic_fstreamI[cw]St11char_traitsI[cw]EE4openEPKwSt13_Ios_Openmode;
+ _ZNSt14basic_[io]fstreamI[cw]St11char_traitsI[cw]EEC[12]EPKwSt13_Ios_Openmode;
+ _ZNSt14basic_[io]fstreamI[cw]St11char_traitsI[cw]EE4openEPKwSt13_Ios_Openmode;
_ZN11__gnu_debug25_Safe_local_iterator_base16_M_attach_singleEPNS_19_Safe_sequence_baseEb;
_ZNKSt10filesystem4path5_List3endEv;
_ZNKSt10filesystem4path5_List5beginEv;
_ZNKSt10filesystem4path7compareERKS0_;
- _ZNKSt10filesystem4path7compareESt17basic_string_viewIcSt11char_traitsIcEE;
+ _ZNKSt10filesystem4path7compareESt17basic_string_viewI[cw]St11char_traitsI[cw]EE;
_ZNKSt10filesystem4path9root_*Ev;
_ZNSt10filesystem10hash_valueERKNS_4pathE;
_ZNSt10filesystem16filesystem_errorC[12]E*;
_ZNSt10filesystem4path1[567]re*;
_ZNSt10filesystem4path5_ListC1ERKS1_;
_ZNSt10filesystem4path5_ListC1Ev;
- _ZNSt10filesystem4path9_M_appendESt17basic_string_viewIcSt11char_traitsIcEE;
- _ZNSt10filesystem4path9_M_concatESt17basic_string_viewIcSt11char_traitsIcEE;
+ _ZNSt10filesystem4path9_M_appendESt17basic_string_viewI[cw]St11char_traitsI[cw]EE;
+ _ZNSt10filesystem4path9_M_concatESt17basic_string_viewI[cw]St11char_traitsI[cw]EE;
_ZNSt10filesystem4pathaSERKS0_;
_ZNSt10filesystem4pathdVERKS0_;
_ZNSt10filesystem4pathpLERKS0_;
_ZNKSt10filesystem7__cxx114path5_List3endEv;
_ZNKSt10filesystem7__cxx114path5_List5beginEv;
_ZNKSt10filesystem7__cxx114path7compareERKS1_;
- _ZNKSt10filesystem7__cxx114path7compareESt17basic_string_viewIcSt11char_traitsIcEE;
+ _ZNKSt10filesystem7__cxx114path7compareESt17basic_string_viewI[cw]St11char_traitsI[cw]EE;
_ZNKSt10filesystem7__cxx114path9root_*Ev;
_ZNSt10filesystem7__cxx1110hash_valueERKNS0_4pathE;
_ZNSt10filesystem7__cxx1116filesystem_errorC[12]E*;
_ZNSt10filesystem7__cxx114path1[567]re*;
_ZNSt10filesystem7__cxx114path5_ListC1ERKS2_;
_ZNSt10filesystem7__cxx114path5_ListC1Ev;
- _ZNSt10filesystem7__cxx114path9_M_appendESt17basic_string_viewIcSt11char_traitsIcEE;
- _ZNSt10filesystem7__cxx114path9_M_concatESt17basic_string_viewIcSt11char_traitsIcEE;
+ _ZNSt10filesystem7__cxx114path9_M_appendESt17basic_string_viewI[cw]St11char_traitsI[cw]EE;
+ _ZNSt10filesystem7__cxx114path9_M_concatESt17basic_string_viewI[cw]St11char_traitsI[cw]EE;
_ZNSt10filesystem7__cxx114pathaSERKS1_;
_ZNSt10filesystem7__cxx114pathdVERKS1_;
_ZNSt10filesystem7__cxx114pathpLERKS1_;
_ZNSt10filesystem7__cxx1128recursive_directory_iteratoraSEOS1_;
_ZNSt10filesystem7__cxx1128recursive_directory_iteratorppEv;
+ _ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC1Ev;
+ _ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEC1EOS5_;
+ _ZNSt12__shared_ptrINSt10filesystem7__cxx114_DirELN9__gnu_cxx12_Lock_policyE2EEaSEOS5_;
+ _ZNSt12__shared_ptrINSt10filesystem7__cxx1128recursive_directory_iterator10_Dir_stackELN9__gnu_cxx12_Lock_policyE2EEC1Ev;
+ _ZNSt12__shared_ptrINSt10filesystem7__cxx1128recursive_directory_iterator10_Dir_stackELN9__gnu_cxx12_Lock_policyE2EEC1EOS6_;
+
# basic_ostream::operator<<(nullptr_t)
_ZNSolsEDn;
_ZNSt13basic_ostreamIwSt11char_traitsIwEElsEDn;
fs::remove(const path& p, error_code& ec) noexcept
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
- if (exists(symlink_status(p, ec)))
+ auto st = symlink_status(p, ec);
+ if (exists(st))
{
if ((is_directory(p, ec) && RemoveDirectoryW(p.c_str()))
|| DeleteFileW(p.c_str()))
else if (!ec)
ec.assign((int)GetLastError(), generic_category());
}
+ else if (status_known(st))
+ ec.clear();
#else
if (::remove(p.c_str()) == 0)
{
fs::remove(const path& p, error_code& ec) noexcept
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
- if (exists(symlink_status(p, ec)))
+ auto st = symlink_status(p, ec);
+ if (exists(st))
{
if ((is_directory(p, ec) && RemoveDirectoryW(p.c_str()))
|| DeleteFileW(p.c_str()))
else if (!ec)
ec.assign((int)GetLastError(), generic_category());
}
+ else if (status_known(st))
+ ec.clear();
#else
if (::remove(p.c_str()) == 0)
{
compare_paths( p2, p );
VERIFY( !ec );
+ const auto root = fs::absolute("/");
+
ec = bad_ec;
p = "/";
p = canonical( p, ec );
- compare_paths( p, "/" );
+ compare_paths( p, root );
VERIFY( !ec );
ec = bad_ec;
p = "/.";
p = canonical( p, ec );
- compare_paths( p, "/" );
+ compare_paths( p, root );
VERIFY( !ec );
ec = bad_ec;
p = "/..";
p = canonical( p, ec );
- compare_paths( p, "/" );
+ compare_paths( p, root );
VERIFY( !ec );
ec = bad_ec;
p = "/../.././.";
p = canonical( p, ec );
- compare_paths( p, "/" );
+ compare_paths( p, root );
VERIFY( !ec );
}
#endif
}
-
void
test03()
{
fs::path foo = dir/"foo", bar = dir/"bar";
fs::create_directory(foo);
fs::create_directory(bar);
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+ const fs::path baz = dir/"foo\\\\..\\bar///";
+#else
fs::create_symlink("../bar", foo/"baz");
+ const fs::path baz = dir/"foo//./baz///";
+#endif
auto dirc = canonical(dir);
auto barc = canonical(bar);
auto p1 = fs::canonical(dir/"foo//.///..//./");
compare_paths( p1, dirc );
- auto p2 = fs::canonical(dir/"foo//./baz///..//./");
+ auto p2 = fs::canonical(baz/"..//./");
compare_paths( p2, dirc );
- auto p3 = fs::canonical(dir/"foo//./baz////./");
+ auto p3 = fs::canonical(baz/"./");
compare_paths( p3, barc );
- auto p4 = fs::canonical(dir/"foo//./baz///..//./bar");
+ auto p4 = fs::canonical(baz/"..//./bar");
compare_paths( p4, barc );
- auto p5 = fs::canonical(dir/"foo//./baz///..//./bar/");
+ auto p5 = fs::canonical(baz/"..//./bar/");
compare_paths( p5, p4 );
- auto p6 = fs::canonical(dir/"foo//./baz///..//./bar/.");
+ auto p6 = fs::canonical(baz/"..//./bar/.");
compare_paths( p6, p4 );
remove_all(dir);
void
test02()
{
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+ return;
+#endif
+
const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
auto from = __gnu_test::nonexistent_path();
auto to = __gnu_test::nonexistent_path();
b = fs::create_directories( p/"./d4/../d5", ec );
VERIFY( !ec );
VERIFY( b );
+ VERIFY( is_directory(p/"d4") );
+ VERIFY( is_directory(p/"d5") );
VERIFY( is_directory(p/"./d4/../d5") );
std::uintmax_t count = remove_all(p, ec);
void
test04()
{
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // filesystem permissions not supported
+ return;
+#endif
+
using std::filesystem::perms;
using std::filesystem::perm_options;
path p = __gnu_test::nonexistent_path();
void
test01()
{
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // filesystem permissions not supported
+ return;
+#endif
+
auto p = __gnu_test::nonexistent_path();
create_directory(p);
permissions(p, fs::perms::none);
// { dg-options "-std=gnu++17" }
// { dg-do run { target c++17 } }
// { dg-require-filesystem-ts "" }
+// { dg-xfail-if "permissions not supported" { *-*-mingw* } }
// C++17 30.10.14.26 Permissions [fs.op.permissions]
VERIFY( !ec );
VERIFY( !n );
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+#else
auto link = __gnu_test::nonexistent_path();
create_symlink(p, link); // dangling symlink
ec = bad_ec;
VERIFY( !ec );
VERIFY( n );
VERIFY( !exists(symlink_status(p)) );
+#endif
const auto dir = __gnu_test::nonexistent_path();
create_directories(dir/"a/b");
VERIFY( !n );
VERIFY( exists(dir/"a/b") );
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No permissions support
+#else
permissions(dir, fs::perms::none, ec);
if (!ec)
{
VERIFY( !n );
permissions(dir, fs::perms::owner_all, ec);
}
+#endif
ec = bad_ec;
n = remove(dir/"a/b", ec);
VERIFY( !ec );
VERIFY( n == 0 );
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+#else
auto link = __gnu_test::nonexistent_path();
create_symlink(p, link); // dangling symlink
ec = bad_ec;
VERIFY( n == 1 );
VERIFY( !exists(symlink_status(link)) ); // The symlink is removed, but
VERIFY( exists(p) ); // its target is not.
+#endif
const auto dir = __gnu_test::nonexistent_path();
create_directories(dir/"a/b/c");
void
test03()
{
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No permissions support
+ return;
+#endif
+
fs::path dir = __gnu_test::nonexistent_path();
fs::create_directory(dir);
__gnu_test::scoped_file d(dir, __gnu_test::scoped_file::adopt_file);
void
test01()
{
+ const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
+ std::error_code ec;
+
auto dir = __gnu_test::nonexistent_path();
fs::create_directory(dir);
const auto dirc = canonical(dir);
fs::create_directory(foo);
fs::create_directory(bar);
fs::create_directory(bar/"baz");
+ fs::path p;
+
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+#else
fs::create_symlink("../bar", foo/"bar");
- auto p = fs::weakly_canonical(dir/"foo//./bar///../biz/.");
+ p = fs::weakly_canonical(dir/"foo//./bar///../biz/.");
VERIFY( p == dirc/"biz/" );
p = fs::weakly_canonical(dir/"foo/.//bar/././baz/.");
VERIFY( p == dirc/"bar/baz" );
p = fs::weakly_canonical(fs::current_path()/dir/"bar//../foo/bar/baz");
VERIFY( p == dirc/"bar/baz" );
- const std::error_code bad_ec = make_error_code(std::errc::invalid_argument);
- std::error_code ec;
-
ec = bad_ec;
p = fs::weakly_canonical(dir/"foo//./bar///../biz/.", ec);
VERIFY( !ec );
p = fs::weakly_canonical(fs::current_path()/dir/"bar//../foo/bar/baz", ec);
VERIFY( !ec );
VERIFY( p == dirc/"bar/baz" );
+#endif
+
+ // As above, but using "foo/.." instead of "foo",
+ // because there is no "foo/bar" symlink
+
+ p = fs::weakly_canonical(dir/"./bar///../biz/.");
+ VERIFY( p == dirc/"biz/" );
+ p = fs::weakly_canonical(dir/"foo/.././/bar/././baz/.");
+ VERIFY( p == dirc/"bar/baz" );
+ p = fs::weakly_canonical(fs::current_path()/dir/"bar//../foo/../bar/baz");
+ VERIFY( p == dirc/"bar/baz" );
+
+ ec = bad_ec;
+ p = fs::weakly_canonical(dir/"foo/..//./bar///../biz/.", ec);
+ VERIFY( !ec );
+ VERIFY( p == dirc/"biz/" );
+ ec = bad_ec;
+ p = fs::weakly_canonical(dir/"foo/.././/bar/././baz/.", ec);
+ VERIFY( !ec );
+ VERIFY( p == dirc/"bar/baz" );
+ ec = bad_ec;
+ p = fs::weakly_canonical(fs::current_path()/dir/"bar//../foo/../bar/baz", ec);
+ VERIFY( !ec );
+ VERIFY( p == dirc/"bar/baz" );
fs::remove_all(dir, ec);
}
canonical( p, ec );
VERIFY( !ec );
+ const auto root = fs::absolute("/");
+
p = "/";
p = canonical( p, ec );
- VERIFY( p == "/" );
+ VERIFY( p == root );
VERIFY( !ec );
p = "/.";
p = canonical( p, ec );
- VERIFY( p == "/" );
+ VERIFY( p == root );
VERIFY( !ec );
p = "/..";
p = canonical( p, ec );
- VERIFY( p == "/" );
+ VERIFY( p == root );
VERIFY( !ec );
p = "/../.././.";
p = canonical( p, ec );
- VERIFY( p == "/" );
+ VERIFY( p == root );
VERIFY( !ec );
}
void
test02()
{
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+ return;
+#endif
+
auto from = __gnu_test::nonexistent_path();
auto to = __gnu_test::nonexistent_path();
std::error_code ec, bad = std::make_error_code(std::errc::invalid_argument);
b = fs::create_directories( p/"./d4/../d5", ec );
VERIFY( !ec );
VERIFY( b );
+ VERIFY( is_directory(p/"d4") );
+ VERIFY( is_directory(p/"d5") );
VERIFY( is_directory(p/"./d4/../d5") );
std::uintmax_t count = remove_all(p, ec);
void
test04()
{
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // filesystem permissions not supported
+ return;
+#endif
+
using perms = std::experimental::filesystem::perms;
path p = __gnu_test::nonexistent_path();
create_directory(p);
void
test01()
{
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // filesystem permissions not supported
+ return;
+#endif
+
auto p = __gnu_test::nonexistent_path();
create_directory(p);
permissions(p, fs::perms::none);
// { dg-options "-DUSE_FILESYSTEM_TS -lstdc++fs" }
// { dg-do run { target c++11 } }
// { dg-require-filesystem-ts "" }
+// { dg-xfail-if "permissions not supported" { *-*-mingw* } }
// 15.26 Permissions [fs.op.permissions]
VERIFY( !ec );
VERIFY( !n );
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+ return;
+#else
auto link = __gnu_test::nonexistent_path();
create_symlink(p, link); // dangling symlink
ec = bad_ec;
VERIFY( !ec );
VERIFY( n );
VERIFY( !exists(symlink_status(p)) );
+#endif
const auto dir = __gnu_test::nonexistent_path();
create_directories(dir/"a/b");
VERIFY( !n );
VERIFY( exists(dir/"a/b") );
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No permissions support
+#else
permissions(dir, fs::perms::none, ec);
if (!ec)
{
VERIFY( !n );
permissions(dir, fs::perms::owner_all, ec);
}
+#endif
ec = bad_ec;
n = remove(dir/"a/b", ec);
VERIFY( !ec );
VERIFY( n == 0 );
+#if defined(__MINGW32__) || defined(__MINGW64__)
+ // No symlink support
+#else
auto link = __gnu_test::nonexistent_path();
create_symlink(p, link); // dangling symlink
ec = bad_ec;
VERIFY( n == 1 );
VERIFY( !exists(symlink_status(link)) ); // The symlink is removed, but
VERIFY( exists(p) ); // its target is not.
+#endif
const auto dir = __gnu_test::nonexistent_path();
create_directories(dir/"a/b/c");
namespace fs = std::experimental::filesystem;
+bool check(fs::space_info const& s)
+{
+ const std::uintmax_t err = -1;
+ return s.capacity != err || s.free != err || s.available != err;
+}
+
void
test01()
{
s = fs::space(root, ec);
VERIFY( !ec );
- s = fs::space(__gnu_test::nonexistent_path(), ec);
- VERIFY( ec );
- VERIFY( s.capacity == static_cast<uintmax_t>(-1) );
- VERIFY( s.free == static_cast<uintmax_t>(-1) );
- VERIFY( s.available == static_cast<uintmax_t>(-1) );
+ s = fs::space(__gnu_test::nonexistent_path()/".", ec);
+ if (ec)
+ VERIFY( ! check(s) );
+ else
+ VERIFY( check(s) );
}
void
test02()
{
fs::space_info s = fs::space(".");
+ VERIFY( check(s) );
VERIFY( s.capacity >= s.free );
}