2 Unix SMB/CIFS implementation.
3 SMB read/write torture tester
4 Copyright (C) Andrew Tridgell 1997-2003
5 Copyright (C) Jelmer Vernooij 2006
6 Copyright (C) David Mulder 2019
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "torture/smbtorture.h"
23 #include "libcli/smb2/smb2.h"
24 #include "libcli/smb2/smb2_calls.h"
25 #include "torture/torture.h"
26 #include "torture/smb2/proto.h"
28 static bool run_smb2_readwritetest(struct torture_context
*tctx
,
29 struct smb2_tree
*t1
, struct smb2_tree
*t2
)
31 const char *lockfname
= "torture2.lck";
32 struct smb2_create f1
= {0};
33 struct smb2_create f2
= {0};
34 struct smb2_handle h1
= {{0}};
35 struct smb2_handle h2
= {{0}};
42 ret
= smb2_deltree(t1
, lockfname
);
43 torture_assert(tctx
, ret
!= -1, "unlink failed");
45 f1
.in
.desired_access
= SEC_FILE_ALL
;
46 f1
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
47 NTCREATEX_SHARE_ACCESS_WRITE
;
48 f1
.in
.create_disposition
= FILE_CREATE
;
49 f1
.in
.fname
= lockfname
;
51 status
= smb2_create(t1
, tctx
, &f1
);
52 torture_assert_ntstatus_ok_goto(tctx
, status
, correct
, done
,
53 talloc_asprintf(tctx
, "first open read/write of %s failed (%s)",
54 lockfname
, nt_errstr(status
)));
55 h1
= f1
.out
.file
.handle
;
57 f2
.in
.desired_access
= SEC_FILE_READ_DATA
;
58 f2
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
|
59 NTCREATEX_SHARE_ACCESS_WRITE
;
60 f2
.in
.create_disposition
= FILE_OPEN
;
61 f2
.in
.fname
= lockfname
;
63 status
= smb2_create(t2
, tctx
, &f2
);
64 torture_assert_ntstatus_ok_goto(tctx
, status
, correct
, done
,
65 talloc_asprintf(tctx
, "second open read-only of %s failed (%s)",
66 lockfname
, nt_errstr(status
)));
67 h2
= f2
.out
.file
.handle
;
69 torture_comment(tctx
, "Checking data integrity over %d ops\n",
72 for (i
= 0; i
< torture_numops
; i
++) {
73 struct smb2_write w
= {0};
74 struct smb2_read r
= {0};
75 size_t buf_size
= ((unsigned int)random()%(sizeof(buf
)-1))+ 1;
78 if (torture_setting_bool(tctx
, "progress", true)) {
79 torture_comment(tctx
, "%d\r", i
); fflush(stdout
);
83 generate_random_buffer(buf
, buf_size
);
85 w
.in
.file
.handle
= h1
;
88 w
.in
.data
.length
= buf_size
;
90 status
= smb2_write(t1
, &w
);
91 if (!NT_STATUS_IS_OK(status
) || w
.out
.nwritten
!= buf_size
) {
92 torture_comment(tctx
, "write failed (%s)\n",
94 torture_result(tctx
, TORTURE_FAIL
,
95 "wrote %d, expected %d\n",
96 (int)w
.out
.nwritten
, (int)buf_size
);
101 r
.in
.file
.handle
= h2
;
103 r
.in
.length
= buf_size
;
104 status
= smb2_read(t2
, tctx
, &r
);
105 if (!NT_STATUS_IS_OK(status
) || r
.out
.data
.length
!= buf_size
) {
106 torture_comment(tctx
, "read failed (%s)\n",
108 torture_result(tctx
, TORTURE_FAIL
,
109 "read %d, expected %d\n",
110 (int)r
.out
.data
.length
, (int)buf_size
);
115 torture_assert_mem_equal_goto(tctx
, r
.out
.data
.data
, buf
,
116 buf_size
, correct
, done
, "read/write compare failed\n");
119 status
= smb2_util_close(t2
, h2
);
120 torture_assert_ntstatus_ok_goto(tctx
, status
, correct
, done
,
121 talloc_asprintf(tctx
, "close failed (%s)", nt_errstr(status
)));
124 status
= smb2_util_close(t1
, h1
);
125 torture_assert_ntstatus_ok_goto(tctx
, status
, correct
, done
,
126 talloc_asprintf(tctx
, "close failed (%s)", nt_errstr(status
)));
130 if (!smb2_util_handle_empty(h2
)) {
131 smb2_util_close(t2
, h2
);
133 if (!smb2_util_handle_empty(h1
)) {
134 smb2_util_close(t1
, h1
);
137 status
= smb2_util_unlink(t1
, lockfname
);
138 if (!NT_STATUS_IS_OK(status
)) {
139 torture_comment(tctx
, "unlink failed (%s)", nt_errstr(status
));
146 static bool run_smb2_wrap_readwritetest(struct torture_context
*tctx
,
147 struct smb2_tree
*tree1
,
148 struct smb2_tree
*tree2
)
150 return run_smb2_readwritetest(tctx
, tree1
, tree1
);
153 struct torture_suite
*torture_smb2_readwrite_init(TALLOC_CTX
*ctx
)
155 struct torture_suite
*suite
= torture_suite_create(ctx
, "rw");
157 torture_suite_add_2smb2_test(suite
, "rw1", run_smb2_readwritetest
);
158 torture_suite_add_2smb2_test(suite
, "rw2", run_smb2_wrap_readwritetest
);
160 suite
->description
= talloc_strdup(suite
, "SMB2 Samba4 Read/Write");