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