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
This commit is contained in:
Jonathan Wakely 2016-10-24 17:45:31 +01:00 committed by Jonathan Wakely
parent 38000825cd
commit b3dec9e57e
4 changed files with 105 additions and 9 deletions

View file

@ -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

View file

@ -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);

View file

@ -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

View file

@ -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();
}