summaryrefslogtreecommitdiff
path: root/source3/lib/recvfile.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2011-12-30 20:23:00 -0800
committerJeremy Allison <jra@samba.org>2011-12-30 20:23:00 -0800
commita5715420e37b98038fe8f2c3028e4c6938400eed (patch)
tree2f06da33a5bc0a9293d97a05e61bd9c6dc55ab32 /source3/lib/recvfile.c
parenta108eb4fdb565cc6580a15f3d9221f8b9f863fe6 (diff)
downloadsamba-a5715420e37b98038fe8f2c3028e4c6938400eed.tar.gz
samba-a5715420e37b98038fe8f2c3028e4c6938400eed.tar.bz2
samba-a5715420e37b98038fe8f2c3028e4c6938400eed.zip
Second part of fix for bug #8679 - recvfile code path using splice() on Linux leaves data in the pipe on short write.
Split out the functionality of drain_socket() into a separate function from default_sys_recvfile().
Diffstat (limited to 'source3/lib/recvfile.c')
-rw-r--r--source3/lib/recvfile.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c
index 5d1c0b2c55..31d9311498 100644
--- a/source3/lib/recvfile.c
+++ b/source3/lib/recvfile.c
@@ -242,9 +242,38 @@ ssize_t sys_recvfile(int fromfd,
/*****************************************************************
Throw away "count" bytes from the client socket.
+ Returns count or -1 on error.
*****************************************************************/
ssize_t drain_socket(int sockfd, size_t count)
{
- return default_sys_recvfile(sockfd, -1, (SMB_OFF_T)-1, count);
+ size_t total = 0;
+ size_t bufsize = MIN(TRANSFER_BUF_SIZE,count);
+ char *buffer = NULL;
+
+ if (count == 0) {
+ return 0;
+ }
+
+ buffer = SMB_MALLOC_ARRAY(char, bufsize);
+ if (buffer == NULL) {
+ return -1;
+ }
+
+ while (total < count) {
+ ssize_t read_ret;
+ size_t toread = MIN(bufsize,count - total);
+
+ /* Read from socket - ignore EINTR. */
+ read_ret = sys_read(sockfd, buffer, toread);
+ if (read_ret <= 0) {
+ /* EOF or socket error. */
+ free(buffer);
+ return -1;
+ }
+ total += read_ret;
+ }
+
+ free(buffer);
+ return count;
}