Remove another use of global_loadparm.
[jra/samba/.git] / source4 / torture / raw / read.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for various read 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
29 #define CHECK_STATUS(status, correct) do { \
30         if (!NT_STATUS_EQUAL(status, correct)) { \
31                 printf("(%s) Incorrect status %s - should be %s\n", \
32                        __location__, nt_errstr(status), nt_errstr(correct)); \
33                 ret = false; \
34                 goto done; \
35         }} while (0)
36
37 #define CHECK_VALUE(v, correct) do { \
38         if ((v) != (correct)) { \
39                 printf("(%s) Incorrect value %s=%ld - should be %ld\n", \
40                        __location__, #v, (long)v, (long)correct); \
41                 ret = false; \
42                 goto done; \
43         }} while (0)
44
45 #define CHECK_BUFFER(buf, seed, len) do { \
46         if (!check_buffer(buf, seed, len, __LINE__)) { \
47                 ret = false; \
48                 goto done; \
49         }} while (0)
50
51 #define BASEDIR "\\testread"
52
53
54 /*
55   setup a random buffer based on a seed
56 */
57 static void setup_buffer(uint8_t *buf, uint_t seed, int len)
58 {
59         int i;
60         srandom(seed);
61         for (i=0;i<len;i++) buf[i] = random();
62 }
63
64 /*
65   check a random buffer based on a seed
66 */
67 static bool check_buffer(uint8_t *buf, uint_t seed, int len, int line)
68 {
69         int i;
70         srandom(seed);
71         for (i=0;i<len;i++) {
72                 uint8_t v = random();
73                 if (buf[i] != v) {
74                         printf("Buffer incorrect at line %d! ofs=%d v1=0x%x v2=0x%x\n", 
75                                line, i, buf[i], v);
76                         return false;
77                 }
78         }
79         return true;
80 }
81
82 /*
83   test read ops
84 */
85 static bool test_read(struct torture_context *tctx, struct smbcli_state *cli)
86 {
87         union smb_read io;
88         NTSTATUS status;
89         bool ret = true;
90         int fnum;
91         uint8_t *buf;
92         const int maxsize = 90000;
93         const char *fname = BASEDIR "\\test.txt";
94         const char *test_data = "TEST DATA";
95         uint_t seed = time(NULL);
96
97         buf = talloc_zero_array(tctx, uint8_t, maxsize);
98
99         if (!torture_setup_dir(cli, BASEDIR)) {
100                 return false;
101         }
102
103         printf("Testing RAW_READ_READ\n");
104         io.generic.level = RAW_READ_READ;
105         
106         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
107         if (fnum == -1) {
108                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
109                 ret = false;
110                 goto done;
111         }
112
113         printf("Trying empty file read\n");
114         io.read.in.file.fnum = fnum;
115         io.read.in.count = 1;
116         io.read.in.offset = 0;
117         io.read.in.remaining = 0;
118         io.read.out.data = buf;
119         status = smb_raw_read(cli->tree, &io);
120
121         CHECK_STATUS(status, NT_STATUS_OK);
122         CHECK_VALUE(io.read.out.nread, 0);
123
124         printf("Trying zero file read\n");
125         io.read.in.count = 0;
126         status = smb_raw_read(cli->tree, &io);
127         CHECK_STATUS(status, NT_STATUS_OK);
128         CHECK_VALUE(io.read.out.nread, 0);
129
130         printf("Trying bad fnum\n");
131         io.read.in.file.fnum = fnum+1;
132         status = smb_raw_read(cli->tree, &io);
133         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
134         io.read.in.file.fnum = fnum;
135
136         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
137
138         printf("Trying small read\n");
139         io.read.in.file.fnum = fnum;
140         io.read.in.offset = 0;
141         io.read.in.remaining = 0;
142         io.read.in.count = strlen(test_data);
143         status = smb_raw_read(cli->tree, &io);
144         CHECK_STATUS(status, NT_STATUS_OK);
145         CHECK_VALUE(io.read.out.nread, strlen(test_data));
146         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
147                 ret = false;
148                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
149                 goto done;
150         }
151
152         printf("Trying short read\n");
153         io.read.in.offset = 1;
154         io.read.in.count = strlen(test_data);
155         status = smb_raw_read(cli->tree, &io);
156         CHECK_STATUS(status, NT_STATUS_OK);
157         CHECK_VALUE(io.read.out.nread, strlen(test_data)-1);
158         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
159                 ret = false;
160                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
161                 goto done;
162         }
163
164         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
165                 printf("Trying max offset\n");
166                 io.read.in.offset = ~0;
167                 io.read.in.count = strlen(test_data);
168                 status = smb_raw_read(cli->tree, &io);
169                 CHECK_STATUS(status, NT_STATUS_OK);
170                 CHECK_VALUE(io.read.out.nread, 0);
171         }
172
173         setup_buffer(buf, seed, maxsize);
174         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
175         memset(buf, 0, maxsize);
176
177         printf("Trying large read\n");
178         io.read.in.offset = 0;
179         io.read.in.count = ~0;
180         status = smb_raw_read(cli->tree, &io);
181         CHECK_STATUS(status, NT_STATUS_OK);
182         CHECK_BUFFER(buf, seed, io.read.out.nread);
183
184
185         printf("Trying locked region\n");
186         cli->session->pid++;
187         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
188                 printf("Failed to lock file at %d\n", __LINE__);
189                 ret = false;
190                 goto done;
191         }
192         cli->session->pid--;
193         memset(buf, 0, maxsize);
194         io.read.in.offset = 0;
195         io.read.in.count = ~0;
196         status = smb_raw_read(cli->tree, &io);
197         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
198         
199
200 done:
201         smbcli_close(cli->tree, fnum);
202         smb_raw_exit(cli->session);
203         smbcli_deltree(cli->tree, BASEDIR);
204         return ret;
205 }
206
207
208 /*
209   test lockread ops
210 */
211 static bool test_lockread(struct torture_context *tctx, 
212                                                   struct smbcli_state *cli)
213 {
214         union smb_read io;
215         NTSTATUS status;
216         bool ret = true;
217         int fnum;
218         uint8_t *buf;
219         const int maxsize = 90000;
220         const char *fname = BASEDIR "\\test.txt";
221         const char *test_data = "TEST DATA";
222         uint_t seed = time(NULL);
223
224         buf = talloc_zero_array(tctx, uint8_t, maxsize);
225
226         if (!torture_setup_dir(cli, BASEDIR)) {
227                 return false;
228         }
229
230         printf("Testing RAW_READ_LOCKREAD\n");
231         io.generic.level = RAW_READ_LOCKREAD;
232         
233         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
234         if (fnum == -1) {
235                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
236                 ret = false;
237                 goto done;
238         }
239
240         printf("Trying empty file read\n");
241         io.lockread.in.file.fnum = fnum;
242         io.lockread.in.count = 1;
243         io.lockread.in.offset = 1;
244         io.lockread.in.remaining = 0;
245         io.lockread.out.data = buf;
246         status = smb_raw_read(cli->tree, &io);
247
248         CHECK_STATUS(status, NT_STATUS_OK);
249         CHECK_VALUE(io.lockread.out.nread, 0);
250
251         status = smb_raw_read(cli->tree, &io);
252         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
253
254         status = smb_raw_read(cli->tree, &io);
255         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
256
257         printf("Trying zero file read\n");
258         io.lockread.in.count = 0;
259         status = smb_raw_read(cli->tree, &io);
260         CHECK_STATUS(status, NT_STATUS_OK);
261
262         smbcli_unlock(cli->tree, fnum, 1, 1);
263
264         printf("Trying bad fnum\n");
265         io.lockread.in.file.fnum = fnum+1;
266         status = smb_raw_read(cli->tree, &io);
267         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
268         io.lockread.in.file.fnum = fnum;
269
270         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
271
272         printf("Trying small read\n");
273         io.lockread.in.file.fnum = fnum;
274         io.lockread.in.offset = 0;
275         io.lockread.in.remaining = 0;
276         io.lockread.in.count = strlen(test_data);
277         status = smb_raw_read(cli->tree, &io);
278         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
279
280         smbcli_unlock(cli->tree, fnum, 1, 0);
281
282         status = smb_raw_read(cli->tree, &io);
283         CHECK_STATUS(status, NT_STATUS_OK);
284         CHECK_VALUE(io.lockread.out.nread, strlen(test_data));
285         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
286                 ret = false;
287                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
288                 goto done;
289         }
290
291         printf("Trying short read\n");
292         io.lockread.in.offset = 1;
293         io.lockread.in.count = strlen(test_data);
294         status = smb_raw_read(cli->tree, &io);
295         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
296         smbcli_unlock(cli->tree, fnum, 0, strlen(test_data));
297         status = smb_raw_read(cli->tree, &io);
298         CHECK_STATUS(status, NT_STATUS_OK);
299
300         CHECK_VALUE(io.lockread.out.nread, strlen(test_data)-1);
301         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
302                 ret = false;
303                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
304                 goto done;
305         }
306
307         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
308                 printf("Trying max offset\n");
309                 io.lockread.in.offset = ~0;
310                 io.lockread.in.count = strlen(test_data);
311                 status = smb_raw_read(cli->tree, &io);
312                 CHECK_STATUS(status, NT_STATUS_OK);
313                 CHECK_VALUE(io.lockread.out.nread, 0);
314         }
315
316         setup_buffer(buf, seed, maxsize);
317         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
318         memset(buf, 0, maxsize);
319
320         printf("Trying large read\n");
321         io.lockread.in.offset = 0;
322         io.lockread.in.count = ~0;
323         status = smb_raw_read(cli->tree, &io);
324         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
325         smbcli_unlock(cli->tree, fnum, 1, strlen(test_data));
326         status = smb_raw_read(cli->tree, &io);
327         CHECK_STATUS(status, NT_STATUS_OK);
328         CHECK_BUFFER(buf, seed, io.lockread.out.nread);
329         smbcli_unlock(cli->tree, fnum, 0, 0xFFFF);
330
331
332         printf("Trying locked region\n");
333         cli->session->pid++;
334         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
335                 printf("Failed to lock file at %d\n", __LINE__);
336                 ret = false;
337                 goto done;
338         }
339         cli->session->pid--;
340         memset(buf, 0, maxsize);
341         io.lockread.in.offset = 0;
342         io.lockread.in.count = ~0;
343         status = smb_raw_read(cli->tree, &io);
344         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
345         
346
347 done:
348         smbcli_close(cli->tree, fnum);
349         smbcli_deltree(cli->tree, BASEDIR);
350         return ret;
351 }
352
353
354 /*
355   test readx ops
356 */
357 static bool test_readx(struct torture_context *tctx, struct smbcli_state *cli)
358 {
359         union smb_read io;
360         NTSTATUS status;
361         bool ret = true;
362         int fnum;
363         uint8_t *buf;
364         const int maxsize = 90000;
365         const char *fname = BASEDIR "\\test.txt";
366         const char *test_data = "TEST DATA";
367         uint_t seed = time(NULL);
368
369         buf = talloc_zero_array(tctx, uint8_t, maxsize);
370
371         if (!torture_setup_dir(cli, BASEDIR)) {
372                 return false;
373         }
374
375         printf("Testing RAW_READ_READX\n");
376         
377         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
378         if (fnum == -1) {
379                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
380                 ret = false;
381                 goto done;
382         }
383
384         printf("Trying empty file read\n");
385         io.generic.level = RAW_READ_READX;
386         io.readx.in.file.fnum = fnum;
387         io.readx.in.mincnt = 1;
388         io.readx.in.maxcnt = 1;
389         io.readx.in.offset = 0;
390         io.readx.in.remaining = 0;
391         io.readx.in.read_for_execute = false;
392         io.readx.out.data = buf;
393         status = smb_raw_read(cli->tree, &io);
394
395         CHECK_STATUS(status, NT_STATUS_OK);
396         CHECK_VALUE(io.readx.out.nread, 0);
397         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
398         CHECK_VALUE(io.readx.out.compaction_mode, 0);
399
400         printf("Trying zero file read\n");
401         io.readx.in.mincnt = 0;
402         io.readx.in.maxcnt = 0;
403         status = smb_raw_read(cli->tree, &io);
404         CHECK_STATUS(status, NT_STATUS_OK);
405         CHECK_VALUE(io.readx.out.nread, 0);
406         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
407         CHECK_VALUE(io.readx.out.compaction_mode, 0);
408
409         printf("Trying bad fnum\n");
410         io.readx.in.file.fnum = fnum+1;
411         status = smb_raw_read(cli->tree, &io);
412         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
413         io.readx.in.file.fnum = fnum;
414
415         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
416
417         printf("Trying small read\n");
418         io.readx.in.file.fnum = fnum;
419         io.readx.in.offset = 0;
420         io.readx.in.remaining = 0;
421         io.readx.in.read_for_execute = false;
422         io.readx.in.mincnt = strlen(test_data);
423         io.readx.in.maxcnt = strlen(test_data);
424         status = smb_raw_read(cli->tree, &io);
425         CHECK_STATUS(status, NT_STATUS_OK);
426         CHECK_VALUE(io.readx.out.nread, strlen(test_data));
427         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
428         CHECK_VALUE(io.readx.out.compaction_mode, 0);
429         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
430                 ret = false;
431                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
432                 goto done;
433         }
434
435         printf("Trying short read\n");
436         io.readx.in.offset = 1;
437         io.readx.in.mincnt = strlen(test_data);
438         io.readx.in.maxcnt = strlen(test_data);
439         status = smb_raw_read(cli->tree, &io);
440         CHECK_STATUS(status, NT_STATUS_OK);
441         CHECK_VALUE(io.readx.out.nread, strlen(test_data)-1);
442         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
443         CHECK_VALUE(io.readx.out.compaction_mode, 0);
444         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
445                 ret = false;
446                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
447                 goto done;
448         }
449
450         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
451                 printf("Trying max offset\n");
452                 io.readx.in.offset = 0xffffffff;
453                 io.readx.in.mincnt = strlen(test_data);
454                 io.readx.in.maxcnt = strlen(test_data);
455                 status = smb_raw_read(cli->tree, &io);
456                 CHECK_STATUS(status, NT_STATUS_OK);
457                 CHECK_VALUE(io.readx.out.nread, 0);
458                 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
459                 CHECK_VALUE(io.readx.out.compaction_mode, 0);
460         }
461
462         printf("Trying mincnt past EOF\n");
463         memset(buf, 0, maxsize);
464         io.readx.in.offset = 0;
465         io.readx.in.mincnt = 100;
466         io.readx.in.maxcnt = 110;
467         status = smb_raw_read(cli->tree, &io);
468         CHECK_STATUS(status, NT_STATUS_OK);
469         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
470         CHECK_VALUE(io.readx.out.compaction_mode, 0);
471         CHECK_VALUE(io.readx.out.nread, strlen(test_data));
472         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
473                 ret = false;
474                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
475                 goto done;
476         }
477
478
479         setup_buffer(buf, seed, maxsize);
480         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
481         memset(buf, 0, maxsize);
482
483         printf("Trying large read\n");
484         io.readx.in.offset = 0;
485         io.readx.in.mincnt = 0xFFFF;
486         io.readx.in.maxcnt = 0xFFFF;
487         status = smb_raw_read(cli->tree, &io);
488         CHECK_STATUS(status, NT_STATUS_OK);
489         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
490         CHECK_VALUE(io.readx.out.compaction_mode, 0);
491         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
492         CHECK_BUFFER(buf, seed, io.readx.out.nread);
493
494         printf("Trying extra large read\n");
495         io.readx.in.offset = 0;
496         io.readx.in.mincnt = 100;
497         io.readx.in.maxcnt = 80000;
498         status = smb_raw_read(cli->tree, &io);
499         CHECK_STATUS(status, NT_STATUS_OK);
500         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
501         CHECK_VALUE(io.readx.out.compaction_mode, 0);
502         if (torture_setting_bool(tctx, "samba3", false)) {
503                 printf("SAMBA3: large read extension\n");
504                 CHECK_VALUE(io.readx.out.nread, 80000);
505         } else {
506                 CHECK_VALUE(io.readx.out.nread, 0);
507         }
508         CHECK_BUFFER(buf, seed, io.readx.out.nread);
509
510         printf("Trying mincnt > maxcnt\n");
511         memset(buf, 0, maxsize);
512         io.readx.in.offset = 0;
513         io.readx.in.mincnt = 30000;
514         io.readx.in.maxcnt = 20000;
515         status = smb_raw_read(cli->tree, &io);
516         CHECK_STATUS(status, NT_STATUS_OK);
517         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
518         CHECK_VALUE(io.readx.out.compaction_mode, 0);
519         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
520         CHECK_BUFFER(buf, seed, io.readx.out.nread);
521
522         printf("Trying mincnt < maxcnt\n");
523         memset(buf, 0, maxsize);
524         io.readx.in.offset = 0;
525         io.readx.in.mincnt = 20000;
526         io.readx.in.maxcnt = 30000;
527         status = smb_raw_read(cli->tree, &io);
528         CHECK_STATUS(status, NT_STATUS_OK);
529         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
530         CHECK_VALUE(io.readx.out.compaction_mode, 0);
531         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
532         CHECK_BUFFER(buf, seed, io.readx.out.nread);
533
534         if (cli->transport->negotiate.capabilities & CAP_LARGE_READX) {
535                 printf("Trying large readx\n");
536                 io.readx.in.offset = 0;
537                 io.readx.in.mincnt = 0;
538                 io.readx.in.maxcnt = 0x10000 - 1;
539                 status = smb_raw_read(cli->tree, &io);
540                 CHECK_STATUS(status, NT_STATUS_OK);
541                 CHECK_VALUE(io.readx.out.nread, 0xFFFF);
542
543                 io.readx.in.maxcnt = 0x10000;
544                 status = smb_raw_read(cli->tree, &io);
545                 CHECK_STATUS(status, NT_STATUS_OK);
546                 if (torture_setting_bool(tctx, "samba3", false)) {
547                         printf("SAMBA3: large read extension\n");
548                         CHECK_VALUE(io.readx.out.nread, 0x10000);
549                 } else {
550                         CHECK_VALUE(io.readx.out.nread, 0);
551                 }
552
553                 io.readx.in.maxcnt = 0x10001;
554                 status = smb_raw_read(cli->tree, &io);
555                 CHECK_STATUS(status, NT_STATUS_OK);
556                 if (torture_setting_bool(tctx, "samba3", false)) {
557                         printf("SAMBA3: large read extension\n");
558                         CHECK_VALUE(io.readx.out.nread, 0x10001);
559                 } else {
560                         CHECK_VALUE(io.readx.out.nread, 0);
561                 }
562         }
563
564         printf("Trying locked region\n");
565         cli->session->pid++;
566         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
567                 printf("Failed to lock file at %d\n", __LINE__);
568                 ret = false;
569                 goto done;
570         }
571         cli->session->pid--;
572         memset(buf, 0, maxsize);
573         io.readx.in.offset = 0;
574         io.readx.in.mincnt = 100;
575         io.readx.in.maxcnt = 200;
576         status = smb_raw_read(cli->tree, &io);
577         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);     
578
579         if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
580                 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
581                 goto done;
582         }
583
584         printf("Trying large offset read\n");
585         io.readx.in.offset = ((uint64_t)0x2) << 32;
586         io.readx.in.mincnt = 10;
587         io.readx.in.maxcnt = 10;
588         status = smb_raw_read(cli->tree, &io);
589         CHECK_STATUS(status, NT_STATUS_OK);
590         CHECK_VALUE(io.readx.out.nread, 0);
591
592         if (NT_STATUS_IS_ERR(smbcli_lock64(cli->tree, fnum, io.readx.in.offset, 1, 0, WRITE_LOCK))) {
593                 printf("Failed to lock file at %d\n", __LINE__);
594                 ret = false;
595                 goto done;
596         }
597
598         status = smb_raw_read(cli->tree, &io);
599         CHECK_STATUS(status, NT_STATUS_OK);
600         CHECK_VALUE(io.readx.out.nread, 0);
601
602 done:
603         smbcli_close(cli->tree, fnum);
604         smbcli_deltree(cli->tree, BASEDIR);
605         return ret;
606 }
607
608
609 /*
610   test readbraw ops
611 */
612 static bool test_readbraw(struct torture_context *tctx, 
613                                                   struct smbcli_state *cli)
614 {
615         union smb_read io;
616         NTSTATUS status;
617         bool ret = true;
618         int fnum;
619         uint8_t *buf;
620         const int maxsize = 90000;
621         const char *fname = BASEDIR "\\test.txt";
622         const char *test_data = "TEST DATA";
623         uint_t seed = time(NULL);
624
625         buf = talloc_zero_array(tctx, uint8_t, maxsize);
626
627         if (!torture_setup_dir(cli, BASEDIR)) {
628                 return false;
629         }
630
631         printf("Testing RAW_READ_READBRAW\n");
632         
633         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
634         if (fnum == -1) {
635                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
636                 ret = false;
637                 goto done;
638         }
639
640         printf("Trying empty file read\n");
641         io.generic.level = RAW_READ_READBRAW;
642         io.readbraw.in.file.fnum = fnum;
643         io.readbraw.in.mincnt = 1;
644         io.readbraw.in.maxcnt = 1;
645         io.readbraw.in.offset = 0;
646         io.readbraw.in.timeout = 0;
647         io.readbraw.out.data = buf;
648         status = smb_raw_read(cli->tree, &io);
649
650         CHECK_STATUS(status, NT_STATUS_OK);
651         CHECK_VALUE(io.readbraw.out.nread, 0);
652
653         printf("Trying zero file read\n");
654         io.readbraw.in.mincnt = 0;
655         io.readbraw.in.maxcnt = 0;
656         status = smb_raw_read(cli->tree, &io);
657         CHECK_STATUS(status, NT_STATUS_OK);
658         CHECK_VALUE(io.readbraw.out.nread, 0);
659
660         printf("Trying bad fnum\n");
661         io.readbraw.in.file.fnum = fnum+1;
662         status = smb_raw_read(cli->tree, &io);
663         CHECK_STATUS(status, NT_STATUS_OK);
664         CHECK_VALUE(io.readbraw.out.nread, 0);
665         io.readbraw.in.file.fnum = fnum;
666
667         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
668
669         printf("Trying small read\n");
670         io.readbraw.in.file.fnum = fnum;
671         io.readbraw.in.offset = 0;
672         io.readbraw.in.mincnt = strlen(test_data);
673         io.readbraw.in.maxcnt = strlen(test_data);
674         status = smb_raw_read(cli->tree, &io);
675         CHECK_STATUS(status, NT_STATUS_OK);
676         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data));
677         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
678                 ret = false;
679                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
680                 goto done;
681         }
682
683         printf("Trying short read\n");
684         io.readbraw.in.offset = 1;
685         io.readbraw.in.mincnt = strlen(test_data);
686         io.readbraw.in.maxcnt = strlen(test_data);
687         status = smb_raw_read(cli->tree, &io);
688         CHECK_STATUS(status, NT_STATUS_OK);
689         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data)-1);
690         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
691                 ret = false;
692                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
693                 goto done;
694         }
695
696         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
697                 printf("Trying max offset\n");
698                 io.readbraw.in.offset = ~0;
699                 io.readbraw.in.mincnt = strlen(test_data);
700                 io.readbraw.in.maxcnt = strlen(test_data);
701                 status = smb_raw_read(cli->tree, &io);
702                 CHECK_STATUS(status, NT_STATUS_OK);
703                 CHECK_VALUE(io.readbraw.out.nread, 0);
704         }
705
706         setup_buffer(buf, seed, maxsize);
707         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
708         memset(buf, 0, maxsize);
709
710         printf("Trying large read\n");
711         io.readbraw.in.offset = 0;
712         io.readbraw.in.mincnt = ~0;
713         io.readbraw.in.maxcnt = ~0;
714         status = smb_raw_read(cli->tree, &io);
715         CHECK_STATUS(status, NT_STATUS_OK);
716         CHECK_VALUE(io.readbraw.out.nread, 0xFFFF);
717         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
718
719         printf("Trying mincnt > maxcnt\n");
720         memset(buf, 0, maxsize);
721         io.readbraw.in.offset = 0;
722         io.readbraw.in.mincnt = 30000;
723         io.readbraw.in.maxcnt = 20000;
724         status = smb_raw_read(cli->tree, &io);
725         CHECK_STATUS(status, NT_STATUS_OK);
726         CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
727         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
728
729         printf("Trying mincnt < maxcnt\n");
730         memset(buf, 0, maxsize);
731         io.readbraw.in.offset = 0;
732         io.readbraw.in.mincnt = 20000;
733         io.readbraw.in.maxcnt = 30000;
734         status = smb_raw_read(cli->tree, &io);
735         CHECK_STATUS(status, NT_STATUS_OK);
736         CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
737         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
738
739         printf("Trying locked region\n");
740         cli->session->pid++;
741         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
742                 printf("Failed to lock file at %d\n", __LINE__);
743                 ret = false;
744                 goto done;
745         }
746         cli->session->pid--;
747         memset(buf, 0, maxsize);
748         io.readbraw.in.offset = 0;
749         io.readbraw.in.mincnt = 100;
750         io.readbraw.in.maxcnt = 200;
751         status = smb_raw_read(cli->tree, &io);
752         CHECK_STATUS(status, NT_STATUS_OK);
753         CHECK_VALUE(io.readbraw.out.nread, 0);
754
755         printf("Trying locked region with timeout\n");
756         memset(buf, 0, maxsize);
757         io.readbraw.in.offset = 0;
758         io.readbraw.in.mincnt = 100;
759         io.readbraw.in.maxcnt = 200;
760         io.readbraw.in.timeout = 10000;
761         status = smb_raw_read(cli->tree, &io);
762         CHECK_STATUS(status, NT_STATUS_OK);
763         CHECK_VALUE(io.readbraw.out.nread, 0);
764
765         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
766                 printf("Trying large offset read\n");
767                 io.readbraw.in.offset = ((uint64_t)0x2) << 32;
768                 io.readbraw.in.mincnt = 10;
769                 io.readbraw.in.maxcnt = 10;
770                 io.readbraw.in.timeout = 0;
771                 status = smb_raw_read(cli->tree, &io);
772                 CHECK_STATUS(status, NT_STATUS_OK);
773                 CHECK_VALUE(io.readbraw.out.nread, 0);
774         }
775
776 done:
777         smbcli_close(cli->tree, fnum);
778         smbcli_deltree(cli->tree, BASEDIR);
779         return ret;
780 }
781
782 /*
783   test read for execute
784 */
785 static bool test_read_for_execute(struct torture_context *tctx, 
786                                                                   struct smbcli_state *cli)
787 {
788         union smb_open op;
789         union smb_write wr;
790         union smb_read rd;
791         NTSTATUS status;
792         bool ret = true;
793         int fnum=0;
794         uint8_t *buf;
795         const int maxsize = 900;
796         const char *fname = BASEDIR "\\test.txt";
797         const uint8_t data[] = "TEST DATA";
798
799         buf = talloc_zero_array(tctx, uint8_t, maxsize);
800
801         if (!torture_setup_dir(cli, BASEDIR)) {
802                 return false;
803         }
804
805         printf("Testing RAW_READ_READX with read_for_execute\n");
806
807         op.generic.level = RAW_OPEN_NTCREATEX;
808         op.ntcreatex.in.root_fid = 0;
809         op.ntcreatex.in.flags = 0;
810         op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
811         op.ntcreatex.in.create_options = 0;
812         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
813         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
814         op.ntcreatex.in.alloc_size = 0;
815         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
816         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
817         op.ntcreatex.in.security_flags = 0;
818         op.ntcreatex.in.fname = fname;
819         status = smb_raw_open(cli->tree, tctx, &op);
820         CHECK_STATUS(status, NT_STATUS_OK);
821         fnum = op.ntcreatex.out.file.fnum;
822
823         wr.generic.level = RAW_WRITE_WRITEX;
824         wr.writex.in.file.fnum = fnum;
825         wr.writex.in.offset = 0;
826         wr.writex.in.wmode = 0;
827         wr.writex.in.remaining = 0;
828         wr.writex.in.count = ARRAY_SIZE(data);
829         wr.writex.in.data = data;
830         status = smb_raw_write(cli->tree, &wr);
831         CHECK_STATUS(status, NT_STATUS_OK);
832         CHECK_VALUE(wr.writex.out.nwritten, ARRAY_SIZE(data));
833
834         status = smbcli_close(cli->tree, fnum);
835         CHECK_STATUS(status, NT_STATUS_OK);
836
837         printf("open file with SEC_FILE_EXECUTE\n");
838         op.generic.level = RAW_OPEN_NTCREATEX;
839         op.ntcreatex.in.root_fid = 0;
840         op.ntcreatex.in.flags = 0;
841         op.ntcreatex.in.access_mask = SEC_FILE_EXECUTE;
842         op.ntcreatex.in.create_options = 0;
843         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
844         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
845         op.ntcreatex.in.alloc_size = 0;
846         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
847         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
848         op.ntcreatex.in.security_flags = 0;
849         op.ntcreatex.in.fname = fname;
850         status = smb_raw_open(cli->tree, tctx, &op);
851         CHECK_STATUS(status, NT_STATUS_OK);
852         fnum = op.ntcreatex.out.file.fnum;
853
854         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
855         rd.generic.level = RAW_READ_READX;
856         rd.readx.in.file.fnum = fnum;
857         rd.readx.in.mincnt = 0;
858         rd.readx.in.maxcnt = maxsize;
859         rd.readx.in.offset = 0;
860         rd.readx.in.remaining = 0;
861         rd.readx.in.read_for_execute = true;
862         rd.readx.out.data = buf;
863         status = smb_raw_read(cli->tree, &rd);
864         CHECK_STATUS(status, NT_STATUS_OK);
865         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
866         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
867         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
868
869         printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
870         rd.generic.level = RAW_READ_READX;
871         rd.readx.in.file.fnum = fnum;
872         rd.readx.in.mincnt = 0;
873         rd.readx.in.maxcnt = maxsize;
874         rd.readx.in.offset = 0;
875         rd.readx.in.remaining = 0;
876         rd.readx.in.read_for_execute = false;
877         rd.readx.out.data = buf;
878         status = smb_raw_read(cli->tree, &rd);
879         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
880
881         status = smbcli_close(cli->tree, fnum);
882         CHECK_STATUS(status, NT_STATUS_OK);
883
884         printf("open file with SEC_FILE_READ_DATA\n");
885         op.generic.level = RAW_OPEN_NTCREATEX;
886         op.ntcreatex.in.root_fid = 0;
887         op.ntcreatex.in.flags = 0;
888         op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
889         op.ntcreatex.in.create_options = 0;
890         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
891         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
892         op.ntcreatex.in.alloc_size = 0;
893         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
894         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
895         op.ntcreatex.in.security_flags = 0;
896         op.ntcreatex.in.fname = fname;
897         status = smb_raw_open(cli->tree, tctx, &op);
898         CHECK_STATUS(status, NT_STATUS_OK);
899         fnum = op.ntcreatex.out.file.fnum;
900
901         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
902         rd.generic.level = RAW_READ_READX;
903         rd.readx.in.file.fnum = fnum;
904         rd.readx.in.mincnt = 0;
905         rd.readx.in.maxcnt = maxsize;
906         rd.readx.in.offset = 0;
907         rd.readx.in.remaining = 0;
908         rd.readx.in.read_for_execute = true;
909         rd.readx.out.data = buf;
910         status = smb_raw_read(cli->tree, &rd);
911         CHECK_STATUS(status, NT_STATUS_OK);
912         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
913         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
914         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
915
916         printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
917         rd.generic.level = RAW_READ_READX;
918         rd.readx.in.file.fnum = fnum;
919         rd.readx.in.mincnt = 0;
920         rd.readx.in.maxcnt = maxsize;
921         rd.readx.in.offset = 0;
922         rd.readx.in.remaining = 0;
923         rd.readx.in.read_for_execute = false;
924         rd.readx.out.data = buf;
925         status = smb_raw_read(cli->tree, &rd);
926         CHECK_STATUS(status, NT_STATUS_OK);
927         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
928         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
929         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
930
931 done:
932         smbcli_close(cli->tree, fnum);
933         smbcli_deltree(cli->tree, BASEDIR);
934         return ret;
935 }
936
937
938 /* 
939    basic testing of read calls
940 */
941 struct torture_suite *torture_raw_read(TALLOC_CTX *mem_ctx)
942 {
943         struct torture_suite *suite = torture_suite_create(mem_ctx, "READ");
944
945         torture_suite_add_1smb_test(suite, "read", test_read);
946         torture_suite_add_1smb_test(suite, "readx", test_readx);
947         torture_suite_add_1smb_test(suite, "lockread", test_lockread);
948         torture_suite_add_1smb_test(suite, "readbraw", test_readbraw);
949         torture_suite_add_1smb_test(suite, "read for execute", 
950                                                                 test_read_for_execute);
951
952         return suite;
953 }