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