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/>.
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"); \
34 #define CHECK_VALUE(v, correct) do { \
35 torture_assert_int_equal_goto(tctx, (v), (correct), ret, done, \
39 #define CHECK_BUFFER(buf, seed, len) do { \
40 if (!check_buffer(tctx, buf, seed, len, __LINE__)) { \
42 torture_fail_goto(tctx, done, "buffer check failed\n"); \
45 #define CHECK_READX_ALIGN(io) do { \
46 if ((io.readx.out.flags2 & FLAGS2_UNICODE_STRINGS) && \
47 (io.readx.out.data_offset % 2 != 0)) { \
49 torture_fail_goto(tctx, done, "data not 16 bit aligned\n"); \
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
)
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
)
76 torture_warning(tctx
, "Buffer incorrect at line %d! "
77 "ofs=%d v1=0x%x v2=0x%x\n", line
, i
,
88 static bool test_read(struct torture_context
*tctx
, struct smbcli_state
*cli
)
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");
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
);
114 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
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) {
154 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
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) {
166 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
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");
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__
);
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
);
207 smbcli_close(cli
->tree
, fnum
);
208 smb_raw_exit(cli
->session
);
209 smbcli_deltree(cli
->tree
, BASEDIR
);
217 static bool test_lockread(struct torture_context
*tctx
,
218 struct smbcli_state
*cli
)
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");
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
);
244 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
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) {
296 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
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) {
312 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
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");
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__
);
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
);
357 smbcli_close(cli
->tree
, fnum
);
358 smbcli_deltree(cli
->tree
, BASEDIR
);
366 static bool test_readx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
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
;
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
);
388 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
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
) {
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) {
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
));
458 status
= smbcli_request_destroy(smbreq
);
460 printf("reserved field %u is %u not zero\n",
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) {
484 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
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) {
500 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
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) {
530 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
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);
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);
641 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
644 printf("Server does not support the CAP_LARGE_READX extension\n");
647 printf("Trying locked region\n");
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__
);
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");
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__
);
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
);
688 smbcli_close(cli
->tree
, fnum
);
689 smbcli_deltree(cli
->tree
, BASEDIR
);
697 static bool test_readbraw(struct torture_context
*tctx
,
698 struct smbcli_state
*cli
)
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");
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
);
723 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
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) {
767 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
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) {
780 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
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");
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__
);
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);
865 smbcli_close(cli
->tree
, fnum
);
866 smbcli_deltree(cli
->tree
, BASEDIR
);
871 test read for execute
873 static bool test_read_for_execute(struct torture_context
*tctx
,
874 struct smbcli_state
*cli
)
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);
1018 smbcli_close(cli
->tree
, fnum
);
1019 smbcli_deltree(cli
->tree
, BASEDIR
);
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
);