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_SMBLOCK(_tctx) \
84 (torture_setting_bool(_tctx, "smblock_pdu_support", true))
85 #define TARGET_SUPPORTS_OPENX_DENY_DOS(_tctx) \
86 (torture_setting_bool(_tctx, "openx_deny_dos_support", true))
88 test SMBlock and SMBunlock ops
90 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
96 const char *fname = BASEDIR "\\test.txt";
98 if (!TARGET_SUPPORTS_SMBLOCK(tctx))
99 torture_skip(tctx, "Target does not support the SMBlock PDU");
101 if (!torture_setup_dir(cli, BASEDIR)) {
105 torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
106 io.generic.level = RAW_LOCK_LOCK;
108 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
109 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
110 "Failed to create %s - %s\n",
111 fname, smbcli_errstr(cli->tree)));
113 torture_comment(tctx, "Trying 0/0 lock\n");
114 io.lock.level = RAW_LOCK_LOCK;
115 io.lock.in.file.fnum = fnum;
116 io.lock.in.count = 0;
117 io.lock.in.offset = 0;
118 status = smb_raw_lock(cli->tree, &io);
119 CHECK_STATUS(status, NT_STATUS_OK);
121 status = smb_raw_lock(cli->tree, &io);
122 CHECK_STATUS(status, NT_STATUS_OK);
124 io.lock.level = RAW_LOCK_UNLOCK;
125 status = smb_raw_lock(cli->tree, &io);
126 CHECK_STATUS(status, NT_STATUS_OK);
128 torture_comment(tctx, "Trying 0/1 lock\n");
129 io.lock.level = RAW_LOCK_LOCK;
130 io.lock.in.file.fnum = fnum;
131 io.lock.in.count = 1;
132 io.lock.in.offset = 0;
133 status = smb_raw_lock(cli->tree, &io);
134 CHECK_STATUS(status, NT_STATUS_OK);
136 status = smb_raw_lock(cli->tree, &io);
137 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
139 io.lock.level = RAW_LOCK_UNLOCK;
140 status = smb_raw_lock(cli->tree, &io);
141 CHECK_STATUS(status, NT_STATUS_OK);
142 io.lock.level = RAW_LOCK_UNLOCK;
143 status = smb_raw_lock(cli->tree, &io);
144 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
146 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
147 io.lock.level = RAW_LOCK_LOCK;
148 io.lock.in.file.fnum = fnum;
149 io.lock.in.count = 4000;
150 io.lock.in.offset = 0xEEFFFFFF;
151 status = smb_raw_lock(cli->tree, &io);
152 CHECK_STATUS(status, NT_STATUS_OK);
154 status = smb_raw_lock(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
157 io.lock.level = RAW_LOCK_UNLOCK;
158 status = smb_raw_lock(cli->tree, &io);
159 CHECK_STATUS(status, NT_STATUS_OK);
160 io.lock.level = RAW_LOCK_UNLOCK;
161 status = smb_raw_lock(cli->tree, &io);
162 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
164 torture_comment(tctx, "Trying 0xEF000000 lock\n");
165 io.lock.level = RAW_LOCK_LOCK;
166 io.lock.in.file.fnum = fnum;
167 io.lock.in.count = 4000;
168 io.lock.in.offset = 0xEEFFFFFF;
169 status = smb_raw_lock(cli->tree, &io);
170 CHECK_STATUS(status, NT_STATUS_OK);
172 status = smb_raw_lock(cli->tree, &io);
173 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
175 io.lock.level = RAW_LOCK_UNLOCK;
176 status = smb_raw_lock(cli->tree, &io);
177 CHECK_STATUS(status, NT_STATUS_OK);
178 io.lock.level = RAW_LOCK_UNLOCK;
179 status = smb_raw_lock(cli->tree, &io);
180 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
182 torture_comment(tctx, "Trying max lock\n");
183 io.lock.level = RAW_LOCK_LOCK;
184 io.lock.in.file.fnum = fnum;
185 io.lock.in.count = 4000;
186 io.lock.in.offset = 0xEF000000;
187 status = smb_raw_lock(cli->tree, &io);
188 CHECK_STATUS(status, NT_STATUS_OK);
190 status = smb_raw_lock(cli->tree, &io);
191 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
193 io.lock.level = RAW_LOCK_UNLOCK;
194 status = smb_raw_lock(cli->tree, &io);
195 CHECK_STATUS(status, NT_STATUS_OK);
196 io.lock.level = RAW_LOCK_UNLOCK;
197 status = smb_raw_lock(cli->tree, &io);
198 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
200 torture_comment(tctx, "Trying wrong pid unlock\n");
201 io.lock.level = RAW_LOCK_LOCK;
202 io.lock.in.file.fnum = fnum;
203 io.lock.in.count = 4002;
204 io.lock.in.offset = 10001;
205 status = smb_raw_lock(cli->tree, &io);
206 CHECK_STATUS(status, NT_STATUS_OK);
208 io.lock.level = RAW_LOCK_UNLOCK;
209 status = smb_raw_lock(cli->tree, &io);
210 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
212 status = smb_raw_lock(cli->tree, &io);
213 CHECK_STATUS(status, NT_STATUS_OK);
216 smbcli_close(cli->tree, fnum);
217 smb_raw_exit(cli->session);
218 smbcli_deltree(cli->tree, BASEDIR);
226 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
229 struct smb_lock_entry lock[1];
233 const char *fname = BASEDIR "\\test.txt";
235 if (!torture_setup_dir(cli, BASEDIR)) {
239 torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
240 io.generic.level = RAW_LOCK_LOCKX;
242 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
243 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
244 "Failed to create %s - %s\n",
245 fname, smbcli_errstr(cli->tree)));
247 io.lockx.level = RAW_LOCK_LOCKX;
248 io.lockx.in.file.fnum = fnum;
249 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
250 io.lockx.in.timeout = 0;
251 io.lockx.in.ulock_cnt = 0;
252 io.lockx.in.lock_cnt = 1;
253 lock[0].pid = cli->session->pid;
256 io.lockx.in.locks = &lock[0];
257 status = smb_raw_lock(cli->tree, &io);
258 CHECK_STATUS(status, NT_STATUS_OK);
261 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
262 io.lockx.in.ulock_cnt = 0;
263 io.lockx.in.lock_cnt = 1;
264 lock[0].count = 4000;
265 lock[0].offset = 0xEEFFFFFF;
266 status = smb_raw_lock(cli->tree, &io);
267 CHECK_STATUS(status, NT_STATUS_OK);
269 status = smb_raw_lock(cli->tree, &io);
270 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
272 io.lockx.in.ulock_cnt = 1;
273 io.lockx.in.lock_cnt = 0;
274 status = smb_raw_lock(cli->tree, &io);
275 CHECK_STATUS(status, NT_STATUS_OK);
276 status = smb_raw_lock(cli->tree, &io);
277 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
279 torture_comment(tctx, "Trying 0xEF000000 lock\n");
280 io.lockx.in.ulock_cnt = 0;
281 io.lockx.in.lock_cnt = 1;
282 lock[0].count = 4000;
283 lock[0].offset = 0xEF000000;
284 status = smb_raw_lock(cli->tree, &io);
285 CHECK_STATUS(status, NT_STATUS_OK);
287 status = smb_raw_lock(cli->tree, &io);
288 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
290 io.lockx.in.ulock_cnt = 1;
291 io.lockx.in.lock_cnt = 0;
292 status = smb_raw_lock(cli->tree, &io);
293 CHECK_STATUS(status, NT_STATUS_OK);
294 status = smb_raw_lock(cli->tree, &io);
295 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
297 torture_comment(tctx, "Trying zero lock\n");
298 io.lockx.in.ulock_cnt = 0;
299 io.lockx.in.lock_cnt = 1;
302 status = smb_raw_lock(cli->tree, &io);
303 CHECK_STATUS(status, NT_STATUS_OK);
305 status = smb_raw_lock(cli->tree, &io);
306 CHECK_STATUS(status, NT_STATUS_OK);
308 io.lockx.in.ulock_cnt = 1;
309 io.lockx.in.lock_cnt = 0;
310 status = smb_raw_lock(cli->tree, &io);
311 CHECK_STATUS(status, NT_STATUS_OK);
312 status = smb_raw_lock(cli->tree, &io);
313 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
315 torture_comment(tctx, "Trying max lock\n");
316 io.lockx.in.ulock_cnt = 0;
317 io.lockx.in.lock_cnt = 1;
320 status = smb_raw_lock(cli->tree, &io);
321 CHECK_STATUS(status, NT_STATUS_OK);
323 status = smb_raw_lock(cli->tree, &io);
324 CHECK_STATUS(status, NT_STATUS_OK);
326 io.lockx.in.ulock_cnt = 1;
327 io.lockx.in.lock_cnt = 0;
328 status = smb_raw_lock(cli->tree, &io);
329 CHECK_STATUS(status, NT_STATUS_OK);
330 status = smb_raw_lock(cli->tree, &io);
331 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
333 torture_comment(tctx, "Trying 2^63\n");
334 io.lockx.in.ulock_cnt = 0;
335 io.lockx.in.lock_cnt = 1;
338 lock[0].offset <<= 63;
339 status = smb_raw_lock(cli->tree, &io);
340 CHECK_STATUS(status, NT_STATUS_OK);
342 status = smb_raw_lock(cli->tree, &io);
343 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
345 io.lockx.in.ulock_cnt = 1;
346 io.lockx.in.lock_cnt = 0;
347 status = smb_raw_lock(cli->tree, &io);
348 CHECK_STATUS(status, NT_STATUS_OK);
349 status = smb_raw_lock(cli->tree, &io);
350 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
352 torture_comment(tctx, "Trying 2^63 - 1\n");
353 io.lockx.in.ulock_cnt = 0;
354 io.lockx.in.lock_cnt = 1;
357 lock[0].offset <<= 63;
359 status = smb_raw_lock(cli->tree, &io);
360 CHECK_STATUS(status, NT_STATUS_OK);
362 status = smb_raw_lock(cli->tree, &io);
363 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
365 io.lockx.in.ulock_cnt = 1;
366 io.lockx.in.lock_cnt = 0;
367 status = smb_raw_lock(cli->tree, &io);
368 CHECK_STATUS(status, NT_STATUS_OK);
369 status = smb_raw_lock(cli->tree, &io);
370 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
372 torture_comment(tctx, "Trying max lock 2\n");
373 io.lockx.in.ulock_cnt = 0;
374 io.lockx.in.lock_cnt = 1;
377 status = smb_raw_lock(cli->tree, &io);
378 CHECK_STATUS(status, NT_STATUS_OK);
381 status = smb_raw_lock(cli->tree, &io);
382 if (TARGET_SUPPORTS_INVALID_LOCK_RANGE(tctx))
383 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
385 CHECK_STATUS(status, NT_STATUS_OK);
387 io.lockx.in.ulock_cnt = 1;
388 io.lockx.in.lock_cnt = 0;
390 status = smb_raw_lock(cli->tree, &io);
392 CHECK_STATUS(status, NT_STATUS_OK);
393 status = smb_raw_lock(cli->tree, &io);
394 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
397 smbcli_close(cli->tree, fnum);
398 smb_raw_exit(cli->session);
399 smbcli_deltree(cli->tree, BASEDIR);
406 static bool test_pidhigh(struct torture_context *tctx,
407 struct smbcli_state *cli)
410 struct smb_lock_entry lock[1];
414 const char *fname = BASEDIR "\\test.txt";
417 if (!torture_setup_dir(cli, BASEDIR)) {
421 torture_comment(tctx, "Testing high pid\n");
422 io.generic.level = RAW_LOCK_LOCKX;
424 cli->session->pid = 1;
426 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
427 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
428 "Failed to create %s - %s\n",
429 fname, smbcli_errstr(cli->tree)));
431 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
432 torture_result(tctx, TORTURE_FAIL,
433 "Failed to write 1 byte - %s\n",
434 smbcli_errstr(cli->tree));
439 io.lockx.level = RAW_LOCK_LOCKX;
440 io.lockx.in.file.fnum = fnum;
441 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
442 io.lockx.in.timeout = 0;
443 io.lockx.in.ulock_cnt = 0;
444 io.lockx.in.lock_cnt = 1;
445 lock[0].pid = cli->session->pid;
447 lock[0].count = 0xFFFFFFFF;
448 io.lockx.in.locks = &lock[0];
449 status = smb_raw_lock(cli->tree, &io);
450 CHECK_STATUS(status, NT_STATUS_OK);
452 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
453 torture_result(tctx, TORTURE_FAIL,
454 "Failed to read 1 byte - %s\n",
455 smbcli_errstr(cli->tree));
460 cli->session->pid = 2;
462 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
463 torture_result(tctx, TORTURE_FAIL,
464 "pid is incorrect handled for read with lock!\n");
469 cli->session->pid = 0x10001;
471 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
472 torture_result(tctx, TORTURE_FAIL,
473 "High pid is used on this server!\n");
476 torture_warning(tctx, "High pid is not used on this server (correct)\n");
480 smbcli_close(cli->tree, fnum);
481 smb_raw_exit(cli->session);
482 smbcli_deltree(cli->tree, BASEDIR);
488 test locking&X async operation
490 static bool test_async(struct torture_context *tctx,
491 struct smbcli_state *cli)
493 struct smbcli_session *session;
494 struct smb_composite_sesssetup setup;
495 struct smbcli_tree *tree;
497 const char *host, *share;
499 struct smb_lock_entry lock[2];
503 const char *fname = BASEDIR "\\test.txt";
505 struct smbcli_request *req, *req2;
506 struct smbcli_session_options options;
508 if (!torture_setup_dir(cli, BASEDIR)) {
512 lp_smbcli_session_options(tctx->lp_ctx, &options);
514 torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
515 io.generic.level = RAW_LOCK_LOCKX;
517 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
518 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
519 "Failed to create %s - %s\n",
520 fname, smbcli_errstr(cli->tree)));
522 io.lockx.level = RAW_LOCK_LOCKX;
523 io.lockx.in.file.fnum = fnum;
524 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
525 io.lockx.in.timeout = 0;
526 io.lockx.in.ulock_cnt = 0;
527 io.lockx.in.lock_cnt = 1;
528 lock[0].pid = cli->session->pid;
529 lock[0].offset = 100;
531 lock[1].pid = cli->session->pid;
532 lock[1].offset = 110;
534 io.lockx.in.locks = &lock[0];
535 status = smb_raw_lock(cli->tree, &io);
536 CHECK_STATUS(status, NT_STATUS_OK);
540 torture_comment(tctx, "testing cancel by CANCEL_LOCK\n");
542 /* setup a timed lock */
543 io.lockx.in.timeout = 10000;
544 req = smb_raw_lock_send(cli->tree, &io);
545 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
546 "Failed to setup timed lock (%s)\n", __location__));
548 /* cancel the wrong range */
550 io.lockx.in.timeout = 0;
551 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
552 status = smb_raw_lock(cli->tree, &io);
553 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
555 /* cancel with the wrong bits set */
556 lock[0].offset = 100;
557 io.lockx.in.timeout = 0;
558 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
559 status = smb_raw_lock(cli->tree, &io);
560 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
562 /* cancel the right range */
563 lock[0].offset = 100;
564 io.lockx.in.timeout = 0;
565 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
566 status = smb_raw_lock(cli->tree, &io);
567 CHECK_STATUS(status, NT_STATUS_OK);
569 /* receive the failed lock request */
570 status = smbcli_request_simple_recv(req);
571 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
573 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
574 "lock cancel was not immediate (%s)\n", __location__));
576 /* MS-CIFS (2.2.4.32.1) states that a cancel is honored if and only
577 * if the lock vector contains one entry. When given mutliple cancel
578 * requests in a single PDU we expect the server to return an
579 * error. Samba4 handles this correctly. Windows servers seem to
580 * accept the request but only cancel the first lock. Samba3
581 * now does what Windows does (JRA).
583 torture_comment(tctx, "testing multiple cancel\n");
585 /* acquire second lock */
586 io.lockx.in.timeout = 0;
587 io.lockx.in.ulock_cnt = 0;
588 io.lockx.in.lock_cnt = 1;
589 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
590 io.lockx.in.locks = &lock[1];
591 status = smb_raw_lock(cli->tree, &io);
592 CHECK_STATUS(status, NT_STATUS_OK);
594 /* setup 2 timed locks */
596 io.lockx.in.timeout = 10000;
597 io.lockx.in.lock_cnt = 1;
598 io.lockx.in.locks = &lock[0];
599 req = smb_raw_lock_send(cli->tree, &io);
600 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
601 "Failed to setup timed lock (%s)\n", __location__));
602 io.lockx.in.locks = &lock[1];
603 req2 = smb_raw_lock_send(cli->tree, &io);
604 torture_assert(tctx,(req2 != NULL), talloc_asprintf(tctx,
605 "Failed to setup timed lock (%s)\n", __location__));
607 /* try to cancel both locks in the same packet */
608 io.lockx.in.timeout = 0;
609 io.lockx.in.lock_cnt = 2;
610 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
611 io.lockx.in.locks = lock;
612 status = smb_raw_lock(cli->tree, &io);
613 CHECK_STATUS(status, NT_STATUS_OK);
615 torture_warning(tctx, "Target server accepted a lock cancel "
616 "request with multiple locks. This violates "
617 "MS-CIFS 2.2.4.32.1.\n");
619 /* receive the failed lock requests */
620 status = smbcli_request_simple_recv(req);
621 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
623 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
624 "first lock was not cancelled immediately (%s)\n",
627 /* send cancel to second lock */
628 io.lockx.in.timeout = 0;
629 io.lockx.in.lock_cnt = 1;
630 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK |
631 LOCKING_ANDX_LARGE_FILES;
632 io.lockx.in.locks = &lock[1];
633 status = smb_raw_lock(cli->tree, &io);
634 CHECK_STATUS(status, NT_STATUS_OK);
636 status = smbcli_request_simple_recv(req2);
637 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
639 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
640 "second lock was not cancelled immediately (%s)\n",
643 /* cleanup the second lock */
644 io.lockx.in.ulock_cnt = 1;
645 io.lockx.in.lock_cnt = 0;
646 io.lockx.in.locks = &lock[1];
647 status = smb_raw_lock(cli->tree, &io);
648 CHECK_STATUS(status, NT_STATUS_OK);
650 torture_comment(tctx, "testing cancel by unlock\n");
651 io.lockx.in.ulock_cnt = 0;
652 io.lockx.in.lock_cnt = 1;
653 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
654 io.lockx.in.timeout = 0;
655 io.lockx.in.locks = &lock[0];
656 status = smb_raw_lock(cli->tree, &io);
657 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
659 io.lockx.in.timeout = 5000;
660 req = smb_raw_lock_send(cli->tree, &io);
661 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
662 "Failed to setup timed lock (%s)\n", __location__));
664 io.lockx.in.ulock_cnt = 1;
665 io.lockx.in.lock_cnt = 0;
666 status = smb_raw_lock(cli->tree, &io);
667 CHECK_STATUS(status, NT_STATUS_OK);
670 status = smbcli_request_simple_recv(req);
671 CHECK_STATUS(status, NT_STATUS_OK);
673 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
674 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
675 __location__, (int)(time(NULL)-t)));
677 torture_comment(tctx, "testing cancel by close\n");
678 io.lockx.in.ulock_cnt = 0;
679 io.lockx.in.lock_cnt = 1;
680 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
681 io.lockx.in.timeout = 0;
682 status = smb_raw_lock(cli->tree, &io);
683 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
686 io.lockx.in.timeout = 10000;
687 req = smb_raw_lock_send(cli->tree, &io);
688 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
689 "Failed to setup timed lock (%s)\n", __location__));
691 status = smbcli_close(cli->tree, fnum);
692 CHECK_STATUS(status, NT_STATUS_OK);
694 status = smbcli_request_simple_recv(req);
695 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
697 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
698 "lock cancel by close was not immediate (%s)\n", __location__));
700 torture_comment(tctx, "create a new sessions\n");
701 session = smbcli_session_init(cli->transport, tctx, false, options);
702 setup.in.sesskey = cli->transport->negotiate.sesskey;
703 setup.in.capabilities = cli->transport->negotiate.capabilities;
704 setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
705 setup.in.credentials = cmdline_credentials;
706 setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
707 status = smb_composite_sesssetup(session, &setup);
708 CHECK_STATUS(status, NT_STATUS_OK);
709 session->vuid = setup.out.vuid;
711 torture_comment(tctx, "create new tree context\n");
712 share = torture_setting_string(tctx, "share", NULL);
713 host = torture_setting_string(tctx, "host", NULL);
714 tree = smbcli_tree_init(session, tctx, false);
715 tcon.generic.level = RAW_TCON_TCONX;
716 tcon.tconx.in.flags = 0;
717 tcon.tconx.in.password = data_blob(NULL, 0);
718 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
719 tcon.tconx.in.device = "A:";
720 status = smb_raw_tcon(tree, tctx, &tcon);
721 CHECK_STATUS(status, NT_STATUS_OK);
722 tree->tid = tcon.tconx.out.tid;
724 torture_comment(tctx, "testing cancel by exit\n");
725 fname = BASEDIR "\\test_exit.txt";
726 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
727 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
728 "Failed to reopen %s - %s\n",
729 fname, smbcli_errstr(tree)));
731 io.lockx.level = RAW_LOCK_LOCKX;
732 io.lockx.in.file.fnum = fnum;
733 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
734 io.lockx.in.timeout = 0;
735 io.lockx.in.ulock_cnt = 0;
736 io.lockx.in.lock_cnt = 1;
737 lock[0].pid = session->pid;
738 lock[0].offset = 100;
740 io.lockx.in.locks = &lock[0];
741 status = smb_raw_lock(tree, &io);
742 CHECK_STATUS(status, NT_STATUS_OK);
744 io.lockx.in.ulock_cnt = 0;
745 io.lockx.in.lock_cnt = 1;
746 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
747 io.lockx.in.timeout = 0;
748 status = smb_raw_lock(tree, &io);
749 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
751 io.lockx.in.timeout = 10000;
753 req = smb_raw_lock_send(tree, &io);
754 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
755 "Failed to setup timed lock (%s)\n", __location__));
757 status = smb_raw_exit(session);
758 CHECK_STATUS(status, NT_STATUS_OK);
760 status = smbcli_request_simple_recv(req);
761 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
763 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
764 "lock cancel by exit was not immediate (%s)\n", __location__));
766 torture_comment(tctx, "testing cancel by ulogoff\n");
767 fname = BASEDIR "\\test_ulogoff.txt";
768 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
769 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
770 "Failed to reopen %s - %s\n",
771 fname, smbcli_errstr(tree)));
773 io.lockx.level = RAW_LOCK_LOCKX;
774 io.lockx.in.file.fnum = fnum;
775 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
776 io.lockx.in.timeout = 0;
777 io.lockx.in.ulock_cnt = 0;
778 io.lockx.in.lock_cnt = 1;
779 lock[0].pid = session->pid;
780 lock[0].offset = 100;
782 io.lockx.in.locks = &lock[0];
783 status = smb_raw_lock(tree, &io);
784 CHECK_STATUS(status, NT_STATUS_OK);
786 io.lockx.in.ulock_cnt = 0;
787 io.lockx.in.lock_cnt = 1;
788 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
789 io.lockx.in.timeout = 0;
790 status = smb_raw_lock(tree, &io);
791 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
793 io.lockx.in.timeout = 10000;
795 req = smb_raw_lock_send(tree, &io);
796 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
797 "Failed to setup timed lock (%s)\n", __location__));
799 status = smb_raw_ulogoff(session);
800 CHECK_STATUS(status, NT_STATUS_OK);
802 status = smbcli_request_simple_recv(req);
803 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
804 torture_result(tctx, TORTURE_FAIL,
805 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
807 smb_tree_disconnect(tree);
808 smb_raw_exit(session);
811 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
813 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
814 "lock cancel by ulogoff was not immediate (%s)\n", __location__));
816 torture_comment(tctx, "testing cancel by tdis\n");
817 tree->session = cli->session;
819 fname = BASEDIR "\\test_tdis.txt";
820 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
821 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
822 "Failed to reopen %s - %s\n",
823 fname, smbcli_errstr(tree)));
825 io.lockx.level = RAW_LOCK_LOCKX;
826 io.lockx.in.file.fnum = fnum;
827 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
828 io.lockx.in.timeout = 0;
829 io.lockx.in.ulock_cnt = 0;
830 io.lockx.in.lock_cnt = 1;
831 lock[0].pid = cli->session->pid;
832 lock[0].offset = 100;
834 io.lockx.in.locks = &lock[0];
835 status = smb_raw_lock(tree, &io);
836 CHECK_STATUS(status, NT_STATUS_OK);
838 status = smb_raw_lock(tree, &io);
839 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
841 io.lockx.in.timeout = 10000;
843 req = smb_raw_lock_send(tree, &io);
844 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
845 "Failed to setup timed lock (%s)\n", __location__));
847 status = smb_tree_disconnect(tree);
848 CHECK_STATUS(status, NT_STATUS_OK);
850 status = smbcli_request_simple_recv(req);
851 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
853 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
854 "lock cancel by tdis was not immediate (%s)\n", __location__));
857 smb_raw_exit(cli->session);
858 smbcli_deltree(cli->tree, BASEDIR);
863 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
865 static bool test_errorcode(struct torture_context *tctx,
866 struct smbcli_state *cli)
870 struct smb_lock_entry lock[2];
875 struct smbcli_request *req;
879 uint16_t deny_mode = 0;
881 if (!torture_setup_dir(cli, BASEDIR)) {
885 torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
887 torture_comment(tctx, "testing with timeout = 0\n");
888 fname = BASEDIR "\\test0.txt";
892 * the first run is with t = 0,
893 * the second with t > 0 (=1)
897 * use the DENY_DOS mode, that creates two fnum's of one low-level
898 * file handle, this demonstrates that the cache is per fnum, not
901 if (TARGET_SUPPORTS_OPENX_DENY_DOS(tctx))
902 deny_mode = OPENX_MODE_DENY_DOS;
904 deny_mode = OPENX_MODE_DENY_NONE;
906 op.openx.level = RAW_OPEN_OPENX;
907 op.openx.in.fname = fname;
908 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
909 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | deny_mode;
910 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
911 op.openx.in.search_attrs = 0;
912 op.openx.in.file_attrs = 0;
913 op.openx.in.write_time = 0;
914 op.openx.in.size = 0;
915 op.openx.in.timeout = 0;
917 status = smb_raw_open(cli->tree, tctx, &op);
918 CHECK_STATUS(status, NT_STATUS_OK);
919 fnum = op.openx.out.file.fnum;
921 status = smb_raw_open(cli->tree, tctx, &op);
922 CHECK_STATUS(status, NT_STATUS_OK);
923 fnum2 = op.openx.out.file.fnum;
925 io.lockx.level = RAW_LOCK_LOCKX;
926 io.lockx.in.file.fnum = fnum;
927 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
928 io.lockx.in.timeout = t;
929 io.lockx.in.ulock_cnt = 0;
930 io.lockx.in.lock_cnt = 1;
931 lock[0].pid = cli->session->pid;
932 lock[0].offset = 100;
934 io.lockx.in.locks = &lock[0];
935 status = smb_raw_lock(cli->tree, &io);
936 CHECK_STATUS(status, NT_STATUS_OK);
939 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
940 * this also demonstrates that the error code cache is per file handle
941 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
943 io.lockx.in.file.fnum = fnum2;
944 status = smb_raw_lock(cli->tree, &io);
945 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
947 io.lockx.in.file.fnum = fnum;
948 status = smb_raw_lock(cli->tree, &io);
949 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
951 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
952 io.lockx.in.file.fnum = fnum;
953 status = smb_raw_lock(cli->tree, &io);
954 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
956 io.lockx.in.file.fnum = fnum2;
957 status = smb_raw_lock(cli->tree, &io);
958 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
960 io.lockx.in.file.fnum = fnum;
961 status = smb_raw_lock(cli->tree, &io);
962 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
964 io.lockx.in.file.fnum = fnum2;
965 status = smb_raw_lock(cli->tree, &io);
966 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
968 /* demonstrate that the smbpid doesn't matter */
970 io.lockx.in.file.fnum = fnum;
971 status = smb_raw_lock(cli->tree, &io);
972 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
974 io.lockx.in.file.fnum = fnum2;
975 status = smb_raw_lock(cli->tree, &io);
976 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
980 * demonstrate the a successful lock with count = 0 and the same offset,
981 * doesn't reset the error cache
983 lock[0].offset = 100;
985 io.lockx.in.file.fnum = fnum;
986 status = smb_raw_lock(cli->tree, &io);
987 CHECK_STATUS(status, NT_STATUS_OK);
989 io.lockx.in.file.fnum = fnum2;
990 status = smb_raw_lock(cli->tree, &io);
991 CHECK_STATUS(status, NT_STATUS_OK);
993 lock[0].offset = 100;
995 io.lockx.in.file.fnum = fnum;
996 status = smb_raw_lock(cli->tree, &io);
997 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
999 io.lockx.in.file.fnum = fnum2;
1000 status = smb_raw_lock(cli->tree, &io);
1001 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1004 * demonstrate the a successful lock with count = 0 and outside the locked range,
1005 * doesn't reset the error cache
1007 lock[0].offset = 110;
1009 io.lockx.in.file.fnum = fnum;
1010 status = smb_raw_lock(cli->tree, &io);
1011 CHECK_STATUS(status, NT_STATUS_OK);
1013 io.lockx.in.file.fnum = fnum2;
1014 status = smb_raw_lock(cli->tree, &io);
1015 CHECK_STATUS(status, NT_STATUS_OK);
1017 lock[0].offset = 100;
1019 io.lockx.in.file.fnum = fnum;
1020 status = smb_raw_lock(cli->tree, &io);
1021 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1023 io.lockx.in.file.fnum = fnum2;
1024 status = smb_raw_lock(cli->tree, &io);
1025 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1027 lock[0].offset = 99;
1029 io.lockx.in.file.fnum = fnum;
1030 status = smb_raw_lock(cli->tree, &io);
1031 CHECK_STATUS(status, NT_STATUS_OK);
1033 io.lockx.in.file.fnum = fnum2;
1034 status = smb_raw_lock(cli->tree, &io);
1035 CHECK_STATUS(status, NT_STATUS_OK);
1037 lock[0].offset = 100;
1039 io.lockx.in.file.fnum = fnum;
1040 status = smb_raw_lock(cli->tree, &io);
1041 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1043 io.lockx.in.file.fnum = fnum2;
1044 status = smb_raw_lock(cli->tree, &io);
1045 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1047 /* demonstrate that a changing count doesn't reset the error cache */
1048 lock[0].offset = 100;
1050 io.lockx.in.file.fnum = fnum;
1051 status = smb_raw_lock(cli->tree, &io);
1052 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1054 io.lockx.in.file.fnum = fnum2;
1055 status = smb_raw_lock(cli->tree, &io);
1056 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1058 lock[0].offset = 100;
1060 io.lockx.in.file.fnum = fnum;
1061 status = smb_raw_lock(cli->tree, &io);
1062 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1064 io.lockx.in.file.fnum = fnum2;
1065 status = smb_raw_lock(cli->tree, &io);
1066 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1069 * demonstrate the a lock with count = 0 and inside the locked range,
1070 * fails and resets the error cache
1072 lock[0].offset = 101;
1074 io.lockx.in.file.fnum = fnum;
1075 status = smb_raw_lock(cli->tree, &io);
1076 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1077 status = smb_raw_lock(cli->tree, &io);
1078 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1080 io.lockx.in.file.fnum = fnum2;
1081 status = smb_raw_lock(cli->tree, &io);
1082 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1083 status = smb_raw_lock(cli->tree, &io);
1084 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1086 lock[0].offset = 100;
1088 io.lockx.in.file.fnum = fnum;
1089 status = smb_raw_lock(cli->tree, &io);
1090 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
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, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1097 status = smb_raw_lock(cli->tree, &io);
1098 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1100 /* demonstrate the a changing offset, resets the error cache */
1101 lock[0].offset = 105;
1103 io.lockx.in.file.fnum = fnum;
1104 status = smb_raw_lock(cli->tree, &io);
1105 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1106 status = smb_raw_lock(cli->tree, &io);
1107 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1109 io.lockx.in.file.fnum = fnum2;
1110 status = smb_raw_lock(cli->tree, &io);
1111 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1112 status = smb_raw_lock(cli->tree, &io);
1113 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1115 lock[0].offset = 100;
1117 io.lockx.in.file.fnum = fnum;
1118 status = smb_raw_lock(cli->tree, &io);
1119 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1120 status = smb_raw_lock(cli->tree, &io);
1121 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1123 io.lockx.in.file.fnum = fnum2;
1124 status = smb_raw_lock(cli->tree, &io);
1125 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1126 status = smb_raw_lock(cli->tree, &io);
1127 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1129 lock[0].offset = 95;
1131 io.lockx.in.file.fnum = fnum;
1132 status = smb_raw_lock(cli->tree, &io);
1133 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1134 status = smb_raw_lock(cli->tree, &io);
1135 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1137 io.lockx.in.file.fnum = fnum2;
1138 status = smb_raw_lock(cli->tree, &io);
1139 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1140 status = smb_raw_lock(cli->tree, &io);
1141 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1143 lock[0].offset = 100;
1145 io.lockx.in.file.fnum = fnum;
1146 status = smb_raw_lock(cli->tree, &io);
1147 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1148 status = smb_raw_lock(cli->tree, &io);
1149 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1151 io.lockx.in.file.fnum = fnum2;
1152 status = smb_raw_lock(cli->tree, &io);
1153 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1154 status = smb_raw_lock(cli->tree, &io);
1155 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1158 * demonstrate the a successful lock in a different range,
1159 * doesn't reset the cache, the failing lock on the 2nd handle
1162 lock[0].offset = 120;
1164 io.lockx.in.file.fnum = fnum;
1165 status = smb_raw_lock(cli->tree, &io);
1166 CHECK_STATUS(status, NT_STATUS_OK);
1168 io.lockx.in.file.fnum = fnum2;
1169 status = smb_raw_lock(cli->tree, &io);
1170 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1172 lock[0].offset = 100;
1174 io.lockx.in.file.fnum = fnum;
1175 status = smb_raw_lock(cli->tree, &io);
1176 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1177 status = smb_raw_lock(cli->tree, &io);
1178 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1180 io.lockx.in.file.fnum = fnum2;
1181 status = smb_raw_lock(cli->tree, &io);
1182 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1183 status = smb_raw_lock(cli->tree, &io);
1184 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1186 /* end of the loop */
1188 smb_raw_exit(cli->session);
1190 torture_comment(tctx, "testing with timeout > 0 (=%d)\n",
1192 fname = BASEDIR "\\test1.txt";
1197 torture_comment(tctx, "testing special cases with timeout > 0 (=%d)\n",
1201 * the following 3 test sections demonstrate that
1202 * the cache is only set when the error is reported
1203 * to the client (after the timeout went by)
1205 smb_raw_exit(cli->session);
1206 torture_comment(tctx, "testing a conflict while a lock is pending\n");
1207 fname = BASEDIR "\\test2.txt";
1208 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1209 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1210 "Failed to reopen %s - %s\n",
1211 fname, smbcli_errstr(cli->tree)));
1213 io.lockx.level = RAW_LOCK_LOCKX;
1214 io.lockx.in.file.fnum = fnum;
1215 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1216 io.lockx.in.timeout = 0;
1217 io.lockx.in.ulock_cnt = 0;
1218 io.lockx.in.lock_cnt = 1;
1219 lock[0].pid = cli->session->pid;
1220 lock[0].offset = 100;
1222 io.lockx.in.locks = &lock[0];
1223 status = smb_raw_lock(cli->tree, &io);
1224 CHECK_STATUS(status, NT_STATUS_OK);
1227 io.lockx.in.timeout = t;
1228 req = smb_raw_lock_send(cli->tree, &io);
1229 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1230 "Failed to setup timed lock (%s)\n", __location__));
1232 io.lockx.in.timeout = 0;
1233 lock[0].offset = 105;
1235 status = smb_raw_lock(cli->tree, &io);
1236 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1238 status = smbcli_request_simple_recv(req);
1239 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1242 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1246 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1247 "lock comes back to early timeout[%d] delay[%d]"
1248 "(%s)\n", t, delay, __location__));
1250 status = smb_raw_lock(cli->tree, &io);
1251 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1253 smbcli_close(cli->tree, fnum);
1254 fname = BASEDIR "\\test3.txt";
1255 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1256 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1257 "Failed to reopen %s - %s\n",
1258 fname, smbcli_errstr(cli->tree)));
1260 io.lockx.level = RAW_LOCK_LOCKX;
1261 io.lockx.in.file.fnum = fnum;
1262 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1263 io.lockx.in.timeout = 0;
1264 io.lockx.in.ulock_cnt = 0;
1265 io.lockx.in.lock_cnt = 1;
1266 lock[0].pid = cli->session->pid;
1267 lock[0].offset = 100;
1269 io.lockx.in.locks = &lock[0];
1270 status = smb_raw_lock(cli->tree, &io);
1271 CHECK_STATUS(status, NT_STATUS_OK);
1274 io.lockx.in.timeout = t;
1275 req = smb_raw_lock_send(cli->tree, &io);
1276 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1277 "Failed to setup timed lock (%s)\n", __location__));
1279 io.lockx.in.timeout = 0;
1280 lock[0].offset = 105;
1282 status = smb_raw_lock(cli->tree, &io);
1283 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1285 status = smbcli_request_simple_recv(req);
1286 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1289 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1293 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1294 "lock comes back to early timeout[%d] delay[%d]"
1295 "(%s)\n", t, delay, __location__));
1297 lock[0].offset = 100;
1299 status = smb_raw_lock(cli->tree, &io);
1300 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1302 smbcli_close(cli->tree, fnum);
1303 fname = BASEDIR "\\test4.txt";
1304 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1305 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1306 "Failed to reopen %s - %s\n",
1307 fname, smbcli_errstr(cli->tree)));
1309 io.lockx.level = RAW_LOCK_LOCKX;
1310 io.lockx.in.file.fnum = fnum;
1311 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1312 io.lockx.in.timeout = 0;
1313 io.lockx.in.ulock_cnt = 0;
1314 io.lockx.in.lock_cnt = 1;
1315 lock[0].pid = cli->session->pid;
1316 lock[0].offset = 100;
1318 io.lockx.in.locks = &lock[0];
1319 status = smb_raw_lock(cli->tree, &io);
1320 CHECK_STATUS(status, NT_STATUS_OK);
1323 io.lockx.in.timeout = t;
1324 req = smb_raw_lock_send(cli->tree, &io);
1325 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1326 "Failed to setup timed lock (%s)\n", __location__));
1328 io.lockx.in.timeout = 0;
1329 status = smb_raw_lock(cli->tree, &io);
1330 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1332 status = smbcli_request_simple_recv(req);
1333 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1336 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1340 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1341 "lock comes back to early timeout[%d] delay[%d]"
1342 "(%s)\n", t, delay, __location__));
1344 status = smb_raw_lock(cli->tree, &io);
1345 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1348 smb_raw_exit(cli->session);
1349 smbcli_deltree(cli->tree, BASEDIR);
1355 test LOCKING_ANDX_CHANGE_LOCKTYPE
1357 static bool test_changetype(struct torture_context *tctx,
1358 struct smbcli_state *cli)
1361 struct smb_lock_entry lock[2];
1366 const char *fname = BASEDIR "\\test.txt";
1368 if (!torture_setup_dir(cli, BASEDIR)) {
1372 torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1373 io.generic.level = RAW_LOCK_LOCKX;
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 create %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_SHARED_LOCK;
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 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1394 torture_result(tctx, TORTURE_FAIL,
1395 "allowed write on read locked region (%s)\n", __location__);
1400 /* windows server don't seem to support this */
1401 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1402 status = smb_raw_lock(cli->tree, &io);
1403 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1405 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1406 torture_result(tctx, TORTURE_FAIL,
1407 "allowed write after lock change (%s)\n", __location__);
1413 smbcli_close(cli->tree, fnum);
1414 smb_raw_exit(cli->session);
1415 smbcli_deltree(cli->tree, BASEDIR);
1419 struct double_lock_test {
1420 struct smb_lock_entry lock1;
1421 struct smb_lock_entry lock2;
1422 NTSTATUS exp_status;
1426 * Tests zero byte locks.
1428 static struct double_lock_test zero_byte_tests[] = {
1429 /* {pid, offset, count}, {pid, offset, count}, status */
1431 /** First, takes a zero byte lock at offset 10. Then:
1432 * - Taking 0 byte lock at 10 should succeed.
1433 * - Taking 1 byte locks at 9,10,11 should succeed.
1434 * - Taking 2 byte lock at 9 should fail.
1435 * - Taking 2 byte lock at 10 should succeed.
1436 * - Taking 3 byte lock at 9 should fail.
1438 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1439 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
1440 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1441 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1442 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
1443 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1444 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
1446 /** Same, but opposite order. */
1447 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1448 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
1449 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1450 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1451 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1452 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1453 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1455 /** Zero zero case. */
1456 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
1459 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
1465 const char *fname = BASEDIR "\\zero.txt";
1467 torture_comment(tctx, "Testing zero length byte range locks:\n");
1469 if (!torture_setup_dir(cli, BASEDIR)) {
1473 io.generic.level = RAW_LOCK_LOCKX;
1475 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1476 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1477 "Failed to create %s - %s\n",
1478 fname, smbcli_errstr(cli->tree)));
1480 /* Setup initial parameters */
1481 io.lockx.level = RAW_LOCK_LOCKX;
1482 io.lockx.in.file.fnum = fnum;
1483 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1484 io.lockx.in.timeout = 0;
1486 /* Try every combination of locks in zero_byte_tests. The first lock is
1487 * assumed to succeed. The second lock may contend, depending on the
1488 * expected status. */
1490 i < ARRAY_SIZE(zero_byte_tests);
1492 torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1493 zero_byte_tests[i].lock1.pid,
1494 zero_byte_tests[i].lock1.offset,
1495 zero_byte_tests[i].lock1.count,
1496 zero_byte_tests[i].lock2.pid,
1497 zero_byte_tests[i].lock2.offset,
1498 zero_byte_tests[i].lock2.count,
1499 nt_errstr(zero_byte_tests[i].exp_status));
1501 /* Lock both locks. */
1502 io.lockx.in.ulock_cnt = 0;
1503 io.lockx.in.lock_cnt = 1;
1505 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1506 &zero_byte_tests[i].lock1);
1507 status = smb_raw_lock(cli->tree, &io);
1508 CHECK_STATUS(status, NT_STATUS_OK);
1510 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1511 &zero_byte_tests[i].lock2);
1512 status = smb_raw_lock(cli->tree, &io);
1514 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1515 NT_STATUS_LOCK_NOT_GRANTED)) {
1516 /* Allow either of the failure messages and keep going
1517 * if we see the wrong status. */
1518 CHECK_STATUS_OR_CONT(status,
1519 NT_STATUS_LOCK_NOT_GRANTED,
1520 NT_STATUS_FILE_LOCK_CONFLICT);
1523 CHECK_STATUS_CONT(status,
1524 zero_byte_tests[i].exp_status);
1527 /* Unlock both locks. */
1528 io.lockx.in.ulock_cnt = 1;
1529 io.lockx.in.lock_cnt = 0;
1531 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1532 status = smb_raw_lock(cli->tree, &io);
1533 CHECK_STATUS(status, NT_STATUS_OK);
1536 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1537 &zero_byte_tests[i].lock1);
1538 status = smb_raw_lock(cli->tree, &io);
1539 CHECK_STATUS(status, NT_STATUS_OK);
1543 smbcli_close(cli->tree, fnum);
1544 smb_raw_exit(cli->session);
1545 smbcli_deltree(cli->tree, BASEDIR);
1549 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1555 const char *fname = BASEDIR "\\unlock.txt";
1556 struct smb_lock_entry lock1;
1557 struct smb_lock_entry lock2;
1559 torture_comment(tctx, "Testing LOCKX unlock:\n");
1561 if (!torture_setup_dir(cli, BASEDIR)) {
1565 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1566 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1567 "Failed to create %s - %s\n",
1568 fname, smbcli_errstr(cli->tree)));
1570 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1571 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
1572 "Failed to create %s - %s\n",
1573 fname, smbcli_errstr(cli->tree)));
1575 /* Setup initial parameters */
1576 io.lockx.level = RAW_LOCK_LOCKX;
1577 io.lockx.in.timeout = 0;
1579 lock1.pid = cli->session->pid;
1582 lock2.pid = cli->session->pid - 1;
1587 * Take exclusive lock, then unlock it with a shared-unlock call.
1589 torture_comment(tctx, " taking exclusive lock.\n");
1590 io.lockx.in.ulock_cnt = 0;
1591 io.lockx.in.lock_cnt = 1;
1592 io.lockx.in.mode = 0;
1593 io.lockx.in.file.fnum = fnum1;
1594 io.lockx.in.locks = &lock1;
1595 status = smb_raw_lock(cli->tree, &io);
1596 CHECK_STATUS(status, NT_STATUS_OK);
1598 torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
1599 io.lockx.in.ulock_cnt = 1;
1600 io.lockx.in.lock_cnt = 0;
1601 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1602 io.lockx.in.file.fnum = fnum1;
1603 io.lockx.in.locks = &lock1;
1604 status = smb_raw_lock(cli->tree, &io);
1605 CHECK_STATUS(status, NT_STATUS_OK);
1607 torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
1608 io.lockx.in.ulock_cnt = 0;
1609 io.lockx.in.lock_cnt = 1;
1610 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1611 io.lockx.in.file.fnum = fnum2;
1612 io.lockx.in.locks = &lock2;
1613 status = smb_raw_lock(cli->tree, &io);
1614 CHECK_STATUS(status, NT_STATUS_OK);
1617 * Unlock a shared lock with an exclusive-unlock call.
1619 torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
1620 io.lockx.in.ulock_cnt = 1;
1621 io.lockx.in.lock_cnt = 0;
1622 io.lockx.in.mode = 0;
1623 io.lockx.in.file.fnum = fnum2;
1624 io.lockx.in.locks = &lock2;
1625 status = smb_raw_lock(cli->tree, &io);
1626 CHECK_STATUS(status, NT_STATUS_OK);
1628 torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
1629 io.lockx.in.ulock_cnt = 0;
1630 io.lockx.in.lock_cnt = 1;
1631 io.lockx.in.mode = 0;
1632 io.lockx.in.file.fnum = fnum1;
1633 io.lockx.in.locks = &lock1;
1634 status = smb_raw_lock(cli->tree, &io);
1635 CHECK_STATUS(status, NT_STATUS_OK);
1638 io.lockx.in.ulock_cnt = 1;
1639 io.lockx.in.lock_cnt = 0;
1640 status = smb_raw_lock(cli->tree, &io);
1641 CHECK_STATUS(status, NT_STATUS_OK);
1644 * Test unlocking of 0-byte locks.
1647 torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
1648 "always unlocks the exclusive first.\n");
1649 lock1.pid = cli->session->pid;
1652 lock2.pid = cli->session->pid;
1655 io.lockx.in.ulock_cnt = 0;
1656 io.lockx.in.lock_cnt = 1;
1657 io.lockx.in.file.fnum = fnum1;
1658 io.lockx.in.locks = &lock1;
1660 /* lock 0-byte shared
1661 * Note: Order of the shared/exclusive locks doesn't matter. */
1662 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1663 status = smb_raw_lock(cli->tree, &io);
1664 CHECK_STATUS(status, NT_STATUS_OK);
1666 /* lock 0-byte exclusive */
1667 io.lockx.in.mode = 0;
1668 status = smb_raw_lock(cli->tree, &io);
1669 CHECK_STATUS(status, NT_STATUS_OK);
1671 /* test contention */
1672 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1673 io.lockx.in.locks = &lock2;
1674 io.lockx.in.file.fnum = fnum2;
1675 status = smb_raw_lock(cli->tree, &io);
1676 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1677 NT_STATUS_FILE_LOCK_CONFLICT);
1680 io.lockx.in.ulock_cnt = 1;
1681 io.lockx.in.lock_cnt = 0;
1682 io.lockx.in.file.fnum = fnum1;
1683 io.lockx.in.locks = &lock1;
1684 status = smb_raw_lock(cli->tree, &io);
1685 CHECK_STATUS(status, NT_STATUS_OK);
1687 /* test - can we take a shared lock? */
1688 io.lockx.in.ulock_cnt = 0;
1689 io.lockx.in.lock_cnt = 1;
1690 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1691 io.lockx.in.file.fnum = fnum2;
1692 io.lockx.in.locks = &lock2;
1693 status = smb_raw_lock(cli->tree, &io);
1695 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1696 * new to Win7, it succeeds in WinXP too), until I can come to a
1697 * resolution as to whether Samba should support this or not. There is
1698 * code to preference unlocking exclusive locks before shared locks,
1699 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1700 if (TARGET_IS_SAMBA3(tctx)) {
1701 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1702 NT_STATUS_FILE_LOCK_CONFLICT);
1704 CHECK_STATUS(status, NT_STATUS_OK);
1708 io.lockx.in.ulock_cnt = 1;
1709 io.lockx.in.lock_cnt = 0;
1710 status = smb_raw_lock(cli->tree, &io);
1712 /* XXX Same as above. */
1713 if (TARGET_IS_SAMBA3(tctx)) {
1714 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1716 CHECK_STATUS(status, NT_STATUS_OK);
1719 io.lockx.in.file.fnum = fnum1;
1720 io.lockx.in.locks = &lock1;
1721 status = smb_raw_lock(cli->tree, &io);
1722 CHECK_STATUS(status, NT_STATUS_OK);
1725 smbcli_close(cli->tree, fnum1);
1726 smbcli_close(cli->tree, fnum2);
1727 smb_raw_exit(cli->session);
1728 smbcli_deltree(cli->tree, BASEDIR);
1732 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1738 const char *fname = BASEDIR "\\unlock_multiple.txt";
1739 struct smb_lock_entry lock1;
1740 struct smb_lock_entry lock2;
1741 struct smb_lock_entry locks[2];
1743 torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
1745 if (!torture_setup_dir(cli, BASEDIR)) {
1749 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1750 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1751 "Failed to create %s - %s\n",
1752 fname, smbcli_errstr(cli->tree)));
1754 /* Setup initial parameters */
1755 io.lockx.level = RAW_LOCK_LOCKX;
1756 io.lockx.in.timeout = 0;
1758 lock1.pid = cli->session->pid;
1761 lock2.pid = cli->session->pid;
1768 io.lockx.in.file.fnum = fnum1;
1769 io.lockx.in.mode = 0; /* exclusive */
1771 /** Test1: Take second lock, but not first. */
1772 torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
1775 io.lockx.in.ulock_cnt = 0;
1776 io.lockx.in.lock_cnt = 1;
1777 io.lockx.in.locks = &lock2;
1778 status = smb_raw_lock(cli->tree, &io);
1779 CHECK_STATUS(status, NT_STATUS_OK);
1781 /* Try to unlock both locks. */
1782 io.lockx.in.ulock_cnt = 2;
1783 io.lockx.in.lock_cnt = 0;
1784 io.lockx.in.locks = locks;
1786 status = smb_raw_lock(cli->tree, &io);
1787 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1789 /* Second lock should not be unlocked. */
1790 io.lockx.in.ulock_cnt = 0;
1791 io.lockx.in.lock_cnt = 1;
1792 io.lockx.in.locks = &lock2;
1793 status = smb_raw_lock(cli->tree, &io);
1794 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1797 io.lockx.in.ulock_cnt = 1;
1798 io.lockx.in.lock_cnt = 0;
1799 io.lockx.in.locks = &lock2;
1800 status = smb_raw_lock(cli->tree, &io);
1801 CHECK_STATUS(status, NT_STATUS_OK);
1803 /** Test2: Take first lock, but not second. */
1804 torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
1807 io.lockx.in.ulock_cnt = 0;
1808 io.lockx.in.lock_cnt = 1;
1809 io.lockx.in.locks = &lock1;
1810 status = smb_raw_lock(cli->tree, &io);
1811 CHECK_STATUS(status, NT_STATUS_OK);
1813 /* Try to unlock both locks. */
1814 io.lockx.in.ulock_cnt = 2;
1815 io.lockx.in.lock_cnt = 0;
1816 io.lockx.in.locks = locks;
1818 status = smb_raw_lock(cli->tree, &io);
1819 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1821 /* First lock should be unlocked. */
1822 io.lockx.in.ulock_cnt = 0;
1823 io.lockx.in.lock_cnt = 1;
1824 io.lockx.in.locks = &lock1;
1825 status = smb_raw_lock(cli->tree, &io);
1826 CHECK_STATUS(status, NT_STATUS_OK);
1829 io.lockx.in.ulock_cnt = 1;
1830 io.lockx.in.lock_cnt = 0;
1831 io.lockx.in.locks = &lock1;
1832 status = smb_raw_lock(cli->tree, &io);
1833 CHECK_STATUS(status, NT_STATUS_OK);
1835 /* Test3: Request 2 locks, second will contend. What happens to the
1837 torture_comment(tctx, " request 2 locks, second one will contend. "
1838 "Expect both to fail.\n");
1840 /* Lock the second range */
1841 io.lockx.in.ulock_cnt = 0;
1842 io.lockx.in.lock_cnt = 1;
1843 io.lockx.in.locks = &lock2;
1844 status = smb_raw_lock(cli->tree, &io);
1845 CHECK_STATUS(status, NT_STATUS_OK);
1847 /* Request both locks */
1848 io.lockx.in.ulock_cnt = 0;
1849 io.lockx.in.lock_cnt = 2;
1850 io.lockx.in.locks = locks;
1852 status = smb_raw_lock(cli->tree, &io);
1853 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1855 /* First lock should be unlocked. */
1856 io.lockx.in.ulock_cnt = 0;
1857 io.lockx.in.lock_cnt = 1;
1858 io.lockx.in.locks = &lock1;
1859 status = smb_raw_lock(cli->tree, &io);
1860 CHECK_STATUS(status, NT_STATUS_OK);
1863 io.lockx.in.ulock_cnt = 2;
1864 io.lockx.in.lock_cnt = 0;
1865 io.lockx.in.locks = locks;
1866 status = smb_raw_lock(cli->tree, &io);
1867 CHECK_STATUS(status, NT_STATUS_OK);
1869 /* Test4: Request unlock and lock. The lock contends, is the unlock
1870 * then re-locked? */
1871 torture_comment(tctx, " request unlock and lock, second one will "
1872 "contend. Expect the unlock to succeed.\n");
1874 /* Lock both ranges */
1875 io.lockx.in.ulock_cnt = 0;
1876 io.lockx.in.lock_cnt = 2;
1877 io.lockx.in.locks = locks;
1878 status = smb_raw_lock(cli->tree, &io);
1879 CHECK_STATUS(status, NT_STATUS_OK);
1881 /* Attempt to unlock the first range and lock the second */
1882 io.lockx.in.ulock_cnt = 1;
1883 io.lockx.in.lock_cnt = 1;
1884 io.lockx.in.locks = locks;
1885 status = smb_raw_lock(cli->tree, &io);
1886 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1888 /* The first lock should've been unlocked */
1889 io.lockx.in.ulock_cnt = 0;
1890 io.lockx.in.lock_cnt = 1;
1891 io.lockx.in.locks = &lock1;
1892 status = smb_raw_lock(cli->tree, &io);
1893 CHECK_STATUS(status, NT_STATUS_OK);
1896 io.lockx.in.ulock_cnt = 2;
1897 io.lockx.in.lock_cnt = 0;
1898 io.lockx.in.locks = locks;
1899 status = smb_raw_lock(cli->tree, &io);
1900 CHECK_STATUS(status, NT_STATUS_OK);
1903 smbcli_close(cli->tree, fnum1);
1904 smb_raw_exit(cli->session);
1905 smbcli_deltree(cli->tree, BASEDIR);
1910 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1911 * - stacking an exclusive on top of shared fails
1912 * - stacking two exclusives fail
1914 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
1920 const char *fname = BASEDIR "\\stacking.txt";
1921 struct smb_lock_entry lock1;
1922 struct smb_lock_entry lock2;
1924 torture_comment(tctx, "Testing stacking:\n");
1926 if (!torture_setup_dir(cli, BASEDIR)) {
1930 io.generic.level = RAW_LOCK_LOCKX;
1932 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1933 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1934 "Failed to create %s - %s\n",
1935 fname, smbcli_errstr(cli->tree)));
1937 /* Setup initial parameters */
1938 io.lockx.level = RAW_LOCK_LOCKX;
1939 io.lockx.in.timeout = 0;
1941 lock1.pid = cli->session->pid;
1944 lock2.pid = cli->session->pid - 1;
1949 * Try to take a shared lock, then stack an exclusive.
1951 torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
1952 io.lockx.in.file.fnum = fnum1;
1953 io.lockx.in.locks = &lock1;
1955 io.lockx.in.ulock_cnt = 0;
1956 io.lockx.in.lock_cnt = 1;
1957 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1958 status = smb_raw_lock(cli->tree, &io);
1959 CHECK_STATUS(status, NT_STATUS_OK);
1961 io.lockx.in.ulock_cnt = 0;
1962 io.lockx.in.lock_cnt = 1;
1963 io.lockx.in.mode = 0;
1964 status = smb_raw_lock(cli->tree, &io);
1965 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1966 NT_STATUS_FILE_LOCK_CONFLICT);
1969 io.lockx.in.ulock_cnt = 1;
1970 io.lockx.in.lock_cnt = 0;
1971 status = smb_raw_lock(cli->tree, &io);
1972 CHECK_STATUS(status, NT_STATUS_OK);
1975 * Prove that two exclusive locks do not stack.
1977 torture_comment(tctx, " two exclusive locks do not stack.\n");
1978 io.lockx.in.ulock_cnt = 0;
1979 io.lockx.in.lock_cnt = 1;
1980 io.lockx.in.mode = 0;
1981 status = smb_raw_lock(cli->tree, &io);
1982 CHECK_STATUS(status, NT_STATUS_OK);
1983 status = smb_raw_lock(cli->tree, &io);
1984 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1985 NT_STATUS_FILE_LOCK_CONFLICT);
1988 io.lockx.in.ulock_cnt = 1;
1989 io.lockx.in.lock_cnt = 0;
1990 status = smb_raw_lock(cli->tree, &io);
1991 CHECK_STATUS(status, NT_STATUS_OK);
1994 smbcli_close(cli->tree, fnum1);
1995 smb_raw_exit(cli->session);
1996 smbcli_deltree(cli->tree, BASEDIR);
2001 * Test how 0-byte read requests contend with byte range locks
2003 static bool test_zerobyteread(struct torture_context *tctx,
2004 struct smbcli_state *cli)
2011 const char *fname = BASEDIR "\\zerobyteread.txt";
2012 struct smb_lock_entry lock1;
2015 if (!torture_setup_dir(cli, BASEDIR)) {
2019 io.generic.level = RAW_LOCK_LOCKX;
2021 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2022 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
2023 "Failed to create %s - %s\n",
2024 fname, smbcli_errstr(cli->tree)));
2026 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2027 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
2028 "Failed to create %s - %s\n",
2029 fname, smbcli_errstr(cli->tree)));
2031 /* Setup initial parameters */
2032 io.lockx.level = RAW_LOCK_LOCKX;
2033 io.lockx.in.timeout = 0;
2035 lock1.pid = cli->session->pid;
2040 rd.readx.level = RAW_READ_READX;
2042 torture_comment(tctx, "Testing zero byte read on lock range:\n");
2044 /* Take an exclusive lock */
2045 torture_comment(tctx, " taking exclusive lock.\n");
2046 io.lockx.in.ulock_cnt = 0;
2047 io.lockx.in.lock_cnt = 1;
2048 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2049 io.lockx.in.file.fnum = fnum1;
2050 io.lockx.in.locks = &lock1;
2051 status = smb_raw_lock(cli->tree, &io);
2052 CHECK_STATUS(status, NT_STATUS_OK);
2054 /* Try a zero byte read */
2055 torture_comment(tctx, " reading 0 bytes.\n");
2056 rd.readx.in.file.fnum = fnum2;
2057 rd.readx.in.offset = 5;
2058 rd.readx.in.mincnt = 0;
2059 rd.readx.in.maxcnt = 0;
2060 rd.readx.in.remaining = 0;
2061 rd.readx.in.read_for_execute = false;
2062 rd.readx.out.data = &c;
2063 status = smb_raw_read(cli->tree, &rd);
2064 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2065 "zero byte read did not return 0 bytes");
2066 CHECK_STATUS(status, NT_STATUS_OK);
2069 io.lockx.in.ulock_cnt = 1;
2070 io.lockx.in.lock_cnt = 0;
2071 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2072 io.lockx.in.file.fnum = fnum1;
2073 io.lockx.in.locks = &lock1;
2074 status = smb_raw_lock(cli->tree, &io);
2075 CHECK_STATUS(status, NT_STATUS_OK);
2077 torture_comment(tctx, "Testing zero byte read on zero byte lock "
2080 /* Take an exclusive lock */
2081 torture_comment(tctx, " taking exclusive 0-byte lock.\n");
2082 io.lockx.in.ulock_cnt = 0;
2083 io.lockx.in.lock_cnt = 1;
2084 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2085 io.lockx.in.file.fnum = fnum1;
2086 io.lockx.in.locks = &lock1;
2089 status = smb_raw_lock(cli->tree, &io);
2090 CHECK_STATUS(status, NT_STATUS_OK);
2092 /* Try a zero byte read before the lock */
2093 torture_comment(tctx, " reading 0 bytes before the lock.\n");
2094 rd.readx.in.file.fnum = fnum2;
2095 rd.readx.in.offset = 4;
2096 rd.readx.in.mincnt = 0;
2097 rd.readx.in.maxcnt = 0;
2098 rd.readx.in.remaining = 0;
2099 rd.readx.in.read_for_execute = false;
2100 rd.readx.out.data = &c;
2101 status = smb_raw_read(cli->tree, &rd);
2102 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2103 "zero byte read did not return 0 bytes");
2104 CHECK_STATUS(status, NT_STATUS_OK);
2106 /* Try a zero byte read on the lock */
2107 torture_comment(tctx, " reading 0 bytes on the lock.\n");
2108 rd.readx.in.file.fnum = fnum2;
2109 rd.readx.in.offset = 5;
2110 rd.readx.in.mincnt = 0;
2111 rd.readx.in.maxcnt = 0;
2112 rd.readx.in.remaining = 0;
2113 rd.readx.in.read_for_execute = false;
2114 rd.readx.out.data = &c;
2115 status = smb_raw_read(cli->tree, &rd);
2116 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2117 "zero byte read did not return 0 bytes");
2118 CHECK_STATUS(status, NT_STATUS_OK);
2120 /* Try a zero byte read after the lock */
2121 torture_comment(tctx, " reading 0 bytes after the lock.\n");
2122 rd.readx.in.file.fnum = fnum2;
2123 rd.readx.in.offset = 6;
2124 rd.readx.in.mincnt = 0;
2125 rd.readx.in.maxcnt = 0;
2126 rd.readx.in.remaining = 0;
2127 rd.readx.in.read_for_execute = false;
2128 rd.readx.out.data = &c;
2129 status = smb_raw_read(cli->tree, &rd);
2130 torture_assert_int_equal_goto(tctx, rd.readx.out.nread, 0, ret, done,
2131 "zero byte read did not return 0 bytes");
2132 CHECK_STATUS(status, NT_STATUS_OK);
2135 io.lockx.in.ulock_cnt = 1;
2136 io.lockx.in.lock_cnt = 0;
2137 io.lockx.in.mode = LOCKING_ANDX_EXCLUSIVE_LOCK;
2138 io.lockx.in.file.fnum = fnum1;
2139 io.lockx.in.locks = &lock1;
2140 status = smb_raw_lock(cli->tree, &io);
2141 CHECK_STATUS(status, NT_STATUS_OK);
2144 smbcli_close(cli->tree, fnum1);
2145 smbcli_close(cli->tree, fnum2);
2146 smb_raw_exit(cli->session);
2147 smbcli_deltree(cli->tree, BASEDIR);
2152 basic testing of lock calls
2154 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
2156 struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
2158 torture_suite_add_1smb_test(suite, "lockx", test_lockx);
2159 torture_suite_add_1smb_test(suite, "lock", test_lock);
2160 torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
2161 torture_suite_add_1smb_test(suite, "async", test_async);
2162 torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
2163 torture_suite_add_1smb_test(suite, "changetype", test_changetype);
2165 torture_suite_add_1smb_test(suite, "stacking", test_stacking);
2166 torture_suite_add_1smb_test(suite, "unlock", test_unlock);
2167 torture_suite_add_1smb_test(suite, "multiple_unlock",
2168 test_multiple_unlock);
2169 torture_suite_add_1smb_test(suite, "zerobytelocks",
2170 test_zerobytelocks);
2171 torture_suite_add_1smb_test(suite, "zerobyteread",