[SCM] Samba Shared Repository - branch master updated

Jeremy Allison jra at samba.org
Thu Sep 22 22:24:03 UTC 2016


The branch, master has been updated
       via  bff3e5e torture/ioctl: switch sparse src/dest dup ext behaviour
       via  710f067 torture/smb2/ioctl: don't check for untruncated dest failure
       via  281ce60 torture/ioctl: add FSCTL_DUP_EXTENTS_TO_FILE tests
       via  dd02a5c libcli: add FILE_SUPPORTS_BLOCK_REFCOUNTING
       via  0ad260e idl/ioctl: fix DUPLICATE_EXTENTS_TO_FILE fid field
       via  de7d7ac torture/ioctl: make sparse file support check generic
      from  872a18b s4-torture: parse spoolss ndr packets using iremotewinspool calls

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


- Log -----------------------------------------------------------------
commit bff3e5efba36395a68f134bf58566611b65f35d5
Author: David Disseldorp <ddiss at samba.org>
Date:   Thu Sep 22 00:00:07 2016 -0700

    torture/ioctl: switch sparse src/dest dup ext behaviour
    
    Contrary to 2.3.8 FSCTL_DUPLICATE_EXTENTS_TO_FILE
    STATUS_NOT_SUPPORTED: Target file is sparse, while source is a
    non-sparse file.
    
    ...Windows Server 2016 RTM appears to respond the other way around.
    
    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 Sep 23 00:23:09 CEST 2016 on sn-devel-144

commit 710f06702b9243dcbad3c2170271a030d2ff5a01
Author: David Disseldorp <ddiss at samba.org>
Date:   Wed Sep 21 16:43:54 2016 -0700

    torture/smb2/ioctl: don't check for untruncated dest failure
    
    This should fail, but passes against WS2016 RTM...
    
    2.3.8 FSCTL_DUPLICATE_EXTENTS_TO_FILE Reply:
    The destination range extends beyond the target file's allocation size.
    The caller might need to increase the target's allocation size before
    using FSCTL_DUPLICATE_EXTENTS_TO_FILE.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 281ce600de9a8eafbecf82a5444e922a31311552
Author: David Disseldorp <ddiss at samba.org>
Date:   Fri Jan 30 12:59:42 2015 +0100

    torture/ioctl: add FSCTL_DUP_EXTENTS_TO_FILE tests
    
    FSCTL_DUPLICATE_EXTENTS_TO_FILE is yet another copy offload mechanism,
    this time only targeting COW FSes, where the request triggers a meta-
    data only clone of the source range.
    
    These tests attempt to cover most of the normal use cases, as well as
    number of more exotic scenarios.
    
    FILE_SUPPORTS_BLOCK_REFCOUNTING FS attribute presence is checked prior
    to running the tests, so they will currently be skipped during Samba
    self test (which lacks the flag).
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit dd02a5c91763e83bae2e453f801a0f868cd7ac29
Author: David Disseldorp <ddiss at samba.org>
Date:   Mon Jul 20 17:56:34 2015 +0200

    libcli: add FILE_SUPPORTS_BLOCK_REFCOUNTING
    
    This FS attribute is used to advertise whether the server supports
    FSCTL_DUP_EXTENTS_TO_FILE requests.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit 0ad260e8f08b5f91e55468892e52dcfe9eee536a
Author: David Disseldorp <ddiss at samba.org>
Date:   Tue Sep 20 09:10:37 2016 -0700

    idl/ioctl: fix DUPLICATE_EXTENTS_TO_FILE fid field
    
    This idl was based on an earlier draft documentation version. The
    current documentation now shows:
    "SourceFileID (16 bytes): An SMB2_FILEID structure, as specified in
    [MS-SMB2] section 2.2.14.1, that is an identifier of the open to the
    source file.".
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

commit de7d7ac608889784965f2fec08f9a721f20d22eb
Author: David Disseldorp <ddiss at samba.org>
Date:   Mon Jul 20 17:52:44 2015 +0200

    torture/ioctl: make sparse file support check generic
    
    Rename test_ioctl_sparse_fs_supported() to test_ioctl_fs_supported() and
    allow callers to query generic FileSystemAttributes flags via the new
    fs_support_flags parameter.
    
    Signed-off-by: David Disseldorp <ddiss at samba.org>
    Reviewed-by: Jeremy Allison <jra at samba.org>

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

