aboutsummaryrefslogtreecommitdiff
path: root/libstdc++-v3
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2017-12-14 21:49:03 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2017-12-14 21:49:03 +0000
commitc49bef17fd1e7afa1255a875aa23773960c187e9 (patch)
tree2f3ae438d660cd698acd48638d55e64091207e2a /libstdc++-v3
parent83fd5e73b3c16296e0d7ba54f6c547e01c7eae7b (diff)
downloadgcc-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/ChangeLog4
-rw-r--r--libstdc++-v3/src/filesystem/std-ops.cc67
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