PR libstdc++/83279 handle sendfile not copying entire file
Backport from mainline 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. From-SVN: r256290
This commit is contained in:
parent
826137607d
commit
0070e3297e
@ -1,5 +1,12 @@
|
|||||||
2018-01-05 Jonathan Wakely <jwakely@redhat.com>
|
2018-01-05 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
Backport from mainline
|
||||||
|
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.
|
||||||
|
|
||||||
Backport from mainline
|
Backport from mainline
|
||||||
2018-01-04 Jonathan Wakely <jwakely@redhat.com>
|
2018-01-04 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
@ -443,19 +443,57 @@ namespace
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t count = from_st->st_size;
|
||||||
#ifdef _GLIBCXX_USE_SENDFILE
|
#ifdef _GLIBCXX_USE_SENDFILE
|
||||||
off_t offset = 0;
|
off_t offset = 0;
|
||||||
const auto n = ::sendfile(out.fd, in.fd, &offset, from_st->st_size);
|
ssize_t n = ::sendfile(out.fd, in.fd, &offset, count);
|
||||||
if (n < 0 && (errno == ENOSYS || errno == EINVAL))
|
if (n < 0 && errno != ENOSYS && errno != EINVAL)
|
||||||
{
|
{
|
||||||
#endif
|
ec.assign(errno, std::generic_category());
|
||||||
__gnu_cxx::stdio_filebuf<char> sbin(in.fd, std::ios::in);
|
return false;
|
||||||
__gnu_cxx::stdio_filebuf<char> sbout(out.fd, std::ios::out);
|
}
|
||||||
|
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
|
||||||
|
|
||||||
|
using std::ios;
|
||||||
|
__gnu_cxx::stdio_filebuf<char> sbin(in.fd, ios::in|ios::binary);
|
||||||
|
__gnu_cxx::stdio_filebuf<char> sbout(out.fd, ios::out|ios::binary);
|
||||||
|
|
||||||
if (sbin.is_open())
|
if (sbin.is_open())
|
||||||
in.fd = -1;
|
in.fd = -1;
|
||||||
if (sbout.is_open())
|
if (sbout.is_open())
|
||||||
out.fd = -1;
|
out.fd = -1;
|
||||||
if (from_st->st_size && !(std::ostream(&sbout) << &sbin))
|
|
||||||
|
#ifdef _GLIBCXX_USE_SENDFILE
|
||||||
|
if (n != 0)
|
||||||
|
{
|
||||||
|
if (n < 0)
|
||||||
|
n = 0;
|
||||||
|
|
||||||
|
const auto p1 = sbin.pubseekoff(n, ios::beg, ios::in);
|
||||||
|
const auto p2 = sbout.pubseekoff(n, ios::beg, ios::out);
|
||||||
|
|
||||||
|
const std::streampos errpos(std::streamoff(-1));
|
||||||
|
if (p1 == errpos || p2 == errpos)
|
||||||
|
{
|
||||||
|
ec = std::make_error_code(std::errc::io_error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (count && !(std::ostream(&sbout) << &sbin))
|
||||||
{
|
{
|
||||||
ec = std::make_error_code(std::errc::io_error);
|
ec = std::make_error_code(std::errc::io_error);
|
||||||
return false;
|
return false;
|
||||||
@ -465,26 +503,8 @@ namespace
|
|||||||
ec.assign(errno, std::generic_category());
|
ec.assign(errno, std::generic_category());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ec.clear();
|
ec.clear();
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
#ifdef _GLIBCXX_USE_SENDFILE
|
|
||||||
}
|
|
||||||
if (n != from_st->st_size)
|
|
||||||
{
|
|
||||||
ec.assign(errno, std::generic_category());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!out.close() || !in.close())
|
|
||||||
{
|
|
||||||
ec.assign(errno, std::generic_category());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ec.clear();
|
|
||||||
return true;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user