Summary of changes:
 libcli/smb/smb_constants.h   |    1 +
 librpc/idl/ioctl.idl         |    3 +-
 source4/torture/smb2/ioctl.c | 1374 ++++++++++++++++++++++++++++++++++++++++--
 3 files changed, 1332 insertions(+), 46 deletions(-)


Changeset truncated at 500 lines:

diff --git a/libcli/smb/smb_constants.h b/libcli/smb/smb_constants.h
index 2fcb590..b963c73 100644
--- a/libcli/smb/smb_constants.h
+++ b/libcli/smb/smb_constants.h
@@ -402,6 +402,7 @@ enum csc_policy {
 #define FILE_SUPPORTS_ENCRYPTION        0x00020000
 #define FILE_NAMED_STREAMS              0x00040000
 #define FILE_READ_ONLY_VOLUME           0x00080000
+#define FILE_SUPPORTS_BLOCK_REFCOUNTING	0x08000000
 
 /* ShareAccess field. */
 #define FILE_SHARE_NONE 0 /* Cannot be used in bitmask. */
diff --git a/librpc/idl/ioctl.idl b/librpc/idl/ioctl.idl
index dbeef14..eb2dc8a 100644
--- a/librpc/idl/ioctl.idl
+++ b/librpc/idl/ioctl.idl
@@ -89,8 +89,7 @@ interface copychunk
 	} fsctl_offload_write_output;
 
 	typedef [public] struct {
-		/* The FileHandle field is the volatile part of the fileid */
-		hyper fid_volatile;
+		uint8 source_fid[16];
 		hyper source_off;
 		hyper target_off;
 		hyper byte_count;
diff --git a/source4/torture/smb2/ioctl.c b/source4/torture/smb2/ioctl.c
index 0aa3714..2baf7b6 100644
--- a/source4/torture/smb2/ioctl.c
+++ b/source4/torture/smb2/ioctl.c
@@ -3,7 +3,7 @@
 
    test suite for SMB2 ioctl operations
 
-   Copyright (C) David Disseldorp 2011-2015
+   Copyright (C) David Disseldorp 2011-2016
 
    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
@@ -2586,11 +2586,16 @@ static bool test_ioctl_network_interface_info(struct torture_context *torture,
 	return true;
 }
 
-static NTSTATUS test_ioctl_sparse_fs_supported(struct torture_context *torture,
-					       struct smb2_tree *tree,
-					       TALLOC_CTX *mem_ctx,
-					       struct smb2_handle *fh,
-					       bool *sparse_support)
+/*
+ * Check whether all @fs_support_flags are set in the server's
+ * RAW_QFS_ATTRIBUTE_INFORMATION FileSystemAttributes response.
+ */
+static NTSTATUS test_ioctl_fs_supported(struct torture_context *torture,
+					struct smb2_tree *tree,
+					TALLOC_CTX *mem_ctx,
+					struct smb2_handle *fh,
+					uint64_t fs_support_flags,
+					bool *supported)
 {
 	NTSTATUS status;
 	union smb_fsinfo info;
@@ -2603,10 +2608,11 @@ static NTSTATUS test_ioctl_sparse_fs_supported(struct torture_context *torture,
 		return status;
 	}
 
-	if (info.attribute_info.out.fs_attr & FILE_SUPPORTS_SPARSE_FILES) {
-		*sparse_support = true;
+	if ((info.attribute_info.out.fs_attr & fs_support_flags)
+							== fs_support_flags) {
+		*supported = true;
 	} else {
-		*sparse_support = false;
+		*supported = false;
 	}
 	return NT_STATUS_OK;
 }
@@ -2671,8 +2677,8 @@ static bool test_ioctl_sparse_file_flag(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -2722,8 +2728,8 @@ static bool test_ioctl_sparse_file_attr(struct torture_context *torture,
 			(FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_SPARSE));
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -2753,8 +2759,8 @@ static bool test_ioctl_sparse_dir_flag(struct torture_context *torture,
 				    FILE_ATTRIBUTE_DIRECTORY);
 	torture_assert(torture, ok, "setup sparse directory");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &dirh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &dirh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, dirh);
@@ -2794,8 +2800,8 @@ static bool test_ioctl_sparse_set_nobuf(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -2864,8 +2870,8 @@ static bool test_ioctl_sparse_set_oversize(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -3024,8 +3030,8 @@ static bool test_ioctl_sparse_qar(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -3149,8 +3155,8 @@ static bool test_ioctl_sparse_qar_malformed(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -3282,8 +3288,8 @@ static bool test_ioctl_sparse_punch(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -3423,8 +3429,8 @@ static bool test_ioctl_sparse_hole_dealloc(struct torture_context *torture,
 	torture_assert(torture, ok, "setup file 1");
 
 	/* check for FS sparse file */
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -3680,8 +3686,8 @@ static bool test_ioctl_sparse_compressed(struct torture_context *torture,
 	torture_assert(torture, ok, "setup file 1");
 
 	/* check for FS sparse file and compression support */
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -3788,8 +3794,8 @@ static bool test_ioctl_sparse_copy_chunk(struct torture_context *torture,
 	torture_assert(torture, ok, "setup file");
 
 	/* check for FS sparse file support */
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &src_h,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &src_h,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	smb2_util_close(tree, src_h);
 	if (!ok) {
@@ -3988,8 +3994,8 @@ static bool test_ioctl_sparse_punch_invalid(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -4096,8 +4102,8 @@ static bool test_ioctl_sparse_perms(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	smb2_util_close(tree, fh);
 	if (!ok) {
@@ -4339,8 +4345,8 @@ static bool test_ioctl_sparse_lck(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		torture_skip(torture, "Sparse files not supported\n");
@@ -4446,8 +4452,8 @@ static bool test_ioctl_sparse_qar_ob1(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		torture_skip(torture, "Sparse files not supported\n");
@@ -4602,8 +4608,8 @@ static bool test_ioctl_sparse_qar_multi(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		torture_skip(torture, "Sparse files not supported\n");
@@ -4675,8 +4681,8 @@ static bool test_ioctl_sparse_qar_overflow(struct torture_context *torture,
 				    FILE_ATTRIBUTE_NORMAL);
 	torture_assert(torture, ok, "setup file");
 
-	status = test_ioctl_sparse_fs_supported(torture, tree, tmp_ctx, &fh,
-						&ok);
+	status = test_ioctl_fs_supported(torture, tree, tmp_ctx, &fh,
+					 FILE_SUPPORTS_SPARSE_FILES, &ok);
 	torture_assert_ntstatus_ok(torture, status, "SMB2_GETINFO_FS");
 	if (!ok) {
 		smb2_util_close(tree, fh);
@@ -4846,8 +4852,1260 @@ static bool test_ioctl_trim_simple(struct torture_context *torture,
 	return true;
 }
 
+static bool test_setup_dup_extents(struct torture_context *tctx,
+				   struct smb2_tree *tree,
+				   TALLOC_CTX *mem_ctx,
+				   struct smb2_handle *src_h,
+				   uint64_t src_size,
+				   uint32_t src_desired_access,
+				   struct smb2_handle *dest_h,
+				   uint64_t dest_size,
+				   uint32_t dest_desired_access,
+				   struct fsctl_dup_extents_to_file *dup_ext_buf,
+				   union smb_ioctl *ioctl)
+{
+	bool ok;
+
+	ok = test_setup_create_fill(tctx, tree, mem_ctx, FNAME,
+				    src_h, src_size, src_desired_access,
+				    FILE_ATTRIBUTE_NORMAL);
+	torture_assert(tctx, ok, "src file create fill");
+
+	ok = test_setup_create_fill(tctx, tree, mem_ctx, FNAME2,
+				    dest_h, dest_size, dest_desired_access,
+				    FILE_ATTRIBUTE_NORMAL);
+	torture_assert(tctx, ok, "dest file create fill");
+
+	ZERO_STRUCTPN(ioctl);
+	ioctl->smb2.level = RAW_IOCTL_SMB2;
+	ioctl->smb2.in.file.handle = *dest_h;
+	ioctl->smb2.in.function = FSCTL_DUP_EXTENTS_TO_FILE;
+	ioctl->smb2.in.max_response_size = 0;
+	ioctl->smb2.in.flags = SMB2_IOCTL_FLAG_IS_FSCTL;
+
+	ZERO_STRUCTPN(dup_ext_buf);
+	smb2_push_handle(dup_ext_buf->source_fid, src_h);
+
+	return true;
+}
+
+static bool test_ioctl_dup_extents_simple(struct torture_context *tctx,
+					  struct smb2_tree *tree)
+{
+	struct smb2_handle src_h;
+	struct smb2_handle dest_h;
+	NTSTATUS status;
+	union smb_ioctl ioctl;
+	TALLOC_CTX *tmp_ctx = talloc_new(tree);
+	struct fsctl_dup_extents_to_file dup_ext_buf;
+	enum ndr_err_code ndr_ret;
+	union smb_fileinfo io;
+	union smb_setfileinfo sinfo;
+	bool ok;
+
+	ok = test_setup_dup_extents(tctx, tree, tmp_ctx,
+				    &src_h, 4096, /* fill 4096 byte src file */
+				    SEC_RIGHTS_FILE_ALL,
+				    &dest_h, 0,	/* 0 byte dest file */
+				    SEC_RIGHTS_FILE_ALL,
+				    &dup_ext_buf,
+				    &ioctl);
+	if (!ok) {
+		torture_fail(tctx, "setup dup extents error");
+	}
+
+	status = test_ioctl_fs_supported(tctx, tree, tmp_ctx, &src_h,
+					 FILE_SUPPORTS_BLOCK_REFCOUNTING, &ok);
+	torture_assert_ntstatus_ok(tctx, status, "SMB2_GETINFO_FS");
+	if (!ok) {
+		smb2_util_close(tree, src_h);
+		smb2_util_close(tree, dest_h);
+		talloc_free(tmp_ctx);
+		torture_skip(tctx, "block refcounting not supported\n");
+	}
+
+	/* extend dest to match src len */
+	ZERO_STRUCT(sinfo);
+	sinfo.end_of_file_info.level =
+		RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+	sinfo.end_of_file_info.in.file.handle = dest_h;
+	sinfo.end_of_file_info.in.size = 4096;
+	status = smb2_setinfo_file(tree, &sinfo);
+	torture_assert_ntstatus_ok(tctx, status, "smb2_setinfo_file");
+
+	/* copy all src file data */
+	dup_ext_buf.source_off = 0;
+	dup_ext_buf.target_off = 0;
+	dup_ext_buf.byte_count = 4096;
+
+	ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
+				       &dup_ext_buf,
+		       (ndr_push_flags_fn_t)ndr_push_fsctl_dup_extents_to_file);
+	torture_assert_ndr_success(tctx, ndr_ret,
+				   "ndr_push_fsctl_dup_extents_to_file");
+
+	status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
+	torture_assert_ntstatus_ok(tctx, status,
+				   "FSCTL_DUP_EXTENTS_TO_FILE");
+
+	/* the file size shouldn't have been changed by this operation! */
+	ZERO_STRUCT(io);
+	io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+	io.generic.in.file.handle = dest_h;
+	status = smb2_getinfo_file(tree, tmp_ctx, &io);
+	torture_assert_ntstatus_ok(tctx, status, "getinfo");
+	torture_assert_int_equal(tctx, (int)io.all_info2.out.size,
+				 4096, "size after IO");
+
+	smb2_util_close(tree, src_h);
+	smb2_util_close(tree, dest_h);
+
+	/* reopen for pattern check */
+	ok = test_setup_open(tctx, tree, tmp_ctx, FNAME, &src_h,
+			     SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL);
+	torture_assert_ntstatus_ok(tctx, status, "src open after dup");
+	ok = test_setup_open(tctx, tree, tmp_ctx, FNAME2, &dest_h,
+			     SEC_RIGHTS_FILE_ALL, FILE_ATTRIBUTE_NORMAL);
+	torture_assert_ntstatus_ok(tctx, status, "dest open after dup");
+
+	ok = check_pattern(tctx, tree, tmp_ctx, src_h, 0, 4096, 0);
+	if (!ok) {
+		torture_fail(tctx, "inconsistent src file data");
+	}
+
+	ok = check_pattern(tctx, tree, tmp_ctx, dest_h, 0, 4096, 0);
+	if (!ok) {
+		torture_fail(tctx, "inconsistent dest file data");
+	}
+
+	smb2_util_close(tree, src_h);
+	smb2_util_close(tree, dest_h);
+	talloc_free(tmp_ctx);
+	return true;
+}
+
+static bool test_ioctl_dup_extents_len_beyond_dest(struct torture_context *tctx,
+						   struct smb2_tree *tree)
+{
+	struct smb2_handle src_h;
+	struct smb2_handle dest_h;
+	NTSTATUS status;
+	union smb_ioctl ioctl;
+	TALLOC_CTX *tmp_ctx = talloc_new(tree);
+	struct fsctl_dup_extents_to_file dup_ext_buf;
+	enum ndr_err_code ndr_ret;
+	union smb_fileinfo io;
+	union smb_setfileinfo sinfo;
+	bool ok;
+
+	ok = test_setup_dup_extents(tctx, tree, tmp_ctx,
+				    &src_h, 32768, /* fill 32768 byte src file */
+				    SEC_RIGHTS_FILE_ALL,
+				    &dest_h, 0,	/* 0 byte dest file */
+				    SEC_RIGHTS_FILE_ALL,
+				    &dup_ext_buf,
+				    &ioctl);
+	if (!ok) {
+		torture_fail(tctx, "setup dup extents error");
+	}
+
+	status = test_ioctl_fs_supported(tctx, tree, tmp_ctx, &src_h,
+					 FILE_SUPPORTS_BLOCK_REFCOUNTING, &ok);
+	torture_assert_ntstatus_ok(tctx, status, "SMB2_GETINFO_FS");
+	if (!ok) {
+		smb2_util_close(tree, src_h);
+		smb2_util_close(tree, dest_h);
+		talloc_free(tmp_ctx);
+		torture_skip(tctx, "block refcounting not supported\n");
+	}
+
+	ZERO_STRUCT(io);
+	io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+	io.generic.in.file.handle = dest_h;
+	status = smb2_getinfo_file(tree, tmp_ctx, &io);
+	torture_assert_ntstatus_ok(tctx, status, "getinfo");
+	torture_assert_int_equal(tctx, (int)io.all_info2.out.size,
+				 0, "size after IO");
+
+	/* copy all src file data */
+	dup_ext_buf.source_off = 0;
+	dup_ext_buf.target_off = 0;
+	dup_ext_buf.byte_count = 32768;
+
+	ndr_ret = ndr_push_struct_blob(&ioctl.smb2.in.out, tmp_ctx,
+				       &dup_ext_buf,
+		       (ndr_push_flags_fn_t)ndr_push_fsctl_dup_extents_to_file);
+	torture_assert_ndr_success(tctx, ndr_ret,
+				   "ndr_push_fsctl_dup_extents_to_file");
+
+	status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
+#if 0
+	/*
+	 * 2.3.8 FSCTL_DUPLICATE_EXTENTS_TO_FILE Reply - this should fail, but
+	 * passes against WS2016 RTM!
+	 */
+	torture_assert_ntstatus_equal(tctx, status, NT_STATUS_NOT_SUPPORTED,
+				   "FSCTL_DUP_EXTENTS_TO_FILE");
+#endif
+
+	/* the file sizes shouldn't have been changed */
+	ZERO_STRUCT(io);
+	io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+	io.generic.in.file.handle = src_h;
+	status = smb2_getinfo_file(tree, tmp_ctx, &io);
+	torture_assert_ntstatus_ok(tctx, status, "getinfo");
+	torture_assert_int_equal(tctx, (int)io.all_info2.out.size,
+				 32768, "size after IO");
+
+	ZERO_STRUCT(io);
+	io.generic.level = RAW_FILEINFO_SMB2_ALL_INFORMATION;
+	io.generic.in.file.handle = dest_h;
+	status = smb2_getinfo_file(tree, tmp_ctx, &io);
+	torture_assert_ntstatus_ok(tctx, status, "getinfo");
+	torture_assert_int_equal(tctx, (int)io.all_info2.out.size,
+				 0, "size after IO");
+
+	/* extend dest */
+	ZERO_STRUCT(sinfo);
+	sinfo.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFORMATION;
+	sinfo.end_of_file_info.in.file.handle = dest_h;
+	sinfo.end_of_file_info.in.size = 32768;
+	status = smb2_setinfo_file(tree, &sinfo);
+	torture_assert_ntstatus_ok(tctx, status, "smb2_setinfo_file");
+
+	ok = check_zero(tctx, tree, tmp_ctx, dest_h, 0, 32768);
+	if (!ok) {
+		torture_fail(tctx, "inconsistent file data");
+	}
+
+	/* reissue ioctl, now with enough space */
+	status = smb2_ioctl(tree, tmp_ctx, &ioctl.smb2);
+	torture_assert_ntstatus_ok(tctx, status,
+				   "FSCTL_DUP_EXTENTS_TO_FILE");
+
+	ok = check_pattern(tctx, tree, tmp_ctx, dest_h, 0, 32768, 0);
+	if (!ok) {


-- 
Samba Shared Repository



More information about the samba-cvs mailing list