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