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