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