[PATCH] Fix bug 9412 - SMB2 server doesn't support recvfile.

Jones jones.kstw at gmail.com
Thu Apr 3 04:11:54 MDT 2014


Hello Jeremy, Metze,

Thanks for kindly response!

Am 02.04.2014 19:51, schrieb Jeremy Allison:
> Not quite right I'm afraid, you need to
> catch a RECVFILE return of -1 within the loop.


That's great!

2014-04-03 2:06 GMT+08:00 Stefan (metze) Metzmacher <metze at samba.org>:
> And turn the socket into blocking mode once we get EAGAIN?


Add poll_one_fd() and infinite waiting for socket fd is ready to read.
But i am concerned that use poll() to instead of original fcntl(),
perhaps this is not a good method.
Should still use fcntl() to make sure the socket fd is into blocking mode?
Please kindly help comment,
thanks.

-- 
Regards,
Jones
-------------- next part --------------
From 6a354e372c1ed9bc24dd32d69859c82d24b5b5ac Mon Sep 17 00:00:00 2001
From: Jones Syue <jones.kstw at gmail.com>
Date: Thu, 3 Apr 2014 17:37:00 +0800
Subject: [PATCH] Scoping out a loop around the RECVFILE call.

Signed-off-by: Jones Syue <jones.kstw at gmail.com>
---
 source3/smbd/vfs.c | 45 ++++++++++++++++++++++++++++++---------------
 1 file changed, 30 insertions(+), 15 deletions(-)

diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c
index bc9157a..157c8cd 100644
--- a/source3/smbd/vfs.c
+++ b/source3/smbd/vfs.c
@@ -468,28 +468,43 @@ ssize_t vfs_pwrite_data(struct smb_request *req,
 			size_t N,
 			off_t offset)
 {
-	size_t total=0;
-	ssize_t ret;
+	size_t total = 0;
+	ssize_t ret = 0;
+	ssize_t thistime = 0;
+	size_t left = N;
+	off_t next = offset;
+	int revent;
 
 	if (req && req->unread_bytes) {
 		int sockfd = req->sconn->sock;
-		int old_flags;
 		SMB_ASSERT(req->unread_bytes == N);
 		/* VFS_RECVFILE must drain the socket
 		 * before returning. */
 		req->unread_bytes = 0;
-		/* Ensure the socket is blocking. */
-		old_flags = fcntl(sockfd, F_GETFL, 0);
-		if (set_blocking(sockfd, true) == -1) {
-			return (ssize_t)-1;
-		}
-		ret = SMB_VFS_RECVFILE(sockfd,
-					fsp,
-					offset,
-					N);
-		if (fcntl(sockfd, F_SETFL, old_flags) == -1) {
-			return (ssize_t)-1;
-		}
+		/* Scoping out a loop around the RECVFILE call. */
+		do {
+			thistime = SMB_VFS_RECVFILE(sockfd,
+						    fsp,
+						    next,
+						    left);
+#if defined(EWOULDBLOCK)
+			if (thistime == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
+#else /* EWOULDBLOCK */
+			if (thistime == -1 && errno == EAGAIN) {
+#endif /* EWOULDBLOCK */
+				poll_one_fd(sockfd, POLLIN, -1, &revent);
+				continue;
+			} else if (thistime == -1) {
+				if (ret == 0) {
+					ret = thistime;
+				}
+				break;
+			} else {
+				left -= thistime;
+				next += thistime;
+				ret += thistime;
+			}
+		} while (left > 0);
 		return ret;
 	}
 
-- 
1.8.3.4


More information about the samba-technical mailing list