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"
28 #define BASEDIR "\\locktest"
31 This test checks for two things:
33 1) correct support for retaining locks over a close (ie. the server
34 must not use posix semantics)
35 2) support for lock timeouts
37 BOOL torture_locktest1(void)
39 struct smbcli_state *cli1, *cli2;
40 const char *fname = BASEDIR "\\lockt1.lck";
41 int fnum1, fnum2, fnum3;
45 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
49 printf("starting locktest1\n");
51 if (!torture_setup_dir(cli1, BASEDIR)) {
55 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
57 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
60 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
62 printf("(%s) open2 of %s failed (%s)\n",
63 __location__, fname, smbcli_errstr(cli1->tree));
66 fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
68 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
72 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
73 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
78 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
79 printf("lock2 succeeded! This is a locking bug\n");
82 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
83 NT_STATUS_LOCK_NOT_GRANTED)) return False;
86 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
87 printf("lock2 succeeded! This is a locking bug\n");
90 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
91 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
94 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 5, 9, 0, WRITE_LOCK))) {
95 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
99 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 5, 9, 0, WRITE_LOCK))) {
100 printf("lock2 succeeded! This is a locking bug\n");
103 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
104 NT_STATUS_LOCK_NOT_GRANTED)) return False;
107 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
108 printf("lock2 succeeded! This is a locking bug\n");
111 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
112 NT_STATUS_LOCK_NOT_GRANTED)) return False;
115 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
116 printf("lock2 succeeded! This is a locking bug\n");
119 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
120 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
123 lock_timeout = (6 + (random() % 20));
124 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
126 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
127 printf("lock3 succeeded! This is a locking bug\n");
130 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
131 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
136 printf("error: This server appears not to support timed lock requests\n");
138 printf("server slept for %u seconds for a %u second timeout\n",
139 (uint_t)(t2-t1), lock_timeout);
141 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
142 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
146 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
147 printf("lock4 succeeded! This is a locking bug\n");
150 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
151 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
154 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
155 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
159 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
160 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
164 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
165 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
170 if (!torture_close_connection(cli1)) {
174 if (!torture_close_connection(cli2)) {
178 printf("Passed locktest1\n");
184 This test checks that
186 1) the server supports multiple locking contexts on the one SMB
187 connection, distinguished by PID.
189 2) the server correctly fails overlapping locks made by the same PID (this
190 goes against POSIX behaviour, which is why it is tricky to implement)
192 3) the server denies unlock requests by an incorrect client PID
194 BOOL torture_locktest2(void)
196 struct smbcli_state *cli;
197 const char *fname = BASEDIR "\\lockt2.lck";
198 int fnum1, fnum2, fnum3;
201 if (!torture_open_connection(&cli)) {
205 printf("starting locktest2\n");
207 if (!torture_setup_dir(cli, BASEDIR)) {
211 printf("Testing pid context\n");
213 cli->session->pid = 1;
215 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
217 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
221 fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
223 printf("(%s) open2 of %s failed (%s)\n",
224 __location__, fname, smbcli_errstr(cli->tree));
228 cli->session->pid = 2;
230 fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
232 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
236 cli->session->pid = 1;
238 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
239 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
243 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
244 printf("WRITE lock1 succeeded! This is a locking bug\n");
247 if (!check_error(__location__, cli, ERRDOS, ERRlock,
248 NT_STATUS_LOCK_NOT_GRANTED)) return False;
251 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
252 printf("WRITE lock2 succeeded! This is a locking bug\n");
255 if (!check_error(__location__, cli, ERRDOS, ERRlock,
256 NT_STATUS_LOCK_NOT_GRANTED)) return False;
259 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
260 printf("READ lock2 succeeded! This is a locking bug\n");
263 if (!check_error(__location__, cli, ERRDOS, ERRlock,
264 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
267 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
268 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
271 cli->session->pid = 2;
273 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
274 printf("unlock at 100 succeeded! This is a locking bug\n");
278 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
279 printf("unlock1 succeeded! This is a locking bug\n");
282 if (!check_error(__location__, cli,
284 NT_STATUS_RANGE_NOT_LOCKED)) return False;
287 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
288 printf("unlock2 succeeded! This is a locking bug\n");
291 if (!check_error(__location__, cli,
293 NT_STATUS_RANGE_NOT_LOCKED)) return False;
296 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
297 printf("lock3 succeeded! This is a locking bug\n");
300 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
303 cli->session->pid = 1;
305 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
306 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
310 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
311 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
315 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
316 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
320 if (!torture_close_connection(cli)) {
324 printf("locktest2 finished\n");
331 This test checks that
333 1) the server supports the full offset range in lock requests
335 BOOL torture_locktest3(void)
337 struct smbcli_state *cli1, *cli2;
338 const char *fname = BASEDIR "\\lockt3.lck";
342 extern int torture_numops;
344 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
346 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
350 printf("starting locktest3\n");
352 printf("Testing 32 bit offset ranges\n");
354 if (!torture_setup_dir(cli1, BASEDIR)) {
358 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
360 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
363 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
365 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
369 printf("Establishing %d locks\n", torture_numops);
371 for (offset=i=0;i<torture_numops;i++) {
373 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
374 printf("lock1 %d failed (%s)\n",
376 smbcli_errstr(cli1->tree));
380 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
381 printf("lock2 %d failed (%s)\n",
383 smbcli_errstr(cli1->tree));
388 printf("Testing %d locks\n", torture_numops);
390 for (offset=i=0;i<torture_numops;i++) {
393 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
394 printf("error: lock1 %d succeeded!\n", i);
398 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
399 printf("error: lock2 %d succeeded!\n", i);
403 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
404 printf("error: lock3 %d succeeded!\n", i);
408 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
409 printf("error: lock4 %d succeeded!\n", i);
414 printf("Removing %d locks\n", torture_numops);
416 for (offset=i=0;i<torture_numops;i++) {
419 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
420 printf("unlock1 %d failed (%s)\n",
422 smbcli_errstr(cli1->tree));
426 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
427 printf("unlock2 %d failed (%s)\n",
429 smbcli_errstr(cli1->tree));
434 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
435 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
439 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
440 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
444 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
445 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
449 if (!torture_close_connection(cli1)) {
453 if (!torture_close_connection(cli2)) {
457 printf("finished locktest3\n");
462 #define EXPECTED(ret, v) if ((ret) != (v)) { \
463 printf("** "); correct = False; \
467 looks at overlapping locks
469 BOOL torture_locktest4(void)
471 struct smbcli_state *cli1, *cli2;
472 const char *fname = BASEDIR "\\lockt4.lck";
478 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
482 printf("starting locktest4\n");
484 if (!torture_setup_dir(cli1, BASEDIR)) {
488 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
489 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
491 memset(buf, 0, sizeof(buf));
493 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
494 printf("Failed to create file\n");
499 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
500 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
501 EXPECTED(ret, False);
502 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
504 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
505 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
507 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
509 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
510 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
511 EXPECTED(ret, False);
512 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
514 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
515 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
517 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
519 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
520 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
521 EXPECTED(ret, False);
522 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
524 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
525 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
527 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
529 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
530 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
532 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
534 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
535 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
536 EXPECTED(ret, False);
537 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
539 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
540 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
541 EXPECTED(ret, False);
542 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
544 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
545 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
547 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
549 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
550 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
551 EXPECTED(ret, False);
552 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
554 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
555 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
556 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
557 EXPECTED(ret, False);
558 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
561 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
562 (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
563 EXPECTED(ret, False);
564 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
566 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
567 (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
568 EXPECTED(ret, False);
569 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
572 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
573 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
574 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
575 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
577 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
580 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
581 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
582 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
583 (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
584 !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
585 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
587 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
589 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
590 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
591 (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&
592 (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);
594 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
596 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
597 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
598 (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&
599 (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);
601 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
603 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
604 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
605 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
606 !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&
607 (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);
609 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
611 smbcli_close(cli1->tree, fnum1);
612 smbcli_close(cli2->tree, fnum2);
613 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
614 f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
615 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
616 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
617 NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
618 ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
619 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
620 smbcli_close(cli1->tree, f);
621 smbcli_close(cli1->tree, fnum1);
623 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
626 smbcli_close(cli1->tree, fnum1);
627 smbcli_close(cli2->tree, fnum2);
628 smbcli_unlink(cli1->tree, fname);
629 torture_close_connection(cli1);
630 torture_close_connection(cli2);
632 printf("finished locktest4\n");
637 looks at lock upgrade/downgrade.
639 BOOL torture_locktest5(void)
641 struct smbcli_state *cli1, *cli2;
642 const char *fname = BASEDIR "\\lockt5.lck";
643 int fnum1, fnum2, fnum3;
648 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
652 printf("starting locktest5\n");
654 if (!torture_setup_dir(cli1, BASEDIR)) {
658 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
659 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
660 fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
662 memset(buf, 0, sizeof(buf));
664 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
665 printf("Failed to create file\n");
670 /* Check for NT bug... */
671 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
672 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
673 smbcli_close(cli1->tree, fnum1);
674 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
675 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
677 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
678 smbcli_close(cli1->tree, fnum1);
679 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
680 smbcli_unlock(cli1->tree, fnum3, 0, 1);
682 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
683 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
685 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
687 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
688 EXPECTED(ret, False);
690 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
692 /* Unlock the process 2 lock. */
693 smbcli_unlock(cli2->tree, fnum2, 0, 4);
695 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
696 EXPECTED(ret, False);
698 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
700 /* Unlock the process 1 fnum3 lock. */
701 smbcli_unlock(cli1->tree, fnum3, 0, 4);
703 /* Stack 2 more locks here. */
704 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
705 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
708 printf("the same process %s stack read locks\n", ret?"can":"cannot");
710 /* Unlock the first process lock, then check this was the WRITE lock that was
713 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
714 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
717 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
719 /* Unlock the process 2 lock. */
720 smbcli_unlock(cli2->tree, fnum2, 0, 4);
722 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
724 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
725 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
726 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
729 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
731 /* Ensure the next unlock fails. */
732 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
733 EXPECTED(ret, False);
734 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
736 /* Ensure connection 2 can get a write lock. */
737 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
740 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
744 smbcli_close(cli1->tree, fnum1);
745 smbcli_close(cli2->tree, fnum2);
746 smbcli_unlink(cli1->tree, fname);
747 if (!torture_close_connection(cli1)) {
750 if (!torture_close_connection(cli2)) {
754 printf("finished locktest5\n");
760 tries the unusual lockingX locktype bits
762 BOOL torture_locktest6(void)
764 struct smbcli_state *cli;
765 const char *fname[1] = { "\\lock6.txt" };
770 if (!torture_open_connection(&cli)) {
774 if (!torture_setup_dir(cli, BASEDIR)) {
778 printf("starting locktest6\n");
781 printf("Testing %s\n", fname[i]);
783 smbcli_unlink(cli->tree, fname[i]);
785 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
786 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
787 smbcli_close(cli->tree, fnum);
788 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
790 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
791 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
792 smbcli_close(cli->tree, fnum);
793 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
795 smbcli_unlink(cli->tree, fname[i]);
798 torture_close_connection(cli);
800 printf("finished locktest6\n");
804 BOOL torture_locktest7(void)
806 struct smbcli_state *cli1;
807 const char *fname = BASEDIR "\\lockt7.lck";
812 BOOL correct = False;
814 if (!torture_open_connection(&cli1)) {
818 printf("starting locktest7\n");
820 if (!torture_setup_dir(cli1, BASEDIR)) {
824 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
826 memset(buf, 0, sizeof(buf));
828 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
829 printf("Failed to create file (%s)\n", __location__);
833 cli1->session->pid = 1;
835 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
836 printf("Unable to apply read lock on range 130:4, error was %s (%s)\n",
837 smbcli_errstr(cli1->tree), __location__);
840 printf("pid1 successfully locked range 130:4 for READ\n");
843 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
844 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
845 smbcli_errstr(cli1->tree), __location__);
848 printf("pid1 successfully read the range 130:4\n");
851 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
852 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
853 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
854 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
859 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n",
864 cli1->session->pid = 2;
866 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
867 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
869 printf("pid2 successfully read the range 130:4\n");
872 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
873 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
874 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
875 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
880 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
885 cli1->session->pid = 1;
886 smbcli_unlock(cli1->tree, fnum1, 130, 4);
888 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
889 printf("Unable to apply write lock on range 130:4, error was %s (%s)\n",
890 smbcli_errstr(cli1->tree), __location__);
893 printf("pid1 successfully locked range 130:4 for WRITE\n");
896 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
897 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
898 smbcli_errstr(cli1->tree), __location__);
901 printf("pid1 successfully read the range 130:4\n");
904 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
905 printf("pid1 unable to write to the range 130:4, error was %s (%s)\n",
906 smbcli_errstr(cli1->tree), __location__);
909 printf("pid1 successfully wrote to the range 130:4\n");
912 cli1->session->pid = 2;
914 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
915 printf("pid2 unable to read the range 130:4, error was %s\n",
916 smbcli_errstr(cli1->tree));
917 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
918 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
923 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n",
928 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
929 printf("pid2 unable to write to the range 130:4, error was %s\n",
930 smbcli_errstr(cli1->tree));
931 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
932 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
937 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
942 printf("Testing truncate of locked file.\n");
944 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
947 printf("Unable to truncate locked file (%s)\n", __location__);
951 printf("Truncated locked file.\n");
954 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
955 printf("getatr failed (%s) (%s)\n", smbcli_errstr(cli1->tree), __location__);
961 printf("Unable to truncate locked file. Size was %u (%s)\n", size, __location__);
966 cli1->session->pid = 1;
968 smbcli_unlock(cli1->tree, fnum1, 130, 4);
972 smbcli_close(cli1->tree, fnum1);
973 smbcli_close(cli1->tree, fnum2);
974 smbcli_unlink(cli1->tree, fname);
975 torture_close_connection(cli1);
977 printf("finished locktest7\n");