r23792: convert Samba4 to GPLv3
[samba.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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "includes.h"
21 #include "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27 #include "libcli/composite/composite.h"
28 #include "libcli/smb_composite/smb_composite.h"
29 #include "lib/cmdline/popt_common.h"
30
31 #define CHECK_STATUS(status, correct) do { \
32         if (!NT_STATUS_EQUAL(status, correct)) { \
33                 printf("(%s) Incorrect status %s - should be %s\n", \
34                        __location__, nt_errstr(status), nt_errstr(correct)); \
35                 ret = False; \
36                 goto done; \
37         }} while (0)
38
39 #define BASEDIR "\\testlock"
40
41
42 /*
43   test SMBlock and SMBunlock ops
44 */
45 static BOOL test_lock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
46 {
47         union smb_lock io;
48         NTSTATUS status;
49         BOOL ret = True;
50         int fnum;
51         const char *fname = BASEDIR "\\test.txt";
52
53         if (!torture_setup_dir(cli, BASEDIR)) {
54                 return False;
55         }
56
57         printf("Testing RAW_LOCK_LOCK\n");
58         io.generic.level = RAW_LOCK_LOCK;
59         
60         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
61         if (fnum == -1) {
62                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
63                 ret = False;
64                 goto done;
65         }
66
67         printf("Trying 0/0 lock\n");
68         io.lock.level = RAW_LOCK_LOCK;
69         io.lock.in.file.fnum = fnum;
70         io.lock.in.count = 0;
71         io.lock.in.offset = 0;
72         status = smb_raw_lock(cli->tree, &io);
73         CHECK_STATUS(status, NT_STATUS_OK);
74         cli->session->pid++;
75         status = smb_raw_lock(cli->tree, &io);
76         CHECK_STATUS(status, NT_STATUS_OK);
77         cli->session->pid--;
78         io.lock.level = RAW_LOCK_UNLOCK;
79         status = smb_raw_lock(cli->tree, &io);
80         CHECK_STATUS(status, NT_STATUS_OK);
81
82         printf("Trying 0/1 lock\n");
83         io.lock.level = RAW_LOCK_LOCK;
84         io.lock.in.file.fnum = fnum;
85         io.lock.in.count = 1;
86         io.lock.in.offset = 0;
87         status = smb_raw_lock(cli->tree, &io);
88         CHECK_STATUS(status, NT_STATUS_OK);
89         cli->session->pid++;
90         status = smb_raw_lock(cli->tree, &io);
91         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
92         cli->session->pid--;
93         io.lock.level = RAW_LOCK_UNLOCK;
94         status = smb_raw_lock(cli->tree, &io);
95         CHECK_STATUS(status, NT_STATUS_OK);
96         io.lock.level = RAW_LOCK_UNLOCK;
97         status = smb_raw_lock(cli->tree, &io);
98         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
99
100         printf("Trying 0xEEFFFFFF lock\n");
101         io.lock.level = RAW_LOCK_LOCK;
102         io.lock.in.file.fnum = fnum;
103         io.lock.in.count = 4000;
104         io.lock.in.offset = 0xEEFFFFFF;
105         status = smb_raw_lock(cli->tree, &io);
106         CHECK_STATUS(status, NT_STATUS_OK);
107         cli->session->pid++;
108         status = smb_raw_lock(cli->tree, &io);
109         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
110         cli->session->pid--;
111         io.lock.level = RAW_LOCK_UNLOCK;
112         status = smb_raw_lock(cli->tree, &io);
113         CHECK_STATUS(status, NT_STATUS_OK);
114         io.lock.level = RAW_LOCK_UNLOCK;
115         status = smb_raw_lock(cli->tree, &io);
116         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
117
118         printf("Trying 0xEF000000 lock\n");
119         io.lock.level = RAW_LOCK_LOCK;
120         io.lock.in.file.fnum = fnum;
121         io.lock.in.count = 4000;
122         io.lock.in.offset = 0xEEFFFFFF;
123         status = smb_raw_lock(cli->tree, &io);
124         CHECK_STATUS(status, NT_STATUS_OK);
125         cli->session->pid++;
126         status = smb_raw_lock(cli->tree, &io);
127         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
128         cli->session->pid--;
129         io.lock.level = RAW_LOCK_UNLOCK;
130         status = smb_raw_lock(cli->tree, &io);
131         CHECK_STATUS(status, NT_STATUS_OK);
132         io.lock.level = RAW_LOCK_UNLOCK;
133         status = smb_raw_lock(cli->tree, &io);
134         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
135
136         printf("Trying max lock\n");
137         io.lock.level = RAW_LOCK_LOCK;
138         io.lock.in.file.fnum = fnum;
139         io.lock.in.count = 4000;
140         io.lock.in.offset = 0xEF000000;
141         status = smb_raw_lock(cli->tree, &io);
142         CHECK_STATUS(status, NT_STATUS_OK);
143         cli->session->pid++;
144         status = smb_raw_lock(cli->tree, &io);
145         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
146         cli->session->pid--;
147         io.lock.level = RAW_LOCK_UNLOCK;
148         status = smb_raw_lock(cli->tree, &io);
149         CHECK_STATUS(status, NT_STATUS_OK);
150         io.lock.level = RAW_LOCK_UNLOCK;
151         status = smb_raw_lock(cli->tree, &io);
152         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
153
154         printf("Trying wrong pid unlock\n");
155         io.lock.level = RAW_LOCK_LOCK;
156         io.lock.in.file.fnum = fnum;
157         io.lock.in.count = 4002;
158         io.lock.in.offset = 10001;
159         status = smb_raw_lock(cli->tree, &io);
160         CHECK_STATUS(status, NT_STATUS_OK);
161         cli->session->pid++;
162         io.lock.level = RAW_LOCK_UNLOCK;
163         status = smb_raw_lock(cli->tree, &io);
164         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
165         cli->session->pid--;
166         status = smb_raw_lock(cli->tree, &io);
167         CHECK_STATUS(status, NT_STATUS_OK);
168
169 done:
170         smbcli_close(cli->tree, fnum);
171         smb_raw_exit(cli->session);
172         smbcli_deltree(cli->tree, BASEDIR);
173         return ret;
174 }
175
176
177 /*
178   test locking&X ops
179 */
180 static BOOL test_lockx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
181 {
182         union smb_lock io;
183         struct smb_lock_entry lock[1];
184         NTSTATUS status;
185         BOOL ret = True;
186         int fnum;
187         const char *fname = BASEDIR "\\test.txt";
188
189         if (!torture_setup_dir(cli, BASEDIR)) {
190                 return False;
191         }
192
193         printf("Testing RAW_LOCK_LOCKX\n");
194         io.generic.level = RAW_LOCK_LOCKX;
195         
196         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
197         if (fnum == -1) {
198                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
199                 ret = False;
200                 goto done;
201         }
202
203         io.lockx.level = RAW_LOCK_LOCKX;
204         io.lockx.in.file.fnum = fnum;
205         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
206         io.lockx.in.timeout = 0;
207         io.lockx.in.ulock_cnt = 0;
208         io.lockx.in.lock_cnt = 1;
209         lock[0].pid = cli->session->pid;
210         lock[0].offset = 10;
211         lock[0].count = 1;
212         io.lockx.in.locks = &lock[0];
213         status = smb_raw_lock(cli->tree, &io);
214         CHECK_STATUS(status, NT_STATUS_OK);
215
216
217         printf("Trying 0xEEFFFFFF lock\n");
218         io.lockx.in.ulock_cnt = 0;
219         io.lockx.in.lock_cnt = 1;
220         lock[0].count = 4000;
221         lock[0].offset = 0xEEFFFFFF;
222         status = smb_raw_lock(cli->tree, &io);
223         CHECK_STATUS(status, NT_STATUS_OK);
224         lock[0].pid++;
225         status = smb_raw_lock(cli->tree, &io);
226         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
227         lock[0].pid--;
228         io.lockx.in.ulock_cnt = 1;
229         io.lockx.in.lock_cnt = 0;
230         status = smb_raw_lock(cli->tree, &io);
231         CHECK_STATUS(status, NT_STATUS_OK);
232         status = smb_raw_lock(cli->tree, &io);
233         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
234
235         printf("Trying 0xEF000000 lock\n");
236         io.lockx.in.ulock_cnt = 0;
237         io.lockx.in.lock_cnt = 1;
238         lock[0].count = 4000;
239         lock[0].offset = 0xEF000000;
240         status = smb_raw_lock(cli->tree, &io);
241         CHECK_STATUS(status, NT_STATUS_OK);
242         lock[0].pid++;
243         status = smb_raw_lock(cli->tree, &io);
244         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
245         lock[0].pid--;
246         io.lockx.in.ulock_cnt = 1;
247         io.lockx.in.lock_cnt = 0;
248         status = smb_raw_lock(cli->tree, &io);
249         CHECK_STATUS(status, NT_STATUS_OK);
250         status = smb_raw_lock(cli->tree, &io);
251         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
252
253         printf("Trying zero lock\n");
254         io.lockx.in.ulock_cnt = 0;
255         io.lockx.in.lock_cnt = 1;
256         lock[0].count = 0;
257         lock[0].offset = ~0;
258         status = smb_raw_lock(cli->tree, &io);
259         CHECK_STATUS(status, NT_STATUS_OK);
260         lock[0].pid++;
261         status = smb_raw_lock(cli->tree, &io);
262         CHECK_STATUS(status, NT_STATUS_OK);
263         lock[0].pid--;
264         io.lockx.in.ulock_cnt = 1;
265         io.lockx.in.lock_cnt = 0;
266         status = smb_raw_lock(cli->tree, &io);
267         CHECK_STATUS(status, NT_STATUS_OK);
268         status = smb_raw_lock(cli->tree, &io);
269         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
270
271         printf("Trying max lock\n");
272         io.lockx.in.ulock_cnt = 0;
273         io.lockx.in.lock_cnt = 1;
274         lock[0].count = 0;
275         lock[0].offset = ~0;
276         status = smb_raw_lock(cli->tree, &io);
277         CHECK_STATUS(status, NT_STATUS_OK);
278         lock[0].pid++;
279         status = smb_raw_lock(cli->tree, &io);
280         CHECK_STATUS(status, NT_STATUS_OK);
281         lock[0].pid--;
282         io.lockx.in.ulock_cnt = 1;
283         io.lockx.in.lock_cnt = 0;
284         status = smb_raw_lock(cli->tree, &io);
285         CHECK_STATUS(status, NT_STATUS_OK);
286         status = smb_raw_lock(cli->tree, &io);
287         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
288
289         printf("Trying 2^63\n");
290         io.lockx.in.ulock_cnt = 0;
291         io.lockx.in.lock_cnt = 1;
292         lock[0].count = 1;
293         lock[0].offset = 1;
294         lock[0].offset <<= 63;
295         status = smb_raw_lock(cli->tree, &io);
296         CHECK_STATUS(status, NT_STATUS_OK);
297         lock[0].pid++;
298         status = smb_raw_lock(cli->tree, &io);
299         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
300         lock[0].pid--;
301         io.lockx.in.ulock_cnt = 1;
302         io.lockx.in.lock_cnt = 0;
303         status = smb_raw_lock(cli->tree, &io);
304         CHECK_STATUS(status, NT_STATUS_OK);
305         status = smb_raw_lock(cli->tree, &io);
306         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
307
308         printf("Trying 2^63 - 1\n");
309         io.lockx.in.ulock_cnt = 0;
310         io.lockx.in.lock_cnt = 1;
311         lock[0].count = 1;
312         lock[0].offset = 1;
313         lock[0].offset <<= 63;
314         lock[0].offset--;
315         status = smb_raw_lock(cli->tree, &io);
316         CHECK_STATUS(status, NT_STATUS_OK);
317         lock[0].pid++;
318         status = smb_raw_lock(cli->tree, &io);
319         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
320         lock[0].pid--;
321         io.lockx.in.ulock_cnt = 1;
322         io.lockx.in.lock_cnt = 0;
323         status = smb_raw_lock(cli->tree, &io);
324         CHECK_STATUS(status, NT_STATUS_OK);
325         status = smb_raw_lock(cli->tree, &io);
326         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
327
328         printf("Trying max lock 2\n");
329         io.lockx.in.ulock_cnt = 0;
330         io.lockx.in.lock_cnt = 1;
331         lock[0].count = 1;
332         lock[0].offset = ~0;
333         status = smb_raw_lock(cli->tree, &io);
334         CHECK_STATUS(status, NT_STATUS_OK);
335         lock[0].pid++;
336         lock[0].count = 2;
337         status = smb_raw_lock(cli->tree, &io);
338         CHECK_STATUS(status, NT_STATUS_OK);
339         lock[0].pid--;
340         io.lockx.in.ulock_cnt = 1;
341         io.lockx.in.lock_cnt = 0;
342         lock[0].count = 1;
343         status = smb_raw_lock(cli->tree, &io);
344         CHECK_STATUS(status, NT_STATUS_OK);
345         status = smb_raw_lock(cli->tree, &io);
346         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
347
348 done:
349         smbcli_close(cli->tree, fnum);
350         smb_raw_exit(cli->session);
351         smbcli_deltree(cli->tree, BASEDIR);
352         return ret;
353 }
354
355
356 /*
357   test high pid
358 */
359 static BOOL test_pidhigh(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
360 {
361         union smb_lock io;
362         struct smb_lock_entry lock[1];
363         NTSTATUS status;
364         BOOL ret = True;
365         int fnum;
366         const char *fname = BASEDIR "\\test.txt";
367         uint8_t c = 1;
368
369         if (!torture_setup_dir(cli, BASEDIR)) {
370                 return False;
371         }
372
373         printf("Testing high pid\n");
374         io.generic.level = RAW_LOCK_LOCKX;
375
376         cli->session->pid = 1;
377         
378         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
379         if (fnum == -1) {
380                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
381                 ret = False;
382                 goto done;
383         }
384
385         if (smbcli_write(cli->tree, fnum, 0, &c, 0, 1) != 1) {
386                 printf("Failed to write 1 byte - %s\n", smbcli_errstr(cli->tree));
387                 ret = False;
388                 goto done;
389         }
390
391         io.lockx.level = RAW_LOCK_LOCKX;
392         io.lockx.in.file.fnum = fnum;
393         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
394         io.lockx.in.timeout = 0;
395         io.lockx.in.ulock_cnt = 0;
396         io.lockx.in.lock_cnt = 1;
397         lock[0].pid = cli->session->pid;
398         lock[0].offset = 0;
399         lock[0].count = 0xFFFFFFFF;
400         io.lockx.in.locks = &lock[0];
401         status = smb_raw_lock(cli->tree, &io);
402         CHECK_STATUS(status, NT_STATUS_OK);
403
404         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
405                 printf("Failed to read 1 byte - %s\n", smbcli_errstr(cli->tree));
406                 ret = False;
407                 goto done;
408         }
409
410         cli->session->pid |= 0x10000;
411
412         cli->session->pid = 2;
413
414         if (smbcli_read(cli->tree, fnum, &c, 0, 1) == 1) {
415                 printf("pid is incorrect handled for read with lock!\n");
416                 ret = False;
417                 goto done;
418         }
419
420         cli->session->pid = 0x10001;
421
422         if (smbcli_read(cli->tree, fnum, &c, 0, 1) != 1) {
423                 printf("High pid is used on this server!\n");
424                 ret = False;
425         } else {
426                 printf("High pid is not used on this server (correct)\n");
427         }
428
429 done:
430         smbcli_close(cli->tree, fnum);
431         smb_raw_exit(cli->session);
432         smbcli_deltree(cli->tree, BASEDIR);
433         return ret;
434 }
435
436
437 /*
438   test locking&X async operation
439 */
440 static BOOL test_async(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
441 {
442         struct smbcli_session *session;
443         struct smb_composite_sesssetup setup;
444         struct smbcli_tree *tree;
445         union smb_tcon tcon;
446         const char *host, *share;
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.in.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         printf("testing cancel by close\n");
560         io.lockx.in.ulock_cnt = 0;
561         io.lockx.in.lock_cnt = 1;
562         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
563         io.lockx.in.timeout = 0;
564         status = smb_raw_lock(cli->tree, &io);
565         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
566
567         t = time(NULL);
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         status = smbcli_close(cli->tree, fnum);
577         CHECK_STATUS(status, NT_STATUS_OK);
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 close was not immediate (%s)\n", __location__);
584                 ret = False;
585                 goto done;
586         }
587
588         printf("create a new sessions\n");
589         session = smbcli_session_init(cli->transport, mem_ctx, False);
590         setup.in.sesskey = cli->transport->negotiate.sesskey;
591         setup.in.capabilities = cli->transport->negotiate.capabilities;
592         setup.in.workgroup = lp_workgroup();
593         setup.in.credentials = cmdline_credentials;
594         status = smb_composite_sesssetup(session, &setup);
595         CHECK_STATUS(status, NT_STATUS_OK);
596         session->vuid = setup.out.vuid;
597
598         printf("create new tree context\n");
599         share = lp_parm_string(-1, "torture", "share");
600         host  = lp_parm_string(-1, "torture", "host");
601         tree = smbcli_tree_init(session, mem_ctx, False);
602         tcon.generic.level = RAW_TCON_TCONX;
603         tcon.tconx.in.flags = 0;
604         tcon.tconx.in.password = data_blob(NULL, 0);
605         tcon.tconx.in.path = talloc_asprintf(mem_ctx, "\\\\%s\\%s", host, share);
606         tcon.tconx.in.device = "A:";
607         status = smb_raw_tcon(tree, mem_ctx, &tcon);
608         CHECK_STATUS(status, NT_STATUS_OK);
609         tree->tid = tcon.tconx.out.tid;
610
611         printf("testing cancel by exit\n");
612         fname = BASEDIR "\\test_exit.txt";
613         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
614         if (fnum == -1) {
615                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
616                 ret = False;
617                 goto done;
618         }
619         io.lockx.level = RAW_LOCK_LOCKX;
620         io.lockx.in.file.fnum = fnum;
621         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
622         io.lockx.in.timeout = 0;
623         io.lockx.in.ulock_cnt = 0;
624         io.lockx.in.lock_cnt = 1;
625         lock[0].pid = session->pid;
626         lock[0].offset = 100;
627         lock[0].count = 10;
628         io.lockx.in.locks = &lock[0];
629         status = smb_raw_lock(tree, &io);
630         CHECK_STATUS(status, NT_STATUS_OK);
631
632         io.lockx.in.ulock_cnt = 0;
633         io.lockx.in.lock_cnt = 1;
634         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
635         io.lockx.in.timeout = 0;
636         status = smb_raw_lock(tree, &io);
637         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
638
639         io.lockx.in.timeout = 10000;
640         t = time(NULL);
641         req = smb_raw_lock_send(tree, &io);
642         if (req == NULL) {
643                 printf("Failed to setup timed lock (%s)\n", __location__);
644                 ret = False;
645                 goto done;
646         }
647
648         status = smb_raw_exit(session);
649         CHECK_STATUS(status, NT_STATUS_OK);
650
651         status = smbcli_request_simple_recv(req);
652         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
653
654         if (time(NULL) > t+2) {
655                 printf("lock cancel by exit was not immediate (%s)\n", __location__);
656                 ret = False;
657                 goto done;
658         }
659
660         printf("testing cancel by ulogoff\n");
661         fname = BASEDIR "\\test_ulogoff.txt";
662         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
663         if (fnum == -1) {
664                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
665                 ret = False;
666                 goto done;
667         }
668         io.lockx.level = RAW_LOCK_LOCKX;
669         io.lockx.in.file.fnum = fnum;
670         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
671         io.lockx.in.timeout = 0;
672         io.lockx.in.ulock_cnt = 0;
673         io.lockx.in.lock_cnt = 1;
674         lock[0].pid = session->pid;
675         lock[0].offset = 100;
676         lock[0].count = 10;
677         io.lockx.in.locks = &lock[0];
678         status = smb_raw_lock(tree, &io);
679         CHECK_STATUS(status, NT_STATUS_OK);
680
681         io.lockx.in.ulock_cnt = 0;
682         io.lockx.in.lock_cnt = 1;
683         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
684         io.lockx.in.timeout = 0;
685         status = smb_raw_lock(tree, &io);
686         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
687
688         io.lockx.in.timeout = 10000;
689         t = time(NULL);
690         req = smb_raw_lock_send(tree, &io);
691         if (req == NULL) {
692                 printf("Failed to setup timed lock (%s)\n", __location__);
693                 ret = False;
694                 goto done;
695         }
696
697         status = smb_raw_ulogoff(session);
698         CHECK_STATUS(status, NT_STATUS_OK);
699
700         status = smbcli_request_simple_recv(req);
701         if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
702                 printf("lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
703                         nt_errstr(status));
704                 smb_tree_disconnect(tree);
705                 smb_raw_exit(session);
706                 goto done;
707         }
708         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
709
710         if (time(NULL) > t+2) {
711                 printf("lock cancel by ulogoff was not immediate (%s)\n", __location__);
712                 ret = False;
713                 goto done;
714         }
715
716         printf("testing cancel by tdis\n");
717         tree->session = cli->session;
718
719         fname = BASEDIR "\\test_tdis.txt";
720         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
721         if (fnum == -1) {
722                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
723                 ret = False;
724                 goto done;
725         }
726         io.lockx.level = RAW_LOCK_LOCKX;
727         io.lockx.in.file.fnum = fnum;
728         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
729         io.lockx.in.timeout = 0;
730         io.lockx.in.ulock_cnt = 0;
731         io.lockx.in.lock_cnt = 1;
732         lock[0].pid = cli->session->pid;
733         lock[0].offset = 100;
734         lock[0].count = 10;
735         io.lockx.in.locks = &lock[0];
736         status = smb_raw_lock(tree, &io);
737         CHECK_STATUS(status, NT_STATUS_OK);
738
739         status = smb_raw_lock(tree, &io);
740         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
741
742         io.lockx.in.timeout = 10000;
743         t = time(NULL);
744         req = smb_raw_lock_send(tree, &io);
745         if (req == NULL) {
746                 printf("Failed to setup timed lock (%s)\n", __location__);
747                 ret = False;
748                 goto done;
749         }
750
751         status = smb_tree_disconnect(tree);
752         CHECK_STATUS(status, NT_STATUS_OK);
753
754         status = smbcli_request_simple_recv(req);
755         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
756
757         if (time(NULL) > t+2) {
758                 printf("lock cancel by tdis was not immediate (%s)\n", __location__);
759                 ret = False;
760                 goto done;
761         }
762
763 done:
764         smb_raw_exit(cli->session);
765         smbcli_deltree(cli->tree, BASEDIR);
766         return ret;
767 }
768
769 /*
770   test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
771 */
772 static BOOL test_errorcode(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
773 {
774         union smb_lock io;
775         union smb_open op;
776         struct smb_lock_entry lock[2];
777         NTSTATUS status;
778         BOOL ret = True;
779         int fnum, fnum2;
780         const char *fname;
781         struct smbcli_request *req;
782         time_t start;
783         int t;
784
785         if (!torture_setup_dir(cli, BASEDIR)) {
786                 return False;
787         }
788
789         printf("Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
790
791         printf("testing with timeout = 0\n");
792         fname = BASEDIR "\\test0.txt";
793         t = 0;
794
795         /*
796          * the first run is with t = 0,
797          * the second with t > 0 (=1)
798          */
799 next_run:
800         /* 
801          * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
802          * this demonstrates that the cache is per fnum
803          */
804         op.openx.level = RAW_OPEN_OPENX;
805         op.openx.in.fname = fname;
806         op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
807         op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
808         op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
809         op.openx.in.search_attrs = 0;
810         op.openx.in.file_attrs = 0;
811         op.openx.in.write_time = 0;
812         op.openx.in.size = 0;
813         op.openx.in.timeout = 0;
814
815         status = smb_raw_open(cli->tree, mem_ctx, &op);
816         CHECK_STATUS(status, NT_STATUS_OK);
817         fnum = op.openx.out.file.fnum;
818
819         status = smb_raw_open(cli->tree, mem_ctx, &op);
820         CHECK_STATUS(status, NT_STATUS_OK);
821         fnum2 = op.openx.out.file.fnum;
822
823         io.lockx.level = RAW_LOCK_LOCKX;
824         io.lockx.in.file.fnum = fnum;
825         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
826         io.lockx.in.timeout = t;
827         io.lockx.in.ulock_cnt = 0;
828         io.lockx.in.lock_cnt = 1;
829         lock[0].pid = cli->session->pid;
830         lock[0].offset = 100;
831         lock[0].count = 10;
832         io.lockx.in.locks = &lock[0];
833         status = smb_raw_lock(cli->tree, &io);
834         CHECK_STATUS(status, NT_STATUS_OK);
835
836         /*
837          * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
838          * this also demonstrates that the error code cache is per file handle
839          * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
840          */
841         io.lockx.in.file.fnum = fnum2;
842         status = smb_raw_lock(cli->tree, &io);
843         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
844
845         io.lockx.in.file.fnum = fnum;
846         status = smb_raw_lock(cli->tree, &io);
847         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
848
849         /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
850         io.lockx.in.file.fnum = fnum;
851         status = smb_raw_lock(cli->tree, &io);
852         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
853
854         io.lockx.in.file.fnum = fnum2;
855         status = smb_raw_lock(cli->tree, &io);
856         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
857
858         io.lockx.in.file.fnum = fnum;
859         status = smb_raw_lock(cli->tree, &io);
860         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
861
862         io.lockx.in.file.fnum = fnum2;
863         status = smb_raw_lock(cli->tree, &io);
864         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
865
866         /* demonstrate that the smbpid doesn't matter */
867         lock[0].pid++;
868         io.lockx.in.file.fnum = fnum;
869         status = smb_raw_lock(cli->tree, &io);
870         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
871
872         io.lockx.in.file.fnum = fnum2;
873         status = smb_raw_lock(cli->tree, &io);
874         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
875         lock[0].pid--;
876
877         /* 
878          * demonstrate the a successful lock with count = 0 and the same offset,
879          * doesn't reset the error cache
880          */
881         lock[0].offset = 100;
882         lock[0].count = 0;
883         io.lockx.in.file.fnum = fnum;
884         status = smb_raw_lock(cli->tree, &io);
885         CHECK_STATUS(status, NT_STATUS_OK);
886
887         io.lockx.in.file.fnum = fnum2;
888         status = smb_raw_lock(cli->tree, &io);
889         CHECK_STATUS(status, NT_STATUS_OK);
890
891         lock[0].offset = 100;
892         lock[0].count = 10;
893         io.lockx.in.file.fnum = fnum;
894         status = smb_raw_lock(cli->tree, &io);
895         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
896
897         io.lockx.in.file.fnum = fnum2;
898         status = smb_raw_lock(cli->tree, &io);
899         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
900
901         /* 
902          * demonstrate the a successful lock with count = 0 and outside the locked range,
903          * doesn't reset the error cache
904          */
905         lock[0].offset = 110;
906         lock[0].count = 0;
907         io.lockx.in.file.fnum = fnum;
908         status = smb_raw_lock(cli->tree, &io);
909         CHECK_STATUS(status, NT_STATUS_OK);
910
911         io.lockx.in.file.fnum = fnum2;
912         status = smb_raw_lock(cli->tree, &io);
913         CHECK_STATUS(status, NT_STATUS_OK);
914
915         lock[0].offset = 100;
916         lock[0].count = 10;
917         io.lockx.in.file.fnum = fnum;
918         status = smb_raw_lock(cli->tree, &io);
919         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
920
921         io.lockx.in.file.fnum = fnum2;
922         status = smb_raw_lock(cli->tree, &io);
923         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
924
925         lock[0].offset = 99;
926         lock[0].count = 0;
927         io.lockx.in.file.fnum = fnum;
928         status = smb_raw_lock(cli->tree, &io);
929         CHECK_STATUS(status, NT_STATUS_OK);
930
931         io.lockx.in.file.fnum = fnum2;
932         status = smb_raw_lock(cli->tree, &io);
933         CHECK_STATUS(status, NT_STATUS_OK);
934
935         lock[0].offset = 100;
936         lock[0].count = 10;
937         io.lockx.in.file.fnum = fnum;
938         status = smb_raw_lock(cli->tree, &io);
939         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
940
941         io.lockx.in.file.fnum = fnum2;
942         status = smb_raw_lock(cli->tree, &io);
943         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
944
945         /* demonstrate that a changing count doesn't reset the error cache */
946         lock[0].offset = 100;
947         lock[0].count = 5;
948         io.lockx.in.file.fnum = fnum;
949         status = smb_raw_lock(cli->tree, &io);
950         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
951
952         io.lockx.in.file.fnum = fnum2;
953         status = smb_raw_lock(cli->tree, &io);
954         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
955
956         lock[0].offset = 100;
957         lock[0].count = 15;
958         io.lockx.in.file.fnum = fnum;
959         status = smb_raw_lock(cli->tree, &io);
960         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
961
962         io.lockx.in.file.fnum = fnum2;
963         status = smb_raw_lock(cli->tree, &io);
964         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
965
966         /* 
967          * demonstrate the a lock with count = 0 and inside the locked range,
968          * fails and resets the error cache
969          */
970         lock[0].offset = 101;
971         lock[0].count = 0;
972         io.lockx.in.file.fnum = fnum;
973         status = smb_raw_lock(cli->tree, &io);
974         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
975         status = smb_raw_lock(cli->tree, &io);
976         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
977
978         io.lockx.in.file.fnum = fnum2;
979         status = smb_raw_lock(cli->tree, &io);
980         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
981         status = smb_raw_lock(cli->tree, &io);
982         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
983
984         lock[0].offset = 100;
985         lock[0].count = 10;
986         io.lockx.in.file.fnum = fnum;
987         status = smb_raw_lock(cli->tree, &io);
988         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
989         status = smb_raw_lock(cli->tree, &io);
990         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
991
992         io.lockx.in.file.fnum = fnum2;
993         status = smb_raw_lock(cli->tree, &io);
994         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
995         status = smb_raw_lock(cli->tree, &io);
996         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
997
998         /* demonstrate the a changing offset, resets the error cache */
999         lock[0].offset = 105;
1000         lock[0].count = 10;
1001         io.lockx.in.file.fnum = fnum;
1002         status = smb_raw_lock(cli->tree, &io);
1003         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1004         status = smb_raw_lock(cli->tree, &io);
1005         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1006
1007         io.lockx.in.file.fnum = fnum2;
1008         status = smb_raw_lock(cli->tree, &io);
1009         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1010         status = smb_raw_lock(cli->tree, &io);
1011         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1012
1013         lock[0].offset = 100;
1014         lock[0].count = 10;
1015         io.lockx.in.file.fnum = fnum;
1016         status = smb_raw_lock(cli->tree, &io);
1017         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1018         status = smb_raw_lock(cli->tree, &io);
1019         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1020
1021         io.lockx.in.file.fnum = fnum2;
1022         status = smb_raw_lock(cli->tree, &io);
1023         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1024         status = smb_raw_lock(cli->tree, &io);
1025         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1026
1027         lock[0].offset = 95;
1028         lock[0].count = 9;
1029         io.lockx.in.file.fnum = fnum;
1030         status = smb_raw_lock(cli->tree, &io);
1031         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1032         status = smb_raw_lock(cli->tree, &io);
1033         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1034
1035         io.lockx.in.file.fnum = fnum2;
1036         status = smb_raw_lock(cli->tree, &io);
1037         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1038         status = smb_raw_lock(cli->tree, &io);
1039         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1040
1041         lock[0].offset = 100;
1042         lock[0].count = 10;
1043         io.lockx.in.file.fnum = fnum;
1044         status = smb_raw_lock(cli->tree, &io);
1045         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1046         status = smb_raw_lock(cli->tree, &io);
1047         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1048
1049         io.lockx.in.file.fnum = fnum2;
1050         status = smb_raw_lock(cli->tree, &io);
1051         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1052         status = smb_raw_lock(cli->tree, &io);
1053         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1054
1055         /* 
1056          * demonstrate the a successful lock in a different range, 
1057          * doesn't reset the cache, the failing lock on the 2nd handle
1058          * resets the resets the cache
1059          */
1060         lock[0].offset = 120;
1061         lock[0].count = 15;
1062         io.lockx.in.file.fnum = fnum;
1063         status = smb_raw_lock(cli->tree, &io);
1064         CHECK_STATUS(status, NT_STATUS_OK);
1065
1066         io.lockx.in.file.fnum = fnum2;
1067         status = smb_raw_lock(cli->tree, &io);
1068         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1069
1070         lock[0].offset = 100;
1071         lock[0].count = 10;
1072         io.lockx.in.file.fnum = fnum;
1073         status = smb_raw_lock(cli->tree, &io);
1074         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1075         status = smb_raw_lock(cli->tree, &io);
1076         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1077
1078         io.lockx.in.file.fnum = fnum2;
1079         status = smb_raw_lock(cli->tree, &io);
1080         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1081         status = smb_raw_lock(cli->tree, &io);
1082         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1083
1084         /* end of the loop */
1085         if (t == 0) {
1086                 smb_raw_exit(cli->session);
1087                 printf("testing with timeout > 0 (=1)\n");
1088                 fname = BASEDIR "\\test1.txt";
1089                 t = 1;
1090                 goto next_run;
1091         }
1092
1093         /*
1094          * the following 3 test sections demonstrate that
1095          * the cache is only set when the error is reported
1096          * to the client (after the timeout went by)
1097          */
1098         smb_raw_exit(cli->session);
1099         printf("testing a conflict while a lock is pending\n");
1100         fname = BASEDIR "\\test2.txt";
1101         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1102         if (fnum == -1) {
1103                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1104                 ret = False;
1105                 goto done;
1106         }
1107         io.lockx.level = RAW_LOCK_LOCKX;
1108         io.lockx.in.file.fnum = fnum;
1109         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1110         io.lockx.in.timeout = 0;
1111         io.lockx.in.ulock_cnt = 0;
1112         io.lockx.in.lock_cnt = 1;
1113         lock[0].pid = cli->session->pid;
1114         lock[0].offset = 100;
1115         lock[0].count = 10;
1116         io.lockx.in.locks = &lock[0];
1117         status = smb_raw_lock(cli->tree, &io);
1118         CHECK_STATUS(status, NT_STATUS_OK);
1119
1120         start = time(NULL);
1121         io.lockx.in.timeout = 1000;
1122         req = smb_raw_lock_send(cli->tree, &io);
1123         if (req == NULL) {
1124                 printf("Failed to setup timed lock (%s)\n", __location__);
1125                 ret = False;
1126                 goto done;
1127         }
1128
1129         io.lockx.in.timeout = 0;
1130         lock[0].offset = 105;
1131         lock[0].count = 10;
1132         status = smb_raw_lock(cli->tree, &io);
1133         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1134
1135         status = smbcli_request_simple_recv(req);
1136         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1137
1138         status = smb_raw_lock(cli->tree, &io);
1139         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1140
1141         if (time(NULL) < start+1) {
1142                 printf("lock comes back to early (%s)\n", __location__);
1143                 ret = False;
1144                 goto done;
1145         }
1146
1147         smbcli_close(cli->tree, fnum);
1148         fname = BASEDIR "\\test3.txt";
1149         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1150         if (fnum == -1) {
1151                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1152                 ret = False;
1153                 goto done;
1154         }
1155         io.lockx.level = RAW_LOCK_LOCKX;
1156         io.lockx.in.file.fnum = fnum;
1157         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1158         io.lockx.in.timeout = 0;
1159         io.lockx.in.ulock_cnt = 0;
1160         io.lockx.in.lock_cnt = 1;
1161         lock[0].pid = cli->session->pid;
1162         lock[0].offset = 100;
1163         lock[0].count = 10;
1164         io.lockx.in.locks = &lock[0];
1165         status = smb_raw_lock(cli->tree, &io);
1166         CHECK_STATUS(status, NT_STATUS_OK);
1167
1168         start = time(NULL);
1169         io.lockx.in.timeout = 1000;
1170         req = smb_raw_lock_send(cli->tree, &io);
1171         if (req == NULL) {
1172                 printf("Failed to setup timed lock (%s)\n", __location__);
1173                 ret = False;
1174                 goto done;
1175         }
1176
1177         io.lockx.in.timeout = 0;
1178         lock[0].offset = 105;
1179         lock[0].count = 10;
1180         status = smb_raw_lock(cli->tree, &io);
1181         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1182
1183         status = smbcli_request_simple_recv(req);
1184         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1185
1186         lock[0].offset = 100;
1187         lock[0].count = 10;
1188         status = smb_raw_lock(cli->tree, &io);
1189         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1190
1191         if (time(NULL) < start+1) {
1192                 printf("lock comes back to early (%s)\n", __location__);
1193                 ret = False;
1194                 goto done;
1195         }
1196
1197         smbcli_close(cli->tree, fnum);
1198         fname = BASEDIR "\\test4.txt";
1199         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1200         if (fnum == -1) {
1201                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1202                 ret = False;
1203                 goto done;
1204         }
1205         io.lockx.level = RAW_LOCK_LOCKX;
1206         io.lockx.in.file.fnum = fnum;
1207         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1208         io.lockx.in.timeout = 0;
1209         io.lockx.in.ulock_cnt = 0;
1210         io.lockx.in.lock_cnt = 1;
1211         lock[0].pid = cli->session->pid;
1212         lock[0].offset = 100;
1213         lock[0].count = 10;
1214         io.lockx.in.locks = &lock[0];
1215         status = smb_raw_lock(cli->tree, &io);
1216         CHECK_STATUS(status, NT_STATUS_OK);
1217
1218         start = time(NULL);
1219         io.lockx.in.timeout = 1000;
1220         req = smb_raw_lock_send(cli->tree, &io);
1221         if (req == NULL) {
1222                 printf("Failed to setup timed lock (%s)\n", __location__);
1223                 ret = False;
1224                 goto done;
1225         }
1226
1227         io.lockx.in.timeout = 0;
1228         status = smb_raw_lock(cli->tree, &io);
1229         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1230
1231         status = smbcli_request_simple_recv(req);
1232         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1233
1234         status = smb_raw_lock(cli->tree, &io);
1235         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1236
1237         if (time(NULL) < start+1) {
1238                 printf("lock comes back to early (%s)\n", __location__);
1239                 ret = False;
1240                 goto done;
1241         }
1242
1243 done:
1244         smb_raw_exit(cli->session);
1245         smbcli_deltree(cli->tree, BASEDIR);
1246         return ret;
1247 }
1248
1249
1250 /*
1251   test LOCKING_ANDX_CHANGE_LOCKTYPE
1252 */
1253 static BOOL test_changetype(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
1254 {
1255         union smb_lock io;
1256         struct smb_lock_entry lock[2];
1257         NTSTATUS status;
1258         BOOL ret = True;
1259         int fnum;
1260         uint8_t c = 0;
1261         const char *fname = BASEDIR "\\test.txt";
1262
1263         if (!torture_setup_dir(cli, BASEDIR)) {
1264                 return False;
1265         }
1266
1267         printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1268         io.generic.level = RAW_LOCK_LOCKX;
1269         
1270         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1271         if (fnum == -1) {
1272                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1273                 ret = False;
1274                 goto done;
1275         }
1276
1277         io.lockx.level = RAW_LOCK_LOCKX;
1278         io.lockx.in.file.fnum = fnum;
1279         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1280         io.lockx.in.timeout = 0;
1281         io.lockx.in.ulock_cnt = 0;
1282         io.lockx.in.lock_cnt = 1;
1283         lock[0].pid = cli->session->pid;
1284         lock[0].offset = 100;
1285         lock[0].count = 10;
1286         io.lockx.in.locks = &lock[0];
1287         status = smb_raw_lock(cli->tree, &io);
1288         CHECK_STATUS(status, NT_STATUS_OK);
1289
1290         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1291                 printf("allowed write on read locked region (%s)\n", __location__);
1292                 ret = False;
1293                 goto done;
1294         }
1295
1296         /* windows server don't seem to support this */
1297         io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1298         status = smb_raw_lock(cli->tree, &io);
1299         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1300
1301         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1302                 printf("allowed write after lock change (%s)\n", __location__);
1303                 ret = False;
1304                 goto done;
1305         }
1306
1307 done:
1308         smbcli_close(cli->tree, fnum);
1309         smb_raw_exit(cli->session);
1310         smbcli_deltree(cli->tree, BASEDIR);
1311         return ret;
1312 }
1313
1314
1315 /* 
1316    basic testing of lock calls
1317 */
1318 BOOL torture_raw_lock(struct torture_context *torture)
1319 {
1320         struct smbcli_state *cli;
1321         BOOL ret = True;
1322         TALLOC_CTX *mem_ctx;
1323
1324         if (!torture_open_connection(&cli, 0)) {
1325                 return False;
1326         }
1327
1328         mem_ctx = talloc_init("torture_raw_lock");
1329
1330         ret &= test_lockx(cli, mem_ctx);
1331         ret &= test_lock(cli, mem_ctx);
1332         ret &= test_pidhigh(cli, mem_ctx);
1333         ret &= test_async(cli, mem_ctx);
1334         ret &= test_errorcode(cli, mem_ctx);
1335         ret &= test_changetype(cli, mem_ctx);
1336
1337         torture_close_connection(cli);
1338         talloc_free(mem_ctx);
1339         return ret;
1340 }