Initial recvfile VFS change

Jeremy Allison jra at samba.org
Tue Oct 30 00:54:34 GMT 2007


Here's the first addition of a VFS recvfile call,
API is :

ssize_t sys_recvfile(int fromfd,
                        int tofd,
                        SMB_OFF_T offset,
                        size_t count)

designed to make adding a zero-copy write
path from the socket layer to the filesystem
work in Samba (3.2.x). The goal is for any
non-chained, non-signed writeX calls over a
user defined size (8k ? 16K ?) use the splice()
system call or equivalent.

Jeremy.
-------------- next part --------------
>From bfbdb6324c5d13bfde8b742e9c5a0e0c9092bd86 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 29 Oct 2007 17:16:13 -0700
Subject: Add in the recvfile entry to the VFS layer with a default
 implementation. Needed for the zero-copy write code.
 Jeremy.

---
 examples/VFS/skel_opaque.c      |   13 +++++++++++++
 examples/VFS/skel_transparent.c |   12 ++++++++++++
 source/Makefile.in              |    2 +-
 source/include/smbprofile.h     |    4 ++++
 source/include/vfs.h            |    4 ++++
 source/include/vfs_macros.h     |    3 +++
 source/modules/vfs_default.c    |   17 +++++++++++++++++
 source/modules/vfs_full_audit.c |   22 ++++++++++++++++++++++
 source/profile/profile.c        |    1 +
 9 files changed, 77 insertions(+), 1 deletions(-)

diff --git a/examples/VFS/skel_opaque.c b/examples/VFS/skel_opaque.c
index 244c02e..fd4b206 100644
--- a/examples/VFS/skel_opaque.c
+++ b/examples/VFS/skel_opaque.c
@@ -155,6 +155,17 @@ static SMB_OFF_T skel_lseek(vfs_handle_struct *handle, files_struct *fsp, int fi
 	return vfswrap_lseek(NULL, fsp, filedes, offset, whence);
 }
 
