bde360ba65ada739c7138c07c950d17c6319c5d3
[metze/samba/wip.git] / source4 / torture / raw / read.c
1 /* 
2    Unix SMB/CIFS implementation.
3    test suite for various read operations
4    Copyright (C) Andrew Tridgell 2003
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 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, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22 #include "torture/torture.h"
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.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 smbcli_state *cli, TALLOC_CTX *mem_ctx)
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_size(mem_ctx, 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 smbcli_state *cli, TALLOC_CTX *mem_ctx)
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_size(mem_ctx, 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 smbcli_state *cli, TALLOC_CTX *mem_ctx)
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_size(mem_ctx, 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 smbcli_state *cli, TALLOC_CTX *mem_ctx)
595 {
596         union smb_read io;
597         NTSTATUS status;
598         BOOL ret = True;
599         int fnum;
600         uint8_t *buf;
601         const int maxsize = 90000;
602         const char *fname = BASEDIR "\\test.txt";
603         const char *test_data = "TEST DATA";
604         uint_t seed = time(NULL);
605
606         buf = talloc_zero_size(mem_ctx, maxsize);
607
608         if (!torture_setup_dir(cli, BASEDIR)) {
609                 return False;
610         }
611
612         printf("Testing RAW_READ_READBRAW\n");
613         
614         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
615         if (fnum == -1) {
616                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
617                 ret = False;
618                 goto done;
619         }
620
621         printf("Trying empty file read\n");
622         io.generic.level = RAW_READ_READBRAW;
623         io.readbraw.in.file.fnum = fnum;
624         io.readbraw.in.mincnt = 1;
625         io.readbraw.in.maxcnt = 1;
626         io.readbraw.in.offset = 0;
627         io.readbraw.in.timeout = 0;
628         io.readbraw.out.data = buf;
629         status = smb_raw_read(cli->tree, &io);
630
631         CHECK_STATUS(status, NT_STATUS_OK);
632         CHECK_VALUE(io.readbraw.out.nread, 0);
633
634         printf("Trying zero file read\n");
635         io.readbraw.in.mincnt = 0;
636         io.readbraw.in.maxcnt = 0;
637         status = smb_raw_read(cli->tree, &io);
638         CHECK_STATUS(status, NT_STATUS_OK);
639         CHECK_VALUE(io.readbraw.out.nread, 0);
640
641         printf("Trying bad fnum\n");
642         io.readbraw.in.file.fnum = fnum+1;
643         status = smb_raw_read(cli->tree, &io);
644         CHECK_STATUS(status, NT_STATUS_OK);
645         CHECK_VALUE(io.readbraw.out.nread, 0);
646         io.readbraw.in.file.fnum = fnum;
647
648         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
649
650         printf("Trying small read\n");
651         io.readbraw.in.file.fnum = fnum;
652         io.readbraw.in.offset = 0;
653         io.readbraw.in.mincnt = strlen(test_data);
654         io.readbraw.in.maxcnt = strlen(test_data);
655         status = smb_raw_read(cli->tree, &io);
656         CHECK_STATUS(status, NT_STATUS_OK);
657         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data));
658         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
659                 ret = False;
660                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
661                 goto done;
662         }
663
664         printf("Trying short read\n");
665         io.readbraw.in.offset = 1;
666         io.readbraw.in.mincnt = strlen(test_data);
667         io.readbraw.in.maxcnt = strlen(test_data);
668         status = smb_raw_read(cli->tree, &io);
669         CHECK_STATUS(status, NT_STATUS_OK);
670         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data)-1);
671         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
672                 ret = False;
673                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
674                 goto done;
675         }
676
677         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
678                 printf("Trying max offset\n");
679                 io.readbraw.in.offset = ~0;
680                 io.readbraw.in.mincnt = strlen(test_data);
681                 io.readbraw.in.maxcnt = strlen(test_data);
682                 status = smb_raw_read(cli->tree, &io);
683                 CHECK_STATUS(status, NT_STATUS_OK);
684                 CHECK_VALUE(io.readbraw.out.nread, 0);
685         }
686
687         setup_buffer(buf, seed, maxsize);
688         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
689         memset(buf, 0, maxsize);
690
691         printf("Trying large read\n");
692         io.readbraw.in.offset = 0;
693         io.readbraw.in.mincnt = ~0;
694         io.readbraw.in.maxcnt = ~0;
695         status = smb_raw_read(cli->tree, &io);
696         CHECK_STATUS(status, NT_STATUS_OK);
697         CHECK_VALUE(io.readbraw.out.nread, 0xFFFF);
698         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
699
700         printf("Trying mincnt > maxcnt\n");
701         memset(buf, 0, maxsize);
702         io.readbraw.in.offset = 0;
703         io.readbraw.in.mincnt = 30000;
704         io.readbraw.in.maxcnt = 20000;
705         status = smb_raw_read(cli->tree, &io);
706         CHECK_STATUS(status, NT_STATUS_OK);
707         CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
708         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
709
710         printf("Trying mincnt < maxcnt\n");
711         memset(buf, 0, maxsize);
712         io.readbraw.in.offset = 0;
713         io.readbraw.in.mincnt = 20000;
714         io.readbraw.in.maxcnt = 30000;
715         status = smb_raw_read(cli->tree, &io);
716         CHECK_STATUS(status, NT_STATUS_OK);
717         CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
718         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
719
720         printf("Trying locked region\n");
721         cli->session->pid++;
722         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
723                 printf("Failed to lock file at %d\n", __LINE__);
724                 ret = False;
725                 goto done;
726         }
727         cli->session->pid--;
728         memset(buf, 0, maxsize);
729         io.readbraw.in.offset = 0;
730         io.readbraw.in.mincnt = 100;
731         io.readbraw.in.maxcnt = 200;
732         status = smb_raw_read(cli->tree, &io);
733         CHECK_STATUS(status, NT_STATUS_OK);
734         CHECK_VALUE(io.readbraw.out.nread, 0);
735
736         printf("Trying locked region with timeout\n");
737         memset(buf, 0, maxsize);
738         io.readbraw.in.offset = 0;
739         io.readbraw.in.mincnt = 100;
740         io.readbraw.in.maxcnt = 200;
741         io.readbraw.in.timeout = 10000;
742         status = smb_raw_read(cli->tree, &io);
743         CHECK_STATUS(status, NT_STATUS_OK);
744         CHECK_VALUE(io.readbraw.out.nread, 0);
745
746         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
747                 printf("Trying large offset read\n");
748                 io.readbraw.in.offset = ((uint64_t)0x2) << 32;
749                 io.readbraw.in.mincnt = 10;
750                 io.readbraw.in.maxcnt = 10;
751                 io.readbraw.in.timeout = 0;
752                 status = smb_raw_read(cli->tree, &io);
753                 CHECK_STATUS(status, NT_STATUS_OK);
754                 CHECK_VALUE(io.readbraw.out.nread, 0);
755         }
756
757 done:
758         smbcli_close(cli->tree, fnum);
759         smbcli_deltree(cli->tree, BASEDIR);
760         return ret;
761 }
762
763 /*
764   test read for execute
765 */
766 static BOOL test_read_for_execute(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
767 {
768         union smb_open op;
769         union smb_write wr;
770         union smb_read rd;
771         NTSTATUS status;
772         BOOL ret = True;
773         int fnum=0;
774         uint8_t *buf;
775         const int maxsize = 900;
776         const char *fname = BASEDIR "\\test.txt";
777         const uint8_t data[] = "TEST DATA";
778
779         buf = talloc_zero_size(mem_ctx, maxsize);
780
781         if (!torture_setup_dir(cli, BASEDIR)) {
782                 return False;
783         }
784
785         printf("Testing RAW_READ_READX with read_for_execute\n");
786
787         op.generic.level = RAW_OPEN_NTCREATEX;
788         op.ntcreatex.in.root_fid = 0;
789         op.ntcreatex.in.flags = 0;
790         op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
791         op.ntcreatex.in.create_options = 0;
792         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
793         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
794         op.ntcreatex.in.alloc_size = 0;
795         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
796         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
797         op.ntcreatex.in.security_flags = 0;
798         op.ntcreatex.in.fname = fname;
799         status = smb_raw_open(cli->tree, mem_ctx, &op);
800         CHECK_STATUS(status, NT_STATUS_OK);
801         fnum = op.ntcreatex.out.file.fnum;
802
803         wr.generic.level = RAW_WRITE_WRITEX;
804         wr.writex.in.file.fnum = fnum;
805         wr.writex.in.offset = 0;
806         wr.writex.in.wmode = 0;
807         wr.writex.in.remaining = 0;
808         wr.writex.in.count = ARRAY_SIZE(data);
809         wr.writex.in.data = data;
810         status = smb_raw_write(cli->tree, &wr);
811         CHECK_STATUS(status, NT_STATUS_OK);
812         CHECK_VALUE(wr.writex.out.nwritten, ARRAY_SIZE(data));
813
814         status = smbcli_close(cli->tree, fnum);
815         CHECK_STATUS(status, NT_STATUS_OK);
816
817         printf("open file with SEC_FILE_EXECUTE\n");
818         op.generic.level = RAW_OPEN_NTCREATEX;
819         op.ntcreatex.in.root_fid = 0;
820         op.ntcreatex.in.flags = 0;
821         op.ntcreatex.in.access_mask = SEC_FILE_EXECUTE;
822         op.ntcreatex.in.create_options = 0;
823         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
824         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
825         op.ntcreatex.in.alloc_size = 0;
826         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
827         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
828         op.ntcreatex.in.security_flags = 0;
829         op.ntcreatex.in.fname = fname;
830         status = smb_raw_open(cli->tree, mem_ctx, &op);
831         CHECK_STATUS(status, NT_STATUS_OK);
832         fnum = op.ntcreatex.out.file.fnum;
833
834         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
835         rd.generic.level = RAW_READ_READX;
836         rd.readx.in.file.fnum = fnum;
837         rd.readx.in.mincnt = 0;
838         rd.readx.in.maxcnt = maxsize;
839         rd.readx.in.offset = 0;
840         rd.readx.in.remaining = 0;
841         rd.readx.in.read_for_execute = True;
842         rd.readx.out.data = buf;
843         status = smb_raw_read(cli->tree, &rd);
844         CHECK_STATUS(status, NT_STATUS_OK);
845         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
846         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
847         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
848
849         printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
850         rd.generic.level = RAW_READ_READX;
851         rd.readx.in.file.fnum = fnum;
852         rd.readx.in.mincnt = 0;
853         rd.readx.in.maxcnt = maxsize;
854         rd.readx.in.offset = 0;
855         rd.readx.in.remaining = 0;
856         rd.readx.in.read_for_execute = False;
857         rd.readx.out.data = buf;
858         status = smb_raw_read(cli->tree, &rd);
859         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
860
861         status = smbcli_close(cli->tree, fnum);
862         CHECK_STATUS(status, NT_STATUS_OK);
863
864         printf("open file with SEC_FILE_READ_DATA\n");
865         op.generic.level = RAW_OPEN_NTCREATEX;
866         op.ntcreatex.in.root_fid = 0;
867         op.ntcreatex.in.flags = 0;
868         op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
869         op.ntcreatex.in.create_options = 0;
870         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
871         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
872         op.ntcreatex.in.alloc_size = 0;
873         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
874         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
875         op.ntcreatex.in.security_flags = 0;
876         op.ntcreatex.in.fname = fname;
877         status = smb_raw_open(cli->tree, mem_ctx, &op);
878         CHECK_STATUS(status, NT_STATUS_OK);
879         fnum = op.ntcreatex.out.file.fnum;
880
881         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
882         rd.generic.level = RAW_READ_READX;
883         rd.readx.in.file.fnum = fnum;
884         rd.readx.in.mincnt = 0;
885         rd.readx.in.maxcnt = maxsize;
886         rd.readx.in.offset = 0;
887         rd.readx.in.remaining = 0;
888         rd.readx.in.read_for_execute = True;
889         rd.readx.out.data = buf;
890         status = smb_raw_read(cli->tree, &rd);
891         CHECK_STATUS(status, NT_STATUS_OK);
892         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
893         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
894         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
895
896         printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
897         rd.generic.level = RAW_READ_READX;
898         rd.readx.in.file.fnum = fnum;
899         rd.readx.in.mincnt = 0;
900         rd.readx.in.maxcnt = maxsize;
901         rd.readx.in.offset = 0;
902         rd.readx.in.remaining = 0;
903         rd.readx.in.read_for_execute = False;
904         rd.readx.out.data = buf;
905         status = smb_raw_read(cli->tree, &rd);
906         CHECK_STATUS(status, NT_STATUS_OK);
907         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
908         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
909         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
910
911 done:
912         smbcli_close(cli->tree, fnum);
913         smbcli_deltree(cli->tree, BASEDIR);
914         return ret;
915 }
916
917
918 /* 
919    basic testing of read calls
920 */
921 BOOL torture_raw_read(struct torture_context *torture)
922 {
923         struct smbcli_state *cli;
924         BOOL ret = True;
925         TALLOC_CTX *mem_ctx;
926
927         if (!torture_open_connection(&cli, 0)) {
928                 return False;
929         }
930
931         mem_ctx = talloc_init("torture_raw_read");
932
933         ret &= test_read(cli, mem_ctx);
934         ret &= test_readx(cli, mem_ctx);
935         ret &= test_lockread(cli, mem_ctx);
936         ret &= test_readbraw(cli, mem_ctx);
937         ret &= test_read_for_execute(cli, mem_ctx);
938
939         torture_close_connection(cli);
940         talloc_free(mem_ctx);
941         return ret;
942 }