Merge branch 'master' of ssh://git.samba.org/data/git/samba
[kai/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         setup.in.gensec_settings = lp_gensec_settings(tctx, tctx->lp_ctx);
602         status = smb_composite_sesssetup(session, &setup);
603         CHECK_STATUS(status, NT_STATUS_OK);
604         session->vuid = setup.out.vuid;
605
606         printf("create new tree context\n");
607         share = torture_setting_string(tctx, "share", NULL);
608         host  = torture_setting_string(tctx, "host", NULL);
609         tree = smbcli_tree_init(session, tctx, false);
610         tcon.generic.level = RAW_TCON_TCONX;
611         tcon.tconx.in.flags = 0;
612         tcon.tconx.in.password = data_blob(NULL, 0);
613         tcon.tconx.in.path = talloc_asprintf(tctx, "\\\\%s\\%s", host, share);
614         tcon.tconx.in.device = "A:";
615         status = smb_raw_tcon(tree, tctx, &tcon);
616         CHECK_STATUS(status, NT_STATUS_OK);
617         tree->tid = tcon.tconx.out.tid;
618
619         printf("testing cancel by exit\n");
620         fname = BASEDIR "\\test_exit.txt";
621         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
622         if (fnum == -1) {
623                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
624                 ret = false;
625                 goto done;
626         }
627         io.lockx.level = RAW_LOCK_LOCKX;
628         io.lockx.in.file.fnum = fnum;
629         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
630         io.lockx.in.timeout = 0;
631         io.lockx.in.ulock_cnt = 0;
632         io.lockx.in.lock_cnt = 1;
633         lock[0].pid = session->pid;
634         lock[0].offset = 100;
635         lock[0].count = 10;
636         io.lockx.in.locks = &lock[0];
637         status = smb_raw_lock(tree, &io);
638         CHECK_STATUS(status, NT_STATUS_OK);
639
640         io.lockx.in.ulock_cnt = 0;
641         io.lockx.in.lock_cnt = 1;
642         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
643         io.lockx.in.timeout = 0;
644         status = smb_raw_lock(tree, &io);
645         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
646
647         io.lockx.in.timeout = 10000;
648         t = time(NULL);
649         req = smb_raw_lock_send(tree, &io);
650         if (req == NULL) {
651                 printf("Failed to setup timed lock (%s)\n", __location__);
652                 ret = false;
653                 goto done;
654         }
655
656         status = smb_raw_exit(session);
657         CHECK_STATUS(status, NT_STATUS_OK);
658
659         status = smbcli_request_simple_recv(req);
660         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
661
662         if (time(NULL) > t+2) {
663                 printf("lock cancel by exit was not immediate (%s)\n", __location__);
664                 ret = false;
665                 goto done;
666         }
667
668         printf("testing cancel by ulogoff\n");
669         fname = BASEDIR "\\test_ulogoff.txt";
670         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
671         if (fnum == -1) {
672                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
673                 ret = false;
674                 goto done;
675         }
676         io.lockx.level = RAW_LOCK_LOCKX;
677         io.lockx.in.file.fnum = fnum;
678         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
679         io.lockx.in.timeout = 0;
680         io.lockx.in.ulock_cnt = 0;
681         io.lockx.in.lock_cnt = 1;
682         lock[0].pid = session->pid;
683         lock[0].offset = 100;
684         lock[0].count = 10;
685         io.lockx.in.locks = &lock[0];
686         status = smb_raw_lock(tree, &io);
687         CHECK_STATUS(status, NT_STATUS_OK);
688
689         io.lockx.in.ulock_cnt = 0;
690         io.lockx.in.lock_cnt = 1;
691         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
692         io.lockx.in.timeout = 0;
693         status = smb_raw_lock(tree, &io);
694         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
695
696         io.lockx.in.timeout = 10000;
697         t = time(NULL);
698         req = smb_raw_lock_send(tree, &io);
699         if (req == NULL) {
700                 printf("Failed to setup timed lock (%s)\n", __location__);
701                 ret = false;
702                 goto done;
703         }
704
705         status = smb_raw_ulogoff(session);
706         CHECK_STATUS(status, NT_STATUS_OK);
707
708         status = smbcli_request_simple_recv(req);
709         if (NT_STATUS_EQUAL(NT_STATUS_FILE_LOCK_CONFLICT, status)) {
710                 printf("lock not canceled by ulogoff - %s (ignored because of vfs_vifs fails it)\n",
711                         nt_errstr(status));
712                 smb_tree_disconnect(tree);
713                 smb_raw_exit(session);
714                 goto done;
715         }
716         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
717
718         if (time(NULL) > t+2) {
719                 printf("lock cancel by ulogoff was not immediate (%s)\n", __location__);
720                 ret = false;
721                 goto done;
722         }
723
724         printf("testing cancel by tdis\n");
725         tree->session = cli->session;
726
727         fname = BASEDIR "\\test_tdis.txt";
728         fnum = smbcli_open(tree, fname, O_RDWR|O_CREAT, DENY_NONE);
729         if (fnum == -1) {
730                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(tree));
731                 ret = false;
732                 goto done;
733         }
734         io.lockx.level = RAW_LOCK_LOCKX;
735         io.lockx.in.file.fnum = fnum;
736         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
737         io.lockx.in.timeout = 0;
738         io.lockx.in.ulock_cnt = 0;
739         io.lockx.in.lock_cnt = 1;
740         lock[0].pid = cli->session->pid;
741         lock[0].offset = 100;
742         lock[0].count = 10;
743         io.lockx.in.locks = &lock[0];
744         status = smb_raw_lock(tree, &io);
745         CHECK_STATUS(status, NT_STATUS_OK);
746
747         status = smb_raw_lock(tree, &io);
748         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
749
750         io.lockx.in.timeout = 10000;
751         t = time(NULL);
752         req = smb_raw_lock_send(tree, &io);
753         if (req == NULL) {
754                 printf("Failed to setup timed lock (%s)\n", __location__);
755                 ret = false;
756                 goto done;
757         }
758
759         status = smb_tree_disconnect(tree);
760         CHECK_STATUS(status, NT_STATUS_OK);
761
762         status = smbcli_request_simple_recv(req);
763         CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
764
765         if (time(NULL) > t+2) {
766                 printf("lock cancel by tdis was not immediate (%s)\n", __location__);
767                 ret = false;
768                 goto done;
769         }
770
771 done:
772         smb_raw_exit(cli->session);
773         smbcli_deltree(cli->tree, BASEDIR);
774         return ret;
775 }
776
777 /*
778   test NT_STATUS_LOCK_NOT_GRANTED vs. NT_STATUS_FILE_LOCK_CONFLICT
779 */
780 static bool test_errorcode(struct torture_context *tctx, 
781                                                    struct smbcli_state *cli)
782 {
783         union smb_lock io;
784         union smb_open op;
785         struct smb_lock_entry lock[2];
786         NTSTATUS status;
787         bool ret = true;
788         int fnum, fnum2;
789         const char *fname;
790         struct smbcli_request *req;
791         time_t start;
792         int t;
793
794         if (!torture_setup_dir(cli, BASEDIR)) {
795                 return false;
796         }
797
798         printf("Testing LOCK_NOT_GRANTED vs. FILE_LOCK_CONFLICT\n");
799
800         printf("testing with timeout = 0\n");
801         fname = BASEDIR "\\test0.txt";
802         t = 0;
803
804         /*
805          * the first run is with t = 0,
806          * the second with t > 0 (=1)
807          */
808 next_run:
809         /* 
810          * use the DENY_DOS mode, that creates two fnum's of one low-level file handle,
811          * this demonstrates that the cache is per fnum
812          */
813         op.openx.level = RAW_OPEN_OPENX;
814         op.openx.in.fname = fname;
815         op.openx.in.flags = OPENX_FLAGS_ADDITIONAL_INFO;
816         op.openx.in.open_mode = OPENX_MODE_ACCESS_RDWR | OPENX_MODE_DENY_DOS;
817         op.openx.in.open_func = OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE;
818         op.openx.in.search_attrs = 0;
819         op.openx.in.file_attrs = 0;
820         op.openx.in.write_time = 0;
821         op.openx.in.size = 0;
822         op.openx.in.timeout = 0;
823
824         status = smb_raw_open(cli->tree, tctx, &op);
825         CHECK_STATUS(status, NT_STATUS_OK);
826         fnum = op.openx.out.file.fnum;
827
828         status = smb_raw_open(cli->tree, tctx, &op);
829         CHECK_STATUS(status, NT_STATUS_OK);
830         fnum2 = op.openx.out.file.fnum;
831
832         io.lockx.level = RAW_LOCK_LOCKX;
833         io.lockx.in.file.fnum = fnum;
834         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
835         io.lockx.in.timeout = t;
836         io.lockx.in.ulock_cnt = 0;
837         io.lockx.in.lock_cnt = 1;
838         lock[0].pid = cli->session->pid;
839         lock[0].offset = 100;
840         lock[0].count = 10;
841         io.lockx.in.locks = &lock[0];
842         status = smb_raw_lock(cli->tree, &io);
843         CHECK_STATUS(status, NT_STATUS_OK);
844
845         /*
846          * demonstrate that the first conflicting lock on each handle give LOCK_NOT_GRANTED
847          * this also demonstrates that the error code cache is per file handle
848          * (LOCK_NOT_GRANTED is only be used when timeout is 0!)
849          */
850         io.lockx.in.file.fnum = fnum2;
851         status = smb_raw_lock(cli->tree, &io);
852         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
853
854         io.lockx.in.file.fnum = fnum;
855         status = smb_raw_lock(cli->tree, &io);
856         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
857
858         /* demonstrate that each following conflict gives FILE_LOCK_CONFLICT */
859         io.lockx.in.file.fnum = fnum;
860         status = smb_raw_lock(cli->tree, &io);
861         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
862
863         io.lockx.in.file.fnum = fnum2;
864         status = smb_raw_lock(cli->tree, &io);
865         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
866
867         io.lockx.in.file.fnum = fnum;
868         status = smb_raw_lock(cli->tree, &io);
869         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
870
871         io.lockx.in.file.fnum = fnum2;
872         status = smb_raw_lock(cli->tree, &io);
873         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
874
875         /* demonstrate that the smbpid doesn't matter */
876         lock[0].pid++;
877         io.lockx.in.file.fnum = fnum;
878         status = smb_raw_lock(cli->tree, &io);
879         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
880
881         io.lockx.in.file.fnum = fnum2;
882         status = smb_raw_lock(cli->tree, &io);
883         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
884         lock[0].pid--;
885
886         /* 
887          * demonstrate the a successful lock with count = 0 and the same offset,
888          * doesn't reset the error cache
889          */
890         lock[0].offset = 100;
891         lock[0].count = 0;
892         io.lockx.in.file.fnum = fnum;
893         status = smb_raw_lock(cli->tree, &io);
894         CHECK_STATUS(status, NT_STATUS_OK);
895
896         io.lockx.in.file.fnum = fnum2;
897         status = smb_raw_lock(cli->tree, &io);
898         CHECK_STATUS(status, NT_STATUS_OK);
899
900         lock[0].offset = 100;
901         lock[0].count = 10;
902         io.lockx.in.file.fnum = fnum;
903         status = smb_raw_lock(cli->tree, &io);
904         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
905
906         io.lockx.in.file.fnum = fnum2;
907         status = smb_raw_lock(cli->tree, &io);
908         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
909
910         /* 
911          * demonstrate the a successful lock with count = 0 and outside the locked range,
912          * doesn't reset the error cache
913          */
914         lock[0].offset = 110;
915         lock[0].count = 0;
916         io.lockx.in.file.fnum = fnum;
917         status = smb_raw_lock(cli->tree, &io);
918         CHECK_STATUS(status, NT_STATUS_OK);
919
920         io.lockx.in.file.fnum = fnum2;
921         status = smb_raw_lock(cli->tree, &io);
922         CHECK_STATUS(status, NT_STATUS_OK);
923
924         lock[0].offset = 100;
925         lock[0].count = 10;
926         io.lockx.in.file.fnum = fnum;
927         status = smb_raw_lock(cli->tree, &io);
928         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
929
930         io.lockx.in.file.fnum = fnum2;
931         status = smb_raw_lock(cli->tree, &io);
932         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
933
934         lock[0].offset = 99;
935         lock[0].count = 0;
936         io.lockx.in.file.fnum = fnum;
937         status = smb_raw_lock(cli->tree, &io);
938         CHECK_STATUS(status, NT_STATUS_OK);
939
940         io.lockx.in.file.fnum = fnum2;
941         status = smb_raw_lock(cli->tree, &io);
942         CHECK_STATUS(status, NT_STATUS_OK);
943
944         lock[0].offset = 100;
945         lock[0].count = 10;
946         io.lockx.in.file.fnum = fnum;
947         status = smb_raw_lock(cli->tree, &io);
948         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
949
950         io.lockx.in.file.fnum = fnum2;
951         status = smb_raw_lock(cli->tree, &io);
952         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
953
954         /* demonstrate that a changing count doesn't reset the error cache */
955         lock[0].offset = 100;
956         lock[0].count = 5;
957         io.lockx.in.file.fnum = fnum;
958         status = smb_raw_lock(cli->tree, &io);
959         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
960
961         io.lockx.in.file.fnum = fnum2;
962         status = smb_raw_lock(cli->tree, &io);
963         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
964
965         lock[0].offset = 100;
966         lock[0].count = 15;
967         io.lockx.in.file.fnum = fnum;
968         status = smb_raw_lock(cli->tree, &io);
969         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
970
971         io.lockx.in.file.fnum = fnum2;
972         status = smb_raw_lock(cli->tree, &io);
973         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
974
975         /* 
976          * demonstrate the a lock with count = 0 and inside the locked range,
977          * fails and resets the error cache
978          */
979         lock[0].offset = 101;
980         lock[0].count = 0;
981         io.lockx.in.file.fnum = fnum;
982         status = smb_raw_lock(cli->tree, &io);
983         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
984         status = smb_raw_lock(cli->tree, &io);
985         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
986
987         io.lockx.in.file.fnum = fnum2;
988         status = smb_raw_lock(cli->tree, &io);
989         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
990         status = smb_raw_lock(cli->tree, &io);
991         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
992
993         lock[0].offset = 100;
994         lock[0].count = 10;
995         io.lockx.in.file.fnum = fnum;
996         status = smb_raw_lock(cli->tree, &io);
997         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
998         status = smb_raw_lock(cli->tree, &io);
999         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1000
1001         io.lockx.in.file.fnum = fnum2;
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         /* demonstrate the a changing offset, resets the error cache */
1008         lock[0].offset = 105;
1009         lock[0].count = 10;
1010         io.lockx.in.file.fnum = fnum;
1011         status = smb_raw_lock(cli->tree, &io);
1012         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1013         status = smb_raw_lock(cli->tree, &io);
1014         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1015
1016         io.lockx.in.file.fnum = fnum2;
1017         status = smb_raw_lock(cli->tree, &io);
1018         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1019         status = smb_raw_lock(cli->tree, &io);
1020         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1021
1022         lock[0].offset = 100;
1023         lock[0].count = 10;
1024         io.lockx.in.file.fnum = fnum;
1025         status = smb_raw_lock(cli->tree, &io);
1026         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1027         status = smb_raw_lock(cli->tree, &io);
1028         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1029
1030         io.lockx.in.file.fnum = fnum2;
1031         status = smb_raw_lock(cli->tree, &io);
1032         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1033         status = smb_raw_lock(cli->tree, &io);
1034         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1035
1036         lock[0].offset = 95;
1037         lock[0].count = 9;
1038         io.lockx.in.file.fnum = fnum;
1039         status = smb_raw_lock(cli->tree, &io);
1040         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1041         status = smb_raw_lock(cli->tree, &io);
1042         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1043
1044         io.lockx.in.file.fnum = fnum2;
1045         status = smb_raw_lock(cli->tree, &io);
1046         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1047         status = smb_raw_lock(cli->tree, &io);
1048         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1049
1050         lock[0].offset = 100;
1051         lock[0].count = 10;
1052         io.lockx.in.file.fnum = fnum;
1053         status = smb_raw_lock(cli->tree, &io);
1054         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1055         status = smb_raw_lock(cli->tree, &io);
1056         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1057
1058         io.lockx.in.file.fnum = fnum2;
1059         status = smb_raw_lock(cli->tree, &io);
1060         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1061         status = smb_raw_lock(cli->tree, &io);
1062         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1063
1064         /* 
1065          * demonstrate the a successful lock in a different range, 
1066          * doesn't reset the cache, the failing lock on the 2nd handle
1067          * resets the resets the cache
1068          */
1069         lock[0].offset = 120;
1070         lock[0].count = 15;
1071         io.lockx.in.file.fnum = fnum;
1072         status = smb_raw_lock(cli->tree, &io);
1073         CHECK_STATUS(status, NT_STATUS_OK);
1074
1075         io.lockx.in.file.fnum = fnum2;
1076         status = smb_raw_lock(cli->tree, &io);
1077         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1078
1079         lock[0].offset = 100;
1080         lock[0].count = 10;
1081         io.lockx.in.file.fnum = fnum;
1082         status = smb_raw_lock(cli->tree, &io);
1083         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1084         status = smb_raw_lock(cli->tree, &io);
1085         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1086
1087         io.lockx.in.file.fnum = fnum2;
1088         status = smb_raw_lock(cli->tree, &io);
1089         CHECK_STATUS(status, (t?NT_STATUS_FILE_LOCK_CONFLICT:NT_STATUS_LOCK_NOT_GRANTED));
1090         status = smb_raw_lock(cli->tree, &io);
1091         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1092
1093         /* end of the loop */
1094         if (t == 0) {
1095                 smb_raw_exit(cli->session);
1096                 printf("testing with timeout > 0 (=1)\n");
1097                 fname = BASEDIR "\\test1.txt";
1098                 t = 1;
1099                 goto next_run;
1100         }
1101
1102         /*
1103          * the following 3 test sections demonstrate that
1104          * the cache is only set when the error is reported
1105          * to the client (after the timeout went by)
1106          */
1107         smb_raw_exit(cli->session);
1108         printf("testing a conflict while a lock is pending\n");
1109         fname = BASEDIR "\\test2.txt";
1110         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1111         if (fnum == -1) {
1112                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1113                 ret = false;
1114                 goto done;
1115         }
1116         io.lockx.level = RAW_LOCK_LOCKX;
1117         io.lockx.in.file.fnum = fnum;
1118         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1119         io.lockx.in.timeout = 0;
1120         io.lockx.in.ulock_cnt = 0;
1121         io.lockx.in.lock_cnt = 1;
1122         lock[0].pid = cli->session->pid;
1123         lock[0].offset = 100;
1124         lock[0].count = 10;
1125         io.lockx.in.locks = &lock[0];
1126         status = smb_raw_lock(cli->tree, &io);
1127         CHECK_STATUS(status, NT_STATUS_OK);
1128
1129         start = time(NULL);
1130         io.lockx.in.timeout = 1000;
1131         req = smb_raw_lock_send(cli->tree, &io);
1132         if (req == NULL) {
1133                 printf("Failed to setup timed lock (%s)\n", __location__);
1134                 ret = false;
1135                 goto done;
1136         }
1137
1138         io.lockx.in.timeout = 0;
1139         lock[0].offset = 105;
1140         lock[0].count = 10;
1141         status = smb_raw_lock(cli->tree, &io);
1142         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1143
1144         status = smbcli_request_simple_recv(req);
1145         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1146
1147         status = smb_raw_lock(cli->tree, &io);
1148         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1149
1150         if (time(NULL) < start+1) {
1151                 printf("lock comes back to early (%s)\n", __location__);
1152                 ret = false;
1153                 goto done;
1154         }
1155
1156         smbcli_close(cli->tree, fnum);
1157         fname = BASEDIR "\\test3.txt";
1158         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1159         if (fnum == -1) {
1160                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1161                 ret = false;
1162                 goto done;
1163         }
1164         io.lockx.level = RAW_LOCK_LOCKX;
1165         io.lockx.in.file.fnum = fnum;
1166         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1167         io.lockx.in.timeout = 0;
1168         io.lockx.in.ulock_cnt = 0;
1169         io.lockx.in.lock_cnt = 1;
1170         lock[0].pid = cli->session->pid;
1171         lock[0].offset = 100;
1172         lock[0].count = 10;
1173         io.lockx.in.locks = &lock[0];
1174         status = smb_raw_lock(cli->tree, &io);
1175         CHECK_STATUS(status, NT_STATUS_OK);
1176
1177         start = time(NULL);
1178         io.lockx.in.timeout = 1000;
1179         req = smb_raw_lock_send(cli->tree, &io);
1180         if (req == NULL) {
1181                 printf("Failed to setup timed lock (%s)\n", __location__);
1182                 ret = false;
1183                 goto done;
1184         }
1185
1186         io.lockx.in.timeout = 0;
1187         lock[0].offset = 105;
1188         lock[0].count = 10;
1189         status = smb_raw_lock(cli->tree, &io);
1190         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1191
1192         status = smbcli_request_simple_recv(req);
1193         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1194
1195         lock[0].offset = 100;
1196         lock[0].count = 10;
1197         status = smb_raw_lock(cli->tree, &io);
1198         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1199
1200         if (time(NULL) < start+1) {
1201                 printf("lock comes back to early (%s)\n", __location__);
1202                 ret = false;
1203                 goto done;
1204         }
1205
1206         smbcli_close(cli->tree, fnum);
1207         fname = BASEDIR "\\test4.txt";
1208         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1209         if (fnum == -1) {
1210                 printf("Failed to reopen %s - %s\n", fname, smbcli_errstr(cli->tree));
1211                 ret = false;
1212                 goto done;
1213         }
1214         io.lockx.level = RAW_LOCK_LOCKX;
1215         io.lockx.in.file.fnum = fnum;
1216         io.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
1217         io.lockx.in.timeout = 0;
1218         io.lockx.in.ulock_cnt = 0;
1219         io.lockx.in.lock_cnt = 1;
1220         lock[0].pid = cli->session->pid;
1221         lock[0].offset = 100;
1222         lock[0].count = 10;
1223         io.lockx.in.locks = &lock[0];
1224         status = smb_raw_lock(cli->tree, &io);
1225         CHECK_STATUS(status, NT_STATUS_OK);
1226
1227         start = time(NULL);
1228         io.lockx.in.timeout = 1000;
1229         req = smb_raw_lock_send(cli->tree, &io);
1230         if (req == NULL) {
1231                 printf("Failed to setup timed lock (%s)\n", __location__);
1232                 ret = false;
1233                 goto done;
1234         }
1235
1236         io.lockx.in.timeout = 0;
1237         status = smb_raw_lock(cli->tree, &io);
1238         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
1239
1240         status = smbcli_request_simple_recv(req);
1241         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1242
1243         status = smb_raw_lock(cli->tree, &io);
1244         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
1245
1246         if (time(NULL) < start+1) {
1247                 printf("lock comes back to early (%s)\n", __location__);
1248                 ret = false;
1249                 goto done;
1250         }
1251
1252 done:
1253         smb_raw_exit(cli->session);
1254         smbcli_deltree(cli->tree, BASEDIR);
1255         return ret;
1256 }
1257
1258
1259 /*
1260   test LOCKING_ANDX_CHANGE_LOCKTYPE
1261 */
1262 static bool test_changetype(struct torture_context *tctx, 
1263                                                         struct smbcli_state *cli)
1264 {
1265         union smb_lock io;
1266         struct smb_lock_entry lock[2];
1267         NTSTATUS status;
1268         bool ret = true;
1269         int fnum;
1270         uint8_t c = 0;
1271         const char *fname = BASEDIR "\\test.txt";
1272
1273         if (!torture_setup_dir(cli, BASEDIR)) {
1274                 return false;
1275         }
1276
1277         printf("Testing LOCKING_ANDX_CHANGE_LOCKTYPE\n");
1278         io.generic.level = RAW_LOCK_LOCKX;
1279         
1280         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1281         if (fnum == -1) {
1282                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
1283                 ret = false;
1284                 goto done;
1285         }
1286
1287         io.lockx.level = RAW_LOCK_LOCKX;
1288         io.lockx.in.file.fnum = fnum;
1289         io.lockx.in.mode = LOCKING_ANDX_SHARED_LOCK;
1290         io.lockx.in.timeout = 0;
1291         io.lockx.in.ulock_cnt = 0;
1292         io.lockx.in.lock_cnt = 1;
1293         lock[0].pid = cli->session->pid;
1294         lock[0].offset = 100;
1295         lock[0].count = 10;
1296         io.lockx.in.locks = &lock[0];
1297         status = smb_raw_lock(cli->tree, &io);
1298         CHECK_STATUS(status, NT_STATUS_OK);
1299
1300         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1301                 printf("allowed write on read locked region (%s)\n", __location__);
1302                 ret = false;
1303                 goto done;
1304         }
1305
1306         /* windows server don't seem to support this */
1307         io.lockx.in.mode = LOCKING_ANDX_CHANGE_LOCKTYPE;
1308         status = smb_raw_lock(cli->tree, &io);
1309         CHECK_STATUS(status, NT_STATUS_DOS(ERRDOS, ERRnoatomiclocks));
1310
1311         if (smbcli_write(cli->tree, fnum, 0, &c, 100, 1) == 1) {
1312                 printf("allowed write after lock change (%s)\n", __location__);
1313                 ret = false;
1314                 goto done;
1315         }
1316
1317 done:
1318         smbcli_close(cli->tree, fnum);
1319         smb_raw_exit(cli->session);
1320         smbcli_deltree(cli->tree, BASEDIR);
1321         return ret;
1322 }
1323
1324
1325 /* 
1326    basic testing of lock calls
1327 */
1328 struct torture_suite *torture_raw_lock(TALLOC_CTX *mem_ctx)
1329 {
1330         struct torture_suite *suite = torture_suite_create(mem_ctx, "LOCK");
1331
1332         torture_suite_add_1smb_test(suite, "lockx", test_lockx);
1333         torture_suite_add_1smb_test(suite, "lock", test_lock);
1334         torture_suite_add_1smb_test(suite, "pidhigh", test_pidhigh);
1335         torture_suite_add_1smb_test(suite, "async", test_async);
1336         torture_suite_add_1smb_test(suite, "errorcode", test_errorcode);
1337         torture_suite_add_1smb_test(suite, "changetype", test_changetype);
1338
1339         return suite;
1340 }