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