r23792: convert Samba4 to GPLv3
[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 smbcli_state *cli, TALLOC_CTX *mem_ctx)
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_size(mem_ctx, 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 smbcli_state *cli, TALLOC_CTX *mem_ctx)
211 {
212         union smb_read io;
213         NTSTATUS status;
214         BOOL ret = True;
215         int fnum;
216         uint8_t *buf;
217         const int maxsize = 90000;
218         const char *fname = BASEDIR "\\test.txt";
219         const char *test_data = "TEST DATA";
220         uint_t seed = time(NULL);
221
222         buf = talloc_zero_size(mem_ctx, maxsize);
223
224         if (!torture_setup_dir(cli, BASEDIR)) {
225                 return False;
226         }
227
228         printf("Testing RAW_READ_LOCKREAD\n");
229         io.generic.level = RAW_READ_LOCKREAD;
230         
231         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
232         if (fnum == -1) {
233                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
234                 ret = False;
235                 goto done;
236         }
237
238         printf("Trying empty file read\n");
239         io.lockread.in.file.fnum = fnum;
240         io.lockread.in.count = 1;
241         io.lockread.in.offset = 1;
242         io.lockread.in.remaining = 0;
243         io.lockread.out.data = buf;
244         status = smb_raw_read(cli->tree, &io);
245
246         CHECK_STATUS(status, NT_STATUS_OK);
247         CHECK_VALUE(io.lockread.out.nread, 0);
248
249         status = smb_raw_read(cli->tree, &io);
250         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
251
252         status = smb_raw_read(cli->tree, &io);
253         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
254
255         printf("Trying zero file read\n");
256         io.lockread.in.count = 0;
257         status = smb_raw_read(cli->tree, &io);
258         CHECK_STATUS(status, NT_STATUS_OK);
259
260         smbcli_unlock(cli->tree, fnum, 1, 1);
261
262         printf("Trying bad fnum\n");
263         io.lockread.in.file.fnum = fnum+1;
264         status = smb_raw_read(cli->tree, &io);
265         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
266         io.lockread.in.file.fnum = fnum;
267
268         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
269
270         printf("Trying small read\n");
271         io.lockread.in.file.fnum = fnum;
272         io.lockread.in.offset = 0;
273         io.lockread.in.remaining = 0;
274         io.lockread.in.count = strlen(test_data);
275         status = smb_raw_read(cli->tree, &io);
276         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
277
278         smbcli_unlock(cli->tree, fnum, 1, 0);
279
280         status = smb_raw_read(cli->tree, &io);
281         CHECK_STATUS(status, NT_STATUS_OK);
282         CHECK_VALUE(io.lockread.out.nread, strlen(test_data));
283         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
284                 ret = False;
285                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
286                 goto done;
287         }
288
289         printf("Trying short read\n");
290         io.lockread.in.offset = 1;
291         io.lockread.in.count = strlen(test_data);
292         status = smb_raw_read(cli->tree, &io);
293         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
294         smbcli_unlock(cli->tree, fnum, 0, strlen(test_data));
295         status = smb_raw_read(cli->tree, &io);
296         CHECK_STATUS(status, NT_STATUS_OK);
297
298         CHECK_VALUE(io.lockread.out.nread, strlen(test_data)-1);
299         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
300                 ret = False;
301                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
302                 goto done;
303         }
304
305         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
306                 printf("Trying max offset\n");
307                 io.lockread.in.offset = ~0;
308                 io.lockread.in.count = strlen(test_data);
309                 status = smb_raw_read(cli->tree, &io);
310                 CHECK_STATUS(status, NT_STATUS_OK);
311                 CHECK_VALUE(io.lockread.out.nread, 0);
312         }
313
314         setup_buffer(buf, seed, maxsize);
315         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
316         memset(buf, 0, maxsize);
317
318         printf("Trying large read\n");
319         io.lockread.in.offset = 0;
320         io.lockread.in.count = ~0;
321         status = smb_raw_read(cli->tree, &io);
322         CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
323         smbcli_unlock(cli->tree, fnum, 1, strlen(test_data));
324         status = smb_raw_read(cli->tree, &io);
325         CHECK_STATUS(status, NT_STATUS_OK);
326         CHECK_BUFFER(buf, seed, io.lockread.out.nread);
327         smbcli_unlock(cli->tree, fnum, 0, 0xFFFF);
328
329
330         printf("Trying locked region\n");
331         cli->session->pid++;
332         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
333                 printf("Failed to lock file at %d\n", __LINE__);
334                 ret = False;
335                 goto done;
336         }
337         cli->session->pid--;
338         memset(buf, 0, maxsize);
339         io.lockread.in.offset = 0;
340         io.lockread.in.count = ~0;
341         status = smb_raw_read(cli->tree, &io);
342         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
343         
344
345 done:
346         smbcli_close(cli->tree, fnum);
347         smbcli_deltree(cli->tree, BASEDIR);
348         return ret;
349 }
350
351
352 /*
353   test readx ops
354 */
355 static BOOL test_readx(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
356 {
357         union smb_read io;
358         NTSTATUS status;
359         BOOL ret = True;
360         int fnum;
361         uint8_t *buf;
362         const int maxsize = 90000;
363         const char *fname = BASEDIR "\\test.txt";
364         const char *test_data = "TEST DATA";
365         uint_t seed = time(NULL);
366
367         buf = talloc_zero_size(mem_ctx, maxsize);
368
369         if (!torture_setup_dir(cli, BASEDIR)) {
370                 return False;
371         }
372
373         printf("Testing RAW_READ_READX\n");
374         
375         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
376         if (fnum == -1) {
377                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
378                 ret = False;
379                 goto done;
380         }
381
382         printf("Trying empty file read\n");
383         io.generic.level = RAW_READ_READX;
384         io.readx.in.file.fnum = fnum;
385         io.readx.in.mincnt = 1;
386         io.readx.in.maxcnt = 1;
387         io.readx.in.offset = 0;
388         io.readx.in.remaining = 0;
389         io.readx.in.read_for_execute = False;
390         io.readx.out.data = buf;
391         status = smb_raw_read(cli->tree, &io);
392
393         CHECK_STATUS(status, NT_STATUS_OK);
394         CHECK_VALUE(io.readx.out.nread, 0);
395         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
396         CHECK_VALUE(io.readx.out.compaction_mode, 0);
397
398         printf("Trying zero file read\n");
399         io.readx.in.mincnt = 0;
400         io.readx.in.maxcnt = 0;
401         status = smb_raw_read(cli->tree, &io);
402         CHECK_STATUS(status, NT_STATUS_OK);
403         CHECK_VALUE(io.readx.out.nread, 0);
404         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
405         CHECK_VALUE(io.readx.out.compaction_mode, 0);
406
407         printf("Trying bad fnum\n");
408         io.readx.in.file.fnum = fnum+1;
409         status = smb_raw_read(cli->tree, &io);
410         CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
411         io.readx.in.file.fnum = fnum;
412
413         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
414
415         printf("Trying small read\n");
416         io.readx.in.file.fnum = fnum;
417         io.readx.in.offset = 0;
418         io.readx.in.remaining = 0;
419         io.readx.in.read_for_execute = False;
420         io.readx.in.mincnt = strlen(test_data);
421         io.readx.in.maxcnt = strlen(test_data);
422         status = smb_raw_read(cli->tree, &io);
423         CHECK_STATUS(status, NT_STATUS_OK);
424         CHECK_VALUE(io.readx.out.nread, strlen(test_data));
425         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
426         CHECK_VALUE(io.readx.out.compaction_mode, 0);
427         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
428                 ret = False;
429                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
430                 goto done;
431         }
432
433         printf("Trying short read\n");
434         io.readx.in.offset = 1;
435         io.readx.in.mincnt = strlen(test_data);
436         io.readx.in.maxcnt = strlen(test_data);
437         status = smb_raw_read(cli->tree, &io);
438         CHECK_STATUS(status, NT_STATUS_OK);
439         CHECK_VALUE(io.readx.out.nread, strlen(test_data)-1);
440         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
441         CHECK_VALUE(io.readx.out.compaction_mode, 0);
442         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
443                 ret = False;
444                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
445                 goto done;
446         }
447
448         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
449                 printf("Trying max offset\n");
450                 io.readx.in.offset = 0xffffffff;
451                 io.readx.in.mincnt = strlen(test_data);
452                 io.readx.in.maxcnt = strlen(test_data);
453                 status = smb_raw_read(cli->tree, &io);
454                 CHECK_STATUS(status, NT_STATUS_OK);
455                 CHECK_VALUE(io.readx.out.nread, 0);
456                 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
457                 CHECK_VALUE(io.readx.out.compaction_mode, 0);
458         }
459
460         setup_buffer(buf, seed, maxsize);
461         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
462         memset(buf, 0, maxsize);
463
464         printf("Trying large read\n");
465         io.readx.in.offset = 0;
466         io.readx.in.mincnt = 0xFFFF;
467         io.readx.in.maxcnt = 0xFFFF;
468         status = smb_raw_read(cli->tree, &io);
469         CHECK_STATUS(status, NT_STATUS_OK);
470         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
471         CHECK_VALUE(io.readx.out.compaction_mode, 0);
472         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
473         CHECK_BUFFER(buf, seed, io.readx.out.nread);
474
475         printf("Trying extra large read\n");
476         io.readx.in.offset = 0;
477         io.readx.in.mincnt = 100;
478         io.readx.in.maxcnt = 80000;
479         status = smb_raw_read(cli->tree, &io);
480         CHECK_STATUS(status, NT_STATUS_OK);
481         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
482         CHECK_VALUE(io.readx.out.compaction_mode, 0);
483         if (lp_parm_bool(-1, "torture", "samba3", False)) {
484                 printf("SAMBA3: large read extension\n");
485                 CHECK_VALUE(io.readx.out.nread, 80000);
486         } else {
487                 CHECK_VALUE(io.readx.out.nread, 0);
488         }
489         CHECK_BUFFER(buf, seed, io.readx.out.nread);
490
491         printf("Trying mincnt > maxcnt\n");
492         memset(buf, 0, maxsize);
493         io.readx.in.offset = 0;
494         io.readx.in.mincnt = 30000;
495         io.readx.in.maxcnt = 20000;
496         status = smb_raw_read(cli->tree, &io);
497         CHECK_STATUS(status, NT_STATUS_OK);
498         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
499         CHECK_VALUE(io.readx.out.compaction_mode, 0);
500         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
501         CHECK_BUFFER(buf, seed, io.readx.out.nread);
502
503         printf("Trying mincnt < maxcnt\n");
504         memset(buf, 0, maxsize);
505         io.readx.in.offset = 0;
506         io.readx.in.mincnt = 20000;
507         io.readx.in.maxcnt = 30000;
508         status = smb_raw_read(cli->tree, &io);
509         CHECK_STATUS(status, NT_STATUS_OK);
510         CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
511         CHECK_VALUE(io.readx.out.compaction_mode, 0);
512         CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
513         CHECK_BUFFER(buf, seed, io.readx.out.nread);
514
515         if (cli->transport->negotiate.capabilities & CAP_LARGE_READX) {
516                 printf("Trying large readx\n");
517                 io.readx.in.offset = 0;
518                 io.readx.in.mincnt = 0;
519                 io.readx.in.maxcnt = 0x10000 - 1;
520                 status = smb_raw_read(cli->tree, &io);
521                 CHECK_STATUS(status, NT_STATUS_OK);
522                 CHECK_VALUE(io.readx.out.nread, 0xFFFF);
523
524                 io.readx.in.maxcnt = 0x10000;
525                 status = smb_raw_read(cli->tree, &io);
526                 CHECK_STATUS(status, NT_STATUS_OK);
527                 if (lp_parm_bool(-1, "torture", "samba3", False)) {
528                         printf("SAMBA3: large read extension\n");
529                         CHECK_VALUE(io.readx.out.nread, 0x10000);
530                 } else {
531                         CHECK_VALUE(io.readx.out.nread, 0);
532                 }
533
534                 io.readx.in.maxcnt = 0x10001;
535                 status = smb_raw_read(cli->tree, &io);
536                 CHECK_STATUS(status, NT_STATUS_OK);
537                 if (lp_parm_bool(-1, "torture", "samba3", False)) {
538                         printf("SAMBA3: large read extension\n");
539                         CHECK_VALUE(io.readx.out.nread, 0x10001);
540                 } else {
541                         CHECK_VALUE(io.readx.out.nread, 0);
542                 }
543         }
544
545         printf("Trying locked region\n");
546         cli->session->pid++;
547         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
548                 printf("Failed to lock file at %d\n", __LINE__);
549                 ret = False;
550                 goto done;
551         }
552         cli->session->pid--;
553         memset(buf, 0, maxsize);
554         io.readx.in.offset = 0;
555         io.readx.in.mincnt = 100;
556         io.readx.in.maxcnt = 200;
557         status = smb_raw_read(cli->tree, &io);
558         CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);     
559
560         if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
561                 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
562                 goto done;
563         }
564
565         printf("Trying large offset read\n");
566         io.readx.in.offset = ((uint64_t)0x2) << 32;
567         io.readx.in.mincnt = 10;
568         io.readx.in.maxcnt = 10;
569         status = smb_raw_read(cli->tree, &io);
570         CHECK_STATUS(status, NT_STATUS_OK);
571         CHECK_VALUE(io.readx.out.nread, 0);
572
573         if (NT_STATUS_IS_ERR(smbcli_lock64(cli->tree, fnum, io.readx.in.offset, 1, 0, WRITE_LOCK))) {
574                 printf("Failed to lock file at %d\n", __LINE__);
575                 ret = False;
576                 goto done;
577         }
578
579         status = smb_raw_read(cli->tree, &io);
580         CHECK_STATUS(status, NT_STATUS_OK);
581         CHECK_VALUE(io.readx.out.nread, 0);
582
583 done:
584         smbcli_close(cli->tree, fnum);
585         smbcli_deltree(cli->tree, BASEDIR);
586         return ret;
587 }
588
589
590 /*
591   test readbraw ops
592 */
593 static BOOL test_readbraw(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
594 {
595         union smb_read io;
596         NTSTATUS status;
597         BOOL ret = True;
598         int fnum;
599         uint8_t *buf;
600         const int maxsize = 90000;
601         const char *fname = BASEDIR "\\test.txt";
602         const char *test_data = "TEST DATA";
603         uint_t seed = time(NULL);
604
605         buf = talloc_zero_size(mem_ctx, maxsize);
606
607         if (!torture_setup_dir(cli, BASEDIR)) {
608                 return False;
609         }
610
611         printf("Testing RAW_READ_READBRAW\n");
612         
613         fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
614         if (fnum == -1) {
615                 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
616                 ret = False;
617                 goto done;
618         }
619
620         printf("Trying empty file read\n");
621         io.generic.level = RAW_READ_READBRAW;
622         io.readbraw.in.file.fnum = fnum;
623         io.readbraw.in.mincnt = 1;
624         io.readbraw.in.maxcnt = 1;
625         io.readbraw.in.offset = 0;
626         io.readbraw.in.timeout = 0;
627         io.readbraw.out.data = buf;
628         status = smb_raw_read(cli->tree, &io);
629
630         CHECK_STATUS(status, NT_STATUS_OK);
631         CHECK_VALUE(io.readbraw.out.nread, 0);
632
633         printf("Trying zero file read\n");
634         io.readbraw.in.mincnt = 0;
635         io.readbraw.in.maxcnt = 0;
636         status = smb_raw_read(cli->tree, &io);
637         CHECK_STATUS(status, NT_STATUS_OK);
638         CHECK_VALUE(io.readbraw.out.nread, 0);
639
640         printf("Trying bad fnum\n");
641         io.readbraw.in.file.fnum = fnum+1;
642         status = smb_raw_read(cli->tree, &io);
643         CHECK_STATUS(status, NT_STATUS_OK);
644         CHECK_VALUE(io.readbraw.out.nread, 0);
645         io.readbraw.in.file.fnum = fnum;
646
647         smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
648
649         printf("Trying small read\n");
650         io.readbraw.in.file.fnum = fnum;
651         io.readbraw.in.offset = 0;
652         io.readbraw.in.mincnt = strlen(test_data);
653         io.readbraw.in.maxcnt = strlen(test_data);
654         status = smb_raw_read(cli->tree, &io);
655         CHECK_STATUS(status, NT_STATUS_OK);
656         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data));
657         if (memcmp(buf, test_data, strlen(test_data)) != 0) {
658                 ret = False;
659                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
660                 goto done;
661         }
662
663         printf("Trying short read\n");
664         io.readbraw.in.offset = 1;
665         io.readbraw.in.mincnt = strlen(test_data);
666         io.readbraw.in.maxcnt = strlen(test_data);
667         status = smb_raw_read(cli->tree, &io);
668         CHECK_STATUS(status, NT_STATUS_OK);
669         CHECK_VALUE(io.readbraw.out.nread, strlen(test_data)-1);
670         if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
671                 ret = False;
672                 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
673                 goto done;
674         }
675
676         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
677                 printf("Trying max offset\n");
678                 io.readbraw.in.offset = ~0;
679                 io.readbraw.in.mincnt = strlen(test_data);
680                 io.readbraw.in.maxcnt = strlen(test_data);
681                 status = smb_raw_read(cli->tree, &io);
682                 CHECK_STATUS(status, NT_STATUS_OK);
683                 CHECK_VALUE(io.readbraw.out.nread, 0);
684         }
685
686         setup_buffer(buf, seed, maxsize);
687         smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
688         memset(buf, 0, maxsize);
689
690         printf("Trying large read\n");
691         io.readbraw.in.offset = 0;
692         io.readbraw.in.mincnt = ~0;
693         io.readbraw.in.maxcnt = ~0;
694         status = smb_raw_read(cli->tree, &io);
695         CHECK_STATUS(status, NT_STATUS_OK);
696         CHECK_VALUE(io.readbraw.out.nread, 0xFFFF);
697         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
698
699         printf("Trying mincnt > maxcnt\n");
700         memset(buf, 0, maxsize);
701         io.readbraw.in.offset = 0;
702         io.readbraw.in.mincnt = 30000;
703         io.readbraw.in.maxcnt = 20000;
704         status = smb_raw_read(cli->tree, &io);
705         CHECK_STATUS(status, NT_STATUS_OK);
706         CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
707         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
708
709         printf("Trying mincnt < maxcnt\n");
710         memset(buf, 0, maxsize);
711         io.readbraw.in.offset = 0;
712         io.readbraw.in.mincnt = 20000;
713         io.readbraw.in.maxcnt = 30000;
714         status = smb_raw_read(cli->tree, &io);
715         CHECK_STATUS(status, NT_STATUS_OK);
716         CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
717         CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
718
719         printf("Trying locked region\n");
720         cli->session->pid++;
721         if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
722                 printf("Failed to lock file at %d\n", __LINE__);
723                 ret = False;
724                 goto done;
725         }
726         cli->session->pid--;
727         memset(buf, 0, maxsize);
728         io.readbraw.in.offset = 0;
729         io.readbraw.in.mincnt = 100;
730         io.readbraw.in.maxcnt = 200;
731         status = smb_raw_read(cli->tree, &io);
732         CHECK_STATUS(status, NT_STATUS_OK);
733         CHECK_VALUE(io.readbraw.out.nread, 0);
734
735         printf("Trying locked region with timeout\n");
736         memset(buf, 0, maxsize);
737         io.readbraw.in.offset = 0;
738         io.readbraw.in.mincnt = 100;
739         io.readbraw.in.maxcnt = 200;
740         io.readbraw.in.timeout = 10000;
741         status = smb_raw_read(cli->tree, &io);
742         CHECK_STATUS(status, NT_STATUS_OK);
743         CHECK_VALUE(io.readbraw.out.nread, 0);
744
745         if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
746                 printf("Trying large offset read\n");
747                 io.readbraw.in.offset = ((uint64_t)0x2) << 32;
748                 io.readbraw.in.mincnt = 10;
749                 io.readbraw.in.maxcnt = 10;
750                 io.readbraw.in.timeout = 0;
751                 status = smb_raw_read(cli->tree, &io);
752                 CHECK_STATUS(status, NT_STATUS_OK);
753                 CHECK_VALUE(io.readbraw.out.nread, 0);
754         }
755
756 done:
757         smbcli_close(cli->tree, fnum);
758         smbcli_deltree(cli->tree, BASEDIR);
759         return ret;
760 }
761
762 /*
763   test read for execute
764 */
765 static BOOL test_read_for_execute(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
766 {
767         union smb_open op;
768         union smb_write wr;
769         union smb_read rd;
770         NTSTATUS status;
771         BOOL ret = True;
772         int fnum=0;
773         uint8_t *buf;
774         const int maxsize = 900;
775         const char *fname = BASEDIR "\\test.txt";
776         const uint8_t data[] = "TEST DATA";
777
778         buf = talloc_zero_size(mem_ctx, maxsize);
779
780         if (!torture_setup_dir(cli, BASEDIR)) {
781                 return False;
782         }
783
784         printf("Testing RAW_READ_READX with read_for_execute\n");
785
786         op.generic.level = RAW_OPEN_NTCREATEX;
787         op.ntcreatex.in.root_fid = 0;
788         op.ntcreatex.in.flags = 0;
789         op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
790         op.ntcreatex.in.create_options = 0;
791         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
792         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
793         op.ntcreatex.in.alloc_size = 0;
794         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
795         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
796         op.ntcreatex.in.security_flags = 0;
797         op.ntcreatex.in.fname = fname;
798         status = smb_raw_open(cli->tree, mem_ctx, &op);
799         CHECK_STATUS(status, NT_STATUS_OK);
800         fnum = op.ntcreatex.out.file.fnum;
801
802         wr.generic.level = RAW_WRITE_WRITEX;
803         wr.writex.in.file.fnum = fnum;
804         wr.writex.in.offset = 0;
805         wr.writex.in.wmode = 0;
806         wr.writex.in.remaining = 0;
807         wr.writex.in.count = ARRAY_SIZE(data);
808         wr.writex.in.data = data;
809         status = smb_raw_write(cli->tree, &wr);
810         CHECK_STATUS(status, NT_STATUS_OK);
811         CHECK_VALUE(wr.writex.out.nwritten, ARRAY_SIZE(data));
812
813         status = smbcli_close(cli->tree, fnum);
814         CHECK_STATUS(status, NT_STATUS_OK);
815
816         printf("open file with SEC_FILE_EXECUTE\n");
817         op.generic.level = RAW_OPEN_NTCREATEX;
818         op.ntcreatex.in.root_fid = 0;
819         op.ntcreatex.in.flags = 0;
820         op.ntcreatex.in.access_mask = SEC_FILE_EXECUTE;
821         op.ntcreatex.in.create_options = 0;
822         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
823         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
824         op.ntcreatex.in.alloc_size = 0;
825         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
826         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
827         op.ntcreatex.in.security_flags = 0;
828         op.ntcreatex.in.fname = fname;
829         status = smb_raw_open(cli->tree, mem_ctx, &op);
830         CHECK_STATUS(status, NT_STATUS_OK);
831         fnum = op.ntcreatex.out.file.fnum;
832
833         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
834         rd.generic.level = RAW_READ_READX;
835         rd.readx.in.file.fnum = fnum;
836         rd.readx.in.mincnt = 0;
837         rd.readx.in.maxcnt = maxsize;
838         rd.readx.in.offset = 0;
839         rd.readx.in.remaining = 0;
840         rd.readx.in.read_for_execute = True;
841         rd.readx.out.data = buf;
842         status = smb_raw_read(cli->tree, &rd);
843         CHECK_STATUS(status, NT_STATUS_OK);
844         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
845         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
846         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
847
848         printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
849         rd.generic.level = RAW_READ_READX;
850         rd.readx.in.file.fnum = fnum;
851         rd.readx.in.mincnt = 0;
852         rd.readx.in.maxcnt = maxsize;
853         rd.readx.in.offset = 0;
854         rd.readx.in.remaining = 0;
855         rd.readx.in.read_for_execute = False;
856         rd.readx.out.data = buf;
857         status = smb_raw_read(cli->tree, &rd);
858         CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
859
860         status = smbcli_close(cli->tree, fnum);
861         CHECK_STATUS(status, NT_STATUS_OK);
862
863         printf("open file with SEC_FILE_READ_DATA\n");
864         op.generic.level = RAW_OPEN_NTCREATEX;
865         op.ntcreatex.in.root_fid = 0;
866         op.ntcreatex.in.flags = 0;
867         op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
868         op.ntcreatex.in.create_options = 0;
869         op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
870         op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
871         op.ntcreatex.in.alloc_size = 0;
872         op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
873         op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
874         op.ntcreatex.in.security_flags = 0;
875         op.ntcreatex.in.fname = fname;
876         status = smb_raw_open(cli->tree, mem_ctx, &op);
877         CHECK_STATUS(status, NT_STATUS_OK);
878         fnum = op.ntcreatex.out.file.fnum;
879
880         printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
881         rd.generic.level = RAW_READ_READX;
882         rd.readx.in.file.fnum = fnum;
883         rd.readx.in.mincnt = 0;
884         rd.readx.in.maxcnt = maxsize;
885         rd.readx.in.offset = 0;
886         rd.readx.in.remaining = 0;
887         rd.readx.in.read_for_execute = True;
888         rd.readx.out.data = buf;
889         status = smb_raw_read(cli->tree, &rd);
890         CHECK_STATUS(status, NT_STATUS_OK);
891         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
892         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
893         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
894
895         printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
896         rd.generic.level = RAW_READ_READX;
897         rd.readx.in.file.fnum = fnum;
898         rd.readx.in.mincnt = 0;
899         rd.readx.in.maxcnt = maxsize;
900         rd.readx.in.offset = 0;
901         rd.readx.in.remaining = 0;
902         rd.readx.in.read_for_execute = False;
903         rd.readx.out.data = buf;
904         status = smb_raw_read(cli->tree, &rd);
905         CHECK_STATUS(status, NT_STATUS_OK);
906         CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
907         CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
908         CHECK_VALUE(rd.readx.out.compaction_mode, 0);
909
910 done:
911         smbcli_close(cli->tree, fnum);
912         smbcli_deltree(cli->tree, BASEDIR);
913         return ret;
914 }
915
916
917 /* 
918    basic testing of read calls
919 */
920 BOOL torture_raw_read(struct torture_context *torture)
921 {
922         struct smbcli_state *cli;
923         BOOL ret = True;
924         TALLOC_CTX *mem_ctx;
925
926         if (!torture_open_connection(&cli, 0)) {
927                 return False;
928         }
929
930         mem_ctx = talloc_init("torture_raw_read");
931
932         ret &= test_read(cli, mem_ctx);
933         ret &= test_readx(cli, mem_ctx);
934         ret &= test_lockread(cli, mem_ctx);
935         ret &= test_readbraw(cli, mem_ctx);
936         ret &= test_read_for_execute(cli, mem_ctx);
937
938         torture_close_connection(cli);
939         talloc_free(mem_ctx);
940         return ret;
941 }