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