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