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 "system/time.h"
23 #include "system/filesys.h"
24 #include "libcli/libcli.h"
25 #include "torture/util.h"
26 #include "torture/raw/proto.h"
28 #define CHECK_STATUS(status, correct) do { \
29 torture_assert_ntstatus_equal_goto(tctx, status, correct, ret, \
30 done, "incorrect status"); \
33 #define CHECK_VALUE(v, correct) do { \
34 torture_assert_int_equal_goto(tctx, (v), (correct), ret, done, \
38 #define CHECK_BUFFER(buf, seed, len) do { \
39 if (!check_buffer(tctx, buf, seed, len, __LINE__)) { \
41 torture_fail_goto(tctx, done, "buffer check failed\n"); \
44 #define CHECK_READX_ALIGN(io) do { \
45 if ((io.readx.out.flags2 & FLAGS2_UNICODE_STRINGS) && \
46 (io.readx.out.data_offset % 2 != 0)) { \
48 torture_fail_goto(tctx, done, "data not 16 bit aligned\n"); \
51 #define BASEDIR "\\testread"
55 setup a random buffer based on a seed
57 static void setup_buffer(uint8_t *buf
, unsigned int seed
, int len
)
61 for (i
=0;i
<len
;i
++) buf
[i
] = random();
65 check a random buffer based on a seed
67 static bool check_buffer(struct torture_context
*tctx
, uint8_t *buf
,
68 unsigned int seed
, int len
, int line
)
75 torture_warning(tctx
, "Buffer incorrect at line %d! "
76 "ofs=%d v1=0x%x v2=0x%x\n", line
, i
,
87 static bool test_read(struct torture_context
*tctx
, struct smbcli_state
*cli
)
94 const int maxsize
= 90000;
95 const char *fname
= BASEDIR
"\\test.txt";
96 const char *test_data
= "TEST DATA";
97 unsigned int seed
= time(NULL
);
99 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
101 if (!torture_setting_bool(tctx
, "read_support", true)) {
102 printf("server refuses to support READ\n");
106 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
108 printf("Testing RAW_READ_READ\n");
109 io
.generic
.level
= RAW_READ_READ
;
111 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
113 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
118 printf("Trying empty file read\n");
119 io
.read
.in
.file
.fnum
= fnum
;
120 io
.read
.in
.count
= 1;
121 io
.read
.in
.offset
= 0;
122 io
.read
.in
.remaining
= 0;
123 io
.read
.out
.data
= buf
;
124 status
= smb_raw_read(cli
->tree
, &io
);
126 CHECK_STATUS(status
, NT_STATUS_OK
);
127 CHECK_VALUE(io
.read
.out
.nread
, 0);
129 printf("Trying zero file read\n");
130 io
.read
.in
.count
= 0;
131 status
= smb_raw_read(cli
->tree
, &io
);
132 CHECK_STATUS(status
, NT_STATUS_OK
);
133 CHECK_VALUE(io
.read
.out
.nread
, 0);
135 printf("Trying bad fnum\n");
136 io
.read
.in
.file
.fnum
= fnum
+1;
137 status
= smb_raw_read(cli
->tree
, &io
);
138 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
139 io
.read
.in
.file
.fnum
= fnum
;
141 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
143 printf("Trying small read\n");
144 io
.read
.in
.file
.fnum
= fnum
;
145 io
.read
.in
.offset
= 0;
146 io
.read
.in
.remaining
= 0;
147 io
.read
.in
.count
= strlen(test_data
);
148 status
= smb_raw_read(cli
->tree
, &io
);
149 CHECK_STATUS(status
, NT_STATUS_OK
);
150 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
));
151 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
153 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
157 printf("Trying short read\n");
158 io
.read
.in
.offset
= 1;
159 io
.read
.in
.count
= strlen(test_data
);
160 status
= smb_raw_read(cli
->tree
, &io
);
161 CHECK_STATUS(status
, NT_STATUS_OK
);
162 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
)-1);
163 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
165 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
169 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
170 printf("Trying max offset\n");
171 io
.read
.in
.offset
= ~0;
172 io
.read
.in
.count
= strlen(test_data
);
173 status
= smb_raw_read(cli
->tree
, &io
);
174 CHECK_STATUS(status
, NT_STATUS_OK
);
175 CHECK_VALUE(io
.read
.out
.nread
, 0);
178 setup_buffer(buf
, seed
, maxsize
);
179 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
180 memset(buf
, 0, maxsize
);
182 printf("Trying large read\n");
183 io
.read
.in
.offset
= 0;
184 io
.read
.in
.count
= ~0;
185 status
= smb_raw_read(cli
->tree
, &io
);
186 CHECK_STATUS(status
, NT_STATUS_OK
);
187 CHECK_BUFFER(buf
, seed
, io
.read
.out
.nread
);
190 printf("Trying locked region\n");
192 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
193 printf("Failed to lock file at %d\n", __LINE__
);
198 memset(buf
, 0, maxsize
);
199 io
.read
.in
.offset
= 0;
200 io
.read
.in
.count
= ~0;
201 status
= smb_raw_read(cli
->tree
, &io
);
202 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
206 smbcli_close(cli
->tree
, fnum
);
207 smb_raw_exit(cli
->session
);
208 smbcli_deltree(cli
->tree
, BASEDIR
);
216 static bool test_lockread(struct torture_context
*tctx
,
217 struct smbcli_state
*cli
)
224 const int maxsize
= 90000;
225 const char *fname
= BASEDIR
"\\test.txt";
226 const char *test_data
= "TEST DATA";
227 unsigned int seed
= time(NULL
);
229 if (!cli
->transport
->negotiate
.lockread_supported
) {
230 printf("Server does not support lockread - skipping\n");
234 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
236 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
238 printf("Testing RAW_READ_LOCKREAD\n");
239 io
.generic
.level
= RAW_READ_LOCKREAD
;
241 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
243 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
248 printf("Trying empty file read\n");
249 io
.lockread
.in
.file
.fnum
= fnum
;
250 io
.lockread
.in
.count
= 1;
251 io
.lockread
.in
.offset
= 1;
252 io
.lockread
.in
.remaining
= 0;
253 io
.lockread
.out
.data
= buf
;
254 status
= smb_raw_read(cli
->tree
, &io
);
256 CHECK_STATUS(status
, NT_STATUS_OK
);
257 CHECK_VALUE(io
.lockread
.out
.nread
, 0);
259 status
= smb_raw_read(cli
->tree
, &io
);
260 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
262 status
= smb_raw_read(cli
->tree
, &io
);
263 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
265 printf("Trying zero file read\n");
266 io
.lockread
.in
.count
= 0;
267 status
= smb_raw_read(cli
->tree
, &io
);
268 CHECK_STATUS(status
, NT_STATUS_OK
);
270 smbcli_unlock(cli
->tree
, fnum
, 1, 1);
272 printf("Trying bad fnum\n");
273 io
.lockread
.in
.file
.fnum
= fnum
+1;
274 status
= smb_raw_read(cli
->tree
, &io
);
275 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
276 io
.lockread
.in
.file
.fnum
= fnum
;
278 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
280 printf("Trying small read\n");
281 io
.lockread
.in
.file
.fnum
= fnum
;
282 io
.lockread
.in
.offset
= 0;
283 io
.lockread
.in
.remaining
= 0;
284 io
.lockread
.in
.count
= strlen(test_data
);
285 status
= smb_raw_read(cli
->tree
, &io
);
286 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
288 smbcli_unlock(cli
->tree
, fnum
, 1, 0);
290 status
= smb_raw_read(cli
->tree
, &io
);
291 CHECK_STATUS(status
, NT_STATUS_OK
);
292 CHECK_VALUE(io
.lockread
.out
.nread
, strlen(test_data
));
293 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
295 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
299 printf("Trying short read\n");
300 io
.lockread
.in
.offset
= 1;
301 io
.lockread
.in
.count
= strlen(test_data
);
302 status
= smb_raw_read(cli
->tree
, &io
);
303 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
304 smbcli_unlock(cli
->tree
, fnum
, 0, strlen(test_data
));
305 status
= smb_raw_read(cli
->tree
, &io
);
306 CHECK_STATUS(status
, NT_STATUS_OK
);
308 CHECK_VALUE(io
.lockread
.out
.nread
, strlen(test_data
)-1);
309 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
311 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
315 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
316 printf("Trying max offset\n");
317 io
.lockread
.in
.offset
= ~0;
318 io
.lockread
.in
.count
= strlen(test_data
);
319 status
= smb_raw_read(cli
->tree
, &io
);
320 CHECK_STATUS(status
, NT_STATUS_OK
);
321 CHECK_VALUE(io
.lockread
.out
.nread
, 0);
324 setup_buffer(buf
, seed
, maxsize
);
325 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
326 memset(buf
, 0, maxsize
);
328 printf("Trying large read\n");
329 io
.lockread
.in
.offset
= 0;
330 io
.lockread
.in
.count
= ~0;
331 status
= smb_raw_read(cli
->tree
, &io
);
332 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
333 smbcli_unlock(cli
->tree
, fnum
, 1, strlen(test_data
));
334 status
= smb_raw_read(cli
->tree
, &io
);
335 CHECK_STATUS(status
, NT_STATUS_OK
);
336 CHECK_BUFFER(buf
, seed
, io
.lockread
.out
.nread
);
337 smbcli_unlock(cli
->tree
, fnum
, 0, 0xFFFF);
340 printf("Trying locked region\n");
342 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
343 printf("Failed to lock file at %d\n", __LINE__
);
348 memset(buf
, 0, maxsize
);
349 io
.lockread
.in
.offset
= 0;
350 io
.lockread
.in
.count
= ~0;
351 status
= smb_raw_read(cli
->tree
, &io
);
352 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
356 smbcli_close(cli
->tree
, fnum
);
357 smbcli_deltree(cli
->tree
, BASEDIR
);
365 static bool test_readx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
372 const int maxsize
= 90000;
373 const char *fname
= BASEDIR
"\\test.txt";
374 const char *test_data
= "TEST DATA";
375 unsigned int seed
= time(NULL
);
377 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
379 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
381 printf("Testing RAW_READ_READX\n");
383 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
385 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
390 printf("Trying empty file read\n");
391 io
.generic
.level
= RAW_READ_READX
;
392 io
.readx
.in
.file
.fnum
= fnum
;
393 io
.readx
.in
.mincnt
= 1;
394 io
.readx
.in
.maxcnt
= 1;
395 io
.readx
.in
.offset
= 0;
396 io
.readx
.in
.remaining
= 0;
397 io
.readx
.in
.read_for_execute
= false;
398 io
.readx
.out
.data
= buf
;
399 status
= smb_raw_read(cli
->tree
, &io
);
401 CHECK_STATUS(status
, NT_STATUS_OK
);
402 CHECK_VALUE(io
.readx
.out
.nread
, 0);
403 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
404 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
405 CHECK_READX_ALIGN(io
);
407 printf("Trying zero file read\n");
408 io
.readx
.in
.mincnt
= 0;
409 io
.readx
.in
.maxcnt
= 0;
410 status
= smb_raw_read(cli
->tree
, &io
);
411 CHECK_STATUS(status
, NT_STATUS_OK
);
412 CHECK_VALUE(io
.readx
.out
.nread
, 0);
413 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
414 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
415 CHECK_READX_ALIGN(io
);
417 printf("Trying bad fnum\n");
418 io
.readx
.in
.file
.fnum
= fnum
+1;
419 status
= smb_raw_read(cli
->tree
, &io
);
420 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
421 io
.readx
.in
.file
.fnum
= fnum
;
423 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
425 printf("Trying small read\n");
426 io
.readx
.in
.file
.fnum
= fnum
;
427 io
.readx
.in
.offset
= 0;
428 io
.readx
.in
.remaining
= 0;
429 io
.readx
.in
.read_for_execute
= false;
430 io
.readx
.in
.mincnt
= strlen(test_data
);
431 io
.readx
.in
.maxcnt
= strlen(test_data
);
432 status
= smb_raw_read(cli
->tree
, &io
);
433 CHECK_STATUS(status
, NT_STATUS_OK
);
434 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
435 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
436 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
437 CHECK_READX_ALIGN(io
);
438 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
440 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
444 printf("Trying short read\n");
445 io
.readx
.in
.offset
= 1;
446 io
.readx
.in
.mincnt
= strlen(test_data
);
447 io
.readx
.in
.maxcnt
= strlen(test_data
);
448 status
= smb_raw_read(cli
->tree
, &io
);
449 CHECK_STATUS(status
, NT_STATUS_OK
);
450 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
)-1);
451 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
452 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
453 CHECK_READX_ALIGN(io
);
454 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
456 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
460 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
461 printf("Trying max offset\n");
462 io
.readx
.in
.offset
= 0xffffffff;
463 io
.readx
.in
.mincnt
= strlen(test_data
);
464 io
.readx
.in
.maxcnt
= strlen(test_data
);
465 status
= smb_raw_read(cli
->tree
, &io
);
466 CHECK_STATUS(status
, NT_STATUS_OK
);
467 CHECK_VALUE(io
.readx
.out
.nread
, 0);
468 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
469 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
470 CHECK_READX_ALIGN(io
);
473 printf("Trying mincnt past EOF\n");
474 memset(buf
, 0, maxsize
);
475 io
.readx
.in
.offset
= 0;
476 io
.readx
.in
.mincnt
= 100;
477 io
.readx
.in
.maxcnt
= 110;
478 status
= smb_raw_read(cli
->tree
, &io
);
479 CHECK_STATUS(status
, NT_STATUS_OK
);
480 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
481 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
482 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
483 CHECK_READX_ALIGN(io
);
484 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
486 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
491 setup_buffer(buf
, seed
, maxsize
);
492 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
493 memset(buf
, 0, maxsize
);
495 printf("Trying page sized read\n");
496 io
.readx
.in
.offset
= 0;
497 io
.readx
.in
.mincnt
= 0x1000;
498 io
.readx
.in
.maxcnt
= 0x1000;
499 status
= smb_raw_read(cli
->tree
, &io
);
500 CHECK_STATUS(status
, NT_STATUS_OK
);
501 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
502 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
503 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
504 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
505 CHECK_READX_ALIGN(io
);
507 printf("Trying page + 1 sized read (check alignment)\n");
508 io
.readx
.in
.offset
= 0;
509 io
.readx
.in
.mincnt
= 0x1001;
510 io
.readx
.in
.maxcnt
= 0x1001;
511 status
= smb_raw_read(cli
->tree
, &io
);
512 CHECK_STATUS(status
, NT_STATUS_OK
);
513 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
514 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
515 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
516 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
517 CHECK_READX_ALIGN(io
);
519 printf("Trying large read (UINT16_MAX)\n");
520 io
.readx
.in
.offset
= 0;
521 io
.readx
.in
.mincnt
= 0xFFFF;
522 io
.readx
.in
.maxcnt
= 0xFFFF;
523 status
= smb_raw_read(cli
->tree
, &io
);
524 CHECK_STATUS(status
, NT_STATUS_OK
);
525 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
526 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
527 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
528 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
529 CHECK_READX_ALIGN(io
);
531 printf("Trying extra large read\n");
532 io
.readx
.in
.offset
= 0;
533 io
.readx
.in
.mincnt
= 100;
534 io
.readx
.in
.maxcnt
= 80000;
535 status
= smb_raw_read(cli
->tree
, &io
);
536 CHECK_STATUS(status
, NT_STATUS_OK
);
537 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
538 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
539 if (io
.readx
.out
.nread
== io
.readx
.in
.maxcnt
) {
540 printf("SAMBA: large read extension\n");
541 CHECK_VALUE(io
.readx
.out
.nread
, 80000);
543 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
545 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
546 CHECK_READX_ALIGN(io
);
548 printf("Trying mincnt > maxcnt\n");
549 memset(buf
, 0, maxsize
);
550 io
.readx
.in
.offset
= 0;
551 io
.readx
.in
.mincnt
= 30000;
552 io
.readx
.in
.maxcnt
= 20000;
553 status
= smb_raw_read(cli
->tree
, &io
);
554 CHECK_STATUS(status
, NT_STATUS_OK
);
555 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
556 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
557 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
558 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
559 CHECK_READX_ALIGN(io
);
561 printf("Trying mincnt < maxcnt\n");
562 memset(buf
, 0, maxsize
);
563 io
.readx
.in
.offset
= 0;
564 io
.readx
.in
.mincnt
= 20000;
565 io
.readx
.in
.maxcnt
= 30000;
566 status
= smb_raw_read(cli
->tree
, &io
);
567 CHECK_STATUS(status
, NT_STATUS_OK
);
568 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
569 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
570 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
571 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
572 CHECK_READX_ALIGN(io
);
574 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_READX
) {
575 printf("Trying large readx\n");
576 io
.readx
.in
.offset
= 0;
577 io
.readx
.in
.mincnt
= 0;
578 io
.readx
.in
.maxcnt
= 0x10000 - 1;
579 status
= smb_raw_read(cli
->tree
, &io
);
580 CHECK_STATUS(status
, NT_STATUS_OK
);
581 CHECK_VALUE(io
.readx
.out
.nread
, 0xFFFF);
582 CHECK_READX_ALIGN(io
);
584 io
.readx
.in
.maxcnt
= 0x10000;
585 status
= smb_raw_read(cli
->tree
, &io
);
586 CHECK_STATUS(status
, NT_STATUS_OK
);
587 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
588 CHECK_READX_ALIGN(io
);
590 io
.readx
.in
.maxcnt
= 0x10001;
591 status
= smb_raw_read(cli
->tree
, &io
);
592 CHECK_STATUS(status
, NT_STATUS_OK
);
593 if (io
.readx
.out
.nread
== io
.readx
.in
.maxcnt
) {
594 printf("SAMBA: large read extension\n");
595 CHECK_VALUE(io
.readx
.out
.nread
, 0x10001);
597 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
600 printf("Server does not support the CAP_LARGE_READX extension\n");
603 printf("Trying locked region\n");
605 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
606 printf("Failed to lock file at %d\n", __LINE__
);
611 memset(buf
, 0, maxsize
);
612 io
.readx
.in
.offset
= 0;
613 io
.readx
.in
.mincnt
= 100;
614 io
.readx
.in
.maxcnt
= 200;
615 status
= smb_raw_read(cli
->tree
, &io
);
616 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
618 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
619 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
623 printf("Trying large offset read\n");
624 io
.readx
.in
.offset
= ((uint64_t)0x2) << 32;
625 io
.readx
.in
.mincnt
= 10;
626 io
.readx
.in
.maxcnt
= 10;
627 status
= smb_raw_read(cli
->tree
, &io
);
628 CHECK_STATUS(status
, NT_STATUS_OK
);
629 CHECK_VALUE(io
.readx
.out
.nread
, 0);
630 CHECK_READX_ALIGN(io
);
632 if (NT_STATUS_IS_ERR(smbcli_lock64(cli
->tree
, fnum
, io
.readx
.in
.offset
, 1, 0, WRITE_LOCK
))) {
633 printf("Failed to lock file at %d\n", __LINE__
);
638 status
= smb_raw_read(cli
->tree
, &io
);
639 CHECK_STATUS(status
, NT_STATUS_OK
);
640 CHECK_VALUE(io
.readx
.out
.nread
, 0);
641 CHECK_READX_ALIGN(io
);
644 smbcli_close(cli
->tree
, fnum
);
645 smbcli_deltree(cli
->tree
, BASEDIR
);
653 static bool test_readbraw(struct torture_context
*tctx
,
654 struct smbcli_state
*cli
)
661 const int maxsize
= 90000;
662 const char *fname
= BASEDIR
"\\test.txt";
663 const char *test_data
= "TEST DATA";
664 unsigned int seed
= time(NULL
);
666 if (!cli
->transport
->negotiate
.readbraw_supported
) {
667 printf("Server does not support readbraw - skipping\n");
671 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
673 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
675 printf("Testing RAW_READ_READBRAW\n");
677 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
679 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
684 printf("Trying empty file read\n");
685 io
.generic
.level
= RAW_READ_READBRAW
;
686 io
.readbraw
.in
.file
.fnum
= fnum
;
687 io
.readbraw
.in
.mincnt
= 1;
688 io
.readbraw
.in
.maxcnt
= 1;
689 io
.readbraw
.in
.offset
= 0;
690 io
.readbraw
.in
.timeout
= 0;
691 io
.readbraw
.out
.data
= buf
;
692 status
= smb_raw_read(cli
->tree
, &io
);
694 CHECK_STATUS(status
, NT_STATUS_OK
);
695 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
697 printf("Trying zero file read\n");
698 io
.readbraw
.in
.mincnt
= 0;
699 io
.readbraw
.in
.maxcnt
= 0;
700 status
= smb_raw_read(cli
->tree
, &io
);
701 CHECK_STATUS(status
, NT_STATUS_OK
);
702 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
704 printf("Trying bad fnum\n");
705 io
.readbraw
.in
.file
.fnum
= fnum
+1;
706 status
= smb_raw_read(cli
->tree
, &io
);
707 CHECK_STATUS(status
, NT_STATUS_OK
);
708 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
709 io
.readbraw
.in
.file
.fnum
= fnum
;
711 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
713 printf("Trying small read\n");
714 io
.readbraw
.in
.file
.fnum
= fnum
;
715 io
.readbraw
.in
.offset
= 0;
716 io
.readbraw
.in
.mincnt
= strlen(test_data
);
717 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
718 status
= smb_raw_read(cli
->tree
, &io
);
719 CHECK_STATUS(status
, NT_STATUS_OK
);
720 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
));
721 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
723 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
727 printf("Trying short read\n");
728 io
.readbraw
.in
.offset
= 1;
729 io
.readbraw
.in
.mincnt
= strlen(test_data
);
730 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
731 status
= smb_raw_read(cli
->tree
, &io
);
732 CHECK_STATUS(status
, NT_STATUS_OK
);
733 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
)-1);
734 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
736 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
740 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
741 printf("Trying max offset\n");
742 io
.readbraw
.in
.offset
= ~0;
743 io
.readbraw
.in
.mincnt
= strlen(test_data
);
744 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
745 status
= smb_raw_read(cli
->tree
, &io
);
746 CHECK_STATUS(status
, NT_STATUS_OK
);
747 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
750 setup_buffer(buf
, seed
, maxsize
);
751 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
752 memset(buf
, 0, maxsize
);
754 printf("Trying large read\n");
755 io
.readbraw
.in
.offset
= 0;
756 io
.readbraw
.in
.mincnt
= ~0;
757 io
.readbraw
.in
.maxcnt
= ~0;
758 status
= smb_raw_read(cli
->tree
, &io
);
759 CHECK_STATUS(status
, NT_STATUS_OK
);
760 CHECK_VALUE(io
.readbraw
.out
.nread
, 0xFFFF);
761 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
763 printf("Trying mincnt > maxcnt\n");
764 memset(buf
, 0, maxsize
);
765 io
.readbraw
.in
.offset
= 0;
766 io
.readbraw
.in
.mincnt
= 30000;
767 io
.readbraw
.in
.maxcnt
= 20000;
768 status
= smb_raw_read(cli
->tree
, &io
);
769 CHECK_STATUS(status
, NT_STATUS_OK
);
770 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
771 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
773 printf("Trying mincnt < maxcnt\n");
774 memset(buf
, 0, maxsize
);
775 io
.readbraw
.in
.offset
= 0;
776 io
.readbraw
.in
.mincnt
= 20000;
777 io
.readbraw
.in
.maxcnt
= 30000;
778 status
= smb_raw_read(cli
->tree
, &io
);
779 CHECK_STATUS(status
, NT_STATUS_OK
);
780 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
781 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
783 printf("Trying locked region\n");
785 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
786 printf("Failed to lock file at %d\n", __LINE__
);
791 memset(buf
, 0, maxsize
);
792 io
.readbraw
.in
.offset
= 0;
793 io
.readbraw
.in
.mincnt
= 100;
794 io
.readbraw
.in
.maxcnt
= 200;
795 status
= smb_raw_read(cli
->tree
, &io
);
796 CHECK_STATUS(status
, NT_STATUS_OK
);
797 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
799 printf("Trying locked region with timeout\n");
800 memset(buf
, 0, maxsize
);
801 io
.readbraw
.in
.offset
= 0;
802 io
.readbraw
.in
.mincnt
= 100;
803 io
.readbraw
.in
.maxcnt
= 200;
804 io
.readbraw
.in
.timeout
= 10000;
805 status
= smb_raw_read(cli
->tree
, &io
);
806 CHECK_STATUS(status
, NT_STATUS_OK
);
807 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
809 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
810 printf("Trying large offset read\n");
811 io
.readbraw
.in
.offset
= ((uint64_t)0x2) << 32;
812 io
.readbraw
.in
.mincnt
= 10;
813 io
.readbraw
.in
.maxcnt
= 10;
814 io
.readbraw
.in
.timeout
= 0;
815 status
= smb_raw_read(cli
->tree
, &io
);
816 CHECK_STATUS(status
, NT_STATUS_OK
);
817 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
821 smbcli_close(cli
->tree
, fnum
);
822 smbcli_deltree(cli
->tree
, BASEDIR
);
827 test read for execute
829 static bool test_read_for_execute(struct torture_context
*tctx
,
830 struct smbcli_state
*cli
)
839 const int maxsize
= 900;
840 const char *fname
= BASEDIR
"\\test.txt";
841 const uint8_t data
[] = "TEST DATA";
843 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
845 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
847 printf("Testing RAW_READ_READX with read_for_execute\n");
849 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
850 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
851 op
.ntcreatex
.in
.flags
= 0;
852 op
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
853 op
.ntcreatex
.in
.create_options
= 0;
854 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
855 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
856 op
.ntcreatex
.in
.alloc_size
= 0;
857 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
858 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
859 op
.ntcreatex
.in
.security_flags
= 0;
860 op
.ntcreatex
.in
.fname
= fname
;
861 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
862 CHECK_STATUS(status
, NT_STATUS_OK
);
863 fnum
= op
.ntcreatex
.out
.file
.fnum
;
865 wr
.generic
.level
= RAW_WRITE_WRITEX
;
866 wr
.writex
.in
.file
.fnum
= fnum
;
867 wr
.writex
.in
.offset
= 0;
868 wr
.writex
.in
.wmode
= 0;
869 wr
.writex
.in
.remaining
= 0;
870 wr
.writex
.in
.count
= ARRAY_SIZE(data
);
871 wr
.writex
.in
.data
= data
;
872 status
= smb_raw_write(cli
->tree
, &wr
);
873 CHECK_STATUS(status
, NT_STATUS_OK
);
874 CHECK_VALUE(wr
.writex
.out
.nwritten
, ARRAY_SIZE(data
));
876 status
= smbcli_close(cli
->tree
, fnum
);
877 CHECK_STATUS(status
, NT_STATUS_OK
);
879 printf("open file with SEC_FILE_EXECUTE\n");
880 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
881 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
882 op
.ntcreatex
.in
.flags
= 0;
883 op
.ntcreatex
.in
.access_mask
= SEC_FILE_EXECUTE
;
884 op
.ntcreatex
.in
.create_options
= 0;
885 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
886 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
887 op
.ntcreatex
.in
.alloc_size
= 0;
888 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
889 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
890 op
.ntcreatex
.in
.security_flags
= 0;
891 op
.ntcreatex
.in
.fname
= fname
;
892 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
893 CHECK_STATUS(status
, NT_STATUS_OK
);
894 fnum
= op
.ntcreatex
.out
.file
.fnum
;
896 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
897 rd
.generic
.level
= RAW_READ_READX
;
898 rd
.readx
.in
.file
.fnum
= fnum
;
899 rd
.readx
.in
.mincnt
= 0;
900 rd
.readx
.in
.maxcnt
= maxsize
;
901 rd
.readx
.in
.offset
= 0;
902 rd
.readx
.in
.remaining
= 0;
903 rd
.readx
.in
.read_for_execute
= true;
904 rd
.readx
.out
.data
= buf
;
905 status
= smb_raw_read(cli
->tree
, &rd
);
906 CHECK_STATUS(status
, NT_STATUS_OK
);
907 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
908 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
909 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
911 printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
912 rd
.generic
.level
= RAW_READ_READX
;
913 rd
.readx
.in
.file
.fnum
= fnum
;
914 rd
.readx
.in
.mincnt
= 0;
915 rd
.readx
.in
.maxcnt
= maxsize
;
916 rd
.readx
.in
.offset
= 0;
917 rd
.readx
.in
.remaining
= 0;
918 rd
.readx
.in
.read_for_execute
= false;
919 rd
.readx
.out
.data
= buf
;
920 status
= smb_raw_read(cli
->tree
, &rd
);
921 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
923 status
= smbcli_close(cli
->tree
, fnum
);
924 CHECK_STATUS(status
, NT_STATUS_OK
);
926 printf("open file with SEC_FILE_READ_DATA\n");
927 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
928 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
929 op
.ntcreatex
.in
.flags
= 0;
930 op
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
931 op
.ntcreatex
.in
.create_options
= 0;
932 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
933 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
934 op
.ntcreatex
.in
.alloc_size
= 0;
935 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
936 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
937 op
.ntcreatex
.in
.security_flags
= 0;
938 op
.ntcreatex
.in
.fname
= fname
;
939 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
940 CHECK_STATUS(status
, NT_STATUS_OK
);
941 fnum
= op
.ntcreatex
.out
.file
.fnum
;
943 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
944 rd
.generic
.level
= RAW_READ_READX
;
945 rd
.readx
.in
.file
.fnum
= fnum
;
946 rd
.readx
.in
.mincnt
= 0;
947 rd
.readx
.in
.maxcnt
= maxsize
;
948 rd
.readx
.in
.offset
= 0;
949 rd
.readx
.in
.remaining
= 0;
950 rd
.readx
.in
.read_for_execute
= true;
951 rd
.readx
.out
.data
= buf
;
952 status
= smb_raw_read(cli
->tree
, &rd
);
953 CHECK_STATUS(status
, NT_STATUS_OK
);
954 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
955 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
956 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
958 printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
959 rd
.generic
.level
= RAW_READ_READX
;
960 rd
.readx
.in
.file
.fnum
= fnum
;
961 rd
.readx
.in
.mincnt
= 0;
962 rd
.readx
.in
.maxcnt
= maxsize
;
963 rd
.readx
.in
.offset
= 0;
964 rd
.readx
.in
.remaining
= 0;
965 rd
.readx
.in
.read_for_execute
= false;
966 rd
.readx
.out
.data
= buf
;
967 status
= smb_raw_read(cli
->tree
, &rd
);
968 CHECK_STATUS(status
, NT_STATUS_OK
);
969 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
970 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
971 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
974 smbcli_close(cli
->tree
, fnum
);
975 smbcli_deltree(cli
->tree
, BASEDIR
);
981 basic testing of read calls
983 struct torture_suite
*torture_raw_read(TALLOC_CTX
*mem_ctx
)
985 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "read");
987 torture_suite_add_1smb_test(suite
, "read", test_read
);
988 torture_suite_add_1smb_test(suite
, "readx", test_readx
);
989 torture_suite_add_1smb_test(suite
, "lockread", test_lockread
);
990 torture_suite_add_1smb_test(suite
, "readbraw", test_readbraw
);
991 torture_suite_add_1smb_test(suite
, "read for execute",
992 test_read_for_execute
);