2 Unix SMB/CIFS implementation.
3 test suite for various lock operations
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/raw/raw_proto.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
28 #include "libcli/composite/composite.h"
29 #include "libcli/smb_composite/smb_composite.h"
30 #include "lib/cmdline/popt_common.h"
31 #include "param/param.h"
33 #define CHECK_STATUS(status, correct) do { \
34 if (!NT_STATUS_EQUAL(status, correct)) { \
35 torture_result(tctx, TORTURE_FAIL, \
36 "(%s) Incorrect status %s - should be %s\n", \
37 __location__, nt_errstr(status), nt_errstr(correct)); \
42 #define CHECK_STATUS_CONT(status, correct) do { \
43 if (!NT_STATUS_EQUAL(status, correct)) { \
44 torture_result(tctx, TORTURE_FAIL, \
45 "(%s) Incorrect status %s - should be %s\n", \
46 __location__, nt_errstr(status), nt_errstr(correct)); \
50 #define CHECK_STATUS_OR(status, correct1, correct2) do { \
51 if ((!NT_STATUS_EQUAL(status, correct1)) && \
52 (!NT_STATUS_EQUAL(status, correct2))) { \
53 torture_result(tctx, TORTURE_FAIL, \
54 "(%s) Incorrect status %s - should be %s or %s\n", \
55 __location__, nt_errstr(status), nt_errstr(correct1), \
56 nt_errstr(correct2)); \
61 #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
62 if ((!NT_STATUS_EQUAL(status, correct1)) && \
63 (!NT_STATUS_EQUAL(status, correct2))) { \
64 torture_result(tctx, TORTURE_FAIL, \
65 "(%s) Incorrect status %s - should be %s or %s\n", \
66 __location__, nt_errstr(status), nt_errstr(correct1), \
67 nt_errstr(correct2)); \
70 #define BASEDIR "\\testlock"
72 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
73 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
74 #define TARGET_IS_WINDOWS(_tctx) \
75 ((torture_setting_bool(_tctx, "w2k3", false)) || \
76 (torture_setting_bool(_tctx, "w2k8", false)) || \
77 (torture_setting_bool(_tctx, "win7", false)))
78 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
79 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
81 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
82 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
83 #define TARGET_SUPPORTS_SMBEXIT(_tctx) \
84 (torture_setting_bool(_tctx, "smbexit_pdu_support", true))
85 #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
86 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
87 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
88 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
89 #define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \
90 (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true))
92 test SMBlock and SMBunlock ops
94 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
100 const char *fname
= BASEDIR
"\\test.txt";
102 if (!TARGET_SUPPORTS_SMBLOCK(tctx
))
103 torture_skip(tctx
, "Target does not support the SMBlock PDU");
105 if (!torture_setup_dir(cli
, BASEDIR
)) {
109 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
110 io
.generic
.level
= RAW_LOCK_LOCK
;
112 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
113 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
114 "Failed to create %s - %s\n",
115 fname
, smbcli_errstr(cli
->tree
)));
117 torture_comment(tctx
, "Trying 0/0 lock\n");
118 io
.lock
.level
= RAW_LOCK_LOCK
;
119 io
.lock
.in
.file
.fnum
= fnum
;
120 io
.lock
.in
.count
= 0;
121 io
.lock
.in
.offset
= 0;
122 status
= smb_raw_lock(cli
->tree
, &io
);
123 CHECK_STATUS(status
, NT_STATUS_OK
);
125 status
= smb_raw_lock(cli
->tree
, &io
);
126 CHECK_STATUS(status
, NT_STATUS_OK
);
128 io
.lock
.level
= RAW_LOCK_UNLOCK
;
129 status
= smb_raw_lock(cli
->tree
, &io
);
130 CHECK_STATUS(status
, NT_STATUS_OK
);
132 torture_comment(tctx
, "Trying 0/1 lock\n");
133 io
.lock
.level
= RAW_LOCK_LOCK
;
134 io
.lock
.in
.file
.fnum
= fnum
;
135 io
.lock
.in
.count
= 1;
136 io
.lock
.in
.offset
= 0;
137 status
= smb_raw_lock(cli
->tree
, &io
);
138 CHECK_STATUS(status
, NT_STATUS_OK
);
140 status
= smb_raw_lock(cli
->tree
, &io
);
141 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
143 io
.lock
.level
= RAW_LOCK_UNLOCK
;
144 status
= smb_raw_lock(cli
->tree
, &io
);
145 CHECK_STATUS(status
, NT_STATUS_OK
);
146 io
.lock
.level
= RAW_LOCK_UNLOCK
;
147 status
= smb_raw_lock(cli
->tree
, &io
);
148 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
150 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
151 io
.lock
.level
= RAW_LOCK_LOCK
;
152 io
.lock
.in
.file
.fnum
= fnum
;
153 io
.lock
.in
.count
= 4000;
154 io
.lock
.in
.offset
= 0xEEFFFFFF;
155 status
= smb_raw_lock(cli
->tree
, &io
);
156 CHECK_STATUS(status
, NT_STATUS_OK
);
158 status
= smb_raw_lock(cli
->tree
, &io
);
159 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
161 io
.lock
.level
= RAW_LOCK_UNLOCK
;
162 status
= smb_raw_lock(cli
->tree
, &io
);
163 CHECK_STATUS(status
, NT_STATUS_OK
);
164 io
.lock
.level
= RAW_LOCK_UNLOCK
;
165 status
= smb_raw_lock(cli
->tree
, &io
);
166 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
168 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
169 io
.lock
.level
= RAW_LOCK_LOCK
;
170 io
.lock
.in
.file
.fnum
= fnum
;
171 io
.lock
.in
.count
= 4000;
172 io
.lock
.in
.offset
= 0xEEFFFFFF;
173 status
= smb_raw_lock(cli
->tree
, &io
);
174 CHECK_STATUS(status
, NT_STATUS_OK
);
176 status
= smb_raw_lock(cli
->tree
, &io
);
177 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
179 io
.lock
.level
= RAW_LOCK_UNLOCK
;
180 status
= smb_raw_lock(cli
->tree
, &io
);
181 CHECK_STATUS(status
, NT_STATUS_OK
);
182 io
.lock
.level
= RAW_LOCK_UNLOCK
;
183 status
= smb_raw_lock(cli
->tree
, &io
);
184 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
186 torture_comment(tctx
, "Trying max lock\n");
187 io
.lock
.level
= RAW_LOCK_LOCK
;
188 io
.lock
.in
.file
.fnum
= fnum
;
189 io
.lock
.in
.count
= 4000;
190 io
.lock
.in
.offset
= 0xEF000000;
191 status
= smb_raw_lock(cli
->tree
, &io
);
192 CHECK_STATUS(status
, NT_STATUS_OK
);
194 status
= smb_raw_lock(cli
->tree
, &io
);
195 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
197 io
.lock
.level
= RAW_LOCK_UNLOCK
;
198 status
= smb_raw_lock(cli
->tree
, &io
);
199 CHECK_STATUS(status
, NT_STATUS_OK
);
200 io
.lock
.level
= RAW_LOCK_UNLOCK
;
201 status
= smb_raw_lock(cli
->tree
, &io
);
202 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
204 torture_comment(tctx
, "Trying wrong pid unlock\n");
205 io
.lock
.level
= RAW_LOCK_LOCK
;
206 io
.lock
.in
.file
.fnum
= fnum
;
207 io
.lock
.in
.count
= 4002;
208 io
.lock
.in
.offset
= 10001;
209 status
= smb_raw_lock(cli
->tree
, &io
);
210 CHECK_STATUS(status
, NT_STATUS_OK
);
212 io
.lock
.level
= RAW_LOCK_UNLOCK
;
213 status
= smb_raw_lock(cli
->tree
, &io
);
214 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
216 status
= smb_raw_lock(cli
->tree
, &io
);
217 CHECK_STATUS(status
, NT_STATUS_OK
);
220 smbcli_close(cli
->tree
, fnum
);
221 smb_raw_exit(cli
->session
);
222 smbcli_deltree(cli
->tree
, BASEDIR
);
230 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
233 struct smb_lock_entry lock
[1];
237 const char *fname
= BASEDIR
"\\test.txt";
239 if (!torture_setup_dir(cli
, BASEDIR
)) {
243 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
244 io
.generic
.level
= RAW_LOCK_LOCKX
;
246 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
247 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
248 "Failed to create %s - %s\n",
249 fname
, smbcli_errstr(cli
->tree
)));
251 io
.lockx
.level
= RAW_LOCK_LOCKX
;
252 io
.lockx
.in
.file
.fnum
= fnum
;
253 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
254 io
.lockx
.in
.timeout
= 0;
255 io
.lockx
.in
.ulock_cnt
= 0;
256 io
.lockx
.in
.lock_cnt
= 1;
257 lock
[0].pid
= cli
->session
->pid
;
260 io
.lockx
.in
.locks
= &lock
[0];
261 status
= smb_raw_lock(cli
->tree
, &io
);
262 CHECK_STATUS(status
, NT_STATUS_OK
);
265 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
266 io
.lockx
.in
.ulock_cnt
= 0;
267 io
.lockx
.in
.lock_cnt
= 1;
268 lock
[0].count
= 4000;
269 lock
[0].offset
= 0xEEFFFFFF;
270 status
= smb_raw_lock(cli
->tree
, &io
);
271 CHECK_STATUS(status
, NT_STATUS_OK
);
273 status
= smb_raw_lock(cli
->tree
, &io
);
274 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
276 io
.lockx
.in
.ulock_cnt
= 1;
277 io
.lockx
.in
.lock_cnt
= 0;
278 status
= smb_raw_lock(cli
->tree
, &io
);
279 CHECK_STATUS(status
, NT_STATUS_OK
);
280 status
= smb_raw_lock(cli
->tree
, &io
);
281 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
283 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
284 io
.lockx
.in
.ulock_cnt
= 0;
285 io
.lockx
.in
.lock_cnt
= 1;
286 lock
[0].count
= 4000;
287 lock
[0].offset
= 0xEF000000;
288 status
= smb_raw_lock(cli
->tree
, &io
);
289 CHECK_STATUS(status
, NT_STATUS_OK
);
291 status
= smb_raw_lock(cli
->tree
, &io
);
292 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
294 io
.lockx
.in
.ulock_cnt
= 1;
295 io
.lockx
.in
.lock_cnt
= 0;
296 status
= smb_raw_lock(cli
->tree
, &io
);
297 CHECK_STATUS(status
, NT_STATUS_OK
);
298 status
= smb_raw_lock(cli
->tree
, &io
);
299 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
301 torture_comment(tctx
, "Trying zero lock\n");
302 io
.lockx
.in
.ulock_cnt
= 0;
303 io
.lockx
.in
.lock_cnt
= 1;
306 status
= smb_raw_lock(cli
->tree
, &io
);
307 CHECK_STATUS(status
, NT_STATUS_OK
);
309 status
= smb_raw_lock(cli
->tree
, &io
);
310 CHECK_STATUS(status
, NT_STATUS_OK
);
312 io
.lockx
.in
.ulock_cnt
= 1;
313 io
.lockx
.in
.lock_cnt
= 0;
314 status
= smb_raw_lock(cli
->tree
, &io
);
315 CHECK_STATUS(status
, NT_STATUS_OK
);
316 status
= smb_raw_lock(cli
->tree
, &io
);
317 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
319 torture_comment(tctx
, "Trying max lock\n");
320 io
.lockx
.in
.ulock_cnt
= 0;
321 io
.lockx
.in
.lock_cnt
= 1;
324 status
= smb_raw_lock(cli
->tree
, &io
);
325 CHECK_STATUS(status
, NT_STATUS_OK
);
327 status
= smb_raw_lock(cli
->tree
, &io
);
328 CHECK_STATUS(status
, NT_STATUS_OK
);
330 io
.lockx
.in
.ulock_cnt
= 1;
331 io
.lockx
.in
.lock_cnt
= 0;
332 status
= smb_raw_lock(cli
->tree
, &io
);
333 CHECK_STATUS(status
, NT_STATUS_OK
);
334 status
= smb_raw_lock(cli
->tree
, &io
);
335 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
337 torture_comment(tctx
, "Trying 2^63\n");
338 io
.lockx
.in
.ulock_cnt
= 0;
339 io
.lockx
.in
.lock_cnt
= 1;
342 lock
[0].offset
<<= 63;
343 status
= smb_raw_lock(cli
->tree
, &io
);
344 CHECK_STATUS(status
, NT_STATUS_OK
);
346 status
= smb_raw_lock(cli
->tree
, &io
);
347 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
349 io
.lockx
.in
.ulock_cnt
= 1;
350 io
.lockx
.in
.lock_cnt
= 0;
351 status
= smb_raw_lock(cli
->tree
, &io
);
352 CHECK_STATUS(status
, NT_STATUS_OK
);
353 status
= smb_raw_lock(cli
->tree
, &io
);
354 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
356 torture_comment(tctx
, "Trying 2^63 - 1\n");
357 io
.lockx
.in
.ulock_cnt
= 0;
358 io
.lockx
.in
.lock_cnt
= 1;
361 lock
[0].offset
<<= 63;
363 status
= smb_raw_lock(cli
->tree
, &io
);
364 CHECK_STATUS(status
, NT_STATUS_OK
);
366 status
= smb_raw_lock(cli
->tree
, &io
);
367 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
369 io
.lockx
.in
.ulock_cnt
= 1;
370 io
.lockx
.in
.lock_cnt
= 0;
371 status
= smb_raw_lock(cli
->tree
, &io
);
372 CHECK_STATUS(status
, NT_STATUS_OK
);
373 status
= smb_raw_lock(cli
->tree
, &io
);
374 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
376 torture_comment(tctx
, "Trying max lock 2\n");
377 io
.lockx
.in
.ulock_cnt
= 0;
378 io
.lockx
.in
.lock_cnt
= 1;
381 status
= smb_raw_lock(cli
->tree
, &io
);
382 CHECK_STATUS(status
, NT_STATUS_OK
);
385 status
= smb_raw_lock(cli
->tree
, &io
);
386 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx
))
387 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
389 CHECK_STATUS(status
, NT_STATUS_OK
);
391 io
.lockx
.in
.ulock_cnt
= 1;
392 io
.lockx
.in
.lock_cnt
= 0;
394 status
= smb_raw_lock(cli
->tree
, &io
);
396 CHECK_STATUS(status
, NT_STATUS_OK
);
397 status
= smb_raw_lock(cli
->tree
, &io
);
398 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
401 smbcli_close(cli
->tree
, fnum
);
402 smb_raw_exit(cli
->session
);
403 smbcli_deltree(cli
->tree
, BASEDIR
);
410 static bool test_pidhigh(struct torture_context
*tctx
,
411 struct smbcli_state
*cli
)
414 struct smb_lock_entry lock
[1];
418 const char *fname
= BASEDIR
"\\test.txt";
421 if (!torture_setup_dir(cli
, BASEDIR
)) {
425 torture_comment(tctx
, "Testing high pid\n");
426 io
.generic
.level
= RAW_LOCK_LOCKX
;
428 cli
->session
->pid
= 1;
430 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
431 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
432 "Failed to create %s - %s\n",
433 fname
, smbcli_errstr(cli
->tree
)));
435 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
436 torture_result(tctx
, TORTURE_FAIL
,
437 "Failed to write 1 byte - %s\n",
438 smbcli_errstr(cli
->tree
));
443 io
.lockx
.level
= RAW_LOCK_LOCKX
;
444 io
.lockx
.in
.file
.fnum
= fnum
;
445 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
446 io
.lockx
.in
.timeout
= 0;
447 io
.lockx
.in
.ulock_cnt
= 0;
448 io
.lockx
.in
.lock_cnt
= 1;
449 lock
[0].pid
= cli
->session
->pid
;
451 lock
[0].count
= 0xFFFFFFFF;
452 io
.lockx
.in
.locks
= &lock
[0];
453 status
= smb_raw_lock(cli
->tree
, &io
);
454 CHECK_STATUS(status
, NT_STATUS_OK
);
456 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
457 torture_result(tctx
, TORTURE_FAIL
,
458 "Failed to read 1 byte - %s\n",
459 smbcli_errstr(cli
->tree
));
464 cli
->session
->pid
= 2;
466 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
467 torture_result(tctx
, TORTURE_FAIL
,
468 "pid is incorrect handled for read with lock!\n");
473 cli
->session
->pid
= 0x10001;
475 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
476 torture_result(tctx
, TORTURE_FAIL
,
477 "High pid is used on this server!\n");
480 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
484 smbcli_close(cli
->tree
, fnum
);
485 smb_raw_exit(cli
->session
);
486 smbcli_deltree(cli
->tree
, BASEDIR
);
492 test locking&X async operation
494 static bool test_async(struct torture_context
*tctx
,
495 struct smbcli_state
*cli
)
497 struct smbcli_session
*session
;
498 struct smb_composite_sesssetup setup
;
499 struct smbcli_tree
*tree
;
501 const char *host
, *share
;
503 struct smb_lock_entry lock
[2];
507 const char *fname
= BASEDIR
"\\test.txt";
509 struct smbcli_request
*req
, *req2
;
510 struct smbcli_session_options options
;
512 if (!torture_setup_dir(cli
, BASEDIR
)) {
516 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
518 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
519 io
.generic
.level
= RAW_LOCK_LOCKX
;
521 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
522 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
523 "Failed to create %s - %s\n",
524 fname
, smbcli_errstr(cli
->tree
)));
526 io
.lockx
.level
= RAW_LOCK_LOCKX
;
527 io
.lockx
.in
.file
.fnum
= fnum
;
528 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
529 io
.lockx
.in
.timeout
= 0;
530 io
.lockx
.in
.ulock_cnt
= 0;
531 io
.lockx
.in
.lock_cnt
= 1;
532 lock
[0].pid
= cli
->session
->pid
;
533 lock
[0].offset
= 100;
535 lock
[1].pid
= cli
->session
->pid
;
536 lock
[1].offset
= 110;
538 io
.lockx
.in
.locks
= &lock
[0];
539 status
= smb_raw_lock(cli
->tree
, &io
);
540 CHECK_STATUS(status
, NT_STATUS_OK
);
544 torture_comment(tctx
, "Testing cancel by CANCEL_LOCK\n");
546 /* setup a timed lock */
547 io
.lockx
.in
.timeout
= 10000;
548 req
= smb_raw_lock_send(cli
->tree
, &io
);
549 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
550 "Failed to setup timed lock (%s)\n", __location__
));
552 /* cancel the wrong range */
554 io
.lockx
.in
.timeout
= 0;
555 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
556 status
= smb_raw_lock(cli
->tree
, &io
);
557 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
559 /* cancel with the wrong bits set */
560 lock
[0].offset
= 100;
561 io
.lockx
.in
.timeout
= 0;
562 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
563 status
= smb_raw_lock(cli
->tree
, &io
);
564 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
566 /* cancel the right range */
567 lock
[0].offset
= 100;
568 io
.lockx
.in
.timeout
= 0;
569 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
570 status
= smb_raw_lock(cli
->tree
, &io
);
571 CHECK_STATUS(status
, NT_STATUS_OK
);
573 /* receive the failed lock request */
574 status
= smbcli_request_simple_recv(req
);
575 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
577 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
578 "lock cancel was not immediate (%s)\n", __location__
));
580 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
581 * if the lock vector contains one entry. When given mutliple cancel
582 * requests in a single PDU we expect the server to return an
583 * error. Samba4 handles this correctly. Windows servers seem to
584 * accept the request but only cancel the first lock. Samba3
585 * now does what Windows does (JRA).
587 torture_comment(tctx
, "Testing multiple cancel\n");
589 /* acquire second lock */
590 io
.lockx
.in
.timeout
= 0;
591 io
.lockx
.in
.ulock_cnt
= 0;
592 io
.lockx
.in
.lock_cnt
= 1;
593 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
594 io
.lockx
.in
.locks
= &lock
[1];
595 status
= smb_raw_lock(cli
->tree
, &io
);
596 CHECK_STATUS(status
, NT_STATUS_OK
);
598 /* setup 2 timed locks */
600 io
.lockx
.in
.timeout
= 10000;
601 io
.lockx
.in
.lock_cnt
= 1;
602 io
.lockx
.in
.locks
= &lock
[0];
603 req
= smb_raw_lock_send(cli
->tree
, &io
);
604 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
605 "Failed to setup timed lock (%s)\n", __location__
));
606 io
.lockx
.in
.locks
= &lock
[1];
607 req2
= smb_raw_lock_send(cli
->tree
, &io
);
608 torture_assert(tctx
,(req2
!= NULL
), talloc_asprintf(tctx
,
609 "Failed to setup timed lock (%s)\n", __location__
));
611 /* try to cancel both locks in the same packet */
612 io
.lockx
.in
.timeout
= 0;
613 io
.lockx
.in
.lock_cnt
= 2;
614 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
615 io
.lockx
.in
.locks
= lock
;
616 status
= smb_raw_lock(cli
->tree
, &io
);
617 CHECK_STATUS(status
, NT_STATUS_OK
);
619 torture_warning(tctx
, "Target server accepted a lock cancel "
620 "request with multiple locks. This violates "
621 "MS-CIFS 2.2.4.32.1.\n");
623 /* receive the failed lock requests */
624 status
= smbcli_request_simple_recv(req
);
625 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
627 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
628 "first lock was not cancelled immediately (%s)\n",
631 /* send cancel to second lock */
632 io
.lockx
.in
.timeout
= 0;
633 io
.lockx
.in
.lock_cnt
= 1;
634 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
|
635 LOCKING_ANDX_LARGE_FILES
;
636 io
.lockx
.in
.locks
= &lock
[1];
637 status
= smb_raw_lock(cli
->tree
, &io
);
638 CHECK_STATUS(status
, NT_STATUS_OK
);
640 status
= smbcli_request_simple_recv(req2
);
641 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
643 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
644 "second lock was not cancelled immediately (%s)\n",
647 /* cleanup the second lock */
648 io
.lockx
.in
.ulock_cnt
= 1;
649 io
.lockx
.in
.lock_cnt
= 0;
650 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
651 io
.lockx
.in
.locks
= &lock
[1];
652 status
= smb_raw_lock(cli
->tree
, &io
);
653 CHECK_STATUS(status
, NT_STATUS_OK
);
655 /* If a lock request contained multiple ranges and we are cancelling
656 * one while it's still pending, what happens? */
657 torture_comment(tctx
, "Testing cancel 1/2 lock request\n");
659 /* Send request with two ranges */
660 io
.lockx
.in
.timeout
= -1;
661 io
.lockx
.in
.ulock_cnt
= 0;
662 io
.lockx
.in
.lock_cnt
= 2;
663 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
664 io
.lockx
.in
.locks
= lock
;
665 req
= smb_raw_lock_send(cli
->tree
, &io
);
666 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
667 "Failed to setup pending lock (%s)\n", __location__
));
669 /* Try to cancel the first lock range */
670 io
.lockx
.in
.timeout
= 0;
671 io
.lockx
.in
.lock_cnt
= 1;
672 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
673 io
.lockx
.in
.locks
= &lock
[0];
674 status
= smb_raw_lock(cli
->tree
, &io
);
675 CHECK_STATUS(status
, NT_STATUS_OK
);
677 /* Locking request should've failed and second range should be
679 status
= smbcli_request_simple_recv(req
);
680 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
682 io
.lockx
.in
.timeout
= 0;
683 io
.lockx
.in
.ulock_cnt
= 0;
684 io
.lockx
.in
.lock_cnt
= 1;
685 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
686 io
.lockx
.in
.locks
= &lock
[1];
687 status
= smb_raw_lock(cli
->tree
, &io
);
688 CHECK_STATUS(status
, NT_STATUS_OK
);
690 /* Cleanup both locks */
691 io
.lockx
.in
.ulock_cnt
= 2;
692 io
.lockx
.in
.lock_cnt
= 0;
693 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
694 io
.lockx
.in
.locks
= lock
;
695 status
= smb_raw_lock(cli
->tree
, &io
);
696 CHECK_STATUS(status
, NT_STATUS_OK
);
698 torture_comment(tctx
, "Testing cancel 2/2 lock request\n");
700 /* Lock second range so it contends */
701 io
.lockx
.in
.timeout
= 0;
702 io
.lockx
.in
.ulock_cnt
= 0;
703 io
.lockx
.in
.lock_cnt
= 1;
704 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
705 io
.lockx
.in
.locks
= &lock
[1];
706 status
= smb_raw_lock(cli
->tree
, &io
);
707 CHECK_STATUS(status
, NT_STATUS_OK
);
709 /* Send request with two ranges */
710 io
.lockx
.in
.timeout
= -1;
711 io
.lockx
.in
.ulock_cnt
= 0;
712 io
.lockx
.in
.lock_cnt
= 2;
713 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
714 io
.lockx
.in
.locks
= lock
;
715 req
= smb_raw_lock_send(cli
->tree
, &io
);
716 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
717 "Failed to setup pending lock (%s)\n", __location__
));
719 /* Try to cancel the second lock range */
720 io
.lockx
.in
.timeout
= 0;
721 io
.lockx
.in
.lock_cnt
= 1;
722 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
723 io
.lockx
.in
.locks
= &lock
[1];
724 status
= smb_raw_lock(cli
->tree
, &io
);
725 CHECK_STATUS(status
, NT_STATUS_OK
);
727 /* Locking request should've failed and first range should be
729 status
= smbcli_request_simple_recv(req
);
730 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
732 io
.lockx
.in
.timeout
= 0;
733 io
.lockx
.in
.ulock_cnt
= 0;
734 io
.lockx
.in
.lock_cnt
= 1;
735 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
736 io
.lockx
.in
.locks
= &lock
[0];
737 status
= smb_raw_lock(cli
->tree
, &io
);
738 CHECK_STATUS(status
, NT_STATUS_OK
);
740 /* Cleanup both locks */
741 io
.lockx
.in
.ulock_cnt
= 2;
742 io
.lockx
.in
.lock_cnt
= 0;
743 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
744 io
.lockx
.in
.locks
= lock
;
745 status
= smb_raw_lock(cli
->tree
, &io
);
746 CHECK_STATUS(status
, NT_STATUS_OK
);
748 torture_comment(tctx
, "Testing cancel by unlock\n");
749 io
.lockx
.in
.ulock_cnt
= 0;
750 io
.lockx
.in
.lock_cnt
= 1;
751 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
752 io
.lockx
.in
.timeout
= 0;
753 io
.lockx
.in
.locks
= &lock
[0];
754 status
= smb_raw_lock(cli
->tree
, &io
);
755 CHECK_STATUS(status
, NT_STATUS_OK
);
757 io
.lockx
.in
.timeout
= 5000;
758 req
= smb_raw_lock_send(cli
->tree
, &io
);
759 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
760 "Failed to setup timed lock (%s)\n", __location__
));
762 io
.lockx
.in
.ulock_cnt
= 1;
763 io
.lockx
.in
.lock_cnt
= 0;
764 status
= smb_raw_lock(cli
->tree
, &io
);
765 CHECK_STATUS(status
, NT_STATUS_OK
);
768 status
= smbcli_request_simple_recv(req
);
769 CHECK_STATUS(status
, NT_STATUS_OK
);
771 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
772 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
773 __location__
, (int)(time_mono(NULL
)-t
)));
775 torture_comment(tctx
, "Testing cancel by close\n");
776 io
.lockx
.in
.ulock_cnt
= 0;
777 io
.lockx
.in
.lock_cnt
= 1;
778 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
779 io
.lockx
.in
.timeout
= 0;
780 status
= smb_raw_lock(cli
->tree
, &io
);
781 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
784 io
.lockx
.in
.timeout
= 10000;
785 req
= smb_raw_lock_send(cli
->tree
, &io
);
786 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
787 "Failed to setup timed lock (%s)\n", __location__
));
789 status
= smbcli_close(cli
->tree
, fnum
);
790 CHECK_STATUS(status
, NT_STATUS_OK
);
792 status
= smbcli_request_simple_recv(req
);
793 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
794 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
796 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
798 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
799 "lock cancel by close was not immediate (%s)\n", __location__
));
801 torture_comment(tctx
, "create a new sessions\n");
802 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
803 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
804 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
805 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
806 setup
.in
.credentials
= cmdline_credentials
;
807 setup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
808 status
= smb_composite_sesssetup(session
, &setup
);
809 CHECK_STATUS(status
, NT_STATUS_OK
);
810 session
->vuid
= setup
.out
.vuid
;
812 torture_comment(tctx
, "create new tree context\n");
813 share
= torture_setting_string(tctx
, "share", NULL
);
814 host
= torture_setting_string(tctx
, "host", NULL
);
815 tree
= smbcli_tree_init(session
, tctx
, false);
816 tcon
.generic
.level
= RAW_TCON_TCONX
;
817 tcon
.tconx
.in
.flags
= 0;
818 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
819 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
820 tcon
.tconx
.in
.device
= "A:";
821 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
822 CHECK_STATUS(status
, NT_STATUS_OK
);
823 tree
->tid
= tcon
.tconx
.out
.tid
;
825 torture_comment(tctx
, "Testing cancel by exit\n");
826 if (TARGET_SUPPORTS_SMBEXIT(tctx
)) {
827 fname
= BASEDIR
"\\test_exit.txt";
828 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
829 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
830 "Failed to reopen %s - %s\n",
831 fname
, smbcli_errstr(tree
)));
833 io
.lockx
.level
= RAW_LOCK_LOCKX
;
834 io
.lockx
.in
.file
.fnum
= fnum
;
835 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
836 io
.lockx
.in
.timeout
= 0;
837 io
.lockx
.in
.ulock_cnt
= 0;
838 io
.lockx
.in
.lock_cnt
= 1;
839 lock
[0].pid
= session
->pid
;
840 lock
[0].offset
= 100;
842 io
.lockx
.in
.locks
= &lock
[0];
843 status
= smb_raw_lock(tree
, &io
);
844 CHECK_STATUS(status
, NT_STATUS_OK
);
846 io
.lockx
.in
.ulock_cnt
= 0;
847 io
.lockx
.in
.lock_cnt
= 1;
848 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
849 io
.lockx
.in
.timeout
= 0;
850 status
= smb_raw_lock(tree
, &io
);
851 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
853 io
.lockx
.in
.timeout
= 10000;
855 req
= smb_raw_lock_send(tree
, &io
);
856 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
857 "Failed to setup timed lock (%s)\n",
860 status
= smb_raw_exit(session
);
861 CHECK_STATUS(status
, NT_STATUS_OK
);
863 status
= smbcli_request_simple_recv(req
);
864 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
865 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
867 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
869 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
870 "lock cancel by exit was not immediate (%s)\n",
874 torture_comment(tctx
,
875 " skipping test, SMBExit not supported\n");
878 torture_comment(tctx
, "Testing cancel by ulogoff\n");
879 fname
= BASEDIR
"\\test_ulogoff.txt";
880 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
881 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
882 "Failed to reopen %s - %s\n",
883 fname
, smbcli_errstr(tree
)));
885 io
.lockx
.level
= RAW_LOCK_LOCKX
;
886 io
.lockx
.in
.file
.fnum
= fnum
;
887 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
888 io
.lockx
.in
.timeout
= 0;
889 io
.lockx
.in
.ulock_cnt
= 0;
890 io
.lockx
.in
.lock_cnt
= 1;
891 lock
[0].pid
= session
->pid
;
892 lock
[0].offset
= 100;
894 io
.lockx
.in
.locks
= &lock
[0];
895 status
= smb_raw_lock(tree
, &io
);
896 CHECK_STATUS(status
, NT_STATUS_OK
);
898 io
.lockx
.in
.ulock_cnt
= 0;
899 io
.lockx
.in
.lock_cnt
= 1;
900 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
901 io
.lockx
.in
.timeout
= 0;
902 status
= smb_raw_lock(tree
, &io
);
903 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
905 io
.lockx
.in
.timeout
= 10000;
907 req
= smb_raw_lock_send(tree
, &io
);
908 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
909 "Failed to setup timed lock (%s)\n", __location__
));
911 status
= smb_raw_ulogoff(session
);
912 CHECK_STATUS(status
, NT_STATUS_OK
);
914 status
= smbcli_request_simple_recv(req
);
915 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
)) {
916 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
917 torture_result(tctx
, TORTURE_FAIL
,
918 "lock not canceled by ulogoff - %s "
919 "(ignored because of vfs_vifs fails it)\n",
921 smb_tree_disconnect(tree
);
922 smb_raw_exit(session
);
925 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
927 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
930 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
931 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
933 torture_comment(tctx
, "Testing cancel by tdis\n");
934 tree
->session
= cli
->session
;
936 fname
= BASEDIR
"\\test_tdis.txt";
937 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
938 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
939 "Failed to reopen %s - %s\n",
940 fname
, smbcli_errstr(tree
)));
942 io
.lockx
.level
= RAW_LOCK_LOCKX
;
943 io
.lockx
.in
.file
.fnum
= fnum
;
944 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
945 io
.lockx
.in
.timeout
= 0;
946 io
.lockx
.in
.ulock_cnt
= 0;
947 io
.lockx
.in
.lock_cnt
= 1;
948 lock
[0].pid
= cli
->session
->pid
;
949 lock
[0].offset
= 100;
951 io
.lockx
.in
.locks
= &lock
[0];
952 status
= smb_raw_lock(tree
, &io
);
953 CHECK_STATUS(status
, NT_STATUS_OK
);
955 status
= smb_raw_lock(tree
, &io
);
956 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
958 io
.lockx
.in
.timeout
= 10000;
960 req
= smb_raw_lock_send(tree
, &io
);
961 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
962 "Failed to setup timed lock (%s)\n", __location__
));
964 status
= smb_tree_disconnect(tree
);
965 CHECK_STATUS(status
, NT_STATUS_OK
);
967 status
= smbcli_request_simple_recv(req
);
968 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
969 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
971 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
973 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
974 "lock cancel by tdis was not immediate (%s)\n", __location__
));
977 smb_raw_exit(cli
->session
);
978 smbcli_deltree(cli
->tree
, BASEDIR
);
983 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
985 static bool test_errorcode(struct torture_context
*tctx
,
986 struct smbcli_state
*cli
)
990 struct smb_lock_entry lock
[2];
995 struct smbcli_request
*req
;
999 uint16_t deny_mode
= 0;
1001 if (!torture_setup_dir(cli
, BASEDIR
)) {
1005 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
1007 torture_comment(tctx
, "Testing with timeout = 0\n");
1008 fname
= BASEDIR
"\\test0.txt";
1012 * the first run is with t = 0,
1013 * the second with t > 0 (=1)
1017 * use the DENY_DOS mode, that creates two fnum's of one low-level
1018 * file handle, this demonstrates that the cache is per fnum, not
1021 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx
))
1022 deny_mode
= OPENX_MODE_DENY_DOS
;
1024 deny_mode
= OPENX_MODE_DENY_NONE
;
1026 op
.openx
.level
= RAW_OPEN_OPENX
;
1027 op
.openx
.in
.fname
= fname
;
1028 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1029 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| deny_mode
;
1030 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
1031 op
.openx
.in
.search_attrs
= 0;
1032 op
.openx
.in
.file_attrs
= 0;
1033 op
.openx
.in
.write_time
= 0;
1034 op
.openx
.in
.size
= 0;
1035 op
.openx
.in
.timeout
= 0;
1037 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1038 CHECK_STATUS(status
, NT_STATUS_OK
);
1039 fnum
= op
.openx
.out
.file
.fnum
;
1041 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1042 CHECK_STATUS(status
, NT_STATUS_OK
);
1043 fnum2
= op
.openx
.out
.file
.fnum
;
1045 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1046 io
.lockx
.in
.file
.fnum
= fnum
;
1047 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1048 io
.lockx
.in
.timeout
= t
;
1049 io
.lockx
.in
.ulock_cnt
= 0;
1050 io
.lockx
.in
.lock_cnt
= 1;
1051 lock
[0].pid
= cli
->session
->pid
;
1052 lock
[0].offset
= 100;
1054 io
.lockx
.in
.locks
= &lock
[0];
1055 status
= smb_raw_lock(cli
->tree
, &io
);
1056 CHECK_STATUS(status
, NT_STATUS_OK
);
1059 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
1060 * this also demonstrates that the error code cache is per file handle
1061 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
1063 io
.lockx
.in
.file
.fnum
= fnum2
;
1064 status
= smb_raw_lock(cli
->tree
, &io
);
1065 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1067 io
.lockx
.in
.file
.fnum
= fnum
;
1068 status
= smb_raw_lock(cli
->tree
, &io
);
1069 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1071 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
1072 io
.lockx
.in
.file
.fnum
= fnum
;
1073 status
= smb_raw_lock(cli
->tree
, &io
);
1074 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1076 io
.lockx
.in
.file
.fnum
= fnum2
;
1077 status
= smb_raw_lock(cli
->tree
, &io
);
1078 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1080 io
.lockx
.in
.file
.fnum
= fnum
;
1081 status
= smb_raw_lock(cli
->tree
, &io
);
1082 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1084 io
.lockx
.in
.file
.fnum
= fnum2
;
1085 status
= smb_raw_lock(cli
->tree
, &io
);
1086 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1088 /* demonstrate that the smbpid doesn't matter */
1090 io
.lockx
.in
.file
.fnum
= fnum
;
1091 status
= smb_raw_lock(cli
->tree
, &io
);
1092 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1094 io
.lockx
.in
.file
.fnum
= fnum2
;
1095 status
= smb_raw_lock(cli
->tree
, &io
);
1096 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1100 * demonstrate the a successful lock with count = 0 and the same offset,
1101 * doesn't reset the error cache
1103 lock
[0].offset
= 100;
1105 io
.lockx
.in
.file
.fnum
= fnum
;
1106 status
= smb_raw_lock(cli
->tree
, &io
);
1107 CHECK_STATUS(status
, NT_STATUS_OK
);
1109 io
.lockx
.in
.file
.fnum
= fnum2
;
1110 status
= smb_raw_lock(cli
->tree
, &io
);
1111 CHECK_STATUS(status
, NT_STATUS_OK
);
1113 lock
[0].offset
= 100;
1115 io
.lockx
.in
.file
.fnum
= fnum
;
1116 status
= smb_raw_lock(cli
->tree
, &io
);
1117 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1119 io
.lockx
.in
.file
.fnum
= fnum2
;
1120 status
= smb_raw_lock(cli
->tree
, &io
);
1121 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1124 * demonstrate the a successful lock with count = 0 and outside the locked range,
1125 * doesn't reset the error cache
1127 lock
[0].offset
= 110;
1129 io
.lockx
.in
.file
.fnum
= fnum
;
1130 status
= smb_raw_lock(cli
->tree
, &io
);
1131 CHECK_STATUS(status
, NT_STATUS_OK
);
1133 io
.lockx
.in
.file
.fnum
= fnum2
;
1134 status
= smb_raw_lock(cli
->tree
, &io
);
1135 CHECK_STATUS(status
, NT_STATUS_OK
);
1137 lock
[0].offset
= 100;
1139 io
.lockx
.in
.file
.fnum
= fnum
;
1140 status
= smb_raw_lock(cli
->tree
, &io
);
1141 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1143 io
.lockx
.in
.file
.fnum
= fnum2
;
1144 status
= smb_raw_lock(cli
->tree
, &io
);
1145 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1147 lock
[0].offset
= 99;
1149 io
.lockx
.in
.file
.fnum
= fnum
;
1150 status
= smb_raw_lock(cli
->tree
, &io
);
1151 CHECK_STATUS(status
, NT_STATUS_OK
);
1153 io
.lockx
.in
.file
.fnum
= fnum2
;
1154 status
= smb_raw_lock(cli
->tree
, &io
);
1155 CHECK_STATUS(status
, NT_STATUS_OK
);
1157 lock
[0].offset
= 100;
1159 io
.lockx
.in
.file
.fnum
= fnum
;
1160 status
= smb_raw_lock(cli
->tree
, &io
);
1161 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1163 io
.lockx
.in
.file
.fnum
= fnum2
;
1164 status
= smb_raw_lock(cli
->tree
, &io
);
1165 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1167 /* demonstrate that a changing count doesn't reset the error cache */
1168 lock
[0].offset
= 100;
1170 io
.lockx
.in
.file
.fnum
= fnum
;
1171 status
= smb_raw_lock(cli
->tree
, &io
);
1172 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1174 io
.lockx
.in
.file
.fnum
= fnum2
;
1175 status
= smb_raw_lock(cli
->tree
, &io
);
1176 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1178 lock
[0].offset
= 100;
1180 io
.lockx
.in
.file
.fnum
= fnum
;
1181 status
= smb_raw_lock(cli
->tree
, &io
);
1182 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1184 io
.lockx
.in
.file
.fnum
= fnum2
;
1185 status
= smb_raw_lock(cli
->tree
, &io
);
1186 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1189 * demonstrate the a lock with count = 0 and inside the locked range,
1190 * fails and resets the error cache
1192 lock
[0].offset
= 101;
1194 io
.lockx
.in
.file
.fnum
= fnum
;
1195 status
= smb_raw_lock(cli
->tree
, &io
);
1196 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1197 status
= smb_raw_lock(cli
->tree
, &io
);
1198 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1200 io
.lockx
.in
.file
.fnum
= fnum2
;
1201 status
= smb_raw_lock(cli
->tree
, &io
);
1202 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1203 status
= smb_raw_lock(cli
->tree
, &io
);
1204 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1206 lock
[0].offset
= 100;
1208 io
.lockx
.in
.file
.fnum
= fnum
;
1209 status
= smb_raw_lock(cli
->tree
, &io
);
1210 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1211 status
= smb_raw_lock(cli
->tree
, &io
);
1212 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1214 io
.lockx
.in
.file
.fnum
= fnum2
;
1215 status
= smb_raw_lock(cli
->tree
, &io
);
1216 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1217 status
= smb_raw_lock(cli
->tree
, &io
);
1218 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1220 /* demonstrate the a changing offset, resets the error cache */
1221 lock
[0].offset
= 105;
1223 io
.lockx
.in
.file
.fnum
= fnum
;
1224 status
= smb_raw_lock(cli
->tree
, &io
);
1225 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1226 status
= smb_raw_lock(cli
->tree
, &io
);
1227 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1229 io
.lockx
.in
.file
.fnum
= fnum2
;
1230 status
= smb_raw_lock(cli
->tree
, &io
);
1231 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1232 status
= smb_raw_lock(cli
->tree
, &io
);
1233 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1235 lock
[0].offset
= 100;
1237 io
.lockx
.in
.file
.fnum
= fnum
;
1238 status
= smb_raw_lock(cli
->tree
, &io
);
1239 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1240 status
= smb_raw_lock(cli
->tree
, &io
);
1241 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1243 io
.lockx
.in
.file
.fnum
= fnum2
;
1244 status
= smb_raw_lock(cli
->tree
, &io
);
1245 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1246 status
= smb_raw_lock(cli
->tree
, &io
);
1247 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1249 lock
[0].offset
= 95;
1251 io
.lockx
.in
.file
.fnum
= fnum
;
1252 status
= smb_raw_lock(cli
->tree
, &io
);
1253 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1254 status
= smb_raw_lock(cli
->tree
, &io
);
1255 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1257 io
.lockx
.in
.file
.fnum
= fnum2
;
1258 status
= smb_raw_lock(cli
->tree
, &io
);
1259 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1260 status
= smb_raw_lock(cli
->tree
, &io
);
1261 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1263 lock
[0].offset
= 100;
1265 io
.lockx
.in
.file
.fnum
= fnum
;
1266 status
= smb_raw_lock(cli
->tree
, &io
);
1267 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1268 status
= smb_raw_lock(cli
->tree
, &io
);
1269 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1271 io
.lockx
.in
.file
.fnum
= fnum2
;
1272 status
= smb_raw_lock(cli
->tree
, &io
);
1273 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1274 status
= smb_raw_lock(cli
->tree
, &io
);
1275 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1278 * demonstrate the a successful lock in a different range,
1279 * doesn't reset the cache, the failing lock on the 2nd handle
1282 lock
[0].offset
= 120;
1284 io
.lockx
.in
.file
.fnum
= fnum
;
1285 status
= smb_raw_lock(cli
->tree
, &io
);
1286 CHECK_STATUS(status
, NT_STATUS_OK
);
1288 io
.lockx
.in
.file
.fnum
= fnum2
;
1289 status
= smb_raw_lock(cli
->tree
, &io
);
1290 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1292 lock
[0].offset
= 100;
1294 io
.lockx
.in
.file
.fnum
= fnum
;
1295 status
= smb_raw_lock(cli
->tree
, &io
);
1296 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1297 status
= smb_raw_lock(cli
->tree
, &io
);
1298 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1300 io
.lockx
.in
.file
.fnum
= fnum2
;
1301 status
= smb_raw_lock(cli
->tree
, &io
);
1302 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1303 status
= smb_raw_lock(cli
->tree
, &io
);
1304 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1306 /* end of the loop */
1308 smb_raw_exit(cli
->session
);
1310 torture_comment(tctx
, "Testing with timeout > 0 (=%d)\n",
1312 fname
= BASEDIR
"\\test1.txt";
1317 torture_comment(tctx
, "Testing special cases with timeout > 0 (=%d)\n",
1321 * the following 3 test sections demonstrate that
1322 * the cache is only set when the error is reported
1323 * to the client (after the timeout went by)
1325 smb_raw_exit(cli
->session
);
1326 torture_comment(tctx
, "Testing a conflict while a lock is pending\n");
1327 fname
= BASEDIR
"\\test2.txt";
1328 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1329 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1330 "Failed to reopen %s - %s\n",
1331 fname
, smbcli_errstr(cli
->tree
)));
1333 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1334 io
.lockx
.in
.file
.fnum
= fnum
;
1335 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1336 io
.lockx
.in
.timeout
= 0;
1337 io
.lockx
.in
.ulock_cnt
= 0;
1338 io
.lockx
.in
.lock_cnt
= 1;
1339 lock
[0].pid
= cli
->session
->pid
;
1340 lock
[0].offset
= 100;
1342 io
.lockx
.in
.locks
= &lock
[0];
1343 status
= smb_raw_lock(cli
->tree
, &io
);
1344 CHECK_STATUS(status
, NT_STATUS_OK
);
1346 start
= time_mono(NULL
);
1347 io
.lockx
.in
.timeout
= t
;
1348 req
= smb_raw_lock_send(cli
->tree
, &io
);
1349 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1350 "Failed to setup timed lock (%s)\n", __location__
));
1352 io
.lockx
.in
.timeout
= 0;
1353 lock
[0].offset
= 105;
1355 status
= smb_raw_lock(cli
->tree
, &io
);
1356 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1358 status
= smbcli_request_simple_recv(req
);
1359 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1362 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1366 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1367 "lock comes back to early timeout[%d] delay[%d]"
1368 "(%s)\n", t
, delay
, __location__
));
1370 status
= smb_raw_lock(cli
->tree
, &io
);
1371 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1373 smbcli_close(cli
->tree
, fnum
);
1374 fname
= BASEDIR
"\\test3.txt";
1375 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1376 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1377 "Failed to reopen %s - %s\n",
1378 fname
, smbcli_errstr(cli
->tree
)));
1380 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1381 io
.lockx
.in
.file
.fnum
= fnum
;
1382 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1383 io
.lockx
.in
.timeout
= 0;
1384 io
.lockx
.in
.ulock_cnt
= 0;
1385 io
.lockx
.in
.lock_cnt
= 1;
1386 lock
[0].pid
= cli
->session
->pid
;
1387 lock
[0].offset
= 100;
1389 io
.lockx
.in
.locks
= &lock
[0];
1390 status
= smb_raw_lock(cli
->tree
, &io
);
1391 CHECK_STATUS(status
, NT_STATUS_OK
);
1393 start
= time_mono(NULL
);
1394 io
.lockx
.in
.timeout
= t
;
1395 req
= smb_raw_lock_send(cli
->tree
, &io
);
1396 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1397 "Failed to setup timed lock (%s)\n", __location__
));
1399 io
.lockx
.in
.timeout
= 0;
1400 lock
[0].offset
= 105;
1402 status
= smb_raw_lock(cli
->tree
, &io
);
1403 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1405 status
= smbcli_request_simple_recv(req
);
1406 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1409 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1413 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1414 "lock comes back to early timeout[%d] delay[%d]"
1415 "(%s)\n", t
, delay
, __location__
));
1417 lock
[0].offset
= 100;
1419 status
= smb_raw_lock(cli
->tree
, &io
);
1420 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1422 smbcli_close(cli
->tree
, fnum
);
1423 fname
= BASEDIR
"\\test4.txt";
1424 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1425 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1426 "Failed to reopen %s - %s\n",
1427 fname
, smbcli_errstr(cli
->tree
)));
1429 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1430 io
.lockx
.in
.file
.fnum
= fnum
;
1431 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1432 io
.lockx
.in
.timeout
= 0;
1433 io
.lockx
.in
.ulock_cnt
= 0;
1434 io
.lockx
.in
.lock_cnt
= 1;
1435 lock
[0].pid
= cli
->session
->pid
;
1436 lock
[0].offset
= 100;
1438 io
.lockx
.in
.locks
= &lock
[0];
1439 status
= smb_raw_lock(cli
->tree
, &io
);
1440 CHECK_STATUS(status
, NT_STATUS_OK
);
1442 start
= time_mono(NULL
);
1443 io
.lockx
.in
.timeout
= t
;
1444 req
= smb_raw_lock_send(cli
->tree
, &io
);
1445 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1446 "Failed to setup timed lock (%s)\n", __location__
));
1448 io
.lockx
.in
.timeout
= 0;
1449 status
= smb_raw_lock(cli
->tree
, &io
);
1450 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1452 status
= smbcli_request_simple_recv(req
);
1453 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1456 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1460 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1461 "lock comes back to early timeout[%d] delay[%d]"
1462 "(%s)\n", t
, delay
, __location__
));
1464 status
= smb_raw_lock(cli
->tree
, &io
);
1465 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1468 smb_raw_exit(cli
->session
);
1469 smbcli_deltree(cli
->tree
, BASEDIR
);
1475 test LOCKING_ANDX_CHANGE_LOCKTYPE
1477 static bool test_changetype(struct torture_context
*tctx
,
1478 struct smbcli_state
*cli
)
1481 struct smb_lock_entry lock
[2];
1486 const char *fname
= BASEDIR
"\\test.txt";
1488 if (!torture_setup_dir(cli
, BASEDIR
)) {
1492 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1493 io
.generic
.level
= RAW_LOCK_LOCKX
;
1495 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1496 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1497 "Failed to create %s - %s\n",
1498 fname
, smbcli_errstr(cli
->tree
)));
1500 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1501 io
.lockx
.in
.file
.fnum
= fnum
;
1502 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1503 io
.lockx
.in
.timeout
= 0;
1504 io
.lockx
.in
.ulock_cnt
= 0;
1505 io
.lockx
.in
.lock_cnt
= 1;
1506 lock
[0].pid
= cli
->session
->pid
;
1507 lock
[0].offset
= 100;
1509 io
.lockx
.in
.locks
= &lock
[0];
1510 status
= smb_raw_lock(cli
->tree
, &io
);
1511 CHECK_STATUS(status
, NT_STATUS_OK
);
1513 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1514 torture_result(tctx
, TORTURE_FAIL
,
1515 "allowed write on read locked region (%s)\n", __location__
);
1520 /* windows server don't seem to support this */
1521 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1522 status
= smb_raw_lock(cli
->tree
, &io
);
1523 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1525 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1526 torture_result(tctx
, TORTURE_FAIL
,
1527 "allowed write after lock change (%s)\n", __location__
);
1533 smbcli_close(cli
->tree
, fnum
);
1534 smb_raw_exit(cli
->session
);
1535 smbcli_deltree(cli
->tree
, BASEDIR
);
1539 struct double_lock_test
{
1540 struct smb_lock_entry lock1
;
1541 struct smb_lock_entry lock2
;
1542 NTSTATUS exp_status
;
1546 * Tests zero byte locks.
1548 static struct double_lock_test zero_byte_tests
[] = {
1549 /* {pid, offset, count}, {pid, offset, count}, status */
1551 /** First, takes a zero byte lock at offset 10. Then:
1552 * - Taking 0 byte lock at 10 should succeed.
1553 * - Taking 1 byte locks at 9,10,11 should succeed.
1554 * - Taking 2 byte lock at 9 should fail.
1555 * - Taking 2 byte lock at 10 should succeed.
1556 * - Taking 3 byte lock at 9 should fail.
1558 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1559 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1560 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1561 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1562 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1563 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1564 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1566 /** Same, but opposite order. */
1567 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1568 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1569 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1570 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1571 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1572 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1573 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1575 /** Zero zero case. */
1576 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1579 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1585 const char *fname
= BASEDIR
"\\zero.txt";
1587 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1589 if (!torture_setup_dir(cli
, BASEDIR
)) {
1593 io
.generic
.level
= RAW_LOCK_LOCKX
;
1595 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1596 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1597 "Failed to create %s - %s\n",
1598 fname
, smbcli_errstr(cli
->tree
)));
1600 /* Setup initial parameters */
1601 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1602 io
.lockx
.in
.file
.fnum
= fnum
;
1603 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1604 io
.lockx
.in
.timeout
= 0;
1606 /* Try every combination of locks in zero_byte_tests. The first lock is
1607 * assumed to succeed. The second lock may contend, depending on the
1608 * expected status. */
1610 i
< ARRAY_SIZE(zero_byte_tests
);
1612 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1613 zero_byte_tests
[i
].lock1
.pid
,
1614 (unsigned long long) zero_byte_tests
[i
].lock1
.offset
,
1615 (unsigned long long) zero_byte_tests
[i
].lock1
.count
,
1616 zero_byte_tests
[i
].lock2
.pid
,
1617 (unsigned long long) zero_byte_tests
[i
].lock2
.offset
,
1618 (unsigned long long) zero_byte_tests
[i
].lock2
.count
,
1619 nt_errstr(zero_byte_tests
[i
].exp_status
));
1621 /* Lock both locks. */
1622 io
.lockx
.in
.ulock_cnt
= 0;
1623 io
.lockx
.in
.lock_cnt
= 1;
1625 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1626 &zero_byte_tests
[i
].lock1
);
1627 status
= smb_raw_lock(cli
->tree
, &io
);
1628 CHECK_STATUS(status
, NT_STATUS_OK
);
1630 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1631 &zero_byte_tests
[i
].lock2
);
1632 status
= smb_raw_lock(cli
->tree
, &io
);
1634 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1635 NT_STATUS_LOCK_NOT_GRANTED
)) {
1636 /* Allow either of the failure messages and keep going
1637 * if we see the wrong status. */
1638 CHECK_STATUS_OR_CONT(status
,
1639 NT_STATUS_LOCK_NOT_GRANTED
,
1640 NT_STATUS_FILE_LOCK_CONFLICT
);
1643 CHECK_STATUS_CONT(status
,
1644 zero_byte_tests
[i
].exp_status
);
1647 /* Unlock both locks. */
1648 io
.lockx
.in
.ulock_cnt
= 1;
1649 io
.lockx
.in
.lock_cnt
= 0;
1651 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1652 status
= smb_raw_lock(cli
->tree
, &io
);
1653 CHECK_STATUS(status
, NT_STATUS_OK
);
1656 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1657 &zero_byte_tests
[i
].lock1
);
1658 status
= smb_raw_lock(cli
->tree
, &io
);
1659 CHECK_STATUS(status
, NT_STATUS_OK
);
1663 smbcli_close(cli
->tree
, fnum
);
1664 smb_raw_exit(cli
->session
);
1665 smbcli_deltree(cli
->tree
, BASEDIR
);
1669 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1675 const char *fname
= BASEDIR
"\\unlock.txt";
1676 struct smb_lock_entry lock1
;
1677 struct smb_lock_entry lock2
;
1679 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1681 if (!torture_setup_dir(cli
, BASEDIR
)) {
1685 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1686 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1687 "Failed to create %s - %s\n",
1688 fname
, smbcli_errstr(cli
->tree
)));
1690 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1691 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1692 "Failed to create %s - %s\n",
1693 fname
, smbcli_errstr(cli
->tree
)));
1695 /* Setup initial parameters */
1696 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1697 io
.lockx
.in
.timeout
= 0;
1699 lock1
.pid
= cli
->session
->pid
;
1702 lock2
.pid
= cli
->session
->pid
- 1;
1707 * Take exclusive lock, then unlock it with a shared-unlock call.
1709 torture_comment(tctx
, " taking exclusive lock.\n");
1710 io
.lockx
.in
.ulock_cnt
= 0;
1711 io
.lockx
.in
.lock_cnt
= 1;
1712 io
.lockx
.in
.mode
= 0;
1713 io
.lockx
.in
.file
.fnum
= fnum1
;
1714 io
.lockx
.in
.locks
= &lock1
;
1715 status
= smb_raw_lock(cli
->tree
, &io
);
1716 CHECK_STATUS(status
, NT_STATUS_OK
);
1718 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1719 io
.lockx
.in
.ulock_cnt
= 1;
1720 io
.lockx
.in
.lock_cnt
= 0;
1721 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1722 io
.lockx
.in
.file
.fnum
= fnum1
;
1723 io
.lockx
.in
.locks
= &lock1
;
1724 status
= smb_raw_lock(cli
->tree
, &io
);
1725 CHECK_STATUS(status
, NT_STATUS_OK
);
1727 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1728 io
.lockx
.in
.ulock_cnt
= 0;
1729 io
.lockx
.in
.lock_cnt
= 1;
1730 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1731 io
.lockx
.in
.file
.fnum
= fnum2
;
1732 io
.lockx
.in
.locks
= &lock2
;
1733 status
= smb_raw_lock(cli
->tree
, &io
);
1734 CHECK_STATUS(status
, NT_STATUS_OK
);
1737 * Unlock a shared lock with an exclusive-unlock call.
1739 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1740 io
.lockx
.in
.ulock_cnt
= 1;
1741 io
.lockx
.in
.lock_cnt
= 0;
1742 io
.lockx
.in
.mode
= 0;
1743 io
.lockx
.in
.file
.fnum
= fnum2
;
1744 io
.lockx
.in
.locks
= &lock2
;
1745 status
= smb_raw_lock(cli
->tree
, &io
);
1746 CHECK_STATUS(status
, NT_STATUS_OK
);
1748 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1749 io
.lockx
.in
.ulock_cnt
= 0;
1750 io
.lockx
.in
.lock_cnt
= 1;
1751 io
.lockx
.in
.mode
= 0;
1752 io
.lockx
.in
.file
.fnum
= fnum1
;
1753 io
.lockx
.in
.locks
= &lock1
;
1754 status
= smb_raw_lock(cli
->tree
, &io
);
1755 CHECK_STATUS(status
, NT_STATUS_OK
);
1758 io
.lockx
.in
.ulock_cnt
= 1;
1759 io
.lockx
.in
.lock_cnt
= 0;
1760 status
= smb_raw_lock(cli
->tree
, &io
);
1761 CHECK_STATUS(status
, NT_STATUS_OK
);
1764 * Test unlocking of 0-byte locks.
1767 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1768 "always unlocks the exclusive first.\n");
1769 lock1
.pid
= cli
->session
->pid
;
1772 lock2
.pid
= cli
->session
->pid
;
1775 io
.lockx
.in
.ulock_cnt
= 0;
1776 io
.lockx
.in
.lock_cnt
= 1;
1777 io
.lockx
.in
.file
.fnum
= fnum1
;
1778 io
.lockx
.in
.locks
= &lock1
;
1780 /* lock 0-byte shared
1781 * Note: Order of the shared/exclusive locks doesn't matter. */
1782 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1783 status
= smb_raw_lock(cli
->tree
, &io
);
1784 CHECK_STATUS(status
, NT_STATUS_OK
);
1786 /* lock 0-byte exclusive */
1787 io
.lockx
.in
.mode
= 0;
1788 status
= smb_raw_lock(cli
->tree
, &io
);
1789 CHECK_STATUS(status
, NT_STATUS_OK
);
1791 /* test contention */
1792 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1793 io
.lockx
.in
.locks
= &lock2
;
1794 io
.lockx
.in
.file
.fnum
= fnum2
;
1795 status
= smb_raw_lock(cli
->tree
, &io
);
1796 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1797 NT_STATUS_FILE_LOCK_CONFLICT
);
1800 io
.lockx
.in
.ulock_cnt
= 1;
1801 io
.lockx
.in
.lock_cnt
= 0;
1802 io
.lockx
.in
.file
.fnum
= fnum1
;
1803 io
.lockx
.in
.locks
= &lock1
;
1804 status
= smb_raw_lock(cli
->tree
, &io
);
1805 CHECK_STATUS(status
, NT_STATUS_OK
);
1807 /* test - can we take a shared lock? */
1808 io
.lockx
.in
.ulock_cnt
= 0;
1809 io
.lockx
.in
.lock_cnt
= 1;
1810 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1811 io
.lockx
.in
.file
.fnum
= fnum2
;
1812 io
.lockx
.in
.locks
= &lock2
;
1813 status
= smb_raw_lock(cli
->tree
, &io
);
1815 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1816 * new to Win7, it succeeds in WinXP too), until I can come to a
1817 * resolution as to whether Samba should support this or not. There is
1818 * code to preference unlocking exclusive locks before shared locks,
1819 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1820 if (TARGET_IS_SAMBA3(tctx
)) {
1821 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1822 NT_STATUS_FILE_LOCK_CONFLICT
);
1824 CHECK_STATUS(status
, NT_STATUS_OK
);
1828 io
.lockx
.in
.ulock_cnt
= 1;
1829 io
.lockx
.in
.lock_cnt
= 0;
1830 status
= smb_raw_lock(cli
->tree
, &io
);
1832 /* XXX Same as above. */
1833 if (TARGET_IS_SAMBA3(tctx
)) {
1834 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1836 CHECK_STATUS(status
, NT_STATUS_OK
);
1839 io
.lockx
.in
.file
.fnum
= fnum1
;
1840 io
.lockx
.in
.locks
= &lock1
;
1841 status
= smb_raw_lock(cli
->tree
, &io
);
1842 CHECK_STATUS(status
, NT_STATUS_OK
);
1845 smbcli_close(cli
->tree
, fnum1
);
1846 smbcli_close(cli
->tree
, fnum2
);
1847 smb_raw_exit(cli
->session
);
1848 smbcli_deltree(cli
->tree
, BASEDIR
);
1852 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1858 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1859 struct smb_lock_entry lock1
;
1860 struct smb_lock_entry lock2
;
1861 struct smb_lock_entry locks
[2];
1863 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1865 if (!torture_setup_dir(cli
, BASEDIR
)) {
1869 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1870 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1871 "Failed to create %s - %s\n",
1872 fname
, smbcli_errstr(cli
->tree
)));
1874 /* Setup initial parameters */
1875 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1876 io
.lockx
.in
.timeout
= 0;
1878 lock1
.pid
= cli
->session
->pid
;
1881 lock2
.pid
= cli
->session
->pid
;
1888 io
.lockx
.in
.file
.fnum
= fnum1
;
1889 io
.lockx
.in
.mode
= 0; /* exclusive */
1891 /** Test1: Take second lock, but not first. */
1892 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
1895 io
.lockx
.in
.ulock_cnt
= 0;
1896 io
.lockx
.in
.lock_cnt
= 1;
1897 io
.lockx
.in
.locks
= &lock2
;
1898 status
= smb_raw_lock(cli
->tree
, &io
);
1899 CHECK_STATUS(status
, NT_STATUS_OK
);
1901 /* Try to unlock both locks. */
1902 io
.lockx
.in
.ulock_cnt
= 2;
1903 io
.lockx
.in
.lock_cnt
= 0;
1904 io
.lockx
.in
.locks
= locks
;
1906 status
= smb_raw_lock(cli
->tree
, &io
);
1907 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1909 /* Second lock should not be unlocked. */
1910 io
.lockx
.in
.ulock_cnt
= 0;
1911 io
.lockx
.in
.lock_cnt
= 1;
1912 io
.lockx
.in
.locks
= &lock2
;
1913 status
= smb_raw_lock(cli
->tree
, &io
);
1914 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1917 io
.lockx
.in
.ulock_cnt
= 1;
1918 io
.lockx
.in
.lock_cnt
= 0;
1919 io
.lockx
.in
.locks
= &lock2
;
1920 status
= smb_raw_lock(cli
->tree
, &io
);
1921 CHECK_STATUS(status
, NT_STATUS_OK
);
1923 /** Test2: Take first lock, but not second. */
1924 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
1927 io
.lockx
.in
.ulock_cnt
= 0;
1928 io
.lockx
.in
.lock_cnt
= 1;
1929 io
.lockx
.in
.locks
= &lock1
;
1930 status
= smb_raw_lock(cli
->tree
, &io
);
1931 CHECK_STATUS(status
, NT_STATUS_OK
);
1933 /* Try to unlock both locks. */
1934 io
.lockx
.in
.ulock_cnt
= 2;
1935 io
.lockx
.in
.lock_cnt
= 0;
1936 io
.lockx
.in
.locks
= locks
;
1938 status
= smb_raw_lock(cli
->tree
, &io
);
1939 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1941 /* First lock should be unlocked. */
1942 io
.lockx
.in
.ulock_cnt
= 0;
1943 io
.lockx
.in
.lock_cnt
= 1;
1944 io
.lockx
.in
.locks
= &lock1
;
1945 status
= smb_raw_lock(cli
->tree
, &io
);
1946 CHECK_STATUS(status
, NT_STATUS_OK
);
1949 io
.lockx
.in
.ulock_cnt
= 1;
1950 io
.lockx
.in
.lock_cnt
= 0;
1951 io
.lockx
.in
.locks
= &lock1
;
1952 status
= smb_raw_lock(cli
->tree
, &io
);
1953 CHECK_STATUS(status
, NT_STATUS_OK
);
1955 /* Test3: Request 2 locks, second will contend. What happens to the
1957 torture_comment(tctx
, " request 2 locks, second one will contend. "
1958 "Expect both to fail.\n");
1960 /* Lock the second range */
1961 io
.lockx
.in
.ulock_cnt
= 0;
1962 io
.lockx
.in
.lock_cnt
= 1;
1963 io
.lockx
.in
.locks
= &lock2
;
1964 status
= smb_raw_lock(cli
->tree
, &io
);
1965 CHECK_STATUS(status
, NT_STATUS_OK
);
1967 /* Request both locks */
1968 io
.lockx
.in
.ulock_cnt
= 0;
1969 io
.lockx
.in
.lock_cnt
= 2;
1970 io
.lockx
.in
.locks
= locks
;
1972 status
= smb_raw_lock(cli
->tree
, &io
);
1973 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1975 /* First lock should be unlocked. */
1976 io
.lockx
.in
.ulock_cnt
= 0;
1977 io
.lockx
.in
.lock_cnt
= 1;
1978 io
.lockx
.in
.locks
= &lock1
;
1979 status
= smb_raw_lock(cli
->tree
, &io
);
1980 CHECK_STATUS(status
, NT_STATUS_OK
);
1983 io
.lockx
.in
.ulock_cnt
= 2;
1984 io
.lockx
.in
.lock_cnt
= 0;
1985 io
.lockx
.in
.locks
= locks
;
1986 status
= smb_raw_lock(cli
->tree
, &io
);
1987 CHECK_STATUS(status
, NT_STATUS_OK
);
1989 /* Test4: Request unlock and lock. The lock contends, is the unlock
1990 * then re-locked? */
1991 torture_comment(tctx
, " request unlock and lock, second one will "
1992 "contend. Expect the unlock to succeed.\n");
1994 /* Lock both ranges */
1995 io
.lockx
.in
.ulock_cnt
= 0;
1996 io
.lockx
.in
.lock_cnt
= 2;
1997 io
.lockx
.in
.locks
= locks
;
1998 status
= smb_raw_lock(cli
->tree
, &io
);
1999 CHECK_STATUS(status
, NT_STATUS_OK
);
2001 /* Attempt to unlock the first range and lock the second */
2002 io
.lockx
.in
.ulock_cnt
= 1;
2003 io
.lockx
.in
.lock_cnt
= 1;
2004 io
.lockx
.in
.locks
= locks
;
2005 status
= smb_raw_lock(cli
->tree
, &io
);
2006 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
2008 /* The first lock should've been unlocked */
2009 io
.lockx
.in
.ulock_cnt
= 0;
2010 io
.lockx
.in
.lock_cnt
= 1;
2011 io
.lockx
.in
.locks
= &lock1
;
2012 status
= smb_raw_lock(cli
->tree
, &io
);
2013 CHECK_STATUS(status
, NT_STATUS_OK
);
2016 io
.lockx
.in
.ulock_cnt
= 2;
2017 io
.lockx
.in
.lock_cnt
= 0;
2018 io
.lockx
.in
.locks
= locks
;
2019 status
= smb_raw_lock(cli
->tree
, &io
);
2020 CHECK_STATUS(status
, NT_STATUS_OK
);
2023 smbcli_close(cli
->tree
, fnum1
);
2024 smb_raw_exit(cli
->session
);
2025 smbcli_deltree(cli
->tree
, BASEDIR
);
2030 * torture_locktest5 covers stacking pretty well, but its missing two tests:
2031 * - stacking an exclusive on top of shared fails
2032 * - stacking two exclusives fail
2034 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
2040 const char *fname
= BASEDIR
"\\stacking.txt";
2041 struct smb_lock_entry lock1
;
2042 struct smb_lock_entry lock2
;
2044 torture_comment(tctx
, "Testing stacking:\n");
2046 if (!torture_setup_dir(cli
, BASEDIR
)) {
2050 io
.generic
.level
= RAW_LOCK_LOCKX
;
2052 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2053 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2054 "Failed to create %s - %s\n",
2055 fname
, smbcli_errstr(cli
->tree
)));
2057 /* Setup initial parameters */
2058 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2059 io
.lockx
.in
.timeout
= 0;
2061 lock1
.pid
= cli
->session
->pid
;
2064 lock2
.pid
= cli
->session
->pid
- 1;
2069 * Try to take a shared lock, then stack an exclusive.
2071 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
2072 io
.lockx
.in
.file
.fnum
= fnum1
;
2073 io
.lockx
.in
.locks
= &lock1
;
2075 io
.lockx
.in
.ulock_cnt
= 0;
2076 io
.lockx
.in
.lock_cnt
= 1;
2077 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
2078 status
= smb_raw_lock(cli
->tree
, &io
);
2079 CHECK_STATUS(status
, NT_STATUS_OK
);
2081 io
.lockx
.in
.ulock_cnt
= 0;
2082 io
.lockx
.in
.lock_cnt
= 1;
2083 io
.lockx
.in
.mode
= 0;
2084 status
= smb_raw_lock(cli
->tree
, &io
);
2085 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2086 NT_STATUS_FILE_LOCK_CONFLICT
);
2089 io
.lockx
.in
.ulock_cnt
= 1;
2090 io
.lockx
.in
.lock_cnt
= 0;
2091 status
= smb_raw_lock(cli
->tree
, &io
);
2092 CHECK_STATUS(status
, NT_STATUS_OK
);
2095 * Prove that two exclusive locks do not stack.
2097 torture_comment(tctx
, " two exclusive locks do not stack.\n");
2098 io
.lockx
.in
.ulock_cnt
= 0;
2099 io
.lockx
.in
.lock_cnt
= 1;
2100 io
.lockx
.in
.mode
= 0;
2101 status
= smb_raw_lock(cli
->tree
, &io
);
2102 CHECK_STATUS(status
, NT_STATUS_OK
);
2103 status
= smb_raw_lock(cli
->tree
, &io
);
2104 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2105 NT_STATUS_FILE_LOCK_CONFLICT
);
2108 io
.lockx
.in
.ulock_cnt
= 1;
2109 io
.lockx
.in
.lock_cnt
= 0;
2110 status
= smb_raw_lock(cli
->tree
, &io
);
2111 CHECK_STATUS(status
, NT_STATUS_OK
);
2114 smbcli_close(cli
->tree
, fnum1
);
2115 smb_raw_exit(cli
->session
);
2116 smbcli_deltree(cli
->tree
, BASEDIR
);
2121 * Test how 0-byte read requests contend with byte range locks
2123 static bool test_zerobyteread(struct torture_context
*tctx
,
2124 struct smbcli_state
*cli
)
2131 const char *fname
= BASEDIR
"\\zerobyteread.txt";
2132 struct smb_lock_entry lock1
;
2135 if (!torture_setup_dir(cli
, BASEDIR
)) {
2139 io
.generic
.level
= RAW_LOCK_LOCKX
;
2141 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2142 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2143 "Failed to create %s - %s\n",
2144 fname
, smbcli_errstr(cli
->tree
)));
2146 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2147 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
2148 "Failed to create %s - %s\n",
2149 fname
, smbcli_errstr(cli
->tree
)));
2151 /* Setup initial parameters */
2152 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2153 io
.lockx
.in
.timeout
= 0;
2155 lock1
.pid
= cli
->session
->pid
;
2160 rd
.readx
.level
= RAW_READ_READX
;
2162 torture_comment(tctx
, "Testing zero byte read on lock range:\n");
2164 /* Take an exclusive lock */
2165 torture_comment(tctx
, " taking exclusive lock.\n");
2166 io
.lockx
.in
.ulock_cnt
= 0;
2167 io
.lockx
.in
.lock_cnt
= 1;
2168 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2169 io
.lockx
.in
.file
.fnum
= fnum1
;
2170 io
.lockx
.in
.locks
= &lock1
;
2171 status
= smb_raw_lock(cli
->tree
, &io
);
2172 CHECK_STATUS(status
, NT_STATUS_OK
);
2174 /* Try a zero byte read */
2175 torture_comment(tctx
, " reading 0 bytes.\n");
2176 rd
.readx
.in
.file
.fnum
= fnum2
;
2177 rd
.readx
.in
.offset
= 5;
2178 rd
.readx
.in
.mincnt
= 0;
2179 rd
.readx
.in
.maxcnt
= 0;
2180 rd
.readx
.in
.remaining
= 0;
2181 rd
.readx
.in
.read_for_execute
= false;
2182 rd
.readx
.out
.data
= &c
;
2183 status
= smb_raw_read(cli
->tree
, &rd
);
2184 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2185 "zero byte read did not return 0 bytes");
2186 CHECK_STATUS(status
, NT_STATUS_OK
);
2189 io
.lockx
.in
.ulock_cnt
= 1;
2190 io
.lockx
.in
.lock_cnt
= 0;
2191 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2192 io
.lockx
.in
.file
.fnum
= fnum1
;
2193 io
.lockx
.in
.locks
= &lock1
;
2194 status
= smb_raw_lock(cli
->tree
, &io
);
2195 CHECK_STATUS(status
, NT_STATUS_OK
);
2197 torture_comment(tctx
, "Testing zero byte read on zero byte lock "
2200 /* Take an exclusive lock */
2201 torture_comment(tctx
, " taking exclusive 0-byte lock.\n");
2202 io
.lockx
.in
.ulock_cnt
= 0;
2203 io
.lockx
.in
.lock_cnt
= 1;
2204 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2205 io
.lockx
.in
.file
.fnum
= fnum1
;
2206 io
.lockx
.in
.locks
= &lock1
;
2209 status
= smb_raw_lock(cli
->tree
, &io
);
2210 CHECK_STATUS(status
, NT_STATUS_OK
);
2212 /* Try a zero byte read before the lock */
2213 torture_comment(tctx
, " reading 0 bytes before the lock.\n");
2214 rd
.readx
.in
.file
.fnum
= fnum2
;
2215 rd
.readx
.in
.offset
= 4;
2216 rd
.readx
.in
.mincnt
= 0;
2217 rd
.readx
.in
.maxcnt
= 0;
2218 rd
.readx
.in
.remaining
= 0;
2219 rd
.readx
.in
.read_for_execute
= false;
2220 rd
.readx
.out
.data
= &c
;
2221 status
= smb_raw_read(cli
->tree
, &rd
);
2222 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2223 "zero byte read did not return 0 bytes");
2224 CHECK_STATUS(status
, NT_STATUS_OK
);
2226 /* Try a zero byte read on the lock */
2227 torture_comment(tctx
, " reading 0 bytes on the lock.\n");
2228 rd
.readx
.in
.file
.fnum
= fnum2
;
2229 rd
.readx
.in
.offset
= 5;
2230 rd
.readx
.in
.mincnt
= 0;
2231 rd
.readx
.in
.maxcnt
= 0;
2232 rd
.readx
.in
.remaining
= 0;
2233 rd
.readx
.in
.read_for_execute
= false;
2234 rd
.readx
.out
.data
= &c
;
2235 status
= smb_raw_read(cli
->tree
, &rd
);
2236 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2237 "zero byte read did not return 0 bytes");
2238 CHECK_STATUS(status
, NT_STATUS_OK
);
2240 /* Try a zero byte read after the lock */
2241 torture_comment(tctx
, " reading 0 bytes after the lock.\n");
2242 rd
.readx
.in
.file
.fnum
= fnum2
;
2243 rd
.readx
.in
.offset
= 6;
2244 rd
.readx
.in
.mincnt
= 0;
2245 rd
.readx
.in
.maxcnt
= 0;
2246 rd
.readx
.in
.remaining
= 0;
2247 rd
.readx
.in
.read_for_execute
= false;
2248 rd
.readx
.out
.data
= &c
;
2249 status
= smb_raw_read(cli
->tree
, &rd
);
2250 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2251 "zero byte read did not return 0 bytes");
2252 CHECK_STATUS(status
, NT_STATUS_OK
);
2255 io
.lockx
.in
.ulock_cnt
= 1;
2256 io
.lockx
.in
.lock_cnt
= 0;
2257 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2258 io
.lockx
.in
.file
.fnum
= fnum1
;
2259 io
.lockx
.in
.locks
= &lock1
;
2260 status
= smb_raw_lock(cli
->tree
, &io
);
2261 CHECK_STATUS(status
, NT_STATUS_OK
);
2264 smbcli_close(cli
->tree
, fnum1
);
2265 smbcli_close(cli
->tree
, fnum2
);
2266 smb_raw_exit(cli
->session
);
2267 smbcli_deltree(cli
->tree
, BASEDIR
);
2272 basic testing of lock calls
2274 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
2276 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "lock");
2278 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
2279 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
2280 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
2281 torture_suite_add_1smb_test(suite
, "async", test_async
);
2282 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
2283 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
2285 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
2286 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
2287 torture_suite_add_1smb_test(suite
, "multiple_unlock",
2288 test_multiple_unlock
);
2289 torture_suite_add_1smb_test(suite
, "zerobytelocks", test_zerobytelocks
);
2290 torture_suite_add_1smb_test(suite
, "zerobyteread", test_zerobyteread
);