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"
32 #include "torture/raw/proto.h"
34 #define CHECK_STATUS(status, correct) do { \
35 if (!NT_STATUS_EQUAL(status, correct)) { \
36 torture_result(tctx, TORTURE_FAIL, \
37 "(%s) Incorrect status %s - should be %s\n", \
38 __location__, nt_errstr(status), nt_errstr(correct)); \
43 #define CHECK_STATUS_CONT(status, correct) do { \
44 if (!NT_STATUS_EQUAL(status, correct)) { \
45 torture_result(tctx, TORTURE_FAIL, \
46 "(%s) Incorrect status %s - should be %s\n", \
47 __location__, nt_errstr(status), nt_errstr(correct)); \
51 #define CHECK_STATUS_OR(status, correct1, correct2) do { \
52 if ((!NT_STATUS_EQUAL(status, correct1)) && \
53 (!NT_STATUS_EQUAL(status, correct2))) { \
54 torture_result(tctx, TORTURE_FAIL, \
55 "(%s) Incorrect status %s - should be %s or %s\n", \
56 __location__, nt_errstr(status), nt_errstr(correct1), \
57 nt_errstr(correct2)); \
62 #define CHECK_STATUS_OR_CONT(status, correct1, correct2) do { \
63 if ((!NT_STATUS_EQUAL(status, correct1)) && \
64 (!NT_STATUS_EQUAL(status, correct2))) { \
65 torture_result(tctx, TORTURE_FAIL, \
66 "(%s) Incorrect status %s - should be %s or %s\n", \
67 __location__, nt_errstr(status), nt_errstr(correct1), \
68 nt_errstr(correct2)); \
71 #define BASEDIR "\\testlock"
73 #define TARGET_IS_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
74 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
75 #define TARGET_IS_WINDOWS(_tctx) \
76 ((torture_setting_bool(_tctx, "w2k3", false)) || \
77 (torture_setting_bool(_tctx, "w2k8", false)) || \
78 (torture_setting_bool(_tctx, "win7", false)))
79 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
80 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
82 #define TARGET_SUPPORTS_INVALID_LOCK_RANGE(_tctx) \
83 (torture_setting_bool(_tctx, "invalid_lock_range_support", true))
84 #define TARGET_SUPPORTS_SMBEXIT(_tctx) \
85 (torture_setting_bool(_tctx, "smbexit_pdu_support", true))
86 #define TARGET_SUPPORTS_SMBLOCK(_tctx) \
87 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
88 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
89 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
90 #define TARGET_RETURNS_RANGE_NOT_LOCKED(_tctx) \
91 (torture_setting_bool(_tctx, "range_not_locked_on_file_close", true))
93 test SMBlock and SMBunlock ops
95 static bool test_lock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
101 const char *fname
= BASEDIR
"\\test.txt";
103 if (!TARGET_SUPPORTS_SMBLOCK(tctx
))
104 torture_skip(tctx
, "Target does not support the SMBlock PDU");
106 if (!torture_setup_dir(cli
, BASEDIR
)) {
110 torture_comment(tctx
, "Testing RAW_LOCK_LOCK\n");
111 io
.generic
.level
= RAW_LOCK_LOCK
;
113 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
114 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
115 "Failed to create %s - %s\n",
116 fname
, smbcli_errstr(cli
->tree
)));
118 torture_comment(tctx
, "Trying 0/0 lock\n");
119 io
.lock
.level
= RAW_LOCK_LOCK
;
120 io
.lock
.in
.file
.fnum
= fnum
;
121 io
.lock
.in
.count
= 0;
122 io
.lock
.in
.offset
= 0;
123 status
= smb_raw_lock(cli
->tree
, &io
);
124 CHECK_STATUS(status
, NT_STATUS_OK
);
126 status
= smb_raw_lock(cli
->tree
, &io
);
127 CHECK_STATUS(status
, NT_STATUS_OK
);
129 io
.lock
.level
= RAW_LOCK_UNLOCK
;
130 status
= smb_raw_lock(cli
->tree
, &io
);
131 CHECK_STATUS(status
, NT_STATUS_OK
);
133 torture_comment(tctx
, "Trying 0/1 lock\n");
134 io
.lock
.level
= RAW_LOCK_LOCK
;
135 io
.lock
.in
.file
.fnum
= fnum
;
136 io
.lock
.in
.count
= 1;
137 io
.lock
.in
.offset
= 0;
138 status
= smb_raw_lock(cli
->tree
, &io
);
139 CHECK_STATUS(status
, NT_STATUS_OK
);
141 status
= smb_raw_lock(cli
->tree
, &io
);
142 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
144 io
.lock
.level
= RAW_LOCK_UNLOCK
;
145 status
= smb_raw_lock(cli
->tree
, &io
);
146 CHECK_STATUS(status
, NT_STATUS_OK
);
147 io
.lock
.level
= RAW_LOCK_UNLOCK
;
148 status
= smb_raw_lock(cli
->tree
, &io
);
149 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
151 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
152 io
.lock
.level
= RAW_LOCK_LOCK
;
153 io
.lock
.in
.file
.fnum
= fnum
;
154 io
.lock
.in
.count
= 4000;
155 io
.lock
.in
.offset
= 0xEEFFFFFF;
156 status
= smb_raw_lock(cli
->tree
, &io
);
157 CHECK_STATUS(status
, NT_STATUS_OK
);
159 status
= smb_raw_lock(cli
->tree
, &io
);
160 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
162 io
.lock
.level
= RAW_LOCK_UNLOCK
;
163 status
= smb_raw_lock(cli
->tree
, &io
);
164 CHECK_STATUS(status
, NT_STATUS_OK
);
165 io
.lock
.level
= RAW_LOCK_UNLOCK
;
166 status
= smb_raw_lock(cli
->tree
, &io
);
167 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
169 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
170 io
.lock
.level
= RAW_LOCK_LOCK
;
171 io
.lock
.in
.file
.fnum
= fnum
;
172 io
.lock
.in
.count
= 4000;
173 io
.lock
.in
.offset
= 0xEEFFFFFF;
174 status
= smb_raw_lock(cli
->tree
, &io
);
175 CHECK_STATUS(status
, NT_STATUS_OK
);
177 status
= smb_raw_lock(cli
->tree
, &io
);
178 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
180 io
.lock
.level
= RAW_LOCK_UNLOCK
;
181 status
= smb_raw_lock(cli
->tree
, &io
);
182 CHECK_STATUS(status
, NT_STATUS_OK
);
183 io
.lock
.level
= RAW_LOCK_UNLOCK
;
184 status
= smb_raw_lock(cli
->tree
, &io
);
185 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
187 torture_comment(tctx
, "Trying max lock\n");
188 io
.lock
.level
= RAW_LOCK_LOCK
;
189 io
.lock
.in
.file
.fnum
= fnum
;
190 io
.lock
.in
.count
= 4000;
191 io
.lock
.in
.offset
= 0xEF000000;
192 status
= smb_raw_lock(cli
->tree
, &io
);
193 CHECK_STATUS(status
, NT_STATUS_OK
);
195 status
= smb_raw_lock(cli
->tree
, &io
);
196 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
198 io
.lock
.level
= RAW_LOCK_UNLOCK
;
199 status
= smb_raw_lock(cli
->tree
, &io
);
200 CHECK_STATUS(status
, NT_STATUS_OK
);
201 io
.lock
.level
= RAW_LOCK_UNLOCK
;
202 status
= smb_raw_lock(cli
->tree
, &io
);
203 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
205 torture_comment(tctx
, "Trying wrong pid unlock\n");
206 io
.lock
.level
= RAW_LOCK_LOCK
;
207 io
.lock
.in
.file
.fnum
= fnum
;
208 io
.lock
.in
.count
= 4002;
209 io
.lock
.in
.offset
= 10001;
210 status
= smb_raw_lock(cli
->tree
, &io
);
211 CHECK_STATUS(status
, NT_STATUS_OK
);
213 io
.lock
.level
= RAW_LOCK_UNLOCK
;
214 status
= smb_raw_lock(cli
->tree
, &io
);
215 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
217 status
= smb_raw_lock(cli
->tree
, &io
);
218 CHECK_STATUS(status
, NT_STATUS_OK
);
221 smbcli_close(cli
->tree
, fnum
);
222 smb_raw_exit(cli
->session
);
223 smbcli_deltree(cli
->tree
, BASEDIR
);
231 static bool test_lockx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
234 struct smb_lock_entry lock
[1];
238 const char *fname
= BASEDIR
"\\test.txt";
240 if (!torture_setup_dir(cli
, BASEDIR
)) {
244 torture_comment(tctx
, "Testing RAW_LOCK_LOCKX\n");
245 io
.generic
.level
= RAW_LOCK_LOCKX
;
247 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
248 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
249 "Failed to create %s - %s\n",
250 fname
, smbcli_errstr(cli
->tree
)));
252 io
.lockx
.level
= RAW_LOCK_LOCKX
;
253 io
.lockx
.in
.file
.fnum
= fnum
;
254 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
255 io
.lockx
.in
.timeout
= 0;
256 io
.lockx
.in
.ulock_cnt
= 0;
257 io
.lockx
.in
.lock_cnt
= 1;
258 lock
[0].pid
= cli
->session
->pid
;
261 io
.lockx
.in
.locks
= &lock
[0];
262 status
= smb_raw_lock(cli
->tree
, &io
);
263 CHECK_STATUS(status
, NT_STATUS_OK
);
266 torture_comment(tctx
, "Trying 0xEEFFFFFF lock\n");
267 io
.lockx
.in
.ulock_cnt
= 0;
268 io
.lockx
.in
.lock_cnt
= 1;
269 lock
[0].count
= 4000;
270 lock
[0].offset
= 0xEEFFFFFF;
271 status
= smb_raw_lock(cli
->tree
, &io
);
272 CHECK_STATUS(status
, NT_STATUS_OK
);
274 status
= smb_raw_lock(cli
->tree
, &io
);
275 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
277 io
.lockx
.in
.ulock_cnt
= 1;
278 io
.lockx
.in
.lock_cnt
= 0;
279 status
= smb_raw_lock(cli
->tree
, &io
);
280 CHECK_STATUS(status
, NT_STATUS_OK
);
281 status
= smb_raw_lock(cli
->tree
, &io
);
282 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
284 torture_comment(tctx
, "Trying 0xEF000000 lock\n");
285 io
.lockx
.in
.ulock_cnt
= 0;
286 io
.lockx
.in
.lock_cnt
= 1;
287 lock
[0].count
= 4000;
288 lock
[0].offset
= 0xEF000000;
289 status
= smb_raw_lock(cli
->tree
, &io
);
290 CHECK_STATUS(status
, NT_STATUS_OK
);
292 status
= smb_raw_lock(cli
->tree
, &io
);
293 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
295 io
.lockx
.in
.ulock_cnt
= 1;
296 io
.lockx
.in
.lock_cnt
= 0;
297 status
= smb_raw_lock(cli
->tree
, &io
);
298 CHECK_STATUS(status
, NT_STATUS_OK
);
299 status
= smb_raw_lock(cli
->tree
, &io
);
300 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
302 torture_comment(tctx
, "Trying zero lock\n");
303 io
.lockx
.in
.ulock_cnt
= 0;
304 io
.lockx
.in
.lock_cnt
= 1;
307 status
= smb_raw_lock(cli
->tree
, &io
);
308 CHECK_STATUS(status
, NT_STATUS_OK
);
310 status
= smb_raw_lock(cli
->tree
, &io
);
311 CHECK_STATUS(status
, NT_STATUS_OK
);
313 io
.lockx
.in
.ulock_cnt
= 1;
314 io
.lockx
.in
.lock_cnt
= 0;
315 status
= smb_raw_lock(cli
->tree
, &io
);
316 CHECK_STATUS(status
, NT_STATUS_OK
);
317 status
= smb_raw_lock(cli
->tree
, &io
);
318 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
320 torture_comment(tctx
, "Trying max lock\n");
321 io
.lockx
.in
.ulock_cnt
= 0;
322 io
.lockx
.in
.lock_cnt
= 1;
325 status
= smb_raw_lock(cli
->tree
, &io
);
326 CHECK_STATUS(status
, NT_STATUS_OK
);
328 status
= smb_raw_lock(cli
->tree
, &io
);
329 CHECK_STATUS(status
, NT_STATUS_OK
);
331 io
.lockx
.in
.ulock_cnt
= 1;
332 io
.lockx
.in
.lock_cnt
= 0;
333 status
= smb_raw_lock(cli
->tree
, &io
);
334 CHECK_STATUS(status
, NT_STATUS_OK
);
335 status
= smb_raw_lock(cli
->tree
, &io
);
336 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
338 torture_comment(tctx
, "Trying 2^63\n");
339 io
.lockx
.in
.ulock_cnt
= 0;
340 io
.lockx
.in
.lock_cnt
= 1;
343 lock
[0].offset
<<= 63;
344 status
= smb_raw_lock(cli
->tree
, &io
);
345 CHECK_STATUS(status
, NT_STATUS_OK
);
347 status
= smb_raw_lock(cli
->tree
, &io
);
348 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
350 io
.lockx
.in
.ulock_cnt
= 1;
351 io
.lockx
.in
.lock_cnt
= 0;
352 status
= smb_raw_lock(cli
->tree
, &io
);
353 CHECK_STATUS(status
, NT_STATUS_OK
);
354 status
= smb_raw_lock(cli
->tree
, &io
);
355 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
357 torture_comment(tctx
, "Trying 2^63 - 1\n");
358 io
.lockx
.in
.ulock_cnt
= 0;
359 io
.lockx
.in
.lock_cnt
= 1;
362 lock
[0].offset
<<= 63;
364 status
= smb_raw_lock(cli
->tree
, &io
);
365 CHECK_STATUS(status
, NT_STATUS_OK
);
367 status
= smb_raw_lock(cli
->tree
, &io
);
368 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
370 io
.lockx
.in
.ulock_cnt
= 1;
371 io
.lockx
.in
.lock_cnt
= 0;
372 status
= smb_raw_lock(cli
->tree
, &io
);
373 CHECK_STATUS(status
, NT_STATUS_OK
);
374 status
= smb_raw_lock(cli
->tree
, &io
);
375 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
377 torture_comment(tctx
, "Trying max lock 2\n");
378 io
.lockx
.in
.ulock_cnt
= 0;
379 io
.lockx
.in
.lock_cnt
= 1;
382 status
= smb_raw_lock(cli
->tree
, &io
);
383 CHECK_STATUS(status
, NT_STATUS_OK
);
386 status
= smb_raw_lock(cli
->tree
, &io
);
387 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx
))
388 CHECK_STATUS(status
, NT_STATUS_INVALID_LOCK_RANGE
);
390 CHECK_STATUS(status
, NT_STATUS_OK
);
392 io
.lockx
.in
.ulock_cnt
= 1;
393 io
.lockx
.in
.lock_cnt
= 0;
395 status
= smb_raw_lock(cli
->tree
, &io
);
397 CHECK_STATUS(status
, NT_STATUS_OK
);
398 status
= smb_raw_lock(cli
->tree
, &io
);
399 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
402 smbcli_close(cli
->tree
, fnum
);
403 smb_raw_exit(cli
->session
);
404 smbcli_deltree(cli
->tree
, BASEDIR
);
411 static bool test_pidhigh(struct torture_context
*tctx
,
412 struct smbcli_state
*cli
)
415 struct smb_lock_entry lock
[1];
419 const char *fname
= BASEDIR
"\\test.txt";
422 if (!torture_setup_dir(cli
, BASEDIR
)) {
426 torture_comment(tctx
, "Testing high pid\n");
427 io
.generic
.level
= RAW_LOCK_LOCKX
;
429 cli
->session
->pid
= 1;
431 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
432 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
433 "Failed to create %s - %s\n",
434 fname
, smbcli_errstr(cli
->tree
)));
436 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 0, 1) != 1) {
437 torture_result(tctx
, TORTURE_FAIL
,
438 "Failed to write 1 byte - %s\n",
439 smbcli_errstr(cli
->tree
));
444 io
.lockx
.level
= RAW_LOCK_LOCKX
;
445 io
.lockx
.in
.file
.fnum
= fnum
;
446 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
447 io
.lockx
.in
.timeout
= 0;
448 io
.lockx
.in
.ulock_cnt
= 0;
449 io
.lockx
.in
.lock_cnt
= 1;
450 lock
[0].pid
= cli
->session
->pid
;
452 lock
[0].count
= 0xFFFFFFFF;
453 io
.lockx
.in
.locks
= &lock
[0];
454 status
= smb_raw_lock(cli
->tree
, &io
);
455 CHECK_STATUS(status
, NT_STATUS_OK
);
457 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
458 torture_result(tctx
, TORTURE_FAIL
,
459 "Failed to read 1 byte - %s\n",
460 smbcli_errstr(cli
->tree
));
465 cli
->session
->pid
= 2;
467 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) == 1) {
468 torture_result(tctx
, TORTURE_FAIL
,
469 "pid is incorrect handled for read with lock!\n");
474 cli
->session
->pid
= 0x10001;
476 if (smbcli_read(cli
->tree
, fnum
, &c
, 0, 1) != 1) {
477 torture_result(tctx
, TORTURE_FAIL
,
478 "High pid is used on this server!\n");
481 torture_warning(tctx
, "High pid is not used on this server (correct)\n");
485 smbcli_close(cli
->tree
, fnum
);
486 smb_raw_exit(cli
->session
);
487 smbcli_deltree(cli
->tree
, BASEDIR
);
493 test locking&X async operation
495 static bool test_async(struct torture_context
*tctx
,
496 struct smbcli_state
*cli
)
498 struct smbcli_session
*session
;
499 struct smb_composite_sesssetup setup
;
500 struct smbcli_tree
*tree
;
502 const char *host
, *share
;
504 struct smb_lock_entry lock
[2];
508 const char *fname
= BASEDIR
"\\test.txt";
510 struct smbcli_request
*req
, *req2
;
511 struct smbcli_session_options options
;
513 if (!torture_setup_dir(cli
, BASEDIR
)) {
517 lpcfg_smbcli_session_options(tctx
->lp_ctx
, &options
);
519 torture_comment(tctx
, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
520 io
.generic
.level
= RAW_LOCK_LOCKX
;
522 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
523 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
524 "Failed to create %s - %s\n",
525 fname
, smbcli_errstr(cli
->tree
)));
527 io
.lockx
.level
= RAW_LOCK_LOCKX
;
528 io
.lockx
.in
.file
.fnum
= fnum
;
529 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
530 io
.lockx
.in
.timeout
= 0;
531 io
.lockx
.in
.ulock_cnt
= 0;
532 io
.lockx
.in
.lock_cnt
= 1;
533 lock
[0].pid
= cli
->session
->pid
;
534 lock
[0].offset
= 100;
536 lock
[1].pid
= cli
->session
->pid
;
537 lock
[1].offset
= 110;
539 io
.lockx
.in
.locks
= &lock
[0];
540 status
= smb_raw_lock(cli
->tree
, &io
);
541 CHECK_STATUS(status
, NT_STATUS_OK
);
545 torture_comment(tctx
, "Testing cancel by CANCEL_LOCK\n");
547 /* setup a timed lock */
548 io
.lockx
.in
.timeout
= 10000;
549 req
= smb_raw_lock_send(cli
->tree
, &io
);
550 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
551 "Failed to setup timed lock (%s)\n", __location__
));
553 /* cancel the wrong range */
555 io
.lockx
.in
.timeout
= 0;
556 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
557 status
= smb_raw_lock(cli
->tree
, &io
);
558 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
560 /* cancel with the wrong bits set */
561 lock
[0].offset
= 100;
562 io
.lockx
.in
.timeout
= 0;
563 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
;
564 status
= smb_raw_lock(cli
->tree
, &io
);
565 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRcancelviolation
));
567 /* cancel the right range */
568 lock
[0].offset
= 100;
569 io
.lockx
.in
.timeout
= 0;
570 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
571 status
= smb_raw_lock(cli
->tree
, &io
);
572 CHECK_STATUS(status
, NT_STATUS_OK
);
574 /* receive the failed lock request */
575 status
= smbcli_request_simple_recv(req
);
576 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
578 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
579 "lock cancel was not immediate (%s)\n", __location__
));
581 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
582 * if the lock vector contains one entry. When given mutliple cancel
583 * requests in a single PDU we expect the server to return an
584 * error. Samba4 handles this correctly. Windows servers seem to
585 * accept the request but only cancel the first lock. Samba3
586 * now does what Windows does (JRA).
588 torture_comment(tctx
, "Testing multiple cancel\n");
590 /* acquire second lock */
591 io
.lockx
.in
.timeout
= 0;
592 io
.lockx
.in
.ulock_cnt
= 0;
593 io
.lockx
.in
.lock_cnt
= 1;
594 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
595 io
.lockx
.in
.locks
= &lock
[1];
596 status
= smb_raw_lock(cli
->tree
, &io
);
597 CHECK_STATUS(status
, NT_STATUS_OK
);
599 /* setup 2 timed locks */
601 io
.lockx
.in
.timeout
= 10000;
602 io
.lockx
.in
.lock_cnt
= 1;
603 io
.lockx
.in
.locks
= &lock
[0];
604 req
= smb_raw_lock_send(cli
->tree
, &io
);
605 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
606 "Failed to setup timed lock (%s)\n", __location__
));
607 io
.lockx
.in
.locks
= &lock
[1];
608 req2
= smb_raw_lock_send(cli
->tree
, &io
);
609 torture_assert(tctx
,(req2
!= NULL
), talloc_asprintf(tctx
,
610 "Failed to setup timed lock (%s)\n", __location__
));
612 /* try to cancel both locks in the same packet */
613 io
.lockx
.in
.timeout
= 0;
614 io
.lockx
.in
.lock_cnt
= 2;
615 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
616 io
.lockx
.in
.locks
= lock
;
617 status
= smb_raw_lock(cli
->tree
, &io
);
618 CHECK_STATUS(status
, NT_STATUS_OK
);
620 torture_warning(tctx
, "Target server accepted a lock cancel "
621 "request with multiple locks. This violates "
622 "MS-CIFS 2.2.4.32.1.\n");
624 /* receive the failed lock requests */
625 status
= smbcli_request_simple_recv(req
);
626 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
628 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
629 "first lock was not cancelled immediately (%s)\n",
632 /* send cancel to second lock */
633 io
.lockx
.in
.timeout
= 0;
634 io
.lockx
.in
.lock_cnt
= 1;
635 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
|
636 LOCKING_ANDX_LARGE_FILES
;
637 io
.lockx
.in
.locks
= &lock
[1];
638 status
= smb_raw_lock(cli
->tree
, &io
);
639 CHECK_STATUS(status
, NT_STATUS_OK
);
641 status
= smbcli_request_simple_recv(req2
);
642 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
644 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
645 "second lock was not cancelled immediately (%s)\n",
648 /* cleanup the second lock */
649 io
.lockx
.in
.ulock_cnt
= 1;
650 io
.lockx
.in
.lock_cnt
= 0;
651 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
652 io
.lockx
.in
.locks
= &lock
[1];
653 status
= smb_raw_lock(cli
->tree
, &io
);
654 CHECK_STATUS(status
, NT_STATUS_OK
);
656 /* If a lock request contained multiple ranges and we are cancelling
657 * one while it's still pending, what happens? */
658 torture_comment(tctx
, "Testing cancel 1/2 lock request\n");
660 /* Send request with two ranges */
661 io
.lockx
.in
.timeout
= -1;
662 io
.lockx
.in
.ulock_cnt
= 0;
663 io
.lockx
.in
.lock_cnt
= 2;
664 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
665 io
.lockx
.in
.locks
= lock
;
666 req
= smb_raw_lock_send(cli
->tree
, &io
);
667 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
668 "Failed to setup pending lock (%s)\n", __location__
));
670 /* Try to cancel the first lock range */
671 io
.lockx
.in
.timeout
= 0;
672 io
.lockx
.in
.lock_cnt
= 1;
673 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
674 io
.lockx
.in
.locks
= &lock
[0];
675 status
= smb_raw_lock(cli
->tree
, &io
);
676 CHECK_STATUS(status
, NT_STATUS_OK
);
678 /* Locking request should've failed and second range should be
680 status
= smbcli_request_simple_recv(req
);
681 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
683 io
.lockx
.in
.timeout
= 0;
684 io
.lockx
.in
.ulock_cnt
= 0;
685 io
.lockx
.in
.lock_cnt
= 1;
686 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
687 io
.lockx
.in
.locks
= &lock
[1];
688 status
= smb_raw_lock(cli
->tree
, &io
);
689 CHECK_STATUS(status
, NT_STATUS_OK
);
691 /* Cleanup both locks */
692 io
.lockx
.in
.ulock_cnt
= 2;
693 io
.lockx
.in
.lock_cnt
= 0;
694 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
695 io
.lockx
.in
.locks
= lock
;
696 status
= smb_raw_lock(cli
->tree
, &io
);
697 CHECK_STATUS(status
, NT_STATUS_OK
);
699 torture_comment(tctx
, "Testing cancel 2/2 lock request\n");
701 /* Lock second range so it contends */
702 io
.lockx
.in
.timeout
= 0;
703 io
.lockx
.in
.ulock_cnt
= 0;
704 io
.lockx
.in
.lock_cnt
= 1;
705 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
706 io
.lockx
.in
.locks
= &lock
[1];
707 status
= smb_raw_lock(cli
->tree
, &io
);
708 CHECK_STATUS(status
, NT_STATUS_OK
);
710 /* Send request with two ranges */
711 io
.lockx
.in
.timeout
= -1;
712 io
.lockx
.in
.ulock_cnt
= 0;
713 io
.lockx
.in
.lock_cnt
= 2;
714 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
715 io
.lockx
.in
.locks
= lock
;
716 req
= smb_raw_lock_send(cli
->tree
, &io
);
717 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
718 "Failed to setup pending lock (%s)\n", __location__
));
720 /* Try to cancel the second lock range */
721 io
.lockx
.in
.timeout
= 0;
722 io
.lockx
.in
.lock_cnt
= 1;
723 io
.lockx
.in
.mode
= LOCKING_ANDX_CANCEL_LOCK
| LOCKING_ANDX_LARGE_FILES
;
724 io
.lockx
.in
.locks
= &lock
[1];
725 status
= smb_raw_lock(cli
->tree
, &io
);
726 CHECK_STATUS(status
, NT_STATUS_OK
);
728 /* Locking request should've failed and first range should be
730 status
= smbcli_request_simple_recv(req
);
731 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
733 io
.lockx
.in
.timeout
= 0;
734 io
.lockx
.in
.ulock_cnt
= 0;
735 io
.lockx
.in
.lock_cnt
= 1;
736 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
737 io
.lockx
.in
.locks
= &lock
[0];
738 status
= smb_raw_lock(cli
->tree
, &io
);
739 CHECK_STATUS(status
, NT_STATUS_OK
);
741 /* Cleanup both locks */
742 io
.lockx
.in
.ulock_cnt
= 2;
743 io
.lockx
.in
.lock_cnt
= 0;
744 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
745 io
.lockx
.in
.locks
= lock
;
746 status
= smb_raw_lock(cli
->tree
, &io
);
747 CHECK_STATUS(status
, NT_STATUS_OK
);
749 torture_comment(tctx
, "Testing cancel by unlock\n");
750 io
.lockx
.in
.ulock_cnt
= 0;
751 io
.lockx
.in
.lock_cnt
= 1;
752 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
753 io
.lockx
.in
.timeout
= 0;
754 io
.lockx
.in
.locks
= &lock
[0];
755 status
= smb_raw_lock(cli
->tree
, &io
);
756 CHECK_STATUS(status
, NT_STATUS_OK
);
758 io
.lockx
.in
.timeout
= 5000;
759 req
= smb_raw_lock_send(cli
->tree
, &io
);
760 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
761 "Failed to setup timed lock (%s)\n", __location__
));
763 io
.lockx
.in
.ulock_cnt
= 1;
764 io
.lockx
.in
.lock_cnt
= 0;
765 status
= smb_raw_lock(cli
->tree
, &io
);
766 CHECK_STATUS(status
, NT_STATUS_OK
);
769 status
= smbcli_request_simple_recv(req
);
770 CHECK_STATUS(status
, NT_STATUS_OK
);
772 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
773 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
774 __location__
, (int)(time_mono(NULL
)-t
)));
776 torture_comment(tctx
, "Testing cancel by close\n");
777 io
.lockx
.in
.ulock_cnt
= 0;
778 io
.lockx
.in
.lock_cnt
= 1;
779 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
780 io
.lockx
.in
.timeout
= 0;
781 status
= smb_raw_lock(cli
->tree
, &io
);
782 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
785 io
.lockx
.in
.timeout
= 10000;
786 req
= smb_raw_lock_send(cli
->tree
, &io
);
787 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
788 "Failed to setup timed lock (%s)\n", __location__
));
790 status
= smbcli_close(cli
->tree
, fnum
);
791 CHECK_STATUS(status
, NT_STATUS_OK
);
793 status
= smbcli_request_simple_recv(req
);
794 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
795 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
797 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
799 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
800 "lock cancel by close was not immediate (%s)\n", __location__
));
802 torture_comment(tctx
, "create a new sessions\n");
803 session
= smbcli_session_init(cli
->transport
, tctx
, false, options
);
804 setup
.in
.sesskey
= cli
->transport
->negotiate
.sesskey
;
805 setup
.in
.capabilities
= cli
->transport
->negotiate
.capabilities
;
806 setup
.in
.workgroup
= lpcfg_workgroup(tctx
->lp_ctx
);
807 setup
.in
.credentials
= cmdline_credentials
;
808 setup
.in
.gensec_settings
= lpcfg_gensec_settings(tctx
, tctx
->lp_ctx
);
809 status
= smb_composite_sesssetup(session
, &setup
);
810 CHECK_STATUS(status
, NT_STATUS_OK
);
811 session
->vuid
= setup
.out
.vuid
;
813 torture_comment(tctx
, "create new tree context\n");
814 share
= torture_setting_string(tctx
, "share", NULL
);
815 host
= torture_setting_string(tctx
, "host", NULL
);
816 tree
= smbcli_tree_init(session
, tctx
, false);
817 tcon
.generic
.level
= RAW_TCON_TCONX
;
818 tcon
.tconx
.in
.flags
= 0;
819 tcon
.tconx
.in
.password
= data_blob(NULL
, 0);
820 tcon
.tconx
.in
.path
= talloc_asprintf(tctx
, "\\\\%s\\%s", host
, share
);
821 tcon
.tconx
.in
.device
= "A:";
822 status
= smb_raw_tcon(tree
, tctx
, &tcon
);
823 CHECK_STATUS(status
, NT_STATUS_OK
);
824 tree
->tid
= tcon
.tconx
.out
.tid
;
826 torture_comment(tctx
, "Testing cancel by exit\n");
827 if (TARGET_SUPPORTS_SMBEXIT(tctx
)) {
828 fname
= BASEDIR
"\\test_exit.txt";
829 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
830 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
831 "Failed to reopen %s - %s\n",
832 fname
, smbcli_errstr(tree
)));
834 io
.lockx
.level
= RAW_LOCK_LOCKX
;
835 io
.lockx
.in
.file
.fnum
= fnum
;
836 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
837 io
.lockx
.in
.timeout
= 0;
838 io
.lockx
.in
.ulock_cnt
= 0;
839 io
.lockx
.in
.lock_cnt
= 1;
840 lock
[0].pid
= session
->pid
;
841 lock
[0].offset
= 100;
843 io
.lockx
.in
.locks
= &lock
[0];
844 status
= smb_raw_lock(tree
, &io
);
845 CHECK_STATUS(status
, NT_STATUS_OK
);
847 io
.lockx
.in
.ulock_cnt
= 0;
848 io
.lockx
.in
.lock_cnt
= 1;
849 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
850 io
.lockx
.in
.timeout
= 0;
851 status
= smb_raw_lock(tree
, &io
);
852 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
854 io
.lockx
.in
.timeout
= 10000;
856 req
= smb_raw_lock_send(tree
, &io
);
857 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
858 "Failed to setup timed lock (%s)\n",
861 status
= smb_raw_exit(session
);
862 CHECK_STATUS(status
, NT_STATUS_OK
);
864 status
= smbcli_request_simple_recv(req
);
865 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
866 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
868 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
870 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
871 "lock cancel by exit was not immediate (%s)\n",
875 torture_comment(tctx
,
876 " skipping test, SMBExit not supported\n");
879 torture_comment(tctx
, "Testing cancel by ulogoff\n");
880 fname
= BASEDIR
"\\test_ulogoff.txt";
881 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
882 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
883 "Failed to reopen %s - %s\n",
884 fname
, smbcli_errstr(tree
)));
886 io
.lockx
.level
= RAW_LOCK_LOCKX
;
887 io
.lockx
.in
.file
.fnum
= fnum
;
888 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
889 io
.lockx
.in
.timeout
= 0;
890 io
.lockx
.in
.ulock_cnt
= 0;
891 io
.lockx
.in
.lock_cnt
= 1;
892 lock
[0].pid
= session
->pid
;
893 lock
[0].offset
= 100;
895 io
.lockx
.in
.locks
= &lock
[0];
896 status
= smb_raw_lock(tree
, &io
);
897 CHECK_STATUS(status
, NT_STATUS_OK
);
899 io
.lockx
.in
.ulock_cnt
= 0;
900 io
.lockx
.in
.lock_cnt
= 1;
901 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
902 io
.lockx
.in
.timeout
= 0;
903 status
= smb_raw_lock(tree
, &io
);
904 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
906 io
.lockx
.in
.timeout
= 10000;
908 req
= smb_raw_lock_send(tree
, &io
);
909 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
910 "Failed to setup timed lock (%s)\n", __location__
));
912 status
= smb_raw_ulogoff(session
);
913 CHECK_STATUS(status
, NT_STATUS_OK
);
915 status
= smbcli_request_simple_recv(req
);
916 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
)) {
917 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT
, status
)) {
918 torture_result(tctx
, TORTURE_FAIL
,
919 "lock not canceled by ulogoff - %s "
920 "(ignored because of vfs_vifs fails it)\n",
922 smb_tree_disconnect(tree
);
923 smb_raw_exit(session
);
926 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
928 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
931 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
932 "lock cancel by ulogoff was not immediate (%s)\n", __location__
));
934 torture_comment(tctx
, "Testing cancel by tdis\n");
935 tree
->session
= cli
->session
;
937 fname
= BASEDIR
"\\test_tdis.txt";
938 fnum
= smbcli_open(tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
939 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
940 "Failed to reopen %s - %s\n",
941 fname
, smbcli_errstr(tree
)));
943 io
.lockx
.level
= RAW_LOCK_LOCKX
;
944 io
.lockx
.in
.file
.fnum
= fnum
;
945 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
946 io
.lockx
.in
.timeout
= 0;
947 io
.lockx
.in
.ulock_cnt
= 0;
948 io
.lockx
.in
.lock_cnt
= 1;
949 lock
[0].pid
= cli
->session
->pid
;
950 lock
[0].offset
= 100;
952 io
.lockx
.in
.locks
= &lock
[0];
953 status
= smb_raw_lock(tree
, &io
);
954 CHECK_STATUS(status
, NT_STATUS_OK
);
956 status
= smb_raw_lock(tree
, &io
);
957 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
959 io
.lockx
.in
.timeout
= 10000;
961 req
= smb_raw_lock_send(tree
, &io
);
962 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
963 "Failed to setup timed lock (%s)\n", __location__
));
965 status
= smb_tree_disconnect(tree
);
966 CHECK_STATUS(status
, NT_STATUS_OK
);
968 status
= smbcli_request_simple_recv(req
);
969 if (TARGET_RETURNS_RANGE_NOT_LOCKED(tctx
))
970 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
972 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
974 torture_assert(tctx
,!(time_mono(NULL
) > t
+2), talloc_asprintf(tctx
,
975 "lock cancel by tdis was not immediate (%s)\n", __location__
));
978 smb_raw_exit(cli
->session
);
979 smbcli_deltree(cli
->tree
, BASEDIR
);
984 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
986 static bool test_errorcode(struct torture_context
*tctx
,
987 struct smbcli_state
*cli
)
991 struct smb_lock_entry lock
[2];
996 struct smbcli_request
*req
;
1000 uint16_t deny_mode
= 0;
1002 if (!torture_setup_dir(cli
, BASEDIR
)) {
1006 torture_comment(tctx
, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
1008 torture_comment(tctx
, "Testing with timeout = 0\n");
1009 fname
= BASEDIR
"\\test0.txt";
1013 * the first run is with t = 0,
1014 * the second with t > 0 (=1)
1018 * use the DENY_DOS mode, that creates two fnum's of one low-level
1019 * file handle, this demonstrates that the cache is per fnum, not
1022 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx
))
1023 deny_mode
= OPENX_MODE_DENY_DOS
;
1025 deny_mode
= OPENX_MODE_DENY_NONE
;
1027 op
.openx
.level
= RAW_OPEN_OPENX
;
1028 op
.openx
.in
.fname
= fname
;
1029 op
.openx
.in
.flags
= OPENX_FLAGS_ADDITIONAL_INFO
;
1030 op
.openx
.in
.open_mode
= OPENX_MODE_ACCESS_RDWR
| deny_mode
;
1031 op
.openx
.in
.open_func
= OPENX_OPEN_FUNC_OPEN
| OPENX_OPEN_FUNC_CREATE
;
1032 op
.openx
.in
.search_attrs
= 0;
1033 op
.openx
.in
.file_attrs
= 0;
1034 op
.openx
.in
.write_time
= 0;
1035 op
.openx
.in
.size
= 0;
1036 op
.openx
.in
.timeout
= 0;
1038 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1039 CHECK_STATUS(status
, NT_STATUS_OK
);
1040 fnum
= op
.openx
.out
.file
.fnum
;
1042 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
1043 CHECK_STATUS(status
, NT_STATUS_OK
);
1044 fnum2
= op
.openx
.out
.file
.fnum
;
1046 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1047 io
.lockx
.in
.file
.fnum
= fnum
;
1048 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1049 io
.lockx
.in
.timeout
= t
;
1050 io
.lockx
.in
.ulock_cnt
= 0;
1051 io
.lockx
.in
.lock_cnt
= 1;
1052 lock
[0].pid
= cli
->session
->pid
;
1053 lock
[0].offset
= 100;
1055 io
.lockx
.in
.locks
= &lock
[0];
1056 status
= smb_raw_lock(cli
->tree
, &io
);
1057 CHECK_STATUS(status
, NT_STATUS_OK
);
1060 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
1061 * this also demonstrates that the error code cache is per file handle
1062 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
1064 io
.lockx
.in
.file
.fnum
= fnum2
;
1065 status
= smb_raw_lock(cli
->tree
, &io
);
1066 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1068 io
.lockx
.in
.file
.fnum
= fnum
;
1069 status
= smb_raw_lock(cli
->tree
, &io
);
1070 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1072 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
1073 io
.lockx
.in
.file
.fnum
= fnum
;
1074 status
= smb_raw_lock(cli
->tree
, &io
);
1075 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1077 io
.lockx
.in
.file
.fnum
= fnum2
;
1078 status
= smb_raw_lock(cli
->tree
, &io
);
1079 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1081 io
.lockx
.in
.file
.fnum
= fnum
;
1082 status
= smb_raw_lock(cli
->tree
, &io
);
1083 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1085 io
.lockx
.in
.file
.fnum
= fnum2
;
1086 status
= smb_raw_lock(cli
->tree
, &io
);
1087 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1089 /* demonstrate that the smbpid doesn't matter */
1091 io
.lockx
.in
.file
.fnum
= fnum
;
1092 status
= smb_raw_lock(cli
->tree
, &io
);
1093 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1095 io
.lockx
.in
.file
.fnum
= fnum2
;
1096 status
= smb_raw_lock(cli
->tree
, &io
);
1097 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1101 * demonstrate the a successful lock with count = 0 and the same offset,
1102 * doesn't reset the error cache
1104 lock
[0].offset
= 100;
1106 io
.lockx
.in
.file
.fnum
= fnum
;
1107 status
= smb_raw_lock(cli
->tree
, &io
);
1108 CHECK_STATUS(status
, NT_STATUS_OK
);
1110 io
.lockx
.in
.file
.fnum
= fnum2
;
1111 status
= smb_raw_lock(cli
->tree
, &io
);
1112 CHECK_STATUS(status
, NT_STATUS_OK
);
1114 lock
[0].offset
= 100;
1116 io
.lockx
.in
.file
.fnum
= fnum
;
1117 status
= smb_raw_lock(cli
->tree
, &io
);
1118 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1120 io
.lockx
.in
.file
.fnum
= fnum2
;
1121 status
= smb_raw_lock(cli
->tree
, &io
);
1122 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1125 * demonstrate the a successful lock with count = 0 and outside the locked range,
1126 * doesn't reset the error cache
1128 lock
[0].offset
= 110;
1130 io
.lockx
.in
.file
.fnum
= fnum
;
1131 status
= smb_raw_lock(cli
->tree
, &io
);
1132 CHECK_STATUS(status
, NT_STATUS_OK
);
1134 io
.lockx
.in
.file
.fnum
= fnum2
;
1135 status
= smb_raw_lock(cli
->tree
, &io
);
1136 CHECK_STATUS(status
, NT_STATUS_OK
);
1138 lock
[0].offset
= 100;
1140 io
.lockx
.in
.file
.fnum
= fnum
;
1141 status
= smb_raw_lock(cli
->tree
, &io
);
1142 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1144 io
.lockx
.in
.file
.fnum
= fnum2
;
1145 status
= smb_raw_lock(cli
->tree
, &io
);
1146 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1148 lock
[0].offset
= 99;
1150 io
.lockx
.in
.file
.fnum
= fnum
;
1151 status
= smb_raw_lock(cli
->tree
, &io
);
1152 CHECK_STATUS(status
, NT_STATUS_OK
);
1154 io
.lockx
.in
.file
.fnum
= fnum2
;
1155 status
= smb_raw_lock(cli
->tree
, &io
);
1156 CHECK_STATUS(status
, NT_STATUS_OK
);
1158 lock
[0].offset
= 100;
1160 io
.lockx
.in
.file
.fnum
= fnum
;
1161 status
= smb_raw_lock(cli
->tree
, &io
);
1162 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1164 io
.lockx
.in
.file
.fnum
= fnum2
;
1165 status
= smb_raw_lock(cli
->tree
, &io
);
1166 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1168 /* demonstrate that a changing count doesn't reset the error cache */
1169 lock
[0].offset
= 100;
1171 io
.lockx
.in
.file
.fnum
= fnum
;
1172 status
= smb_raw_lock(cli
->tree
, &io
);
1173 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1175 io
.lockx
.in
.file
.fnum
= fnum2
;
1176 status
= smb_raw_lock(cli
->tree
, &io
);
1177 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1179 lock
[0].offset
= 100;
1181 io
.lockx
.in
.file
.fnum
= fnum
;
1182 status
= smb_raw_lock(cli
->tree
, &io
);
1183 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1185 io
.lockx
.in
.file
.fnum
= fnum2
;
1186 status
= smb_raw_lock(cli
->tree
, &io
);
1187 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1190 * demonstrate the a lock with count = 0 and inside the locked range,
1191 * fails and resets the error cache
1193 lock
[0].offset
= 101;
1195 io
.lockx
.in
.file
.fnum
= fnum
;
1196 status
= smb_raw_lock(cli
->tree
, &io
);
1197 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1198 status
= smb_raw_lock(cli
->tree
, &io
);
1199 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1201 io
.lockx
.in
.file
.fnum
= fnum2
;
1202 status
= smb_raw_lock(cli
->tree
, &io
);
1203 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1204 status
= smb_raw_lock(cli
->tree
, &io
);
1205 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1207 lock
[0].offset
= 100;
1209 io
.lockx
.in
.file
.fnum
= fnum
;
1210 status
= smb_raw_lock(cli
->tree
, &io
);
1211 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1212 status
= smb_raw_lock(cli
->tree
, &io
);
1213 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1215 io
.lockx
.in
.file
.fnum
= fnum2
;
1216 status
= smb_raw_lock(cli
->tree
, &io
);
1217 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1218 status
= smb_raw_lock(cli
->tree
, &io
);
1219 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1221 /* demonstrate the a changing offset, resets the error cache */
1222 lock
[0].offset
= 105;
1224 io
.lockx
.in
.file
.fnum
= fnum
;
1225 status
= smb_raw_lock(cli
->tree
, &io
);
1226 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1227 status
= smb_raw_lock(cli
->tree
, &io
);
1228 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1230 io
.lockx
.in
.file
.fnum
= fnum2
;
1231 status
= smb_raw_lock(cli
->tree
, &io
);
1232 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1233 status
= smb_raw_lock(cli
->tree
, &io
);
1234 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1236 lock
[0].offset
= 100;
1238 io
.lockx
.in
.file
.fnum
= fnum
;
1239 status
= smb_raw_lock(cli
->tree
, &io
);
1240 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1241 status
= smb_raw_lock(cli
->tree
, &io
);
1242 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1244 io
.lockx
.in
.file
.fnum
= fnum2
;
1245 status
= smb_raw_lock(cli
->tree
, &io
);
1246 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1247 status
= smb_raw_lock(cli
->tree
, &io
);
1248 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1250 lock
[0].offset
= 95;
1252 io
.lockx
.in
.file
.fnum
= fnum
;
1253 status
= smb_raw_lock(cli
->tree
, &io
);
1254 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1255 status
= smb_raw_lock(cli
->tree
, &io
);
1256 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1258 io
.lockx
.in
.file
.fnum
= fnum2
;
1259 status
= smb_raw_lock(cli
->tree
, &io
);
1260 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1261 status
= smb_raw_lock(cli
->tree
, &io
);
1262 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1264 lock
[0].offset
= 100;
1266 io
.lockx
.in
.file
.fnum
= fnum
;
1267 status
= smb_raw_lock(cli
->tree
, &io
);
1268 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1269 status
= smb_raw_lock(cli
->tree
, &io
);
1270 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1272 io
.lockx
.in
.file
.fnum
= fnum2
;
1273 status
= smb_raw_lock(cli
->tree
, &io
);
1274 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1275 status
= smb_raw_lock(cli
->tree
, &io
);
1276 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1279 * demonstrate the a successful lock in a different range,
1280 * doesn't reset the cache, the failing lock on the 2nd handle
1283 lock
[0].offset
= 120;
1285 io
.lockx
.in
.file
.fnum
= fnum
;
1286 status
= smb_raw_lock(cli
->tree
, &io
);
1287 CHECK_STATUS(status
, NT_STATUS_OK
);
1289 io
.lockx
.in
.file
.fnum
= fnum2
;
1290 status
= smb_raw_lock(cli
->tree
, &io
);
1291 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1293 lock
[0].offset
= 100;
1295 io
.lockx
.in
.file
.fnum
= fnum
;
1296 status
= smb_raw_lock(cli
->tree
, &io
);
1297 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1298 status
= smb_raw_lock(cli
->tree
, &io
);
1299 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1301 io
.lockx
.in
.file
.fnum
= fnum2
;
1302 status
= smb_raw_lock(cli
->tree
, &io
);
1303 CHECK_STATUS(status
, (t
?NT_STATUS_FILE_LOCK_CONFLICT
:NT_STATUS_LOCK_NOT_GRANTED
));
1304 status
= smb_raw_lock(cli
->tree
, &io
);
1305 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1307 /* end of the loop */
1309 smb_raw_exit(cli
->session
);
1311 torture_comment(tctx
, "Testing with timeout > 0 (=%d)\n",
1313 fname
= BASEDIR
"\\test1.txt";
1318 torture_comment(tctx
, "Testing special cases with timeout > 0 (=%d)\n",
1322 * the following 3 test sections demonstrate that
1323 * the cache is only set when the error is reported
1324 * to the client (after the timeout went by)
1326 smb_raw_exit(cli
->session
);
1327 torture_comment(tctx
, "Testing a conflict while a lock is pending\n");
1328 fname
= BASEDIR
"\\test2.txt";
1329 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1330 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1331 "Failed to reopen %s - %s\n",
1332 fname
, smbcli_errstr(cli
->tree
)));
1334 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1335 io
.lockx
.in
.file
.fnum
= fnum
;
1336 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1337 io
.lockx
.in
.timeout
= 0;
1338 io
.lockx
.in
.ulock_cnt
= 0;
1339 io
.lockx
.in
.lock_cnt
= 1;
1340 lock
[0].pid
= cli
->session
->pid
;
1341 lock
[0].offset
= 100;
1343 io
.lockx
.in
.locks
= &lock
[0];
1344 status
= smb_raw_lock(cli
->tree
, &io
);
1345 CHECK_STATUS(status
, NT_STATUS_OK
);
1347 start
= time_mono(NULL
);
1348 io
.lockx
.in
.timeout
= t
;
1349 req
= smb_raw_lock_send(cli
->tree
, &io
);
1350 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1351 "Failed to setup timed lock (%s)\n", __location__
));
1353 io
.lockx
.in
.timeout
= 0;
1354 lock
[0].offset
= 105;
1356 status
= smb_raw_lock(cli
->tree
, &io
);
1357 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1359 status
= smbcli_request_simple_recv(req
);
1360 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1363 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1367 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1368 "lock comes back to early timeout[%d] delay[%d]"
1369 "(%s)\n", t
, delay
, __location__
));
1371 status
= smb_raw_lock(cli
->tree
, &io
);
1372 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1374 smbcli_close(cli
->tree
, fnum
);
1375 fname
= BASEDIR
"\\test3.txt";
1376 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1377 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1378 "Failed to reopen %s - %s\n",
1379 fname
, smbcli_errstr(cli
->tree
)));
1381 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1382 io
.lockx
.in
.file
.fnum
= fnum
;
1383 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1384 io
.lockx
.in
.timeout
= 0;
1385 io
.lockx
.in
.ulock_cnt
= 0;
1386 io
.lockx
.in
.lock_cnt
= 1;
1387 lock
[0].pid
= cli
->session
->pid
;
1388 lock
[0].offset
= 100;
1390 io
.lockx
.in
.locks
= &lock
[0];
1391 status
= smb_raw_lock(cli
->tree
, &io
);
1392 CHECK_STATUS(status
, NT_STATUS_OK
);
1394 start
= time_mono(NULL
);
1395 io
.lockx
.in
.timeout
= t
;
1396 req
= smb_raw_lock_send(cli
->tree
, &io
);
1397 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1398 "Failed to setup timed lock (%s)\n", __location__
));
1400 io
.lockx
.in
.timeout
= 0;
1401 lock
[0].offset
= 105;
1403 status
= smb_raw_lock(cli
->tree
, &io
);
1404 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1406 status
= smbcli_request_simple_recv(req
);
1407 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1410 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1414 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1415 "lock comes back to early timeout[%d] delay[%d]"
1416 "(%s)\n", t
, delay
, __location__
));
1418 lock
[0].offset
= 100;
1420 status
= smb_raw_lock(cli
->tree
, &io
);
1421 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1423 smbcli_close(cli
->tree
, fnum
);
1424 fname
= BASEDIR
"\\test4.txt";
1425 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1426 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1427 "Failed to reopen %s - %s\n",
1428 fname
, smbcli_errstr(cli
->tree
)));
1430 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1431 io
.lockx
.in
.file
.fnum
= fnum
;
1432 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
1433 io
.lockx
.in
.timeout
= 0;
1434 io
.lockx
.in
.ulock_cnt
= 0;
1435 io
.lockx
.in
.lock_cnt
= 1;
1436 lock
[0].pid
= cli
->session
->pid
;
1437 lock
[0].offset
= 100;
1439 io
.lockx
.in
.locks
= &lock
[0];
1440 status
= smb_raw_lock(cli
->tree
, &io
);
1441 CHECK_STATUS(status
, NT_STATUS_OK
);
1443 start
= time_mono(NULL
);
1444 io
.lockx
.in
.timeout
= t
;
1445 req
= smb_raw_lock_send(cli
->tree
, &io
);
1446 torture_assert(tctx
,(req
!= NULL
), talloc_asprintf(tctx
,
1447 "Failed to setup timed lock (%s)\n", __location__
));
1449 io
.lockx
.in
.timeout
= 0;
1450 status
= smb_raw_lock(cli
->tree
, &io
);
1451 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1453 status
= smbcli_request_simple_recv(req
);
1454 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1457 if (TARGET_IS_W2K8(tctx
) || TARGET_IS_WIN7(tctx
)) {
1461 torture_assert(tctx
,!(time_mono(NULL
) < start
+delay
), talloc_asprintf(tctx
,
1462 "lock comes back to early timeout[%d] delay[%d]"
1463 "(%s)\n", t
, delay
, __location__
));
1465 status
= smb_raw_lock(cli
->tree
, &io
);
1466 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1469 smb_raw_exit(cli
->session
);
1470 smbcli_deltree(cli
->tree
, BASEDIR
);
1476 test LOCKING_ANDX_CHANGE_LOCKTYPE
1478 static bool test_changetype(struct torture_context
*tctx
,
1479 struct smbcli_state
*cli
)
1482 struct smb_lock_entry lock
[2];
1487 const char *fname
= BASEDIR
"\\test.txt";
1489 if (!torture_setup_dir(cli
, BASEDIR
)) {
1493 torture_comment(tctx
, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1494 io
.generic
.level
= RAW_LOCK_LOCKX
;
1496 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1497 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1498 "Failed to create %s - %s\n",
1499 fname
, smbcli_errstr(cli
->tree
)));
1501 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1502 io
.lockx
.in
.file
.fnum
= fnum
;
1503 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1504 io
.lockx
.in
.timeout
= 0;
1505 io
.lockx
.in
.ulock_cnt
= 0;
1506 io
.lockx
.in
.lock_cnt
= 1;
1507 lock
[0].pid
= cli
->session
->pid
;
1508 lock
[0].offset
= 100;
1510 io
.lockx
.in
.locks
= &lock
[0];
1511 status
= smb_raw_lock(cli
->tree
, &io
);
1512 CHECK_STATUS(status
, NT_STATUS_OK
);
1514 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1515 torture_result(tctx
, TORTURE_FAIL
,
1516 "allowed write on read locked region (%s)\n", __location__
);
1521 /* windows server don't seem to support this */
1522 io
.lockx
.in
.mode
= LOCKING_ANDX_CHANGE_LOCKTYPE
;
1523 status
= smb_raw_lock(cli
->tree
, &io
);
1524 CHECK_STATUS(status
, NT_STATUS_DOS(ERRDOS
, ERRnoatomiclocks
));
1526 if (smbcli_write(cli
->tree
, fnum
, 0, &c
, 100, 1) == 1) {
1527 torture_result(tctx
, TORTURE_FAIL
,
1528 "allowed write after lock change (%s)\n", __location__
);
1534 smbcli_close(cli
->tree
, fnum
);
1535 smb_raw_exit(cli
->session
);
1536 smbcli_deltree(cli
->tree
, BASEDIR
);
1540 struct double_lock_test
{
1541 struct smb_lock_entry lock1
;
1542 struct smb_lock_entry lock2
;
1543 NTSTATUS exp_status
;
1547 * Tests zero byte locks.
1549 static struct double_lock_test zero_byte_tests
[] = {
1550 /* {pid, offset, count}, {pid, offset, count}, status */
1552 /** First, takes a zero byte lock at offset 10. Then:
1553 * - Taking 0 byte lock at 10 should succeed.
1554 * - Taking 1 byte locks at 9,10,11 should succeed.
1555 * - Taking 2 byte lock at 9 should fail.
1556 * - Taking 2 byte lock at 10 should succeed.
1557 * - Taking 3 byte lock at 9 should fail.
1559 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK
},
1560 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK
},
1561 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK
},
1562 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK
},
1563 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED
},
1564 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK
},
1565 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED
},
1567 /** Same, but opposite order. */
1568 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK
},
1569 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1570 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1571 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK
},
1572 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1573 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK
},
1574 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED
},
1576 /** Zero zero case. */
1577 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK
},
1580 static bool test_zerobytelocks(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1586 const char *fname
= BASEDIR
"\\zero.txt";
1588 torture_comment(tctx
, "Testing zero length byte range locks:\n");
1590 if (!torture_setup_dir(cli
, BASEDIR
)) {
1594 io
.generic
.level
= RAW_LOCK_LOCKX
;
1596 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1597 torture_assert(tctx
,(fnum
!= -1), talloc_asprintf(tctx
,
1598 "Failed to create %s - %s\n",
1599 fname
, smbcli_errstr(cli
->tree
)));
1601 /* Setup initial parameters */
1602 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1603 io
.lockx
.in
.file
.fnum
= fnum
;
1604 io
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
; /* Exclusive */
1605 io
.lockx
.in
.timeout
= 0;
1607 /* Try every combination of locks in zero_byte_tests. The first lock is
1608 * assumed to succeed. The second lock may contend, depending on the
1609 * expected status. */
1611 i
< ARRAY_SIZE(zero_byte_tests
);
1613 torture_comment(tctx
, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1614 zero_byte_tests
[i
].lock1
.pid
,
1615 (unsigned long long) zero_byte_tests
[i
].lock1
.offset
,
1616 (unsigned long long) zero_byte_tests
[i
].lock1
.count
,
1617 zero_byte_tests
[i
].lock2
.pid
,
1618 (unsigned long long) zero_byte_tests
[i
].lock2
.offset
,
1619 (unsigned long long) zero_byte_tests
[i
].lock2
.count
,
1620 nt_errstr(zero_byte_tests
[i
].exp_status
));
1622 /* Lock both locks. */
1623 io
.lockx
.in
.ulock_cnt
= 0;
1624 io
.lockx
.in
.lock_cnt
= 1;
1626 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1627 &zero_byte_tests
[i
].lock1
);
1628 status
= smb_raw_lock(cli
->tree
, &io
);
1629 CHECK_STATUS(status
, NT_STATUS_OK
);
1631 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1632 &zero_byte_tests
[i
].lock2
);
1633 status
= smb_raw_lock(cli
->tree
, &io
);
1635 if (NT_STATUS_EQUAL(zero_byte_tests
[i
].exp_status
,
1636 NT_STATUS_LOCK_NOT_GRANTED
)) {
1637 /* Allow either of the failure messages and keep going
1638 * if we see the wrong status. */
1639 CHECK_STATUS_OR_CONT(status
,
1640 NT_STATUS_LOCK_NOT_GRANTED
,
1641 NT_STATUS_FILE_LOCK_CONFLICT
);
1644 CHECK_STATUS_CONT(status
,
1645 zero_byte_tests
[i
].exp_status
);
1648 /* Unlock both locks. */
1649 io
.lockx
.in
.ulock_cnt
= 1;
1650 io
.lockx
.in
.lock_cnt
= 0;
1652 if (NT_STATUS_EQUAL(status
, NT_STATUS_OK
)) {
1653 status
= smb_raw_lock(cli
->tree
, &io
);
1654 CHECK_STATUS(status
, NT_STATUS_OK
);
1657 io
.lockx
.in
.locks
= discard_const_p(struct smb_lock_entry
,
1658 &zero_byte_tests
[i
].lock1
);
1659 status
= smb_raw_lock(cli
->tree
, &io
);
1660 CHECK_STATUS(status
, NT_STATUS_OK
);
1664 smbcli_close(cli
->tree
, fnum
);
1665 smb_raw_exit(cli
->session
);
1666 smbcli_deltree(cli
->tree
, BASEDIR
);
1670 static bool test_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1676 const char *fname
= BASEDIR
"\\unlock.txt";
1677 struct smb_lock_entry lock1
;
1678 struct smb_lock_entry lock2
;
1680 torture_comment(tctx
, "Testing LOCKX unlock:\n");
1682 if (!torture_setup_dir(cli
, BASEDIR
)) {
1686 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1687 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1688 "Failed to create %s - %s\n",
1689 fname
, smbcli_errstr(cli
->tree
)));
1691 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1692 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
1693 "Failed to create %s - %s\n",
1694 fname
, smbcli_errstr(cli
->tree
)));
1696 /* Setup initial parameters */
1697 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1698 io
.lockx
.in
.timeout
= 0;
1700 lock1
.pid
= cli
->session
->pid
;
1703 lock2
.pid
= cli
->session
->pid
- 1;
1708 * Take exclusive lock, then unlock it with a shared-unlock call.
1710 torture_comment(tctx
, " taking exclusive lock.\n");
1711 io
.lockx
.in
.ulock_cnt
= 0;
1712 io
.lockx
.in
.lock_cnt
= 1;
1713 io
.lockx
.in
.mode
= 0;
1714 io
.lockx
.in
.file
.fnum
= fnum1
;
1715 io
.lockx
.in
.locks
= &lock1
;
1716 status
= smb_raw_lock(cli
->tree
, &io
);
1717 CHECK_STATUS(status
, NT_STATUS_OK
);
1719 torture_comment(tctx
, " unlock the exclusive with a shared unlock call.\n");
1720 io
.lockx
.in
.ulock_cnt
= 1;
1721 io
.lockx
.in
.lock_cnt
= 0;
1722 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1723 io
.lockx
.in
.file
.fnum
= fnum1
;
1724 io
.lockx
.in
.locks
= &lock1
;
1725 status
= smb_raw_lock(cli
->tree
, &io
);
1726 CHECK_STATUS(status
, NT_STATUS_OK
);
1728 torture_comment(tctx
, " try shared lock on pid2/fnum2, testing the unlock.\n");
1729 io
.lockx
.in
.ulock_cnt
= 0;
1730 io
.lockx
.in
.lock_cnt
= 1;
1731 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1732 io
.lockx
.in
.file
.fnum
= fnum2
;
1733 io
.lockx
.in
.locks
= &lock2
;
1734 status
= smb_raw_lock(cli
->tree
, &io
);
1735 CHECK_STATUS(status
, NT_STATUS_OK
);
1738 * Unlock a shared lock with an exclusive-unlock call.
1740 torture_comment(tctx
, " unlock new shared lock with exclusive unlock call.\n");
1741 io
.lockx
.in
.ulock_cnt
= 1;
1742 io
.lockx
.in
.lock_cnt
= 0;
1743 io
.lockx
.in
.mode
= 0;
1744 io
.lockx
.in
.file
.fnum
= fnum2
;
1745 io
.lockx
.in
.locks
= &lock2
;
1746 status
= smb_raw_lock(cli
->tree
, &io
);
1747 CHECK_STATUS(status
, NT_STATUS_OK
);
1749 torture_comment(tctx
, " try exclusive lock on pid1, testing the unlock.\n");
1750 io
.lockx
.in
.ulock_cnt
= 0;
1751 io
.lockx
.in
.lock_cnt
= 1;
1752 io
.lockx
.in
.mode
= 0;
1753 io
.lockx
.in
.file
.fnum
= fnum1
;
1754 io
.lockx
.in
.locks
= &lock1
;
1755 status
= smb_raw_lock(cli
->tree
, &io
);
1756 CHECK_STATUS(status
, NT_STATUS_OK
);
1759 io
.lockx
.in
.ulock_cnt
= 1;
1760 io
.lockx
.in
.lock_cnt
= 0;
1761 status
= smb_raw_lock(cli
->tree
, &io
);
1762 CHECK_STATUS(status
, NT_STATUS_OK
);
1765 * Test unlocking of 0-byte locks.
1768 torture_comment(tctx
, " lock shared and exclusive 0-byte locks, testing that Windows "
1769 "always unlocks the exclusive first.\n");
1770 lock1
.pid
= cli
->session
->pid
;
1773 lock2
.pid
= cli
->session
->pid
;
1776 io
.lockx
.in
.ulock_cnt
= 0;
1777 io
.lockx
.in
.lock_cnt
= 1;
1778 io
.lockx
.in
.file
.fnum
= fnum1
;
1779 io
.lockx
.in
.locks
= &lock1
;
1781 /* lock 0-byte shared
1782 * Note: Order of the shared/exclusive locks doesn't matter. */
1783 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1784 status
= smb_raw_lock(cli
->tree
, &io
);
1785 CHECK_STATUS(status
, NT_STATUS_OK
);
1787 /* lock 0-byte exclusive */
1788 io
.lockx
.in
.mode
= 0;
1789 status
= smb_raw_lock(cli
->tree
, &io
);
1790 CHECK_STATUS(status
, NT_STATUS_OK
);
1792 /* test contention */
1793 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1794 io
.lockx
.in
.locks
= &lock2
;
1795 io
.lockx
.in
.file
.fnum
= fnum2
;
1796 status
= smb_raw_lock(cli
->tree
, &io
);
1797 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1798 NT_STATUS_FILE_LOCK_CONFLICT
);
1801 io
.lockx
.in
.ulock_cnt
= 1;
1802 io
.lockx
.in
.lock_cnt
= 0;
1803 io
.lockx
.in
.file
.fnum
= fnum1
;
1804 io
.lockx
.in
.locks
= &lock1
;
1805 status
= smb_raw_lock(cli
->tree
, &io
);
1806 CHECK_STATUS(status
, NT_STATUS_OK
);
1808 /* test - can we take a shared lock? */
1809 io
.lockx
.in
.ulock_cnt
= 0;
1810 io
.lockx
.in
.lock_cnt
= 1;
1811 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
1812 io
.lockx
.in
.file
.fnum
= fnum2
;
1813 io
.lockx
.in
.locks
= &lock2
;
1814 status
= smb_raw_lock(cli
->tree
, &io
);
1816 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1817 * new to Win7, it succeeds in WinXP too), until I can come to a
1818 * resolution as to whether Samba should support this or not. There is
1819 * code to preference unlocking exclusive locks before shared locks,
1820 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1821 if (TARGET_IS_SAMBA3(tctx
)) {
1822 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
1823 NT_STATUS_FILE_LOCK_CONFLICT
);
1825 CHECK_STATUS(status
, NT_STATUS_OK
);
1829 io
.lockx
.in
.ulock_cnt
= 1;
1830 io
.lockx
.in
.lock_cnt
= 0;
1831 status
= smb_raw_lock(cli
->tree
, &io
);
1833 /* XXX Same as above. */
1834 if (TARGET_IS_SAMBA3(tctx
)) {
1835 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1837 CHECK_STATUS(status
, NT_STATUS_OK
);
1840 io
.lockx
.in
.file
.fnum
= fnum1
;
1841 io
.lockx
.in
.locks
= &lock1
;
1842 status
= smb_raw_lock(cli
->tree
, &io
);
1843 CHECK_STATUS(status
, NT_STATUS_OK
);
1846 smbcli_close(cli
->tree
, fnum1
);
1847 smbcli_close(cli
->tree
, fnum2
);
1848 smb_raw_exit(cli
->session
);
1849 smbcli_deltree(cli
->tree
, BASEDIR
);
1853 static bool test_multiple_unlock(struct torture_context
*tctx
, struct smbcli_state
*cli
)
1859 const char *fname
= BASEDIR
"\\unlock_multiple.txt";
1860 struct smb_lock_entry lock1
;
1861 struct smb_lock_entry lock2
;
1862 struct smb_lock_entry locks
[2];
1864 torture_comment(tctx
, "Testing LOCKX multiple unlock:\n");
1866 if (!torture_setup_dir(cli
, BASEDIR
)) {
1870 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
1871 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
1872 "Failed to create %s - %s\n",
1873 fname
, smbcli_errstr(cli
->tree
)));
1875 /* Setup initial parameters */
1876 io
.lockx
.level
= RAW_LOCK_LOCKX
;
1877 io
.lockx
.in
.timeout
= 0;
1879 lock1
.pid
= cli
->session
->pid
;
1882 lock2
.pid
= cli
->session
->pid
;
1889 io
.lockx
.in
.file
.fnum
= fnum1
;
1890 io
.lockx
.in
.mode
= 0; /* exclusive */
1892 /** Test1: Take second lock, but not first. */
1893 torture_comment(tctx
, " unlock 2 locks, first one not locked. Expect no locks "
1896 io
.lockx
.in
.ulock_cnt
= 0;
1897 io
.lockx
.in
.lock_cnt
= 1;
1898 io
.lockx
.in
.locks
= &lock2
;
1899 status
= smb_raw_lock(cli
->tree
, &io
);
1900 CHECK_STATUS(status
, NT_STATUS_OK
);
1902 /* Try to unlock both locks. */
1903 io
.lockx
.in
.ulock_cnt
= 2;
1904 io
.lockx
.in
.lock_cnt
= 0;
1905 io
.lockx
.in
.locks
= locks
;
1907 status
= smb_raw_lock(cli
->tree
, &io
);
1908 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1910 /* Second lock should not be unlocked. */
1911 io
.lockx
.in
.ulock_cnt
= 0;
1912 io
.lockx
.in
.lock_cnt
= 1;
1913 io
.lockx
.in
.locks
= &lock2
;
1914 status
= smb_raw_lock(cli
->tree
, &io
);
1915 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
1918 io
.lockx
.in
.ulock_cnt
= 1;
1919 io
.lockx
.in
.lock_cnt
= 0;
1920 io
.lockx
.in
.locks
= &lock2
;
1921 status
= smb_raw_lock(cli
->tree
, &io
);
1922 CHECK_STATUS(status
, NT_STATUS_OK
);
1924 /** Test2: Take first lock, but not second. */
1925 torture_comment(tctx
, " unlock 2 locks, second one not locked. Expect first lock "
1928 io
.lockx
.in
.ulock_cnt
= 0;
1929 io
.lockx
.in
.lock_cnt
= 1;
1930 io
.lockx
.in
.locks
= &lock1
;
1931 status
= smb_raw_lock(cli
->tree
, &io
);
1932 CHECK_STATUS(status
, NT_STATUS_OK
);
1934 /* Try to unlock both locks. */
1935 io
.lockx
.in
.ulock_cnt
= 2;
1936 io
.lockx
.in
.lock_cnt
= 0;
1937 io
.lockx
.in
.locks
= locks
;
1939 status
= smb_raw_lock(cli
->tree
, &io
);
1940 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
1942 /* First lock should be unlocked. */
1943 io
.lockx
.in
.ulock_cnt
= 0;
1944 io
.lockx
.in
.lock_cnt
= 1;
1945 io
.lockx
.in
.locks
= &lock1
;
1946 status
= smb_raw_lock(cli
->tree
, &io
);
1947 CHECK_STATUS(status
, NT_STATUS_OK
);
1950 io
.lockx
.in
.ulock_cnt
= 1;
1951 io
.lockx
.in
.lock_cnt
= 0;
1952 io
.lockx
.in
.locks
= &lock1
;
1953 status
= smb_raw_lock(cli
->tree
, &io
);
1954 CHECK_STATUS(status
, NT_STATUS_OK
);
1956 /* Test3: Request 2 locks, second will contend. What happens to the
1958 torture_comment(tctx
, " request 2 locks, second one will contend. "
1959 "Expect both to fail.\n");
1961 /* Lock the second range */
1962 io
.lockx
.in
.ulock_cnt
= 0;
1963 io
.lockx
.in
.lock_cnt
= 1;
1964 io
.lockx
.in
.locks
= &lock2
;
1965 status
= smb_raw_lock(cli
->tree
, &io
);
1966 CHECK_STATUS(status
, NT_STATUS_OK
);
1968 /* Request both locks */
1969 io
.lockx
.in
.ulock_cnt
= 0;
1970 io
.lockx
.in
.lock_cnt
= 2;
1971 io
.lockx
.in
.locks
= locks
;
1973 status
= smb_raw_lock(cli
->tree
, &io
);
1974 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
1976 /* First lock should be unlocked. */
1977 io
.lockx
.in
.ulock_cnt
= 0;
1978 io
.lockx
.in
.lock_cnt
= 1;
1979 io
.lockx
.in
.locks
= &lock1
;
1980 status
= smb_raw_lock(cli
->tree
, &io
);
1981 CHECK_STATUS(status
, NT_STATUS_OK
);
1984 io
.lockx
.in
.ulock_cnt
= 2;
1985 io
.lockx
.in
.lock_cnt
= 0;
1986 io
.lockx
.in
.locks
= locks
;
1987 status
= smb_raw_lock(cli
->tree
, &io
);
1988 CHECK_STATUS(status
, NT_STATUS_OK
);
1990 /* Test4: Request unlock and lock. The lock contends, is the unlock
1991 * then re-locked? */
1992 torture_comment(tctx
, " request unlock and lock, second one will "
1993 "contend. Expect the unlock to succeed.\n");
1995 /* Lock both ranges */
1996 io
.lockx
.in
.ulock_cnt
= 0;
1997 io
.lockx
.in
.lock_cnt
= 2;
1998 io
.lockx
.in
.locks
= locks
;
1999 status
= smb_raw_lock(cli
->tree
, &io
);
2000 CHECK_STATUS(status
, NT_STATUS_OK
);
2002 /* Attempt to unlock the first range and lock the second */
2003 io
.lockx
.in
.ulock_cnt
= 1;
2004 io
.lockx
.in
.lock_cnt
= 1;
2005 io
.lockx
.in
.locks
= locks
;
2006 status
= smb_raw_lock(cli
->tree
, &io
);
2007 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
2009 /* The first lock should've been unlocked */
2010 io
.lockx
.in
.ulock_cnt
= 0;
2011 io
.lockx
.in
.lock_cnt
= 1;
2012 io
.lockx
.in
.locks
= &lock1
;
2013 status
= smb_raw_lock(cli
->tree
, &io
);
2014 CHECK_STATUS(status
, NT_STATUS_OK
);
2017 io
.lockx
.in
.ulock_cnt
= 2;
2018 io
.lockx
.in
.lock_cnt
= 0;
2019 io
.lockx
.in
.locks
= locks
;
2020 status
= smb_raw_lock(cli
->tree
, &io
);
2021 CHECK_STATUS(status
, NT_STATUS_OK
);
2024 smbcli_close(cli
->tree
, fnum1
);
2025 smb_raw_exit(cli
->session
);
2026 smbcli_deltree(cli
->tree
, BASEDIR
);
2031 * torture_locktest5 covers stacking pretty well, but its missing two tests:
2032 * - stacking an exclusive on top of shared fails
2033 * - stacking two exclusives fail
2035 static bool test_stacking(struct torture_context
*tctx
, struct smbcli_state
*cli
)
2041 const char *fname
= BASEDIR
"\\stacking.txt";
2042 struct smb_lock_entry lock1
;
2043 struct smb_lock_entry lock2
;
2045 torture_comment(tctx
, "Testing stacking:\n");
2047 if (!torture_setup_dir(cli
, BASEDIR
)) {
2051 io
.generic
.level
= RAW_LOCK_LOCKX
;
2053 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2054 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2055 "Failed to create %s - %s\n",
2056 fname
, smbcli_errstr(cli
->tree
)));
2058 /* Setup initial parameters */
2059 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2060 io
.lockx
.in
.timeout
= 0;
2062 lock1
.pid
= cli
->session
->pid
;
2065 lock2
.pid
= cli
->session
->pid
- 1;
2070 * Try to take a shared lock, then stack an exclusive.
2072 torture_comment(tctx
, " stacking an exclusive on top of a shared lock fails.\n");
2073 io
.lockx
.in
.file
.fnum
= fnum1
;
2074 io
.lockx
.in
.locks
= &lock1
;
2076 io
.lockx
.in
.ulock_cnt
= 0;
2077 io
.lockx
.in
.lock_cnt
= 1;
2078 io
.lockx
.in
.mode
= LOCKING_ANDX_SHARED_LOCK
;
2079 status
= smb_raw_lock(cli
->tree
, &io
);
2080 CHECK_STATUS(status
, NT_STATUS_OK
);
2082 io
.lockx
.in
.ulock_cnt
= 0;
2083 io
.lockx
.in
.lock_cnt
= 1;
2084 io
.lockx
.in
.mode
= 0;
2085 status
= smb_raw_lock(cli
->tree
, &io
);
2086 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2087 NT_STATUS_FILE_LOCK_CONFLICT
);
2090 io
.lockx
.in
.ulock_cnt
= 1;
2091 io
.lockx
.in
.lock_cnt
= 0;
2092 status
= smb_raw_lock(cli
->tree
, &io
);
2093 CHECK_STATUS(status
, NT_STATUS_OK
);
2096 * Prove that two exclusive locks do not stack.
2098 torture_comment(tctx
, " two exclusive locks do not stack.\n");
2099 io
.lockx
.in
.ulock_cnt
= 0;
2100 io
.lockx
.in
.lock_cnt
= 1;
2101 io
.lockx
.in
.mode
= 0;
2102 status
= smb_raw_lock(cli
->tree
, &io
);
2103 CHECK_STATUS(status
, NT_STATUS_OK
);
2104 status
= smb_raw_lock(cli
->tree
, &io
);
2105 CHECK_STATUS_OR(status
, NT_STATUS_LOCK_NOT_GRANTED
,
2106 NT_STATUS_FILE_LOCK_CONFLICT
);
2109 io
.lockx
.in
.ulock_cnt
= 1;
2110 io
.lockx
.in
.lock_cnt
= 0;
2111 status
= smb_raw_lock(cli
->tree
, &io
);
2112 CHECK_STATUS(status
, NT_STATUS_OK
);
2115 smbcli_close(cli
->tree
, fnum1
);
2116 smb_raw_exit(cli
->session
);
2117 smbcli_deltree(cli
->tree
, BASEDIR
);
2122 * Test how 0-byte read requests contend with byte range locks
2124 static bool test_zerobyteread(struct torture_context
*tctx
,
2125 struct smbcli_state
*cli
)
2132 const char *fname
= BASEDIR
"\\zerobyteread.txt";
2133 struct smb_lock_entry lock1
;
2136 if (!torture_setup_dir(cli
, BASEDIR
)) {
2140 io
.generic
.level
= RAW_LOCK_LOCKX
;
2142 fnum1
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2143 torture_assert(tctx
,(fnum1
!= -1), talloc_asprintf(tctx
,
2144 "Failed to create %s - %s\n",
2145 fname
, smbcli_errstr(cli
->tree
)));
2147 fnum2
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
2148 torture_assert(tctx
,(fnum2
!= -1), talloc_asprintf(tctx
,
2149 "Failed to create %s - %s\n",
2150 fname
, smbcli_errstr(cli
->tree
)));
2152 /* Setup initial parameters */
2153 io
.lockx
.level
= RAW_LOCK_LOCKX
;
2154 io
.lockx
.in
.timeout
= 0;
2156 lock1
.pid
= cli
->session
->pid
;
2161 rd
.readx
.level
= RAW_READ_READX
;
2163 torture_comment(tctx
, "Testing zero byte read on lock range:\n");
2165 /* Take an exclusive lock */
2166 torture_comment(tctx
, " taking exclusive lock.\n");
2167 io
.lockx
.in
.ulock_cnt
= 0;
2168 io
.lockx
.in
.lock_cnt
= 1;
2169 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2170 io
.lockx
.in
.file
.fnum
= fnum1
;
2171 io
.lockx
.in
.locks
= &lock1
;
2172 status
= smb_raw_lock(cli
->tree
, &io
);
2173 CHECK_STATUS(status
, NT_STATUS_OK
);
2175 /* Try a zero byte read */
2176 torture_comment(tctx
, " reading 0 bytes.\n");
2177 rd
.readx
.in
.file
.fnum
= fnum2
;
2178 rd
.readx
.in
.offset
= 5;
2179 rd
.readx
.in
.mincnt
= 0;
2180 rd
.readx
.in
.maxcnt
= 0;
2181 rd
.readx
.in
.remaining
= 0;
2182 rd
.readx
.in
.read_for_execute
= false;
2183 rd
.readx
.out
.data
= &c
;
2184 status
= smb_raw_read(cli
->tree
, &rd
);
2185 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2186 "zero byte read did not return 0 bytes");
2187 CHECK_STATUS(status
, NT_STATUS_OK
);
2190 io
.lockx
.in
.ulock_cnt
= 1;
2191 io
.lockx
.in
.lock_cnt
= 0;
2192 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2193 io
.lockx
.in
.file
.fnum
= fnum1
;
2194 io
.lockx
.in
.locks
= &lock1
;
2195 status
= smb_raw_lock(cli
->tree
, &io
);
2196 CHECK_STATUS(status
, NT_STATUS_OK
);
2198 torture_comment(tctx
, "Testing zero byte read on zero byte lock "
2201 /* Take an exclusive lock */
2202 torture_comment(tctx
, " taking exclusive 0-byte lock.\n");
2203 io
.lockx
.in
.ulock_cnt
= 0;
2204 io
.lockx
.in
.lock_cnt
= 1;
2205 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2206 io
.lockx
.in
.file
.fnum
= fnum1
;
2207 io
.lockx
.in
.locks
= &lock1
;
2210 status
= smb_raw_lock(cli
->tree
, &io
);
2211 CHECK_STATUS(status
, NT_STATUS_OK
);
2213 /* Try a zero byte read before the lock */
2214 torture_comment(tctx
, " reading 0 bytes before the lock.\n");
2215 rd
.readx
.in
.file
.fnum
= fnum2
;
2216 rd
.readx
.in
.offset
= 4;
2217 rd
.readx
.in
.mincnt
= 0;
2218 rd
.readx
.in
.maxcnt
= 0;
2219 rd
.readx
.in
.remaining
= 0;
2220 rd
.readx
.in
.read_for_execute
= false;
2221 rd
.readx
.out
.data
= &c
;
2222 status
= smb_raw_read(cli
->tree
, &rd
);
2223 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2224 "zero byte read did not return 0 bytes");
2225 CHECK_STATUS(status
, NT_STATUS_OK
);
2227 /* Try a zero byte read on the lock */
2228 torture_comment(tctx
, " reading 0 bytes on the lock.\n");
2229 rd
.readx
.in
.file
.fnum
= fnum2
;
2230 rd
.readx
.in
.offset
= 5;
2231 rd
.readx
.in
.mincnt
= 0;
2232 rd
.readx
.in
.maxcnt
= 0;
2233 rd
.readx
.in
.remaining
= 0;
2234 rd
.readx
.in
.read_for_execute
= false;
2235 rd
.readx
.out
.data
= &c
;
2236 status
= smb_raw_read(cli
->tree
, &rd
);
2237 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2238 "zero byte read did not return 0 bytes");
2239 CHECK_STATUS(status
, NT_STATUS_OK
);
2241 /* Try a zero byte read after the lock */
2242 torture_comment(tctx
, " reading 0 bytes after the lock.\n");
2243 rd
.readx
.in
.file
.fnum
= fnum2
;
2244 rd
.readx
.in
.offset
= 6;
2245 rd
.readx
.in
.mincnt
= 0;
2246 rd
.readx
.in
.maxcnt
= 0;
2247 rd
.readx
.in
.remaining
= 0;
2248 rd
.readx
.in
.read_for_execute
= false;
2249 rd
.readx
.out
.data
= &c
;
2250 status
= smb_raw_read(cli
->tree
, &rd
);
2251 torture_assert_int_equal_goto(tctx
, rd
.readx
.out
.nread
, 0, ret
, done
,
2252 "zero byte read did not return 0 bytes");
2253 CHECK_STATUS(status
, NT_STATUS_OK
);
2256 io
.lockx
.in
.ulock_cnt
= 1;
2257 io
.lockx
.in
.lock_cnt
= 0;
2258 io
.lockx
.in
.mode
= LOCKING_ANDX_EXCLUSIVE_LOCK
;
2259 io
.lockx
.in
.file
.fnum
= fnum1
;
2260 io
.lockx
.in
.locks
= &lock1
;
2261 status
= smb_raw_lock(cli
->tree
, &io
);
2262 CHECK_STATUS(status
, NT_STATUS_OK
);
2265 smbcli_close(cli
->tree
, fnum1
);
2266 smbcli_close(cli
->tree
, fnum2
);
2267 smb_raw_exit(cli
->session
);
2268 smbcli_deltree(cli
->tree
, BASEDIR
);
2273 basic testing of lock calls
2275 struct torture_suite
*torture_raw_lock(TALLOC_CTX
*mem_ctx
)
2277 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "lock");
2279 torture_suite_add_1smb_test(suite
, "lockx", test_lockx
);
2280 torture_suite_add_1smb_test(suite
, "lock", test_lock
);
2281 torture_suite_add_1smb_test(suite
, "pidhigh", test_pidhigh
);
2282 torture_suite_add_1smb_test(suite
, "async", test_async
);
2283 torture_suite_add_1smb_test(suite
, "errorcode", test_errorcode
);
2284 torture_suite_add_1smb_test(suite
, "changetype", test_changetype
);
2286 torture_suite_add_1smb_test(suite
, "stacking", test_stacking
);
2287 torture_suite_add_1smb_test(suite
, "unlock", test_unlock
);
2288 torture_suite_add_1smb_test(suite
, "multiple_unlock",
2289 test_multiple_unlock
);
2290 torture_suite_add_1smb_test(suite
, "zerobytelocks", test_zerobytelocks
);
2291 torture_suite_add_1smb_test(suite
, "zerobyteread", test_zerobyteread
);