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