s4 now supports the large readx extension
[metze/samba/wip.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             torture_setting_bool(tctx, "samba4", false)) {
504                 printf("SAMBA: large read extension\n");
505                 CHECK_VALUE(io.readx.out.nread, 80000);
506         } else {
507                 CHECK_VALUE(io.readx.out.nread, 0);
508         }
509         CHECK_BUFFER(buf, seed, io.readx.out.nread);
510
511         printf("Trying mincnt > maxcnt\n");
512         memset(buf, 0, maxsize);
513         io.readx.in.offset = 0;
514         io.readx.in.mincnt = 30000;
515         io.readx.in.maxcnt = 20000;
516         status = smb_raw_read(cli->tree, &io);
517         CHECK_STATUS(status, NT_STATUS_OK);
518         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
519         CHECK_VALUE(io.readx.out.compaction_mode, 0);
520         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
521         CHECK_BUFFER(buf, seed, io.readx.out.nread);
522
523         printf("Trying mincnt < maxcnt\n");
524         memset(buf, 0, maxsize);
525         io.readx.in.offset = 0;
526         io.readx.in.mincnt = 20000;
527         io.readx.in.maxcnt = 30000;
528         status = smb_raw_read(cli->tree, &io);
529         CHECK_STATUS(status, NT_STATUS_OK);
530         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
531         CHECK_VALUE(io.readx.out.compaction_mode, 0);
532         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
533         CHECK_BUFFER(buf, seed, io.readx.out.nread);
534
535         if (cli->transport->negotiate.capabilities & CAP_LARGE_READX) {
536                 printf("Trying large readx\n");
537                 io.readx.in.offset = 0;
538                 io.readx.in.mincnt = 0;
539                 io.readx.in.maxcnt = 0x10000 - 1;
540                 status = smb_raw_read(cli->tree, &io);
541                 CHECK_STATUS(status, NT_STATUS_OK);
542                 CHECK_VALUE(io.readx.out.nread, 0xFFFF);
543
544                 io.readx.in.maxcnt = 0x10000;
545                 status = smb_raw_read(cli->tree, &io);
546                 CHECK_STATUS(status, NT_STATUS_OK);
547                 if (torture_setting_bool(tctx, "samba3", false) || 
548                     torture_setting_bool(tctx, "samba4", false)) {
549                         printf("SAMBA: large read extension\n");
550                         CHECK_VALUE(io.readx.out.nread, 0x10000);
551                 } else {
552                         CHECK_VALUE(io.readx.out.nread, 0);
553                 }
554
555                 io.readx.in.maxcnt = 0x10001;
556                 status = smb_raw_read(cli->tree, &io);
557                 CHECK_STATUS(status, NT_STATUS_OK);
558                 if (torture_setting_bool(tctx, "samba3", false) ||
559                     torture_setting_bool(tctx, "samba4", false)) {
560                         printf("SAMBA: large read extension\n");
561                         CHECK_VALUE(io.readx.out.nread, 0x10001);
562                 } else {
563                         CHECK_VALUE(io.readx.out.nread, 0);
564                 }
565         } else {
566                 printf("Server does not support the CAP_LARGE_READX extension\n");
567         }
568
569         printf("Trying locked region\n");
570         cli->session->pid++;
571         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
572                 printf("Failed to lock file at %d\n", __LINE__);
573                 ret = false;
574                 goto done;
575         }
576         cli->session->pid--;
577         memset(buf, 0, maxsize);
578         io.readx.in.offset = 0;
579         io.readx.in.mincnt = 100;
580         io.readx.in.maxcnt = 200;
581         status = smb_raw_read(cli->tree, &io);
582         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);     
583
584         if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
585                 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
586                 goto done;
587         }
588
589         printf("Trying large offset read\n");
590         io.readx.in.offset = ((uint64_t)0x2) << 32;
591         io.readx.in.mincnt = 10;
592         io.readx.in.maxcnt = 10;
593         status = smb_raw_read(cli->tree, &io);
594         CHECK_STATUS(status, NT_STATUS_OK);
595         CHECK_VALUE(io.readx.out.nread, 0);
596
597         if (NT_STATUS_IS_ERR(smbcli_lock64(cli->tree, fnum, io.readx.in.offset, 1, 0, WRITE_LOCK))) {
598                 printf("Failed to lock file at %d\n", __LINE__);
599                 ret = false;
600                 goto done;
601         }
602
603         status = smb_raw_read(cli->tree, &io);
604         CHECK_STATUS(status, NT_STATUS_OK);
605         CHECK_VALUE(io.readx.out.nread, 0);
606
607 done:
608         smbcli_close(cli->tree, fnum);
609         smbcli_deltree(cli->tree, BASEDIR);
610         return ret;
611 }
612
613
614 /*
615   test readbraw ops
616 */
617 static bool test_readbraw(struct torture_context *tctx, 
618                                                   struct smbcli_state *cli)
619 {
620         union smb_read io;
621         NTSTATUS status;
622         bool ret = true;
623         int fnum;
624         uint8_t *buf;
625         const int maxsize = 90000;
626         const char *fname = BASEDIR "\\test.txt";
627         const char *test_data = "TEST DATA";
628         uint_t seed = time(NULL);
629
630         if (!cli->transport->negotiate.readbraw_supported) {
631                 printf("Server does not support readbraw - skipping\n");
632                 return true;
633         }
634
635         buf = talloc_zero_array(tctx, uint8_t, maxsize);
636
637         if (!torture_setup_dir(cli, BASEDIR)) {
638                 return false;
639         }
640
641         printf("Testing RAW_READ_READBRAW\n");
642         
643         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
644         if (fnum == -1) {
645                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
646                 ret = false;
647                 goto done;
648         }
649
650         printf("Trying empty file read\n");
651         io.generic.level = RAW_READ_READBRAW;
652         io.readbraw.in.file.fnum = fnum;
653         io.readbraw.in.mincnt = 1;
654         io.readbraw.in.maxcnt = 1;
655         io.readbraw.in.offset = 0;
656         io.readbraw.in.timeout = 0;
657         io.readbraw.out.data = buf;
658         status = smb_raw_read(cli->tree, &io);
659
660         CHECK_STATUS(status, NT_STATUS_OK);
661         CHECK_VALUE(io.readbraw.out.nread, 0);
662
663         printf("Trying zero file read\n");
664         io.readbraw.in.mincnt = 0;
665         io.readbraw.in.maxcnt = 0;
666         status = smb_raw_read(cli->tree, &io);
667         CHECK_STATUS(status, NT_STATUS_OK);
668         CHECK_VALUE(io.readbraw.out.nread, 0);
669
670         printf("Trying bad fnum\n");
671         io.readbraw.in.file.fnum = fnum+1;
672         status = smb_raw_read(cli->tree, &io);
673         CHECK_STATUS(status, NT_STATUS_OK);
674         CHECK_VALUE(io.readbraw.out.nread, 0);
675         io.readbraw.in.file.fnum = fnum;
676
677         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
678
679         printf("Trying small read\n");
680         io.readbraw.in.file.fnum = fnum;
681         io.readbraw.in.offset = 0;
682         io.readbraw.in.mincnt = strlen(test_data);
683         io.readbraw.in.maxcnt = strlen(test_data);
684         status = smb_raw_read(cli->tree, &io);
685         CHECK_STATUS(status, NT_STATUS_OK);
686         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data));
687         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
688                 ret = false;
689                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
690                 goto done;
691         }
692
693         printf("Trying short read\n");
694         io.readbraw.in.offset = 1;
695         io.readbraw.in.mincnt = strlen(test_data);
696         io.readbraw.in.maxcnt = strlen(test_data);
697         status = smb_raw_read(cli->tree, &io);
698         CHECK_STATUS(status, NT_STATUS_OK);
699         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data)-1);
700         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
701                 ret = false;
702                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
703                 goto done;
704         }
705
706         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
707                 printf("Trying max offset\n");
708                 io.readbraw.in.offset = ~0;
709                 io.readbraw.in.mincnt = strlen(test_data);
710                 io.readbraw.in.maxcnt = strlen(test_data);
711                 status = smb_raw_read(cli->tree, &io);
712                 CHECK_STATUS(status, NT_STATUS_OK);
713                 CHECK_VALUE(io.readbraw.out.nread, 0);
714         }
715
716         setup_buffer(buf, seed, maxsize);
717         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
718         memset(buf, 0, maxsize);
719
720         printf("Trying large read\n");
721         io.readbraw.in.offset = 0;
722         io.readbraw.in.mincnt = ~0;
723         io.readbraw.in.maxcnt = ~0;
724         status = smb_raw_read(cli->tree, &io);
725         CHECK_STATUS(status, NT_STATUS_OK);
726         CHECK_VALUE(io.readbraw.out.nread, 0xFFFF);
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 = 30000;
733         io.readbraw.in.maxcnt = 20000;
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 mincnt < maxcnt\n");
740         memset(buf, 0, maxsize);
741         io.readbraw.in.offset = 0;
742         io.readbraw.in.mincnt = 20000;
743         io.readbraw.in.maxcnt = 30000;
744         status = smb_raw_read(cli->tree, &io);
745         CHECK_STATUS(status, NT_STATUS_OK);
746         CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
747         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
748
749         printf("Trying locked region\n");
750         cli->session->pid++;
751         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
752                 printf("Failed to lock file at %d\n", __LINE__);
753                 ret = false;
754                 goto done;
755         }
756         cli->session->pid--;
757         memset(buf, 0, maxsize);
758         io.readbraw.in.offset = 0;
759         io.readbraw.in.mincnt = 100;
760         io.readbraw.in.maxcnt = 200;
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         printf("Trying locked region with timeout\n");
766         memset(buf, 0, maxsize);
767         io.readbraw.in.offset = 0;
768         io.readbraw.in.mincnt = 100;
769         io.readbraw.in.maxcnt = 200;
770         io.readbraw.in.timeout = 10000;
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         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
776                 printf("Trying large offset read\n");
777                 io.readbraw.in.offset = ((uint64_t)0x2) << 32;
778                 io.readbraw.in.mincnt = 10;
779                 io.readbraw.in.maxcnt = 10;
780                 io.readbraw.in.timeout = 0;
781                 status = smb_raw_read(cli->tree, &io);
782                 CHECK_STATUS(status, NT_STATUS_OK);
783                 CHECK_VALUE(io.readbraw.out.nread, 0);
784         }
785
786 done:
787         smbcli_close(cli->tree, fnum);
788         smbcli_deltree(cli->tree, BASEDIR);
789         return ret;
790 }
791
792 /*
793   test read for execute
794 */
795 static bool test_read_for_execute(struct torture_context *tctx, 
796                                                                   struct smbcli_state *cli)
797 {
798         union smb_open op;
799         union smb_write wr;
800         union smb_read rd;
801         NTSTATUS status;
802         bool ret = true;
803         int fnum=0;
804         uint8_t *buf;
805         const int maxsize = 900;
806         const char *fname = BASEDIR "\\test.txt";
807         const uint8_t data[] = "TEST DATA";
808
809         buf = talloc_zero_array(tctx, uint8_t, maxsize);
810
811         if (!torture_setup_dir(cli, BASEDIR)) {
812                 return false;
813         }
814
815         printf("Testing RAW_READ_READX with read_for_execute\n");
816
817         op.generic.level = RAW_OPEN_NTCREATEX;
818         op.ntcreatex.in.root_fid = 0;
819         op.ntcreatex.in.flags = 0;
820         op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
821         op.ntcreatex.in.create_options = 0;
822         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
823         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
824         op.ntcreatex.in.alloc_size = 0;
825         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
826         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
827         op.ntcreatex.in.security_flags = 0;
828         op.ntcreatex.in.fname = fname;
829         status = smb_raw_open(cli->tree, tctx, &op);
830         CHECK_STATUS(status, NT_STATUS_OK);
831         fnum = op.ntcreatex.out.file.fnum;
832
833         wr.generic.level = RAW_WRITE_WRITEX;
834         wr.writex.in.file.fnum = fnum;
835         wr.writex.in.offset = 0;
836         wr.writex.in.wmode = 0;
837         wr.writex.in.remaining = 0;
838         wr.writex.in.count = ARRAY_SIZE(data);
839         wr.writex.in.data = data;
840         status = smb_raw_write(cli->tree, &wr);
841         CHECK_STATUS(status, NT_STATUS_OK);
842         CHECK_VALUE(wr.writex.out.nwritten, ARRAY_SIZE(data));
843
844         status = smbcli_close(cli->tree, fnum);
845         CHECK_STATUS(status, NT_STATUS_OK);
846
847         printf("open file with SEC_FILE_EXECUTE\n");
848         op.generic.level = RAW_OPEN_NTCREATEX;
849         op.ntcreatex.in.root_fid = 0;
850         op.ntcreatex.in.flags = 0;
851         op.ntcreatex.in.access_mask = SEC_FILE_EXECUTE;
852         op.ntcreatex.in.create_options = 0;
853         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
854         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
855         op.ntcreatex.in.alloc_size = 0;
856         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
857         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
858         op.ntcreatex.in.security_flags = 0;
859         op.ntcreatex.in.fname = fname;
860         status = smb_raw_open(cli->tree, tctx, &op);
861         CHECK_STATUS(status, NT_STATUS_OK);
862         fnum = op.ntcreatex.out.file.fnum;
863
864         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
865         rd.generic.level = RAW_READ_READX;
866         rd.readx.in.file.fnum = fnum;
867         rd.readx.in.mincnt = 0;
868         rd.readx.in.maxcnt = maxsize;
869         rd.readx.in.offset = 0;
870         rd.readx.in.remaining = 0;
871         rd.readx.in.read_for_execute = true;
872         rd.readx.out.data = buf;
873         status = smb_raw_read(cli->tree, &rd);
874         CHECK_STATUS(status, NT_STATUS_OK);
875         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
876         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
877         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
878
879         printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
880         rd.generic.level = RAW_READ_READX;
881         rd.readx.in.file.fnum = fnum;
882         rd.readx.in.mincnt = 0;
883         rd.readx.in.maxcnt = maxsize;
884         rd.readx.in.offset = 0;
885         rd.readx.in.remaining = 0;
886         rd.readx.in.read_for_execute = false;
887         rd.readx.out.data = buf;
888         status = smb_raw_read(cli->tree, &rd);
889         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
890
891         status = smbcli_close(cli->tree, fnum);
892         CHECK_STATUS(status, NT_STATUS_OK);
893
894         printf("open file with SEC_FILE_READ_DATA\n");
895         op.generic.level = RAW_OPEN_NTCREATEX;
896         op.ntcreatex.in.root_fid = 0;
897         op.ntcreatex.in.flags = 0;
898         op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
899         op.ntcreatex.in.create_options = 0;
900         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
901         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
902         op.ntcreatex.in.alloc_size = 0;
903         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
904         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
905         op.ntcreatex.in.security_flags = 0;
906         op.ntcreatex.in.fname = fname;
907         status = smb_raw_open(cli->tree, tctx, &op);
908         CHECK_STATUS(status, NT_STATUS_OK);
909         fnum = op.ntcreatex.out.file.fnum;
910
911         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
912         rd.generic.level = RAW_READ_READX;
913         rd.readx.in.file.fnum = fnum;
914         rd.readx.in.mincnt = 0;
915         rd.readx.in.maxcnt = maxsize;
916         rd.readx.in.offset = 0;
917         rd.readx.in.remaining = 0;
918         rd.readx.in.read_for_execute = true;
919         rd.readx.out.data = buf;
920         status = smb_raw_read(cli->tree, &rd);
921         CHECK_STATUS(status, NT_STATUS_OK);
922         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
923         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
924         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
925
926         printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
927         rd.generic.level = RAW_READ_READX;
928         rd.readx.in.file.fnum = fnum;
929         rd.readx.in.mincnt = 0;
930         rd.readx.in.maxcnt = maxsize;
931         rd.readx.in.offset = 0;
932         rd.readx.in.remaining = 0;
933         rd.readx.in.read_for_execute = false;
934         rd.readx.out.data = buf;
935         status = smb_raw_read(cli->tree, &rd);
936         CHECK_STATUS(status, NT_STATUS_OK);
937         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
938         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
939         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
940
941 done:
942         smbcli_close(cli->tree, fnum);
943         smbcli_deltree(cli->tree, BASEDIR);
944         return ret;
945 }
946
947
948 /* 
949    basic testing of read calls
950 */
951 struct torture_suite *torture_raw_read(TALLOC_CTX *mem_ctx)
952 {
953         struct torture_suite *suite = torture_suite_create(mem_ctx, "READ");
954
955         torture_suite_add_1smb_test(suite, "read", test_read);
956         torture_suite_add_1smb_test(suite, "readx", test_readx);
957         torture_suite_add_1smb_test(suite, "lockread", test_lockread);
958         torture_suite_add_1smb_test(suite, "readbraw", test_readbraw);
959         torture_suite_add_1smb_test(suite, "read for execute", 
960                                                                 test_read_for_execute);
961
962         return suite;
963 }