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