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