[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Thu May 28 21:31:06 MDT 2015


The branch, master has been updated
       via  591f71f s3-libsmbclient: change vnum to 0.2.2
       via  f73bcf4 s3: libsmbclient: Add server-side copy support
      from  2ffa939 s4:torture:smb2:compound: compound read and padding

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 591f71fc359cbb13151755fb64b6e0391511dc07
Author: David Disseldorp <ddiss at samba.org>
Date:   Mon May 25 15:18:44 2015 +0200

    s3-libsmbclient: change vnum to 0.2.2
    
    To reflect new splice ABI.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>
    
    Autobuild-User(master): Jeremy Allison <jra at samba.org>
    Autobuild-Date(master): Fri May 29 05:30:06 CEST 2015 on sn-devel-104

commit f73bcf4934be89f83e86459bc695b7d28348565c
Author: Ross Lagerwall <rosslagerwall at gmail.com>
Date:   Wed May 27 23:13:15 2015 +0100

    s3: libsmbclient: Add server-side copy support
    
    Introduce a new operation, splice, which copies data from one SMBCFILE
    to another. Implement this operation using FSCTL_SRV_COPYCHUNK_WRITE for
    SMB2+ protocols and using read+write for older protocols. Since the
    operation may be long running, it takes a callback which gets called
    periodically to indicate progress to the application and given an
    opportunity to stop it.
    
    Signed-off-by: Ross Lagerwall <rosslagerwall at gmail.com>
    Reviewed-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 libcli/smb/smb2cli_ioctl.c                         |  51 +++-
 libcli/smb/smbXcli_base.c                          |  32 +++
 libcli/smb/smbXcli_base.h                          |   6 +
 source3/include/libsmb_internal.h                  |  11 +-
 source3/include/libsmbclient.h                     |   9 +
 .../{smbclient-0.2.1.sigs => smbclient-0.2.2.sigs} |   2 +
 source3/libsmb/cli_smb2_fnum.c                     | 268 +++++++++++++++++++++
 source3/libsmb/cli_smb2_fnum.h                     |   7 +
 source3/libsmb/clireadwrite.c                      | 116 +++++++++
 source3/libsmb/libsmb_context.c                    |   1 +
 source3/libsmb/libsmb_file.c                       | 109 +++++++++
 source3/libsmb/libsmb_setget.c                     |  12 +
 source3/libsmb/proto.h                             |   7 +
 source3/libsmb/wscript                             |   2 +-
 source3/wscript_build                              |   1 +
 15 files changed, 627 insertions(+), 7 deletions(-)
 copy source3/libsmb/ABI/{smbclient-0.2.1.sigs => smbclient-0.2.2.sigs} (98%)


Changeset truncated at 500 lines:

diff --git a/libcli/smb/smb2cli_ioctl.c b/libcli/smb/smb2cli_ioctl.c
index b0f8eea..42a424e 100644
--- a/libcli/smb/smb2cli_ioctl.c
+++ b/libcli/smb/smb2cli_ioctl.c
@@ -23,6 +23,7 @@
 #include "smb_common.h"
 #include "smbXcli_base.h"
 #include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ioctl.h"
 
 struct smb2cli_ioctl_state {
 	uint8_t fixed[0x38];
@@ -32,6 +33,7 @@ struct smb2cli_ioctl_state {
 	struct iovec *recv_iov;
 	DATA_BLOB out_input_buffer;
 	DATA_BLOB out_output_buffer;
+	uint32_t ctl_code;
 };
 
 static void smb2cli_ioctl_done(struct tevent_req *subreq);
@@ -69,6 +71,7 @@ struct tevent_req *smb2cli_ioctl_send(TALLOC_CTX *mem_ctx,
 	if (req == NULL) {
 		return NULL;
 	}
+	state->ctl_code = in_ctl_code;
 	state->max_input_length = in_max_input_length;
 	state->max_output_length = in_max_output_length;
 
@@ -158,6 +161,32 @@ struct tevent_req *smb2cli_ioctl_send(TALLOC_CTX *mem_ctx,
 	return req;
 }
 
+/*
+ * 3.3.4.4 Sending an Error Response
+ * An error code other than one of the following indicates a failure:
+ */
+static bool smb2cli_ioctl_is_failure(uint32_t ctl_code, NTSTATUS status,
+				     size_t data_size)
+{
+	if (NT_STATUS_IS_OK(status)) {
+		return false;
+	}
+
+	/*
+	 * STATUS_INVALID_PARAMETER in a FSCTL_SRV_COPYCHUNK or
+	 * FSCTL_SRV_COPYCHUNK_WRITE Response, when returning an
+	 * SRV_COPYCHUNK_RESPONSE as described in section 2.2.32.1.
+	 */
+	if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) &&
+	    (ctl_code == FSCTL_SRV_COPYCHUNK ||
+	     ctl_code == FSCTL_SRV_COPYCHUNK_WRITE) &&
+	    data_size == sizeof(struct srv_copychunk_rsp)) {
+		return false;
+	}
+
+	return true;
+}
+
 static void smb2cli_ioctl_done(struct tevent_req *subreq)
 {
 	struct tevent_req *req =
@@ -195,12 +224,16 @@ static void smb2cli_ioctl_done(struct tevent_req *subreq)
 		.status = NT_STATUS_FILE_CLOSED,
 		.body_size = 0x09,
 	},
+	{
+		.status = NT_STATUS_INVALID_PARAMETER,
+		.body_size = 0x31
+	},
 	};
 
 	status = smb2cli_req_recv(subreq, state, &iov,
 				  expected, ARRAY_SIZE(expected));
 	TALLOC_FREE(subreq);
