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