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:
parent
38000825cd
commit
b3dec9e57e
4 changed files with 105 additions and 9 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Add table
Reference in a new issue