r14720: Add torture_context argument to all torture tests
[gd/samba-autobuild/.git] / source4 / torture / raw / lock.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for various lock operations
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
28
29 #define CHECK_STATUS(status, correct) do { \
30         if (!NT_STATUS_EQUAL(status, correct)) { \
31                 printf("(%s) Incorrect status %s - should be %s\n", \
32                        __location__, nt_errstr(status), nt_errstr(correct)); \
33                 ret = False; \
34                 goto done; \
35         }} while (0)
36
37 #define CHECK_VALUE(v, correct) do { \
38         if ((v) != (correct)) { \
39                 printf("(%s) Incorrect value %s=%d - should be %d\n", \
40                        __location__, #v, v, correct); \
41                 ret = False; \
42                 goto done; \
43         }} while (0)
44
45 #define BASEDIR "\\testlock"
46
47
48 /*
49   test SMBlock and SMBunlock ops
50 */
51 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
52 {
53         union smb_lock io;
54         NTSTATUS status;
55         BOOL ret = True;
56         int fnum;
57         const char *fname = BASEDIR "\\test.txt";
58
59         if (!torture_setup_dir(cli, BASEDIR)) {
60                 return False;
61         }
62
63         printf("Testing RAW_LOCK_LOCK\n");
64         io.generic.level = RAW_LOCK_LOCK;
65         
66         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
67         if (fnum == -1) {
68                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
69                 ret = False;
70                 goto done;
71         }
72
73         printf("Trying 0/0 lock\n");
74         io.lock.level = RAW_LOCK_LOCK;
75         io.lock.in.file.fnum = fnum;
76         io.lock.in.count = 0;
77         io.lock.in.offset = 0;
78         status = smb_raw_lock(cli->tree, &io);
79         CHECK_STATUS(status, NT_STATUS_OK);
80         cli->session->pid++;
81         status = smb_raw_lock(cli->tree, &io);
82         CHECK_STATUS(status, NT_STATUS_OK);
83         cli->session->pid--;
84         io.lock.level = RAW_LOCK_UNLOCK;
85         status = smb_raw_lock(cli->tree, &io);
86         CHECK_STATUS(status, NT_STATUS_OK);
87
88         printf("Trying 0/1 lock\n");
89         io.lock.level = RAW_LOCK_LOCK;
90         io.lock.in.file.fnum = fnum;
91         io.lock.in.count = 1;
92         io.lock.in.offset = 0;
93         status = smb_raw_lock(cli->tree, &io);
94         CHECK_STATUS(status, NT_STATUS_OK);
95         cli->session->pid++;
96         status = smb_raw_lock(cli->tree, &io);
97         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
98         cli->session->pid--;
99         io.lock.level = RAW_LOCK_UNLOCK;
100         status = smb_raw_lock(cli->tree, &io);
101         CHECK_STATUS(status, NT_STATUS_OK);
102         io.lock.level = RAW_LOCK_UNLOCK;
103         status = smb_raw_lock(cli->tree, &io);
104         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
105
106         printf("Trying 0xEEFFFFFF lock\n");
107         io.lock.level = RAW_LOCK_LOCK;
108         io.lock.in.file.fnum = fnum;
109         io.lock.in.count = 4000;
110         io.lock.in.offset = 0xEEFFFFFF;
111         status = smb_raw_lock(cli->tree, &io);
112         CHECK_STATUS(status, NT_STATUS_OK);
113         cli->session->pid++;
114         status = smb_raw_lock(cli->tree, &io);
115         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
116         cli->session->pid--;
117         io.lock.level = RAW_LOCK_UNLOCK;
118         status = smb_raw_lock(cli->tree, &io);
119         CHECK_STATUS(status, NT_STATUS_OK);
120         io.lock.level = RAW_LOCK_UNLOCK;
121         status = smb_raw_lock(cli->tree, &io);
122         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
123
124         printf("Trying 0xEF000000 lock\n");
125         io.lock.level = RAW_LOCK_LOCK;
126         io.lock.in.file.fnum = fnum;
127         io.lock.in.count = 4000;
128         io.lock.in.offset = 0xEEFFFFFF;
129         status = smb_raw_lock(cli->tree, &io);
130         CHECK_STATUS(status, NT_STATUS_OK);
131         cli->session->pid++;
132         status = smb_raw_lock(cli->tree, &io);
133         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
134         cli->session->pid--;
135         io.lock.level = RAW_LOCK_UNLOCK;
136         status = smb_raw_lock(cli->tree, &io);
137         CHECK_STATUS(status, NT_STATUS_OK);
138         io.lock.level = RAW_LOCK_UNLOCK;
139         status = smb_raw_lock(cli->tree, &io);
140         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
141
142         printf("Trying max lock\n");
143         io.lock.level = RAW_LOCK_LOCK;
144         io.lock.in.file.fnum = fnum;
145         io.lock.in.count = 4000;
146         io.lock.in.offset = 0xEF000000;
147         status = smb_raw_lock(cli->tree, &io);
148         CHECK_STATUS(status, NT_STATUS_OK);
149         cli->session->pid++;
150         status = smb_raw_lock(cli->tree, &io);
151         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
152         cli->session->pid--;
153         io.lock.level = RAW_LOCK_UNLOCK;
154         status = smb_raw_lock(cli->tree, &io);
155         CHECK_STATUS(status, NT_STATUS_OK);
156         io.lock.level = RAW_LOCK_UNLOCK;
157         status = smb_raw_lock(cli->tree, &io);
158         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
159
160         printf("Trying wrong pid unlock\n");
161         io.lock.level = RAW_LOCK_LOCK;
162         io.lock.in.file.fnum = fnum;
163         io.lock.in.count = 4002;
164         io.lock.in.offset = 10001;
165         status = smb_raw_lock(cli->tree, &io);
166         CHECK_STATUS(status, NT_STATUS_OK);
167         cli->session->pid++;
168         io.lock.level = RAW_LOCK_UNLOCK;
169         status = smb_raw_lock(cli->tree, &io);
170         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
171         cli->session->pid--;
172         status = smb_raw_lock(cli->tree, &io);
173         CHECK_STATUS(status, NT_STATUS_OK);
174
175 done:
176         smbcli_close(cli->tree, fnum);
177         smb_raw_exit(cli->session);
178         smbcli_deltree(cli->tree, BASEDIR);
179         return ret;
180 }
181
182
183 /*
184   test locking&X ops
185 */
186 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
187 {
188         union smb_lock io;
189         struct smb_lock_entry lock[1];
190         NTSTATUS status;
191         BOOL ret = True;
192         int fnum;
193         const char *fname = BASEDIR "\\test.txt";
194
195         if (!torture_setup_dir(cli, BASEDIR)) {
196                 return False;
197         }
198
199         printf("Testing RAW_LOCK_LOCKX\n");
200         io.generic.level = RAW_LOCK_LOCKX;
201         
202         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
203         if (fnum == -1) {
204                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
205                 ret = False;
206                 goto done;
207         }
208
209         io.lockx.level = RAW_LOCK_LOCKX;
210         io.lockx.in.file.fnum = fnum;
211         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
212         io.lockx.in.timeout = 0;
213         io.lockx.in.ulock_cnt = 0;
214         io.lockx.in.lock_cnt = 1;
215         lock[0].pid = cli->session->pid;
216         lock[0].offset = 10;
217         lock[0].count = 1;
218         io.lockx.in.locks = &lock[0];
219         status = smb_raw_lock(cli->tree, &io);
220         CHECK_STATUS(status, NT_STATUS_OK);
221
222
223         printf("Trying 0xEEFFFFFF lock\n");
224         io.lockx.in.ulock_cnt = 0;
225         io.lockx.in.lock_cnt = 1;
226         lock[0].count = 4000;
227         lock[0].offset = 0xEEFFFFFF;
228         status = smb_raw_lock(cli->tree, &io);
229         CHECK_STATUS(status, NT_STATUS_OK);
230         lock[0].pid++;
231         status = smb_raw_lock(cli->tree, &io);
232         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
233         lock[0].pid--;
234         io.lockx.in.ulock_cnt = 1;
235         io.lockx.in.lock_cnt = 0;
236         status = smb_raw_lock(cli->tree, &io);
237         CHECK_STATUS(status, NT_STATUS_OK);
238         status = smb_raw_lock(cli->tree, &io);
239         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
240
241         printf("Trying 0xEF000000 lock\n");
242         io.lockx.in.ulock_cnt = 0;
243         io.lockx.in.lock_cnt = 1;
244         lock[0].count = 4000;
245         lock[0].offset = 0xEF000000;
246         status = smb_raw_lock(cli->tree, &io);
247         CHECK_STATUS(status, NT_STATUS_OK);
248         lock[0].pid++;
249         status = smb_raw_lock(cli->tree, &io);
250         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
251         lock[0].pid--;
252         io.lockx.in.ulock_cnt = 1;
253         io.lockx.in.lock_cnt = 0;
254         status = smb_raw_lock(cli->tree, &io);
255         CHECK_STATUS(status, NT_STATUS_OK);
256         status = smb_raw_lock(cli->tree, &io);
257         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
258
259         printf("Trying zero lock\n");
260         io.lockx.in.ulock_cnt = 0;
261         io.lockx.in.lock_cnt = 1;
262         lock[0].count = 0;
263         lock[0].offset = ~0;
264         status = smb_raw_lock(cli->tree, &io);
265         CHECK_STATUS(status, NT_STATUS_OK);
266         lock[0].pid++;
267         status = smb_raw_lock(cli->tree, &io);
268         CHECK_STATUS(status, NT_STATUS_OK);
269         lock[0].pid--;
270         io.lockx.in.ulock_cnt = 1;
271         io.lockx.in.lock_cnt = 0;
272         status = smb_raw_lock(cli->tree, &io);
273         CHECK_STATUS(status, NT_STATUS_OK);
274         status = smb_raw_lock(cli->tree, &io);
275         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
276
277         printf("Trying max lock\n");
278         io.lockx.in.ulock_cnt = 0;
279         io.lockx.in.lock_cnt = 1;
280         lock[0].count = 0;
281         lock[0].offset = ~0;
282         status = smb_raw_lock(cli->tree, &io);
283         CHECK_STATUS(status, NT_STATUS_OK);
284         lock[0].pid++;
285         status = smb_raw_lock(cli->tree, &io);
286         CHECK_STATUS(status, NT_STATUS_OK);
287         lock[0].pid--;
288         io.lockx.in.ulock_cnt = 1;
289         io.lockx.in.lock_cnt = 0;
290         status = smb_raw_lock(cli->tree, &io);
291         CHECK_STATUS(status, NT_STATUS_OK);
292         status = smb_raw_lock(cli->tree, &io);
293         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
294
295         printf("Trying 2^63\n");
296         io.lockx.in.ulock_cnt = 0;
297         io.lockx.in.lock_cnt = 1;
298         lock[0].count = 1;
299         lock[0].offset = 1;
300         lock[0].offset <<= 63;
301         status = smb_raw_lock(cli->tree, &io);
302         CHECK_STATUS(status, NT_STATUS_OK);
303         lock[0].pid++;
304         status = smb_raw_lock(cli->tree, &io);
305         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
306         lock[0].pid--;
307         io.lockx.in.ulock_cnt = 1;
308         io.lockx.in.lock_cnt = 0;
309         status = smb_raw_lock(cli->tree, &io);
310         CHECK_STATUS(status, NT_STATUS_OK);
311         status = smb_raw_lock(cli->tree, &io);
312         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
313
314         printf("Trying 2^63 - 1\n");
315         io.lockx.in.ulock_cnt = 0;
316         io.lockx.in.lock_cnt = 1;
317         lock[0].count = 1;
318         lock[0].offset = 1;
319         lock[0].offset <<= 63;
320         lock[0].offset--;
321         status = smb_raw_lock(cli->tree, &io);
322         CHECK_STATUS(status, NT_STATUS_OK);
323         lock[0].pid++;
324         status = smb_raw_lock(cli->tree, &io);
325         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
326         lock[0].pid--;
327         io.lockx.in.ulock_cnt = 1;
328         io.lockx.in.lock_cnt = 0;
329         status = smb_raw_lock(cli->tree, &io);
330         CHECK_STATUS(status, NT_STATUS_OK);
331         status = smb_raw_lock(cli->tree, &io);
332         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
333
334         printf("Trying max lock 2\n");
335         io.lockx.in.ulock_cnt = 0;
336         io.lockx.in.lock_cnt = 1;
337         lock[0].count = 1;
338         lock[0].offset = ~0;
339         status = smb_raw_lock(cli->tree, &io);
340         CHECK_STATUS(status, NT_STATUS_OK);
341         lock[0].pid++;
342         lock[0].count = 2;
343         status = smb_raw_lock(cli->tree, &io);
344         CHECK_STATUS(status, NT_STATUS_OK);
345         lock[0].pid--;
346         io.lockx.in.ulock_cnt = 1;
347         io.lockx.in.lock_cnt = 0;
348         lock[0].count = 1;
349         status = smb_raw_lock(cli->tree, &io);
350         CHECK_STATUS(status, NT_STATUS_OK);
351         status = smb_raw_lock(cli->tree, &io);
352         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
353
354 done:
355         smbcli_close(cli->tree, fnum);
356         smb_raw_exit(cli->session);
357         smbcli_deltree(cli->tree, BASEDIR);
358         return ret;
359 }
360
361
362 /*
363   test high pid
364 */
365 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
366 {
367         union smb_lock io;
368         struct smb_lock_entry lock[1];
369         NTSTATUS status;
370         BOOL ret = True;
371         int fnum;
372         const char *fname = BASEDIR "\\test.txt";
373         uint8_t c = 1;
374
375         if (!torture_setup_dir(cli, BASEDIR)) {
376                 return False;
377         }
378
379         printf("Testing high pid\n");
380         io.generic.level = RAW_LOCK_LOCKX;
381
382         cli->session->pid = 1;
383         
384         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
385         if (fnum == -1) {
386                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
387                 ret = False;
388                 goto done;
389         }
390
391         if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
392                 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
393                 ret = False;
394                 goto done;
395         }
396
397         io.lockx.level = RAW_LOCK_LOCKX;
398         io.lockx.in.file.fnum = fnum;
399         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
400         io.lockx.in.timeout = 0;
401         io.lockx.in.ulock_cnt = 0;
402         io.lockx.in.lock_cnt = 1;
403         lock[0].pid = cli->session->pid;
404         lock[0].offset = 0;
405         lock[0].count = 0xFFFFFFFF;
406         io.lockx.in.locks = &lock[0];
407         status = smb_raw_lock(cli->tree, &io);
408         CHECK_STATUS(status, NT_STATUS_OK);
409
410         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
411                 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
412                 ret = False;
413                 goto done;
414         }
415
416         cli->session->pid |= 0x10000;
417
418         cli->session->pid = 2;
419
420         if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
421                 printf("pid is incorrect handled for read with lock!\n");
422                 ret = False;
423                 goto done;
424         }
425
426         cli->session->pid = 0x10001;
427
428         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
429                 printf("High pid is used on this server!\n");
430                 ret = False;
431         } else {
432                 printf("High pid is not used on this server (correct)\n");
433         }
434
435 done:
436         smbcli_close(cli->tree, fnum);
437         smb_raw_exit(cli->session);
438         smbcli_deltree(cli->tree, BASEDIR);
439         return ret;
440 }
441
442
443 /*
444   test locking&X async operation
445 */
446 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
447 {
448         union smb_lock io;
449         struct smb_lock_entry lock[2];
450         NTSTATUS status;
451         BOOL ret = True;
452         int fnum;
453         const char *fname = BASEDIR "\\test.txt";
454         time_t t;
455         struct smbcli_request *req;
456
457         if (!torture_setup_dir(cli, BASEDIR)) {
458                 return False;
459         }
460
461         printf("Testing LOCKING_ANDX_CANCEL_LOCK\n");
462         io.generic.level = RAW_LOCK_LOCKX;
463         
464         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
465         if (fnum == -1) {
466                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
467                 ret = False;
468                 goto done;
469         }
470
471         io.lockx.level = RAW_LOCK_LOCKX;
472         io.lockx.in.file.fnum = fnum;
473         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
474         io.lockx.in.timeout = 0;
475         io.lockx.in.ulock_cnt = 0;
476         io.lockx.in.lock_cnt = 1;
477         lock[0].pid = cli->session->pid;
478         lock[0].offset = 100;
479         lock[0].count = 10;
480         io.lockx.in.locks = &lock[0];
481         status = smb_raw_lock(cli->tree, &io);
482         CHECK_STATUS(status, NT_STATUS_OK);
483
484         t = time(NULL);
485
486         printf("testing cancel by CANCEL_LOCK\n");
487
488         /* setup a timed lock */
489         io.lockx.in.timeout = 10000;
490         req = smb_raw_lock_send(cli->tree, &io);
491         if (req == NULL) {
492                 printf("Failed to setup timed lock (%s)\n", __location__);
493                 ret = False;
494                 goto done;
495         }
496
497         /* cancel the wrong range */
498         lock[0].offset = 0;
499         io.lockx.in.timeout = 0;
500         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
501         status = smb_raw_lock(cli->tree, &io);
502         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
503
504         /* cancel with the wrong bits set */
505         lock[0].offset = 100;
506         io.lockx.in.timeout = 0;
507         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK;
508         status = smb_raw_lock(cli->tree, &io);
509         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRcancelviolation));
510
511         /* cancel the right range */
512         lock[0].offset = 100;
513         io.lockx.in.timeout = 0;
514         io.lockx.in.mode = LOCKING_ANDX_CANCEL_LOCK | LOCKING_ANDX_LARGE_FILES;
515         status = smb_raw_lock(cli->tree, &io);
516         CHECK_STATUS(status, NT_STATUS_OK);
517
518         /* receive the failed lock request */
519         status = smbcli_request_simple_recv(req);
520         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
521
522         if (time(NULL) > t+2) {
523                 printf("lock cancel was not immediate (%s)\n", __location__);
524                 ret = False;
525                 goto done;
526         }
527
528         printf("testing cancel by unlock\n");
529         io.lockx.in.ulock_cnt = 0;
530         io.lockx.in.lock_cnt = 1;
531         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
532         io.lockx.in.timeout = 0;
533         status = smb_raw_lock(cli->tree, &io);
534         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
535
536         io.lockx.in.timeout = 5000;
537         req = smb_raw_lock_send(cli->tree, &io);
538         if (req == NULL) {
539                 printf("Failed to setup timed lock (%s)\n", __location__);
540                 ret = False;
541                 goto done;
542         }
543
544         io.lockx.in.ulock_cnt = 1;
545         io.lockx.in.lock_cnt = 0;
546         status = smb_raw_lock(cli->tree, &io);
547         CHECK_STATUS(status, NT_STATUS_OK);
548
549         t = time(NULL);
550         status = smbcli_request_simple_recv(req);
551         CHECK_STATUS(status, NT_STATUS_OK);
552
553         if (time(NULL) > t+2) {
554                 printf("lock cancel by unlock was not immediate (%s) - took %d secs\n", 
555                        __location__, (int)(time(NULL)-t));
556                 ret = False;
557                 goto done;
558         }
559
560
561         printf("testing cancel by close\n");
562         io.lockx.in.ulock_cnt = 0;
563         io.lockx.in.lock_cnt = 1;
564         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
565         io.lockx.in.timeout = 0;
566         status = smb_raw_lock(cli->tree, &io);
567         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
568
569         io.lockx.in.timeout = 10000;
570         req = smb_raw_lock_send(cli->tree, &io);
571         if (req == NULL) {
572                 printf("Failed to setup timed lock (%s)\n", __location__);
573                 ret = False;
574                 goto done;
575         }
576
577         smbcli_close(cli->tree, fnum);
578
579         status = smbcli_request_simple_recv(req);
580         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
581
582         if (time(NULL) > t+2) {
583                 printf("lock cancel by unlock was not immediate (%s)\n", __location__);
584                 ret = False;
585                 goto done;
586         }
587         
588
589 done:
590         smbcli_close(cli->tree, fnum);
591         smb_raw_exit(cli->session);
592         smbcli_deltree(cli->tree, BASEDIR);
593         return ret;
594 }
595
596
597 /*
598   test LOCKING_ANDX_CHANGE_LOCKTYPE
599 */
600 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
601 {
602         union smb_lock io;
603         struct smb_lock_entry lock[2];
604         NTSTATUS status;
605         BOOL ret = True;
606         int fnum;
607         uint8_t c = 0;
608         const char *fname = BASEDIR "\\test.txt";
609
610         if (!torture_setup_dir(cli, BASEDIR)) {
611                 return False;
612         }
613
614         printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
615         io.generic.level = RAW_LOCK_LOCKX;
616         
617         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
618         if (fnum == -1) {
619                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
620                 ret = False;
621                 goto done;
622         }
623
624         io.lockx.level = RAW_LOCK_LOCKX;
625         io.lockx.in.file.fnum = fnum;
626         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
627         io.lockx.in.timeout = 0;
628         io.lockx.in.ulock_cnt = 0;
629         io.lockx.in.lock_cnt = 1;
630         lock[0].pid = cli->session->pid;
631         lock[0].offset = 100;
632         lock[0].count = 10;
633         io.lockx.in.locks = &lock[0];
634         status = smb_raw_lock(cli->tree, &io);
635         CHECK_STATUS(status, NT_STATUS_OK);
636
637         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
638                 printf("allowed write on read locked region (%s)\n", __location__);
639                 ret = False;
640                 goto done;
641         }
642
643         /* windows server don't seem to support this */
644         io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
645         status = smb_raw_lock(cli->tree, &io);
646         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
647
648         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
649                 printf("allowed write after lock change (%s)\n", __location__);
650                 ret = False;
651                 goto done;
652         }
653
654 done:
655         smbcli_close(cli->tree, fnum);
656         smb_raw_exit(cli->session);
657         smbcli_deltree(cli->tree, BASEDIR);
658         return ret;
659 }
660
661
662 /* 
663    basic testing of lock calls
664 */
665 BOOL torture_raw_lock(struct torture_context *torture)
666 {
667         struct smbcli_state *cli;
668         BOOL ret = True;
669         TALLOC_CTX *mem_ctx;
670
671         if (!torture_open_connection(&cli)) {
672                 return False;
673         }
674
675         mem_ctx = talloc_init("torture_raw_lock");
676
677         ret &= test_lockx(cli, mem_ctx);
678         ret &= test_lock(cli, mem_ctx);
679         ret &= test_pidhigh(cli, mem_ctx);
680         ret &= test_async(cli, mem_ctx);
681         ret &= test_changetype(cli, mem_ctx);
682
683         torture_close_connection(cli);
684         talloc_free(mem_ctx);
685         return ret;
686 }