+static ssize_t skel_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr,
+		                        SMB_OFF_T offset, size_t n)
+{
+	return vfswrap_sendfile(NULL, tofd, fsp, fromfd, hdr, offset, n);
+}
+
+static ssize_t skel_recvfile(vfs_handle_struct *handle, int fromfd, files_struct *fsp, int tofd, SMB_OFF_T offset, size_t n)
+{
+	return vfswrap_recvfile(NULL, fromfd, fsp, tofd, offset, n);
+}
+
 static int skel_rename(vfs_handle_struct *handle,  const char *oldname, const char *newname)
 {
 	return vfswrap_rename(NULL,  oldname, newname);
@@ -603,6 +614,8 @@ static vfs_op_tuple skel_op_tuples[] = {
 	{SMB_VFS_OP(skel_write),			SMB_VFS_OP_WRITE,		SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(skel_pwrite),			SMB_VFS_OP_PWRITE,		SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(skel_lseek),			SMB_VFS_OP_LSEEK,		SMB_VFS_LAYER_OPAQUE},
+	{SMB_VFS_OP(skel_sendfile),			SMB_VFS_OP_SENDFILE,		SMB_VFS_LAYER_OPAQUE},
+	{SMB_VFS_OP(skel_recvfile),			SMB_VFS_OP_RECVFLE,		SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(skel_rename),			SMB_VFS_OP_RENAME,		SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(skel_fsync),			SMB_VFS_OP_FSYNC,		SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(skel_stat),				SMB_VFS_OP_STAT,		SMB_VFS_LAYER_OPAQUE},
diff --git a/examples/VFS/skel_transparent.c b/examples/VFS/skel_transparent.c
index 66ea112..2512f4d 100644
--- a/examples/VFS/skel_transparent.c
+++ b/examples/VFS/skel_transparent.c
@@ -149,6 +149,16 @@ static SMB_OFF_T skel_lseek(vfs_handle_struct *handle, files_struct *fsp, int fi
 	return SMB_VFS_NEXT_LSEEK(handle, fsp, filedes, offset, whence);
 }
 
+static ssize_t skel_sendfile(vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *hdr, SMB_OFF_T offset, size_t n)
+{
+	return SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, hdr, offset, n);
+}
+
+static ssize_t skel_recvfile(vfs_handle_struct *handle, int fromfd, files_struct *fsp, int tofd, SMB_OFF_T offset, size_t n)
+{
+	return SMB_VFS_NEXT_RECVFILE(handle, fromfd, fsp, tofd, offset, n);
+}
+
 static int skel_rename(vfs_handle_struct *handle,  const char *oldname, const char *newname)
 {
 	return SMB_VFS_NEXT_RENAME(handle, oldname, newname);
@@ -561,6 +571,8 @@ static vfs_op_tuple skel_op_tuples[] = {
 	{SMB_VFS_OP(skel_read),				SMB_VFS_OP_READ,		SMB_VFS_LAYER_TRANSPARENT},
 	{SMB_VFS_OP(skel_write),			SMB_VFS_OP_WRITE,		SMB_VFS_LAYER_TRANSPARENT},
 	{SMB_VFS_OP(skel_lseek),			SMB_VFS_OP_LSEEK,		SMB_VFS_LAYER_TRANSPARENT},
+	{SMB_VFS_OP(skel_sendfile),			SMB_VFS_OP_SENDFILE,		SMB_VFS_LAYER_TRANSPARENT},
+	{SMB_VFS_OP(skel_recvfile),			SMB_VFS_OP_RECVFILE,		SMB_VFS_LAYER_TRANSPARENT},
 	{SMB_VFS_OP(skel_rename),			SMB_VFS_OP_RENAME,		SMB_VFS_LAYER_TRANSPARENT},
 	{SMB_VFS_OP(skel_fsync),			SMB_VFS_OP_FSYNC,		SMB_VFS_LAYER_TRANSPARENT},
 	{SMB_VFS_OP(skel_stat),				SMB_VFS_OP_STAT,		SMB_VFS_LAYER_TRANSPARENT},
diff --git a/source/Makefile.in b/source/Makefile.in
index 98fd8f8..a1da65a 100644
--- a/source/Makefile.in
+++ b/source/Makefile.in
@@ -275,7 +275,7 @@ LIB_WITHOUT_PROTO_OBJ = $(LIBREPLACE_OBJ) $(SOCKET_WRAPPER_OBJ) $(TALLOC_OBJ) \
 LIB_WITH_PROTO_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
 	  lib/interface.o lib/md4.o \
 	  lib/pidfile.o \
-	  lib/signal.o lib/system.o lib/sendfile.o lib/time.o \
+	  lib/signal.o lib/system.o lib/sendfile.o lib/recvfile.o lib/time.o \
 	  lib/ufc.o lib/genrand.o lib/username.o \
 	  lib/util_pw.o lib/access.o lib/smbrun.o \
 	  lib/bitmap.o lib/crc32.o lib/dprintf.o \
diff --git a/source/include/smbprofile.h b/source/include/smbprofile.h
index c898155..acd8460 100644
--- a/source/include/smbprofile.h
+++ b/source/include/smbprofile.h
@@ -103,6 +103,10 @@ enum profile_stats_values
 #define syscall_sendfile_count __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, count)
 #define syscall_sendfile_time __profile_stats_value(PR_VALUE_SYSCALL_SENDFILE, time)
 
+	PR_VALUE_SYSCALL_RECVFILE,
+#define syscall_recvfile_count __profile_stats_value(PR_VALUE_SYSCALL_RECVFILE, count)
+#define syscall_recvfile_time __profile_stats_value(PR_VALUE_SYSCALL_RECVFILE, time)
+
 	PR_VALUE_SYSCALL_RENAME,
 #define syscall_rename_count __profile_stats_value(PR_VALUE_SYSCALL_RENAME, count)
 #define syscall_rename_time __profile_stats_value(PR_VALUE_SYSCALL_RENAME, time)
diff --git a/source/include/vfs.h b/source/include/vfs.h
index 9dadacb..03af04d 100644
--- a/source/include/vfs.h
+++ b/source/include/vfs.h
@@ -73,6 +73,7 @@
 /* Leave at 22 - not yet released. But change set_nt_acl to return an NTSTATUS. jra. */
 /* Leave at 22 - not yet released. Add file_id_create operation. --metze */
 /* Leave at 22 - not yet released. Change all BOOL parameters (int) to bool. jra. */
+/* Leave at 22 - not yet released. Added recvfile. */
 #define SMB_VFS_INTERFACE_VERSION 22
 
 
@@ -138,6 +139,7 @@ typedef enum _vfs_op_type {
 	SMB_VFS_OP_PWRITE,
 	SMB_VFS_OP_LSEEK,
 	SMB_VFS_OP_SENDFILE,
+	SMB_VFS_OP_RECVFILE,
 	SMB_VFS_OP_RENAME,
 	SMB_VFS_OP_FSYNC,
 	SMB_VFS_OP_STAT,
@@ -266,6 +268,7 @@ struct vfs_ops {
 		ssize_t (*pwrite)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, const void *data, size_t n, SMB_OFF_T offset);
 		SMB_OFF_T (*lseek)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd, SMB_OFF_T offset, int whence);
 		ssize_t (*sendfile)(struct vfs_handle_struct *handle, int tofd, files_struct *fsp, int fromfd, const DATA_BLOB *header, SMB_OFF_T offset, size_t count);
+		ssize_t (*recvfile)(struct vfs_handle_struct *handle, int fromfd, files_struct *fsp, int tofd, SMB_OFF_T offset, size_t count);
 		int (*rename)(struct vfs_handle_struct *handle, const char *oldname, const char *newname);
 		int (*fsync)(struct vfs_handle_struct *handle, struct files_struct *fsp, int fd);
 		int (*stat)(struct vfs_handle_struct *handle, const char *fname, SMB_STRUCT_STAT *sbuf);
@@ -392,6 +395,7 @@ struct vfs_ops {
 		struct vfs_handle_struct *pwrite;
 		struct vfs_handle_struct *lseek;
 		struct vfs_handle_struct *sendfile;
+		struct vfs_handle_struct *recvfile;
 		struct vfs_handle_struct *rename;
 		struct vfs_handle_struct *fsync;
 		struct vfs_handle_struct *stat;
diff --git a/source/include/vfs_macros.h b/source/include/vfs_macros.h
index 7e161c3..cc7780f 100644
--- a/source/include/vfs_macros.h
+++ b/source/include/vfs_macros.h
@@ -54,6 +54,7 @@
 #define SMB_VFS_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs.ops.pwrite((fsp)->conn->vfs.handles.pwrite, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs.ops.lseek((fsp)->conn->vfs.handles.lseek, (fsp), (fd), (offset), (whence)))
 #define SMB_VFS_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs.ops.sendfile((fsp)->conn->vfs.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
+#define SMB_VFS_RECVFILE(fromfd, fsp, tofd, offset, count) ((fsp)->conn->vfs.ops.recvfile((fsp)->conn->vfs.handles.recvfile, (fromfd), (fsp), (tofd), (offset), (count)))
 #define SMB_VFS_RENAME(conn, old, new) ((conn)->vfs.ops.rename((conn)->vfs.handles.rename, (old), (new)))
 #define SMB_VFS_FSYNC(fsp, fd) ((fsp)->conn->vfs.ops.fsync((fsp)->conn->vfs.handles.fsync, (fsp), (fd)))
 #define SMB_VFS_STAT(conn, fname, sbuf) ((conn)->vfs.ops.stat((conn)->vfs.handles.stat, (fname), (sbuf)))
@@ -172,6 +173,7 @@
 #define SMB_VFS_OPAQUE_PWRITE(fsp, fd, data, n, off) ((fsp)->conn->vfs_opaque.ops.pwrite((fsp)->conn->vfs_opaque.handles.pwrite, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_OPAQUE_LSEEK(fsp, fd, offset, whence) ((fsp)->conn->vfs_opaque.ops.lseek((fsp)->conn->vfs_opaque.handles.lseek, (fsp), (fd), (offset), (whence)))
 #define SMB_VFS_OPAQUE_SENDFILE(tofd, fsp, fromfd, header, offset, count) ((fsp)->conn->vfs_opaque.ops.sendfile((fsp)->conn->vfs_opaque.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
+#define SMB_VFS_OPAQUE_RECVFILE(fromfd, fsp, tofd, offset, count) ((fsp)->conn->vfs_opaque.ops.recvfile((fsp)->conn->vfs_opaque.handles.recvfile, (fromfd), (fsp), (tofd), (offset), (count)))
 #define SMB_VFS_OPAQUE_RENAME(conn, old, new) ((conn)->vfs_opaque.ops.rename((conn)->vfs_opaque.handles.rename, (old), (new)))
 #define SMB_VFS_OPAQUE_FSYNC(fsp, fd) ((fsp)->conn->vfs_opaque.ops.fsync((fsp)->conn->vfs_opaque.handles.fsync, (fsp), (fd)))
 #define SMB_VFS_OPAQUE_STAT(conn, fname, sbuf) ((conn)->vfs_opaque.ops.stat((conn)->vfs_opaque.handles.stat, (fname), (sbuf)))
@@ -291,6 +293,7 @@
 #define SMB_VFS_NEXT_PWRITE(handle, fsp, fd, data, n, off) ((handle)->vfs_next.ops.pwrite((handle)->vfs_next.handles.pwrite, (fsp), (fd), (data), (n), (off)))
 #define SMB_VFS_NEXT_LSEEK(handle, fsp, fd, offset, whence) ((handle)->vfs_next.ops.lseek((handle)->vfs_next.handles.lseek, (fsp), (fd), (offset), (whence)))
 #define SMB_VFS_NEXT_SENDFILE(handle, tofd, fsp, fromfd, header, offset, count) ((handle)->vfs_next.ops.sendfile((handle)->vfs_next.handles.sendfile, (tofd), (fsp), (fromfd), (header), (offset), (count)))
+#define SMB_VFS_NEXT_RECVFILE(handle, fromfd, fsp, tofd, offset, count) ((handle)->vfs_next.ops.recvfile((handle)->vfs_next.handles.recvfile, (fromfd), (fsp), (tofd), (offset), (count)))
 #define SMB_VFS_NEXT_RENAME(handle, old, new) ((handle)->vfs_next.ops.rename((handle)->vfs_next.handles.rename, (old), (new)))
 #define SMB_VFS_NEXT_FSYNC(handle, fsp, fd) ((handle)->vfs_next.ops.fsync((handle)->vfs_next.handles.fsync, (fsp), (fd)))
 #define SMB_VFS_NEXT_STAT(handle, fname, sbuf) ((handle)->vfs_next.ops.stat((handle)->vfs_next.handles.stat, (fname), (sbuf)))
diff --git a/source/modules/vfs_default.c b/source/modules/vfs_default.c
index a3bb61d..8c2bbfe 100644
--- a/source/modules/vfs_default.c
+++ b/source/modules/vfs_default.c
@@ -348,6 +348,21 @@ static ssize_t vfswrap_sendfile(vfs_handle_struct *handle, int tofd, files_struc
 	return result;
 }
 
+static ssize_t vfswrap_recvfile(vfs_handle_struct *handle,
+			int fromfd,
+			files_struct *fsp,
+			int tofd,
+			SMB_OFF_T offset,
+			size_t n)
+{
+	ssize_t result;
+
+	START_PROFILE_BYTES(syscall_recvfile, n);
+	result = sys_recvfile(fromfd, tofd, offset, n);
+	END_PROFILE(syscall_recvfile);
+	return result;
+}
+
 /*********************************************************
  For rename across filesystems Patch from Warren Birnbaum
  <warrenb at hpcvscdp.cv.hp.com>
@@ -1263,6 +1278,8 @@ static vfs_op_tuple vfs_default_ops[] = {
 	 SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(vfswrap_sendfile),	SMB_VFS_OP_SENDFILE,
 	 SMB_VFS_LAYER_OPAQUE},
+	{SMB_VFS_OP(vfswrap_recvfile),	SMB_VFS_OP_RECVFILE,
+	 SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(vfswrap_rename),	SMB_VFS_OP_RENAME,
 	 SMB_VFS_LAYER_OPAQUE},
 	{SMB_VFS_OP(vfswrap_fsync),	SMB_VFS_OP_FSYNC,
diff --git a/source/modules/vfs_full_audit.c b/source/modules/vfs_full_audit.c
index df49c86..c8a82e3 100644
--- a/source/modules/vfs_full_audit.c
+++ b/source/modules/vfs_full_audit.c
@@ -127,6 +127,10 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd,
 			      files_struct *fsp, int fromfd,
 			      const DATA_BLOB *hdr, SMB_OFF_T offset,
 			      size_t n);
+static ssize_t smb_full_audit_recvfile(vfs_handle_struct *handle, int fromfd,
+			      files_struct *fsp, int tofd,
+			      SMB_OFF_T offset,
+			      size_t n);
 static int smb_full_audit_rename(vfs_handle_struct *handle,
 			const char *oldname, const char *newname);
 static int smb_full_audit_fsync(vfs_handle_struct *handle, files_struct *fsp, int fd);
@@ -363,6 +367,8 @@ static vfs_op_tuple audit_op_tuples[] = {
 	 SMB_VFS_LAYER_LOGGER},
 	{SMB_VFS_OP(smb_full_audit_sendfile),	SMB_VFS_OP_SENDFILE,
 	 SMB_VFS_LAYER_LOGGER},
+	{SMB_VFS_OP(smb_full_audit_recvfile),	SMB_VFS_OP_RECVFILE,
+	 SMB_VFS_LAYER_LOGGER},
 	{SMB_VFS_OP(smb_full_audit_rename),	SMB_VFS_OP_RENAME,
 	 SMB_VFS_LAYER_LOGGER},
 	{SMB_VFS_OP(smb_full_audit_fsync),	SMB_VFS_OP_FSYNC,
@@ -1145,6 +1151,22 @@ static ssize_t smb_full_audit_sendfile(vfs_handle_struct *handle, int tofd,
 	return result;
 }
 
+static ssize_t smb_full_audit_recvfile(vfs_handle_struct *handle, int fromfd,
+			      files_struct *fsp, int tofd,
+			      SMB_OFF_T offset,
+			      size_t n)
+{
+	ssize_t result;
+
+	result = SMB_VFS_NEXT_RECVFILE(handle, fromfd, fsp, tofd,
+				       offset, n);
+
+	do_log(SMB_VFS_OP_RECVFILE, (result >= 0), handle,
+	       "%s", fsp->fsp_name);
+
+	return result;
+}
+
 static int smb_full_audit_rename(vfs_handle_struct *handle,
 			const char *oldname, const char *newname)
 {
diff --git a/source/profile/profile.c b/source/profile/profile.c
index 50751d5..e9c7c7b 100644
--- a/source/profile/profile.c
+++ b/source/profile/profile.c
@@ -297,6 +297,7 @@ bool profile_setup(struct messaging_context *msg_ctx, bool rdonly)
 	    "syscall_pwrite",		/* PR_VALUE_SYSCALL_PWRITE */
 	    "syscall_lseek",		/* PR_VALUE_SYSCALL_LSEEK */
 	    "syscall_sendfile",		/* PR_VALUE_SYSCALL_SENDFILE */
+	    "syscall_recvfile",		/* PR_VALUE_SYSCALL_RECVFILE */
 	    "syscall_rename",		/* PR_VALUE_SYSCALL_RENAME */
 	    "syscall_fsync",		/* PR_VALUE_SYSCALL_FSYNC */
 	    "syscall_stat",		/* PR_VALUE_SYSCALL_STAT */
-- 
1.5.3


>From d5886218e53910b7015e6f13bc634e1bf338565a Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra at samba.org>
Date: Mon, 29 Oct 2007 17:17:16 -0700
Subject: Forgot to add recvfile.c
 Jeremy.

---
 source/lib/recvfile.c |  158 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 158 insertions(+), 0 deletions(-)
 create mode 100644 source/lib/recvfile.c

diff --git a/source/lib/recvfile.c b/source/lib/recvfile.c
new file mode 100644
index 0000000..cd9fb12
--- /dev/null
+++ b/source/lib/recvfile.c
@@ -0,0 +1,158 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.2.x
+ recvfile implementations.
+ Copyright (C) Jeremy Allison 2007.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * This file handles the OS dependent recvfile implementations.
+ * The API is such that it returns -1 on error, else returns the
+ * number of bytes written.
+ */
+
+#include "includes.h"
+
+/* Do this on our own in TRANSFER_BUF_SIZE chunks.
+ * 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'.
+ * eturn != count then sets errno.
+ * Returns count if complete success.
+ */
+
+#ifndef TRANSFER_BUF_SIZE
+#define TRANSFER_BUF_SIZE (128*1024)
+#endif
+
+static ssize_t default_sys_recvfile(int fromfd,
+			int tofd,
+			SMB_OFF_T offset,
+			size_t count)
+{
+	int saved_errno = 0;
+	size_t total = 0;
+	size_t bufsize = MIN(TRANSFER_BUF_SIZE,count);
+	size_t total_written = 0;
+	char *buffer = NULL;
+
+	if (count == 0) {
+		return 0;
+	}
+
+	if (tofd != -1 && offset != (SMB_OFF_T)-1) {
+		if (sys_lseek(tofd, offset, SEEK_SET) == -1) {
+			if (errno != ESPIPE) {
+				return -1;
+			}
+		}
+	}
+
+	buffer = SMB_MALLOC_ARRAY(char, bufsize);
+	if (buffer == NULL) {
+		return -1;
+	}
+
+	while (total < count) {
+		size_t num_written = 0;
+		ssize_t read_ret;
+		size_t toread = MIN(bufsize,count - total);
+
+		/* Read from socket - ignore EINTR. */
+		read_ret = sys_read(fromfd, buffer, toread);
+		if (read_ret <= 0) {
+			/* EOF or socket error. */
+			free(buffer);
+			return -1;
+		}
+
+		num_written = 0;
+
+		while (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;
+				}
+			}
+
+			num_written += (size_t)write_ret;
+			total_written += (size_t)write_ret;
+		}
+
+		total += read_ret;
+	}
+
+	free(buffer);
+	if (saved_errno) {
+		/* Return the correct write error. */
+		errno = saved_errno;
+	}
+	return (ssize_t)total_written;
+}
+
+#if defined(HAVE_SPLICE_SYSCALL)
+ssize_t sys_recvfile(int fromfd,
+			int tofd,
+			SMB_OFF_T offset,
+			size_t count)
+{
+	errno = ENOSYS
+	return -1;
+}
+#else
+
+/*****************************************************************
+ No recvfile system call - use the default 128 chunk implementation.
+*****************************************************************/
+
+ssize_t sys_recvfile(int fromfd,
+			int tofd,
+			SMB_OFF_T offset,
+			size_t count)
+{
+	return default_sys_recvfile(fromfd, tofd, offset, count);
+}
+#endif
+
+/*****************************************************************
+ Throw away "count" bytes from the client socket.
+*****************************************************************/
+
+ssize_t drain_socket(int sockfd, size_t count)
+{
+	return default_sys_recvfile(sockfd, -1, (SMB_OFF_T)-1, count);
+}
-- 
1.5.3



More information about the samba-technical mailing list