r16907: Add an index parameter to torture_open_connection. Next step is to enable the
[gd/samba-autobuild/.git] / source4 / torture / basic / locking.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    basic locking tests
5
6    Copyright (C) Andrew Tridgell 2000-2004
7    Copyright (C) Jeremy Allison 2000-2004
8    
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.
13    
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.
18    
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.
22 */
23
24 #include "includes.h"
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"
31
32 #define BASEDIR "\\locktest"
33
34 /*
35   This test checks for two things:
36
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
40  */
41 BOOL torture_locktest1(struct torture_context *torture)
42 {
43         struct smbcli_state *cli1, *cli2;
44         const char *fname = BASEDIR "\\lockt1.lck";
45         int fnum1, fnum2, fnum3;
46         time_t t1, t2;
47         uint_t lock_timeout;
48
49         if (!torture_open_connection(&cli1, 0) ||
50             !torture_open_connection(&cli2, 1)) {
51                 return False;
52         }
53
54         printf("starting locktest1\n");
55
56         if (!torture_setup_dir(cli1, BASEDIR)) {
57                 return False;
58         }
59
60         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
61         if (fnum1 == -1) {
62                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
63                 return False;
64         }
65         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
66         if (fnum2 == -1) {
67                 printf("(%s) open2 of %s failed (%s)\n", 
68                        __location__, fname, smbcli_errstr(cli1->tree));
69                 return False;
70         }
71         fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
72         if (fnum3 == -1) {
73                 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
74                 return False;
75         }
76
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));
79                 return False;
80         }
81
82
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");
85                 return False;
86         } else {
87                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
88                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
89         }
90
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");
93                 return False;
94         } else {
95                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
96                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
97         }
98
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));
101                 return False;
102         }
103
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");
106                 return False;
107         } else {
108                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
109                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
110         }
111
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");
114                 return False;
115         } else {
116                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
117                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
118         }
119
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");
122                 return False;
123         } else {
124                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
125                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
126         }
127
128         lock_timeout = (6 + (random() % 20));
129         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
130         t1 = time(NULL);
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");
133                 return False;
134         } else {
135                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
136                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
137         }
138         t2 = time(NULL);
139
140         if (t2 - t1 < 5) {
141                 printf("error: This server appears not to support timed lock requests\n");
142         }
143         printf("server slept for %u seconds for a %u second timeout\n",
144                (uint_t)(t2-t1), lock_timeout);
145
146         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
147                 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
148                 return False;
149         }
150
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");
153                 return False;
154         } else {
155                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
156                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
157         }
158
159         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
160                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
161                 return False;
162         }
163
164         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
165                 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
166                 return False;
167         }
168
169         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
170                 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
171                 return False;
172         }
173
174
175         if (!torture_close_connection(cli1)) {
176                 return False;
177         }
178
179         if (!torture_close_connection(cli2)) {
180                 return False;
181         }
182
183         printf("Passed locktest1\n");
184         return True;
185 }
186
187
188 /*
189   This test checks that 
190
191   1) the server supports multiple locking contexts on the one SMB
192   connection, distinguished by PID.  
193
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)
196
197   3) the server denies unlock requests by an incorrect client PID
198 */
199 BOOL torture_locktest2(struct torture_context *torture)
200 {
201         struct smbcli_state *cli;
202         const char *fname = BASEDIR "\\lockt2.lck";
203         int fnum1, fnum2, fnum3;
204         BOOL correct = True;
205
206         if (!torture_open_connection(&cli, 0)) {
207                 return False;
208         }
209
210         printf("starting locktest2\n");
211
212         if (!torture_setup_dir(cli, BASEDIR)) {
213                 return False;
214         }
215
216         printf("Testing pid context\n");
217         
218         cli->session->pid = 1;
219
220         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
221         if (fnum1 == -1) {
222                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
223                 return False;
224         }
225
226         fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
227         if (fnum2 == -1) {
228                 printf("(%s) open2 of %s failed (%s)\n", 
229                        __location__, fname, smbcli_errstr(cli->tree));
230                 return False;
231         }
232
233         cli->session->pid = 2;
234
235         fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
236         if (fnum3 == -1) {
237                 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
238                 return False;
239         }
240
241         cli->session->pid = 1;
242
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));
245                 return False;
246         }
247
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");
250                 correct = False;
251         } else {
252                 if (!check_error(__location__, cli, ERRDOS, ERRlock, 
253                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
254         }
255
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");
258                 correct = False;
259         } else {
260                 if (!check_error(__location__, cli, ERRDOS, ERRlock, 
261                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
262         }
263
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");
266                 correct = False;
267         } else {
268                 if (!check_error(__location__, cli, ERRDOS, ERRlock, 
269                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
270         }
271
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));
274         }
275
276         cli->session->pid = 2;
277
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");
280                 correct = False;
281         }
282
283         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
284                 printf("unlock1 succeeded! This is a locking bug\n");
285                 correct = False;
286         } else {
287                 if (!check_error(__location__, cli, 
288                                  ERRDOS, ERRnotlocked, 
289                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
290         }
291
292         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
293                 printf("unlock2 succeeded! This is a locking bug\n");
294                 correct = False;
295         } else {
296                 if (!check_error(__location__, cli, 
297                                  ERRDOS, ERRnotlocked, 
298                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
299         }
300
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");
303                 correct = False;
304         } else {
305                 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
306         }
307
308         cli->session->pid = 1;
309
310         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
311                 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
312                 return False;
313         }
314
315         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
316                 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
317                 return False;
318         }
319
320         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
321                 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
322                 return False;
323         }
324
325         if (!torture_close_connection(cli)) {
326                 correct = False;
327         }
328
329         printf("locktest2 finished\n");
330
331         return correct;
332 }
333
334
335 /*
336   This test checks that 
337
338   1) the server supports the full offset range in lock requests
339 */
340 BOOL torture_locktest3(struct torture_context *torture)
341 {
342         struct smbcli_state *cli1, *cli2;
343         const char *fname = BASEDIR "\\lockt3.lck";
344         int fnum1, fnum2, i;
345         uint32_t offset;
346         BOOL correct = True;
347         extern int torture_numops;
348
349 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
350
351         if (!torture_open_connection(&cli1, 0) ||
352             !torture_open_connection(&cli2, 1)) {
353                 return False;
354         }
355
356         printf("starting locktest3\n");
357
358         printf("Testing 32 bit offset ranges\n");
359
360         if (!torture_setup_dir(cli1, BASEDIR)) {
361                 return False;
362         }
363
364         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
365         if (fnum1 == -1) {
366                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
367                 return False;
368         }
369         fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
370         if (fnum2 == -1) {
371                 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
372                 return False;
373         }
374
375         printf("Establishing %d locks\n", torture_numops);
376
377         for (offset=i=0;i<torture_numops;i++) {
378                 NEXT_OFFSET;
379                 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
380                         printf("lock1 %d failed (%s)\n", 
381                                i,
382                                smbcli_errstr(cli1->tree));
383                         return False;
384                 }
385
386                 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
387                         printf("lock2 %d failed (%s)\n", 
388                                i,
389                                smbcli_errstr(cli1->tree));
390                         return False;
391                 }
392         }
393
394         printf("Testing %d locks\n", torture_numops);
395
396         for (offset=i=0;i<torture_numops;i++) {
397                 NEXT_OFFSET;
398
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);
401                         return False;
402                 }
403
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);
406                         return False;
407                 }
408
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);
411                         return False;
412                 }
413
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);
416                         return False;
417                 }
418         }
419
420         printf("Removing %d locks\n", torture_numops);
421
422         for (offset=i=0;i<torture_numops;i++) {
423                 NEXT_OFFSET;
424
425                 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
426                         printf("unlock1 %d failed (%s)\n", 
427                                i,
428                                smbcli_errstr(cli1->tree));
429                         return False;
430                 }
431
432                 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
433                         printf("unlock2 %d failed (%s)\n", 
434                                i,
435                                smbcli_errstr(cli1->tree));
436                         return False;
437                 }
438         }
439
440         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
441                 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
442                 return False;
443         }
444
445         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
446                 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
447                 return False;
448         }
449
450         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
451                 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
452                 return False;
453         }
454
455         if (!torture_close_connection(cli1)) {
456                 correct = False;
457         }
458         
459         if (!torture_close_connection(cli2)) {
460                 correct = False;
461         }
462
463         printf("finished locktest3\n");
464
465         return correct;
466 }
467
468 #define EXPECTED(ret, v) if ((ret) != (v)) { \
469         printf("** "); correct = False; \
470         }
471
472 /*
473   looks at overlapping locks
474 */
475 BOOL torture_locktest4(struct torture_context *torture)
476 {
477         struct smbcli_state *cli1, *cli2;
478         const char *fname = BASEDIR "\\lockt4.lck";
479         int fnum1, fnum2, f;
480         BOOL ret;
481         uint8_t buf[1000];
482         BOOL correct = True;
483
484         if (!torture_open_connection(&cli1, 0) ||
485             !torture_open_connection(&cli2, 1)) {
486                 return False;
487         }
488
489         printf("starting locktest4\n");
490
491         if (!torture_setup_dir(cli1, BASEDIR)) {
492                 return False;
493         }
494
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);
497
498         memset(buf, 0, sizeof(buf));
499
500         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
501                 printf("Failed to create file\n");
502                 correct = False;
503                 goto fail;
504         }
505
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");
510             
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));
513         EXPECTED(ret, True);
514         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
515
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");
520             
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));
523         EXPECTED(ret, True);
524         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
525         
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");
530             
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)));
533         EXPECTED(ret, True);
534         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
535
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));
538         EXPECTED(ret, True);
539         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
540
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");
545
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");
550
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));
553         EXPECTED(ret, True);
554         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
555
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");
560
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");
566
567
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");
572
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");
577
578
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));
583         EXPECTED(ret, True);
584         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
585
586
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));
593         EXPECTED(ret, True);
594         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
595
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);               
600         EXPECTED(ret, True);
601         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
602
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);               
607         EXPECTED(ret, True);
608         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
609
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);               
615         EXPECTED(ret, True);
616         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
617
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);
629         EXPECTED(ret, True);
630         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
631
632  fail:
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);
638
639         printf("finished locktest4\n");
640         return correct;
641 }
642
643 /*
644   looks at lock upgrade/downgrade.
645 */
646 BOOL torture_locktest5(struct torture_context *torture)
647 {
648         struct smbcli_state *cli1, *cli2;
649         const char *fname = BASEDIR "\\lockt5.lck";
650         int fnum1, fnum2, fnum3;
651         BOOL ret;
652         uint8_t buf[1000];
653         BOOL correct = True;
654
655         if (!torture_open_connection(&cli1, 0) ||
656             !torture_open_connection(&cli2, 1)) {
657                 return False;
658         }
659
660         printf("starting locktest5\n");
661
662         if (!torture_setup_dir(cli1, BASEDIR)) {
663                 return False;
664         }
665
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);
669
670         memset(buf, 0, sizeof(buf));
671
672         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
673                 printf("Failed to create file\n");
674                 correct = False;
675                 goto fail;
676         }
677
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));
684         EXPECTED(ret, True);
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);
689
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));
692         EXPECTED(ret, True);
693         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
694
695         ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
696         EXPECTED(ret, False);
697
698         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
699
700         /* Unlock the process 2 lock. */
701         smbcli_unlock(cli2->tree, fnum2, 0, 4);
702
703         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
704         EXPECTED(ret, False);
705
706         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
707
708         /* Unlock the process 1 fnum3 lock. */
709         smbcli_unlock(cli1->tree, fnum3, 0, 4);
710
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));
714
715         EXPECTED(ret, True);
716         printf("the same process %s stack read locks\n", ret?"can":"cannot");
717
718         /* Unlock the first process lock, then check this was the WRITE lock that was
719                 removed. */
720
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));
723
724         EXPECTED(ret, True);
725         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
726
727         /* Unlock the process 2 lock. */
728         smbcli_unlock(cli2->tree, fnum2, 0, 4);
729
730         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
731
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));
735
736         EXPECTED(ret, True);
737         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
738
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"); 
743
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));
746         EXPECTED(ret, True);
747
748         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
749
750
751  fail:
752         smbcli_close(cli1->tree, fnum1);
753         smbcli_close(cli2->tree, fnum2);
754         smbcli_unlink(cli1->tree, fname);
755         if (!torture_close_connection(cli1)) {
756                 correct = False;
757         }
758         if (!torture_close_connection(cli2)) {
759                 correct = False;
760         }
761
762         printf("finished locktest5\n");
763        
764         return correct;
765 }
766
767 /*
768   tries the unusual lockingX locktype bits
769 */
770 BOOL torture_locktest6(struct torture_context *torture)
771 {
772         struct smbcli_state *cli;
773         const char *fname[1] = { "\\lock6.txt" };
774         int i;
775         int fnum;
776         NTSTATUS status;
777
778         if (!torture_open_connection(&cli, 0)) {
779                 return False;
780         }
781
782         if (!torture_setup_dir(cli, BASEDIR)) {
783                 return False;
784         }
785
786         printf("starting locktest6\n");
787
788         for (i=0;i<1;i++) {
789                 printf("Testing %s\n", fname[i]);
790
791                 smbcli_unlink(cli->tree, fname[i]);
792
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));
797
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));
802
803                 smbcli_unlink(cli->tree, fname[i]);
804         }
805
806         torture_close_connection(cli);
807
808         printf("finished locktest6\n");
809         return True;
810 }
811
812 BOOL torture_locktest7(struct torture_context *torture)
813 {
814         struct smbcli_state *cli1;
815         const char *fname = BASEDIR "\\lockt7.lck";
816         int fnum1;
817         int fnum2 = -1;
818         size_t size;
819         uint8_t buf[200];
820         BOOL correct = False;
821
822         if (!torture_open_connection(&cli1, 0)) {
823                 return False;
824         }
825
826         printf("starting locktest7\n");
827
828         if (!torture_setup_dir(cli1, BASEDIR)) {
829                 return False;
830         }
831
832         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
833
834         memset(buf, 0, sizeof(buf));
835
836         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
837                 printf("Failed to create file (%s)\n", __location__);
838                 goto fail;
839         }
840
841         cli1->session->pid = 1;
842
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__);
846                 goto fail;
847         } else {
848                 printf("pid1 successfully locked range 130:4 for READ\n");
849         }
850
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__);
854                 goto fail;
855         } else {
856                 printf("pid1 successfully read the range 130:4\n");
857         }
858
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", 
863                                __location__);
864                         goto fail;
865                 }
866         } else {
867                 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n", 
868                        __location__);
869                 goto fail;
870         }
871
872         cli1->session->pid = 2;
873
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));
876         } else {
877                 printf("pid2 successfully read the range 130:4\n");
878         }
879
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",
884                                __location__);
885                         goto fail;
886                 }
887         } else {
888                 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n", 
889                        __location__);
890                 goto fail;
891         }
892
893         cli1->session->pid = 1;
894         smbcli_unlock(cli1->tree, fnum1, 130, 4);
895
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__);
899                 goto fail;
900         } else {
901                 printf("pid1 successfully locked range 130:4 for WRITE\n");
902         }
903
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__);
907                 goto fail;
908         } else {
909                 printf("pid1 successfully read the range 130:4\n");
910         }
911
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__);
915                 goto fail;
916         } else {
917                 printf("pid1 successfully wrote to the range 130:4\n");
918         }
919
920         cli1->session->pid = 2;
921
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",
927                                __location__);
928                         goto fail;
929                 }
930         } else {
931                 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n", 
932                        __location__);
933                 goto fail;
934         }
935
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",
941                                __location__);
942                         goto fail;
943                 }
944         } else {
945                 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n", 
946                        __location__);
947                 goto fail;
948         }
949
950         printf("Testing truncate of locked file.\n");
951
952         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
953
954         if (fnum2 == -1) {
955                 printf("Unable to truncate locked file (%s)\n", __location__);
956                 correct = False;
957                 goto fail;
958         } else {
959                 printf("Truncated locked file.\n");
960         }
961
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__);
964                 correct = False;
965                 goto fail;
966         }
967
968         if (size != 0) {
969                 printf("Unable to truncate locked file. Size was %u (%s)\n", 
970                        (unsigned)size, __location__);
971                 correct = False;
972                 goto fail;
973         }
974
975         cli1->session->pid = 1;
976
977         smbcli_unlock(cli1->tree, fnum1, 130, 4);
978         correct = True;
979
980 fail:
981         smbcli_close(cli1->tree, fnum1);
982         smbcli_close(cli1->tree, fnum2);
983         smbcli_unlink(cli1->tree, fname);
984         torture_close_connection(cli1);
985
986         printf("finished locktest7\n");
987         return correct;
988 }
989