diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2016-10-24 17:45:31 +0100 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2016-10-24 17:45:31 +0100 |
commit | b3dec9e57e6960cae54187b7fa416052c8e32e19 (patch) | |
tree | 31de0b552bad0b485a556d5796112652b9f67fa2 /libstdc++-v3 | |
parent | 38000825cd37c3f132cd02edc4e8eb79aff4d3a6 (diff) | |
download | gcc-b3dec9e57e6960cae54187b7fa416052c8e32e19.zip gcc-b3dec9e57e6960cae54187b7fa416052c8e32e19.tar.gz gcc-b3dec9e57e6960cae54187b7fa416052c8e32e19.tar.bz2 |
Implement DR resolutions for filesystem::copy
* src/filesystem/ops.cc (do_copy_file): Return an error if either
source or destination is not a regular file.
(copy): Update comment to refer to LWG 2681. Implement 2682 and 2683
resolutions.
(read_symlink): Add missing ec.clear().
* testsuite/experimental/filesystem/operations/copy.cc: Update
expected behaviour for copying directories with create_symlinks.
Verify that error_code arguments are cleared if there's no error.
* testsuite/experimental/filesystem/operations/read_symlink.cc: New.
From-SVN: r241484
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 12 | ||||
-rw-r--r-- | libstdc++-v3/src/filesystem/ops.cc | 23 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc | 30 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/experimental/filesystem/operations/read_symlink.cc | 49 |
4 files changed, 105 insertions, 9 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 5937af9..112e941 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,15 @@ +2016-10-24 Jonathan Wakely <jwakely@redhat.com> + + * src/filesystem/ops.cc (do_copy_file): Return an error if either + source or destination is not a regular file. + (copy): Update comment to refer to LWG 2681. Implement 2682 and 2683 + resolutions. + (read_symlink): Add missing ec.clear(). + * testsuite/experimental/filesystem/operations/copy.cc: Update + expected behaviour for copying directories with create_symlinks. + Verify that error_code arguments are cleared if there's no error. + * testsuite/experimental/filesystem/operations/read_symlink.cc: New. + 2016-10-24 Ville Voutilainen <ville.voutilainen@gmail.com> Cross-port exception-safety and move fixes of std::any to diff --git a/libstdc++-v3/src/filesystem/ops.cc b/libstdc++-v3/src/filesystem/ops.cc index 2286e22..6f76053 100644 --- a/libstdc++-v3/src/filesystem/ops.cc +++ b/libstdc++-v3/src/filesystem/ops.cc @@ -361,6 +361,11 @@ namespace from_st = &st2; } f = make_file_status(*from_st); + if (!is_regular_file(f)) + { + ec = std::make_error_code(std::errc::not_supported); + return false; + } using opts = fs::copy_options; @@ -392,6 +397,11 @@ namespace ec = std::make_error_code(std::errc::file_exists); return false; } + else if (!is_regular_file(t)) + { + ec = std::make_error_code(std::errc::not_supported); + return false; + } } struct CloseFD { @@ -489,7 +499,8 @@ fs::copy(const path& from, const path& to, copy_options options, file_status f, t; stat_type from_st, to_st; - // N4099 doesn't check copy_symlinks here, but I think that's a defect. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2681. filesystem::copy() cannot copy symlinks if (use_lstat || copy_symlinks ? ::lstat(from.c_str(), &from_st) : ::stat(from.c_str(), &from_st)) @@ -556,6 +567,10 @@ fs::copy(const path& from, const path& to, copy_options options, do_copy_file(from, to, options, &from_st, ptr, ec); } } + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2682. filesystem::copy() won't create a symlink to a directory + else if (is_directory(f) && create_symlinks) + ec = std::make_error_code(errc::is_a_directory); else if (is_directory(f) && (is_set(options, copy_options::recursive) || options == copy_options::none)) { @@ -568,7 +583,10 @@ fs::copy(const path& from, const path& to, copy_options options, for (const directory_entry& x : directory_iterator(from)) copy(x.path(), to/x.path().filename(), options, ec); } - // "Otherwise no effects." (should ec.clear() be called?) + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2683. filesystem::copy() says "no effects" + else + ec.clear(); } bool @@ -1168,6 +1186,7 @@ fs::path fs::read_symlink(const path& p, error_code& ec) ec.assign(errno, std::generic_category()); return {}; } + ec.clear(); return path{buf.data(), buf.data()+len}; #else ec = std::make_error_code(std::errc::not_supported); diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc index 0d112a2..2cfb1c1 100644 --- a/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/copy.cc @@ -22,7 +22,6 @@ // 15.3 Copy [fs.op.copy] #include <experimental/filesystem> -#include <fstream> #include <testsuite_fs.h> #include <testsuite_hooks.h> @@ -43,14 +42,25 @@ test01() fs::copy(".", ".", fs::copy_options::none, ec); VERIFY( ec ); - std::ofstream{p.native()}; + __gnu_test::scoped_file f(p); VERIFY( fs::is_directory(".") ); VERIFY( fs::is_regular_file(p) ); ec.clear(); fs::copy(".", p, fs::copy_options::none, ec); VERIFY( ec ); - remove(p, ec); + auto to = __gnu_test::nonexistent_path(); + ec.clear(); + auto opts = fs::copy_options::create_symlinks; + fs::copy("/", to, opts, ec); + VERIFY( ec == std::make_error_code(std::errc::is_a_directory) ); + VERIFY( !exists(to) ); + + ec.clear(); + opts != fs::copy_options::recursive; + fs::copy("/", to, opts, ec); + VERIFY( ec == std::make_error_code(std::errc::is_a_directory) ); + VERIFY( !exists(to) ); } // Test is_symlink(f) case. @@ -59,29 +69,35 @@ test02() { auto from = __gnu_test::nonexistent_path(); auto to = __gnu_test::nonexistent_path(); - std::error_code ec; + std::error_code ec, bad = std::make_error_code(std::errc::invalid_argument); + ec = bad; fs::create_symlink(".", from, ec); VERIFY( !ec ); VERIFY( fs::exists(from) ); + ec = bad; fs::copy(from, to, fs::copy_options::skip_symlinks, ec); VERIFY( !ec ); VERIFY( !fs::exists(to) ); + ec = bad; fs::copy(from, to, fs::copy_options::skip_symlinks, ec); VERIFY( !ec ); VERIFY( !fs::exists(to) ); + ec = bad; fs::copy(from, to, fs::copy_options::skip_symlinks|fs::copy_options::copy_symlinks, ec); VERIFY( !ec ); VERIFY( !fs::exists(to) ); + ec = bad; fs::copy(from, to, fs::copy_options::copy_symlinks, ec); VERIFY( !ec ); VERIFY( fs::exists(to) ); + VERIFY( is_symlink(to) ); fs::copy(from, to, fs::copy_options::copy_symlinks, ec); VERIFY( ec ); @@ -129,10 +145,10 @@ void test05() { auto to = __gnu_test::nonexistent_path(); - std::error_code ec; + std::error_code ec = std::make_error_code(std::errc::invalid_argument); - fs::copy("/", to, fs::copy_options::create_symlinks, ec); - VERIFY( !ec ); + fs::copy("/", to, fs::copy_options::copy_symlinks, ec); + VERIFY( !ec ); // Previous value should be cleared (LWG 2683) } int diff --git a/libstdc++-v3/testsuite/experimental/filesystem/operations/read_symlink.cc b/libstdc++-v3/testsuite/experimental/filesystem/operations/read_symlink.cc new file mode 100644 index 0000000..c4137bd --- /dev/null +++ b/libstdc++-v3/testsuite/experimental/filesystem/operations/read_symlink.cc @@ -0,0 +1,49 @@ +// Copyright (C) 2016 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 "-lstdc++fs" } +// { dg-do run { target c++11 } } +// { dg-require-filesystem-ts "" } + +#include <experimental/filesystem> +#include <testsuite_hooks.h> +#include <testsuite_fs.h> + +namespace fs = std::experimental::filesystem; + +void +test01() +{ + auto p = __gnu_test::nonexistent_path(); + std::error_code ec; + + read_symlink(p, ec); + VERIFY( ec ); + + fs::path tgt = "."; + create_symlink(tgt, p); + + auto result = read_symlink(p, ec); + VERIFY( !ec ); + VERIFY( result == tgt ); +} + +int +main() +{ + test01(); +} |