ctdb-scripts: Support storing statd-callout state in cluster filesystem
[samba4-gss.git] / source4 / torture / raw / read.c
blobd4ee9d9ab2f78d69ee55c79dc5eac55776ae193b
1 /*
2 Unix SMB/CIFS implementation.
3 test suite for various read operations
4 Copyright (C) Andrew Tridgell 2003
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.
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.
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/>.
20 #include "includes.h"
21 #include "libcli/raw/libcliraw.h"
22 #include "libcli/raw/raw_proto.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
27 #include "torture/raw/proto.h"
29 #define CHECK_STATUS(status, correct) do { \
30 torture_assert_ntstatus_equal_goto(tctx, status, correct, ret, \
31 done, "incorrect status"); \
32 } while (0)
34 #define CHECK_VALUE(v, correct) do { \
35 torture_assert_int_equal_goto(tctx, (v), (correct), ret, done, \
36 "Incorrect value"); \
37 } while (0)
39 #define CHECK_BUFFER(buf, seed, len) do { \
40 if (!check_buffer(tctx, buf, seed, len, __LINE__)) { \
41 ret = false; \
42 torture_fail_goto(tctx, done, "buffer check failed\n"); \
43 }} while (0)
45 #define CHECK_READX_ALIGN(io) do { \
46 if ((io.readx.out.flags2 & FLAGS2_UNICODE_STRINGS) && \
47 (io.readx.out.data_offset % 2 != 0)) { \
48 ret = false; \
49 torture_fail_goto(tctx, done, "data not 16 bit aligned\n"); \
50 }} while (0)
52 #define BASEDIR "\\testread"
56 setup a random buffer based on a seed
58 static void setup_buffer(uint8_t *buf, unsigned int seed, int len)
60 int i;
61 srandom(seed);
62 for (i=0;i<len;i++) buf[i] = random();
66 check a random buffer based on a seed
68 static bool check_buffer(struct torture_context *tctx, uint8_t *buf,
69 unsigned int seed, int len, int line)
71 int i;
72 srandom(seed);
73 for (i=0;i<len;i++) {
74 uint8_t v = random();
75 if (buf[i] != v) {
76 torture_warning(tctx, "Buffer incorrect at line %d! "
77 "ofs=%d v1=0x%x v2=0x%x\n", line, i,
78 buf[i], v);
79 return false;
82 return true;
86 test read ops
88 static bool test_read(struct torture_context *tctx, struct smbcli_state *cli)
90 union smb_read io;
91 NTSTATUS status;
92 bool ret = true;
93 int fnum;
94 uint8_t *buf;
95 const int maxsize = 90000;
96 const char *fname = BASEDIR "\\test.txt";
97 const char *test_data = "TEST DATA";
98 unsigned int seed = time(NULL);
100 buf = talloc_zero_array(tctx, uint8_t, maxsize);
102 if (!torture_setting_bool(tctx, "read_support", true)) {
103 printf("server refuses to support READ\n");
104 return true;
107 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
109 printf("Testing RAW_READ_READ\n");
110 io.generic.level = RAW_READ_READ;
112 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
113 if (fnum == -1) {
114 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
115 ret = false;
116 goto done;
119 printf("Trying empty file read\n");
120 io.read.in.file.fnum = fnum;
121 io.read.in.count = 1;
122 io.read.in.offset = 0;
123 io.read.in.remaining = 0;
124 io.read.out.data = buf;
125 status = smb_raw_read(cli->tree, &io);
127 CHECK_STATUS(status, NT_STATUS_OK);
128 CHECK_VALUE(io.read.out.nread, 0);
130 printf("Trying zero file read\n");
131 io.read.in.count = 0;
132 status = smb_raw_read(cli->tree, &io);
133 CHECK_STATUS(status, NT_STATUS_OK);
134 CHECK_VALUE(io.read.out.nread, 0);
136 printf("Trying bad fnum\n");
137 io.read.in.file.fnum = fnum+1;
138 status = smb_raw_read(cli->tree, &io);
139 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
140 io.read.in.file.fnum = fnum;
142 smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
144 printf("Trying small read\n");
145 io.read.in.file.fnum = fnum;
146 io.read.in.offset = 0;
147 io.read.in.remaining = 0;
148 io.read.in.count = strlen(test_data);
149 status = smb_raw_read(cli->tree, &io);
150 CHECK_STATUS(status, NT_STATUS_OK);
151 CHECK_VALUE(io.read.out.nread, strlen(test_data));
152 if (memcmp(buf, test_data, strlen(test_data)) != 0) {
153 ret = false;
154 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
155 goto done;
158 printf("Trying short read\n");
159 io.read.in.offset = 1;
160 io.read.in.count = strlen(test_data);
161 status = smb_raw_read(cli->tree, &io);
162 CHECK_STATUS(status, NT_STATUS_OK);
163 CHECK_VALUE(io.read.out.nread, strlen(test_data)-1);
164 if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
165 ret = false;
166 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
167 goto done;
170 if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
171 printf("Trying max offset\n");
172 io.read.in.offset = ~0;
173 io.read.in.count = strlen(test_data);
174 status = smb_raw_read(cli->tree, &io);
175 CHECK_STATUS(status, NT_STATUS_OK);
176 CHECK_VALUE(io.read.out.nread, 0);
179 setup_buffer(buf, seed, maxsize);
180 smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
181 memset(buf, 0, maxsize);
183 printf("Trying large read\n");
184 io.read.in.offset = 0;
185 io.read.in.count = ~0;
186 status = smb_raw_read(cli->tree, &io);
187 CHECK_STATUS(status, NT_STATUS_OK);
188 CHECK_BUFFER(buf, seed, io.read.out.nread);
191 printf("Trying locked region\n");
192 cli->session->pid++;
193 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
194 printf("Failed to lock file at %d\n", __LINE__);
195 ret = false;
196 goto done;
198 cli->session->pid--;
199 memset(buf, 0, maxsize);
200 io.read.in.offset = 0;
201 io.read.in.count = ~0;
202 status = smb_raw_read(cli->tree, &io);
203 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
206 done:
207 smbcli_close(cli->tree, fnum);
208 smb_raw_exit(cli->session);
209 smbcli_deltree(cli->tree, BASEDIR);
210 return ret;
215 test lockread ops
217 static bool test_lockread(struct torture_context *tctx,
218 struct smbcli_state *cli)
220 union smb_read io;
221 NTSTATUS status;
222 bool ret = true;
223 int fnum;
224 uint8_t *buf;
225 const int maxsize = 90000;
226 const char *fname = BASEDIR "\\test.txt";
227 const char *test_data = "TEST DATA";
228 unsigned int seed = time(NULL);
230 if (!cli->transport->negotiate.lockread_supported) {
231 printf("Server does not support lockread - skipping\n");
232 return true;
235 buf = talloc_zero_array(tctx, uint8_t, maxsize);
237 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
239 printf("Testing RAW_READ_LOCKREAD\n");
240 io.generic.level = RAW_READ_LOCKREAD;
242 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
243 if (fnum == -1) {
244 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
245 ret = false;
246 goto done;
249 printf("Trying empty file read\n");
250 io.lockread.in.file.fnum = fnum;
251 io.lockread.in.count = 1;
252 io.lockread.in.offset = 1;
253 io.lockread.in.remaining = 0;
254 io.lockread.out.data = buf;
255 status = smb_raw_read(cli->tree, &io);
257 CHECK_STATUS(status, NT_STATUS_OK);
258 CHECK_VALUE(io.lockread.out.nread, 0);
260 status = smb_raw_read(cli->tree, &io);
261 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
263 status = smb_raw_read(cli->tree, &io);
264 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
266 printf("Trying zero file read\n");
267 io.lockread.in.count = 0;
268 status = smb_raw_read(cli->tree, &io);
269 CHECK_STATUS(status, NT_STATUS_OK);
271 smbcli_unlock(cli->tree, fnum, 1, 1);
273 printf("Trying bad fnum\n");
274 io.lockread.in.file.fnum = fnum+1;
275 status = smb_raw_read(cli->tree, &io);
276 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
277 io.lockread.in.file.fnum = fnum;
279 smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
281 printf("Trying small read\n");
282 io.lockread.in.file.fnum = fnum;
283 io.lockread.in.offset = 0;
284 io.lockread.in.remaining = 0;
285 io.lockread.in.count = strlen(test_data);
286 status = smb_raw_read(cli->tree, &io);
287 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
289 smbcli_unlock(cli->tree, fnum, 1, 0);
291 status = smb_raw_read(cli->tree, &io);
292 CHECK_STATUS(status, NT_STATUS_OK);
293 CHECK_VALUE(io.lockread.out.nread, strlen(test_data));
294 if (memcmp(buf, test_data, strlen(test_data)) != 0) {
295 ret = false;
296 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
297 goto done;
300 printf("Trying short read\n");
301 io.lockread.in.offset = 1;
302 io.lockread.in.count = strlen(test_data);
303 status = smb_raw_read(cli->tree, &io);
304 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
305 smbcli_unlock(cli->tree, fnum, 0, strlen(test_data));
306 status = smb_raw_read(cli->tree, &io);
307 CHECK_STATUS(status, NT_STATUS_OK);
309 CHECK_VALUE(io.lockread.out.nread, strlen(test_data)-1);
310 if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
311 ret = false;
312 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
313 goto done;
316 if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
317 printf("Trying max offset\n");
318 io.lockread.in.offset = ~0;
319 io.lockread.in.count = strlen(test_data);
320 status = smb_raw_read(cli->tree, &io);
321 CHECK_STATUS(status, NT_STATUS_OK);
322 CHECK_VALUE(io.lockread.out.nread, 0);
325 setup_buffer(buf, seed, maxsize);
326 smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
327 memset(buf, 0, maxsize);
329 printf("Trying large read\n");
330 io.lockread.in.offset = 0;
331 io.lockread.in.count = ~0;
332 status = smb_raw_read(cli->tree, &io);
333 CHECK_STATUS(status, NT_STATUS_LOCK_NOT_GRANTED);
334 smbcli_unlock(cli->tree, fnum, 1, strlen(test_data));
335 status = smb_raw_read(cli->tree, &io);
336 CHECK_STATUS(status, NT_STATUS_OK);
337 CHECK_BUFFER(buf, seed, io.lockread.out.nread);
338 smbcli_unlock(cli->tree, fnum, 0, 0xFFFF);
341 printf("Trying locked region\n");
342 cli->session->pid++;
343 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
344 printf("Failed to lock file at %d\n", __LINE__);
345 ret = false;
346 goto done;
348 cli->session->pid--;
349 memset(buf, 0, maxsize);
350 io.lockread.in.offset = 0;
351 io.lockread.in.count = ~0;
352 status = smb_raw_read(cli->tree, &io);
353 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
356 done:
357 smbcli_close(cli->tree, fnum);
358 smbcli_deltree(cli->tree, BASEDIR);
359 return ret;
364 test readx ops
366 static bool test_readx(struct torture_context *tctx, struct smbcli_state *cli)
368 union smb_read io;
369 NTSTATUS status;
370 bool ret = true;
371 int fnum;
372 uint8_t *buf;
373 const int maxsize = 90000;
374 const char *fname = BASEDIR "\\test.txt";
375 const char *test_data = "TEST DATA";
376 unsigned int seed = time(NULL);
377 struct smbcli_request *smbreq = NULL;
378 unsigned int i;
380 buf = talloc_zero_array(tctx, uint8_t, maxsize);
382 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
384 printf("Testing RAW_READ_READX\n");
386 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
387 if (fnum == -1) {
388 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
389 ret = false;
390 goto done;
393 printf("Trying empty file read\n");
394 io.generic.level = RAW_READ_READX;
395 io.readx.in.file.fnum = fnum;
396 io.readx.in.mincnt = 1;
397 io.readx.in.maxcnt = 1;
398 io.readx.in.offset = 0;
399 io.readx.in.remaining = 0;
400 io.readx.in.read_for_execute = false;
401 io.readx.out.data = buf;
402 status = smb_raw_read(cli->tree, &io);
404 CHECK_STATUS(status, NT_STATUS_OK);
405 CHECK_VALUE(io.readx.out.nread, 0);
406 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
407 CHECK_VALUE(io.readx.out.compaction_mode, 0);
408 CHECK_READX_ALIGN(io);
410 printf("Trying zero file read\n");
411 io.readx.in.mincnt = 0;
412 io.readx.in.maxcnt = 0;
413 status = smb_raw_read(cli->tree, &io);
414 CHECK_STATUS(status, NT_STATUS_OK);
415 CHECK_VALUE(io.readx.out.nread, 0);
416 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
417 CHECK_VALUE(io.readx.out.compaction_mode, 0);
418 CHECK_READX_ALIGN(io);
420 printf("Trying bad fnum\n");
421 io.readx.in.file.fnum = fnum+1;
422 status = smb_raw_read(cli->tree, &io);
423 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
424 io.readx.in.file.fnum = fnum;
426 smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
428 printf("Checking reserved fields are [0]\n");
429 io.readx.in.file.fnum = fnum;
430 io.readx.in.offset = 0;
431 io.readx.in.remaining = 0;
432 io.readx.in.read_for_execute = false;
433 io.readx.in.mincnt = strlen(test_data);
434 io.readx.in.maxcnt = strlen(test_data);
435 smbreq = smb_raw_read_send(cli->tree, &io);
436 if (smbreq == NULL) {
437 ret = false;
438 torture_fail_goto(tctx, done, "smb_raw_read_send failed\n");
440 if (!smbcli_request_receive(smbreq) ||
441 smbcli_request_is_error(smbreq)) {
442 status = smbcli_request_destroy(smbreq);
443 torture_fail_goto(tctx, done, "receive failed\n");
446 if (smbreq->in.wct != 12) {
447 ret = false;
448 printf("Incorrect wct %u (should be 12)\n",
449 (unsigned int)smbreq->in.wct);
450 status = smbcli_request_destroy(smbreq);
451 torture_fail_goto(tctx, done, "bad wct\n");
454 /* Ensure VWV8 - WVW11 are zero. */
455 for (i = 8; i < 12; i++) {
456 uint16_t br = SVAL(smbreq->in.vwv, VWV(i));
457 if (br != 0) {
458 status = smbcli_request_destroy(smbreq);
459 ret = false;
460 printf("reserved field %u is %u not zero\n",
462 (unsigned int)br);
463 torture_fail_goto(tctx, done, "bad reserved field\n");
467 smbcli_request_destroy(smbreq);
469 printf("Trying small read\n");
470 io.readx.in.file.fnum = fnum;
471 io.readx.in.offset = 0;
472 io.readx.in.remaining = 0;
473 io.readx.in.read_for_execute = false;
474 io.readx.in.mincnt = strlen(test_data);
475 io.readx.in.maxcnt = strlen(test_data);
476 status = smb_raw_read(cli->tree, &io);
477 CHECK_STATUS(status, NT_STATUS_OK);
478 CHECK_VALUE(io.readx.out.nread, strlen(test_data));
479 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
480 CHECK_VALUE(io.readx.out.compaction_mode, 0);
481 CHECK_READX_ALIGN(io);
482 if (memcmp(buf, test_data, strlen(test_data)) != 0) {
483 ret = false;
484 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
485 goto done;
488 printf("Trying short read\n");
489 io.readx.in.offset = 1;
490 io.readx.in.mincnt = strlen(test_data);
491 io.readx.in.maxcnt = strlen(test_data);
492 status = smb_raw_read(cli->tree, &io);
493 CHECK_STATUS(status, NT_STATUS_OK);
494 CHECK_VALUE(io.readx.out.nread, strlen(test_data)-1);
495 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
496 CHECK_VALUE(io.readx.out.compaction_mode, 0);
497 CHECK_READX_ALIGN(io);
498 if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
499 ret = false;
500 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
501 goto done;
504 if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
505 printf("Trying max offset\n");
506 io.readx.in.offset = 0xffffffff;
507 io.readx.in.mincnt = strlen(test_data);
508 io.readx.in.maxcnt = strlen(test_data);
509 status = smb_raw_read(cli->tree, &io);
510 CHECK_STATUS(status, NT_STATUS_OK);
511 CHECK_VALUE(io.readx.out.nread, 0);
512 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
513 CHECK_VALUE(io.readx.out.compaction_mode, 0);
514 CHECK_READX_ALIGN(io);
517 printf("Trying mincnt past EOF\n");
518 memset(buf, 0, maxsize);
519 io.readx.in.offset = 0;
520 io.readx.in.mincnt = 100;
521 io.readx.in.maxcnt = 110;
522 status = smb_raw_read(cli->tree, &io);
523 CHECK_STATUS(status, NT_STATUS_OK);
524 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
525 CHECK_VALUE(io.readx.out.compaction_mode, 0);
526 CHECK_VALUE(io.readx.out.nread, strlen(test_data));
527 CHECK_READX_ALIGN(io);
528 if (memcmp(buf, test_data, strlen(test_data)) != 0) {
529 ret = false;
530 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
531 goto done;
535 setup_buffer(buf, seed, maxsize);
536 smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
537 memset(buf, 0, maxsize);
539 printf("Trying page sized read\n");
540 io.readx.in.offset = 0;
541 io.readx.in.mincnt = 0x1000;
542 io.readx.in.maxcnt = 0x1000;
543 status = smb_raw_read(cli->tree, &io);
544 CHECK_STATUS(status, NT_STATUS_OK);
545 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
546 CHECK_VALUE(io.readx.out.compaction_mode, 0);
547 CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
548 CHECK_BUFFER(buf, seed, io.readx.out.nread);
549 CHECK_READX_ALIGN(io);
551 printf("Trying page + 1 sized read (check alignment)\n");
552 io.readx.in.offset = 0;
553 io.readx.in.mincnt = 0x1001;
554 io.readx.in.maxcnt = 0x1001;
555 status = smb_raw_read(cli->tree, &io);
556 CHECK_STATUS(status, NT_STATUS_OK);
557 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
558 CHECK_VALUE(io.readx.out.compaction_mode, 0);
559 CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
560 CHECK_BUFFER(buf, seed, io.readx.out.nread);
561 CHECK_READX_ALIGN(io);
563 printf("Trying large read (UINT16_MAX)\n");
564 io.readx.in.offset = 0;
565 io.readx.in.mincnt = 0xFFFF;
566 io.readx.in.maxcnt = 0xFFFF;
567 status = smb_raw_read(cli->tree, &io);
568 CHECK_STATUS(status, NT_STATUS_OK);
569 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
570 CHECK_VALUE(io.readx.out.compaction_mode, 0);
571 CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
572 CHECK_BUFFER(buf, seed, io.readx.out.nread);
573 CHECK_READX_ALIGN(io);
575 printf("Trying extra large read\n");
576 io.readx.in.offset = 0;
577 io.readx.in.mincnt = 100;
578 io.readx.in.maxcnt = 80000;
579 status = smb_raw_read(cli->tree, &io);
580 CHECK_STATUS(status, NT_STATUS_OK);
581 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
582 CHECK_VALUE(io.readx.out.compaction_mode, 0);
583 if (io.readx.out.nread == io.readx.in.maxcnt) {
584 printf("SAMBA: large read extension\n");
585 CHECK_VALUE(io.readx.out.nread, 80000);
586 } else {
587 CHECK_VALUE(io.readx.out.nread, 0x10000);
589 CHECK_BUFFER(buf, seed, io.readx.out.nread);
590 CHECK_READX_ALIGN(io);
592 printf("Trying mincnt > maxcnt\n");
593 memset(buf, 0, maxsize);
594 io.readx.in.offset = 0;
595 io.readx.in.mincnt = 30000;
596 io.readx.in.maxcnt = 20000;
597 status = smb_raw_read(cli->tree, &io);
598 CHECK_STATUS(status, NT_STATUS_OK);
599 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
600 CHECK_VALUE(io.readx.out.compaction_mode, 0);
601 CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
602 CHECK_BUFFER(buf, seed, io.readx.out.nread);
603 CHECK_READX_ALIGN(io);
605 printf("Trying mincnt < maxcnt\n");
606 memset(buf, 0, maxsize);
607 io.readx.in.offset = 0;
608 io.readx.in.mincnt = 20000;
609 io.readx.in.maxcnt = 30000;
610 status = smb_raw_read(cli->tree, &io);
611 CHECK_STATUS(status, NT_STATUS_OK);
612 CHECK_VALUE(io.readx.out.remaining, 0xFFFF);
613 CHECK_VALUE(io.readx.out.compaction_mode, 0);
614 CHECK_VALUE(io.readx.out.nread, io.readx.in.maxcnt);
615 CHECK_BUFFER(buf, seed, io.readx.out.nread);
616 CHECK_READX_ALIGN(io);
618 if (cli->transport->negotiate.capabilities & CAP_LARGE_READX) {
619 printf("Trying large readx\n");
620 io.readx.in.offset = 0;
621 io.readx.in.mincnt = 0;
622 io.readx.in.maxcnt = 0x10000 - 1;
623 status = smb_raw_read(cli->tree, &io);
624 CHECK_STATUS(status, NT_STATUS_OK);
625 CHECK_VALUE(io.readx.out.nread, 0xFFFF);
626 CHECK_READX_ALIGN(io);
628 io.readx.in.maxcnt = 0x10000;
629 status = smb_raw_read(cli->tree, &io);
630 CHECK_STATUS(status, NT_STATUS_OK);
631 CHECK_VALUE(io.readx.out.nread, 0x10000);
632 CHECK_READX_ALIGN(io);
634 io.readx.in.maxcnt = 0x10001;
635 status = smb_raw_read(cli->tree, &io);
636 CHECK_STATUS(status, NT_STATUS_OK);
637 if (io.readx.out.nread == io.readx.in.maxcnt) {
638 printf("SAMBA: large read extension\n");
639 CHECK_VALUE(io.readx.out.nread, 0x10001);
640 } else {
641 CHECK_VALUE(io.readx.out.nread, 0x10000);
643 } else {
644 printf("Server does not support the CAP_LARGE_READX extension\n");
647 printf("Trying locked region\n");
648 cli->session->pid++;
649 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
650 printf("Failed to lock file at %d\n", __LINE__);
651 ret = false;
652 goto done;
654 cli->session->pid--;
655 memset(buf, 0, maxsize);
656 io.readx.in.offset = 0;
657 io.readx.in.mincnt = 100;
658 io.readx.in.maxcnt = 200;
659 status = smb_raw_read(cli->tree, &io);
660 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
662 if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
663 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
664 goto done;
667 printf("Trying large offset read\n");
668 io.readx.in.offset = ((uint64_t)0x2) << 32;
669 io.readx.in.mincnt = 10;
670 io.readx.in.maxcnt = 10;
671 status = smb_raw_read(cli->tree, &io);
672 CHECK_STATUS(status, NT_STATUS_OK);
673 CHECK_VALUE(io.readx.out.nread, 0);
674 CHECK_READX_ALIGN(io);
676 if (NT_STATUS_IS_ERR(smbcli_lock64(cli->tree, fnum, io.readx.in.offset, 1, 0, WRITE_LOCK))) {
677 printf("Failed to lock file at %d\n", __LINE__);
678 ret = false;
679 goto done;
682 status = smb_raw_read(cli->tree, &io);
683 CHECK_STATUS(status, NT_STATUS_OK);
684 CHECK_VALUE(io.readx.out.nread, 0);
685 CHECK_READX_ALIGN(io);
687 done:
688 smbcli_close(cli->tree, fnum);
689 smbcli_deltree(cli->tree, BASEDIR);
690 return ret;
695 test readbraw ops
697 static bool test_readbraw(struct torture_context *tctx,
698 struct smbcli_state *cli)
700 union smb_read io;
701 NTSTATUS status;
702 bool ret = true;
703 int fnum;
704 uint8_t *buf;
705 const int maxsize = 90000;
706 const char *fname = BASEDIR "\\test.txt";
707 const char *test_data = "TEST DATA";
708 unsigned int seed = time(NULL);
710 if (!cli->transport->negotiate.readbraw_supported) {
711 printf("Server does not support readbraw - skipping\n");
712 return true;
715 buf = talloc_zero_array(tctx, uint8_t, maxsize);
717 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
719 printf("Testing RAW_READ_READBRAW\n");
721 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
722 if (fnum == -1) {
723 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
724 ret = false;
725 goto done;
728 printf("Trying empty file read\n");
729 io.generic.level = RAW_READ_READBRAW;
730 io.readbraw.in.file.fnum = fnum;
731 io.readbraw.in.mincnt = 1;
732 io.readbraw.in.maxcnt = 1;
733 io.readbraw.in.offset = 0;
734 io.readbraw.in.timeout = 0;
735 io.readbraw.out.data = buf;
736 status = smb_raw_read(cli->tree, &io);
738 CHECK_STATUS(status, NT_STATUS_OK);
739 CHECK_VALUE(io.readbraw.out.nread, 0);
741 printf("Trying zero file read\n");
742 io.readbraw.in.mincnt = 0;
743 io.readbraw.in.maxcnt = 0;
744 status = smb_raw_read(cli->tree, &io);
745 CHECK_STATUS(status, NT_STATUS_OK);
746 CHECK_VALUE(io.readbraw.out.nread, 0);
748 printf("Trying bad fnum\n");
749 io.readbraw.in.file.fnum = fnum+1;
750 status = smb_raw_read(cli->tree, &io);
751 CHECK_STATUS(status, NT_STATUS_OK);
752 CHECK_VALUE(io.readbraw.out.nread, 0);
753 io.readbraw.in.file.fnum = fnum;
755 smbcli_write(cli->tree, fnum, 0, test_data, 0, strlen(test_data));
757 printf("Trying small read\n");
758 io.readbraw.in.file.fnum = fnum;
759 io.readbraw.in.offset = 0;
760 io.readbraw.in.mincnt = strlen(test_data);
761 io.readbraw.in.maxcnt = strlen(test_data);
762 status = smb_raw_read(cli->tree, &io);
763 CHECK_STATUS(status, NT_STATUS_OK);
764 CHECK_VALUE(io.readbraw.out.nread, strlen(test_data));
765 if (memcmp(buf, test_data, strlen(test_data)) != 0) {
766 ret = false;
767 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data, buf);
768 goto done;
771 printf("Trying short read\n");
772 io.readbraw.in.offset = 1;
773 io.readbraw.in.mincnt = strlen(test_data);
774 io.readbraw.in.maxcnt = strlen(test_data);
775 status = smb_raw_read(cli->tree, &io);
776 CHECK_STATUS(status, NT_STATUS_OK);
777 CHECK_VALUE(io.readbraw.out.nread, strlen(test_data)-1);
778 if (memcmp(buf, test_data+1, strlen(test_data)-1) != 0) {
779 ret = false;
780 printf("incorrect data at %d!? (%s:%s)\n", __LINE__, test_data+1, buf);
781 goto done;
784 if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
785 printf("Trying max offset\n");
786 io.readbraw.in.offset = ~0;
787 io.readbraw.in.mincnt = strlen(test_data);
788 io.readbraw.in.maxcnt = strlen(test_data);
789 status = smb_raw_read(cli->tree, &io);
790 CHECK_STATUS(status, NT_STATUS_OK);
791 CHECK_VALUE(io.readbraw.out.nread, 0);
794 setup_buffer(buf, seed, maxsize);
795 smbcli_write(cli->tree, fnum, 0, buf, 0, maxsize);
796 memset(buf, 0, maxsize);
798 printf("Trying large read\n");
799 io.readbraw.in.offset = 0;
800 io.readbraw.in.mincnt = ~0;
801 io.readbraw.in.maxcnt = ~0;
802 status = smb_raw_read(cli->tree, &io);
803 CHECK_STATUS(status, NT_STATUS_OK);
804 CHECK_VALUE(io.readbraw.out.nread, 0xFFFF);
805 CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
807 printf("Trying mincnt > maxcnt\n");
808 memset(buf, 0, maxsize);
809 io.readbraw.in.offset = 0;
810 io.readbraw.in.mincnt = 30000;
811 io.readbraw.in.maxcnt = 20000;
812 status = smb_raw_read(cli->tree, &io);
813 CHECK_STATUS(status, NT_STATUS_OK);
814 CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
815 CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
817 printf("Trying mincnt < maxcnt\n");
818 memset(buf, 0, maxsize);
819 io.readbraw.in.offset = 0;
820 io.readbraw.in.mincnt = 20000;
821 io.readbraw.in.maxcnt = 30000;
822 status = smb_raw_read(cli->tree, &io);
823 CHECK_STATUS(status, NT_STATUS_OK);
824 CHECK_VALUE(io.readbraw.out.nread, io.readbraw.in.maxcnt);
825 CHECK_BUFFER(buf, seed, io.readbraw.out.nread);
827 printf("Trying locked region\n");
828 cli->session->pid++;
829 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 103, 1, 0, WRITE_LOCK))) {
830 printf("Failed to lock file at %d\n", __LINE__);
831 ret = false;
832 goto done;
834 cli->session->pid--;
835 memset(buf, 0, maxsize);
836 io.readbraw.in.offset = 0;
837 io.readbraw.in.mincnt = 100;
838 io.readbraw.in.maxcnt = 200;
839 status = smb_raw_read(cli->tree, &io);
840 CHECK_STATUS(status, NT_STATUS_OK);
841 CHECK_VALUE(io.readbraw.out.nread, 0);
843 printf("Trying locked region with timeout\n");
844 memset(buf, 0, maxsize);
845 io.readbraw.in.offset = 0;
846 io.readbraw.in.mincnt = 100;
847 io.readbraw.in.maxcnt = 200;
848 io.readbraw.in.timeout = 10000;
849 status = smb_raw_read(cli->tree, &io);
850 CHECK_STATUS(status, NT_STATUS_OK);
851 CHECK_VALUE(io.readbraw.out.nread, 0);
853 if (cli->transport->negotiate.capabilities & CAP_LARGE_FILES) {
854 printf("Trying large offset read\n");
855 io.readbraw.in.offset = ((uint64_t)0x2) << 32;
856 io.readbraw.in.mincnt = 10;
857 io.readbraw.in.maxcnt = 10;
858 io.readbraw.in.timeout = 0;
859 status = smb_raw_read(cli->tree, &io);
860 CHECK_STATUS(status, NT_STATUS_OK);
861 CHECK_VALUE(io.readbraw.out.nread, 0);
864 done:
865 smbcli_close(cli->tree, fnum);
866 smbcli_deltree(cli->tree, BASEDIR);
867 return ret;
871 test read for execute
873 static bool test_read_for_execute(struct torture_context *tctx,
874 struct smbcli_state *cli)
876 union smb_open op;
877 union smb_write wr;
878 union smb_read rd;
879 NTSTATUS status;
880 bool ret = true;
881 int fnum=0;
882 uint8_t *buf;
883 const int maxsize = 900;
884 const char *fname = BASEDIR "\\test.txt";
885 const uint8_t data[] = "TEST DATA";
887 buf = talloc_zero_array(tctx, uint8_t, maxsize);
889 torture_assert(tctx, torture_setup_dir(cli, BASEDIR), "Failed to setup up test directory: " BASEDIR);
891 printf("Testing RAW_READ_READX with read_for_execute\n");
893 op.generic.level = RAW_OPEN_NTCREATEX;
894 op.ntcreatex.in.root_fid.fnum = 0;
895 op.ntcreatex.in.flags = 0;
896 op.ntcreatex.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
897 op.ntcreatex.in.create_options = 0;
898 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
899 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
900 op.ntcreatex.in.alloc_size = 0;
901 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_CREATE;
902 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
903 op.ntcreatex.in.security_flags = 0;
904 op.ntcreatex.in.fname = fname;
905 status = smb_raw_open(cli->tree, tctx, &op);
906 CHECK_STATUS(status, NT_STATUS_OK);
907 fnum = op.ntcreatex.out.file.fnum;
909 wr.generic.level = RAW_WRITE_WRITEX;
910 wr.writex.in.file.fnum = fnum;
911 wr.writex.in.offset = 0;
912 wr.writex.in.wmode = 0;
913 wr.writex.in.remaining = 0;
914 wr.writex.in.count = ARRAY_SIZE(data);
915 wr.writex.in.data = data;
916 status = smb_raw_write(cli->tree, &wr);
917 CHECK_STATUS(status, NT_STATUS_OK);
918 CHECK_VALUE(wr.writex.out.nwritten, ARRAY_SIZE(data));
920 status = smbcli_close(cli->tree, fnum);
921 CHECK_STATUS(status, NT_STATUS_OK);
923 printf("open file with SEC_FILE_EXECUTE\n");
924 op.generic.level = RAW_OPEN_NTCREATEX;
925 op.ntcreatex.in.root_fid.fnum = 0;
926 op.ntcreatex.in.flags = 0;
927 op.ntcreatex.in.access_mask = SEC_FILE_EXECUTE;
928 op.ntcreatex.in.create_options = 0;
929 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
930 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
931 op.ntcreatex.in.alloc_size = 0;
932 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
933 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
934 op.ntcreatex.in.security_flags = 0;
935 op.ntcreatex.in.fname = fname;
936 status = smb_raw_open(cli->tree, tctx, &op);
937 CHECK_STATUS(status, NT_STATUS_OK);
938 fnum = op.ntcreatex.out.file.fnum;
940 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
941 rd.generic.level = RAW_READ_READX;
942 rd.readx.in.file.fnum = fnum;
943 rd.readx.in.mincnt = 0;
944 rd.readx.in.maxcnt = maxsize;
945 rd.readx.in.offset = 0;
946 rd.readx.in.remaining = 0;
947 rd.readx.in.read_for_execute = true;
948 rd.readx.out.data = buf;
949 status = smb_raw_read(cli->tree, &rd);
950 CHECK_STATUS(status, NT_STATUS_OK);
951 CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
952 CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
953 CHECK_VALUE(rd.readx.out.compaction_mode, 0);
955 printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
956 rd.generic.level = RAW_READ_READX;
957 rd.readx.in.file.fnum = fnum;
958 rd.readx.in.mincnt = 0;
959 rd.readx.in.maxcnt = maxsize;
960 rd.readx.in.offset = 0;
961 rd.readx.in.remaining = 0;
962 rd.readx.in.read_for_execute = false;
963 rd.readx.out.data = buf;
964 status = smb_raw_read(cli->tree, &rd);
965 CHECK_STATUS(status, NT_STATUS_ACCESS_DENIED);
967 status = smbcli_close(cli->tree, fnum);
968 CHECK_STATUS(status, NT_STATUS_OK);
970 printf("open file with SEC_FILE_READ_DATA\n");
971 op.generic.level = RAW_OPEN_NTCREATEX;
972 op.ntcreatex.in.root_fid.fnum = 0;
973 op.ntcreatex.in.flags = 0;
974 op.ntcreatex.in.access_mask = SEC_FILE_READ_DATA;
975 op.ntcreatex.in.create_options = 0;
976 op.ntcreatex.in.file_attr = FILE_ATTRIBUTE_NORMAL;
977 op.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
978 op.ntcreatex.in.alloc_size = 0;
979 op.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
980 op.ntcreatex.in.impersonation = NTCREATEX_IMPERSONATION_ANONYMOUS;
981 op.ntcreatex.in.security_flags = 0;
982 op.ntcreatex.in.fname = fname;
983 status = smb_raw_open(cli->tree, tctx, &op);
984 CHECK_STATUS(status, NT_STATUS_OK);
985 fnum = op.ntcreatex.out.file.fnum;
987 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
988 rd.generic.level = RAW_READ_READX;
989 rd.readx.in.file.fnum = fnum;
990 rd.readx.in.mincnt = 0;
991 rd.readx.in.maxcnt = maxsize;
992 rd.readx.in.offset = 0;
993 rd.readx.in.remaining = 0;
994 rd.readx.in.read_for_execute = true;
995 rd.readx.out.data = buf;
996 status = smb_raw_read(cli->tree, &rd);
997 CHECK_STATUS(status, NT_STATUS_OK);
998 CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
999 CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
1000 CHECK_VALUE(rd.readx.out.compaction_mode, 0);
1002 printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
1003 rd.generic.level = RAW_READ_READX;
1004 rd.readx.in.file.fnum = fnum;
1005 rd.readx.in.mincnt = 0;
1006 rd.readx.in.maxcnt = maxsize;
1007 rd.readx.in.offset = 0;
1008 rd.readx.in.remaining = 0;
1009 rd.readx.in.read_for_execute = false;
1010 rd.readx.out.data = buf;
1011 status = smb_raw_read(cli->tree, &rd);
1012 CHECK_STATUS(status, NT_STATUS_OK);
1013 CHECK_VALUE(rd.readx.out.nread, ARRAY_SIZE(data));
1014 CHECK_VALUE(rd.readx.out.remaining, 0xFFFF);
1015 CHECK_VALUE(rd.readx.out.compaction_mode, 0);
1017 done:
1018 smbcli_close(cli->tree, fnum);
1019 smbcli_deltree(cli->tree, BASEDIR);
1020 return ret;
1025 basic testing of read calls
1027 struct torture_suite *torture_raw_read(TALLOC_CTX *mem_ctx)
1029 struct torture_suite *suite = torture_suite_create(mem_ctx, "read");
1031 torture_suite_add_1smb_test(suite, "read", test_read);
1032 torture_suite_add_1smb_test(suite, "readx", test_readx);
1033 torture_suite_add_1smb_test(suite, "lockread", test_lockread);
1034 torture_suite_add_1smb_test(suite, "readbraw", test_readbraw);
1035 torture_suite_add_1smb_test(suite, "read for execute",
1036 test_read_for_execute);
1038 return suite;