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