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