[SCM] Samba Shared Repository - branch v3-2-test updated - initial-v3-2-unstable-146-g8fbefe1

Jeremy Allison jra at samba.org
Wed Oct 31 21:34:32 GMT 2007


The branch, v3-2-test has been updated
       via  8fbefe18a2dc23adb0ebe488cfb37ab4a382207d (commit)
       via  52f13d84955224ebbaead53d8428baade6a22fe0 (commit)
       via  8cf78776b0a44bd026cef3d74eb11cfb415f8303 (commit)
       via  b7088bb9c2a00d4717b9a7efa4bddc0c005f4efb (commit)
       via  247675695dfbff503b5792de62f8bb1567ea2327 (commit)
       via  11c03b75ddbcb6e36b231bb40a1773d1c550621c (commit)
       via  765b37c693516757686118fffd3c80cf4d5e7344 (commit)
       via  c833c336435cffd20579903d22ccb910ab467e53 (commit)
       via  d5886218e53910b7015e6f13bc634e1bf338565a (commit)
       via  bfbdb6324c5d13bfde8b742e9c5a0e0c9092bd86 (commit)
      from  3d3d1b806aef3617abaac46daf230ed32076e2ce (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v3-2-test


- Log -----------------------------------------------------------------
commit 8fbefe18a2dc23adb0ebe488cfb37ab4a382207d
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Oct 31 14:24:52 2007 -0700

    Fix vfstest link - move socket calls into smbd/process.c
    not smbd/server.c
    Jeremy

commit 52f13d84955224ebbaead53d8428baade6a22fe0
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Oct 31 14:12:50 2007 -0700

    Add printout of large read/write caps if detected.
    Jeremy.

commit 8cf78776b0a44bd026cef3d74eb11cfb415f8303
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Oct 31 14:01:35 2007 -0700

    Make explicit draining the socket on RECVFILE. Add
    capability for large UNIX write if not signing and
    recvfile set. Cope with large UNIX write length on
    incoming processing. Stevef - we can now test 1-16Mb
    writes from CIFFS.
    Jeremy.

commit b7088bb9c2a00d4717b9a7efa4bddc0c005f4efb
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Oct 30 18:18:40 2007 -0700

    Handle the disk full error case correctly.
    Jeremy.

commit 247675695dfbff503b5792de62f8bb1567ea2327
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Oct 30 17:42:02 2007 -0700

    Ensure we don't prematurely clean out the bytes read.
    Jeremy.

commit 11c03b75ddbcb6e36b231bb40a1773d1c550621c
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Oct 30 16:22:24 2007 -0700

    Add new parameter, "min receivefile size" (by default set
    to zero). If non-zero, writeX calls greater than this
    value will be left in the socket buffer for later handling
    with recvfile (or userspace equivalent). Definition of
    recvfile for your system is left as an exercise for
    the reader (I'm working on getting splice working :-).
    Jeremy.

commit 765b37c693516757686118fffd3c80cf4d5e7344
Merge: c833c336435cffd20579903d22ccb910ab467e53 3d3d1b806aef3617abaac46daf230ed32076e2ce
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Oct 30 12:55:56 2007 -0700

    Merge branch 'v3-2-test' of ssh://jra@git.samba.org/data/git/samba into v3-2-test

commit c833c336435cffd20579903d22ccb910ab467e53
Merge: d5886218e53910b7015e6f13bc634e1bf338565a 95f76ae7a52c6b22db22d03fed6b0848d2a61bee
Author: Jeremy Allison <jra at samba.org>
Date:   Tue Oct 30 10:19:45 2007 -0700

    Merge branch 'v3-2-test' of ssh://jra@git.samba.org/data/git/samba into v3-2-test

commit d5886218e53910b7015e6f13bc634e1bf338565a
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 29 17:17:16 2007 -0700

    Forgot to add recvfile.c
    Jeremy.

commit bfbdb6324c5d13bfde8b742e9c5a0e0c9092bd86
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 29 17:16:13 2007 -0700

    Add in the recvfile entry to the VFS layer with a default
    implementation. Needed for the zero-copy write code.
    Jeremy.

-----------------------------------------------------------------------

Summary of changes:
 examples/VFS/skel_opaque.c      |   13 ++
 examples/VFS/skel_transparent.c |   12 ++
 source/Makefile.in              |    2 +-
 source/client/client.c          |    6 +
 source/include/smb.h            |    1 +
 source/include/smbprofile.h     |    4 +
 source/include/vfs.h            |    4 +
 source/include/vfs_macros.h     |    3 +
 source/lib/recvfile.c           |  206 +++++++++++++++++++++++
 source/lib/util_sock.c          |  106 +------------
 source/modules/vfs_default.c    |   17 ++
 source/modules/vfs_full_audit.c |   22 +++
 source/param/loadparm.c         |    5 +
 source/profile/profile.c        |    1 +
 source/smbd/blocking.c          |    4 +-
 source/smbd/fileio.c            |   41 ++++--
 source/smbd/notify.c            |    2 +-
 source/smbd/process.c           |  350 +++++++++++++++++++++++++++++++++++++--
 source/smbd/reply.c             |   97 +++++++++--
 source/smbd/server.c            |   11 +-
 source/smbd/trans2.c            |    9 +-
 source/smbd/vfs.c               |   36 ++++-
 22 files changed, 791 insertions(+), 161 deletions(-)
 create mode 100644 source/lib/recvfile.c


Changeset truncated at 500 lines:

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/client/client.c b/source/client/client.c
index f18505a..a381d13 100644
--- a/source/client/client.c
+++ b/source/client/client.c
@@ -2013,6 +2013,12 @@ static int cmd_posix(void)
         if (caplow & CIFS_UNIX_POSIX_PATH_OPERATIONS_CAP) {
 		pstrcat(caps, "posix_path_operations ");
 	}
+        if (caplow & CIFS_UNIX_LARGE_READ_CAP) {
+		pstrcat(caps, "large_read ");
+	}
+        if (caplow & CIFS_UNIX_LARGE_WRITE_CAP) {
+		pstrcat(caps, "large_write ");
+	}
 
 	if (strlen(caps) > 0 && caps[strlen(caps)-1] == ' ') {
 		caps[strlen(caps)-1] = '\0';
diff --git a/source/include/smb.h b/source/include/smb.h
index 4c51acf..303f760 100644
--- a/source/include/smb.h
+++ b/source/include/smb.h
@@ -675,6 +675,7 @@ struct smb_request {
 	uint8  wct;
 	const uint8 *inbuf;
 	uint8 *outbuf;
+	size_t unread_bytes;
 };
 
 /* Defines for the sent_oplock_break field above. */
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/lib/recvfile.c b/source/lib/recvfile.c
new file mode 100644
index 0000000..f9788fd
--- /dev/null
+++ b/source/lib/recvfile.c
@@ -0,0 +1,206 @@
+/*
+ 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'.
+ * return != 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)
+
+/*
+ * Try and use the Linux system call to do this.
+ * Remember we only return -1 if the socket read
+ * failed. Else we return the number of bytes
+ * actually written. We always read count bytes
+ * from the network in the case of return != -1.
+ */
+
+ssize_t sys_recvfile(int fromfd,
+			int tofd,
+			SMB_OFF_T offset,
+			size_t count)
+{
+	size_t total_written = 0;
+
+	if (count == 0) {
+		return 0;
+	}
+
+	while (total_written < count) {
+		ssize_t ret = splice(fromfd,
+					NULL,
+					tofd,
+					&offset,
+					count,
+					0);
+		if (ret == -1) {
+			if (errno != EINTR) {
+				if (total_written == 0 &&
+						errno == EBADF || errno == EINVAL) {
+					return default_sys_recvfile(fromfd,
+								tofd,
+								offset,
+								count);
+				}
+				break;
+			}
+			continue;
+		}
+		total_written += ret;
+		count -= ret;
+	}
+
+	if (total_written < count) {
+		int saved_errno = errno;
+		if (drain_socket(fromfd, count-total_written) !=
+				count-total_written) {
+			/* socket is dead. */
+			return -1;
+		}
+		errno = saved_errno;
+	}
+
+	return total_written;
+}
+#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);
+}
diff --git a/source/lib/util_sock.c b/source/lib/util_sock.c
index e66bd5f..bbcbcac 100644
--- a/source/lib/util_sock.c
+++ b/source/lib/util_sock.c
@@ -1113,7 +1113,7 @@ bool send_keepalive(int client)
  Timeout is in milliseconds.
 ****************************************************************************/
 
-static ssize_t read_smb_length_return_keepalive(int fd,
+ssize_t read_smb_length_return_keepalive(int fd,
 						char *inbuf,
 						unsigned int timeout)
 {
@@ -1260,86 +1260,6 @@ ssize_t receive_smb_raw(int fd,
 	return len;
 }
 
-static ssize_t receive_smb_raw_talloc(TALLOC_CTX *mem_ctx, int fd,
-				      char **buffer, unsigned int timeout)
-{
-	char lenbuf[4];
-	ssize_t len,ret;
-
-	smb_read_error = 0;
-
-	len = read_smb_length_return_keepalive(fd, lenbuf, timeout);
-	if (len < 0) {
-		DEBUG(10,("receive_smb_raw: length < 0!\n"));
-
-		/*
-		 * Correct fix. smb_read_error may have already been
-		 * set. Only set it here if not already set. Global
-		 * variables still suck :-). JRA.
-		 */
-
-		if (smb_read_error == 0)
-			smb_read_error = READ_ERROR;
-		return -1;
-	}
-
-	/*
-	 * A WRITEX with CAP_LARGE_WRITEX can be 64k worth of data plus 65 bytes
-	 * of header. Don't print the error if this fits.... JRA.
-	 */
-
-	if (len > (BUFFER_SIZE + LARGE_WRITEX_HDR_SIZE)) {
-		DEBUG(0,("Invalid packet length! (%lu bytes).\n",
-					(unsigned long)len));
-		if (len > BUFFER_SIZE + (SAFETY_MARGIN/2)) {
-
-			/*
-			 * Correct fix. smb_read_error may have already been
-			 * set. Only set it here if not already set. Global
-			 * variables still suck :-). JRA.
-			 */
-
-			if (smb_read_error == 0)
-				smb_read_error = READ_ERROR;
-			return -1;
-		}
-	}
-
-	/*
-	 * The +4 here can't wrap, we've checked the length above already.
-	 */
-
-	*buffer = TALLOC_ARRAY(mem_ctx, char, len+4);
-
-	if (*buffer == NULL) {
-		DEBUG(0, ("Could not allocate inbuf of length %d\n",
-			  (int)len+4));
-		if (smb_read_error == 0)
-			smb_read_error = READ_ERROR;
-		return -1;
-	}
-
-	memcpy(*buffer, lenbuf, sizeof(lenbuf));
-
-	if(len > 0) {
-		if (timeout > 0) {
-			ret = read_socket_with_timeout(fd,(*buffer)+4, len,
-						       len, timeout);
-		} else {
-			ret = read_data(fd, (*buffer)+4, len);
-		}
-
-		if (ret != len) {
-			if (smb_read_error == 0) {
-				smb_read_error = READ_ERROR;
-			}
-			return -1;
-		}
-	}
-
-	return len + 4;
-}
-
 /****************************************************************************
  Wrapper for receive_smb_raw().
  Checks the MAC on signed packets.
@@ -1364,30 +1284,6 @@ bool receive_smb(int fd, char *buffer, unsigned int timeout)
 	return true;
 }
 
-ssize_t receive_smb_talloc(TALLOC_CTX *mem_ctx, int fd, char **buffer,
-			   unsigned int timeout)


-- 
Samba Shared Repository


More information about the samba-cvs mailing list