The branch, v4-0-test has been updated via 7e140cf Ensure the RECVFILE path in vfs_pwrite_data() operates on a blocking socket. via 05e8a78 Ensure the RECVFILE path in vfs_write_data() operates on a blocking socket. via 160a9f3 Ensure drain_socket() operates on a blocking socket. via 1758eaa Add the internals of is_smb2_recvfile_write. via cd0da23 The guts of the receivefile code changes. via 0d190cf Add stub static function that will turn on/off receivefile code path. via 5bd69d5 Add extra fields into struct smbd_smb2_request_read_state to support receivefile. via 97fc9b9 Add macro SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN. via 1828c74 Add utility function get_min_receive_file_size(). via 6083839 Allow smbd_smb2_request_error_ex() to cope with unread bytes on error. via 8854426 Add function smbd_smb2_unread_bytes(). via 67839e1 If we already have an smb1req attached to the struct smbd_smb2_request, don't recreate it. via 07ab7e6 Ensure we don't do an SMB2 aio write if RECVFILE is active. via d94190f smbd: Fix signing when the async echo handler kicks in via 9fe3d7d build: Replace #!/usr/bin/env python with passed in PYTHON= via 03ef312 build: Remove extra space in shebang from 3f8ea16 docs: Fix bug 9809 -- missing entry in specfile
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test - Log ----------------------------------------------------------------- commit 7e140cf2aa36334991b3f71c7fca6d2b8bca0e67 Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 8 10:49:03 2013 -0700 Ensure the RECVFILE path in vfs_pwrite_data() operates on a blocking socket. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> Autobuild-User(master): Jeremy Allison <j...@samba.org> Autobuild-Date(master): Sat Apr 20 01:04:05 CEST 2013 on sn-devel-104 (cherry picked from commit 95f7fc83b251efefcc2a603b936b55e2f0308a72) The last 13 patches address bug #9412 - SMB2 server doesn't support recvfile. Autobuild-User(v4-0-test): Karolin Seeger <ksee...@samba.org> Autobuild-Date(v4-0-test): Thu Apr 25 14:39:27 CEST 2013 on sn-devel-104 commit 05e8a7892494502d27e34e142ffb1a9883d8ea49 Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 8 10:32:10 2013 -0700 Ensure the RECVFILE path in vfs_write_data() operates on a blocking socket. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 1ed710c2ffc91d8b33b87e572a6075e0126b5826) commit 160a9f3b5ab5ca4e040bbffc172bfcc6b07c556f Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 8 10:16:48 2013 -0700 Ensure drain_socket() operates on a blocking socket. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 1b46db7b24a4f064706c2c7e712452135a3fed34) commit 1758eaa1c3d41199077b410691e556ef4f512d34 Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 1 11:16:01 2013 -0700 Add the internals of is_smb2_recvfile_write. This turns on the real receivefile detection, and completes the receivefile code path changes. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 1a7cec37e725c9f29fd71788e15623d904b41c8a) commit cd0da2355fb41bbb260a774b05fda841fd297208 Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 1 13:24:07 2013 -0700 The guts of the receivefile code changes. If an incoming PDU might qualify, only read SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN = (SMB2_HEADER + SMB2_WRITE_BODY_LEN) bytes rather than the whole PDU. Next time we're called, use is_smb2_recvfile_write() to decide if this is an SMB2_WRITE that fit the receivefile criteria, otherwise just read the rest of the PDU. If we did do a short receivefile read, set up the smb2_req->smb1req->unread_bytes value to show what bytes remain in the TCP buffers. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 53b87f2fbabe3a2dcb5df6f6c494ef332bea81e7) commit 0d190cfcb247c7d311971777cce00b3b1683d916 Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 1 13:19:01 2013 -0700 Add stub static function that will turn on/off receivefile code path. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit fdcaf0fa360b9590114605d24af545b1d42b9fd5) commit 5bd69d5d67111298bf05d24488b472fd21b9653e Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 1 13:17:09 2013 -0700 Add extra fields into struct smbd_smb2_request_read_state to support receivefile. Initialize min_recv_size with the size that will trigger the receivefile write path. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 4b91097002d73ae5dd2d4ac225f8e9eecca11e49) commit 97fc9b9af3f5a2b1af04bdb9c3d71ab3a065a022 Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 1 13:14:13 2013 -0700 Add macro SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN. This is the 'short' length we'll read in the SMB2_WRITE receivefile code path. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 36d4b9d208c0025f054ad8ae4062ca3c81e345d5) commit 1828c74c6c85cdba9689012ac991187b5eb2cfa3 Author: Jeremy Allison <j...@samba.org> Date: Mon Apr 1 13:12:55 2013 -0700 Add utility function get_min_receive_file_size(). Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 61da7f00b3f3daebb82e6a5d987883e0897dc4e9) commit 6083839d1c0372cd172d619b82a2862e9d46f81f Author: Jeremy Allison <j...@samba.org> Date: Tue Mar 19 12:36:52 2013 -0700 Allow smbd_smb2_request_error_ex() to cope with unread bytes on error. Drain the socket if a RECVFILE write failed. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 63739440f128229a6a99d0653562d3735ae909fb) commit 8854426ee1a31be34ab8be3f11c43685ede7141a Author: Jeremy Allison <j...@samba.org> Date: Tue Mar 19 12:24:17 2013 -0700 Add function smbd_smb2_unread_bytes(). Returns number of bytes left to read for recvfile. Will be used in SMB_2_WRITE_FILE code path. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit a36d7633bd3608b71f610fc9df2ad9c66bfdd9c6) commit 67839e1138d8d9a2e4aa69fdd0eb1e0504a1910d Author: Jeremy Allison <j...@samba.org> Date: Tue Mar 19 12:16:32 2013 -0700 If we already have an smb1req attached to the struct smbd_smb2_request, don't recreate it. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit ec9fc986da8279f15338b7682c629bfdfc36d016) commit 07ab7e645de69700b2924465eccd5489c78b457a Author: Jeremy Allison <j...@samba.org> Date: Mon Mar 18 12:00:25 2013 -0700 Ensure we don't do an SMB2 aio write if RECVFILE is active. Signed-off-by: Jeremy Allison <j...@samba.org> Reviewed-by: Stefan (metze) Metzmacher <me...@samba.org> (cherry picked from commit 9791c1a24822d8b46bf7dd231b615d281b58540b) commit d94190f96a528c98f300a1c7a014284bd81c8b13 Author: Volker Lendecke <v...@samba.org> Date: Fri Apr 19 12:36:08 2013 +0200 smbd: Fix signing when the async echo handler kicks in This was introduced as a copy&paste error in 5e0258fc932c Signed-off-by: Volker Lendecke <v...@samba.org> Reviewed-by: Christian Ambach <a...@samba.org> (cherry picked from commit 5aa9e552ec70ffbd48495e0d7c28517e726487bf) Fix bug #9824 - SMB signing and the async echo responder don't work together. commit 9fe3d7dff7a4e531d97ff002b1deac0ac2fbf633 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Apr 8 15:57:45 2013 +1000 build: Replace #!/usr/bin/env python with passed in PYTHON= This means that if we were forced to use a specific python for the build, we will put that binary into the top of samba-tool, so it continues to work after the install. Andrew Bartlett Reviewed-by: Michael Adam <ob...@samba.org> (cherry picked from commit 58e3c5323e343dcab1c528c6b6a44925b76cb297) The last 2 patches address bug #9785 - Fixes to use specified python for runtime installation of Samba. commit 03ef3121ae897789c68a216af690e7207d8a32e0 Author: Andrew Bartlett <abart...@samba.org> Date: Mon Apr 8 08:33:55 2013 +1000 build: Remove extra space in shebang Reviewed-by: Michael Adam <ob...@samba.org> (cherry picked from commit 45a596fbe9ed2b198956d58784999df780f6dd65) ----------------------------------------------------------------------- Summary of changes: buildtools/wafsamba/samba_python.py | 10 +++ buildtools/wafsamba/wafsamba.py | 15 ++++- source3/lib/recvfile.c | 17 ++++- source3/smbd/aio.c | 5 ++ source3/smbd/globals.h | 3 + source3/smbd/process.c | 2 +- source3/smbd/smb2_glue.c | 22 +++++- source3/smbd/smb2_server.c | 130 +++++++++++++++++++++++++++++++++-- source3/smbd/vfs.c | 26 +++++++- source3/wscript | 2 +- wscript | 7 +-- 11 files changed, 219 insertions(+), 20 deletions(-) Changeset truncated at 500 lines: diff --git a/buildtools/wafsamba/samba_python.py b/buildtools/wafsamba/samba_python.py index b2172f7..847b431 100644 --- a/buildtools/wafsamba/samba_python.py +++ b/buildtools/wafsamba/samba_python.py @@ -5,6 +5,16 @@ from samba_utils import * from samba_autoconf import * from Configure import conf + +@conf +def SAMBA_CHECK_PYTHON(conf, mandatory=True): + # enable tool to build python extensions + conf.find_program('python', var='PYTHON', mandatory=mandatory) + conf.check_tool('python') + path_python = conf.find_program('python') + conf.env.PYTHON_SPECIFIED = (conf.env.PYTHON != path_python) + conf.check_python_version((2,4,2)) + @conf def SAMBA_CHECK_PYTHON_HEADERS(conf, mandatory=True): if conf.env["python_headers_checked"] == []: diff --git a/buildtools/wafsamba/wafsamba.py b/buildtools/wafsamba/wafsamba.py index f7156ec..3559cc1 100644 --- a/buildtools/wafsamba/wafsamba.py +++ b/buildtools/wafsamba/wafsamba.py @@ -696,14 +696,25 @@ def copy_and_fix_python_path(task): replacement="""sys.path.insert(0, "%s") sys.path.insert(1, "%s")""" % (task.env["PYTHONARCHDIR"], task.env["PYTHONDIR"]) + shebang = None + + if task.env["PYTHON"][0] == "/": + replacement_shebang = "#!%s" % task.env["PYTHON"] + else: + replacement_shebang = "#!/usr/bin/env %s" % task.env["PYTHON"] + installed_location=task.outputs[0].bldpath(task.env) source_file = open(task.inputs[0].srcpath(task.env)) installed_file = open(installed_location, 'w') + lineno = 0 for line in source_file: newline = line - if pattern in line: + if lineno == 0 and task.env["PYTHON_SPECIFIED"] == True and line[:2] == "#!": + newline = replacement_shebang + elif pattern in line: newline = line.replace(pattern, replacement) installed_file.write(newline) + lineno = lineno + 1 installed_file.close() os.chmod(installed_location, 0755) return 0 @@ -727,6 +738,8 @@ def install_file(bld, destdir, file, chmod=MODE_644, flat=False, target=inst_file) bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHONARCHDIR"]) bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHONDIR"]) + bld.add_manual_dependency(bld.path.find_or_declare(inst_file), str(bld.env["PYTHON_SPECIFIED"])) + bld.add_manual_dependency(bld.path.find_or_declare(inst_file), bld.env["PYTHON"]) file = inst_file if base_name: file = os.path.join(base_name, file) diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c index c53ba77..72f4257 100644 --- a/source3/lib/recvfile.c +++ b/source3/lib/recvfile.c @@ -240,6 +240,7 @@ ssize_t sys_recvfile(int fromfd, /***************************************************************** Throw away "count" bytes from the client socket. Returns count or -1 on error. + Must only operate on a blocking socket. *****************************************************************/ ssize_t drain_socket(int sockfd, size_t count) @@ -247,6 +248,7 @@ ssize_t drain_socket(int sockfd, size_t count) size_t total = 0; size_t bufsize = MIN(TRANSFER_BUF_SIZE,count); char *buffer = NULL; + int old_flags = 0; if (count == 0) { return 0; @@ -257,6 +259,12 @@ ssize_t drain_socket(int sockfd, size_t count) return -1; } + old_flags = fcntl(sockfd, F_GETFL, 0); + if (set_blocking(sockfd, true) == -1) { + free(buffer); + return -1; + } + while (total < count) { ssize_t read_ret; size_t toread = MIN(bufsize,count - total); @@ -265,12 +273,17 @@ ssize_t drain_socket(int sockfd, size_t count) read_ret = sys_read(sockfd, buffer, toread); if (read_ret <= 0) { /* EOF or socket error. */ - free(buffer); - return -1; + count = (size_t)-1; + goto out; } total += read_ret; } + out: + free(buffer); + if (fcntl(sockfd, F_SETFL, old_flags) == -1) { + return -1; + } return count; } diff --git a/source3/smbd/aio.c b/source3/smbd/aio.c index 3f553eb..e8be408 100644 --- a/source3/smbd/aio.c +++ b/source3/smbd/aio.c @@ -861,6 +861,11 @@ NTSTATUS schedule_aio_smb2_write(connection_struct *conn, return NT_STATUS_RETRY; } + if (smbreq->unread_bytes) { + /* Can't do async with recvfile. */ + return NT_STATUS_RETRY; + } + if (!(aio_ex = create_aio_extra(smbreq->smb2req, fsp, 0))) { return NT_STATUS_NO_MEMORY; } diff --git a/source3/smbd/globals.h b/source3/smbd/globals.h index 51f55bf..16ac24b 100644 --- a/source3/smbd/globals.h +++ b/source3/smbd/globals.h @@ -246,6 +246,7 @@ NTSTATUS smbd_smb2_request_pending_queue(struct smbd_smb2_request *req, uint32_t defer_time); struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req); +size_t smbd_smb2_unread_bytes(struct smbd_smb2_request *req); void remove_smb2_chained_fsp(files_struct *fsp); NTSTATUS smbd_smb2_request_verify_creditcharge(struct smbd_smb2_request *req, @@ -540,6 +541,8 @@ struct smbd_smb2_request { #define SMBD_SMB2_OUT_DYN_PTR(req) (uint8_t *)(SMBD_SMB2_OUT_DYN_IOV(req)->iov_base) #define SMBD_SMB2_OUT_DYN_LEN(req) (SMBD_SMB2_OUT_DYN_IOV(req)->iov_len) +#define SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN (SMB2_HDR_BODY + 0x30) + struct { /* * vector[0] TRANSPORT HEADER (empty) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index f03a20f..8add79d 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2412,7 +2412,7 @@ static void smbd_server_connection_read_handler( &unread_bytes, &encrypted, &inbuf_len, &seqnum, - false /* trusted channel */); + !from_client /* trusted channel */); if (from_client) { smbd_unlock_socket(sconn); diff --git a/source3/smbd/smb2_glue.c b/source3/smbd/smb2_glue.c index 1b2b4dd..54135b5 100644 --- a/source3/smbd/smb2_glue.c +++ b/source3/smbd/smb2_glue.c @@ -28,9 +28,13 @@ struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req) struct smb_request *smbreq; const uint8_t *inhdr = SMBD_SMB2_IN_HDR_PTR(req); - smbreq = talloc_zero(req, struct smb_request); - if (smbreq == NULL) { - return NULL; + if (req->smb1req) { + smbreq = req->smb1req; + } else { + smbreq = talloc_zero(req, struct smb_request); + if (smbreq == NULL) { + return NULL; + } } smbreq->request_time = req->request_time; @@ -55,6 +59,18 @@ struct smb_request *smbd_smb2_fake_smb_request(struct smbd_smb2_request *req) } /********************************************************* + Are there unread bytes for recvfile ? +*********************************************************/ + +size_t smbd_smb2_unread_bytes(struct smbd_smb2_request *req) +{ + if (req->smb1req) { + return req->smb1req->unread_bytes; + } + return 0; +} + +/********************************************************* Called from file_free() to remove any chained fsp pointers. *********************************************************/ diff --git a/source3/smbd/smb2_server.c b/source3/smbd/smb2_server.c index 62d1074..29d4f7c 100644 --- a/source3/smbd/smb2_server.c +++ b/source3/smbd/smb2_server.c @@ -2621,11 +2621,21 @@ NTSTATUS smbd_smb2_request_error_ex(struct smbd_smb2_request *req, { DATA_BLOB body; uint8_t *outhdr = SMBD_SMB2_OUT_HDR_PTR(req); + size_t unread_bytes = smbd_smb2_unread_bytes(req); DEBUG(10,("smbd_smb2_request_error_ex: idx[%d] status[%s] |%s| at %s\n", req->current_idx, nt_errstr(status), info ? " +info" : "", location)); + if (unread_bytes) { + /* Recvfile error. Drain incoming socket. */ + size_t ret = drain_socket(req->sconn->sock, unread_bytes); + if (ret != unread_bytes) { + smbd_server_connection_terminate(req->sconn, + "Failed to drain SMB2 socket\n"); + } + } + body.data = outhdr + SMB2_HDR_BODY; body.length = 8; SSVAL(body.data, 0, 9); @@ -2821,6 +2831,8 @@ struct smbd_smb2_request_read_state { uint8_t nbt[NBT_HDR_SIZE]; bool done; } hdr; + bool doing_receivefile; + size_t min_recv_size; size_t pktlen; uint8_t *pktbuf; }; @@ -2832,6 +2844,17 @@ static int smbd_smb2_request_next_vector(struct tstream_context *stream, size_t *_count); static void smbd_smb2_request_read_done(struct tevent_req *subreq); +static size_t get_min_receive_file_size(struct smbd_smb2_request *smb2_req) +{ + if (smb2_req->do_signing) { + return 0; + } + if (smb2_req->do_encryption) { + return 0; + } + return (size_t)lp_min_receive_file_size(); +} + static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx, struct tevent_context *ev, struct smbd_server_connection *sconn) @@ -2853,6 +2876,7 @@ static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx, return tevent_req_post(req, ev); } state->smb2_req->sconn = sconn; + state->min_recv_size = get_min_receive_file_size(state->smb2_req); subreq = tstream_readv_pdu_queue_send(state->smb2_req, state->ev, @@ -2868,6 +2892,47 @@ static struct tevent_req *smbd_smb2_request_read_send(TALLOC_CTX *mem_ctx, return req; } +static bool is_smb2_recvfile_write(struct smbd_smb2_request_read_state *state) +{ + uint32_t flags; + + if (IVAL(state->pktbuf, 0) == SMB2_TF_MAGIC) { + /* Transform header. Cannot recvfile. */ + return false; + } + if (IVAL(state->pktbuf, 0) != SMB2_MAGIC) { + /* Not SMB2. Normal error path will cope. */ + return false; + } + if (SVAL(state->pktbuf, 4) != SMB2_HDR_BODY) { + /* Not SMB2. Normal error path will cope. */ + return false; + } + if (SVAL(state->pktbuf, SMB2_HDR_OPCODE) != SMB2_OP_WRITE) { + /* Needs to be a WRITE. */ + return false; + } + if (IVAL(state->pktbuf, SMB2_HDR_NEXT_COMMAND) != 0) { + /* Chained. Cannot recvfile. */ + return false; + } + flags = IVAL(state->pktbuf, SMB2_HDR_FLAGS); + if (flags & SMB2_HDR_FLAG_CHAINED) { + /* Chained. Cannot recvfile. */ + return false; + } + if (flags & SMB2_HDR_FLAG_SIGNED) { + /* Signed. Cannot recvfile. */ + return false; + } + + DEBUG(10,("Doing recvfile write len = %u\n", + (unsigned int)(state->pktlen - + SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN))); + + return true; +} + static int smbd_smb2_request_next_vector(struct tstream_context *stream, void *private_data, TALLOC_CTX *mem_ctx, @@ -2877,12 +2942,38 @@ static int smbd_smb2_request_next_vector(struct tstream_context *stream, struct smbd_smb2_request_read_state *state = talloc_get_type_abort(private_data, struct smbd_smb2_request_read_state); - struct iovec *vector; + struct iovec *vector = NULL; + size_t min_recvfile_size = UINT32_MAX; if (state->pktlen > 0) { - /* if there're no remaining bytes, we're done */ - *_vector = NULL; - *_count = 0; + if (state->doing_receivefile && !is_smb2_recvfile_write(state)) { + /* + * Not a possible receivefile write. + * Read the rest of the data. + */ + state->doing_receivefile = false; + vector = talloc_array(mem_ctx, struct iovec, 1); + if (vector == NULL) { + return -1; + } + vector[0].iov_base = (void *)(state->pktbuf + + SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN); + vector[0].iov_len = (state->pktlen - + SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN); + *_vector = vector; + *_count = 1; + } else { + /* + * Either this is a receivefile write so we've + * done a short read, or if not we have all the data. + * Either way, we're done and + * smbd_smb2_request_read_done() will handle + * and short read case by looking at the + * state->doing_receivefile value. + */ + *_vector = NULL; + *_count = 0; + } return 0; } @@ -2928,7 +3019,26 @@ static int smbd_smb2_request_next_vector(struct tstream_context *stream, } vector[0].iov_base = (void *)state->pktbuf; - vector[0].iov_len = state->pktlen; + + if (state->min_recv_size != 0) { + min_recvfile_size = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN; + min_recvfile_size += state->min_recv_size; + } + + if (state->pktlen > min_recvfile_size) { + /* + * Might be a receivefile write. Read the SMB2 HEADER + + * SMB2_WRITE header first. Set 'doing_receivefile' + * as we're *attempting* receivefile write. If this + * turns out not to be a SMB2_WRITE request or otherwise + * not suitable then we'll just read the rest of the data + * the next time this function is called. + */ + vector[0].iov_len = SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN; + state->doing_receivefile = true; + } else { + vector[0].iov_len = state->pktlen; + } *_vector = vector; *_count = 1; @@ -2991,6 +3101,16 @@ static void smbd_smb2_request_read_done(struct tevent_req *subreq) return; } + if (state->doing_receivefile) { + state->smb2_req->smb1req = talloc_zero(state->smb2_req, + struct smb_request); + if (tevent_req_nomem(state->smb2_req->smb1req, req)) { + return; + } + state->smb2_req->smb1req->unread_bytes = + state->pktlen - SMBD_SMB2_SHORT_RECEIVEFILE_WRITE_LEN; + } + state->smb2_req->current_idx = 1; tevent_req_done(req); diff --git a/source3/smbd/vfs.c b/source3/smbd/vfs.c index 581a025..124981c 100644 --- a/source3/smbd/vfs.c +++ b/source3/smbd/vfs.c @@ -428,14 +428,25 @@ ssize_t vfs_write_data(struct smb_request *req, ssize_t ret; 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; - return SMB_VFS_RECVFILE(req->sconn->sock, + /* 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, (off_t)-1, N); + if (fcntl(sockfd, F_SETFL, old_flags) == -1) { + return (ssize_t)-1; + } + return ret; } while (total < N) { @@ -461,14 +472,25 @@ ssize_t vfs_pwrite_data(struct smb_request *req, ssize_t ret; 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; - return SMB_VFS_RECVFILE(req->sconn->sock, + /* 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; + } + return ret; } while (total < N) { diff --git a/source3/wscript b/source3/wscript index e1672e0..00432c4 100644 --- a/source3/wscript +++ b/source3/wscript @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python srcdir=".." diff --git a/wscript b/wscript index c8dcccd..de518ac 100644 --- a/wscript +++ b/wscript @@ -1,4 +1,4 @@ -#! /usr/bin/env python +#!/usr/bin/env python srcdir = '.' blddir = 'bin' @@ -82,13 +82,10 @@ def configure(conf): conf.RECURSE('lib/replace') - conf.find_program('python', var='PYTHON', mandatory=True) conf.find_program('perl', var='PERL', mandatory=True) conf.find_program('xsltproc', var='XSLTPROC') - # enable tool to build python extensions - conf.check_tool('python') - conf.check_python_version((2,4,2)) + conf.SAMBA_CHECK_PYTHON(mandatory=True) conf.SAMBA_CHECK_PYTHON_HEADERS(mandatory=True) if sys.platform == 'darwin' and not conf.env['HAVE_ENVIRON_DECL']: -- Samba Shared Repository