-	if (tevent_req_nterror(req, status)) {
+	if (iov == NULL && tevent_req_nterror(req, status)) {
 		return;
 	}
 
@@ -214,6 +247,11 @@ static void smb2cli_ioctl_done(struct tevent_req *subreq)
 	output_buffer_offset = IVAL(fixed, 0x20);
 	output_buffer_length = IVAL(fixed, 0x24);
 
+	if (smb2cli_ioctl_is_failure(state->ctl_code, status, output_buffer_length) &&
+	    tevent_req_nterror(req, status)) {
+		return;
+	}
+
 	if ((input_buffer_offset > 0) && (input_buffer_length > 0)) {
 		uint32_t ofs;
 
@@ -294,6 +332,10 @@ static void smb2cli_ioctl_done(struct tevent_req *subreq)
 		state->out_output_buffer.length = output_buffer_length;
 	}
 
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
 	tevent_req_done(req);
 }
 
@@ -305,9 +347,10 @@ NTSTATUS smb2cli_ioctl_recv(struct tevent_req *req,
 	struct smb2cli_ioctl_state *state =
 		tevent_req_data(req,
 		struct smb2cli_ioctl_state);
-	NTSTATUS status;
+	NTSTATUS status = NT_STATUS_OK;
 
-	if (tevent_req_is_nterror(req, &status)) {
+	if (tevent_req_is_nterror(req, &status) &&
+	    smb2cli_ioctl_is_failure(state->ctl_code, status, state->out_output_buffer.length)) {
 		tevent_req_received(req);
 		return status;
 	}
@@ -321,7 +364,7 @@ NTSTATUS smb2cli_ioctl_recv(struct tevent_req *req,
 	}
 
 	tevent_req_received(req);
-	return NT_STATUS_OK;
+	return status;
 }
 
 NTSTATUS smb2cli_ioctl(struct smbXcli_conn *conn,
diff --git a/libcli/smb/smbXcli_base.c b/libcli/smb/smbXcli_base.c
index 0754203..2f47fe6 100644
--- a/libcli/smb/smbXcli_base.c
+++ b/libcli/smb/smbXcli_base.c
@@ -130,6 +130,9 @@ struct smbXcli_conn {
 		uint16_t cur_credits;
 		uint16_t max_credits;
 
+		uint32_t cc_chunk_len;
+		uint32_t cc_max_chunks;
+
 		uint8_t io_priority;
 
 		uint8_t preauth_sha512[64];
@@ -409,6 +412,13 @@ struct smbXcli_conn *smbXcli_conn_create(TALLOC_CTX *mem_ctx,
 	conn->smb2.max_credits = 0;
 	conn->smb2.io_priority = 1;
 
+	/*
+	 * Samba and Windows servers accept a maximum of 16 MiB with a maximum
+	 * chunk length of 1 MiB.
+	 */
+	conn->smb2.cc_chunk_len = 1024 * 1024;
+	conn->smb2.cc_max_chunks = 16;
+
 	talloc_set_destructor(conn, smbXcli_conn_destructor);
 	return conn;
 
@@ -2595,6 +2605,28 @@ void smb2cli_conn_set_io_priority(struct smbXcli_conn *conn,
 	conn->smb2.io_priority = io_priority;
 }
 
+uint32_t smb2cli_conn_cc_chunk_len(struct smbXcli_conn *conn)
+{
+	return conn->smb2.cc_chunk_len;
+}
+
+void smb2cli_conn_set_cc_chunk_len(struct smbXcli_conn *conn,
+				    uint32_t chunk_len)
+{
+	conn->smb2.cc_chunk_len = chunk_len;
+}
+
+uint32_t smb2cli_conn_cc_max_chunks(struct smbXcli_conn *conn)
+{
+	return conn->smb2.cc_max_chunks;
+}
+
+void smb2cli_conn_set_cc_max_chunks(struct smbXcli_conn *conn,
+				    uint32_t max_chunks)
+{
+	conn->smb2.cc_max_chunks = max_chunks;
+}
+
 static void smb2cli_req_cancel_done(struct tevent_req *subreq);
 
 static bool smb2cli_req_cancel(struct tevent_req *req)
diff --git a/libcli/smb/smbXcli_base.h b/libcli/smb/smbXcli_base.h
index 8f27c20..cf93135 100644
--- a/libcli/smb/smbXcli_base.h
+++ b/libcli/smb/smbXcli_base.h
@@ -306,6 +306,12 @@ void smb2cli_conn_set_max_credits(struct smbXcli_conn *conn,
 uint8_t smb2cli_conn_get_io_priority(struct smbXcli_conn *conn);
 void smb2cli_conn_set_io_priority(struct smbXcli_conn *conn,
 				  uint8_t io_priority);
+uint32_t smb2cli_conn_cc_chunk_len(struct smbXcli_conn *conn);
+void smb2cli_conn_set_cc_chunk_len(struct smbXcli_conn *conn,
+				   uint32_t chunk_len);
+uint32_t smb2cli_conn_cc_max_chunks(struct smbXcli_conn *conn);
+void smb2cli_conn_set_cc_max_chunks(struct smbXcli_conn *conn,
+				    uint32_t max_chunks);
 
 struct tevent_req *smb2cli_req_create(TALLOC_CTX *mem_ctx,
 				      struct tevent_context *ev,
diff --git a/source3/include/libsmb_internal.h b/source3/include/libsmb_internal.h
index c9c83eb..fcdb513 100644
--- a/source3/include/libsmb_internal.h
+++ b/source3/include/libsmb_internal.h
@@ -238,13 +238,12 @@ struct SMBC_internal_data {
         }               printing;
 #endif
 
-#if 0 /* None available yet */
         /* SMB high-level functions */
         struct
         {
+                smbc_splice_fn                  splice_fn;
         }               smb;
 
-#endif
 	uint16_t	port;
 };	
 
@@ -365,6 +364,14 @@ SMBC_write_ctx(SMBCCTX *context,
                const void *buf,
                size_t count);
 
+off_t
+SMBC_splice_ctx(SMBCCTX *context,
+                SMBCFILE *srcfile,
+                SMBCFILE *dstfile,
+                off_t count,
+                int (*splice_cb)(off_t n, void *priv),
+                void *priv);
+
 int
 SMBC_close_ctx(SMBCCTX *context,
                SMBCFILE *file);
diff --git a/source3/include/libsmbclient.h b/source3/include/libsmbclient.h
index 42e41f7..faaab2e 100644
--- a/source3/include/libsmbclient.h
+++ b/source3/include/libsmbclient.h
@@ -872,6 +872,15 @@ typedef ssize_t (*smbc_write_fn)(SMBCCTX *c,
 smbc_write_fn smbc_getFunctionWrite(SMBCCTX *c);
 void smbc_setFunctionWrite(SMBCCTX *c, smbc_write_fn fn);
 
+typedef off_t (*smbc_splice_fn)(SMBCCTX *c,
+                                SMBCFILE *srcfile,
+                                SMBCFILE *dstfile,
+                                off_t count,
+                                int (*splice_cb)(off_t n, void *priv),
+                                void *priv);
+smbc_splice_fn smbc_getFunctionSplice(SMBCCTX *c);
+void smbc_setFunctionSplice(SMBCCTX *c, smbc_splice_fn fn);
+
 typedef int (*smbc_unlink_fn)(SMBCCTX *c,
                               const char *fname);
 smbc_unlink_fn smbc_getFunctionUnlink(SMBCCTX *c);
diff --git a/source3/libsmb/ABI/smbclient-0.2.1.sigs b/source3/libsmb/ABI/smbclient-0.2.2.sigs
similarity index 98%
copy from source3/libsmb/ABI/smbclient-0.2.1.sigs
copy to source3/libsmb/ABI/smbclient-0.2.2.sigs
index 1b7f6ce..fdafdd0 100644
--- a/source3/libsmb/ABI/smbclient-0.2.1.sigs
+++ b/source3/libsmb/ABI/smbclient-0.2.2.sigs
@@ -44,6 +44,7 @@ smbc_getFunctionRemovexattr: smbc_removexattr_fn (SMBCCTX *)
 smbc_getFunctionRename: smbc_rename_fn (SMBCCTX *)
 smbc_getFunctionRmdir: smbc_rmdir_fn (SMBCCTX *)
 smbc_getFunctionSetxattr: smbc_setxattr_fn (SMBCCTX *)
+smbc_getFunctionSplice: smbc_splice_fn (SMBCCTX *)
 smbc_getFunctionStat: smbc_stat_fn (SMBCCTX *)
 smbc_getFunctionStatVFS: smbc_statvfs_fn (SMBCCTX *)
 smbc_getFunctionTelldir: smbc_telldir_fn (SMBCCTX *)
@@ -130,6 +131,7 @@ smbc_setFunctionRemovexattr: void (SMBCCTX *, smbc_removexattr_fn)
 smbc_setFunctionRename: void (SMBCCTX *, smbc_rename_fn)
 smbc_setFunctionRmdir: void (SMBCCTX *, smbc_rmdir_fn)
 smbc_setFunctionSetxattr: void (SMBCCTX *, smbc_setxattr_fn)
+smbc_setFunctionSplice: void (SMBCCTX *, smbc_splice_fn)
 smbc_setFunctionStat: void (SMBCCTX *, smbc_stat_fn)
 smbc_setFunctionStatVFS: void (SMBCCTX *, smbc_statvfs_fn)
 smbc_setFunctionTelldir: void (SMBCCTX *, smbc_telldir_fn)
diff --git a/source3/libsmb/cli_smb2_fnum.c b/source3/libsmb/cli_smb2_fnum.c
index de4bd6f..21c0340 100644
--- a/source3/libsmb/cli_smb2_fnum.c
+++ b/source3/libsmb/cli_smb2_fnum.c
@@ -38,6 +38,7 @@
 #include "lib/util/tevent_ntstatus.h"
 #include "../libcli/security/security.h"
 #include "lib/util_ea.h"
+#include "librpc/gen_ndr/ndr_ioctl.h"
 
 struct smb2_hnd {
 	uint64_t fid_persistent;
@@ -2578,3 +2579,270 @@ NTSTATUS cli_smb2_writeall_recv(struct tevent_req *req,
 	}
 	return NT_STATUS_OK;
 }
+
+struct cli_smb2_splice_state {
+	struct tevent_context *ev;
+	struct cli_state *cli;
+	struct smb2_hnd *src_ph;
+	struct smb2_hnd *dst_ph;
+	int (*splice_cb)(off_t n, void *priv);
+	void *priv;
+	off_t written;
+	off_t size;
+	off_t src_offset;
+	off_t dst_offset;
+	bool resized;
+	struct req_resume_key_rsp resume_rsp;
+	struct srv_copychunk_copy cc_copy;
+};
+
+static void cli_splice_copychunk_send(struct cli_smb2_splice_state *state,
+				      struct tevent_req *req);
+
+static void cli_splice_copychunk_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_smb2_splice_state *state =
+		tevent_req_data(req,
+		struct cli_smb2_splice_state);
+	struct smbXcli_conn *conn = state->cli->conn;
+	DATA_BLOB out_input_buffer = data_blob_null;
+	DATA_BLOB out_output_buffer = data_blob_null;
+	struct srv_copychunk_rsp cc_copy_rsp;
+	enum ndr_err_code ndr_ret;
+	NTSTATUS status;
+
+	status = smb2cli_ioctl_recv(subreq, state,
+				    &out_input_buffer,
+				    &out_output_buffer);
+	TALLOC_FREE(subreq);
+	if ((!NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER) ||
+	     state->resized) && tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	ndr_ret = ndr_pull_struct_blob(&out_output_buffer, state, &cc_copy_rsp,
+			(ndr_pull_flags_fn_t)ndr_pull_srv_copychunk_rsp);
+	if (ndr_ret != NDR_ERR_SUCCESS) {
+		DEBUG(0, ("failed to unmarshall copy chunk rsp\n"));
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
+	if (NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
+		uint32_t max_chunks = MIN(cc_copy_rsp.chunks_written,
+			     cc_copy_rsp.total_bytes_written / cc_copy_rsp.chunk_bytes_written);
+		if ((cc_copy_rsp.chunk_bytes_written > smb2cli_conn_cc_chunk_len(conn) ||
+		     max_chunks > smb2cli_conn_cc_max_chunks(conn)) &&
+		     tevent_req_nterror(req, status)) {
+			return;
+		}
+
+		state->resized = true;
+		smb2cli_conn_set_cc_chunk_len(conn, cc_copy_rsp.chunk_bytes_written);
+		smb2cli_conn_set_cc_max_chunks(conn, max_chunks);
+	} else {
+		if ((state->src_offset > INT64_MAX - cc_copy_rsp.total_bytes_written) ||
+		    (state->dst_offset > INT64_MAX - cc_copy_rsp.total_bytes_written) ||
+		    (state->written > INT64_MAX - cc_copy_rsp.total_bytes_written)) {
+			tevent_req_nterror(req, NT_STATUS_FILE_TOO_LARGE);
+			return;
+		}
+		state->src_offset += cc_copy_rsp.total_bytes_written;
+		state->dst_offset += cc_copy_rsp.total_bytes_written;
+		state->written += cc_copy_rsp.total_bytes_written;
+		if (!state->splice_cb(state->written, state->priv)) {
+			tevent_req_nterror(req, NT_STATUS_CANCELLED);
+			return;
+		}
+	}
+
+	cli_splice_copychunk_send(state, req);
+}
+
+static void cli_splice_copychunk_send(struct cli_smb2_splice_state *state,
+				      struct tevent_req *req)
+{
+	struct tevent_req *subreq;
+	enum ndr_err_code ndr_ret;
+	struct smbXcli_conn *conn = state->cli->conn;
+	struct srv_copychunk_copy *cc_copy = &state->cc_copy;
+	off_t src_offset = state->src_offset;
+	off_t dst_offset = state->dst_offset;
+	uint32_t req_len = MIN(smb2cli_conn_cc_chunk_len(conn) * smb2cli_conn_cc_max_chunks(conn),
+			       state->size - state->written);
+	DATA_BLOB in_input_buffer = data_blob_null;
+	DATA_BLOB in_output_buffer = data_blob_null;
+
+	if (state->size - state->written == 0) {
+		tevent_req_done(req);
+		return;
+	}
+
+	cc_copy->chunk_count = 0;
+	while (req_len) {
+		cc_copy->chunks[cc_copy->chunk_count].source_off = src_offset;
+		cc_copy->chunks[cc_copy->chunk_count].target_off = dst_offset;
+		cc_copy->chunks[cc_copy->chunk_count].length = MIN(req_len,
+				                                   smb2cli_conn_cc_chunk_len(conn));
+		if (req_len < cc_copy->chunks[cc_copy->chunk_count].length) {
+			tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+			return;
+		}
+		req_len -= cc_copy->chunks[cc_copy->chunk_count].length;
+		if ((src_offset > INT64_MAX - cc_copy->chunks[cc_copy->chunk_count].length) ||
+		    (dst_offset > INT64_MAX - cc_copy->chunks[cc_copy->chunk_count].length)) {
+			tevent_req_nterror(req, NT_STATUS_FILE_TOO_LARGE);
+			return;
+		}
+		src_offset += cc_copy->chunks[cc_copy->chunk_count].length;
+		dst_offset += cc_copy->chunks[cc_copy->chunk_count].length;
+		cc_copy->chunk_count++;
+	}
+
+	ndr_ret = ndr_push_struct_blob(&in_input_buffer, state, cc_copy,
+				       (ndr_push_flags_fn_t)ndr_push_srv_copychunk_copy);
+	if (ndr_ret != NDR_ERR_SUCCESS) {
+		DEBUG(0, ("failed to marshall copy chunk req\n"));
+		tevent_req_nterror(req, NT_STATUS_INTERNAL_ERROR);
+		return;
+	}
+
+	subreq = smb2cli_ioctl_send(state, state->ev, state->cli->conn,
+			       state->cli->timeout,
+			       state->cli->smb2.session,
+			       state->cli->smb2.tcon,
+			       state->dst_ph->fid_persistent, /* in_fid_persistent */
+			       state->dst_ph->fid_volatile, /* in_fid_volatile */
+			       FSCTL_SRV_COPYCHUNK_WRITE,
+			       0, /* in_max_input_length */
+			       &in_input_buffer,
+			       12, /* in_max_output_length */
+			       &in_output_buffer,
+			       SMB2_IOCTL_FLAG_IS_FSCTL);
+	if (tevent_req_nomem(subreq, req)) {
+		return;
+	}
+	tevent_req_set_callback(subreq,
+				cli_splice_copychunk_done,
+				req);
+}
+
+static void cli_splice_key_done(struct tevent_req *subreq)
+{
+	struct tevent_req *req = tevent_req_callback_data(
+		subreq, struct tevent_req);
+	struct cli_smb2_splice_state *state =
+		tevent_req_data(req,
+		struct cli_smb2_splice_state);
+	enum ndr_err_code ndr_ret;
+	NTSTATUS status;
+
+	DATA_BLOB out_input_buffer = data_blob_null;
+	DATA_BLOB out_output_buffer = data_blob_null;
+
+	status = smb2cli_ioctl_recv(subreq, state,
+				    &out_input_buffer,
+				    &out_output_buffer);
+	TALLOC_FREE(subreq);
+	if (tevent_req_nterror(req, status)) {
+		return;
+	}
+
+	ndr_ret = ndr_pull_struct_blob(&out_output_buffer,
+			state, &state->resume_rsp,
+			(ndr_pull_flags_fn_t)ndr_pull_req_resume_key_rsp);
+	if (ndr_ret != NDR_ERR_SUCCESS) {
+		DEBUG(0, ("failed to unmarshall resume key rsp\n"));
+		tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);
+		return;
+	}
+
+	memcpy(&state->cc_copy.source_key,
+	       &state->resume_rsp.resume_key,
+	       sizeof state->resume_rsp.resume_key);
+
+	cli_splice_copychunk_send(state, req);
+}
+
+struct tevent_req *cli_smb2_splice_send(TALLOC_CTX *mem_ctx,
+				struct tevent_context *ev,
+				struct cli_state *cli,
+				uint16_t src_fnum, uint16_t dst_fnum,
+				off_t size, off_t src_offset, off_t dst_offset,
+				int (*splice_cb)(off_t n, void *priv),
+				void *priv)
+{
+	struct tevent_req *req;
+	struct tevent_req *subreq;
+	struct cli_smb2_splice_state *state;
+	NTSTATUS status;
+	DATA_BLOB in_input_buffer = data_blob_null;
+	DATA_BLOB in_output_buffer = data_blob_null;
+
+	req = tevent_req_create(mem_ctx, &state, struct cli_smb2_splice_state);
+	if (req == NULL) {
+		return NULL;
+	}
+	state->cli = cli;
+	state->ev = ev;
+	state->splice_cb = splice_cb;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list