commit:     a3c87da25dc1944e6b7720e304318ae5474dff95
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Wed May 10 06:25:01 2017 +0000
Commit:     Brian Dolbec <dolsen <AT> gentoo <DOT> org>
CommitDate: Sun May 14 18:07:44 2017 +0000
URL:        https://gitweb.gentoo.org/proj/portage.git/commit/?id=a3c87da2

file_copy: fix lseek offset after EINTR (bug 618086)

Fix the lseek offset for the plain read/write loop to account
for buffered data that has not been written to to the output
file yet (due to previous interruption by EINTR). This code
only affects Linux 2.6.32 and earlier (newer kernels use
copy_file_range or sendfile).

X-Gentoo-bug: 618086
X-Gentoo-bug-url: https://bugs.gentoo.org/show_bug.cgi?id=618086
Acked-by: Brian Dolbec <dolsen <AT> gentoo.org>

 src/portage_util_file_copy_reflink_linux.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/src/portage_util_file_copy_reflink_linux.c 
b/src/portage_util_file_copy_reflink_linux.c
index 2fb17a0f5..4be9e0568 100644
--- a/src/portage_util_file_copy_reflink_linux.c
+++ b/src/portage_util_file_copy_reflink_linux.c
@@ -323,12 +323,14 @@ _reflink_linux_file_copy(PyObject *self, PyObject *args)
                 if (buf == NULL) {
                     error = errno;
 
-                /* For the read call, the fd_in file offset must be
-                 * exactly equal to offset_out. Use lseek to ensure
-                 * correct state, in case an EINTR retry caused it to
-                 * get out of sync somewhow.
+                /* For the read call, the fd_in file offset must be exactly
+                 * equal to offset_out + buf_bytes, where buf_bytes is the
+                 * amount of buffered data that has not been written to
+                 * to the output file yet. Use lseek to ensure correct state,
+                 * in case an EINTR retry caused it to get out of sync
+                 * somewhow.
                  */
-                } else if (lseek(fd_in, offset_out, SEEK_SET) < 0) {
+                } else if (lseek(fd_in, offset_out + buf_bytes, SEEK_SET) < 0) 
{
                     error = errno;
                 } else {
                     while (1) {
@@ -345,6 +347,7 @@ _reflink_linux_file_copy(PyObject *self, PyObject *args)
 
                             } else if (buf_bytes < 0) {
                                 error = errno;
+                                buf_bytes = 0;
                                 break;
                             }
                         }

Reply via email to