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 "torture/torture.h"
26 #include "libcli/raw/libcliraw.h"
27 #include "system/time.h"
28 #include "system/filesys.h"
30 #define BASEDIR "\\locktest"
33 This test checks for two things:
35 1) correct support for retaining locks over a close (ie. the server
36 must not use posix semantics)
37 2) support for lock timeouts
39 BOOL torture_locktest1(void)
41 struct smbcli_state *cli1, *cli2;
42 const char *fname = BASEDIR "\\lockt1.lck";
43 int fnum1, fnum2, fnum3;
47 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
51 printf("starting locktest1\n");
53 if (!torture_setup_dir(cli1, BASEDIR)) {
57 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
59 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
62 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
64 printf("(%s) open2 of %s failed (%s)\n",
65 __location__, fname, smbcli_errstr(cli1->tree));
68 fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
70 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
74 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
75 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
80 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
81 printf("lock2 succeeded! This is a locking bug\n");
84 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
85 NT_STATUS_LOCK_NOT_GRANTED)) return False;
88 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
89 printf("lock2 succeeded! This is a locking bug\n");
92 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
93 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
96 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 5, 9, 0, WRITE_LOCK))) {
97 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
101 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 5, 9, 0, WRITE_LOCK))) {
102 printf("lock2 succeeded! This is a locking bug\n");
105 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
106 NT_STATUS_LOCK_NOT_GRANTED)) return False;
109 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
110 printf("lock2 succeeded! This is a locking bug\n");
113 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
114 NT_STATUS_LOCK_NOT_GRANTED)) return False;
117 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
118 printf("lock2 succeeded! This is a locking bug\n");
121 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
122 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
125 lock_timeout = (6 + (random() % 20));
126 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
128 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
129 printf("lock3 succeeded! This is a locking bug\n");
132 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
133 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
138 printf("error: This server appears not to support timed lock requests\n");
140 printf("server slept for %u seconds for a %u second timeout\n",
141 (uint_t)(t2-t1), lock_timeout);
143 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
144 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
148 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
149 printf("lock4 succeeded! This is a locking bug\n");
152 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
153 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
156 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
157 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
161 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
162 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
166 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
167 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
172 if (!torture_close_connection(cli1)) {
176 if (!torture_close_connection(cli2)) {
180 printf("Passed locktest1\n");
186 This test checks that
188 1) the server supports multiple locking contexts on the one SMB
189 connection, distinguished by PID.
191 2) the server correctly fails overlapping locks made by the same PID (this
192 goes against POSIX behaviour, which is why it is tricky to implement)
194 3) the server denies unlock requests by an incorrect client PID
196 BOOL torture_locktest2(void)
198 struct smbcli_state *cli;
199 const char *fname = BASEDIR "\\lockt2.lck";
200 int fnum1, fnum2, fnum3;
203 if (!torture_open_connection(&cli)) {
207 printf("starting locktest2\n");
209 if (!torture_setup_dir(cli, BASEDIR)) {
213 printf("Testing pid context\n");
215 cli->session->pid = 1;
217 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
219 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
223 fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
225 printf("(%s) open2 of %s failed (%s)\n",
226 __location__, fname, smbcli_errstr(cli->tree));
230 cli->session->pid = 2;
232 fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
234 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
238 cli->session->pid = 1;
240 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
241 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
245 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
246 printf("WRITE lock1 succeeded! This is a locking bug\n");
249 if (!check_error(__location__, cli, ERRDOS, ERRlock,
250 NT_STATUS_LOCK_NOT_GRANTED)) return False;
253 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
254 printf("WRITE lock2 succeeded! This is a locking bug\n");
257 if (!check_error(__location__, cli, ERRDOS, ERRlock,
258 NT_STATUS_LOCK_NOT_GRANTED)) return False;
261 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
262 printf("READ lock2 succeeded! This is a locking bug\n");
265 if (!check_error(__location__, cli, ERRDOS, ERRlock,
266 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
269 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
270 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
273 cli->session->pid = 2;
275 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
276 printf("unlock at 100 succeeded! This is a locking bug\n");
280 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
281 printf("unlock1 succeeded! This is a locking bug\n");
284 if (!check_error(__location__, cli,
285 ERRDOS, ERRnotlocked,
286 NT_STATUS_RANGE_NOT_LOCKED)) return False;
289 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
290 printf("unlock2 succeeded! This is a locking bug\n");
293 if (!check_error(__location__, cli,
294 ERRDOS, ERRnotlocked,
295 NT_STATUS_RANGE_NOT_LOCKED)) return False;
298 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
299 printf("lock3 succeeded! This is a locking bug\n");
302 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
305 cli->session->pid = 1;
307 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
308 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
312 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
313 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
317 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
318 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
322 if (!torture_close_connection(cli)) {
326 printf("locktest2 finished\n");
333 This test checks that
335 1) the server supports the full offset range in lock requests
337 BOOL torture_locktest3(void)
339 struct smbcli_state *cli1, *cli2;
340 const char *fname = BASEDIR "\\lockt3.lck";
344 extern int torture_numops;
346 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
348 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
352 printf("starting locktest3\n");
354 printf("Testing 32 bit offset ranges\n");
356 if (!torture_setup_dir(cli1, BASEDIR)) {
360 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
362 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
365 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
367 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
371 printf("Establishing %d locks\n", torture_numops);
373 for (offset=i=0;i<torture_numops;i++) {
375 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
376 printf("lock1 %d failed (%s)\n",
378 smbcli_errstr(cli1->tree));
382 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
383 printf("lock2 %d failed (%s)\n",
385 smbcli_errstr(cli1->tree));
390 printf("Testing %d locks\n", torture_numops);
392 for (offset=i=0;i<torture_numops;i++) {
395 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
396 printf("error: lock1 %d succeeded!\n", i);
400 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
401 printf("error: lock2 %d succeeded!\n", i);
405 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
406 printf("error: lock3 %d succeeded!\n", i);
410 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
411 printf("error: lock4 %d succeeded!\n", i);
416 printf("Removing %d locks\n", torture_numops);
418 for (offset=i=0;i<torture_numops;i++) {
421 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
422 printf("unlock1 %d failed (%s)\n",
424 smbcli_errstr(cli1->tree));
428 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
429 printf("unlock2 %d failed (%s)\n",
431 smbcli_errstr(cli1->tree));
436 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
437 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
441 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
442 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
446 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
447 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
451 if (!torture_close_connection(cli1)) {
455 if (!torture_close_connection(cli2)) {
459 printf("finished locktest3\n");
464 #define EXPECTED(ret, v) if ((ret) != (v)) { \
465 printf("** "); correct = False; \
469 looks at overlapping locks
471 BOOL torture_locktest4(void)
473 struct smbcli_state *cli1, *cli2;
474 const char *fname = BASEDIR "\\lockt4.lck";
480 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
484 printf("starting locktest4\n");
486 if (!torture_setup_dir(cli1, BASEDIR)) {
490 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
491 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
493 memset(buf, 0, sizeof(buf));
495 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
496 printf("Failed to create file\n");
501 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
502 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
503 EXPECTED(ret, False);
504 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
506 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
507 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
509 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
511 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
512 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
513 EXPECTED(ret, False);
514 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
516 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
517 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
519 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
521 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
522 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
523 EXPECTED(ret, False);
524 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
526 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
527 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
529 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
531 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
532 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
534 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
536 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
537 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
538 EXPECTED(ret, False);
539 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
541 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
542 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
543 EXPECTED(ret, False);
544 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
546 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
547 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
549 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
551 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
552 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
553 EXPECTED(ret, False);
554 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
556 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
557 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
558 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
559 EXPECTED(ret, False);
560 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
563 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
564 (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
565 EXPECTED(ret, False);
566 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
568 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
569 (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
570 EXPECTED(ret, False);
571 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
574 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
575 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
576 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
577 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
579 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
582 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
583 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
584 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
585 (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
586 !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
587 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
589 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
591 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
592 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
593 (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&
594 (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);
596 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
598 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
599 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
600 (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&
601 (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);
603 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
605 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
606 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
607 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
608 !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&
609 (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);
611 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
613 smbcli_close(cli1->tree, fnum1);
614 smbcli_close(cli2->tree, fnum2);
615 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
616 f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
617 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
618 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
619 NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
620 ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
621 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
622 smbcli_close(cli1->tree, f);
623 smbcli_close(cli1->tree, fnum1);
625 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
628 smbcli_close(cli1->tree, fnum1);
629 smbcli_close(cli2->tree, fnum2);
630 smbcli_unlink(cli1->tree, fname);
631 torture_close_connection(cli1);
632 torture_close_connection(cli2);
634 printf("finished locktest4\n");
639 looks at lock upgrade/downgrade.
641 BOOL torture_locktest5(void)
643 struct smbcli_state *cli1, *cli2;
644 const char *fname = BASEDIR "\\lockt5.lck";
645 int fnum1, fnum2, fnum3;
650 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
654 printf("starting locktest5\n");
656 if (!torture_setup_dir(cli1, BASEDIR)) {
660 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
661 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
662 fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
664 memset(buf, 0, sizeof(buf));
666 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
667 printf("Failed to create file\n");
672 /* Check for NT bug... */
673 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
674 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
675 smbcli_close(cli1->tree, fnum1);
676 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
677 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
679 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
680 smbcli_close(cli1->tree, fnum1);
681 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
682 smbcli_unlock(cli1->tree, fnum3, 0, 1);
684 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
685 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
687 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
689 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
690 EXPECTED(ret, False);
692 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
694 /* Unlock the process 2 lock. */
695 smbcli_unlock(cli2->tree, fnum2, 0, 4);
697 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
698 EXPECTED(ret, False);
700 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
702 /* Unlock the process 1 fnum3 lock. */
703 smbcli_unlock(cli1->tree, fnum3, 0, 4);
705 /* Stack 2 more locks here. */
706 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
707 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
710 printf("the same process %s stack read locks\n", ret?"can":"cannot");
712 /* Unlock the first process lock, then check this was the WRITE lock that was
715 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
716 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
719 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
721 /* Unlock the process 2 lock. */
722 smbcli_unlock(cli2->tree, fnum2, 0, 4);
724 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
726 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
727 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
728 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
731 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
733 /* Ensure the next unlock fails. */
734 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
735 EXPECTED(ret, False);
736 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
738 /* Ensure connection 2 can get a write lock. */
739 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
742 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
746 smbcli_close(cli1->tree, fnum1);
747 smbcli_close(cli2->tree, fnum2);
748 smbcli_unlink(cli1->tree, fname);
749 if (!torture_close_connection(cli1)) {
752 if (!torture_close_connection(cli2)) {
756 printf("finished locktest5\n");
762 tries the unusual lockingX locktype bits
764 BOOL torture_locktest6(void)
766 struct smbcli_state *cli;
767 const char *fname[1] = { "\\lock6.txt" };
772 if (!torture_open_connection(&cli)) {
776 if (!torture_setup_dir(cli, BASEDIR)) {
780 printf("starting locktest6\n");
783 printf("Testing %s\n", fname[i]);
785 smbcli_unlink(cli->tree, fname[i]);
787 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
788 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
789 smbcli_close(cli->tree, fnum);
790 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
792 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
793 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
794 smbcli_close(cli->tree, fnum);
795 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
797 smbcli_unlink(cli->tree, fname[i]);
800 torture_close_connection(cli);
802 printf("finished locktest6\n");
806 BOOL torture_locktest7(void)
808 struct smbcli_state *cli1;
809 const char *fname = BASEDIR "\\lockt7.lck";
814 BOOL correct = False;
816 if (!torture_open_connection(&cli1)) {
820 printf("starting locktest7\n");
822 if (!torture_setup_dir(cli1, BASEDIR)) {
826 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
828 memset(buf, 0, sizeof(buf));
830 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
831 printf("Failed to create file (%s)\n", __location__);
835 cli1->session->pid = 1;
837 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
838 printf("Unable to apply read lock on range 130:4, error was %s (%s)\n",
839 smbcli_errstr(cli1->tree), __location__);
842 printf("pid1 successfully locked range 130:4 for READ\n");
845 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
846 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
847 smbcli_errstr(cli1->tree), __location__);
850 printf("pid1 successfully read the range 130:4\n");
853 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
854 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
855 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
856 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
861 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n",
866 cli1->session->pid = 2;
868 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
869 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
871 printf("pid2 successfully read the range 130:4\n");
874 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
875 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
876 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
877 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
882 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
887 cli1->session->pid = 1;
888 smbcli_unlock(cli1->tree, fnum1, 130, 4);
890 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
891 printf("Unable to apply write lock on range 130:4, error was %s (%s)\n",
892 smbcli_errstr(cli1->tree), __location__);
895 printf("pid1 successfully locked range 130:4 for WRITE\n");
898 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
899 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
900 smbcli_errstr(cli1->tree), __location__);
903 printf("pid1 successfully read the range 130:4\n");
906 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
907 printf("pid1 unable to write to the range 130:4, error was %s (%s)\n",
908 smbcli_errstr(cli1->tree), __location__);
911 printf("pid1 successfully wrote to the range 130:4\n");
914 cli1->session->pid = 2;
916 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
917 printf("pid2 unable to read the range 130:4, error was %s\n",
918 smbcli_errstr(cli1->tree));
919 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
920 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
925 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n",
930 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
931 printf("pid2 unable to write to the range 130:4, error was %s\n",
932 smbcli_errstr(cli1->tree));
933 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
934 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
939 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
944 printf("Testing truncate of locked file.\n");
946 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
949 printf("Unable to truncate locked file (%s)\n", __location__);
953 printf("Truncated locked file.\n");
956 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
957 printf("getatr failed (%s) (%s)\n", smbcli_errstr(cli1->tree), __location__);
963 printf("Unable to truncate locked file. Size was %u (%s)\n",
964 (unsigned)size, __location__);
969 cli1->session->pid = 1;
971 smbcli_unlock(cli1->tree, fnum1, 130, 4);
975 smbcli_close(cli1->tree, fnum1);
976 smbcli_close(cli1->tree, fnum2);
977 smbcli_unlink(cli1->tree, fname);
978 torture_close_connection(cli1);
980 printf("finished locktest7\n");