RAW-LOCK: samba4 behaves like windows 7 in regard of locking error codes
[Samba/ekacnet.git] / source4 / torture / raw / lock.c
blobf798f50ce755d689132e6eb250ba6fb05f32fa43
1 /*
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/>.
20 #include "includes.h"
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)); \
38 ret = false; \
39 goto done; \
40 }} while (0)
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)); \
47 ret = false; \
48 }} while (0)
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)); \
57 ret = false; \
58 goto done; \
59 }} while (0)
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)); \
68 ret = false; \
69 }} while (0)
70 #define BASEDIR "\\testlock"
72 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
73 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
76 test SMBlock and SMBunlock ops
78 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
80 union smb_lock io;
81 NTSTATUS status;
82 bool ret = true;
83 int fnum;
84 const char *fname = BASEDIR "\\test.txt";
86 if (!torture_setup_dir(cli, BASEDIR)) {
87 return false;
90 torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
91 io.generic.level = RAW_LOCK_LOCK;
93 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
94 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
95 "Failed to create %s - %s\n",
96 fname, smbcli_errstr(cli->tree)));
98 torture_comment(tctx, "Trying 0/0 lock\n");
99 io.lock.level = RAW_LOCK_LOCK;
100 io.lock.in.file.fnum = fnum;
101 io.lock.in.count = 0;
102 io.lock.in.offset = 0;
103 status = smb_raw_lock(cli->tree, &io);
104 CHECK_STATUS(status, NT_STATUS_OK);
105 cli->session->pid++;
106 status = smb_raw_lock(cli->tree, &io);
107 CHECK_STATUS(status, NT_STATUS_OK);
108 cli->session->pid--;
109 io.lock.level = RAW_LOCK_UNLOCK;
110 status = smb_raw_lock(cli->tree, &io);
111 CHECK_STATUS(status, NT_STATUS_OK);
113 torture_comment(tctx, "Trying 0/1 lock\n");
114 io.lock.level = RAW_LOCK_LOCK;
115 io.lock.in.file.fnum = fnum;
116 io.lock.in.count = 1;
117 io.lock.in.offset = 0;
118 status = smb_raw_lock(cli->tree, &io);
119 CHECK_STATUS(status, NT_STATUS_OK);
120 cli->session->pid++;
121 status = smb_raw_lock(cli->tree, &io);
122 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
123 cli->session->pid--;
124 io.lock.level = RAW_LOCK_UNLOCK;
125 status = smb_raw_lock(cli->tree, &io);
126 CHECK_STATUS(status, NT_STATUS_OK);
127 io.lock.level = RAW_LOCK_UNLOCK;
128 status = smb_raw_lock(cli->tree, &io);
129 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
131 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
132 io.lock.level = RAW_LOCK_LOCK;
133 io.lock.in.file.fnum = fnum;
134 io.lock.in.count = 4000;
135 io.lock.in.offset = 0xEEFFFFFF;
136 status = smb_raw_lock(cli->tree, &io);
137 CHECK_STATUS(status, NT_STATUS_OK);
138 cli->session->pid++;
139 status = smb_raw_lock(cli->tree, &io);
140 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
141 cli->session->pid--;
142 io.lock.level = RAW_LOCK_UNLOCK;
143 status = smb_raw_lock(cli->tree, &io);
144 CHECK_STATUS(status, NT_STATUS_OK);
145 io.lock.level = RAW_LOCK_UNLOCK;
146 status = smb_raw_lock(cli->tree, &io);
147 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
149 torture_comment(tctx, "Trying 0xEF000000 lock\n");
150 io.lock.level = RAW_LOCK_LOCK;
151 io.lock.in.file.fnum = fnum;
152 io.lock.in.count = 4000;
153 io.lock.in.offset = 0xEEFFFFFF;
154 status = smb_raw_lock(cli->tree, &io);
155 CHECK_STATUS(status, NT_STATUS_OK);
156 cli->session->pid++;
157 status = smb_raw_lock(cli->tree, &io);
158 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
159 cli->session->pid--;
160 io.lock.level = RAW_LOCK_UNLOCK;
161 status = smb_raw_lock(cli->tree, &io);
162 CHECK_STATUS(status, NT_STATUS_OK);
163 io.lock.level = RAW_LOCK_UNLOCK;
164 status = smb_raw_lock(cli->tree, &io);
165 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
167 torture_comment(tctx, "Trying max lock\n");
168 io.lock.level = RAW_LOCK_LOCK;
169 io.lock.in.file.fnum = fnum;
170 io.lock.in.count = 4000;
171 io.lock.in.offset = 0xEF000000;
172 status = smb_raw_lock(cli->tree, &io);
173 CHECK_STATUS(status, NT_STATUS_OK);
174 cli->session->pid++;
175 status = smb_raw_lock(cli->tree, &io);
176 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
177 cli->session->pid--;
178 io.lock.level = RAW_LOCK_UNLOCK;
179 status = smb_raw_lock(cli->tree, &io);
180 CHECK_STATUS(status, NT_STATUS_OK);
181 io.lock.level = RAW_LOCK_UNLOCK;
182 status = smb_raw_lock(cli->tree, &io);
183 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
185 torture_comment(tctx, "Trying wrong pid unlock\n");
186 io.lock.level = RAW_LOCK_LOCK;
187 io.lock.in.file.fnum = fnum;
188 io.lock.in.count = 4002;
189 io.lock.in.offset = 10001;
190 status = smb_raw_lock(cli->tree, &io);
191 CHECK_STATUS(status, NT_STATUS_OK);
192 cli->session->pid++;
193 io.lock.level = RAW_LOCK_UNLOCK;
194 status = smb_raw_lock(cli->tree, &io);
195 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
196 cli->session->pid--;
197 status = smb_raw_lock(cli->tree, &io);
198 CHECK_STATUS(status, NT_STATUS_OK);
200 done:
201 smbcli_close(cli->tree, fnum);
202 smb_raw_exit(cli->session);
203 smbcli_deltree(cli->tree, BASEDIR);
204 return ret;
209 test locking&X ops
211 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
213 union smb_lock io;
214 struct smb_lock_entry lock[1];
215 NTSTATUS status;
216 bool ret = true;
217 int fnum;
218 const char *fname = BASEDIR "\\test.txt";
220 if (!torture_setup_dir(cli, BASEDIR)) {
221 return false;
224 torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
225 io.generic.level = RAW_LOCK_LOCKX;
227 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
228 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
229 "Failed to create %s - %s\n",
230 fname, smbcli_errstr(cli->tree)));
232 io.lockx.level = RAW_LOCK_LOCKX;
233 io.lockx.in.file.fnum = fnum;
234 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
235 io.lockx.in.timeout = 0;
236 io.lockx.in.ulock_cnt = 0;
237 io.lockx.in.lock_cnt = 1;
238 lock[0].pid = cli->session->pid;
239 lock[0].offset = 10;
240 lock[0].count = 1;
241 io.lockx.in.locks = &lock[0];
242 status = smb_raw_lock(cli->tree, &io);
243 CHECK_STATUS(status, NT_STATUS_OK);
246 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
247 io.lockx.in.ulock_cnt = 0;
248 io.lockx.in.lock_cnt = 1;
249 lock[0].count = 4000;
250 lock[0].offset = 0xEEFFFFFF;
251 status = smb_raw_lock(cli->tree, &io);
252 CHECK_STATUS(status, NT_STATUS_OK);
253 lock[0].pid++;
254 status = smb_raw_lock(cli->tree, &io);
255 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
256 lock[0].pid--;
257 io.lockx.in.ulock_cnt = 1;
258 io.lockx.in.lock_cnt = 0;
259 status = smb_raw_lock(cli->tree, &io);
260 CHECK_STATUS(status, NT_STATUS_OK);
261 status = smb_raw_lock(cli->tree, &io);
262 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
264 torture_comment(tctx, "Trying 0xEF000000 lock\n");
265 io.lockx.in.ulock_cnt = 0;
266 io.lockx.in.lock_cnt = 1;
267 lock[0].count = 4000;
268 lock[0].offset = 0xEF000000;
269 status = smb_raw_lock(cli->tree, &io);
270 CHECK_STATUS(status, NT_STATUS_OK);
271 lock[0].pid++;
272 status = smb_raw_lock(cli->tree, &io);
273 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
274 lock[0].pid--;
275 io.lockx.in.ulock_cnt = 1;
276 io.lockx.in.lock_cnt = 0;
277 status = smb_raw_lock(cli->tree, &io);
278 CHECK_STATUS(status, NT_STATUS_OK);
279 status = smb_raw_lock(cli->tree, &io);
280 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
282 torture_comment(tctx, "Trying zero lock\n");
283 io.lockx.in.ulock_cnt = 0;
284 io.lockx.in.lock_cnt = 1;
285 lock[0].count = 0;
286 lock[0].offset = ~0;
287 status = smb_raw_lock(cli->tree, &io);
288 CHECK_STATUS(status, NT_STATUS_OK);
289 lock[0].pid++;
290 status = smb_raw_lock(cli->tree, &io);
291 CHECK_STATUS(status, NT_STATUS_OK);
292 lock[0].pid--;
293 io.lockx.in.ulock_cnt = 1;
294 io.lockx.in.lock_cnt = 0;
295 status = smb_raw_lock(cli->tree, &io);
296 CHECK_STATUS(status, NT_STATUS_OK);
297 status = smb_raw_lock(cli->tree, &io);
298 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
300 torture_comment(tctx, "Trying max lock\n");
301 io.lockx.in.ulock_cnt = 0;
302 io.lockx.in.lock_cnt = 1;
303 lock[0].count = 0;
304 lock[0].offset = ~0;
305 status = smb_raw_lock(cli->tree, &io);
306 CHECK_STATUS(status, NT_STATUS_OK);
307 lock[0].pid++;
308 status = smb_raw_lock(cli->tree, &io);
309 CHECK_STATUS(status, NT_STATUS_OK);
310 lock[0].pid--;
311 io.lockx.in.ulock_cnt = 1;
312 io.lockx.in.lock_cnt = 0;
313 status = smb_raw_lock(cli->tree, &io);
314 CHECK_STATUS(status, NT_STATUS_OK);
315 status = smb_raw_lock(cli->tree, &io);
316 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
318 torture_comment(tctx, "Trying 2^63\n");
319 io.lockx.in.ulock_cnt = 0;
320 io.lockx.in.lock_cnt = 1;
321 lock[0].count = 1;
322 lock[0].offset = 1;
323 lock[0].offset <<= 63;
324 status = smb_raw_lock(cli->tree, &io);
325 CHECK_STATUS(status, NT_STATUS_OK);
326 lock[0].pid++;
327 status = smb_raw_lock(cli->tree, &io);
328 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
329 lock[0].pid--;
330 io.lockx.in.ulock_cnt = 1;
331 io.lockx.in.lock_cnt = 0;
332 status = smb_raw_lock(cli->tree, &io);
333 CHECK_STATUS(status, NT_STATUS_OK);
334 status = smb_raw_lock(cli->tree, &io);
335 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
337 torture_comment(tctx, "Trying 2^63 - 1\n");
338 io.lockx.in.ulock_cnt = 0;
339 io.lockx.in.lock_cnt = 1;
340 lock[0].count = 1;
341 lock[0].offset = 1;
342 lock[0].offset <<= 63;
343 lock[0].offset--;
344 status = smb_raw_lock(cli->tree, &io);
345 CHECK_STATUS(status, NT_STATUS_OK);
346 lock[0].pid++;
347 status = smb_raw_lock(cli->tree, &io);
348 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
349 lock[0].pid--;
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 max lock 2\n");
358 io.lockx.in.ulock_cnt = 0;
359 io.lockx.in.lock_cnt = 1;
360 lock[0].count = 1;
361 lock[0].offset = ~0;
362 status = smb_raw_lock(cli->tree, &io);
363 CHECK_STATUS(status, NT_STATUS_OK);
364 lock[0].pid++;
365 lock[0].count = 2;
366 status = smb_raw_lock(cli->tree, &io);
367 if (TARGET_IS_WIN7(tctx))
368 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
369 else
370 CHECK_STATUS(status, NT_STATUS_OK);
371 lock[0].pid--;
372 io.lockx.in.ulock_cnt = 1;
373 io.lockx.in.lock_cnt = 0;
374 lock[0].count = 1;
375 status = smb_raw_lock(cli->tree, &io);
377 /* XXX This is very strange - Win7 gives us an invalid range when we
378 * unlock the range even though the range is locked! Win7 bug? */
379 if (TARGET_IS_WIN7(tctx))
380 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
381 else {
382 CHECK_STATUS(status, NT_STATUS_OK);
383 status = smb_raw_lock(cli->tree, &io);
384 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
387 done:
388 smbcli_close(cli->tree, fnum);
389 smb_raw_exit(cli->session);
390 smbcli_deltree(cli->tree, BASEDIR);
391 return ret;
395 test high pid
397 static bool test_pidhigh(struct torture_context *tctx,
398 struct smbcli_state *cli)
400 union smb_lock io;
401 struct smb_lock_entry lock[1];
402 NTSTATUS status;
403 bool ret = true;
404 int fnum;
405 const char *fname = BASEDIR "\\test.txt";
406 uint8_t c = 1;
408 if (!torture_setup_dir(cli, BASEDIR)) {
409 return false;
412 torture_comment(tctx, "Testing high pid\n");
413 io.generic.level = RAW_LOCK_LOCKX;
415 cli->session->pid = 1;
417 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
418 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
419 "Failed to create %s - %s\n",
420 fname, smbcli_errstr(cli->tree)));
422 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
423 torture_result(tctx, TORTURE_FAIL,
424 "Failed to write 1 byte - %s\n",
425 smbcli_errstr(cli->tree));
426 ret = false;
427 goto done;
430 io.lockx.level = RAW_LOCK_LOCKX;
431 io.lockx.in.file.fnum = fnum;
432 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
433 io.lockx.in.timeout = 0;
434 io.lockx.in.ulock_cnt = 0;
435 io.lockx.in.lock_cnt = 1;
436 lock[0].pid = cli->session->pid;
437 lock[0].offset = 0;
438 lock[0].count = 0xFFFFFFFF;
439 io.lockx.in.locks = &lock[0];
440 status = smb_raw_lock(cli->tree, &io);
441 CHECK_STATUS(status, NT_STATUS_OK);
443 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
444 torture_result(tctx, TORTURE_FAIL,
445 "Failed to read 1 byte - %s\n",
446 smbcli_errstr(cli->tree));
447 ret = false;
448 goto done;
451 cli->session->pid = 2;
453 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
454 torture_result(tctx, TORTURE_FAIL,
455 "pid is incorrect handled for read with lock!\n");
456 ret = false;
457 goto done;
460 cli->session->pid = 0x10001;
462 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
463 torture_result(tctx, TORTURE_FAIL,
464 "High pid is used on this server!\n");
465 ret = false;
466 } else {
467 torture_warning(tctx, "High pid is not used on this server (correct)\n");
470 done:
471 smbcli_close(cli->tree, fnum);
472 smb_raw_exit(cli->session);
473 smbcli_deltree(cli->tree, BASEDIR);
474 return ret;
479 test locking&X async operation
481 static bool test_async(struct torture_context *tctx,
482 struct smbcli_state *cli)
484 struct smbcli_session *session;
485 struct smb_composite_sesssetup setup;
486 struct smbcli_tree *tree;
487 union smb_tcon tcon;
488 const char *host, *share;
489 union smb_lock io;
490 struct smb_lock_entry lock[2];
491 NTSTATUS status;
492 bool ret = true;
493 int fnum;
494 const char *fname = BASEDIR "\\test.txt";
495 time_t t;
496 struct smbcli_request *req;
497 struct smbcli_session_options options;
499 if (!torture_setup_dir(cli, BASEDIR)) {
500 return false;
503 lp_smbcli_session_options(tctx->lp_ctx, &options);
505 torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
506 io.generic.level = RAW_LOCK_LOCKX;
508 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
509 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
510 "Failed to create %s - %s\n",
511 fname, smbcli_errstr(cli->tree)));
513 io.lockx.level = RAW_LOCK_LOCKX;
514 io.lockx.in.file.fnum = fnum;
515 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
516 io.lockx.in.timeout = 0;
517 io.lockx.in.ulock_cnt = 0;
518 io.lockx.in.lock_cnt = 1;
519 lock[0].pid = cli->session->pid;
520 lock[0].offset = 100;
521 lock[0].count = 10;
522 io.lockx.in.locks = &lock[0];
523 status = smb_raw_lock(cli->tree, &io);
524 CHECK_STATUS(status, NT_STATUS_OK);
526 t = time(NULL);
528 torture_comment(tctx, "testing cancel by CANCEL_LOCK\n");
530 /* setup a timed lock */
531 io.lockx.in.timeout = 10000;
532 req = smb_raw_lock_send(cli->tree, &io);
533 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
534 "Failed to setup timed lock (%s)\n", __location__));
536 /* cancel the wrong range */
537 lock[0].offset = 0;
538 io.lockx.in.timeout = 0;
539 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
540 status = smb_raw_lock(cli->tree, &io);
541 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
543 /* cancel with the wrong bits set */
544 lock[0].offset = 100;
545 io.lockx.in.timeout = 0;
546 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
547 status = smb_raw_lock(cli->tree, &io);
548 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
550 /* cancel the right range */
551 lock[0].offset = 100;
552 io.lockx.in.timeout = 0;
553 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
554 status = smb_raw_lock(cli->tree, &io);
555 CHECK_STATUS(status, NT_STATUS_OK);
557 /* receive the failed lock request */
558 status = smbcli_request_simple_recv(req);
559 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
561 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
562 "lock cancel was not immediate (%s)\n", __location__));
564 torture_comment(tctx, "testing cancel by unlock\n");
565 io.lockx.in.ulock_cnt = 0;
566 io.lockx.in.lock_cnt = 1;
567 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
568 io.lockx.in.timeout = 0;
569 status = smb_raw_lock(cli->tree, &io);
570 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
572 io.lockx.in.timeout = 5000;
573 req = smb_raw_lock_send(cli->tree, &io);
574 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
575 "Failed to setup timed lock (%s)\n", __location__));
577 io.lockx.in.ulock_cnt = 1;
578 io.lockx.in.lock_cnt = 0;
579 status = smb_raw_lock(cli->tree, &io);
580 CHECK_STATUS(status, NT_STATUS_OK);
582 t = time(NULL);
583 status = smbcli_request_simple_recv(req);
584 CHECK_STATUS(status, NT_STATUS_OK);
586 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
587 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
588 __location__, (int)(time(NULL)-t)));
590 torture_comment(tctx, "testing cancel by close\n");
591 io.lockx.in.ulock_cnt = 0;
592 io.lockx.in.lock_cnt = 1;
593 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
594 io.lockx.in.timeout = 0;
595 status = smb_raw_lock(cli->tree, &io);
596 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
598 t = time(NULL);
599 io.lockx.in.timeout = 10000;
600 req = smb_raw_lock_send(cli->tree, &io);
601 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
602 "Failed to setup timed lock (%s)\n", __location__));
604 status = smbcli_close(cli->tree, fnum);
605 CHECK_STATUS(status, NT_STATUS_OK);
607 status = smbcli_request_simple_recv(req);
608 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
610 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
611 "lock cancel by close was not immediate (%s)\n", __location__));
613 torture_comment(tctx, "create a new sessions\n");
614 session = smbcli_session_init(cli->transport, tctx, false, options);
615 setup.in.sesskey = cli->transport->negotiate.sesskey;
616 setup.in.capabilities = cli->transport->negotiate.capabilities;
617 setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
618 setup.in.credentials = cmdline_credentials;
619 setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
620 status = smb_composite_sesssetup(session, &setup);
621 CHECK_STATUS(status, NT_STATUS_OK);
622 session->vuid = setup.out.vuid;
624 torture_comment(tctx, "create new tree context\n");
625 share = torture_setting_string(tctx, "share", NULL);
626 host = torture_setting_string(tctx, "host", NULL);
627 tree = smbcli_tree_init(session, tctx, false);
628 tcon.generic.level = RAW_TCON_TCONX;
629 tcon.tconx.in.flags = 0;
630 tcon.tconx.in.password = data_blob(NULL, 0);
631 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
632 tcon.tconx.in.device = "A:";
633 status = smb_raw_tcon(tree, tctx, &tcon);
634 CHECK_STATUS(status, NT_STATUS_OK);
635 tree->tid = tcon.tconx.out.tid;
637 torture_comment(tctx, "testing cancel by exit\n");
638 fname = BASEDIR "\\test_exit.txt";
639 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
640 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
641 "Failed to reopen %s - %s\n",
642 fname, smbcli_errstr(tree)));
644 io.lockx.level = RAW_LOCK_LOCKX;
645 io.lockx.in.file.fnum = fnum;
646 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
647 io.lockx.in.timeout = 0;
648 io.lockx.in.ulock_cnt = 0;
649 io.lockx.in.lock_cnt = 1;
650 lock[0].pid = session->pid;
651 lock[0].offset = 100;
652 lock[0].count = 10;
653 io.lockx.in.locks = &lock[0];
654 status = smb_raw_lock(tree, &io);
655 CHECK_STATUS(status, NT_STATUS_OK);
657 io.lockx.in.ulock_cnt = 0;
658 io.lockx.in.lock_cnt = 1;
659 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
660 io.lockx.in.timeout = 0;
661 status = smb_raw_lock(tree, &io);
662 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
664 io.lockx.in.timeout = 10000;
665 t = time(NULL);
666 req = smb_raw_lock_send(tree, &io);
667 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
668 "Failed to setup timed lock (%s)\n", __location__));
670 status = smb_raw_exit(session);
671 CHECK_STATUS(status, NT_STATUS_OK);
673 status = smbcli_request_simple_recv(req);
674 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
676 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
677 "lock cancel by exit was not immediate (%s)\n", __location__));
679 torture_comment(tctx, "testing cancel by ulogoff\n");
680 fname = BASEDIR "\\test_ulogoff.txt";
681 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
682 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
683 "Failed to reopen %s - %s\n",
684 fname, smbcli_errstr(tree)));
686 io.lockx.level = RAW_LOCK_LOCKX;
687 io.lockx.in.file.fnum = fnum;
688 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
689 io.lockx.in.timeout = 0;
690 io.lockx.in.ulock_cnt = 0;
691 io.lockx.in.lock_cnt = 1;
692 lock[0].pid = session->pid;
693 lock[0].offset = 100;
694 lock[0].count = 10;
695 io.lockx.in.locks = &lock[0];
696 status = smb_raw_lock(tree, &io);
697 CHECK_STATUS(status, NT_STATUS_OK);
699 io.lockx.in.ulock_cnt = 0;
700 io.lockx.in.lock_cnt = 1;
701 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
702 io.lockx.in.timeout = 0;
703 status = smb_raw_lock(tree, &io);
704 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
706 io.lockx.in.timeout = 10000;
707 t = time(NULL);
708 req = smb_raw_lock_send(tree, &io);
709 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
710 "Failed to setup timed lock (%s)\n", __location__));
712 status = smb_raw_ulogoff(session);
713 CHECK_STATUS(status, NT_STATUS_OK);
715 status = smbcli_request_simple_recv(req);
716 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
717 torture_result(tctx, TORTURE_FAIL,
718 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
719 nt_errstr(status));
720 smb_tree_disconnect(tree);
721 smb_raw_exit(session);
722 goto done;
724 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
726 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
727 "lock cancel by ulogoff was not immediate (%s)\n", __location__));
729 torture_comment(tctx, "testing cancel by tdis\n");
730 tree->session = cli->session;
732 fname = BASEDIR "\\test_tdis.txt";
733 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
734 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
735 "Failed to reopen %s - %s\n",
736 fname, smbcli_errstr(tree)));
738 io.lockx.level = RAW_LOCK_LOCKX;
739 io.lockx.in.file.fnum = fnum;
740 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
741 io.lockx.in.timeout = 0;
742 io.lockx.in.ulock_cnt = 0;
743 io.lockx.in.lock_cnt = 1;
744 lock[0].pid = cli->session->pid;
745 lock[0].offset = 100;
746 lock[0].count = 10;
747 io.lockx.in.locks = &lock[0];
748 status = smb_raw_lock(tree, &io);
749 CHECK_STATUS(status, NT_STATUS_OK);
751 status = smb_raw_lock(tree, &io);
752 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
754 io.lockx.in.timeout = 10000;
755 t = time(NULL);
756 req = smb_raw_lock_send(tree, &io);
757 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
758 "Failed to setup timed lock (%s)\n", __location__));
760 status = smb_tree_disconnect(tree);
761 CHECK_STATUS(status, NT_STATUS_OK);
763 status = smbcli_request_simple_recv(req);
764 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
766 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
767 "lock cancel by tdis was not immediate (%s)\n", __location__));
769 done:
770 smb_raw_exit(cli->session);
771 smbcli_deltree(cli->tree, BASEDIR);
772 return ret;
776 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
778 static bool test_errorcode(struct torture_context *tctx,
779 struct smbcli_state *cli)
781 union smb_lock io;
782 union smb_open op;
783 struct smb_lock_entry lock[2];
784 NTSTATUS status;
785 bool ret = true;
786 int fnum, fnum2;
787 const char *fname;
788 struct smbcli_request *req;
789 time_t start;
790 int t;
792 if (!torture_setup_dir(cli, BASEDIR)) {
793 return false;
796 torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
798 torture_comment(tctx, "testing with timeout = 0\n");
799 fname = BASEDIR "\\test0.txt";
800 t = 0;
803 * the first run is with t = 0,
804 * the second with t > 0 (=1)
806 next_run:
808 * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
809 * this demonstrates that the cache is per fnum
811 op.openx.level = RAW_OPEN_OPENX;
812 op.openx.in.fname = fname;
813 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
814 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
815 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
816 op.openx.in.search_attrs = 0;
817 op.openx.in.file_attrs = 0;
818 op.openx.in.write_time = 0;
819 op.openx.in.size = 0;
820 op.openx.in.timeout = 0;
822 status = smb_raw_open(cli->tree, tctx, &op);
823 CHECK_STATUS(status, NT_STATUS_OK);
824 fnum = op.openx.out.file.fnum;
826 status = smb_raw_open(cli->tree, tctx, &op);
827 CHECK_STATUS(status, NT_STATUS_OK);
828 fnum2 = op.openx.out.file.fnum;
830 io.lockx.level = RAW_LOCK_LOCKX;
831 io.lockx.in.file.fnum = fnum;
832 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
833 io.lockx.in.timeout = t;
834 io.lockx.in.ulock_cnt = 0;
835 io.lockx.in.lock_cnt = 1;
836 lock[0].pid = cli->session->pid;
837 lock[0].offset = 100;
838 lock[0].count = 10;
839 io.lockx.in.locks = &lock[0];
840 status = smb_raw_lock(cli->tree, &io);
841 CHECK_STATUS(status, NT_STATUS_OK);
844 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
845 * this also demonstrates that the error code cache is per file handle
846 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
848 io.lockx.in.file.fnum = fnum2;
849 status = smb_raw_lock(cli->tree, &io);
850 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
852 io.lockx.in.file.fnum = fnum;
853 status = smb_raw_lock(cli->tree, &io);
854 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
856 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
857 io.lockx.in.file.fnum = fnum;
858 status = smb_raw_lock(cli->tree, &io);
859 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
861 io.lockx.in.file.fnum = fnum2;
862 status = smb_raw_lock(cli->tree, &io);
863 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
865 io.lockx.in.file.fnum = fnum;
866 status = smb_raw_lock(cli->tree, &io);
867 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
869 io.lockx.in.file.fnum = fnum2;
870 status = smb_raw_lock(cli->tree, &io);
871 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
873 /* demonstrate that the smbpid doesn't matter */
874 lock[0].pid++;
875 io.lockx.in.file.fnum = fnum;
876 status = smb_raw_lock(cli->tree, &io);
877 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
879 io.lockx.in.file.fnum = fnum2;
880 status = smb_raw_lock(cli->tree, &io);
881 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
882 lock[0].pid--;
885 * demonstrate the a successful lock with count = 0 and the same offset,
886 * doesn't reset the error cache
888 lock[0].offset = 100;
889 lock[0].count = 0;
890 io.lockx.in.file.fnum = fnum;
891 status = smb_raw_lock(cli->tree, &io);
892 CHECK_STATUS(status, NT_STATUS_OK);
894 io.lockx.in.file.fnum = fnum2;
895 status = smb_raw_lock(cli->tree, &io);
896 CHECK_STATUS(status, NT_STATUS_OK);
898 lock[0].offset = 100;
899 lock[0].count = 10;
900 io.lockx.in.file.fnum = fnum;
901 status = smb_raw_lock(cli->tree, &io);
902 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
904 io.lockx.in.file.fnum = fnum2;
905 status = smb_raw_lock(cli->tree, &io);
906 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
909 * demonstrate the a successful lock with count = 0 and outside the locked range,
910 * doesn't reset the error cache
912 lock[0].offset = 110;
913 lock[0].count = 0;
914 io.lockx.in.file.fnum = fnum;
915 status = smb_raw_lock(cli->tree, &io);
916 CHECK_STATUS(status, NT_STATUS_OK);
918 io.lockx.in.file.fnum = fnum2;
919 status = smb_raw_lock(cli->tree, &io);
920 CHECK_STATUS(status, NT_STATUS_OK);
922 lock[0].offset = 100;
923 lock[0].count = 10;
924 io.lockx.in.file.fnum = fnum;
925 status = smb_raw_lock(cli->tree, &io);
926 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
928 io.lockx.in.file.fnum = fnum2;
929 status = smb_raw_lock(cli->tree, &io);
930 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
932 lock[0].offset = 99;
933 lock[0].count = 0;
934 io.lockx.in.file.fnum = fnum;
935 status = smb_raw_lock(cli->tree, &io);
936 CHECK_STATUS(status, NT_STATUS_OK);
938 io.lockx.in.file.fnum = fnum2;
939 status = smb_raw_lock(cli->tree, &io);
940 CHECK_STATUS(status, NT_STATUS_OK);
942 lock[0].offset = 100;
943 lock[0].count = 10;
944 io.lockx.in.file.fnum = fnum;
945 status = smb_raw_lock(cli->tree, &io);
946 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
948 io.lockx.in.file.fnum = fnum2;
949 status = smb_raw_lock(cli->tree, &io);
950 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
952 /* demonstrate that a changing count doesn't reset the error cache */
953 lock[0].offset = 100;
954 lock[0].count = 5;
955 io.lockx.in.file.fnum = fnum;
956 status = smb_raw_lock(cli->tree, &io);
957 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
959 io.lockx.in.file.fnum = fnum2;
960 status = smb_raw_lock(cli->tree, &io);
961 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
963 lock[0].offset = 100;
964 lock[0].count = 15;
965 io.lockx.in.file.fnum = fnum;
966 status = smb_raw_lock(cli->tree, &io);
967 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
969 io.lockx.in.file.fnum = fnum2;
970 status = smb_raw_lock(cli->tree, &io);
971 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
974 * demonstrate the a lock with count = 0 and inside the locked range,
975 * fails and resets the error cache
977 lock[0].offset = 101;
978 lock[0].count = 0;
979 io.lockx.in.file.fnum = fnum;
980 status = smb_raw_lock(cli->tree, &io);
981 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
982 status = smb_raw_lock(cli->tree, &io);
983 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
985 io.lockx.in.file.fnum = fnum2;
986 status = smb_raw_lock(cli->tree, &io);
987 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
988 status = smb_raw_lock(cli->tree, &io);
989 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
991 lock[0].offset = 100;
992 lock[0].count = 10;
993 io.lockx.in.file.fnum = fnum;
994 status = smb_raw_lock(cli->tree, &io);
995 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
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, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1002 status = smb_raw_lock(cli->tree, &io);
1003 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1005 /* demonstrate the a changing offset, resets the error cache */
1006 lock[0].offset = 105;
1007 lock[0].count = 10;
1008 io.lockx.in.file.fnum = fnum;
1009 status = smb_raw_lock(cli->tree, &io);
1010 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1011 status = smb_raw_lock(cli->tree, &io);
1012 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1014 io.lockx.in.file.fnum = fnum2;
1015 status = smb_raw_lock(cli->tree, &io);
1016 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1017 status = smb_raw_lock(cli->tree, &io);
1018 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1020 lock[0].offset = 100;
1021 lock[0].count = 10;
1022 io.lockx.in.file.fnum = fnum;
1023 status = smb_raw_lock(cli->tree, &io);
1024 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1025 status = smb_raw_lock(cli->tree, &io);
1026 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1028 io.lockx.in.file.fnum = fnum2;
1029 status = smb_raw_lock(cli->tree, &io);
1030 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1031 status = smb_raw_lock(cli->tree, &io);
1032 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1034 lock[0].offset = 95;
1035 lock[0].count = 9;
1036 io.lockx.in.file.fnum = fnum;
1037 status = smb_raw_lock(cli->tree, &io);
1038 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1039 status = smb_raw_lock(cli->tree, &io);
1040 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1042 io.lockx.in.file.fnum = fnum2;
1043 status = smb_raw_lock(cli->tree, &io);
1044 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1045 status = smb_raw_lock(cli->tree, &io);
1046 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1048 lock[0].offset = 100;
1049 lock[0].count = 10;
1050 io.lockx.in.file.fnum = fnum;
1051 status = smb_raw_lock(cli->tree, &io);
1052 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1053 status = smb_raw_lock(cli->tree, &io);
1054 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1056 io.lockx.in.file.fnum = fnum2;
1057 status = smb_raw_lock(cli->tree, &io);
1058 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1059 status = smb_raw_lock(cli->tree, &io);
1060 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1063 * demonstrate the a successful lock in a different range,
1064 * doesn't reset the cache, the failing lock on the 2nd handle
1065 * resets the resets the cache
1067 lock[0].offset = 120;
1068 lock[0].count = 15;
1069 io.lockx.in.file.fnum = fnum;
1070 status = smb_raw_lock(cli->tree, &io);
1071 CHECK_STATUS(status, NT_STATUS_OK);
1073 io.lockx.in.file.fnum = fnum2;
1074 status = smb_raw_lock(cli->tree, &io);
1075 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1077 lock[0].offset = 100;
1078 lock[0].count = 10;
1079 io.lockx.in.file.fnum = fnum;
1080 status = smb_raw_lock(cli->tree, &io);
1081 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
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, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1088 status = smb_raw_lock(cli->tree, &io);
1089 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1091 /* end of the loop */
1092 if (t == 0) {
1093 smb_raw_exit(cli->session);
1094 torture_comment(tctx, "testing with timeout > 0 (=1)\n");
1095 fname = BASEDIR "\\test1.txt";
1096 t = 1;
1097 goto next_run;
1101 * the following 3 test sections demonstrate that
1102 * the cache is only set when the error is reported
1103 * to the client (after the timeout went by)
1105 smb_raw_exit(cli->session);
1106 torture_comment(tctx, "testing a conflict while a lock is pending\n");
1107 fname = BASEDIR "\\test2.txt";
1108 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1109 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1110 "Failed to reopen %s - %s\n",
1111 fname, smbcli_errstr(cli->tree)));
1113 io.lockx.level = RAW_LOCK_LOCKX;
1114 io.lockx.in.file.fnum = fnum;
1115 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1116 io.lockx.in.timeout = 0;
1117 io.lockx.in.ulock_cnt = 0;
1118 io.lockx.in.lock_cnt = 1;
1119 lock[0].pid = cli->session->pid;
1120 lock[0].offset = 100;
1121 lock[0].count = 10;
1122 io.lockx.in.locks = &lock[0];
1123 status = smb_raw_lock(cli->tree, &io);
1124 CHECK_STATUS(status, NT_STATUS_OK);
1126 start = time(NULL);
1127 io.lockx.in.timeout = 1000;
1128 req = smb_raw_lock_send(cli->tree, &io);
1129 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1130 "Failed to setup timed lock (%s)\n", __location__));
1132 io.lockx.in.timeout = 0;
1133 lock[0].offset = 105;
1134 lock[0].count = 10;
1135 status = smb_raw_lock(cli->tree, &io);
1136 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1138 status = smbcli_request_simple_recv(req);
1139 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1141 status = smb_raw_lock(cli->tree, &io);
1142 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1144 torture_assert(tctx,!(time(NULL) < start+1), talloc_asprintf(tctx,
1145 "lock comes back to early (%s)\n", __location__));
1147 smbcli_close(cli->tree, fnum);
1148 fname = BASEDIR "\\test3.txt";
1149 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1150 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1151 "Failed to reopen %s - %s\n",
1152 fname, smbcli_errstr(cli->tree)));
1154 io.lockx.level = RAW_LOCK_LOCKX;
1155 io.lockx.in.file.fnum = fnum;
1156 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1157 io.lockx.in.timeout = 0;
1158 io.lockx.in.ulock_cnt = 0;
1159 io.lockx.in.lock_cnt = 1;
1160 lock[0].pid = cli->session->pid;
1161 lock[0].offset = 100;
1162 lock[0].count = 10;
1163 io.lockx.in.locks = &lock[0];
1164 status = smb_raw_lock(cli->tree, &io);
1165 CHECK_STATUS(status, NT_STATUS_OK);
1167 start = time(NULL);
1168 io.lockx.in.timeout = 1000;
1169 req = smb_raw_lock_send(cli->tree, &io);
1170 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1171 "Failed to setup timed lock (%s)\n", __location__));
1173 io.lockx.in.timeout = 0;
1174 lock[0].offset = 105;
1175 lock[0].count = 10;
1176 status = smb_raw_lock(cli->tree, &io);
1177 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1179 status = smbcli_request_simple_recv(req);
1180 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1182 lock[0].offset = 100;
1183 lock[0].count = 10;
1184 status = smb_raw_lock(cli->tree, &io);
1185 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1187 torture_assert(tctx,!(time(NULL) < start+1), talloc_asprintf(tctx,
1188 "lock comes back to early (%s)\n", __location__));
1190 smbcli_close(cli->tree, fnum);
1191 fname = BASEDIR "\\test4.txt";
1192 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1193 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1194 "Failed to reopen %s - %s\n",
1195 fname, smbcli_errstr(cli->tree)));
1197 io.lockx.level = RAW_LOCK_LOCKX;
1198 io.lockx.in.file.fnum = fnum;
1199 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1200 io.lockx.in.timeout = 0;
1201 io.lockx.in.ulock_cnt = 0;
1202 io.lockx.in.lock_cnt = 1;
1203 lock[0].pid = cli->session->pid;
1204 lock[0].offset = 100;
1205 lock[0].count = 10;
1206 io.lockx.in.locks = &lock[0];
1207 status = smb_raw_lock(cli->tree, &io);
1208 CHECK_STATUS(status, NT_STATUS_OK);
1210 start = time(NULL);
1211 io.lockx.in.timeout = 1000;
1212 req = smb_raw_lock_send(cli->tree, &io);
1213 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1214 "Failed to setup timed lock (%s)\n", __location__));
1216 io.lockx.in.timeout = 0;
1217 status = smb_raw_lock(cli->tree, &io);
1218 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1220 status = smbcli_request_simple_recv(req);
1221 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1223 status = smb_raw_lock(cli->tree, &io);
1224 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1226 torture_assert(tctx,!(time(NULL) < start+1), talloc_asprintf(tctx,
1227 "lock comes back to early (%s)\n", __location__));
1229 done:
1230 smb_raw_exit(cli->session);
1231 smbcli_deltree(cli->tree, BASEDIR);
1232 return ret;
1237 test LOCKING_ANDX_CHANGE_LOCKTYPE
1239 static bool test_changetype(struct torture_context *tctx,
1240 struct smbcli_state *cli)
1242 union smb_lock io;
1243 struct smb_lock_entry lock[2];
1244 NTSTATUS status;
1245 bool ret = true;
1246 int fnum;
1247 uint8_t c = 0;
1248 const char *fname = BASEDIR "\\test.txt";
1250 if (!torture_setup_dir(cli, BASEDIR)) {
1251 return false;
1254 torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1255 io.generic.level = RAW_LOCK_LOCKX;
1257 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1258 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1259 "Failed to create %s - %s\n",
1260 fname, smbcli_errstr(cli->tree)));
1262 io.lockx.level = RAW_LOCK_LOCKX;
1263 io.lockx.in.file.fnum = fnum;
1264 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1265 io.lockx.in.timeout = 0;
1266 io.lockx.in.ulock_cnt = 0;
1267 io.lockx.in.lock_cnt = 1;
1268 lock[0].pid = cli->session->pid;
1269 lock[0].offset = 100;
1270 lock[0].count = 10;
1271 io.lockx.in.locks = &lock[0];
1272 status = smb_raw_lock(cli->tree, &io);
1273 CHECK_STATUS(status, NT_STATUS_OK);
1275 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1276 torture_result(tctx, TORTURE_FAIL,
1277 "allowed write on read locked region (%s)\n", __location__);
1278 ret = false;
1279 goto done;
1282 /* windows server don't seem to support this */
1283 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1284 status = smb_raw_lock(cli->tree, &io);
1285 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1287 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1288 torture_result(tctx, TORTURE_FAIL,
1289 "allowed write after lock change (%s)\n", __location__);
1290 ret = false;
1291 goto done;
1294 done:
1295 smbcli_close(cli->tree, fnum);
1296 smb_raw_exit(cli->session);
1297 smbcli_deltree(cli->tree, BASEDIR);
1298 return ret;
1301 struct double_lock_test {
1302 struct smb_lock_entry lock1;
1303 struct smb_lock_entry lock2;
1304 NTSTATUS exp_status;
1308 * Tests zero byte locks.
1310 struct double_lock_test zero_byte_tests[] = {
1311 /* {pid, offset, count}, {pid, offset, count}, status */
1313 /** First, takes a zero byte lock at offset 10. Then:
1314 * - Taking 0 byte lock at 10 should succeed.
1315 * - Taking 1 byte locks at 9,10,11 should succeed.
1316 * - Taking 2 byte lock at 9 should fail.
1317 * - Taking 2 byte lock at 10 should succeed.
1318 * - Taking 3 byte lock at 9 should fail.
1320 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1321 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
1322 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1323 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1324 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
1325 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1326 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
1328 /** Same, but opposite order. */
1329 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1330 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
1331 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1332 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1333 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1334 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1335 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1337 /** Zero zero case. */
1338 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
1341 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
1343 union smb_lock io;
1344 struct smb_lock_entry zerozero;
1345 NTSTATUS status;
1346 bool ret = true;
1347 int fnum, i;
1348 const char *fname = BASEDIR "\\zero.txt";
1350 torture_comment(tctx, "Testing zero length byte range locks:\n");
1352 if (!torture_setup_dir(cli, BASEDIR)) {
1353 return false;
1356 io.generic.level = RAW_LOCK_LOCKX;
1358 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1359 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1360 "Failed to create %s - %s\n",
1361 fname, smbcli_errstr(cli->tree)));
1363 /* Setup initial parameters */
1364 io.lockx.level = RAW_LOCK_LOCKX;
1365 io.lockx.in.file.fnum = fnum;
1366 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1367 io.lockx.in.timeout = 0;
1369 /* Try every combination of locks in zero_byte_tests. The first lock is
1370 * assumed to succeed. The second lock may contend, depending on the
1371 * expected status. */
1372 for (i = 0;
1373 i < sizeof(zero_byte_tests) / sizeof(struct double_lock_test);
1374 i++) {
1375 torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1376 zero_byte_tests[i].lock1.pid,
1377 zero_byte_tests[i].lock1.offset,
1378 zero_byte_tests[i].lock1.count,
1379 zero_byte_tests[i].lock2.pid,
1380 zero_byte_tests[i].lock2.offset,
1381 zero_byte_tests[i].lock2.count,
1382 nt_errstr(zero_byte_tests[i].exp_status));
1384 /* Lock both locks. */
1385 io.lockx.in.ulock_cnt = 0;
1386 io.lockx.in.lock_cnt = 1;
1388 io.lockx.in.locks = &zero_byte_tests[i].lock1;
1389 status = smb_raw_lock(cli->tree, &io);
1390 CHECK_STATUS(status, NT_STATUS_OK);
1392 io.lockx.in.locks = &zero_byte_tests[i].lock2;
1393 status = smb_raw_lock(cli->tree, &io);
1395 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1396 NT_STATUS_LOCK_NOT_GRANTED)) {
1397 /* Allow either of the failure messages and keep going
1398 * if we see the wrong status. */
1399 CHECK_STATUS_OR_CONT(status,
1400 NT_STATUS_LOCK_NOT_GRANTED,
1401 NT_STATUS_FILE_LOCK_CONFLICT);
1403 } else {
1404 CHECK_STATUS_CONT(status,
1405 zero_byte_tests[i].exp_status);
1408 /* Unlock both locks. */
1409 io.lockx.in.ulock_cnt = 1;
1410 io.lockx.in.lock_cnt = 0;
1412 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1413 status = smb_raw_lock(cli->tree, &io);
1414 CHECK_STATUS(status, NT_STATUS_OK);
1417 io.lockx.in.locks = &zero_byte_tests[i].lock1;
1418 status = smb_raw_lock(cli->tree, &io);
1419 CHECK_STATUS(status, NT_STATUS_OK);
1422 done:
1423 smbcli_close(cli->tree, fnum);
1424 smb_raw_exit(cli->session);
1425 smbcli_deltree(cli->tree, BASEDIR);
1426 return ret;
1429 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1431 union smb_lock io;
1432 NTSTATUS status;
1433 bool ret = true;
1434 int fnum1, fnum2;
1435 const char *fname = BASEDIR "\\unlock.txt";
1436 struct smb_lock_entry lock1;
1437 struct smb_lock_entry lock2;
1439 torture_comment(tctx, "Testing LOCKX unlock:\n");
1441 if (!torture_setup_dir(cli, BASEDIR)) {
1442 return false;
1445 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1446 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1447 "Failed to create %s - %s\n",
1448 fname, smbcli_errstr(cli->tree)));
1450 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1451 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
1452 "Failed to create %s - %s\n",
1453 fname, smbcli_errstr(cli->tree)));
1455 /* Setup initial parameters */
1456 io.lockx.level = RAW_LOCK_LOCKX;
1457 io.lockx.in.timeout = 0;
1459 lock1.pid = cli->session->pid;
1460 lock1.offset = 0;
1461 lock1.count = 10;
1462 lock2.pid = cli->session->pid - 1;
1463 lock2.offset = 0;
1464 lock2.count = 10;
1467 * Take exclusive lock, then unlock it with a shared-unlock call.
1469 torture_comment(tctx, " taking exclusive lock.\n");
1470 io.lockx.in.ulock_cnt = 0;
1471 io.lockx.in.lock_cnt = 1;
1472 io.lockx.in.mode = 0;
1473 io.lockx.in.file.fnum = fnum1;
1474 io.lockx.in.locks = &lock1;
1475 status = smb_raw_lock(cli->tree, &io);
1476 CHECK_STATUS(status, NT_STATUS_OK);
1478 torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
1479 io.lockx.in.ulock_cnt = 1;
1480 io.lockx.in.lock_cnt = 0;
1481 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1482 io.lockx.in.file.fnum = fnum1;
1483 io.lockx.in.locks = &lock1;
1484 status = smb_raw_lock(cli->tree, &io);
1485 CHECK_STATUS(status, NT_STATUS_OK);
1487 torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
1488 io.lockx.in.ulock_cnt = 0;
1489 io.lockx.in.lock_cnt = 1;
1490 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1491 io.lockx.in.file.fnum = fnum2;
1492 io.lockx.in.locks = &lock2;
1493 status = smb_raw_lock(cli->tree, &io);
1494 CHECK_STATUS(status, NT_STATUS_OK);
1497 * Unlock a shared lock with an exclusive-unlock call.
1499 torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
1500 io.lockx.in.ulock_cnt = 1;
1501 io.lockx.in.lock_cnt = 0;
1502 io.lockx.in.mode = 0;
1503 io.lockx.in.file.fnum = fnum2;
1504 io.lockx.in.locks = &lock2;
1505 status = smb_raw_lock(cli->tree, &io);
1506 CHECK_STATUS(status, NT_STATUS_OK);
1508 torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
1509 io.lockx.in.ulock_cnt = 0;
1510 io.lockx.in.lock_cnt = 1;
1511 io.lockx.in.mode = 0;
1512 io.lockx.in.file.fnum = fnum1;
1513 io.lockx.in.locks = &lock1;
1514 status = smb_raw_lock(cli->tree, &io);
1515 CHECK_STATUS(status, NT_STATUS_OK);
1517 /* cleanup */
1518 io.lockx.in.ulock_cnt = 1;
1519 io.lockx.in.lock_cnt = 0;
1520 status = smb_raw_lock(cli->tree, &io);
1521 CHECK_STATUS(status, NT_STATUS_OK);
1524 * Test unlocking of 0-byte locks.
1527 torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
1528 "always unlocks the exclusive first.\n");
1529 lock1.pid = cli->session->pid;
1530 lock1.offset = 10;
1531 lock1.count = 0;
1532 lock2.pid = cli->session->pid;
1533 lock2.offset = 5;
1534 lock2.count = 10;
1535 io.lockx.in.ulock_cnt = 0;
1536 io.lockx.in.lock_cnt = 1;
1537 io.lockx.in.file.fnum = fnum1;
1538 io.lockx.in.locks = &lock1;
1540 /* lock 0-byte shared
1541 * Note: Order of the shared/exclusive locks doesn't matter. */
1542 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1543 status = smb_raw_lock(cli->tree, &io);
1544 CHECK_STATUS(status, NT_STATUS_OK);
1546 /* lock 0-byte exclusive */
1547 io.lockx.in.mode = 0;
1548 status = smb_raw_lock(cli->tree, &io);
1549 CHECK_STATUS(status, NT_STATUS_OK);
1551 /* test contention */
1552 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1553 io.lockx.in.locks = &lock2;
1554 io.lockx.in.file.fnum = fnum2;
1555 status = smb_raw_lock(cli->tree, &io);
1556 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1557 NT_STATUS_FILE_LOCK_CONFLICT);
1559 /* unlock */
1560 io.lockx.in.ulock_cnt = 1;
1561 io.lockx.in.lock_cnt = 0;
1562 io.lockx.in.file.fnum = fnum1;
1563 io.lockx.in.locks = &lock1;
1564 status = smb_raw_lock(cli->tree, &io);
1565 CHECK_STATUS(status, NT_STATUS_OK);
1567 /* test - can we take a shared lock? */
1568 io.lockx.in.ulock_cnt = 0;
1569 io.lockx.in.lock_cnt = 1;
1570 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1571 io.lockx.in.file.fnum = fnum2;
1572 io.lockx.in.locks = &lock2;
1573 status = smb_raw_lock(cli->tree, &io);
1575 /* XXX Samba will fail this test. This is temporary(because this isn't
1576 * new to Win7, it succeeds in WinXP too), until I can come to a
1577 * resolution as to whether Samba should support this or not. There is
1578 * code to preference unlocking exclusive locks before shared locks,
1579 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1580 if (TARGET_IS_WIN7(tctx)) {
1581 CHECK_STATUS(status, NT_STATUS_OK);
1582 } else if (TARGET_IS_SAMBA4(tctx)) {
1583 CHECK_STATUS(status, NT_STATUS_OK);
1584 } else {
1585 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1586 NT_STATUS_FILE_LOCK_CONFLICT);
1589 /* cleanup */
1590 io.lockx.in.ulock_cnt = 1;
1591 io.lockx.in.lock_cnt = 0;
1592 status = smb_raw_lock(cli->tree, &io);
1594 /* XXX Same as above. */
1595 if (TARGET_IS_WIN7(tctx)) {
1596 CHECK_STATUS(status, NT_STATUS_OK);
1597 } else if (TARGET_IS_SAMBA4(tctx)) {
1598 CHECK_STATUS(status, NT_STATUS_OK);
1599 } else {
1600 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1603 io.lockx.in.file.fnum = fnum1;
1604 io.lockx.in.locks = &lock1;
1605 status = smb_raw_lock(cli->tree, &io);
1606 CHECK_STATUS(status, NT_STATUS_OK);
1608 done:
1609 smbcli_close(cli->tree, fnum1);
1610 smbcli_close(cli->tree, fnum2);
1611 smb_raw_exit(cli->session);
1612 smbcli_deltree(cli->tree, BASEDIR);
1613 return ret;
1616 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1618 union smb_lock io;
1619 NTSTATUS status;
1620 bool ret = true;
1621 int fnum1;
1622 const char *fname = BASEDIR "\\unlock_multiple.txt";
1623 struct smb_lock_entry lock1;
1624 struct smb_lock_entry lock2;
1625 struct smb_lock_entry locks[2];
1627 torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
1629 if (!torture_setup_dir(cli, BASEDIR)) {
1630 return false;
1633 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1634 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1635 "Failed to create %s - %s\n",
1636 fname, smbcli_errstr(cli->tree)));
1638 /* Setup initial parameters */
1639 io.lockx.level = RAW_LOCK_LOCKX;
1640 io.lockx.in.timeout = 0;
1642 lock1.pid = cli->session->pid;
1643 lock1.offset = 0;
1644 lock1.count = 10;
1645 lock2.pid = cli->session->pid;
1646 lock2.offset = 10;
1647 lock2.count = 10;
1649 locks[0] = lock1;
1650 locks[1] = lock2;
1652 io.lockx.in.file.fnum = fnum1;
1653 io.lockx.in.mode = 0; /* exclusive */
1655 /** Test1: Take second lock, but not first. */
1656 torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
1657 "unlocked. \n");
1659 io.lockx.in.ulock_cnt = 0;
1660 io.lockx.in.lock_cnt = 1;
1661 io.lockx.in.locks = &lock2;
1662 status = smb_raw_lock(cli->tree, &io);
1663 CHECK_STATUS(status, NT_STATUS_OK);
1665 /* Try to unlock both locks. */
1666 io.lockx.in.ulock_cnt = 2;
1667 io.lockx.in.lock_cnt = 0;
1668 io.lockx.in.locks = locks;
1670 status = smb_raw_lock(cli->tree, &io);
1671 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1673 /* Second lock should not be unlocked. */
1674 io.lockx.in.ulock_cnt = 0;
1675 io.lockx.in.lock_cnt = 1;
1676 io.lockx.in.locks = &lock2;
1677 status = smb_raw_lock(cli->tree, &io);
1678 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1680 /* cleanup */
1681 io.lockx.in.ulock_cnt = 1;
1682 io.lockx.in.lock_cnt = 0;
1683 io.lockx.in.locks = &lock2;
1684 status = smb_raw_lock(cli->tree, &io);
1685 CHECK_STATUS(status, NT_STATUS_OK);
1687 /** Test2: Take first lock, but not second. */
1688 torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
1689 "unlocked.\n");
1691 io.lockx.in.ulock_cnt = 0;
1692 io.lockx.in.lock_cnt = 1;
1693 io.lockx.in.locks = &lock1;
1694 status = smb_raw_lock(cli->tree, &io);
1695 CHECK_STATUS(status, NT_STATUS_OK);
1697 /* Try to unlock both locks. */
1698 io.lockx.in.ulock_cnt = 2;
1699 io.lockx.in.lock_cnt = 0;
1700 io.lockx.in.locks = locks;
1702 status = smb_raw_lock(cli->tree, &io);
1703 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1705 /* First lock should be unlocked. */
1706 io.lockx.in.ulock_cnt = 0;
1707 io.lockx.in.lock_cnt = 1;
1708 io.lockx.in.locks = &lock1;
1709 status = smb_raw_lock(cli->tree, &io);
1710 CHECK_STATUS(status, NT_STATUS_OK);
1712 /* cleanup */
1713 io.lockx.in.ulock_cnt = 1;
1714 io.lockx.in.lock_cnt = 0;
1715 io.lockx.in.locks = &lock1;
1716 status = smb_raw_lock(cli->tree, &io);
1717 CHECK_STATUS(status, NT_STATUS_OK);
1719 done:
1720 smbcli_close(cli->tree, fnum1);
1721 smb_raw_exit(cli->session);
1722 smbcli_deltree(cli->tree, BASEDIR);
1723 return ret;
1727 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1728 * - stacking an exclusive on top of shared fails
1729 * - stacking two exclusives fail
1731 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
1733 union smb_lock io;
1734 NTSTATUS status;
1735 bool ret = true;
1736 int fnum1;
1737 const char *fname = BASEDIR "\\stacking.txt";
1738 struct smb_lock_entry lock1;
1739 struct smb_lock_entry lock2;
1741 torture_comment(tctx, "Testing stacking:\n");
1743 if (!torture_setup_dir(cli, BASEDIR)) {
1744 return false;
1747 io.generic.level = RAW_LOCK_LOCKX;
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;
1759 lock1.offset = 0;
1760 lock1.count = 10;
1761 lock2.pid = cli->session->pid - 1;
1762 lock2.offset = 0;
1763 lock2.count = 10;
1766 * Try to take a shared lock, then stack an exclusive.
1768 torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
1769 io.lockx.in.file.fnum = fnum1;
1770 io.lockx.in.locks = &lock1;
1772 io.lockx.in.ulock_cnt = 0;
1773 io.lockx.in.lock_cnt = 1;
1774 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1775 status = smb_raw_lock(cli->tree, &io);
1776 CHECK_STATUS(status, NT_STATUS_OK);
1778 io.lockx.in.ulock_cnt = 0;
1779 io.lockx.in.lock_cnt = 1;
1780 io.lockx.in.mode = 0;
1781 status = smb_raw_lock(cli->tree, &io);
1782 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1783 NT_STATUS_FILE_LOCK_CONFLICT);
1785 /* cleanup */
1786 io.lockx.in.ulock_cnt = 1;
1787 io.lockx.in.lock_cnt = 0;
1788 status = smb_raw_lock(cli->tree, &io);
1789 CHECK_STATUS(status, NT_STATUS_OK);
1792 * Prove that two exclusive locks do not stack.
1794 torture_comment(tctx, " two exclusive locks do not stack.\n");
1795 io.lockx.in.ulock_cnt = 0;
1796 io.lockx.in.lock_cnt = 1;
1797 io.lockx.in.mode = 0;
1798 status = smb_raw_lock(cli->tree, &io);
1799 CHECK_STATUS(status, NT_STATUS_OK);
1800 status = smb_raw_lock(cli->tree, &io);
1801 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1802 NT_STATUS_FILE_LOCK_CONFLICT);
1804 /* cleanup */
1805 io.lockx.in.ulock_cnt = 1;
1806 io.lockx.in.lock_cnt = 0;
1807 status = smb_raw_lock(cli->tree, &io);
1808 CHECK_STATUS(status, NT_STATUS_OK);
1810 done:
1811 smbcli_close(cli->tree, fnum1);
1812 smb_raw_exit(cli->session);
1813 smbcli_deltree(cli->tree, BASEDIR);
1814 return ret;
1818 basic testing of lock calls
1820 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
1822 struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
1824 torture_suite_add_1smb_test(suite, "lockx", test_lockx);
1825 torture_suite_add_1smb_test(suite, "lock", test_lock);
1826 torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
1827 torture_suite_add_1smb_test(suite, "async", test_async);
1828 torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
1829 torture_suite_add_1smb_test(suite, "changetype", test_changetype);
1831 torture_suite_add_1smb_test(suite, "stacking", test_stacking);
1832 torture_suite_add_1smb_test(suite, "unlock", test_unlock);
1833 torture_suite_add_1smb_test(suite, "multiple_unlock",
1834 test_multiple_unlock);
1835 torture_suite_add_1smb_test(suite, "zerobytelocks",
1836 test_zerobytelocks);
1838 return suite;