diff options
author | Eric Fiselier <eric@efcs.ca> | 2018-02-04 02:43:32 +0000 |
---|---|---|
committer | Eric Fiselier <eric@efcs.ca> | 2018-02-04 02:43:32 +0000 |
commit | 0f8c8f59df057a85d6d49913ec9877c6d597785b (patch) | |
tree | b00dc4947430640171f3ac6482c33792fbe546b8 /libcxx/src | |
parent | e1c661f3444f676c8cff5031810ed482c5576bbd (diff) | |
download | bcm5719-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.cpp | 30 |
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); } |