r3148: make --failures work for the BASE-DENY1 and BASE-DENY2 tests
[bbaumbach/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
26 /*
27   This test checks for two things:
28
29   1) correct support for retaining locks over a close (ie. the server
30      must not use posix semantics)
31   2) support for lock timeouts
32  */
33 BOOL torture_locktest1(int dummy)
34 {
35         struct smbcli_state *cli1, *cli2;
36         const char *fname = "\\lockt1.lck";
37         int fnum1, fnum2, fnum3;
38         time_t t1, t2;
39         uint_t lock_timeout;
40
41         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
42                 return False;
43         }
44
45         printf("starting locktest1\n");
46
47         smbcli_unlink(cli1->tree, fname);
48
49         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
50         if (fnum1 == -1) {
51                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
52                 return False;
53         }
54         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
55         if (fnum2 == -1) {
56                 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
57                 return False;
58         }
59         fnum3 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
60         if (fnum3 == -1) {
61                 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
62                 return False;
63         }
64
65         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
66                 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
67                 return False;
68         }
69
70
71         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
72                 printf("lock2 succeeded! This is a locking bug\n");
73                 return False;
74         } else {
75                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
76                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
77         }
78
79         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
80                 printf("lock2 succeeded! This is a locking bug\n");
81                 return False;
82         } else {
83                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
84                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
85         }
86
87         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 5, 9, 0, WRITE_LOCK))) {
88                 printf("lock1 failed (%s)\n", smbcli_errstr(cli1->tree));
89                 return False;
90         }
91
92         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 5, 9, 0, WRITE_LOCK))) {
93                 printf("lock2 succeeded! This is a locking bug\n");
94                 return False;
95         } else {
96                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
97                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
98         }
99
100         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
101                 printf("lock2 succeeded! This is a locking bug\n");
102                 return False;
103         } else {
104                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
105                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
106         }
107
108         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
109                 printf("lock2 succeeded! This is a locking bug\n");
110                 return False;
111         } else {
112                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
113                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
114         }
115
116         lock_timeout = (6 + (random() % 20));
117         printf("Testing lock timeout with timeout=%u\n", lock_timeout);
118         t1 = time(NULL);
119         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, lock_timeout * 1000, WRITE_LOCK))) {
120                 printf("lock3 succeeded! This is a locking bug\n");
121                 return False;
122         } else {
123                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
124                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
125         }
126         t2 = time(NULL);
127
128         if (t2 - t1 < 5) {
129                 printf("error: This server appears not to support timed lock requests\n");
130         }
131         printf("server slept for %u seconds for a %u second timeout\n",
132                (uint_t)(t2-t1), lock_timeout);
133
134         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum2))) {
135                 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
136                 return False;
137         }
138
139         if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
140                 printf("lock4 succeeded! This is a locking bug\n");
141                 return False;
142         } else {
143                 if (!check_error(__location__, cli2, ERRDOS, ERRlock, 
144                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
145         }
146
147         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
148                 printf("close2 failed (%s)\n", smbcli_errstr(cli1->tree));
149                 return False;
150         }
151
152         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum3))) {
153                 printf("close3 failed (%s)\n", smbcli_errstr(cli2->tree));
154                 return False;
155         }
156
157         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
158                 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
159                 return False;
160         }
161
162
163         if (!torture_close_connection(cli1)) {
164                 return False;
165         }
166
167         if (!torture_close_connection(cli2)) {
168                 return False;
169         }
170
171         printf("Passed locktest1\n");
172         return True;
173 }
174
175
176 /*
177   This test checks that 
178
179   1) the server supports multiple locking contexts on the one SMB
180   connection, distinguished by PID.  
181
182   2) the server correctly fails overlapping locks made by the same PID (this
183      goes against POSIX behaviour, which is why it is tricky to implement)
184
185   3) the server denies unlock requests by an incorrect client PID
186 */
187 BOOL torture_locktest2(int dummy)
188 {
189         struct smbcli_state *cli;
190         const char *fname = "\\lockt2.lck";
191         int fnum1, fnum2, fnum3;
192         BOOL correct = True;
193
194         if (!torture_open_connection(&cli)) {
195                 return False;
196         }
197
198         printf("starting locktest2\n");
199
200         smbcli_unlink(cli->tree, fname);
201
202         printf("Testing pid context\n");
203         
204         cli->session->pid = 1;
205
206         fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
207         if (fnum1 == -1) {
208                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
209                 return False;
210         }
211
212         fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
213         if (fnum2 == -1) {
214                 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
215                 return False;
216         }
217
218         cli->session->pid = 2;
219
220         fnum3 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
221         if (fnum3 == -1) {
222                 printf("open3 of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
223                 return False;
224         }
225
226         cli->session->pid = 1;
227
228         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
229                 printf("lock1 failed (%s)\n", smbcli_errstr(cli->tree));
230                 return False;
231         }
232
233         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum1, 0, 4, 0, WRITE_LOCK))) {
234                 printf("WRITE lock1 succeeded! This is a locking bug\n");
235                 correct = False;
236         } else {
237                 if (!check_error(__location__, cli, ERRDOS, ERRlock, 
238                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
239         }
240
241         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, WRITE_LOCK))) {
242                 printf("WRITE lock2 succeeded! This is a locking bug\n");
243                 correct = False;
244         } else {
245                 if (!check_error(__location__, cli, ERRDOS, ERRlock, 
246                                  NT_STATUS_LOCK_NOT_GRANTED)) return False;
247         }
248
249         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum2, 0, 4, 0, READ_LOCK))) {
250                 printf("READ lock2 succeeded! This is a locking bug\n");
251                 correct = False;
252         } else {
253                 if (!check_error(__location__, cli, ERRDOS, ERRlock, 
254                                  NT_STATUS_FILE_LOCK_CONFLICT)) return False;
255         }
256
257         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum1, 100, 4, 0, WRITE_LOCK))) {
258                 printf("lock at 100 failed (%s)\n", smbcli_errstr(cli->tree));
259         }
260
261         cli->session->pid = 2;
262
263         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 100, 4))) {
264                 printf("unlock at 100 succeeded! This is a locking bug\n");
265                 correct = False;
266         }
267
268         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 4))) {
269                 printf("unlock1 succeeded! This is a locking bug\n");
270                 correct = False;
271         } else {
272                 if (!check_error(__location__, cli, 
273                                  ERRDOS, ERRlock, 
274                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
275         }
276
277         if (NT_STATUS_IS_OK(smbcli_unlock(cli->tree, fnum1, 0, 8))) {
278                 printf("unlock2 succeeded! This is a locking bug\n");
279                 correct = False;
280         } else {
281                 if (!check_error(__location__, cli, 
282                                  ERRDOS, ERRlock, 
283                                  NT_STATUS_RANGE_NOT_LOCKED)) return False;
284         }
285
286         if (NT_STATUS_IS_OK(smbcli_lock(cli->tree, fnum3, 0, 4, 0, WRITE_LOCK))) {
287                 printf("lock3 succeeded! This is a locking bug\n");
288                 correct = False;
289         } else {
290                 if (!check_error(__location__, cli, ERRDOS, ERRlock, NT_STATUS_LOCK_NOT_GRANTED)) return False;
291         }
292
293         cli->session->pid = 1;
294
295         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum1))) {
296                 printf("close1 failed (%s)\n", smbcli_errstr(cli->tree));
297                 return False;
298         }
299
300         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum2))) {
301                 printf("close2 failed (%s)\n", smbcli_errstr(cli->tree));
302                 return False;
303         }
304
305         if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum3))) {
306                 printf("close3 failed (%s)\n", smbcli_errstr(cli->tree));
307                 return False;
308         }
309
310         if (!torture_close_connection(cli)) {
311                 correct = False;
312         }
313
314         printf("locktest2 finished\n");
315
316         return correct;
317 }
318
319
320 /*
321   This test checks that 
322
323   1) the server supports the full offset range in lock requests
324 */
325 BOOL torture_locktest3(int dummy)
326 {
327         struct smbcli_state *cli1, *cli2;
328         const char *fname = "\\lockt3.lck";
329         int fnum1, fnum2, i;
330         uint32_t offset;
331         BOOL correct = True;
332         extern int torture_numops;
333
334 #define NEXT_OFFSET offset += (~(uint32_t)0) / torture_numops
335
336         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
337                 return False;
338         }
339
340         printf("starting locktest3\n");
341
342         printf("Testing 32 bit offset ranges\n");
343
344         smbcli_unlink(cli1->tree, fname);
345
346         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
347         if (fnum1 == -1) {
348                 printf("open of %s failed (%s)\n", fname, smbcli_errstr(cli1->tree));
349                 return False;
350         }
351         fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
352         if (fnum2 == -1) {
353                 printf("open2 of %s failed (%s)\n", fname, smbcli_errstr(cli2->tree));
354                 return False;
355         }
356
357         printf("Establishing %d locks\n", torture_numops);
358
359         for (offset=i=0;i<torture_numops;i++) {
360                 NEXT_OFFSET;
361                 if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
362                         printf("lock1 %d failed (%s)\n", 
363                                i,
364                                smbcli_errstr(cli1->tree));
365                         return False;
366                 }
367
368                 if (NT_STATUS_IS_ERR(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
369                         printf("lock2 %d failed (%s)\n", 
370                                i,
371                                smbcli_errstr(cli1->tree));
372                         return False;
373                 }
374         }
375
376         printf("Testing %d locks\n", torture_numops);
377
378         for (offset=i=0;i<torture_numops;i++) {
379                 NEXT_OFFSET;
380
381                 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-2, 1, 0, WRITE_LOCK))) {
382                         printf("error: lock1 %d succeeded!\n", i);
383                         return False;
384                 }
385
386                 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-1, 1, 0, WRITE_LOCK))) {
387                         printf("error: lock2 %d succeeded!\n", i);
388                         return False;
389                 }
390
391                 if (NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, offset-1, 1, 0, WRITE_LOCK))) {
392                         printf("error: lock3 %d succeeded!\n", i);
393                         return False;
394                 }
395
396                 if (NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, offset-2, 1, 0, WRITE_LOCK))) {
397                         printf("error: lock4 %d succeeded!\n", i);
398                         return False;
399                 }
400         }
401
402         printf("Removing %d locks\n", torture_numops);
403
404         for (offset=i=0;i<torture_numops;i++) {
405                 NEXT_OFFSET;
406
407                 if (NT_STATUS_IS_ERR(smbcli_unlock(cli1->tree, fnum1, offset-1, 1))) {
408                         printf("unlock1 %d failed (%s)\n", 
409                                i,
410                                smbcli_errstr(cli1->tree));
411                         return False;
412                 }
413
414                 if (NT_STATUS_IS_ERR(smbcli_unlock(cli2->tree, fnum2, offset-2, 1))) {
415                         printf("unlock2 %d failed (%s)\n", 
416                                i,
417                                smbcli_errstr(cli1->tree));
418                         return False;
419                 }
420         }
421
422         if (NT_STATUS_IS_ERR(smbcli_close(cli1->tree, fnum1))) {
423                 printf("close1 failed (%s)\n", smbcli_errstr(cli1->tree));
424                 return False;
425         }
426
427         if (NT_STATUS_IS_ERR(smbcli_close(cli2->tree, fnum2))) {
428                 printf("close2 failed (%s)\n", smbcli_errstr(cli2->tree));
429                 return False;
430         }
431
432         if (NT_STATUS_IS_ERR(smbcli_unlink(cli1->tree, fname))) {
433                 printf("unlink failed (%s)\n", smbcli_errstr(cli1->tree));
434                 return False;
435         }
436
437         if (!torture_close_connection(cli1)) {
438                 correct = False;
439         }
440         
441         if (!torture_close_connection(cli2)) {
442                 correct = False;
443         }
444
445         printf("finished locktest3\n");
446
447         return correct;
448 }
449
450 #define EXPECTED(ret, v) if ((ret) != (v)) { \
451         printf("** "); correct = False; \
452         }
453
454 /*
455   looks at overlapping locks
456 */
457 BOOL torture_locktest4(int dummy)
458 {
459         struct smbcli_state *cli1, *cli2;
460         const char *fname = "\\lockt4.lck";
461         int fnum1, fnum2, f;
462         BOOL ret;
463         char buf[1000];
464         BOOL correct = True;
465
466         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
467                 return False;
468         }
469
470         printf("starting locktest4\n");
471
472         smbcli_unlink(cli1->tree, fname);
473
474         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
475         fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
476
477         memset(buf, 0, sizeof(buf));
478
479         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
480                 printf("Failed to create file\n");
481                 correct = False;
482                 goto fail;
483         }
484
485         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
486               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 2, 4, 0, WRITE_LOCK));
487         EXPECTED(ret, False);
488         printf("the same process %s set overlapping write locks\n", ret?"can":"cannot");
489             
490         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 10, 4, 0, READ_LOCK)) &&
491               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 12, 4, 0, READ_LOCK));
492         EXPECTED(ret, True);
493         printf("the same process %s set overlapping read locks\n", ret?"can":"cannot");
494
495         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 20, 4, 0, WRITE_LOCK)) &&
496               NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 22, 4, 0, WRITE_LOCK));
497         EXPECTED(ret, False);
498         printf("a different connection %s set overlapping write locks\n", ret?"can":"cannot");
499             
500         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 30, 4, 0, READ_LOCK)) &&
501                 NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 32, 4, 0, READ_LOCK));
502         EXPECTED(ret, True);
503         printf("a different connection %s set overlapping read locks\n", ret?"can":"cannot");
504         
505         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 40, 4, 0, WRITE_LOCK))) &&
506               NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 42, 4, 0, WRITE_LOCK)));
507         EXPECTED(ret, False);
508         printf("a different pid %s set overlapping write locks\n", ret?"can":"cannot");
509             
510         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 50, 4, 0, READ_LOCK))) &&
511               NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 52, 4, 0, READ_LOCK)));
512         EXPECTED(ret, True);
513         printf("a different pid %s set overlapping read locks\n", ret?"can":"cannot");
514
515         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK)) &&
516               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 60, 4, 0, READ_LOCK));
517         EXPECTED(ret, True);
518         printf("the same process %s set the same read lock twice\n", ret?"can":"cannot");
519
520         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK)) &&
521               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 70, 4, 0, WRITE_LOCK));
522         EXPECTED(ret, False);
523         printf("the same process %s set the same write lock twice\n", ret?"can":"cannot");
524
525         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, READ_LOCK)) &&
526               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 80, 4, 0, WRITE_LOCK));
527         EXPECTED(ret, False);
528         printf("the same process %s overlay a read lock with a write lock\n", ret?"can":"cannot");
529
530         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, WRITE_LOCK)) &&
531               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 90, 4, 0, READ_LOCK));
532         EXPECTED(ret, True);
533         printf("the same process %s overlay a write lock with a read lock\n", ret?"can":"cannot");
534
535         ret = NT_STATUS_IS_OK((cli1->session->pid = 1, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, WRITE_LOCK))) &&
536               NT_STATUS_IS_OK((cli1->session->pid = 2, smbcli_lock(cli1->tree, fnum1, 100, 4, 0, READ_LOCK)));
537         EXPECTED(ret, False);
538         printf("a different pid %s overlay a write lock with a read lock\n", ret?"can":"cannot");
539
540         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 110, 4, 0, READ_LOCK)) &&
541               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 112, 4, 0, READ_LOCK)) &&
542               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 110, 6));
543         EXPECTED(ret, False);
544         printf("the same process %s coalesce read locks\n", ret?"can":"cannot");
545
546
547         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 120, 4, 0, WRITE_LOCK)) &&
548               (smbcli_read(cli2->tree, fnum2, buf, 120, 4) == 4);
549         EXPECTED(ret, False);
550         printf("this server %s strict write locking\n", ret?"doesn't do":"does");
551
552         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK)) &&
553               (smbcli_write(cli2->tree, fnum2, 0, buf, 130, 4) == 4);
554         EXPECTED(ret, False);
555         printf("this server %s strict read locking\n", ret?"doesn't do":"does");
556
557
558         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
559               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 140, 4, 0, READ_LOCK)) &&
560               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4)) &&
561               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 140, 4));
562         EXPECTED(ret, True);
563         printf("this server %s do recursive read locking\n", ret?"does":"doesn't");
564
565
566         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, WRITE_LOCK)) &&
567               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 150, 4, 0, READ_LOCK)) &&
568               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4)) &&
569               (smbcli_read(cli2->tree, fnum2, buf, 150, 4) == 4) &&
570               !(smbcli_write(cli2->tree, fnum2, 0, buf, 150, 4) == 4) &&
571               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 150, 4));
572         EXPECTED(ret, True);
573         printf("this server %s do recursive lock overlays\n", ret?"does":"doesn't");
574
575         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 160, 4, 0, READ_LOCK)) &&
576               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 160, 4)) &&
577               (smbcli_write(cli2->tree, fnum2, 0, buf, 160, 4) == 4) &&         
578               (smbcli_read(cli2->tree, fnum2, buf, 160, 4) == 4);               
579         EXPECTED(ret, True);
580         printf("the same process %s remove a read lock using write locking\n", ret?"can":"cannot");
581
582         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 170, 4, 0, WRITE_LOCK)) &&
583               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 170, 4)) &&
584               (smbcli_write(cli2->tree, fnum2, 0, buf, 170, 4) == 4) &&         
585               (smbcli_read(cli2->tree, fnum2, buf, 170, 4) == 4);               
586         EXPECTED(ret, True);
587         printf("the same process %s remove a write lock using read locking\n", ret?"can":"cannot");
588
589         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, WRITE_LOCK)) &&
590               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 190, 4, 0, READ_LOCK)) &&
591               NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 190, 4)) &&
592               !(smbcli_write(cli2->tree, fnum2, 0, buf, 190, 4) == 4) &&                
593               (smbcli_read(cli2->tree, fnum2, buf, 190, 4) == 4);               
594         EXPECTED(ret, True);
595         printf("the same process %s remove the first lock first\n", ret?"does":"doesn't");
596
597         smbcli_close(cli1->tree, fnum1);
598         smbcli_close(cli2->tree, fnum2);
599         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
600         f = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
601         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
602               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, f, 0, 1, 0, READ_LOCK)) &&
603               NT_STATUS_IS_OK(smbcli_close(cli1->tree, fnum1)) &&
604               ((fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE)) != -1) &&
605               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
606         smbcli_close(cli1->tree, f);
607         smbcli_close(cli1->tree, fnum1);
608         EXPECTED(ret, True);
609         printf("the server %s have the NT byte range lock bug\n", !ret?"does":"doesn't");
610
611  fail:
612         smbcli_close(cli1->tree, fnum1);
613         smbcli_close(cli2->tree, fnum2);
614         smbcli_unlink(cli1->tree, fname);
615         torture_close_connection(cli1);
616         torture_close_connection(cli2);
617
618         printf("finished locktest4\n");
619         return correct;
620 }
621
622 /*
623   looks at lock upgrade/downgrade.
624 */
625 BOOL torture_locktest5(int dummy)
626 {
627         struct smbcli_state *cli1, *cli2;
628         const char *fname = "\\lockt5.lck";
629         int fnum1, fnum2, fnum3;
630         BOOL ret;
631         char buf[1000];
632         BOOL correct = True;
633
634         if (!torture_open_connection(&cli1) || !torture_open_connection(&cli2)) {
635                 return False;
636         }
637
638         printf("starting locktest5\n");
639
640         smbcli_unlink(cli1->tree, fname);
641
642         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
643         fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
644         fnum3 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
645
646         memset(buf, 0, sizeof(buf));
647
648         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
649                 printf("Failed to create file\n");
650                 correct = False;
651                 goto fail;
652         }
653
654         /* Check for NT bug... */
655         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 8, 0, READ_LOCK)) &&
656                   NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 1, 0, READ_LOCK));
657         smbcli_close(cli1->tree, fnum1);
658         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
659         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 7, 1, 0, WRITE_LOCK));
660         EXPECTED(ret, True);
661         printf("this server %s the NT locking bug\n", ret ? "doesn't have" : "has");
662         smbcli_close(cli1->tree, fnum1);
663         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR, DENY_NONE);
664         smbcli_unlock(cli1->tree, fnum3, 0, 1);
665
666         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, WRITE_LOCK)) &&
667               NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 1, 1, 0, READ_LOCK));
668         EXPECTED(ret, True);
669         printf("the same process %s overlay a write with a read lock\n", ret?"can":"cannot");
670
671         ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
672         EXPECTED(ret, False);
673
674         printf("a different processs %s get a read lock on the first process lock stack\n", ret?"can":"cannot");
675
676         /* Unlock the process 2 lock. */
677         smbcli_unlock(cli2->tree, fnum2, 0, 4);
678
679         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum3, 0, 4, 0, READ_LOCK));
680         EXPECTED(ret, False);
681
682         printf("the same processs on a different fnum %s get a read lock\n", ret?"can":"cannot");
683
684         /* Unlock the process 1 fnum3 lock. */
685         smbcli_unlock(cli1->tree, fnum3, 0, 4);
686
687         /* Stack 2 more locks here. */
688         ret = NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK)) &&
689                   NT_STATUS_IS_OK(smbcli_lock(cli1->tree, fnum1, 0, 4, 0, READ_LOCK));
690
691         EXPECTED(ret, True);
692         printf("the same process %s stack read locks\n", ret?"can":"cannot");
693
694         /* Unlock the first process lock, then check this was the WRITE lock that was
695                 removed. */
696
697 ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
698         NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, READ_LOCK));
699
700         EXPECTED(ret, True);
701         printf("the first unlock removes the %s lock\n", ret?"WRITE":"READ");
702
703         /* Unlock the process 2 lock. */
704         smbcli_unlock(cli2->tree, fnum2, 0, 4);
705
706         /* We should have 3 stacked locks here. Ensure we need to do 3 unlocks. */
707
708         ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 1, 1)) &&
709                   NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4)) &&
710                   NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
711
712         EXPECTED(ret, True);
713         printf("the same process %s unlock the stack of 4 locks\n", ret?"can":"cannot"); 
714
715         /* Ensure the next unlock fails. */
716         ret = NT_STATUS_IS_OK(smbcli_unlock(cli1->tree, fnum1, 0, 4));
717         EXPECTED(ret, False);
718         printf("the same process %s count the lock stack\n", !ret?"can":"cannot"); 
719
720         /* Ensure connection 2 can get a write lock. */
721         ret = NT_STATUS_IS_OK(smbcli_lock(cli2->tree, fnum2, 0, 4, 0, WRITE_LOCK));
722         EXPECTED(ret, True);
723
724         printf("a different processs %s get a write lock on the unlocked stack\n", ret?"can":"cannot");
725
726
727  fail:
728         smbcli_close(cli1->tree, fnum1);
729         smbcli_close(cli2->tree, fnum2);
730         smbcli_unlink(cli1->tree, fname);
731         if (!torture_close_connection(cli1)) {
732                 correct = False;
733         }
734         if (!torture_close_connection(cli2)) {
735                 correct = False;
736         }
737
738         printf("finished locktest5\n");
739        
740         return correct;
741 }
742
743 /*
744   tries the unusual lockingX locktype bits
745 */
746 BOOL torture_locktest6(int dummy)
747 {
748         struct smbcli_state *cli;
749         const char *fname[1] = { "\\lock6.txt" };
750         int i;
751         int fnum;
752         NTSTATUS status;
753
754         if (!torture_open_connection(&cli)) {
755                 return False;
756         }
757
758         printf("starting locktest6\n");
759
760         for (i=0;i<1;i++) {
761                 printf("Testing %s\n", fname[i]);
762
763                 smbcli_unlink(cli->tree, fname[i]);
764
765                 fnum = smbcli_open(cli->tree, fname[i], O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
766                 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CHANGE_LOCKTYPE);
767                 smbcli_close(cli->tree, fnum);
768                 printf("CHANGE_LOCKTYPE gave %s\n", nt_errstr(status));
769
770                 fnum = smbcli_open(cli->tree, fname[i], O_RDWR, DENY_NONE);
771                 status = smbcli_locktype(cli->tree, fnum, 0, 8, 0, LOCKING_ANDX_CANCEL_LOCK);
772                 smbcli_close(cli->tree, fnum);
773                 printf("CANCEL_LOCK gave %s\n", nt_errstr(status));
774
775                 smbcli_unlink(cli->tree, fname[i]);
776         }
777
778         torture_close_connection(cli);
779
780         printf("finished locktest6\n");
781         return True;
782 }
783
784 BOOL torture_locktest7(int dummy)
785 {
786         struct smbcli_state *cli1;
787         const char *fname = "\\lockt7.lck";
788         int fnum1;
789         int fnum2;
790         size_t size;
791         char buf[200];
792         BOOL correct = False;
793
794         if (!torture_open_connection(&cli1)) {
795                 return False;
796         }
797
798         printf("starting locktest7\n");
799
800         smbcli_unlink(cli1->tree, fname);
801
802         fnum1 = smbcli_open(cli1->tree, fname, O_RDWR|O_CREAT|O_EXCL, DENY_NONE);
803
804         memset(buf, 0, sizeof(buf));
805
806         if (smbcli_write(cli1->tree, fnum1, 0, buf, 0, sizeof(buf)) != sizeof(buf)) {
807                 printf("Failed to create file (%s)\n", __location__);
808                 goto fail;
809         }
810
811         cli1->session->pid = 1;
812
813         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, READ_LOCK))) {
814                 printf("Unable to apply read lock on range 130:4, error was %s (%s)\n", 
815                        smbcli_errstr(cli1->tree), __location__);
816                 goto fail;
817         } else {
818                 printf("pid1 successfully locked range 130:4 for READ\n");
819         }
820
821         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
822                 printf("pid1 unable to read the range 130:4, error was %s (%s)\n", 
823                        smbcli_errstr(cli1->tree), __location__);
824                 goto fail;
825         } else {
826                 printf("pid1 successfully read the range 130:4\n");
827         }
828
829         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
830                 printf("pid1 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
831                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
832                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n", 
833                                __location__);
834                         goto fail;
835                 }
836         } else {
837                 printf("pid1 successfully wrote to the range 130:4 (should be denied) (%s)\n", 
838                        __location__);
839                 goto fail;
840         }
841
842         cli1->session->pid = 2;
843
844         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
845                 printf("pid2 unable to read the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
846         } else {
847                 printf("pid2 successfully read the range 130:4\n");
848         }
849
850         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
851                 printf("pid2 unable to write to the range 130:4, error was %s\n", smbcli_errstr(cli1->tree));
852                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
853                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
854                                __location__);
855                         goto fail;
856                 }
857         } else {
858                 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n", 
859                        __location__);
860                 goto fail;
861         }
862
863         cli1->session->pid = 1;
864         smbcli_unlock(cli1->tree, fnum1, 130, 4);
865
866         if (NT_STATUS_IS_ERR(smbcli_lock(cli1->tree, fnum1, 130, 4, 0, WRITE_LOCK))) {
867                 printf("Unable to apply write lock on range 130:4, error was %s (%s)\n", 
868                        smbcli_errstr(cli1->tree), __location__);
869                 goto fail;
870         } else {
871                 printf("pid1 successfully locked range 130:4 for WRITE\n");
872         }
873
874         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
875                 printf("pid1 unable to read the range 130:4, error was %s (%s)\n", 
876                        smbcli_errstr(cli1->tree), __location__);
877                 goto fail;
878         } else {
879                 printf("pid1 successfully read the range 130:4\n");
880         }
881
882         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
883                 printf("pid1 unable to write to the range 130:4, error was %s (%s)\n", 
884                        smbcli_errstr(cli1->tree), __location__);
885                 goto fail;
886         } else {
887                 printf("pid1 successfully wrote to the range 130:4\n");
888         }
889
890         cli1->session->pid = 2;
891
892         if (smbcli_read(cli1->tree, fnum1, buf, 130, 4) != 4) {
893                 printf("pid2 unable to read the range 130:4, error was %s\n", 
894                        smbcli_errstr(cli1->tree));
895                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
896                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
897                                __location__);
898                         goto fail;
899                 }
900         } else {
901                 printf("pid2 successfully read the range 130:4 (should be denied) (%s)\n", 
902                        __location__);
903                 goto fail;
904         }
905
906         if (smbcli_write(cli1->tree, fnum1, 0, buf, 130, 4) != 4) {
907                 printf("pid2 unable to write to the range 130:4, error was %s\n", 
908                        smbcli_errstr(cli1->tree));
909                 if (NT_STATUS_V(smbcli_nt_error(cli1->tree)) != NT_STATUS_V(NT_STATUS_FILE_LOCK_CONFLICT)) {
910                         printf("Incorrect error (should be NT_STATUS_FILE_LOCK_CONFLICT) (%s)\n",
911                                __location__);
912                         goto fail;
913                 }
914         } else {
915                 printf("pid2 successfully wrote to the range 130:4 (should be denied) (%s)\n", 
916                        __location__);
917                 goto fail;
918         }
919
920         printf("Testing truncate of locked file.\n");
921
922         fnum2 = smbcli_open(cli1->tree, fname, O_RDWR|O_TRUNC, DENY_NONE);
923
924         if (fnum2 == -1) {
925                 printf("Unable to truncate locked file (%s)\n", __location__);
926                 correct = False;
927                 goto fail;
928         } else {
929                 printf("Truncated locked file.\n");
930         }
931
932         if (NT_STATUS_IS_ERR(smbcli_getatr(cli1->tree, fname, NULL, &size, NULL))) {
933                 printf("getatr failed (%s) (%s)\n", smbcli_errstr(cli1->tree), __location__);
934                 correct = False;
935                 goto fail;
936         }
937
938         if (size != 0) {
939                 printf("Unable to truncate locked file. Size was %u (%s)\n", size, __location__);
940                 correct = False;
941                 goto fail;
942         }
943
944         cli1->session->pid = 1;
945
946         smbcli_unlock(cli1->tree, fnum1, 130, 4);
947         correct = True;
948
949 fail:
950         smbcli_close(cli1->tree, fnum1);
951         smbcli_close(cli1->tree, fnum2);
952         smbcli_unlink(cli1->tree, fname);
953         torture_close_connection(cli1);
954
955         printf("finished locktest7\n");
956         return correct;
957 }
958