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, 0) ||
50 !torture_open_connection(&cli2, 1)) {
54 printf("starting locktest1\n");
56 if (!torture_setup_dir(cli1, BASEDIR)) {
60 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
62 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
65 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
67 printf("(%s) open2 of %s failed (%s)\n",
68 __location__, fname, smbcli_errstr(cli1->tree));
71 fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
73 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
77 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
78 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
83 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
84 printf("lock2 succeeded! This is a locking bug\n");
87 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
88 NT_STATUS_LOCK_NOT_GRANTED)) return False;
91 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
92 printf("lock2 succeeded! This is a locking bug\n");
95 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
96 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
99 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 5, 9, 0, WRITE_LOCK))) {
100 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
104 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 5, 9, 0, WRITE_LOCK))) {
105 printf("lock2 succeeded! This is a locking bug\n");
108 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
109 NT_STATUS_LOCK_NOT_GRANTED)) return False;
112 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
113 printf("lock2 succeeded! This is a locking bug\n");
116 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
117 NT_STATUS_LOCK_NOT_GRANTED)) return False;
120 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
121 printf("lock2 succeeded! This is a locking bug\n");
124 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
125 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
128 lock_timeout = (6 + (random() % 20));
129 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
131 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
132 printf("lock3 succeeded! This is a locking bug\n");
135 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
136 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
141 printf("error: This server appears not to support timed lock requests\n");
143 printf("server slept for %u seconds for a %u second timeout\n",
144 (uint_t)(t2-t1), lock_timeout);
146 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
147 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
151 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
152 printf("lock4 succeeded! This is a locking bug\n");
155 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
156 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
159 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
160 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
164 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
165 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
169 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
170 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
175 if (!torture_close_connection(cli1)) {
179 if (!torture_close_connection(cli2)) {
183 printf("Passed locktest1\n");
189 This test checks that
191 1) the server supports multiple locking contexts on the one SMB
192 connection, distinguished by PID.
194 2) the server correctly fails overlapping locks made by the same PID (this
195 goes against POSIX behaviour, which is why it is tricky to implement)
197 3) the server denies unlock requests by an incorrect client PID
199 BOOL torture_locktest2(struct torture_context *torture)
201 struct smbcli_state *cli;
202 const char *fname = BASEDIR "\\lockt2.lck";
203 int fnum1, fnum2, fnum3;
206 if (!torture_open_connection(&cli, 0)) {
210 printf("starting locktest2\n");
212 if (!torture_setup_dir(cli, BASEDIR)) {
216 printf("Testing pid context\n");
218 cli->session->pid = 1;
220 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
222 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
226 fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
228 printf("(%s) open2 of %s failed (%s)\n",
229 __location__, fname, smbcli_errstr(cli->tree));
233 cli->session->pid = 2;
235 fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
237 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
241 cli->session->pid = 1;
243 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
244 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
248 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
249 printf("WRITE lock1 succeeded! This is a locking bug\n");
252 if (!check_error(__location__, cli, ERRDOS, ERRlock,
253 NT_STATUS_LOCK_NOT_GRANTED)) return False;
256 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
257 printf("WRITE lock2 succeeded! This is a locking bug\n");
260 if (!check_error(__location__, cli, ERRDOS, ERRlock,
261 NT_STATUS_LOCK_NOT_GRANTED)) return False;
264 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
265 printf("READ lock2 succeeded! This is a locking bug\n");
268 if (!check_error(__location__, cli, ERRDOS, ERRlock,
269 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
272 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
273 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
276 cli->session->pid = 2;
278 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
279 printf("unlock at 100 succeeded! This is a locking bug\n");
283 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
284 printf("unlock1 succeeded! This is a locking bug\n");
287 if (!check_error(__location__, cli,
288 ERRDOS, ERRnotlocked,
289 NT_STATUS_RANGE_NOT_LOCKED)) return False;
292 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
293 printf("unlock2 succeeded! This is a locking bug\n");
296 if (!check_error(__location__, cli,
297 ERRDOS, ERRnotlocked,
298 NT_STATUS_RANGE_NOT_LOCKED)) return False;
301 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
302 printf("lock3 succeeded! This is a locking bug\n");
305 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
308 cli->session->pid = 1;
310 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
311 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
315 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
316 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
320 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
321 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
325 if (!torture_close_connection(cli)) {
329 printf("locktest2 finished\n");
336 This test checks that
338 1) the server supports the full offset range in lock requests
340 BOOL torture_locktest3(struct torture_context *torture)
342 struct smbcli_state *cli1, *cli2;
343 const char *fname = BASEDIR "\\lockt3.lck";
347 extern int torture_numops;
349 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
351 if (!torture_open_connection(&cli1, 0) ||
352 !torture_open_connection(&cli2, 1)) {
356 printf("starting locktest3\n");
358 printf("Testing 32 bit offset ranges\n");
360 if (!torture_setup_dir(cli1, BASEDIR)) {
364 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
366 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
369 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
371 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
375 printf("Establishing %d locks\n", torture_numops);
377 for (offset=i=0;i<torture_numops;i++) {
379 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
380 printf("lock1 %d failed (%s)\n",
382 smbcli_errstr(cli1->tree));
386 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
387 printf("lock2 %d failed (%s)\n",
389 smbcli_errstr(cli1->tree));
394 printf("Testing %d locks\n", torture_numops);
396 for (offset=i=0;i<torture_numops;i++) {
399 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
400 printf("error: lock1 %d succeeded!\n", i);
404 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
405 printf("error: lock2 %d succeeded!\n", i);
409 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
410 printf("error: lock3 %d succeeded!\n", i);
414 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
415 printf("error: lock4 %d succeeded!\n", i);
420 printf("Removing %d locks\n", torture_numops);
422 for (offset=i=0;i<torture_numops;i++) {
425 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
426 printf("unlock1 %d failed (%s)\n",
428 smbcli_errstr(cli1->tree));
432 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
433 printf("unlock2 %d failed (%s)\n",
435 smbcli_errstr(cli1->tree));
440 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
441 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
445 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
446 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
450 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
451 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
455 if (!torture_close_connection(cli1)) {
459 if (!torture_close_connection(cli2)) {
463 printf("finished locktest3\n");
468 #define EXPECTED(ret, v) if ((ret) != (v)) { \
469 printf("** "); correct = False; \
473 looks at overlapping locks
475 BOOL torture_locktest4(struct torture_context *torture)
477 struct smbcli_state *cli1, *cli2;
478 const char *fname = BASEDIR "\\lockt4.lck";
484 if (!torture_open_connection(&cli1, 0) ||
485 !torture_open_connection(&cli2, 1)) {
489 printf("starting locktest4\n");
491 if (!torture_setup_dir(cli1, BASEDIR)) {
495 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
496 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
498 memset(buf, 0, sizeof(buf));
500 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
501 printf("Failed to create file\n");
506 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
507 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
508 EXPECTED(ret, False);
509 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
511 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
512 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
514 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
516 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
517 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
518 EXPECTED(ret, False);
519 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
521 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
522 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
524 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
526 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
527 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
528 EXPECTED(ret, False);
529 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
531 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
532 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
534 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
536 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
537 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
539 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
541 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
542 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
543 EXPECTED(ret, False);
544 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
546 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
547 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
548 EXPECTED(ret, False);
549 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
551 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
552 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
554 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
556 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
557 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
558 EXPECTED(ret, False);
559 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
561 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
562 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
563 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
564 EXPECTED(ret, False);
565 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
568 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
569 (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
570 EXPECTED(ret, False);
571 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
573 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
574 (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
575 EXPECTED(ret, False);
576 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
579 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
580 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
581 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
582 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
584 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
587 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
588 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
589 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
590 (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
591 !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
592 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
594 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
596 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
597 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
598 (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&
599 (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);
601 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
603 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
604 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
605 (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&
606 (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);
608 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
610 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
611 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
612 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
613 !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&
614 (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);
616 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
618 smbcli_close(cli1->tree, fnum1);
619 smbcli_close(cli2->tree, fnum2);
620 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
621 f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
622 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
623 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
624 NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
625 ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
626 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
627 smbcli_close(cli1->tree, f);
628 smbcli_close(cli1->tree, fnum1);
630 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
633 smbcli_close(cli1->tree, fnum1);
634 smbcli_close(cli2->tree, fnum2);
635 smbcli_unlink(cli1->tree, fname);
636 torture_close_connection(cli1);
637 torture_close_connection(cli2);
639 printf("finished locktest4\n");
644 looks at lock upgrade/downgrade.
646 BOOL torture_locktest5(struct torture_context *torture)
648 struct smbcli_state *cli1, *cli2;
649 const char *fname = BASEDIR "\\lockt5.lck";
650 int fnum1, fnum2, fnum3;
655 if (!torture_open_connection(&cli1, 0) ||
656 !torture_open_connection(&cli2, 1)) {
660 printf("starting locktest5\n");
662 if (!torture_setup_dir(cli1, BASEDIR)) {
666 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
667 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
668 fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
670 memset(buf, 0, sizeof(buf));
672 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
673 printf("Failed to create file\n");
678 /* Check for NT bug... */
679 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
680 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
681 smbcli_close(cli1->tree, fnum1);
682 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
683 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
685 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
686 smbcli_close(cli1->tree, fnum1);
687 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
688 smbcli_unlock(cli1->tree, fnum3, 0, 1);
690 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
691 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
693 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
695 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
696 EXPECTED(ret, False);
698 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
700 /* Unlock the process 2 lock. */
701 smbcli_unlock(cli2->tree, fnum2, 0, 4);
703 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
704 EXPECTED(ret, False);
706 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
708 /* Unlock the process 1 fnum3 lock. */
709 smbcli_unlock(cli1->tree, fnum3, 0, 4);
711 /* Stack 2 more locks here. */
712 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
713 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
716 printf("the same process %s stack read locks\n", ret?"can":"cannot");
718 /* Unlock the first process lock, then check this was the WRITE lock that was
721 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
722 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
725 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
727 /* Unlock the process 2 lock. */
728 smbcli_unlock(cli2->tree, fnum2, 0, 4);
730 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
732 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
733 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
734 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
737 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
739 /* Ensure the next unlock fails. */
740 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
741 EXPECTED(ret, False);
742 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
744 /* Ensure connection 2 can get a write lock. */
745 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
748 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
752 smbcli_close(cli1->tree, fnum1);
753 smbcli_close(cli2->tree, fnum2);
754 smbcli_unlink(cli1->tree, fname);
755 if (!torture_close_connection(cli1)) {
758 if (!torture_close_connection(cli2)) {
762 printf("finished locktest5\n");
768 tries the unusual lockingX locktype bits
770 BOOL torture_locktest6(struct torture_context *torture)
772 struct smbcli_state *cli;
773 const char *fname[1] = { "\\lock6.txt" };
778 if (!torture_open_connection(&cli, 0)) {
782 if (!torture_setup_dir(cli, BASEDIR)) {
786 printf("starting locktest6\n");
789 printf("Testing %s\n", fname[i]);
791 smbcli_unlink(cli->tree, fname[i]);
793 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
794 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
795 smbcli_close(cli->tree, fnum);
796 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
798 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
799 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
800 smbcli_close(cli->tree, fnum);
801 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
803 smbcli_unlink(cli->tree, fname[i]);
806 torture_close_connection(cli);
808 printf("finished locktest6\n");
812 BOOL torture_locktest7(struct torture_context *torture)
814 struct smbcli_state *cli1;
815 const char *fname = BASEDIR "\\lockt7.lck";
820 BOOL correct = False;
822 if (!torture_open_connection(&cli1, 0)) {
826 printf("starting locktest7\n");
828 if (!torture_setup_dir(cli1, BASEDIR)) {
832 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
834 memset(buf, 0, sizeof(buf));
836 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
837 printf("Failed to create file (%s)\n", __location__);
841 cli1->session->pid = 1;
843 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
844 printf("Unable to apply read lock on range 130:4, error was %s (%s)\n",
845 smbcli_errstr(cli1->tree), __location__);
848 printf("pid1 successfully locked range 130:4 for READ\n");
851 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
852 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
853 smbcli_errstr(cli1->tree), __location__);
856 printf("pid1 successfully read the range 130:4\n");
859 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
860 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
861 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
862 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
867 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n",
872 cli1->session->pid = 2;
874 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
875 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
877 printf("pid2 successfully read the range 130:4\n");
880 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
881 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
882 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
883 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
888 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
893 cli1->session->pid = 1;
894 smbcli_unlock(cli1->tree, fnum1, 130, 4);
896 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
897 printf("Unable to apply write lock on range 130:4, error was %s (%s)\n",
898 smbcli_errstr(cli1->tree), __location__);
901 printf("pid1 successfully locked range 130:4 for WRITE\n");
904 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
905 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
906 smbcli_errstr(cli1->tree), __location__);
909 printf("pid1 successfully read the range 130:4\n");
912 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
913 printf("pid1 unable to write to the range 130:4, error was %s (%s)\n",
914 smbcli_errstr(cli1->tree), __location__);
917 printf("pid1 successfully wrote to the range 130:4\n");
920 cli1->session->pid = 2;
922 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
923 printf("pid2 unable to read the range 130:4, error was %s\n",
924 smbcli_errstr(cli1->tree));
925 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
926 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
931 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n",
936 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
937 printf("pid2 unable to write to the range 130:4, error was %s\n",
938 smbcli_errstr(cli1->tree));
939 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
940 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
945 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
950 printf("Testing truncate of locked file.\n");
952 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
955 printf("Unable to truncate locked file (%s)\n", __location__);
959 printf("Truncated locked file.\n");
962 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
963 printf("getatr failed (%s) (%s)\n", smbcli_errstr(cli1->tree), __location__);
969 printf("Unable to truncate locked file. Size was %u (%s)\n",
970 (unsigned)size, __location__);
975 cli1->session->pid = 1;
977 smbcli_unlock(cli1->tree, fnum1, 130, 4);
981 smbcli_close(cli1->tree, fnum1);
982 smbcli_close(cli1->tree, fnum2);
983 smbcli_unlink(cli1->tree, fname);
984 torture_close_connection(cli1);
986 printf("finished locktest7\n");