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 "libcli/libcli.h"
28 #include "system/time.h"
29 #include "system/filesys.h"
31 #define BASEDIR "\\locktest"
34 This test checks for two things:
36 1) correct support for retaining locks over a close (ie. the server
37 must not use posix semantics)
38 2) support for lock timeouts
40 BOOL torture_locktest1(void)
42 struct smbcli_state *cli1, *cli2;
43 const char *fname = BASEDIR "\\lockt1.lck";
44 int fnum1, fnum2, fnum3;
48 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
52 printf("starting locktest1\n");
54 if (!torture_setup_dir(cli1, BASEDIR)) {
58 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
60 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
63 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
65 printf("(%s) open2 of %s failed (%s)\n",
66 __location__, fname, smbcli_errstr(cli1->tree));
69 fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
71 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
75 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
76 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
81 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
82 printf("lock2 succeeded! This is a locking bug\n");
85 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
86 NT_STATUS_LOCK_NOT_GRANTED)) return False;
89 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
90 printf("lock2 succeeded! This is a locking bug\n");
93 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
94 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
97 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 5, 9, 0, WRITE_LOCK))) {
98 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
102 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 5, 9, 0, WRITE_LOCK))) {
103 printf("lock2 succeeded! This is a locking bug\n");
106 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
107 NT_STATUS_LOCK_NOT_GRANTED)) return False;
110 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
111 printf("lock2 succeeded! This is a locking bug\n");
114 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
115 NT_STATUS_LOCK_NOT_GRANTED)) return False;
118 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
119 printf("lock2 succeeded! This is a locking bug\n");
122 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
123 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
126 lock_timeout = (6 + (random() % 20));
127 printf("Testing lock timeout with timeout=%u\n", lock_timeout);
129 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
130 printf("lock3 succeeded! This is a locking bug\n");
133 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
134 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
139 printf("error: This server appears not to support timed lock requests\n");
141 printf("server slept for %u seconds for a %u second timeout\n",
142 (uint_t)(t2-t1), lock_timeout);
144 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
145 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
149 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
150 printf("lock4 succeeded! This is a locking bug\n");
153 if (!check_error(__location__, cli2, ERRDOS, ERRlock,
154 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
157 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
158 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
162 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
163 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
167 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
168 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
173 if (!torture_close_connection(cli1)) {
177 if (!torture_close_connection(cli2)) {
181 printf("Passed locktest1\n");
187 This test checks that
189 1) the server supports multiple locking contexts on the one SMB
190 connection, distinguished by PID.
192 2) the server correctly fails overlapping locks made by the same PID (this
193 goes against POSIX behaviour, which is why it is tricky to implement)
195 3) the server denies unlock requests by an incorrect client PID
197 BOOL torture_locktest2(void)
199 struct smbcli_state *cli;
200 const char *fname = BASEDIR "\\lockt2.lck";
201 int fnum1, fnum2, fnum3;
204 if (!torture_open_connection(&cli)) {
208 printf("starting locktest2\n");
210 if (!torture_setup_dir(cli, BASEDIR)) {
214 printf("Testing pid context\n");
216 cli->session->pid = 1;
218 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
220 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
224 fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
226 printf("(%s) open2 of %s failed (%s)\n",
227 __location__, fname, smbcli_errstr(cli->tree));
231 cli->session->pid = 2;
233 fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
235 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
239 cli->session->pid = 1;
241 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
242 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
246 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
247 printf("WRITE lock1 succeeded! This is a locking bug\n");
250 if (!check_error(__location__, cli, ERRDOS, ERRlock,
251 NT_STATUS_LOCK_NOT_GRANTED)) return False;
254 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
255 printf("WRITE lock2 succeeded! This is a locking bug\n");
258 if (!check_error(__location__, cli, ERRDOS, ERRlock,
259 NT_STATUS_LOCK_NOT_GRANTED)) return False;
262 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
263 printf("READ lock2 succeeded! This is a locking bug\n");
266 if (!check_error(__location__, cli, ERRDOS, ERRlock,
267 NT_STATUS_FILE_LOCK_CONFLICT)) return False;
270 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
271 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
274 cli->session->pid = 2;
276 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
277 printf("unlock at 100 succeeded! This is a locking bug\n");
281 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
282 printf("unlock1 succeeded! This is a locking bug\n");
285 if (!check_error(__location__, cli,
286 ERRDOS, ERRnotlocked,
287 NT_STATUS_RANGE_NOT_LOCKED)) return False;
290 if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
291 printf("unlock2 succeeded! This is a locking bug\n");
294 if (!check_error(__location__, cli,
295 ERRDOS, ERRnotlocked,
296 NT_STATUS_RANGE_NOT_LOCKED)) return False;
299 if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
300 printf("lock3 succeeded! This is a locking bug\n");
303 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
306 cli->session->pid = 1;
308 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
309 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
313 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
314 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
318 if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
319 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
323 if (!torture_close_connection(cli)) {
327 printf("locktest2 finished\n");
334 This test checks that
336 1) the server supports the full offset range in lock requests
338 BOOL torture_locktest3(void)
340 struct smbcli_state *cli1, *cli2;
341 const char *fname = BASEDIR "\\lockt3.lck";
345 extern int torture_numops;
347 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
349 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
353 printf("starting locktest3\n");
355 printf("Testing 32 bit offset ranges\n");
357 if (!torture_setup_dir(cli1, BASEDIR)) {
361 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
363 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
366 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
368 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
372 printf("Establishing %d locks\n", torture_numops);
374 for (offset=i=0;i<torture_numops;i++) {
376 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
377 printf("lock1 %d failed (%s)\n",
379 smbcli_errstr(cli1->tree));
383 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
384 printf("lock2 %d failed (%s)\n",
386 smbcli_errstr(cli1->tree));
391 printf("Testing %d locks\n", torture_numops);
393 for (offset=i=0;i<torture_numops;i++) {
396 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
397 printf("error: lock1 %d succeeded!\n", i);
401 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
402 printf("error: lock2 %d succeeded!\n", i);
406 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
407 printf("error: lock3 %d succeeded!\n", i);
411 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
412 printf("error: lock4 %d succeeded!\n", i);
417 printf("Removing %d locks\n", torture_numops);
419 for (offset=i=0;i<torture_numops;i++) {
422 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
423 printf("unlock1 %d failed (%s)\n",
425 smbcli_errstr(cli1->tree));
429 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
430 printf("unlock2 %d failed (%s)\n",
432 smbcli_errstr(cli1->tree));
437 if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
438 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
442 if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
443 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
447 if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
448 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
452 if (!torture_close_connection(cli1)) {
456 if (!torture_close_connection(cli2)) {
460 printf("finished locktest3\n");
465 #define EXPECTED(ret, v) if ((ret) != (v)) { \
466 printf("** "); correct = False; \
470 looks at overlapping locks
472 BOOL torture_locktest4(void)
474 struct smbcli_state *cli1, *cli2;
475 const char *fname = BASEDIR "\\lockt4.lck";
481 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
485 printf("starting locktest4\n");
487 if (!torture_setup_dir(cli1, BASEDIR)) {
491 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
492 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
494 memset(buf, 0, sizeof(buf));
496 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
497 printf("Failed to create file\n");
502 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
503 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
504 EXPECTED(ret, False);
505 printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
507 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
508 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
510 printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
512 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
513 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
514 EXPECTED(ret, False);
515 printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
517 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
518 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
520 printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
522 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
523 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
524 EXPECTED(ret, False);
525 printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
527 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
528 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
530 printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
532 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
533 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
535 printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
537 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
538 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
539 EXPECTED(ret, False);
540 printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
542 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
543 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
544 EXPECTED(ret, False);
545 printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
547 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
548 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
550 printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
552 ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
553 NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
554 EXPECTED(ret, False);
555 printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
557 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
558 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
559 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
560 EXPECTED(ret, False);
561 printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
564 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
565 (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
566 EXPECTED(ret, False);
567 printf("this server %s strict write locking\n", ret?"doesn't do":"does");
569 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
570 (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
571 EXPECTED(ret, False);
572 printf("this server %s strict read locking\n", ret?"doesn't do":"does");
575 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
576 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
577 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
578 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
580 printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
583 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
584 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
585 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
586 (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
587 !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
588 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
590 printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
592 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
593 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
594 (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&
595 (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);
597 printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
599 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
600 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
601 (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&
602 (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);
604 printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
606 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
607 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
608 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
609 !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&
610 (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);
612 printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
614 smbcli_close(cli1->tree, fnum1);
615 smbcli_close(cli2->tree, fnum2);
616 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
617 f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
618 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
619 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
620 NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
621 ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
622 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
623 smbcli_close(cli1->tree, f);
624 smbcli_close(cli1->tree, fnum1);
626 printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
629 smbcli_close(cli1->tree, fnum1);
630 smbcli_close(cli2->tree, fnum2);
631 smbcli_unlink(cli1->tree, fname);
632 torture_close_connection(cli1);
633 torture_close_connection(cli2);
635 printf("finished locktest4\n");
640 looks at lock upgrade/downgrade.
642 BOOL torture_locktest5(void)
644 struct smbcli_state *cli1, *cli2;
645 const char *fname = BASEDIR "\\lockt5.lck";
646 int fnum1, fnum2, fnum3;
651 if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
655 printf("starting locktest5\n");
657 if (!torture_setup_dir(cli1, BASEDIR)) {
661 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
662 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
663 fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
665 memset(buf, 0, sizeof(buf));
667 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
668 printf("Failed to create file\n");
673 /* Check for NT bug... */
674 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
675 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
676 smbcli_close(cli1->tree, fnum1);
677 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
678 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
680 printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
681 smbcli_close(cli1->tree, fnum1);
682 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
683 smbcli_unlock(cli1->tree, fnum3, 0, 1);
685 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
686 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
688 printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
690 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
691 EXPECTED(ret, False);
693 printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
695 /* Unlock the process 2 lock. */
696 smbcli_unlock(cli2->tree, fnum2, 0, 4);
698 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
699 EXPECTED(ret, False);
701 printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
703 /* Unlock the process 1 fnum3 lock. */
704 smbcli_unlock(cli1->tree, fnum3, 0, 4);
706 /* Stack 2 more locks here. */
707 ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
708 NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
711 printf("the same process %s stack read locks\n", ret?"can":"cannot");
713 /* Unlock the first process lock, then check this was the WRITE lock that was
716 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
717 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
720 printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
722 /* Unlock the process 2 lock. */
723 smbcli_unlock(cli2->tree, fnum2, 0, 4);
725 /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
727 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
728 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
729 NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
732 printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot");
734 /* Ensure the next unlock fails. */
735 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
736 EXPECTED(ret, False);
737 printf("the same process %s count the lock stack\n", !ret?"can":"cannot");
739 /* Ensure connection 2 can get a write lock. */
740 ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
743 printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
747 smbcli_close(cli1->tree, fnum1);
748 smbcli_close(cli2->tree, fnum2);
749 smbcli_unlink(cli1->tree, fname);
750 if (!torture_close_connection(cli1)) {
753 if (!torture_close_connection(cli2)) {
757 printf("finished locktest5\n");
763 tries the unusual lockingX locktype bits
765 BOOL torture_locktest6(void)
767 struct smbcli_state *cli;
768 const char *fname[1] = { "\\lock6.txt" };
773 if (!torture_open_connection(&cli)) {
777 if (!torture_setup_dir(cli, BASEDIR)) {
781 printf("starting locktest6\n");
784 printf("Testing %s\n", fname[i]);
786 smbcli_unlink(cli->tree, fname[i]);
788 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
789 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
790 smbcli_close(cli->tree, fnum);
791 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
793 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
794 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
795 smbcli_close(cli->tree, fnum);
796 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
798 smbcli_unlink(cli->tree, fname[i]);
801 torture_close_connection(cli);
803 printf("finished locktest6\n");
807 BOOL torture_locktest7(void)
809 struct smbcli_state *cli1;
810 const char *fname = BASEDIR "\\lockt7.lck";
815 BOOL correct = False;
817 if (!torture_open_connection(&cli1)) {
821 printf("starting locktest7\n");
823 if (!torture_setup_dir(cli1, BASEDIR)) {
827 fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
829 memset(buf, 0, sizeof(buf));
831 if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
832 printf("Failed to create file (%s)\n", __location__);
836 cli1->session->pid = 1;
838 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
839 printf("Unable to apply read lock on range 130:4, error was %s (%s)\n",
840 smbcli_errstr(cli1->tree), __location__);
843 printf("pid1 successfully locked range 130:4 for READ\n");
846 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
847 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
848 smbcli_errstr(cli1->tree), __location__);
851 printf("pid1 successfully read the range 130:4\n");
854 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
855 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
856 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
857 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
862 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n",
867 cli1->session->pid = 2;
869 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
870 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
872 printf("pid2 successfully read the range 130:4\n");
875 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
876 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
877 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
878 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
883 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
888 cli1->session->pid = 1;
889 smbcli_unlock(cli1->tree, fnum1, 130, 4);
891 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
892 printf("Unable to apply write lock on range 130:4, error was %s (%s)\n",
893 smbcli_errstr(cli1->tree), __location__);
896 printf("pid1 successfully locked range 130:4 for WRITE\n");
899 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
900 printf("pid1 unable to read the range 130:4, error was %s (%s)\n",
901 smbcli_errstr(cli1->tree), __location__);
904 printf("pid1 successfully read the range 130:4\n");
907 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
908 printf("pid1 unable to write to the range 130:4, error was %s (%s)\n",
909 smbcli_errstr(cli1->tree), __location__);
912 printf("pid1 successfully wrote to the range 130:4\n");
915 cli1->session->pid = 2;
917 if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
918 printf("pid2 unable to read the range 130:4, error was %s\n",
919 smbcli_errstr(cli1->tree));
920 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
921 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
926 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n",
931 if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
932 printf("pid2 unable to write to the range 130:4, error was %s\n",
933 smbcli_errstr(cli1->tree));
934 if (!NT_STATUS_EQUAL(smbcli_nt_error(cli1->tree), NT_STATUS_FILE_LOCK_CONFLICT)) {
935 printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
940 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n",
945 printf("Testing truncate of locked file.\n");
947 fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
950 printf("Unable to truncate locked file (%s)\n", __location__);
954 printf("Truncated locked file.\n");
957 if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
958 printf("getatr failed (%s) (%s)\n", smbcli_errstr(cli1->tree), __location__);
964 printf("Unable to truncate locked file. Size was %u (%s)\n",
965 (unsigned)size, __location__);
970 cli1->session->pid = 1;
972 smbcli_unlock(cli1->tree, fnum1, 130, 4);
976 smbcli_close(cli1->tree, fnum1);
977 smbcli_close(cli1->tree, fnum2);
978 smbcli_unlink(cli1->tree, fname);
979 torture_close_connection(cli1);
981 printf("finished locktest7\n");