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 <dd...@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 <dd...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>
    
    Autobuild-User(master): Jeremy Allison <j...@samba.org>
    Autobuild-Date(master): Fri Sep 23 00:23:09 CEST 2016 on sn-devel-144

commit 710f06702b9243dcbad3c2170271a030d2ff5a01
Author: David Disseldorp <dd...@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 <dd...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 281ce600de9a8eafbecf82a5444e922a31311552
Author: David Disseldorp <dd...@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 <dd...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit dd02a5c91763e83bae2e453f801a0f868cd7ac29
Author: David Disseldorp <dd...@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 <dd...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit 0ad260e8f08b5f91e55468892e52dcfe9eee536a
Author: David Disseldorp <dd...@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 <dd...@samba.org>
    Reviewed-by: Jeremy Allison <j...@samba.org>

commit de7d7ac608889784965f2fec08f9a721f20d22eb
Author: David Disseldorp <dd...@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 <dd...@samba.org>
    Reviewed-by: Jeremy Allison <j...@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

Reply via email to