From: Jeremy Allison Date: Sat, 31 Dec 2011 04:45:10 +0000 (-0800) Subject: Third part of fix for bug #8679 - recvfile code path using splice() on Linux leaves... X-Git-Tag: tevent-0.9.15~570 X-Git-Url: http://git.samba.org/?p=ddiss%2Fsamba.git;a=commitdiff_plain;h=5e6263960aaf1a5f9993cb7bb5646d36ff92b9cc 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. --- diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c index 31d9311498d..c74cdd5a67d 100644 --- a/source3/lib/recvfile.c +++ b/source3/lib/recvfile.c @@ -30,16 +30,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. */ @@ -96,23 +90,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;