From b0bc8bec29bce808253adf2a95b7fdb7d36a176f Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Fri, 30 Dec 2011 20:45:10 -0800 Subject: [PATCH] Third part of fix for bug #8679 - recvfile code path using splice() on Linux leaves data in the pipe on short write. Fix default_sys_recvfile() to correctly cope with short writes. Return the amount written. Return -1 and set errno if no data could be written. (cherry picked from commit 5e6263960aaf1a5f9993cb7bb5646d36ff92b9cc) (cherry picked from commit ec9b07e84e806705e22f0cf2eb527fed14efac55) --- source3/lib/recvfile.c | 39 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c index 449bdf3bcef..cc69d427d8f 100644 --- a/source3/lib/recvfile.c +++ b/source3/lib/recvfile.c @@ -29,16 +29,10 @@ * It's safe to make direct syscalls to lseek/write here * as we're below the Samba vfs layer. * - * If tofd is -1 we just drain the incoming socket of count - * bytes without writing to the outgoing fd. - * If a write fails we do the same (to cope with disk full) - * errors. - * * Returns -1 on short reads from fromfd (read error) * and sets errno. * * Returns number of bytes written to 'tofd' - * or thrown away if 'tofd == -1'. * return != count then sets errno. * Returns count if complete success. */ @@ -95,23 +89,26 @@ static ssize_t default_sys_recvfile(int fromfd, num_written = 0; - while (num_written < read_ret) { + /* Don't write any more after a write error. */ + while (tofd != -1 && (num_written < read_ret)) { ssize_t write_ret; - if (tofd == -1) { - write_ret = read_ret; - } else { - /* Write to file - ignore EINTR. */ - write_ret = sys_write(tofd, - buffer + num_written, - read_ret - num_written); - - if (write_ret <= 0) { - /* write error - stop writing. */ - tofd = -1; - saved_errno = errno; - continue; - } + /* Write to file - ignore EINTR. */ + write_ret = sys_write(tofd, + buffer + num_written, + read_ret - num_written); + + if (write_ret <= 0) { + /* write error - stop writing. */ + tofd = -1; + if (total_written == 0) { + /* Ensure we return + -1 if the first + write failed. */ + total_written = -1; + } + saved_errno = errno; + break; } num_written += (size_t)write_ret; -- 2.11.4.GIT