summaryrefslogtreecommitdiffstats
path: root/libcxx/src
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2018-02-04 02:43:32 +0000
committerEric Fiselier <eric@efcs.ca>2018-02-04 02:43:32 +0000
commit0f8c8f59df057a85d6d49913ec9877c6d597785b (patch)
treeb00dc4947430640171f3ac6482c33792fbe546b8 /libcxx/src
parente1c661f3444f676c8cff5031810ed482c5576bbd (diff)
downloadbcm5719-llvm-0f8c8f59df057a85d6d49913ec9877c6d597785b.tar.gz
bcm5719-llvm-0f8c8f59df057a85d6d49913ec9877c6d597785b.zip
Address LWG 2849 and fix missing failure condition in copy_file.
Previously copy_file didn't handle the case where the input and output were the same file. llvm-svn: 324187
Diffstat (limited to 'libcxx/src')
-rw-r--r--libcxx/src/experimental/filesystem/operations.cpp30
1 files changed, 20 insertions, 10 deletions
diff --git a/libcxx/src/experimental/filesystem/operations.cpp b/libcxx/src/experimental/filesystem/operations.cpp
index 91aee6ffbcb..2bc28c21dcf 100644
--- a/libcxx/src/experimental/filesystem/operations.cpp
+++ b/libcxx/src/experimental/filesystem/operations.cpp
@@ -263,18 +263,22 @@ void __copy(const path& from, const path& to, copy_options options,
bool __copy_file(const path& from, const path& to, copy_options options,
std::error_code *ec)
{
- if (ec) ec->clear();
+ using StatT = struct ::stat;
+ if (ec)
+ ec->clear();
std::error_code m_ec;
- auto from_st = detail::posix_stat(from, &m_ec);
+ StatT from_stat;
+ auto from_st = detail::posix_stat(from, from_stat, &m_ec);
if (not is_regular_file(from_st)) {
- if (not m_ec)
- m_ec = make_error_code(errc::not_supported);
- set_or_throw(m_ec, ec, "copy_file", from, to);
- return false;
+ if (not m_ec)
+ m_ec = make_error_code(errc::not_supported);
+ set_or_throw(m_ec, ec, "copy_file", from, to);
+ return false;
}
- auto to_st = detail::posix_stat(to, &m_ec);
+ StatT to_stat;
+ auto to_st = detail::posix_stat(to, to_stat, &m_ec);
if (!status_known(to_st)) {
set_or_throw(m_ec, ec, "copy_file", from, to);
return false;
@@ -285,6 +289,11 @@ bool __copy_file(const path& from, const path& to, copy_options options,
set_or_throw(make_error_code(errc::not_supported), ec, "copy_file", from, to);
return false;
}
+ if (to_exists && detail::stat_equivalent(from_stat, to_stat)) {
+ set_or_throw(make_error_code(errc::file_exists), ec, "copy_file", from,
+ to);
+ return false;
+ }
if (to_exists && bool(copy_options::skip_existing & options)) {
return false;
}
@@ -302,8 +311,9 @@ bool __copy_file(const path& from, const path& to, copy_options options,
return detail::copy_file_impl(from, to, from_st.permissions(), ec);
}
else {
- set_or_throw(make_error_code(errc::file_exists), ec, "copy", from, to);
- return false;
+ set_or_throw(make_error_code(errc::file_exists), ec, "copy_file", from,
+ to);
+ return false;
}
_LIBCPP_UNREACHABLE();
@@ -443,7 +453,7 @@ bool __equivalent(const path& p1, const path& p2, std::error_code *ec)
if (!exists(s2))
return make_unsupported_error();
if (ec) ec->clear();
- return (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino);
+ return detail::stat_equivalent(st1, st2);
}
OpenPOWER on IntegriCloud