s4:torture/raw/lock - Fix "discard const" warnings by introducing "discard_const_p"s
[Samba/ekacnet.git] / source4 / torture / raw / lock.c
blob1ccba61c55a80ea5fe3188d3ba31475a39628a14
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_W2K8(_tctx) (torture_setting_bool(_tctx, "w2k8", false))
73 #define TARGET_IS_WIN7(_tctx) (torture_setting_bool(_tctx, "win7", false))
74 #define TARGET_IS_SAMBA3(_tctx) (torture_setting_bool(_tctx, "samba3", false))
75 #define TARGET_IS_SAMBA4(_tctx) (torture_setting_bool(_tctx, "samba4", false))
78 test SMBlock and SMBunlock ops
80 static bool test_lock(struct torture_context *tctx, struct smbcli_state *cli)
82 union smb_lock io;
83 NTSTATUS status;
84 bool ret = true;
85 int fnum;
86 const char *fname = BASEDIR "\\test.txt";
88 if (!torture_setup_dir(cli, BASEDIR)) {
89 return false;
92 torture_comment(tctx, "Testing RAW_LOCK_LOCK\n");
93 io.generic.level = RAW_LOCK_LOCK;
95 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
96 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
97 "Failed to create %s - %s\n",
98 fname, smbcli_errstr(cli->tree)));
100 torture_comment(tctx, "Trying 0/0 lock\n");
101 io.lock.level = RAW_LOCK_LOCK;
102 io.lock.in.file.fnum = fnum;
103 io.lock.in.count = 0;
104 io.lock.in.offset = 0;
105 status = smb_raw_lock(cli->tree, &io);
106 CHECK_STATUS(status, NT_STATUS_OK);
107 cli->session->pid++;
108 status = smb_raw_lock(cli->tree, &io);
109 CHECK_STATUS(status, NT_STATUS_OK);
110 cli->session->pid--;
111 io.lock.level = RAW_LOCK_UNLOCK;
112 status = smb_raw_lock(cli->tree, &io);
113 CHECK_STATUS(status, NT_STATUS_OK);
115 torture_comment(tctx, "Trying 0/1 lock\n");
116 io.lock.level = RAW_LOCK_LOCK;
117 io.lock.in.file.fnum = fnum;
118 io.lock.in.count = 1;
119 io.lock.in.offset = 0;
120 status = smb_raw_lock(cli->tree, &io);
121 CHECK_STATUS(status, NT_STATUS_OK);
122 cli->session->pid++;
123 status = smb_raw_lock(cli->tree, &io);
124 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
125 cli->session->pid--;
126 io.lock.level = RAW_LOCK_UNLOCK;
127 status = smb_raw_lock(cli->tree, &io);
128 CHECK_STATUS(status, NT_STATUS_OK);
129 io.lock.level = RAW_LOCK_UNLOCK;
130 status = smb_raw_lock(cli->tree, &io);
131 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
133 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
134 io.lock.level = RAW_LOCK_LOCK;
135 io.lock.in.file.fnum = fnum;
136 io.lock.in.count = 4000;
137 io.lock.in.offset = 0xEEFFFFFF;
138 status = smb_raw_lock(cli->tree, &io);
139 CHECK_STATUS(status, NT_STATUS_OK);
140 cli->session->pid++;
141 status = smb_raw_lock(cli->tree, &io);
142 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
143 cli->session->pid--;
144 io.lock.level = RAW_LOCK_UNLOCK;
145 status = smb_raw_lock(cli->tree, &io);
146 CHECK_STATUS(status, NT_STATUS_OK);
147 io.lock.level = RAW_LOCK_UNLOCK;
148 status = smb_raw_lock(cli->tree, &io);
149 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
151 torture_comment(tctx, "Trying 0xEF000000 lock\n");
152 io.lock.level = RAW_LOCK_LOCK;
153 io.lock.in.file.fnum = fnum;
154 io.lock.in.count = 4000;
155 io.lock.in.offset = 0xEEFFFFFF;
156 status = smb_raw_lock(cli->tree, &io);
157 CHECK_STATUS(status, NT_STATUS_OK);
158 cli->session->pid++;
159 status = smb_raw_lock(cli->tree, &io);
160 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
161 cli->session->pid--;
162 io.lock.level = RAW_LOCK_UNLOCK;
163 status = smb_raw_lock(cli->tree, &io);
164 CHECK_STATUS(status, NT_STATUS_OK);
165 io.lock.level = RAW_LOCK_UNLOCK;
166 status = smb_raw_lock(cli->tree, &io);
167 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
169 torture_comment(tctx, "Trying max lock\n");
170 io.lock.level = RAW_LOCK_LOCK;
171 io.lock.in.file.fnum = fnum;
172 io.lock.in.count = 4000;
173 io.lock.in.offset = 0xEF000000;
174 status = smb_raw_lock(cli->tree, &io);
175 CHECK_STATUS(status, NT_STATUS_OK);
176 cli->session->pid++;
177 status = smb_raw_lock(cli->tree, &io);
178 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
179 cli->session->pid--;
180 io.lock.level = RAW_LOCK_UNLOCK;
181 status = smb_raw_lock(cli->tree, &io);
182 CHECK_STATUS(status, NT_STATUS_OK);
183 io.lock.level = RAW_LOCK_UNLOCK;
184 status = smb_raw_lock(cli->tree, &io);
185 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
187 torture_comment(tctx, "Trying wrong pid unlock\n");
188 io.lock.level = RAW_LOCK_LOCK;
189 io.lock.in.file.fnum = fnum;
190 io.lock.in.count = 4002;
191 io.lock.in.offset = 10001;
192 status = smb_raw_lock(cli->tree, &io);
193 CHECK_STATUS(status, NT_STATUS_OK);
194 cli->session->pid++;
195 io.lock.level = RAW_LOCK_UNLOCK;
196 status = smb_raw_lock(cli->tree, &io);
197 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
198 cli->session->pid--;
199 status = smb_raw_lock(cli->tree, &io);
200 CHECK_STATUS(status, NT_STATUS_OK);
202 done:
203 smbcli_close(cli->tree, fnum);
204 smb_raw_exit(cli->session);
205 smbcli_deltree(cli->tree, BASEDIR);
206 return ret;
211 test locking&X ops
213 static bool test_lockx(struct torture_context *tctx, struct smbcli_state *cli)
215 union smb_lock io;
216 struct smb_lock_entry lock[1];
217 NTSTATUS status;
218 bool ret = true;
219 int fnum;
220 const char *fname = BASEDIR "\\test.txt";
222 if (!torture_setup_dir(cli, BASEDIR)) {
223 return false;
226 torture_comment(tctx, "Testing RAW_LOCK_LOCKX\n");
227 io.generic.level = RAW_LOCK_LOCKX;
229 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
230 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
231 "Failed to create %s - %s\n",
232 fname, smbcli_errstr(cli->tree)));
234 io.lockx.level = RAW_LOCK_LOCKX;
235 io.lockx.in.file.fnum = fnum;
236 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
237 io.lockx.in.timeout = 0;
238 io.lockx.in.ulock_cnt = 0;
239 io.lockx.in.lock_cnt = 1;
240 lock[0].pid = cli->session->pid;
241 lock[0].offset = 10;
242 lock[0].count = 1;
243 io.lockx.in.locks = &lock[0];
244 status = smb_raw_lock(cli->tree, &io);
245 CHECK_STATUS(status, NT_STATUS_OK);
248 torture_comment(tctx, "Trying 0xEEFFFFFF lock\n");
249 io.lockx.in.ulock_cnt = 0;
250 io.lockx.in.lock_cnt = 1;
251 lock[0].count = 4000;
252 lock[0].offset = 0xEEFFFFFF;
253 status = smb_raw_lock(cli->tree, &io);
254 CHECK_STATUS(status, NT_STATUS_OK);
255 lock[0].pid++;
256 status = smb_raw_lock(cli->tree, &io);
257 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
258 lock[0].pid--;
259 io.lockx.in.ulock_cnt = 1;
260 io.lockx.in.lock_cnt = 0;
261 status = smb_raw_lock(cli->tree, &io);
262 CHECK_STATUS(status, NT_STATUS_OK);
263 status = smb_raw_lock(cli->tree, &io);
264 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
266 torture_comment(tctx, "Trying 0xEF000000 lock\n");
267 io.lockx.in.ulock_cnt = 0;
268 io.lockx.in.lock_cnt = 1;
269 lock[0].count = 4000;
270 lock[0].offset = 0xEF000000;
271 status = smb_raw_lock(cli->tree, &io);
272 CHECK_STATUS(status, NT_STATUS_OK);
273 lock[0].pid++;
274 status = smb_raw_lock(cli->tree, &io);
275 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
276 lock[0].pid--;
277 io.lockx.in.ulock_cnt = 1;
278 io.lockx.in.lock_cnt = 0;
279 status = smb_raw_lock(cli->tree, &io);
280 CHECK_STATUS(status, NT_STATUS_OK);
281 status = smb_raw_lock(cli->tree, &io);
282 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
284 torture_comment(tctx, "Trying zero lock\n");
285 io.lockx.in.ulock_cnt = 0;
286 io.lockx.in.lock_cnt = 1;
287 lock[0].count = 0;
288 lock[0].offset = ~0;
289 status = smb_raw_lock(cli->tree, &io);
290 CHECK_STATUS(status, NT_STATUS_OK);
291 lock[0].pid++;
292 status = smb_raw_lock(cli->tree, &io);
293 CHECK_STATUS(status, NT_STATUS_OK);
294 lock[0].pid--;
295 io.lockx.in.ulock_cnt = 1;
296 io.lockx.in.lock_cnt = 0;
297 status = smb_raw_lock(cli->tree, &io);
298 CHECK_STATUS(status, NT_STATUS_OK);
299 status = smb_raw_lock(cli->tree, &io);
300 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
302 torture_comment(tctx, "Trying max lock\n");
303 io.lockx.in.ulock_cnt = 0;
304 io.lockx.in.lock_cnt = 1;
305 lock[0].count = 0;
306 lock[0].offset = ~0;
307 status = smb_raw_lock(cli->tree, &io);
308 CHECK_STATUS(status, NT_STATUS_OK);
309 lock[0].pid++;
310 status = smb_raw_lock(cli->tree, &io);
311 CHECK_STATUS(status, NT_STATUS_OK);
312 lock[0].pid--;
313 io.lockx.in.ulock_cnt = 1;
314 io.lockx.in.lock_cnt = 0;
315 status = smb_raw_lock(cli->tree, &io);
316 CHECK_STATUS(status, NT_STATUS_OK);
317 status = smb_raw_lock(cli->tree, &io);
318 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
320 torture_comment(tctx, "Trying 2^63\n");
321 io.lockx.in.ulock_cnt = 0;
322 io.lockx.in.lock_cnt = 1;
323 lock[0].count = 1;
324 lock[0].offset = 1;
325 lock[0].offset <<= 63;
326 status = smb_raw_lock(cli->tree, &io);
327 CHECK_STATUS(status, NT_STATUS_OK);
328 lock[0].pid++;
329 status = smb_raw_lock(cli->tree, &io);
330 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
331 lock[0].pid--;
332 io.lockx.in.ulock_cnt = 1;
333 io.lockx.in.lock_cnt = 0;
334 status = smb_raw_lock(cli->tree, &io);
335 CHECK_STATUS(status, NT_STATUS_OK);
336 status = smb_raw_lock(cli->tree, &io);
337 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
339 torture_comment(tctx, "Trying 2^63 - 1\n");
340 io.lockx.in.ulock_cnt = 0;
341 io.lockx.in.lock_cnt = 1;
342 lock[0].count = 1;
343 lock[0].offset = 1;
344 lock[0].offset <<= 63;
345 lock[0].offset--;
346 status = smb_raw_lock(cli->tree, &io);
347 CHECK_STATUS(status, NT_STATUS_OK);
348 lock[0].pid++;
349 status = smb_raw_lock(cli->tree, &io);
350 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
351 lock[0].pid--;
352 io.lockx.in.ulock_cnt = 1;
353 io.lockx.in.lock_cnt = 0;
354 status = smb_raw_lock(cli->tree, &io);
355 CHECK_STATUS(status, NT_STATUS_OK);
356 status = smb_raw_lock(cli->tree, &io);
357 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
359 torture_comment(tctx, "Trying max lock 2\n");
360 io.lockx.in.ulock_cnt = 0;
361 io.lockx.in.lock_cnt = 1;
362 lock[0].count = 1;
363 lock[0].offset = ~0;
364 status = smb_raw_lock(cli->tree, &io);
365 CHECK_STATUS(status, NT_STATUS_OK);
366 lock[0].pid++;
367 lock[0].count = 2;
368 status = smb_raw_lock(cli->tree, &io);
369 if (TARGET_IS_WIN7(tctx) || TARGET_IS_SAMBA4(tctx))
370 CHECK_STATUS(status, NT_STATUS_INVALID_LOCK_RANGE);
371 else
372 CHECK_STATUS(status, NT_STATUS_OK);
373 lock[0].pid--;
374 io.lockx.in.ulock_cnt = 1;
375 io.lockx.in.lock_cnt = 0;
376 lock[0].count = 1;
377 status = smb_raw_lock(cli->tree, &io);
379 CHECK_STATUS(status, NT_STATUS_OK);
380 status = smb_raw_lock(cli->tree, &io);
381 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
383 done:
384 smbcli_close(cli->tree, fnum);
385 smb_raw_exit(cli->session);
386 smbcli_deltree(cli->tree, BASEDIR);
387 return ret;
391 test high pid
393 static bool test_pidhigh(struct torture_context *tctx,
394 struct smbcli_state *cli)
396 union smb_lock io;
397 struct smb_lock_entry lock[1];
398 NTSTATUS status;
399 bool ret = true;
400 int fnum;
401 const char *fname = BASEDIR "\\test.txt";
402 uint8_t c = 1;
404 if (!torture_setup_dir(cli, BASEDIR)) {
405 return false;
408 torture_comment(tctx, "Testing high pid\n");
409 io.generic.level = RAW_LOCK_LOCKX;
411 cli->session->pid = 1;
413 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
414 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
415 "Failed to create %s - %s\n",
416 fname, smbcli_errstr(cli->tree)));
418 if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
419 torture_result(tctx, TORTURE_FAIL,
420 "Failed to write 1 byte - %s\n",
421 smbcli_errstr(cli->tree));
422 ret = false;
423 goto done;
426 io.lockx.level = RAW_LOCK_LOCKX;
427 io.lockx.in.file.fnum = fnum;
428 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
429 io.lockx.in.timeout = 0;
430 io.lockx.in.ulock_cnt = 0;
431 io.lockx.in.lock_cnt = 1;
432 lock[0].pid = cli->session->pid;
433 lock[0].offset = 0;
434 lock[0].count = 0xFFFFFFFF;
435 io.lockx.in.locks = &lock[0];
436 status = smb_raw_lock(cli->tree, &io);
437 CHECK_STATUS(status, NT_STATUS_OK);
439 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
440 torture_result(tctx, TORTURE_FAIL,
441 "Failed to read 1 byte - %s\n",
442 smbcli_errstr(cli->tree));
443 ret = false;
444 goto done;
447 cli->session->pid = 2;
449 if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
450 torture_result(tctx, TORTURE_FAIL,
451 "pid is incorrect handled for read with lock!\n");
452 ret = false;
453 goto done;
456 cli->session->pid = 0x10001;
458 if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
459 torture_result(tctx, TORTURE_FAIL,
460 "High pid is used on this server!\n");
461 ret = false;
462 } else {
463 torture_warning(tctx, "High pid is not used on this server (correct)\n");
466 done:
467 smbcli_close(cli->tree, fnum);
468 smb_raw_exit(cli->session);
469 smbcli_deltree(cli->tree, BASEDIR);
470 return ret;
475 test locking&X async operation
477 static bool test_async(struct torture_context *tctx,
478 struct smbcli_state *cli)
480 struct smbcli_session *session;
481 struct smb_composite_sesssetup setup;
482 struct smbcli_tree *tree;
483 union smb_tcon tcon;
484 const char *host, *share;
485 union smb_lock io;
486 struct smb_lock_entry lock[2];
487 NTSTATUS status;
488 bool ret = true;
489 int fnum;
490 const char *fname = BASEDIR "\\test.txt";
491 time_t t;
492 struct smbcli_request *req;
493 struct smbcli_session_options options;
495 if (!torture_setup_dir(cli, BASEDIR)) {
496 return false;
499 lp_smbcli_session_options(tctx->lp_ctx, &options);
501 torture_comment(tctx, "Testing LOCKING_ANDX_CANCEL_LOCK\n");
502 io.generic.level = RAW_LOCK_LOCKX;
504 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
505 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
506 "Failed to create %s - %s\n",
507 fname, smbcli_errstr(cli->tree)));
509 io.lockx.level = RAW_LOCK_LOCKX;
510 io.lockx.in.file.fnum = fnum;
511 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
512 io.lockx.in.timeout = 0;
513 io.lockx.in.ulock_cnt = 0;
514 io.lockx.in.lock_cnt = 1;
515 lock[0].pid = cli->session->pid;
516 lock[0].offset = 100;
517 lock[0].count = 10;
518 io.lockx.in.locks = &lock[0];
519 status = smb_raw_lock(cli->tree, &io);
520 CHECK_STATUS(status, NT_STATUS_OK);
522 t = time(NULL);
524 torture_comment(tctx, "testing cancel by CANCEL_LOCK\n");
526 /* setup a timed lock */
527 io.lockx.in.timeout = 10000;
528 req = smb_raw_lock_send(cli->tree, &io);
529 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
530 "Failed to setup timed lock (%s)\n", __location__));
532 /* cancel the wrong range */
533 lock[0].offset = 0;
534 io.lockx.in.timeout = 0;
535 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
536 status = smb_raw_lock(cli->tree, &io);
537 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
539 /* cancel with the wrong bits set */
540 lock[0].offset = 100;
541 io.lockx.in.timeout = 0;
542 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
543 status = smb_raw_lock(cli->tree, &io);
544 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
546 /* cancel the right range */
547 lock[0].offset = 100;
548 io.lockx.in.timeout = 0;
549 io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
550 status = smb_raw_lock(cli->tree, &io);
551 CHECK_STATUS(status, NT_STATUS_OK);
553 /* receive the failed lock request */
554 status = smbcli_request_simple_recv(req);
555 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
557 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
558 "lock cancel was not immediate (%s)\n", __location__));
560 torture_comment(tctx, "testing cancel by unlock\n");
561 io.lockx.in.ulock_cnt = 0;
562 io.lockx.in.lock_cnt = 1;
563 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
564 io.lockx.in.timeout = 0;
565 status = smb_raw_lock(cli->tree, &io);
566 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
568 io.lockx.in.timeout = 5000;
569 req = smb_raw_lock_send(cli->tree, &io);
570 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
571 "Failed to setup timed lock (%s)\n", __location__));
573 io.lockx.in.ulock_cnt = 1;
574 io.lockx.in.lock_cnt = 0;
575 status = smb_raw_lock(cli->tree, &io);
576 CHECK_STATUS(status, NT_STATUS_OK);
578 t = time(NULL);
579 status = smbcli_request_simple_recv(req);
580 CHECK_STATUS(status, NT_STATUS_OK);
582 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
583 "lock cancel by unlock was not immediate (%s) - took %d secs\n",
584 __location__, (int)(time(NULL)-t)));
586 torture_comment(tctx, "testing cancel by close\n");
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.timeout = 0;
591 status = smb_raw_lock(cli->tree, &io);
592 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
594 t = time(NULL);
595 io.lockx.in.timeout = 10000;
596 req = smb_raw_lock_send(cli->tree, &io);
597 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
598 "Failed to setup timed lock (%s)\n", __location__));
600 status = smbcli_close(cli->tree, fnum);
601 CHECK_STATUS(status, NT_STATUS_OK);
603 status = smbcli_request_simple_recv(req);
604 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
606 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
607 "lock cancel by close was not immediate (%s)\n", __location__));
609 torture_comment(tctx, "create a new sessions\n");
610 session = smbcli_session_init(cli->transport, tctx, false, options);
611 setup.in.sesskey = cli->transport->negotiate.sesskey;
612 setup.in.capabilities = cli->transport->negotiate.capabilities;
613 setup.in.workgroup = lp_workgroup(tctx->lp_ctx);
614 setup.in.credentials = cmdline_credentials;
615 setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
616 status = smb_composite_sesssetup(session, &setup);
617 CHECK_STATUS(status, NT_STATUS_OK);
618 session->vuid = setup.out.vuid;
620 torture_comment(tctx, "create new tree context\n");
621 share = torture_setting_string(tctx, "share", NULL);
622 host = torture_setting_string(tctx, "host", NULL);
623 tree = smbcli_tree_init(session, tctx, false);
624 tcon.generic.level = RAW_TCON_TCONX;
625 tcon.tconx.in.flags = 0;
626 tcon.tconx.in.password = data_blob(NULL, 0);
627 tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
628 tcon.tconx.in.device = "A:";
629 status = smb_raw_tcon(tree, tctx, &tcon);
630 CHECK_STATUS(status, NT_STATUS_OK);
631 tree->tid = tcon.tconx.out.tid;
633 torture_comment(tctx, "testing cancel by exit\n");
634 fname = BASEDIR "\\test_exit.txt";
635 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
636 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
637 "Failed to reopen %s - %s\n",
638 fname, smbcli_errstr(tree)));
640 io.lockx.level = RAW_LOCK_LOCKX;
641 io.lockx.in.file.fnum = fnum;
642 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
643 io.lockx.in.timeout = 0;
644 io.lockx.in.ulock_cnt = 0;
645 io.lockx.in.lock_cnt = 1;
646 lock[0].pid = session->pid;
647 lock[0].offset = 100;
648 lock[0].count = 10;
649 io.lockx.in.locks = &lock[0];
650 status = smb_raw_lock(tree, &io);
651 CHECK_STATUS(status, NT_STATUS_OK);
653 io.lockx.in.ulock_cnt = 0;
654 io.lockx.in.lock_cnt = 1;
655 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
656 io.lockx.in.timeout = 0;
657 status = smb_raw_lock(tree, &io);
658 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
660 io.lockx.in.timeout = 10000;
661 t = time(NULL);
662 req = smb_raw_lock_send(tree, &io);
663 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
664 "Failed to setup timed lock (%s)\n", __location__));
666 status = smb_raw_exit(session);
667 CHECK_STATUS(status, NT_STATUS_OK);
669 status = smbcli_request_simple_recv(req);
670 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
672 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
673 "lock cancel by exit was not immediate (%s)\n", __location__));
675 torture_comment(tctx, "testing cancel by ulogoff\n");
676 fname = BASEDIR "\\test_ulogoff.txt";
677 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
678 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
679 "Failed to reopen %s - %s\n",
680 fname, smbcli_errstr(tree)));
682 io.lockx.level = RAW_LOCK_LOCKX;
683 io.lockx.in.file.fnum = fnum;
684 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
685 io.lockx.in.timeout = 0;
686 io.lockx.in.ulock_cnt = 0;
687 io.lockx.in.lock_cnt = 1;
688 lock[0].pid = session->pid;
689 lock[0].offset = 100;
690 lock[0].count = 10;
691 io.lockx.in.locks = &lock[0];
692 status = smb_raw_lock(tree, &io);
693 CHECK_STATUS(status, NT_STATUS_OK);
695 io.lockx.in.ulock_cnt = 0;
696 io.lockx.in.lock_cnt = 1;
697 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
698 io.lockx.in.timeout = 0;
699 status = smb_raw_lock(tree, &io);
700 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
702 io.lockx.in.timeout = 10000;
703 t = time(NULL);
704 req = smb_raw_lock_send(tree, &io);
705 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
706 "Failed to setup timed lock (%s)\n", __location__));
708 status = smb_raw_ulogoff(session);
709 CHECK_STATUS(status, NT_STATUS_OK);
711 status = smbcli_request_simple_recv(req);
712 if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
713 torture_result(tctx, TORTURE_FAIL,
714 "lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
715 nt_errstr(status));
716 smb_tree_disconnect(tree);
717 smb_raw_exit(session);
718 goto done;
720 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
722 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
723 "lock cancel by ulogoff was not immediate (%s)\n", __location__));
725 torture_comment(tctx, "testing cancel by tdis\n");
726 tree->session = cli->session;
728 fname = BASEDIR "\\test_tdis.txt";
729 fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
730 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
731 "Failed to reopen %s - %s\n",
732 fname, smbcli_errstr(tree)));
734 io.lockx.level = RAW_LOCK_LOCKX;
735 io.lockx.in.file.fnum = fnum;
736 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
737 io.lockx.in.timeout = 0;
738 io.lockx.in.ulock_cnt = 0;
739 io.lockx.in.lock_cnt = 1;
740 lock[0].pid = cli->session->pid;
741 lock[0].offset = 100;
742 lock[0].count = 10;
743 io.lockx.in.locks = &lock[0];
744 status = smb_raw_lock(tree, &io);
745 CHECK_STATUS(status, NT_STATUS_OK);
747 status = smb_raw_lock(tree, &io);
748 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
750 io.lockx.in.timeout = 10000;
751 t = time(NULL);
752 req = smb_raw_lock_send(tree, &io);
753 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
754 "Failed to setup timed lock (%s)\n", __location__));
756 status = smb_tree_disconnect(tree);
757 CHECK_STATUS(status, NT_STATUS_OK);
759 status = smbcli_request_simple_recv(req);
760 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
762 torture_assert(tctx,!(time(NULL) > t+2), talloc_asprintf(tctx,
763 "lock cancel by tdis was not immediate (%s)\n", __location__));
765 done:
766 smb_raw_exit(cli->session);
767 smbcli_deltree(cli->tree, BASEDIR);
768 return ret;
772 test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
774 static bool test_errorcode(struct torture_context *tctx,
775 struct smbcli_state *cli)
777 union smb_lock io;
778 union smb_open op;
779 struct smb_lock_entry lock[2];
780 NTSTATUS status;
781 bool ret = true;
782 int fnum, fnum2;
783 const char *fname;
784 struct smbcli_request *req;
785 time_t start;
786 int t;
787 int delay;
789 if (!torture_setup_dir(cli, BASEDIR)) {
790 return false;
793 torture_comment(tctx, "Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
795 torture_comment(tctx, "testing with timeout = 0\n");
796 fname = BASEDIR "\\test0.txt";
797 t = 0;
800 * the first run is with t = 0,
801 * the second with t > 0 (=1)
803 next_run:
805 * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
806 * this demonstrates that the cache is per fnum
808 op.openx.level = RAW_OPEN_OPENX;
809 op.openx.in.fname = fname;
810 op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
811 op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
812 op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
813 op.openx.in.search_attrs = 0;
814 op.openx.in.file_attrs = 0;
815 op.openx.in.write_time = 0;
816 op.openx.in.size = 0;
817 op.openx.in.timeout = 0;
819 status = smb_raw_open(cli->tree, tctx, &op);
820 CHECK_STATUS(status, NT_STATUS_OK);
821 fnum = op.openx.out.file.fnum;
823 status = smb_raw_open(cli->tree, tctx, &op);
824 CHECK_STATUS(status, NT_STATUS_OK);
825 fnum2 = op.openx.out.file.fnum;
827 io.lockx.level = RAW_LOCK_LOCKX;
828 io.lockx.in.file.fnum = fnum;
829 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
830 io.lockx.in.timeout = t;
831 io.lockx.in.ulock_cnt = 0;
832 io.lockx.in.lock_cnt = 1;
833 lock[0].pid = cli->session->pid;
834 lock[0].offset = 100;
835 lock[0].count = 10;
836 io.lockx.in.locks = &lock[0];
837 status = smb_raw_lock(cli->tree, &io);
838 CHECK_STATUS(status, NT_STATUS_OK);
841 * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
842 * this also demonstrates that the error code cache is per file handle
843 * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
845 io.lockx.in.file.fnum = fnum2;
846 status = smb_raw_lock(cli->tree, &io);
847 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
849 io.lockx.in.file.fnum = fnum;
850 status = smb_raw_lock(cli->tree, &io);
851 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
853 /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
854 io.lockx.in.file.fnum = fnum;
855 status = smb_raw_lock(cli->tree, &io);
856 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
858 io.lockx.in.file.fnum = fnum2;
859 status = smb_raw_lock(cli->tree, &io);
860 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
862 io.lockx.in.file.fnum = fnum;
863 status = smb_raw_lock(cli->tree, &io);
864 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
866 io.lockx.in.file.fnum = fnum2;
867 status = smb_raw_lock(cli->tree, &io);
868 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
870 /* demonstrate that the smbpid doesn't matter */
871 lock[0].pid++;
872 io.lockx.in.file.fnum = fnum;
873 status = smb_raw_lock(cli->tree, &io);
874 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
876 io.lockx.in.file.fnum = fnum2;
877 status = smb_raw_lock(cli->tree, &io);
878 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
879 lock[0].pid--;
882 * demonstrate the a successful lock with count = 0 and the same offset,
883 * doesn't reset the error cache
885 lock[0].offset = 100;
886 lock[0].count = 0;
887 io.lockx.in.file.fnum = fnum;
888 status = smb_raw_lock(cli->tree, &io);
889 CHECK_STATUS(status, NT_STATUS_OK);
891 io.lockx.in.file.fnum = fnum2;
892 status = smb_raw_lock(cli->tree, &io);
893 CHECK_STATUS(status, NT_STATUS_OK);
895 lock[0].offset = 100;
896 lock[0].count = 10;
897 io.lockx.in.file.fnum = fnum;
898 status = smb_raw_lock(cli->tree, &io);
899 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
901 io.lockx.in.file.fnum = fnum2;
902 status = smb_raw_lock(cli->tree, &io);
903 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
906 * demonstrate the a successful lock with count = 0 and outside the locked range,
907 * doesn't reset the error cache
909 lock[0].offset = 110;
910 lock[0].count = 0;
911 io.lockx.in.file.fnum = fnum;
912 status = smb_raw_lock(cli->tree, &io);
913 CHECK_STATUS(status, NT_STATUS_OK);
915 io.lockx.in.file.fnum = fnum2;
916 status = smb_raw_lock(cli->tree, &io);
917 CHECK_STATUS(status, NT_STATUS_OK);
919 lock[0].offset = 100;
920 lock[0].count = 10;
921 io.lockx.in.file.fnum = fnum;
922 status = smb_raw_lock(cli->tree, &io);
923 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
925 io.lockx.in.file.fnum = fnum2;
926 status = smb_raw_lock(cli->tree, &io);
927 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
929 lock[0].offset = 99;
930 lock[0].count = 0;
931 io.lockx.in.file.fnum = fnum;
932 status = smb_raw_lock(cli->tree, &io);
933 CHECK_STATUS(status, NT_STATUS_OK);
935 io.lockx.in.file.fnum = fnum2;
936 status = smb_raw_lock(cli->tree, &io);
937 CHECK_STATUS(status, NT_STATUS_OK);
939 lock[0].offset = 100;
940 lock[0].count = 10;
941 io.lockx.in.file.fnum = fnum;
942 status = smb_raw_lock(cli->tree, &io);
943 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
945 io.lockx.in.file.fnum = fnum2;
946 status = smb_raw_lock(cli->tree, &io);
947 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
949 /* demonstrate that a changing count doesn't reset the error cache */
950 lock[0].offset = 100;
951 lock[0].count = 5;
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 lock[0].offset = 100;
961 lock[0].count = 15;
962 io.lockx.in.file.fnum = fnum;
963 status = smb_raw_lock(cli->tree, &io);
964 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
966 io.lockx.in.file.fnum = fnum2;
967 status = smb_raw_lock(cli->tree, &io);
968 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
971 * demonstrate the a lock with count = 0 and inside the locked range,
972 * fails and resets the error cache
974 lock[0].offset = 101;
975 lock[0].count = 0;
976 io.lockx.in.file.fnum = fnum;
977 status = smb_raw_lock(cli->tree, &io);
978 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
979 status = smb_raw_lock(cli->tree, &io);
980 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
982 io.lockx.in.file.fnum = fnum2;
983 status = smb_raw_lock(cli->tree, &io);
984 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
985 status = smb_raw_lock(cli->tree, &io);
986 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
988 lock[0].offset = 100;
989 lock[0].count = 10;
990 io.lockx.in.file.fnum = fnum;
991 status = smb_raw_lock(cli->tree, &io);
992 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
993 status = smb_raw_lock(cli->tree, &io);
994 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
996 io.lockx.in.file.fnum = fnum2;
997 status = smb_raw_lock(cli->tree, &io);
998 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
999 status = smb_raw_lock(cli->tree, &io);
1000 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1002 /* demonstrate the a changing offset, resets the error cache */
1003 lock[0].offset = 105;
1004 lock[0].count = 10;
1005 io.lockx.in.file.fnum = fnum;
1006 status = smb_raw_lock(cli->tree, &io);
1007 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1008 status = smb_raw_lock(cli->tree, &io);
1009 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1011 io.lockx.in.file.fnum = fnum2;
1012 status = smb_raw_lock(cli->tree, &io);
1013 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1014 status = smb_raw_lock(cli->tree, &io);
1015 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1017 lock[0].offset = 100;
1018 lock[0].count = 10;
1019 io.lockx.in.file.fnum = fnum;
1020 status = smb_raw_lock(cli->tree, &io);
1021 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1022 status = smb_raw_lock(cli->tree, &io);
1023 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1025 io.lockx.in.file.fnum = fnum2;
1026 status = smb_raw_lock(cli->tree, &io);
1027 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1028 status = smb_raw_lock(cli->tree, &io);
1029 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1031 lock[0].offset = 95;
1032 lock[0].count = 9;
1033 io.lockx.in.file.fnum = fnum;
1034 status = smb_raw_lock(cli->tree, &io);
1035 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1036 status = smb_raw_lock(cli->tree, &io);
1037 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1039 io.lockx.in.file.fnum = fnum2;
1040 status = smb_raw_lock(cli->tree, &io);
1041 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1042 status = smb_raw_lock(cli->tree, &io);
1043 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1045 lock[0].offset = 100;
1046 lock[0].count = 10;
1047 io.lockx.in.file.fnum = fnum;
1048 status = smb_raw_lock(cli->tree, &io);
1049 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1050 status = smb_raw_lock(cli->tree, &io);
1051 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1053 io.lockx.in.file.fnum = fnum2;
1054 status = smb_raw_lock(cli->tree, &io);
1055 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1056 status = smb_raw_lock(cli->tree, &io);
1057 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1060 * demonstrate the a successful lock in a different range,
1061 * doesn't reset the cache, the failing lock on the 2nd handle
1062 * resets the resets the cache
1064 lock[0].offset = 120;
1065 lock[0].count = 15;
1066 io.lockx.in.file.fnum = fnum;
1067 status = smb_raw_lock(cli->tree, &io);
1068 CHECK_STATUS(status, NT_STATUS_OK);
1070 io.lockx.in.file.fnum = fnum2;
1071 status = smb_raw_lock(cli->tree, &io);
1072 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1074 lock[0].offset = 100;
1075 lock[0].count = 10;
1076 io.lockx.in.file.fnum = fnum;
1077 status = smb_raw_lock(cli->tree, &io);
1078 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1079 status = smb_raw_lock(cli->tree, &io);
1080 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1082 io.lockx.in.file.fnum = fnum2;
1083 status = smb_raw_lock(cli->tree, &io);
1084 CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1085 status = smb_raw_lock(cli->tree, &io);
1086 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1088 /* end of the loop */
1089 if (t == 0) {
1090 smb_raw_exit(cli->session);
1091 t = 1;
1092 torture_comment(tctx, "testing with timeout > 0 (=%d)\n",
1094 fname = BASEDIR "\\test1.txt";
1095 goto next_run;
1098 t = 4000;
1099 torture_comment(tctx, "testing special cases with timeout > 0 (=%d)\n",
1103 * the following 3 test sections demonstrate that
1104 * the cache is only set when the error is reported
1105 * to the client (after the timeout went by)
1107 smb_raw_exit(cli->session);
1108 torture_comment(tctx, "testing a conflict while a lock is pending\n");
1109 fname = BASEDIR "\\test2.txt";
1110 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1111 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1112 "Failed to reopen %s - %s\n",
1113 fname, smbcli_errstr(cli->tree)));
1115 io.lockx.level = RAW_LOCK_LOCKX;
1116 io.lockx.in.file.fnum = fnum;
1117 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1118 io.lockx.in.timeout = 0;
1119 io.lockx.in.ulock_cnt = 0;
1120 io.lockx.in.lock_cnt = 1;
1121 lock[0].pid = cli->session->pid;
1122 lock[0].offset = 100;
1123 lock[0].count = 10;
1124 io.lockx.in.locks = &lock[0];
1125 status = smb_raw_lock(cli->tree, &io);
1126 CHECK_STATUS(status, NT_STATUS_OK);
1128 start = time(NULL);
1129 io.lockx.in.timeout = t;
1130 req = smb_raw_lock_send(cli->tree, &io);
1131 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1132 "Failed to setup timed lock (%s)\n", __location__));
1134 io.lockx.in.timeout = 0;
1135 lock[0].offset = 105;
1136 lock[0].count = 10;
1137 status = smb_raw_lock(cli->tree, &io);
1138 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1140 status = smbcli_request_simple_recv(req);
1141 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1143 delay = t / 1000;
1144 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1145 delay /= 2;
1148 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1149 "lock comes back to early timeout[%d] delay[%d]"
1150 "(%s)\n", t, delay, __location__));
1152 status = smb_raw_lock(cli->tree, &io);
1153 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1155 smbcli_close(cli->tree, fnum);
1156 fname = BASEDIR "\\test3.txt";
1157 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1158 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1159 "Failed to reopen %s - %s\n",
1160 fname, smbcli_errstr(cli->tree)));
1162 io.lockx.level = RAW_LOCK_LOCKX;
1163 io.lockx.in.file.fnum = fnum;
1164 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1165 io.lockx.in.timeout = 0;
1166 io.lockx.in.ulock_cnt = 0;
1167 io.lockx.in.lock_cnt = 1;
1168 lock[0].pid = cli->session->pid;
1169 lock[0].offset = 100;
1170 lock[0].count = 10;
1171 io.lockx.in.locks = &lock[0];
1172 status = smb_raw_lock(cli->tree, &io);
1173 CHECK_STATUS(status, NT_STATUS_OK);
1175 start = time(NULL);
1176 io.lockx.in.timeout = t;
1177 req = smb_raw_lock_send(cli->tree, &io);
1178 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1179 "Failed to setup timed lock (%s)\n", __location__));
1181 io.lockx.in.timeout = 0;
1182 lock[0].offset = 105;
1183 lock[0].count = 10;
1184 status = smb_raw_lock(cli->tree, &io);
1185 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1187 status = smbcli_request_simple_recv(req);
1188 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1190 delay = t / 1000;
1191 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1192 delay /= 2;
1195 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1196 "lock comes back to early timeout[%d] delay[%d]"
1197 "(%s)\n", t, delay, __location__));
1199 lock[0].offset = 100;
1200 lock[0].count = 10;
1201 status = smb_raw_lock(cli->tree, &io);
1202 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1204 smbcli_close(cli->tree, fnum);
1205 fname = BASEDIR "\\test4.txt";
1206 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1207 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1208 "Failed to reopen %s - %s\n",
1209 fname, smbcli_errstr(cli->tree)));
1211 io.lockx.level = RAW_LOCK_LOCKX;
1212 io.lockx.in.file.fnum = fnum;
1213 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1214 io.lockx.in.timeout = 0;
1215 io.lockx.in.ulock_cnt = 0;
1216 io.lockx.in.lock_cnt = 1;
1217 lock[0].pid = cli->session->pid;
1218 lock[0].offset = 100;
1219 lock[0].count = 10;
1220 io.lockx.in.locks = &lock[0];
1221 status = smb_raw_lock(cli->tree, &io);
1222 CHECK_STATUS(status, NT_STATUS_OK);
1224 start = time(NULL);
1225 io.lockx.in.timeout = t;
1226 req = smb_raw_lock_send(cli->tree, &io);
1227 torture_assert(tctx,(req != NULL), talloc_asprintf(tctx,
1228 "Failed to setup timed lock (%s)\n", __location__));
1230 io.lockx.in.timeout = 0;
1231 status = smb_raw_lock(cli->tree, &io);
1232 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1234 status = smbcli_request_simple_recv(req);
1235 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1237 delay = t / 1000;
1238 if (TARGET_IS_W2K8(tctx) || TARGET_IS_WIN7(tctx)) {
1239 delay /= 2;
1242 torture_assert(tctx,!(time(NULL) < start+delay), talloc_asprintf(tctx,
1243 "lock comes back to early timeout[%d] delay[%d]"
1244 "(%s)\n", t, delay, __location__));
1246 status = smb_raw_lock(cli->tree, &io);
1247 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1249 done:
1250 smb_raw_exit(cli->session);
1251 smbcli_deltree(cli->tree, BASEDIR);
1252 return ret;
1257 test LOCKING_ANDX_CHANGE_LOCKTYPE
1259 static bool test_changetype(struct torture_context *tctx,
1260 struct smbcli_state *cli)
1262 union smb_lock io;
1263 struct smb_lock_entry lock[2];
1264 NTSTATUS status;
1265 bool ret = true;
1266 int fnum;
1267 uint8_t c = 0;
1268 const char *fname = BASEDIR "\\test.txt";
1270 if (!torture_setup_dir(cli, BASEDIR)) {
1271 return false;
1274 torture_comment(tctx, "Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1275 io.generic.level = RAW_LOCK_LOCKX;
1277 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1278 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1279 "Failed to create %s - %s\n",
1280 fname, smbcli_errstr(cli->tree)));
1282 io.lockx.level = RAW_LOCK_LOCKX;
1283 io.lockx.in.file.fnum = fnum;
1284 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1285 io.lockx.in.timeout = 0;
1286 io.lockx.in.ulock_cnt = 0;
1287 io.lockx.in.lock_cnt = 1;
1288 lock[0].pid = cli->session->pid;
1289 lock[0].offset = 100;
1290 lock[0].count = 10;
1291 io.lockx.in.locks = &lock[0];
1292 status = smb_raw_lock(cli->tree, &io);
1293 CHECK_STATUS(status, NT_STATUS_OK);
1295 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1296 torture_result(tctx, TORTURE_FAIL,
1297 "allowed write on read locked region (%s)\n", __location__);
1298 ret = false;
1299 goto done;
1302 /* windows server don't seem to support this */
1303 io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1304 status = smb_raw_lock(cli->tree, &io);
1305 CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1307 if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1308 torture_result(tctx, TORTURE_FAIL,
1309 "allowed write after lock change (%s)\n", __location__);
1310 ret = false;
1311 goto done;
1314 done:
1315 smbcli_close(cli->tree, fnum);
1316 smb_raw_exit(cli->session);
1317 smbcli_deltree(cli->tree, BASEDIR);
1318 return ret;
1321 struct double_lock_test {
1322 struct smb_lock_entry lock1;
1323 struct smb_lock_entry lock2;
1324 NTSTATUS exp_status;
1328 * Tests zero byte locks.
1330 static const struct double_lock_test zero_byte_tests[] = {
1331 /* {pid, offset, count}, {pid, offset, count}, status */
1333 /** First, takes a zero byte lock at offset 10. Then:
1334 * - Taking 0 byte lock at 10 should succeed.
1335 * - Taking 1 byte locks at 9,10,11 should succeed.
1336 * - Taking 2 byte lock at 9 should fail.
1337 * - Taking 2 byte lock at 10 should succeed.
1338 * - Taking 3 byte lock at 9 should fail.
1340 {{1000, 10, 0}, {1001, 10, 0}, NT_STATUS_OK},
1341 {{1000, 10, 0}, {1001, 9, 1}, NT_STATUS_OK},
1342 {{1000, 10, 0}, {1001, 10, 1}, NT_STATUS_OK},
1343 {{1000, 10, 0}, {1001, 11, 1}, NT_STATUS_OK},
1344 {{1000, 10, 0}, {1001, 9, 2}, NT_STATUS_LOCK_NOT_GRANTED},
1345 {{1000, 10, 0}, {1001, 10, 2}, NT_STATUS_OK},
1346 {{1000, 10, 0}, {1001, 9, 3}, NT_STATUS_LOCK_NOT_GRANTED},
1348 /** Same, but opposite order. */
1349 {{1001, 10, 0}, {1000, 10, 0}, NT_STATUS_OK},
1350 {{1001, 9, 1}, {1000, 10, 0}, NT_STATUS_OK},
1351 {{1001, 10, 1}, {1000, 10, 0}, NT_STATUS_OK},
1352 {{1001, 11, 1}, {1000, 10, 0}, NT_STATUS_OK},
1353 {{1001, 9, 2}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1354 {{1001, 10, 2}, {1000, 10, 0}, NT_STATUS_OK},
1355 {{1001, 9, 3}, {1000, 10, 0}, NT_STATUS_LOCK_NOT_GRANTED},
1357 /** Zero zero case. */
1358 {{1000, 0, 0}, {1001, 0, 0}, NT_STATUS_OK},
1361 static bool test_zerobytelocks(struct torture_context *tctx, struct smbcli_state *cli)
1363 union smb_lock io;
1364 NTSTATUS status;
1365 bool ret = true;
1366 int fnum, i;
1367 const char *fname = BASEDIR "\\zero.txt";
1369 torture_comment(tctx, "Testing zero length byte range locks:\n");
1371 if (!torture_setup_dir(cli, BASEDIR)) {
1372 return false;
1375 io.generic.level = RAW_LOCK_LOCKX;
1377 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1378 torture_assert(tctx,(fnum != -1), talloc_asprintf(tctx,
1379 "Failed to create %s - %s\n",
1380 fname, smbcli_errstr(cli->tree)));
1382 /* Setup initial parameters */
1383 io.lockx.level = RAW_LOCK_LOCKX;
1384 io.lockx.in.file.fnum = fnum;
1385 io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES; /* Exclusive */
1386 io.lockx.in.timeout = 0;
1388 /* Try every combination of locks in zero_byte_tests. The first lock is
1389 * assumed to succeed. The second lock may contend, depending on the
1390 * expected status. */
1391 for (i = 0;
1392 i < ARRAY_SIZE(zero_byte_tests);
1393 i++) {
1394 torture_comment(tctx, " ... {%d, %llu, %llu} + {%d, %llu, %llu} = %s\n",
1395 zero_byte_tests[i].lock1.pid,
1396 zero_byte_tests[i].lock1.offset,
1397 zero_byte_tests[i].lock1.count,
1398 zero_byte_tests[i].lock2.pid,
1399 zero_byte_tests[i].lock2.offset,
1400 zero_byte_tests[i].lock2.count,
1401 nt_errstr(zero_byte_tests[i].exp_status));
1403 /* Lock both locks. */
1404 io.lockx.in.ulock_cnt = 0;
1405 io.lockx.in.lock_cnt = 1;
1407 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1408 &zero_byte_tests[i].lock1);
1409 status = smb_raw_lock(cli->tree, &io);
1410 CHECK_STATUS(status, NT_STATUS_OK);
1412 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1413 &zero_byte_tests[i].lock2);
1414 status = smb_raw_lock(cli->tree, &io);
1416 if (NT_STATUS_EQUAL(zero_byte_tests[i].exp_status,
1417 NT_STATUS_LOCK_NOT_GRANTED)) {
1418 /* Allow either of the failure messages and keep going
1419 * if we see the wrong status. */
1420 CHECK_STATUS_OR_CONT(status,
1421 NT_STATUS_LOCK_NOT_GRANTED,
1422 NT_STATUS_FILE_LOCK_CONFLICT);
1424 } else {
1425 CHECK_STATUS_CONT(status,
1426 zero_byte_tests[i].exp_status);
1429 /* Unlock both locks. */
1430 io.lockx.in.ulock_cnt = 1;
1431 io.lockx.in.lock_cnt = 0;
1433 if (NT_STATUS_EQUAL(status, NT_STATUS_OK)) {
1434 status = smb_raw_lock(cli->tree, &io);
1435 CHECK_STATUS(status, NT_STATUS_OK);
1438 io.lockx.in.locks = discard_const_p(struct smb_lock_entry,
1439 &zero_byte_tests[i].lock1);
1440 status = smb_raw_lock(cli->tree, &io);
1441 CHECK_STATUS(status, NT_STATUS_OK);
1444 done:
1445 smbcli_close(cli->tree, fnum);
1446 smb_raw_exit(cli->session);
1447 smbcli_deltree(cli->tree, BASEDIR);
1448 return ret;
1451 static bool test_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1453 union smb_lock io;
1454 NTSTATUS status;
1455 bool ret = true;
1456 int fnum1, fnum2;
1457 const char *fname = BASEDIR "\\unlock.txt";
1458 struct smb_lock_entry lock1;
1459 struct smb_lock_entry lock2;
1461 torture_comment(tctx, "Testing LOCKX unlock:\n");
1463 if (!torture_setup_dir(cli, BASEDIR)) {
1464 return false;
1467 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1468 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1469 "Failed to create %s - %s\n",
1470 fname, smbcli_errstr(cli->tree)));
1472 fnum2 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1473 torture_assert(tctx,(fnum2 != -1), talloc_asprintf(tctx,
1474 "Failed to create %s - %s\n",
1475 fname, smbcli_errstr(cli->tree)));
1477 /* Setup initial parameters */
1478 io.lockx.level = RAW_LOCK_LOCKX;
1479 io.lockx.in.timeout = 0;
1481 lock1.pid = cli->session->pid;
1482 lock1.offset = 0;
1483 lock1.count = 10;
1484 lock2.pid = cli->session->pid - 1;
1485 lock2.offset = 0;
1486 lock2.count = 10;
1489 * Take exclusive lock, then unlock it with a shared-unlock call.
1491 torture_comment(tctx, " taking exclusive lock.\n");
1492 io.lockx.in.ulock_cnt = 0;
1493 io.lockx.in.lock_cnt = 1;
1494 io.lockx.in.mode = 0;
1495 io.lockx.in.file.fnum = fnum1;
1496 io.lockx.in.locks = &lock1;
1497 status = smb_raw_lock(cli->tree, &io);
1498 CHECK_STATUS(status, NT_STATUS_OK);
1500 torture_comment(tctx, " unlock the exclusive with a shared unlock call.\n");
1501 io.lockx.in.ulock_cnt = 1;
1502 io.lockx.in.lock_cnt = 0;
1503 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1504 io.lockx.in.file.fnum = fnum1;
1505 io.lockx.in.locks = &lock1;
1506 status = smb_raw_lock(cli->tree, &io);
1507 CHECK_STATUS(status, NT_STATUS_OK);
1509 torture_comment(tctx, " try shared lock on pid2/fnum2, testing the unlock.\n");
1510 io.lockx.in.ulock_cnt = 0;
1511 io.lockx.in.lock_cnt = 1;
1512 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1513 io.lockx.in.file.fnum = fnum2;
1514 io.lockx.in.locks = &lock2;
1515 status = smb_raw_lock(cli->tree, &io);
1516 CHECK_STATUS(status, NT_STATUS_OK);
1519 * Unlock a shared lock with an exclusive-unlock call.
1521 torture_comment(tctx, " unlock new shared lock with exclusive unlock call.\n");
1522 io.lockx.in.ulock_cnt = 1;
1523 io.lockx.in.lock_cnt = 0;
1524 io.lockx.in.mode = 0;
1525 io.lockx.in.file.fnum = fnum2;
1526 io.lockx.in.locks = &lock2;
1527 status = smb_raw_lock(cli->tree, &io);
1528 CHECK_STATUS(status, NT_STATUS_OK);
1530 torture_comment(tctx, " try exclusive lock on pid1, testing the unlock.\n");
1531 io.lockx.in.ulock_cnt = 0;
1532 io.lockx.in.lock_cnt = 1;
1533 io.lockx.in.mode = 0;
1534 io.lockx.in.file.fnum = fnum1;
1535 io.lockx.in.locks = &lock1;
1536 status = smb_raw_lock(cli->tree, &io);
1537 CHECK_STATUS(status, NT_STATUS_OK);
1539 /* cleanup */
1540 io.lockx.in.ulock_cnt = 1;
1541 io.lockx.in.lock_cnt = 0;
1542 status = smb_raw_lock(cli->tree, &io);
1543 CHECK_STATUS(status, NT_STATUS_OK);
1546 * Test unlocking of 0-byte locks.
1549 torture_comment(tctx, " lock shared and exclusive 0-byte locks, testing that Windows "
1550 "always unlocks the exclusive first.\n");
1551 lock1.pid = cli->session->pid;
1552 lock1.offset = 10;
1553 lock1.count = 0;
1554 lock2.pid = cli->session->pid;
1555 lock2.offset = 5;
1556 lock2.count = 10;
1557 io.lockx.in.ulock_cnt = 0;
1558 io.lockx.in.lock_cnt = 1;
1559 io.lockx.in.file.fnum = fnum1;
1560 io.lockx.in.locks = &lock1;
1562 /* lock 0-byte shared
1563 * Note: Order of the shared/exclusive locks doesn't matter. */
1564 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1565 status = smb_raw_lock(cli->tree, &io);
1566 CHECK_STATUS(status, NT_STATUS_OK);
1568 /* lock 0-byte exclusive */
1569 io.lockx.in.mode = 0;
1570 status = smb_raw_lock(cli->tree, &io);
1571 CHECK_STATUS(status, NT_STATUS_OK);
1573 /* test contention */
1574 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1575 io.lockx.in.locks = &lock2;
1576 io.lockx.in.file.fnum = fnum2;
1577 status = smb_raw_lock(cli->tree, &io);
1578 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1579 NT_STATUS_FILE_LOCK_CONFLICT);
1581 /* unlock */
1582 io.lockx.in.ulock_cnt = 1;
1583 io.lockx.in.lock_cnt = 0;
1584 io.lockx.in.file.fnum = fnum1;
1585 io.lockx.in.locks = &lock1;
1586 status = smb_raw_lock(cli->tree, &io);
1587 CHECK_STATUS(status, NT_STATUS_OK);
1589 /* test - can we take a shared lock? */
1590 io.lockx.in.ulock_cnt = 0;
1591 io.lockx.in.lock_cnt = 1;
1592 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1593 io.lockx.in.file.fnum = fnum2;
1594 io.lockx.in.locks = &lock2;
1595 status = smb_raw_lock(cli->tree, &io);
1597 /* XXX Samba 3 will fail this test. This is temporary(because this isn't
1598 * new to Win7, it succeeds in WinXP too), until I can come to a
1599 * resolution as to whether Samba should support this or not. There is
1600 * code to preference unlocking exclusive locks before shared locks,
1601 * but its wrapped with "#ifdef ZERO_ZERO". -zkirsch */
1602 if (TARGET_IS_SAMBA3(tctx)) {
1603 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1604 NT_STATUS_FILE_LOCK_CONFLICT);
1605 } else {
1606 CHECK_STATUS(status, NT_STATUS_OK);
1609 /* cleanup */
1610 io.lockx.in.ulock_cnt = 1;
1611 io.lockx.in.lock_cnt = 0;
1612 status = smb_raw_lock(cli->tree, &io);
1614 /* XXX Same as above. */
1615 if (TARGET_IS_SAMBA3(tctx)) {
1616 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1617 } else {
1618 CHECK_STATUS(status, NT_STATUS_OK);
1621 io.lockx.in.file.fnum = fnum1;
1622 io.lockx.in.locks = &lock1;
1623 status = smb_raw_lock(cli->tree, &io);
1624 CHECK_STATUS(status, NT_STATUS_OK);
1626 done:
1627 smbcli_close(cli->tree, fnum1);
1628 smbcli_close(cli->tree, fnum2);
1629 smb_raw_exit(cli->session);
1630 smbcli_deltree(cli->tree, BASEDIR);
1631 return ret;
1634 static bool test_multiple_unlock(struct torture_context *tctx, struct smbcli_state *cli)
1636 union smb_lock io;
1637 NTSTATUS status;
1638 bool ret = true;
1639 int fnum1;
1640 const char *fname = BASEDIR "\\unlock_multiple.txt";
1641 struct smb_lock_entry lock1;
1642 struct smb_lock_entry lock2;
1643 struct smb_lock_entry locks[2];
1645 torture_comment(tctx, "Testing LOCKX multiple unlock:\n");
1647 if (!torture_setup_dir(cli, BASEDIR)) {
1648 return false;
1651 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1652 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1653 "Failed to create %s - %s\n",
1654 fname, smbcli_errstr(cli->tree)));
1656 /* Setup initial parameters */
1657 io.lockx.level = RAW_LOCK_LOCKX;
1658 io.lockx.in.timeout = 0;
1660 lock1.pid = cli->session->pid;
1661 lock1.offset = 0;
1662 lock1.count = 10;
1663 lock2.pid = cli->session->pid;
1664 lock2.offset = 10;
1665 lock2.count = 10;
1667 locks[0] = lock1;
1668 locks[1] = lock2;
1670 io.lockx.in.file.fnum = fnum1;
1671 io.lockx.in.mode = 0; /* exclusive */
1673 /** Test1: Take second lock, but not first. */
1674 torture_comment(tctx, " unlock 2 locks, first one not locked. Expect no locks "
1675 "unlocked. \n");
1677 io.lockx.in.ulock_cnt = 0;
1678 io.lockx.in.lock_cnt = 1;
1679 io.lockx.in.locks = &lock2;
1680 status = smb_raw_lock(cli->tree, &io);
1681 CHECK_STATUS(status, NT_STATUS_OK);
1683 /* Try to unlock both locks. */
1684 io.lockx.in.ulock_cnt = 2;
1685 io.lockx.in.lock_cnt = 0;
1686 io.lockx.in.locks = locks;
1688 status = smb_raw_lock(cli->tree, &io);
1689 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1691 /* Second lock should not be unlocked. */
1692 io.lockx.in.ulock_cnt = 0;
1693 io.lockx.in.lock_cnt = 1;
1694 io.lockx.in.locks = &lock2;
1695 status = smb_raw_lock(cli->tree, &io);
1696 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1698 /* cleanup */
1699 io.lockx.in.ulock_cnt = 1;
1700 io.lockx.in.lock_cnt = 0;
1701 io.lockx.in.locks = &lock2;
1702 status = smb_raw_lock(cli->tree, &io);
1703 CHECK_STATUS(status, NT_STATUS_OK);
1705 /** Test2: Take first lock, but not second. */
1706 torture_comment(tctx, " unlock 2 locks, second one not locked. Expect first lock "
1707 "unlocked.\n");
1709 io.lockx.in.ulock_cnt = 0;
1710 io.lockx.in.lock_cnt = 1;
1711 io.lockx.in.locks = &lock1;
1712 status = smb_raw_lock(cli->tree, &io);
1713 CHECK_STATUS(status, NT_STATUS_OK);
1715 /* Try to unlock both locks. */
1716 io.lockx.in.ulock_cnt = 2;
1717 io.lockx.in.lock_cnt = 0;
1718 io.lockx.in.locks = locks;
1720 status = smb_raw_lock(cli->tree, &io);
1721 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
1723 /* First lock should be unlocked. */
1724 io.lockx.in.ulock_cnt = 0;
1725 io.lockx.in.lock_cnt = 1;
1726 io.lockx.in.locks = &lock1;
1727 status = smb_raw_lock(cli->tree, &io);
1728 CHECK_STATUS(status, NT_STATUS_OK);
1730 /* cleanup */
1731 io.lockx.in.ulock_cnt = 1;
1732 io.lockx.in.lock_cnt = 0;
1733 io.lockx.in.locks = &lock1;
1734 status = smb_raw_lock(cli->tree, &io);
1735 CHECK_STATUS(status, NT_STATUS_OK);
1737 done:
1738 smbcli_close(cli->tree, fnum1);
1739 smb_raw_exit(cli->session);
1740 smbcli_deltree(cli->tree, BASEDIR);
1741 return ret;
1745 * torture_locktest5 covers stacking pretty well, but its missing two tests:
1746 * - stacking an exclusive on top of shared fails
1747 * - stacking two exclusives fail
1749 static bool test_stacking(struct torture_context *tctx, struct smbcli_state *cli)
1751 union smb_lock io;
1752 NTSTATUS status;
1753 bool ret = true;
1754 int fnum1;
1755 const char *fname = BASEDIR "\\stacking.txt";
1756 struct smb_lock_entry lock1;
1757 struct smb_lock_entry lock2;
1759 torture_comment(tctx, "Testing stacking:\n");
1761 if (!torture_setup_dir(cli, BASEDIR)) {
1762 return false;
1765 io.generic.level = RAW_LOCK_LOCKX;
1767 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1768 torture_assert(tctx,(fnum1 != -1), talloc_asprintf(tctx,
1769 "Failed to create %s - %s\n",
1770 fname, smbcli_errstr(cli->tree)));
1772 /* Setup initial parameters */
1773 io.lockx.level = RAW_LOCK_LOCKX;
1774 io.lockx.in.timeout = 0;
1776 lock1.pid = cli->session->pid;
1777 lock1.offset = 0;
1778 lock1.count = 10;
1779 lock2.pid = cli->session->pid - 1;
1780 lock2.offset = 0;
1781 lock2.count = 10;
1784 * Try to take a shared lock, then stack an exclusive.
1786 torture_comment(tctx, " stacking an exclusive on top of a shared lock fails.\n");
1787 io.lockx.in.file.fnum = fnum1;
1788 io.lockx.in.locks = &lock1;
1790 io.lockx.in.ulock_cnt = 0;
1791 io.lockx.in.lock_cnt = 1;
1792 io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1793 status = smb_raw_lock(cli->tree, &io);
1794 CHECK_STATUS(status, NT_STATUS_OK);
1796 io.lockx.in.ulock_cnt = 0;
1797 io.lockx.in.lock_cnt = 1;
1798 io.lockx.in.mode = 0;
1799 status = smb_raw_lock(cli->tree, &io);
1800 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1801 NT_STATUS_FILE_LOCK_CONFLICT);
1803 /* cleanup */
1804 io.lockx.in.ulock_cnt = 1;
1805 io.lockx.in.lock_cnt = 0;
1806 status = smb_raw_lock(cli->tree, &io);
1807 CHECK_STATUS(status, NT_STATUS_OK);
1810 * Prove that two exclusive locks do not stack.
1812 torture_comment(tctx, " two exclusive locks do not stack.\n");
1813 io.lockx.in.ulock_cnt = 0;
1814 io.lockx.in.lock_cnt = 1;
1815 io.lockx.in.mode = 0;
1816 status = smb_raw_lock(cli->tree, &io);
1817 CHECK_STATUS(status, NT_STATUS_OK);
1818 status = smb_raw_lock(cli->tree, &io);
1819 CHECK_STATUS_OR(status, NT_STATUS_LOCK_NOT_GRANTED,
1820 NT_STATUS_FILE_LOCK_CONFLICT);
1822 /* cleanup */
1823 io.lockx.in.ulock_cnt = 1;
1824 io.lockx.in.lock_cnt = 0;
1825 status = smb_raw_lock(cli->tree, &io);
1826 CHECK_STATUS(status, NT_STATUS_OK);
1828 done:
1829 smbcli_close(cli->tree, fnum1);
1830 smb_raw_exit(cli->session);
1831 smbcli_deltree(cli->tree, BASEDIR);
1832 return ret;
1836 basic testing of lock calls
1838 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
1840 struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
1842 torture_suite_add_1smb_test(suite, "lockx", test_lockx);
1843 torture_suite_add_1smb_test(suite, "lock", test_lock);
1844 torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
1845 torture_suite_add_1smb_test(suite, "async", test_async);
1846 torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
1847 torture_suite_add_1smb_test(suite, "changetype", test_changetype);
1849 torture_suite_add_1smb_test(suite, "stacking", test_stacking);
1850 torture_suite_add_1smb_test(suite, "unlock", test_unlock);
1851 torture_suite_add_1smb_test(suite, "multiple_unlock",
1852 test_multiple_unlock);
1853 torture_suite_add_1smb_test(suite, "zerobytelocks",
1854 test_zerobytelocks);
1856 return suite;