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