summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2011-12-30 20:45:10 -0800
committerJeremy Allison <jra@samba.org>2011-12-30 20:45:10 -0800
commit5e6263960aaf1a5f9993cb7bb5646d36ff92b9cc (patch)
tree1cb1ca464ce0b656769855bf51f13f2443e31551
parenta5715420e37b98038fe8f2c3028e4c6938400eed (diff)
downloadsamba-5e6263960aaf1a5f9993cb7bb5646d36ff92b9cc.tar.gz
samba-5e6263960aaf1a5f9993cb7bb5646d36ff92b9cc.tar.bz2
samba-5e6263960aaf1a5f9993cb7bb5646d36ff92b9cc.zip
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.
-rw-r--r--source3/lib/recvfile.c39
1 files changed, 18 insertions, 21 deletions
diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c
index 31d9311498..c74cdd5a67 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;