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 "system/time.h"
27 #include "system/filesys.h"
29 #define BASEDIR "\\locktest"
32 This test checks for two things:
34 1) correct support for retaining locks over a close (ie. the server
35 must not use posix semantics)
36 2) support for lock timeouts
38 BOOL torture_locktest1(void)
40 struct smbcli_state *cli1, *cli2;
41 const char *fname = BASEDIR "\\lockt1.lck";
42 int fnum1, fnum2, fnum3;
46 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
50 printf("starting locktest1\n");
52 if (!torture_setup_dir(cli1, BASEDIR)) {
56 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
58 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
61 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
63 printf("(%s) open2 of %s failed (%s)\n",
64 __location__, fname, smbcli_errstr(cli1->tree));
67 fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
69 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
73 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
74 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
79 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
80 printf("lock2 succeeded! This is a locking bug\n");
83 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
84 NT_STATUS_LOCK_NOT_GRANTED)) return False;
87 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
88 printf("lock2 succeeded! This is a locking bug\n");
91 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
92 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
95 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 5, 9, 0, WRITE_LOCK))) {
96 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
100 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 5, 9, 0, WRITE_LOCK))) {
101 printf("lock2 succeeded! This is a locking bug\n");
104 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
105 NT_STATUS_LOCK_NOT_GRANTED)) return False;
108 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
109 printf("lock2 succeeded! This is a locking bug\n");
112 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
113 NT_STATUS_LOCK_NOT_GRANTED)) return False;
116 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
117 printf("lock2 succeeded! This is a locking bug\n");
120 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
121 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
124 lock_timeout = (6 + (random() % 20));
125 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
127 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
128 printf("lock3 succeeded! This is a locking bug\n");
131 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
132 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
137 printf("error: This server appears not to support timed lock requests\n");
139 printf("server slept for %u seconds for a %u second timeout\n",
140 (uint_t)(t2-t1), lock_timeout);
142 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
143 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
147 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
148 printf("lock4 succeeded! This is a locking bug\n");
151 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
152 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
155 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
156 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
160 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
161 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
165 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
166 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
171 if (!torture_close_connection(cli1)) {
175 if (!torture_close_connection(cli2)) {
179 printf("Passed locktest1\n");
185 This test checks that
187 1) the server supports multiple locking contexts on the one SMB
188 connection, distinguished by PID.
190 2) the server correctly fails overlapping locks made by the same PID (this
191 goes against POSIX behaviour, which is why it is tricky to implement)
193 3) the server denies unlock requests by an incorrect client PID
195 BOOL torture_locktest2(void)
197 struct smbcli_state *cli;
198 const char *fname = BASEDIR "\\lockt2.lck";
199 int fnum1, fnum2, fnum3;
202 if (!torture_open_connection(&cli)) {
206 printf("starting locktest2\n");
208 if (!torture_setup_dir(cli, BASEDIR)) {
212 printf("Testing pid context\n");
214 cli->session->pid = 1;
216 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
218 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
222 fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
224 printf("(%s) open2 of %s failed (%s)\n",
225 __location__, fname, smbcli_errstr(cli->tree));
229 cli->session->pid = 2;
231 fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
233 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
237 cli->session->pid = 1;
239 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
240 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
244 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
245 printf("WRITE lock1 succeeded! This is a locking bug\n");
248 if (!check_error(__location__, cli, ERRDOS, ERRlock,
249 NT_STATUS_LOCK_NOT_GRANTED)) return False;
252 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
253 printf("WRITE lock2 succeeded! This is a locking bug\n");
256 if (!check_error(__location__, cli, ERRDOS, ERRlock,
257 NT_STATUS_LOCK_NOT_GRANTED)) return False;
260 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
261 printf("READ lock2 succeeded! This is a locking bug\n");
264 if (!check_error(__location__, cli, ERRDOS, ERRlock,
265 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
268 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
269 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
272 cli->session->pid = 2;
274 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
275 printf("unlock at 100 succeeded! This is a locking bug\n");
279 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
280 printf("unlock1 succeeded! This is a locking bug\n");
283 if (!check_error(__location__, cli,
285 NT_STATUS_RANGE_NOT_LOCKED)) return False;
288 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
289 printf("unlock2 succeeded! This is a locking bug\n");
292 if (!check_error(__location__, cli,
294 NT_STATUS_RANGE_NOT_LOCKED)) return False;
297 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
298 printf("lock3 succeeded! This is a locking bug\n");
301 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
304 cli->session->pid = 1;
306 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
307 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
311 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
312 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
316 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
317 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
321 if (!torture_close_connection(cli)) {
325 printf("locktest2 finished\n");
332 This test checks that
334 1) the server supports the full offset range in lock requests
336 BOOL torture_locktest3(void)
338 struct smbcli_state *cli1, *cli2;
339 const char *fname = BASEDIR "\\lockt3.lck";
343 extern int torture_numops;
345 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
347 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
351 printf("starting locktest3\n");
353 printf("Testing 32 bit offset ranges\n");
355 if (!torture_setup_dir(cli1, BASEDIR)) {
359 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
361 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
364 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
366 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
370 printf("Establishing %d locks\n", torture_numops);
372 for (offset=i=0;i<torture_numops;i++) {
374 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
375 printf("lock1 %d failed (%s)\n",
377 smbcli_errstr(cli1->tree));
381 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
382 printf("lock2 %d failed (%s)\n",
384 smbcli_errstr(cli1->tree));
389 printf("Testing %d locks\n", torture_numops);
391 for (offset=i=0;i<torture_numops;i++) {
394 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
395 printf("error: lock1 %d succeeded!\n", i);
399 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
400 printf("error: lock2 %d succeeded!\n", i);
404 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
405 printf("error: lock3 %d succeeded!\n", i);
409 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
410 printf("error: lock4 %d succeeded!\n", i);
415 printf("Removing %d locks\n", torture_numops);
417 for (offset=i=0;i<torture_numops;i++) {
420 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
421 printf("unlock1 %d failed (%s)\n",
423 smbcli_errstr(cli1->tree));
427 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
428 printf("unlock2 %d failed (%s)\n",
430 smbcli_errstr(cli1->tree));
435 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
436 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
440 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
441 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
445 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
446 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
450 if (!torture_close_connection(cli1)) {
454 if (!torture_close_connection(cli2)) {
458 printf("finished locktest3\n");
463 #define EXPECTED(ret, v) if ((ret) != (v)) { \
464 printf("** "); correct = False; \
468 looks at overlapping locks
470 BOOL torture_locktest4(void)
472 struct smbcli_state *cli1, *cli2;
473 const char *fname = BASEDIR "\\lockt4.lck";
479 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
483 printf("starting locktest4\n");
485 if (!torture_setup_dir(cli1, BASEDIR)) {
489 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
490 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
492 memset(buf, 0, sizeof(buf));
494 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
495 printf("Failed to create file\n");
500 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
501 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
502 EXPECTED(ret, False);
503 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
505 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
506 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
508 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
510 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
511 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
512 EXPECTED(ret, False);
513 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
515 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
516 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
518 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
520 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
521 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
522 EXPECTED(ret, False);
523 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
525 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
526 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
528 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
530 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
531 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
533 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
535 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
536 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
537 EXPECTED(ret, False);
538 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
540 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
541 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
542 EXPECTED(ret, False);
543 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
545 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
546 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
548 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
550 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
551 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
552 EXPECTED(ret, False);
553 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
555 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
556 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
557 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
558 EXPECTED(ret, False);
559 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
562 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
563 (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
564 EXPECTED(ret, False);
565 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
567 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
568 (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
569 EXPECTED(ret, False);
570 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
573 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
574 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
575 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
576 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
578 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
581 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
582 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
583 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
584 (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
585 !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
586 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
588 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
590 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
591 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
592 (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&
593 (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);
595 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
597 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
598 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
599 (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&
600 (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);
602 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
604 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
605 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
606 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
607 !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&
608 (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);
610 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
612 smbcli_close(cli1->tree, fnum1);
613 smbcli_close(cli2->tree, fnum2);
614 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
615 f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
616 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
617 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
618 NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
619 ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
620 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
621 smbcli_close(cli1->tree, f);
622 smbcli_close(cli1->tree, fnum1);
624 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
627 smbcli_close(cli1->tree, fnum1);
628 smbcli_close(cli2->tree, fnum2);
629 smbcli_unlink(cli1->tree, fname);
630 torture_close_connection(cli1);
631 torture_close_connection(cli2);
633 printf("finished locktest4\n");
638 looks at lock upgrade/downgrade.
640 BOOL torture_locktest5(void)
642 struct smbcli_state *cli1, *cli2;
643 const char *fname = BASEDIR "\\lockt5.lck";
644 int fnum1, fnum2, fnum3;
649 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
653 printf("starting locktest5\n");
655 if (!torture_setup_dir(cli1, BASEDIR)) {
659 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
660 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
661 fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
663 memset(buf, 0, sizeof(buf));
665 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
666 printf("Failed to create file\n");
671 /* Check for NT bug... */
672 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
673 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
674 smbcli_close(cli1->tree, fnum1);
675 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
676 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
678 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
679 smbcli_close(cli1->tree, fnum1);
680 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
681 smbcli_unlock(cli1->tree, fnum3, 0, 1);
683 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
684 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
686 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
688 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
689 EXPECTED(ret, False);
691 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
693 /* Unlock the process 2 lock. */
694 smbcli_unlock(cli2->tree, fnum2, 0, 4);
696 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
697 EXPECTED(ret, False);
699 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
701 /* Unlock the process 1 fnum3 lock. */
702 smbcli_unlock(cli1->tree, fnum3, 0, 4);
704 /* Stack 2 more locks here. */
705 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
706 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
709 printf("the same process %s stack read locks\n", ret?"can":"cannot");
711 /* Unlock the first process lock, then check this was the WRITE lock that was
714 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
715 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
718 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
720 /* Unlock the process 2 lock. */
721 smbcli_unlock(cli2->tree, fnum2, 0, 4);
723 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
725 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
726 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
727 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
730 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
732 /* Ensure the next unlock fails. */
733 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
734 EXPECTED(ret, False);
735 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
737 /* Ensure connection 2 can get a write lock. */
738 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
741 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
745 smbcli_close(cli1->tree, fnum1);
746 smbcli_close(cli2->tree, fnum2);
747 smbcli_unlink(cli1->tree, fname);
748 if (!torture_close_connection(cli1)) {
751 if (!torture_close_connection(cli2)) {
755 printf("finished locktest5\n");
761 tries the unusual lockingX locktype bits
763 BOOL torture_locktest6(void)
765 struct smbcli_state *cli;
766 const char *fname[1] = { "\\lock6.txt" };
771 if (!torture_open_connection(&cli)) {
775 if (!torture_setup_dir(cli, BASEDIR)) {
779 printf("starting locktest6\n");
782 printf("Testing %s\n", fname[i]);
784 smbcli_unlink(cli->tree, fname[i]);
786 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
787 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
788 smbcli_close(cli->tree, fnum);
789 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
791 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
792 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
793 smbcli_close(cli->tree, fnum);
794 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
796 smbcli_unlink(cli->tree, fname[i]);
799 torture_close_connection(cli);
801 printf("finished locktest6\n");
805 BOOL torture_locktest7(void)
807 struct smbcli_state *cli1;
808 const char *fname = BASEDIR "\\lockt7.lck";
813 BOOL correct = False;
815 if (!torture_open_connection(&cli1)) {
819 printf("starting locktest7\n");
821 if (!torture_setup_dir(cli1, BASEDIR)) {
825 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
827 memset(buf, 0, sizeof(buf));
829 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
830 printf("Failed to create file (%s)\n", __location__);
834 cli1->session->pid = 1;
836 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
837 printf("Unable to apply read lock on range 130:4, error was %s (%s)\n",
838 smbcli_errstr(cli1->tree), __location__);
841 printf("pid1 successfully locked range 130:4 for READ\n");
844 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
845 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
846 smbcli_errstr(cli1->tree), __location__);
849 printf("pid1 successfully read the range 130:4\n");
852 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
853 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
854 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
855 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
860 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n",
865 cli1->session->pid = 2;
867 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
868 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
870 printf("pid2 successfully read the range 130:4\n");
873 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
874 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
875 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
876 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
881 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
886 cli1->session->pid = 1;
887 smbcli_unlock(cli1->tree, fnum1, 130, 4);
889 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
890 printf("Unable to apply write lock on range 130:4, error was %s (%s)\n",
891 smbcli_errstr(cli1->tree), __location__);
894 printf("pid1 successfully locked range 130:4 for WRITE\n");
897 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
898 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
899 smbcli_errstr(cli1->tree), __location__);
902 printf("pid1 successfully read the range 130:4\n");
905 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
906 printf("pid1 unable to write to the range 130:4, error was %s (%s)\n",
907 smbcli_errstr(cli1->tree), __location__);
910 printf("pid1 successfully wrote to the range 130:4\n");
913 cli1->session->pid = 2;
915 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
916 printf("pid2 unable to read the range 130:4, error was %s\n",
917 smbcli_errstr(cli1->tree));
918 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
919 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
924 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n",
929 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
930 printf("pid2 unable to write to the range 130:4, error was %s\n",
931 smbcli_errstr(cli1->tree));
932 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
933 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
938 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
943 printf("Testing truncate of locked file.\n");
945 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
948 printf("Unable to truncate locked file (%s)\n", __location__);
952 printf("Truncated locked file.\n");
955 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
956 printf("getatr failed (%s) (%s)\n", smbcli_errstr(cli1->tree), __location__);
962 printf("Unable to truncate locked file. Size was %u (%s)\n", size, __location__);
967 cli1->session->pid = 1;
969 smbcli_unlock(cli1->tree, fnum1, 130, 4);
973 smbcli_close(cli1->tree, fnum1);
974 smbcli_close(cli1->tree, fnum2);
975 smbcli_unlink(cli1->tree, fname);
976 torture_close_connection(cli1);
978 printf("finished locktest7\n");