2 Unix SMB/CIFS implementation.
6 Copyright (C) Andrew Tridgell 2000-2004
7 Copyright (C) Jeremy Allison 2000-2004
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
28 #include "torture/torture.h"
29 #include "system/time.h"
30 #include "system/filesys.h"
32 #define BASEDIR "\\locktest"
35 This test checks for two things:
37 1) correct support for retaining locks over a close (ie. the server
38 must not use posix semantics)
39 2) support for lock timeouts
41 BOOL torture_locktest1(struct torture_context *torture)
43 struct smbcli_state *cli1, *cli2;
44 const char *fname = BASEDIR "\\lockt1.lck";
45 int fnum1, fnum2, fnum3;
49 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
53 printf("starting locktest1\n");
55 if (!torture_setup_dir(cli1, BASEDIR)) {
59 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
61 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
64 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
66 printf("(%s) open2 of %s failed (%s)\n",
67 __location__, fname, smbcli_errstr(cli1->tree));
70 fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
72 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
76 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
77 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
82 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
83 printf("lock2 succeeded! This is a locking bug\n");
86 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
87 NT_STATUS_LOCK_NOT_GRANTED)) return False;
90 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
91 printf("lock2 succeeded! This is a locking bug\n");
94 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
95 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
98 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 5, 9, 0, WRITE_LOCK))) {
99 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
103 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 5, 9, 0, WRITE_LOCK))) {
104 printf("lock2 succeeded! This is a locking bug\n");
107 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
108 NT_STATUS_LOCK_NOT_GRANTED)) return False;
111 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
112 printf("lock2 succeeded! This is a locking bug\n");
115 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
116 NT_STATUS_LOCK_NOT_GRANTED)) return False;
119 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
120 printf("lock2 succeeded! This is a locking bug\n");
123 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
124 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
127 lock_timeout = (6 + (random() % 20));
128 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
130 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
131 printf("lock3 succeeded! This is a locking bug\n");
134 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
135 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
140 printf("error: This server appears not to support timed lock requests\n");
142 printf("server slept for %u seconds for a %u second timeout\n",
143 (uint_t)(t2-t1), lock_timeout);
145 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
146 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
150 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
151 printf("lock4 succeeded! This is a locking bug\n");
154 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
155 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
158 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
159 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
163 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
164 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
168 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
169 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
174 if (!torture_close_connection(cli1)) {
178 if (!torture_close_connection(cli2)) {
182 printf("Passed locktest1\n");
188 This test checks that
190 1) the server supports multiple locking contexts on the one SMB
191 connection, distinguished by PID.
193 2) the server correctly fails overlapping locks made by the same PID (this
194 goes against POSIX behaviour, which is why it is tricky to implement)
196 3) the server denies unlock requests by an incorrect client PID
198 BOOL torture_locktest2(struct torture_context *torture)
200 struct smbcli_state *cli;
201 const char *fname = BASEDIR "\\lockt2.lck";
202 int fnum1, fnum2, fnum3;
205 if (!torture_open_connection(&cli)) {
209 printf("starting locktest2\n");
211 if (!torture_setup_dir(cli, BASEDIR)) {
215 printf("Testing pid context\n");
217 cli->session->pid = 1;
219 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
221 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
225 fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
227 printf("(%s) open2 of %s failed (%s)\n",
228 __location__, fname, smbcli_errstr(cli->tree));
232 cli->session->pid = 2;
234 fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
236 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
240 cli->session->pid = 1;
242 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
243 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
247 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
248 printf("WRITE lock1 succeeded! This is a locking bug\n");
251 if (!check_error(__location__, cli, ERRDOS, ERRlock,
252 NT_STATUS_LOCK_NOT_GRANTED)) return False;
255 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
256 printf("WRITE lock2 succeeded! This is a locking bug\n");
259 if (!check_error(__location__, cli, ERRDOS, ERRlock,
260 NT_STATUS_LOCK_NOT_GRANTED)) return False;
263 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
264 printf("READ lock2 succeeded! This is a locking bug\n");
267 if (!check_error(__location__, cli, ERRDOS, ERRlock,
268 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
271 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
272 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
275 cli->session->pid = 2;
277 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
278 printf("unlock at 100 succeeded! This is a locking bug\n");
282 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
283 printf("unlock1 succeeded! This is a locking bug\n");
286 if (!check_error(__location__, cli,
287 ERRDOS, ERRnotlocked,
288 NT_STATUS_RANGE_NOT_LOCKED)) return False;
291 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
292 printf("unlock2 succeeded! This is a locking bug\n");
295 if (!check_error(__location__, cli,
296 ERRDOS, ERRnotlocked,
297 NT_STATUS_RANGE_NOT_LOCKED)) return False;
300 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
301 printf("lock3 succeeded! This is a locking bug\n");
304 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
307 cli->session->pid = 1;
309 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
310 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
314 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
315 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
319 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
320 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
324 if (!torture_close_connection(cli)) {
328 printf("locktest2 finished\n");
335 This test checks that
337 1) the server supports the full offset range in lock requests
339 BOOL torture_locktest3(struct torture_context *torture)
341 struct smbcli_state *cli1, *cli2;
342 const char *fname = BASEDIR "\\lockt3.lck";
346 extern int torture_numops;
348 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
350 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
354 printf("starting locktest3\n");
356 printf("Testing 32 bit offset ranges\n");
358 if (!torture_setup_dir(cli1, BASEDIR)) {
362 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
364 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
367 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
369 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
373 printf("Establishing %d locks\n", torture_numops);
375 for (offset=i=0;i<torture_numops;i++) {
377 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
378 printf("lock1 %d failed (%s)\n",
380 smbcli_errstr(cli1->tree));
384 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
385 printf("lock2 %d failed (%s)\n",
387 smbcli_errstr(cli1->tree));
392 printf("Testing %d locks\n", torture_numops);
394 for (offset=i=0;i<torture_numops;i++) {
397 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
398 printf("error: lock1 %d succeeded!\n", i);
402 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
403 printf("error: lock2 %d succeeded!\n", i);
407 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
408 printf("error: lock3 %d succeeded!\n", i);
412 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
413 printf("error: lock4 %d succeeded!\n", i);
418 printf("Removing %d locks\n", torture_numops);
420 for (offset=i=0;i<torture_numops;i++) {
423 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
424 printf("unlock1 %d failed (%s)\n",
426 smbcli_errstr(cli1->tree));
430 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
431 printf("unlock2 %d failed (%s)\n",
433 smbcli_errstr(cli1->tree));
438 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
439 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
443 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
444 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
448 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
449 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
453 if (!torture_close_connection(cli1)) {
457 if (!torture_close_connection(cli2)) {
461 printf("finished locktest3\n");
466 #define EXPECTED(ret, v) if ((ret) != (v)) { \
467 printf("** "); correct = False; \
471 looks at overlapping locks
473 BOOL torture_locktest4(struct torture_context *torture)
475 struct smbcli_state *cli1, *cli2;
476 const char *fname = BASEDIR "\\lockt4.lck";
482 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
486 printf("starting locktest4\n");
488 if (!torture_setup_dir(cli1, BASEDIR)) {
492 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
493 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
495 memset(buf, 0, sizeof(buf));
497 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
498 printf("Failed to create file\n");
503 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
504 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
505 EXPECTED(ret, False);
506 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
508 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
509 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
511 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
513 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
514 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
515 EXPECTED(ret, False);
516 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
518 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
519 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
521 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
523 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
524 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
525 EXPECTED(ret, False);
526 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
528 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
529 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
531 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
533 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
534 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
536 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
538 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
539 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
540 EXPECTED(ret, False);
541 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
543 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
544 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
545 EXPECTED(ret, False);
546 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
548 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
549 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
551 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
553 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
554 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
555 EXPECTED(ret, False);
556 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
558 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
559 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
560 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
561 EXPECTED(ret, False);
562 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
565 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
566 (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
567 EXPECTED(ret, False);
568 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
570 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
571 (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
572 EXPECTED(ret, False);
573 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
576 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
577 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
578 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
579 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
581 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
584 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
585 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
586 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
587 (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
588 !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
589 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
591 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
593 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
594 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
595 (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&
596 (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);
598 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
600 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
601 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
602 (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&
603 (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);
605 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
607 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
608 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
609 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
610 !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&
611 (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);
613 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
615 smbcli_close(cli1->tree, fnum1);
616 smbcli_close(cli2->tree, fnum2);
617 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
618 f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
619 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
620 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
621 NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
622 ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
623 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
624 smbcli_close(cli1->tree, f);
625 smbcli_close(cli1->tree, fnum1);
627 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
630 smbcli_close(cli1->tree, fnum1);
631 smbcli_close(cli2->tree, fnum2);
632 smbcli_unlink(cli1->tree, fname);
633 torture_close_connection(cli1);
634 torture_close_connection(cli2);
636 printf("finished locktest4\n");
641 looks at lock upgrade/downgrade.
643 BOOL torture_locktest5(struct torture_context *torture)
645 struct smbcli_state *cli1, *cli2;
646 const char *fname = BASEDIR "\\lockt5.lck";
647 int fnum1, fnum2, fnum3;
652 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
656 printf("starting locktest5\n");
658 if (!torture_setup_dir(cli1, BASEDIR)) {
662 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
663 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
664 fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
666 memset(buf, 0, sizeof(buf));
668 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
669 printf("Failed to create file\n");
674 /* Check for NT bug... */
675 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
676 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
677 smbcli_close(cli1->tree, fnum1);
678 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
679 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
681 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
682 smbcli_close(cli1->tree, fnum1);
683 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
684 smbcli_unlock(cli1->tree, fnum3, 0, 1);
686 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
687 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
689 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
691 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
692 EXPECTED(ret, False);
694 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
696 /* Unlock the process 2 lock. */
697 smbcli_unlock(cli2->tree, fnum2, 0, 4);
699 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
700 EXPECTED(ret, False);
702 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
704 /* Unlock the process 1 fnum3 lock. */
705 smbcli_unlock(cli1->tree, fnum3, 0, 4);
707 /* Stack 2 more locks here. */
708 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
709 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
712 printf("the same process %s stack read locks\n", ret?"can":"cannot");
714 /* Unlock the first process lock, then check this was the WRITE lock that was
717 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
718 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
721 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
723 /* Unlock the process 2 lock. */
724 smbcli_unlock(cli2->tree, fnum2, 0, 4);
726 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
728 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
729 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
730 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
733 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
735 /* Ensure the next unlock fails. */
736 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
737 EXPECTED(ret, False);
738 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
740 /* Ensure connection 2 can get a write lock. */
741 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
744 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
748 smbcli_close(cli1->tree, fnum1);
749 smbcli_close(cli2->tree, fnum2);
750 smbcli_unlink(cli1->tree, fname);
751 if (!torture_close_connection(cli1)) {
754 if (!torture_close_connection(cli2)) {
758 printf("finished locktest5\n");
764 tries the unusual lockingX locktype bits
766 BOOL torture_locktest6(struct torture_context *torture)
768 struct smbcli_state *cli;
769 const char *fname[1] = { "\\lock6.txt" };
774 if (!torture_open_connection(&cli)) {
778 if (!torture_setup_dir(cli, BASEDIR)) {
782 printf("starting locktest6\n");
785 printf("Testing %s\n", fname[i]);
787 smbcli_unlink(cli->tree, fname[i]);
789 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
790 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
791 smbcli_close(cli->tree, fnum);
792 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
794 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
795 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
796 smbcli_close(cli->tree, fnum);
797 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
799 smbcli_unlink(cli->tree, fname[i]);
802 torture_close_connection(cli);
804 printf("finished locktest6\n");
808 BOOL torture_locktest7(struct torture_context *torture)
810 struct smbcli_state *cli1;
811 const char *fname = BASEDIR "\\lockt7.lck";
816 BOOL correct = False;
818 if (!torture_open_connection(&cli1)) {
822 printf("starting locktest7\n");
824 if (!torture_setup_dir(cli1, BASEDIR)) {
828 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
830 memset(buf, 0, sizeof(buf));
832 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
833 printf("Failed to create file (%s)\n", __location__);
837 cli1->session->pid = 1;
839 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
840 printf("Unable to apply read lock on range 130:4, error was %s (%s)\n",
841 smbcli_errstr(cli1->tree), __location__);
844 printf("pid1 successfully locked range 130:4 for READ\n");
847 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
848 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
849 smbcli_errstr(cli1->tree), __location__);
852 printf("pid1 successfully read the range 130:4\n");
855 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
856 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
857 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
858 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
863 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n",
868 cli1->session->pid = 2;
870 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
871 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
873 printf("pid2 successfully read the range 130:4\n");
876 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
877 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
878 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
879 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
884 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
889 cli1->session->pid = 1;
890 smbcli_unlock(cli1->tree, fnum1, 130, 4);
892 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
893 printf("Unable to apply write lock on range 130:4, error was %s (%s)\n",
894 smbcli_errstr(cli1->tree), __location__);
897 printf("pid1 successfully locked range 130:4 for WRITE\n");
900 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
901 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
902 smbcli_errstr(cli1->tree), __location__);
905 printf("pid1 successfully read the range 130:4\n");
908 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
909 printf("pid1 unable to write to the range 130:4, error was %s (%s)\n",
910 smbcli_errstr(cli1->tree), __location__);
913 printf("pid1 successfully wrote to the range 130:4\n");
916 cli1->session->pid = 2;
918 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
919 printf("pid2 unable to read the range 130:4, error was %s\n",
920 smbcli_errstr(cli1->tree));
921 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
922 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
927 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n",
932 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
933 printf("pid2 unable to write to the range 130:4, error was %s\n",
934 smbcli_errstr(cli1->tree));
935 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
936 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
941 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
946 printf("Testing truncate of locked file.\n");
948 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
951 printf("Unable to truncate locked file (%s)\n", __location__);
955 printf("Truncated locked file.\n");
958 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
959 printf("getatr failed (%s) (%s)\n", smbcli_errstr(cli1->tree), __location__);
965 printf("Unable to truncate locked file. Size was %u (%s)\n",
966 (unsigned)size, __location__);
971 cli1->session->pid = 1;
973 smbcli_unlock(cli1->tree, fnum1, 130, 4);
977 smbcli_close(cli1->tree, fnum1);
978 smbcli_close(cli1->tree, fnum2);
979 smbcli_unlink(cli1->tree, fname);
980 torture_close_connection(cli1);
982 printf("finished locktest7\n");