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