diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2017-12-14 21:49:03 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2017-12-14 21:49:03 +0000 |
commit | c49bef17fd1e7afa1255a875aa23773960c187e9 (patch) | |
tree | 2f3ae438d660cd698acd48638d55e64091207e2a /libstdc++-v3 | |
parent | 83fd5e73b3c16296e0d7ba54f6c547e01c7eae7b (diff) | |
download | gcc-c49bef17fd1e7afa1255a875aa23773960c187e9.zip gcc-c49bef17fd1e7afa1255a875aa23773960c187e9.tar.gz gcc-c49bef17fd1e7afa1255a875aa23773960c187e9.tar.bz2 |
PR libstdc++/83279 handle sendfile not copying entire file
PR libstdc++/83279
* src/filesystem/std-ops.cc (do_copy_file): Handle sendfile not
copying entire file.
From-SVN: r255666
Diffstat (limited to 'libstdc++-v3')
-rw-r--r-- | libstdc++-v3/ChangeLog | 4 | ||||
-rw-r--r-- | libstdc++-v3/src/filesystem/std-ops.cc | 67 |
2 files changed, 49 insertions, 22 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 9f2eff1..1b4c6e2 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,9 @@ 2017-12-14 Jonathan Wakely <jwakely@redhat.com> + PR libstdc++/83279 + * src/filesystem/std-ops.cc (do_copy_file): Handle sendfile not + copying entire file. + PR libstdc++/68519 * include/std/condition_variable (condition_variable::wait_for): Convert duration to native clock's duration before addition. diff --git a/libstdc++-v3/src/filesystem/std-ops.cc b/libstdc++-v3/src/filesystem/std-ops.cc index fa5e19a..a15857c 100644 --- a/libstdc++-v3/src/filesystem/std-ops.cc +++ b/libstdc++-v3/src/filesystem/std-ops.cc @@ -382,48 +382,71 @@ fs::do_copy_file(const char* from, const char* to, return false; } + ssize_t n = 0; + size_t count = from_st->st_size; #ifdef _GLIBCXX_USE_SENDFILE - off_t offset = 0; - const auto n = ::sendfile(out.fd, in.fd, &offset, from_st->st_size); - if (n < 0 && (errno == ENOSYS || errno == EINVAL)) + n = ::sendfile(out.fd, in.fd, nullptr, count); + if (n < 0 && errno != ENOSYS && errno != EINVAL) { + ec.assign(errno, std::generic_category()); + return false; + } + if ((size_t)n == count) + { + if (!out.close() || !in.close()) + { + ec.assign(errno, std::generic_category()); + return false; + } + ec.clear(); + return true; + } + else if (n > 0) + count -= n; #endif // _GLIBCXX_USE_SENDFILE - __gnu_cxx::stdio_filebuf<char> sbin(in.fd, std::ios::in); - __gnu_cxx::stdio_filebuf<char> sbout(out.fd, std::ios::out); - if (sbin.is_open()) - in.fd = -1; - if (sbout.is_open()) - out.fd = -1; - if (from_st->st_size && !(std::ostream(&sbout) << &sbin)) + + __gnu_cxx::stdio_filebuf<char> sbin(in.fd, std::ios::in); + __gnu_cxx::stdio_filebuf<char> sbout(out.fd, std::ios::out); + + if (sbin.is_open()) + in.fd = -1; + if (sbout.is_open()) + out.fd = -1; + + const std::streampos errpos(std::streamoff(-1)); + + if (n < 0) + { + auto p1 = sbin.pubseekoff(0, std::ios_base::beg, std::ios_base::in); + auto p2 = sbout.pubseekoff(0, std::ios_base::beg, std::ios_base::out); + if (p1 == errpos || p2 == errpos) { ec = std::make_error_code(std::errc::io_error); return false; } - if (!sbout.close() || !sbin.close()) + } + else if (n > 0) + { + auto p = sbout.pubseekoff(n, std::ios_base::beg, std::ios_base::out); + if (p == errpos) { - ec.assign(errno, std::generic_category()); + ec = std::make_error_code(std::errc::io_error); return false; } - - ec.clear(); - return true; - -#ifdef _GLIBCXX_USE_SENDFILE } - if (n != from_st->st_size) + + if (count && !(std::ostream(&sbout) << &sbin)) { - ec.assign(errno, std::generic_category()); + ec = std::make_error_code(std::errc::io_error); return false; } - if (!out.close() || !in.close()) + if (!sbout.close() || !sbin.close()) { ec.assign(errno, std::generic_category()); return false; } - ec.clear(); return true; -#endif // _GLIBCXX_USE_SENDFILE } #endif // NEED_DO_COPY_FILE #endif // _GLIBCXX_HAVE_SYS_STAT_H |