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