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 "torture/torture.h"
22 #include "libcli/raw/libcliraw.h"
23 #include "libcli/raw/raw_proto.h"
24 #include "system/time.h"
25 #include "system/filesys.h"
26 #include "libcli/libcli.h"
27 #include "torture/util.h"
29 #define CHECK_STATUS(status, correct) do { \
30 if (!NT_STATUS_EQUAL(status, correct)) { \
31 printf("(%s) Incorrect status %s - should be %s\n", \
32 __location__, nt_errstr(status), nt_errstr(correct)); \
37 #define CHECK_VALUE(v, correct) do { \
38 if ((v) != (correct)) { \
39 printf("(%s) Incorrect value %s=%ld - should be %ld\n", \
40 __location__, #v, (long)v, (long)correct); \
45 #define CHECK_BUFFER(buf, seed, len) do { \
46 if (!check_buffer(buf, seed, len, __LINE__)) { \
51 #define BASEDIR "\\testread"
55 setup a random buffer based on a seed
57 static void setup_buffer(uint8_t *buf
, uint_t 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(uint8_t *buf
, uint_t seed
, int len
, int line
)
74 printf("Buffer incorrect at line %d! ofs=%d v1=0x%x v2=0x%x\n",
85 static bool test_read(struct torture_context
*tctx
, struct smbcli_state
*cli
)
92 const int maxsize
= 90000;
93 const char *fname
= BASEDIR
"\\test.txt";
94 const char *test_data
= "TEST DATA";
95 uint_t seed
= time(NULL
);
97 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
99 if (!torture_setup_dir(cli
, BASEDIR
)) {
103 printf("Testing RAW_READ_READ\n");
104 io
.generic
.level
= RAW_READ_READ
;
106 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
108 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
113 printf("Trying empty file read\n");
114 io
.read
.in
.file
.fnum
= fnum
;
115 io
.read
.in
.count
= 1;
116 io
.read
.in
.offset
= 0;
117 io
.read
.in
.remaining
= 0;
118 io
.read
.out
.data
= buf
;
119 status
= smb_raw_read(cli
->tree
, &io
);
121 CHECK_STATUS(status
, NT_STATUS_OK
);
122 CHECK_VALUE(io
.read
.out
.nread
, 0);
124 printf("Trying zero file read\n");
125 io
.read
.in
.count
= 0;
126 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 bad fnum\n");
131 io
.read
.in
.file
.fnum
= fnum
+1;
132 status
= smb_raw_read(cli
->tree
, &io
);
133 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
134 io
.read
.in
.file
.fnum
= fnum
;
136 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
138 printf("Trying small read\n");
139 io
.read
.in
.file
.fnum
= fnum
;
140 io
.read
.in
.offset
= 0;
141 io
.read
.in
.remaining
= 0;
142 io
.read
.in
.count
= strlen(test_data
);
143 status
= smb_raw_read(cli
->tree
, &io
);
144 CHECK_STATUS(status
, NT_STATUS_OK
);
145 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
));
146 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
148 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
152 printf("Trying short read\n");
153 io
.read
.in
.offset
= 1;
154 io
.read
.in
.count
= strlen(test_data
);
155 status
= smb_raw_read(cli
->tree
, &io
);
156 CHECK_STATUS(status
, NT_STATUS_OK
);
157 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
)-1);
158 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
160 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
164 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
165 printf("Trying max offset\n");
166 io
.read
.in
.offset
= ~0;
167 io
.read
.in
.count
= strlen(test_data
);
168 status
= smb_raw_read(cli
->tree
, &io
);
169 CHECK_STATUS(status
, NT_STATUS_OK
);
170 CHECK_VALUE(io
.read
.out
.nread
, 0);
173 setup_buffer(buf
, seed
, maxsize
);
174 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
175 memset(buf
, 0, maxsize
);
177 printf("Trying large read\n");
178 io
.read
.in
.offset
= 0;
179 io
.read
.in
.count
= ~0;
180 status
= smb_raw_read(cli
->tree
, &io
);
181 CHECK_STATUS(status
, NT_STATUS_OK
);
182 CHECK_BUFFER(buf
, seed
, io
.read
.out
.nread
);
185 printf("Trying locked region\n");
187 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
188 printf("Failed to lock file at %d\n", __LINE__
);
193 memset(buf
, 0, maxsize
);
194 io
.read
.in
.offset
= 0;
195 io
.read
.in
.count
= ~0;
196 status
= smb_raw_read(cli
->tree
, &io
);
197 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
201 smbcli_close(cli
->tree
, fnum
);
202 smb_raw_exit(cli
->session
);
203 smbcli_deltree(cli
->tree
, BASEDIR
);
211 static bool test_lockread(struct torture_context
*tctx
,
212 struct smbcli_state
*cli
)
219 const int maxsize
= 90000;
220 const char *fname
= BASEDIR
"\\test.txt";
221 const char *test_data
= "TEST DATA";
222 uint_t seed
= time(NULL
);
224 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
226 if (!torture_setup_dir(cli
, BASEDIR
)) {
230 printf("Testing RAW_READ_LOCKREAD\n");
231 io
.generic
.level
= RAW_READ_LOCKREAD
;
233 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
235 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
240 printf("Trying empty file read\n");
241 io
.lockread
.in
.file
.fnum
= fnum
;
242 io
.lockread
.in
.count
= 1;
243 io
.lockread
.in
.offset
= 1;
244 io
.lockread
.in
.remaining
= 0;
245 io
.lockread
.out
.data
= buf
;
246 status
= smb_raw_read(cli
->tree
, &io
);
248 CHECK_STATUS(status
, NT_STATUS_OK
);
249 CHECK_VALUE(io
.lockread
.out
.nread
, 0);
251 status
= smb_raw_read(cli
->tree
, &io
);
252 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
254 status
= smb_raw_read(cli
->tree
, &io
);
255 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
257 printf("Trying zero file read\n");
258 io
.lockread
.in
.count
= 0;
259 status
= smb_raw_read(cli
->tree
, &io
);
260 CHECK_STATUS(status
, NT_STATUS_OK
);
262 smbcli_unlock(cli
->tree
, fnum
, 1, 1);
264 printf("Trying bad fnum\n");
265 io
.lockread
.in
.file
.fnum
= fnum
+1;
266 status
= smb_raw_read(cli
->tree
, &io
);
267 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
268 io
.lockread
.in
.file
.fnum
= fnum
;
270 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
272 printf("Trying small read\n");
273 io
.lockread
.in
.file
.fnum
= fnum
;
274 io
.lockread
.in
.offset
= 0;
275 io
.lockread
.in
.remaining
= 0;
276 io
.lockread
.in
.count
= strlen(test_data
);
277 status
= smb_raw_read(cli
->tree
, &io
);
278 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
280 smbcli_unlock(cli
->tree
, fnum
, 1, 0);
282 status
= smb_raw_read(cli
->tree
, &io
);
283 CHECK_STATUS(status
, NT_STATUS_OK
);
284 CHECK_VALUE(io
.lockread
.out
.nread
, strlen(test_data
));
285 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
287 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
291 printf("Trying short read\n");
292 io
.lockread
.in
.offset
= 1;
293 io
.lockread
.in
.count
= strlen(test_data
);
294 status
= smb_raw_read(cli
->tree
, &io
);
295 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
296 smbcli_unlock(cli
->tree
, fnum
, 0, strlen(test_data
));
297 status
= smb_raw_read(cli
->tree
, &io
);
298 CHECK_STATUS(status
, NT_STATUS_OK
);
300 CHECK_VALUE(io
.lockread
.out
.nread
, strlen(test_data
)-1);
301 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
303 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
307 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
308 printf("Trying max offset\n");
309 io
.lockread
.in
.offset
= ~0;
310 io
.lockread
.in
.count
= strlen(test_data
);
311 status
= smb_raw_read(cli
->tree
, &io
);
312 CHECK_STATUS(status
, NT_STATUS_OK
);
313 CHECK_VALUE(io
.lockread
.out
.nread
, 0);
316 setup_buffer(buf
, seed
, maxsize
);
317 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
318 memset(buf
, 0, maxsize
);
320 printf("Trying large read\n");
321 io
.lockread
.in
.offset
= 0;
322 io
.lockread
.in
.count
= ~0;
323 status
= smb_raw_read(cli
->tree
, &io
);
324 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
325 smbcli_unlock(cli
->tree
, fnum
, 1, strlen(test_data
));
326 status
= smb_raw_read(cli
->tree
, &io
);
327 CHECK_STATUS(status
, NT_STATUS_OK
);
328 CHECK_BUFFER(buf
, seed
, io
.lockread
.out
.nread
);
329 smbcli_unlock(cli
->tree
, fnum
, 0, 0xFFFF);
332 printf("Trying locked region\n");
334 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
335 printf("Failed to lock file at %d\n", __LINE__
);
340 memset(buf
, 0, maxsize
);
341 io
.lockread
.in
.offset
= 0;
342 io
.lockread
.in
.count
= ~0;
343 status
= smb_raw_read(cli
->tree
, &io
);
344 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
348 smbcli_close(cli
->tree
, fnum
);
349 smbcli_deltree(cli
->tree
, BASEDIR
);
357 static bool test_readx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
364 const int maxsize
= 90000;
365 const char *fname
= BASEDIR
"\\test.txt";
366 const char *test_data
= "TEST DATA";
367 uint_t seed
= time(NULL
);
369 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
371 if (!torture_setup_dir(cli
, BASEDIR
)) {
375 printf("Testing RAW_READ_READX\n");
377 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
379 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
384 printf("Trying empty file read\n");
385 io
.generic
.level
= RAW_READ_READX
;
386 io
.readx
.in
.file
.fnum
= fnum
;
387 io
.readx
.in
.mincnt
= 1;
388 io
.readx
.in
.maxcnt
= 1;
389 io
.readx
.in
.offset
= 0;
390 io
.readx
.in
.remaining
= 0;
391 io
.readx
.in
.read_for_execute
= false;
392 io
.readx
.out
.data
= buf
;
393 status
= smb_raw_read(cli
->tree
, &io
);
395 CHECK_STATUS(status
, NT_STATUS_OK
);
396 CHECK_VALUE(io
.readx
.out
.nread
, 0);
397 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
398 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
400 printf("Trying zero file read\n");
401 io
.readx
.in
.mincnt
= 0;
402 io
.readx
.in
.maxcnt
= 0;
403 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);
409 printf("Trying bad fnum\n");
410 io
.readx
.in
.file
.fnum
= fnum
+1;
411 status
= smb_raw_read(cli
->tree
, &io
);
412 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
413 io
.readx
.in
.file
.fnum
= fnum
;
415 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
417 printf("Trying small read\n");
418 io
.readx
.in
.file
.fnum
= fnum
;
419 io
.readx
.in
.offset
= 0;
420 io
.readx
.in
.remaining
= 0;
421 io
.readx
.in
.read_for_execute
= false;
422 io
.readx
.in
.mincnt
= strlen(test_data
);
423 io
.readx
.in
.maxcnt
= strlen(test_data
);
424 status
= smb_raw_read(cli
->tree
, &io
);
425 CHECK_STATUS(status
, NT_STATUS_OK
);
426 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
427 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
428 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
429 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
431 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
435 printf("Trying short read\n");
436 io
.readx
.in
.offset
= 1;
437 io
.readx
.in
.mincnt
= strlen(test_data
);
438 io
.readx
.in
.maxcnt
= strlen(test_data
);
439 status
= smb_raw_read(cli
->tree
, &io
);
440 CHECK_STATUS(status
, NT_STATUS_OK
);
441 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
)-1);
442 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
443 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
444 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
446 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
450 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
451 printf("Trying max offset\n");
452 io
.readx
.in
.offset
= 0xffffffff;
453 io
.readx
.in
.mincnt
= strlen(test_data
);
454 io
.readx
.in
.maxcnt
= strlen(test_data
);
455 status
= smb_raw_read(cli
->tree
, &io
);
456 CHECK_STATUS(status
, NT_STATUS_OK
);
457 CHECK_VALUE(io
.readx
.out
.nread
, 0);
458 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
459 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
462 printf("Trying mincnt past EOF\n");
463 memset(buf
, 0, maxsize
);
464 io
.readx
.in
.offset
= 0;
465 io
.readx
.in
.mincnt
= 100;
466 io
.readx
.in
.maxcnt
= 110;
467 status
= smb_raw_read(cli
->tree
, &io
);
468 CHECK_STATUS(status
, NT_STATUS_OK
);
469 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
470 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
471 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
472 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
474 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
479 setup_buffer(buf
, seed
, maxsize
);
480 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
481 memset(buf
, 0, maxsize
);
483 printf("Trying large read\n");
484 io
.readx
.in
.offset
= 0;
485 io
.readx
.in
.mincnt
= 0xFFFF;
486 io
.readx
.in
.maxcnt
= 0xFFFF;
487 status
= smb_raw_read(cli
->tree
, &io
);
488 CHECK_STATUS(status
, NT_STATUS_OK
);
489 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
490 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
491 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
492 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
494 printf("Trying extra large read\n");
495 io
.readx
.in
.offset
= 0;
496 io
.readx
.in
.mincnt
= 100;
497 io
.readx
.in
.maxcnt
= 80000;
498 status
= smb_raw_read(cli
->tree
, &io
);
499 CHECK_STATUS(status
, NT_STATUS_OK
);
500 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
501 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
502 if (torture_setting_bool(tctx
, "samba3", false) ||
503 torture_setting_bool(tctx
, "samba4", false)) {
504 printf("SAMBA: large read extension\n");
505 CHECK_VALUE(io
.readx
.out
.nread
, 80000);
507 CHECK_VALUE(io
.readx
.out
.nread
, 0);
509 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
511 printf("Trying mincnt > maxcnt\n");
512 memset(buf
, 0, maxsize
);
513 io
.readx
.in
.offset
= 0;
514 io
.readx
.in
.mincnt
= 30000;
515 io
.readx
.in
.maxcnt
= 20000;
516 status
= smb_raw_read(cli
->tree
, &io
);
517 CHECK_STATUS(status
, NT_STATUS_OK
);
518 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
519 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
520 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
521 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
523 printf("Trying mincnt < maxcnt\n");
524 memset(buf
, 0, maxsize
);
525 io
.readx
.in
.offset
= 0;
526 io
.readx
.in
.mincnt
= 20000;
527 io
.readx
.in
.maxcnt
= 30000;
528 status
= smb_raw_read(cli
->tree
, &io
);
529 CHECK_STATUS(status
, NT_STATUS_OK
);
530 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
531 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
532 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
533 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
535 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_READX
) {
536 printf("Trying large readx\n");
537 io
.readx
.in
.offset
= 0;
538 io
.readx
.in
.mincnt
= 0;
539 io
.readx
.in
.maxcnt
= 0x10000 - 1;
540 status
= smb_raw_read(cli
->tree
, &io
);
541 CHECK_STATUS(status
, NT_STATUS_OK
);
542 CHECK_VALUE(io
.readx
.out
.nread
, 0xFFFF);
544 io
.readx
.in
.maxcnt
= 0x10000;
545 status
= smb_raw_read(cli
->tree
, &io
);
546 CHECK_STATUS(status
, NT_STATUS_OK
);
547 if (torture_setting_bool(tctx
, "samba3", false) ||
548 torture_setting_bool(tctx
, "samba4", false)) {
549 printf("SAMBA: large read extension\n");
550 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
552 CHECK_VALUE(io
.readx
.out
.nread
, 0);
555 io
.readx
.in
.maxcnt
= 0x10001;
556 status
= smb_raw_read(cli
->tree
, &io
);
557 CHECK_STATUS(status
, NT_STATUS_OK
);
558 if (torture_setting_bool(tctx
, "samba3", false) ||
559 torture_setting_bool(tctx
, "samba4", false)) {
560 printf("SAMBA: large read extension\n");
561 CHECK_VALUE(io
.readx
.out
.nread
, 0x10001);
563 CHECK_VALUE(io
.readx
.out
.nread
, 0);
566 printf("Server does not support the CAP_LARGE_READX extension\n");
569 printf("Trying locked region\n");
571 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
572 printf("Failed to lock file at %d\n", __LINE__
);
577 memset(buf
, 0, maxsize
);
578 io
.readx
.in
.offset
= 0;
579 io
.readx
.in
.mincnt
= 100;
580 io
.readx
.in
.maxcnt
= 200;
581 status
= smb_raw_read(cli
->tree
, &io
);
582 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
584 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
585 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
589 printf("Trying large offset read\n");
590 io
.readx
.in
.offset
= ((uint64_t)0x2) << 32;
591 io
.readx
.in
.mincnt
= 10;
592 io
.readx
.in
.maxcnt
= 10;
593 status
= smb_raw_read(cli
->tree
, &io
);
594 CHECK_STATUS(status
, NT_STATUS_OK
);
595 CHECK_VALUE(io
.readx
.out
.nread
, 0);
597 if (NT_STATUS_IS_ERR(smbcli_lock64(cli
->tree
, fnum
, io
.readx
.in
.offset
, 1, 0, WRITE_LOCK
))) {
598 printf("Failed to lock file at %d\n", __LINE__
);
603 status
= smb_raw_read(cli
->tree
, &io
);
604 CHECK_STATUS(status
, NT_STATUS_OK
);
605 CHECK_VALUE(io
.readx
.out
.nread
, 0);
608 smbcli_close(cli
->tree
, fnum
);
609 smbcli_deltree(cli
->tree
, BASEDIR
);
617 static bool test_readbraw(struct torture_context
*tctx
,
618 struct smbcli_state
*cli
)
625 const int maxsize
= 90000;
626 const char *fname
= BASEDIR
"\\test.txt";
627 const char *test_data
= "TEST DATA";
628 uint_t seed
= time(NULL
);
630 if (!cli
->transport
->negotiate
.readbraw_supported
) {
631 printf("Server does not support readbraw - skipping\n");
635 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
637 if (!torture_setup_dir(cli
, BASEDIR
)) {
641 printf("Testing RAW_READ_READBRAW\n");
643 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
645 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
650 printf("Trying empty file read\n");
651 io
.generic
.level
= RAW_READ_READBRAW
;
652 io
.readbraw
.in
.file
.fnum
= fnum
;
653 io
.readbraw
.in
.mincnt
= 1;
654 io
.readbraw
.in
.maxcnt
= 1;
655 io
.readbraw
.in
.offset
= 0;
656 io
.readbraw
.in
.timeout
= 0;
657 io
.readbraw
.out
.data
= buf
;
658 status
= smb_raw_read(cli
->tree
, &io
);
660 CHECK_STATUS(status
, NT_STATUS_OK
);
661 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
663 printf("Trying zero file read\n");
664 io
.readbraw
.in
.mincnt
= 0;
665 io
.readbraw
.in
.maxcnt
= 0;
666 status
= smb_raw_read(cli
->tree
, &io
);
667 CHECK_STATUS(status
, NT_STATUS_OK
);
668 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
670 printf("Trying bad fnum\n");
671 io
.readbraw
.in
.file
.fnum
= fnum
+1;
672 status
= smb_raw_read(cli
->tree
, &io
);
673 CHECK_STATUS(status
, NT_STATUS_OK
);
674 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
675 io
.readbraw
.in
.file
.fnum
= fnum
;
677 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
679 printf("Trying small read\n");
680 io
.readbraw
.in
.file
.fnum
= fnum
;
681 io
.readbraw
.in
.offset
= 0;
682 io
.readbraw
.in
.mincnt
= strlen(test_data
);
683 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
684 status
= smb_raw_read(cli
->tree
, &io
);
685 CHECK_STATUS(status
, NT_STATUS_OK
);
686 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
));
687 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
689 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
693 printf("Trying short read\n");
694 io
.readbraw
.in
.offset
= 1;
695 io
.readbraw
.in
.mincnt
= strlen(test_data
);
696 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
697 status
= smb_raw_read(cli
->tree
, &io
);
698 CHECK_STATUS(status
, NT_STATUS_OK
);
699 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
)-1);
700 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
702 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
706 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
707 printf("Trying max offset\n");
708 io
.readbraw
.in
.offset
= ~0;
709 io
.readbraw
.in
.mincnt
= strlen(test_data
);
710 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
711 status
= smb_raw_read(cli
->tree
, &io
);
712 CHECK_STATUS(status
, NT_STATUS_OK
);
713 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
716 setup_buffer(buf
, seed
, maxsize
);
717 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
718 memset(buf
, 0, maxsize
);
720 printf("Trying large read\n");
721 io
.readbraw
.in
.offset
= 0;
722 io
.readbraw
.in
.mincnt
= ~0;
723 io
.readbraw
.in
.maxcnt
= ~0;
724 status
= smb_raw_read(cli
->tree
, &io
);
725 CHECK_STATUS(status
, NT_STATUS_OK
);
726 CHECK_VALUE(io
.readbraw
.out
.nread
, 0xFFFF);
727 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
729 printf("Trying mincnt > maxcnt\n");
730 memset(buf
, 0, maxsize
);
731 io
.readbraw
.in
.offset
= 0;
732 io
.readbraw
.in
.mincnt
= 30000;
733 io
.readbraw
.in
.maxcnt
= 20000;
734 status
= smb_raw_read(cli
->tree
, &io
);
735 CHECK_STATUS(status
, NT_STATUS_OK
);
736 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
737 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
739 printf("Trying mincnt < maxcnt\n");
740 memset(buf
, 0, maxsize
);
741 io
.readbraw
.in
.offset
= 0;
742 io
.readbraw
.in
.mincnt
= 20000;
743 io
.readbraw
.in
.maxcnt
= 30000;
744 status
= smb_raw_read(cli
->tree
, &io
);
745 CHECK_STATUS(status
, NT_STATUS_OK
);
746 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
747 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
749 printf("Trying locked region\n");
751 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
752 printf("Failed to lock file at %d\n", __LINE__
);
757 memset(buf
, 0, maxsize
);
758 io
.readbraw
.in
.offset
= 0;
759 io
.readbraw
.in
.mincnt
= 100;
760 io
.readbraw
.in
.maxcnt
= 200;
761 status
= smb_raw_read(cli
->tree
, &io
);
762 CHECK_STATUS(status
, NT_STATUS_OK
);
763 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
765 printf("Trying locked region with timeout\n");
766 memset(buf
, 0, maxsize
);
767 io
.readbraw
.in
.offset
= 0;
768 io
.readbraw
.in
.mincnt
= 100;
769 io
.readbraw
.in
.maxcnt
= 200;
770 io
.readbraw
.in
.timeout
= 10000;
771 status
= smb_raw_read(cli
->tree
, &io
);
772 CHECK_STATUS(status
, NT_STATUS_OK
);
773 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
775 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
776 printf("Trying large offset read\n");
777 io
.readbraw
.in
.offset
= ((uint64_t)0x2) << 32;
778 io
.readbraw
.in
.mincnt
= 10;
779 io
.readbraw
.in
.maxcnt
= 10;
780 io
.readbraw
.in
.timeout
= 0;
781 status
= smb_raw_read(cli
->tree
, &io
);
782 CHECK_STATUS(status
, NT_STATUS_OK
);
783 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
787 smbcli_close(cli
->tree
, fnum
);
788 smbcli_deltree(cli
->tree
, BASEDIR
);
793 test read for execute
795 static bool test_read_for_execute(struct torture_context
*tctx
,
796 struct smbcli_state
*cli
)
805 const int maxsize
= 900;
806 const char *fname
= BASEDIR
"\\test.txt";
807 const uint8_t data
[] = "TEST DATA";
809 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
811 if (!torture_setup_dir(cli
, BASEDIR
)) {
815 printf("Testing RAW_READ_READX with read_for_execute\n");
817 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
818 op
.ntcreatex
.in
.root_fid
= 0;
819 op
.ntcreatex
.in
.flags
= 0;
820 op
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
821 op
.ntcreatex
.in
.create_options
= 0;
822 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
823 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
824 op
.ntcreatex
.in
.alloc_size
= 0;
825 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
826 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
827 op
.ntcreatex
.in
.security_flags
= 0;
828 op
.ntcreatex
.in
.fname
= fname
;
829 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
830 CHECK_STATUS(status
, NT_STATUS_OK
);
831 fnum
= op
.ntcreatex
.out
.file
.fnum
;
833 wr
.generic
.level
= RAW_WRITE_WRITEX
;
834 wr
.writex
.in
.file
.fnum
= fnum
;
835 wr
.writex
.in
.offset
= 0;
836 wr
.writex
.in
.wmode
= 0;
837 wr
.writex
.in
.remaining
= 0;
838 wr
.writex
.in
.count
= ARRAY_SIZE(data
);
839 wr
.writex
.in
.data
= data
;
840 status
= smb_raw_write(cli
->tree
, &wr
);
841 CHECK_STATUS(status
, NT_STATUS_OK
);
842 CHECK_VALUE(wr
.writex
.out
.nwritten
, ARRAY_SIZE(data
));
844 status
= smbcli_close(cli
->tree
, fnum
);
845 CHECK_STATUS(status
, NT_STATUS_OK
);
847 printf("open file with SEC_FILE_EXECUTE\n");
848 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
849 op
.ntcreatex
.in
.root_fid
= 0;
850 op
.ntcreatex
.in
.flags
= 0;
851 op
.ntcreatex
.in
.access_mask
= SEC_FILE_EXECUTE
;
852 op
.ntcreatex
.in
.create_options
= 0;
853 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
854 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
855 op
.ntcreatex
.in
.alloc_size
= 0;
856 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
857 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
858 op
.ntcreatex
.in
.security_flags
= 0;
859 op
.ntcreatex
.in
.fname
= fname
;
860 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
861 CHECK_STATUS(status
, NT_STATUS_OK
);
862 fnum
= op
.ntcreatex
.out
.file
.fnum
;
864 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
865 rd
.generic
.level
= RAW_READ_READX
;
866 rd
.readx
.in
.file
.fnum
= fnum
;
867 rd
.readx
.in
.mincnt
= 0;
868 rd
.readx
.in
.maxcnt
= maxsize
;
869 rd
.readx
.in
.offset
= 0;
870 rd
.readx
.in
.remaining
= 0;
871 rd
.readx
.in
.read_for_execute
= true;
872 rd
.readx
.out
.data
= buf
;
873 status
= smb_raw_read(cli
->tree
, &rd
);
874 CHECK_STATUS(status
, NT_STATUS_OK
);
875 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
876 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
877 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
879 printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
880 rd
.generic
.level
= RAW_READ_READX
;
881 rd
.readx
.in
.file
.fnum
= fnum
;
882 rd
.readx
.in
.mincnt
= 0;
883 rd
.readx
.in
.maxcnt
= maxsize
;
884 rd
.readx
.in
.offset
= 0;
885 rd
.readx
.in
.remaining
= 0;
886 rd
.readx
.in
.read_for_execute
= false;
887 rd
.readx
.out
.data
= buf
;
888 status
= smb_raw_read(cli
->tree
, &rd
);
889 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
891 status
= smbcli_close(cli
->tree
, fnum
);
892 CHECK_STATUS(status
, NT_STATUS_OK
);
894 printf("open file with SEC_FILE_READ_DATA\n");
895 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
896 op
.ntcreatex
.in
.root_fid
= 0;
897 op
.ntcreatex
.in
.flags
= 0;
898 op
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
899 op
.ntcreatex
.in
.create_options
= 0;
900 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
901 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
902 op
.ntcreatex
.in
.alloc_size
= 0;
903 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
904 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
905 op
.ntcreatex
.in
.security_flags
= 0;
906 op
.ntcreatex
.in
.fname
= fname
;
907 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
908 CHECK_STATUS(status
, NT_STATUS_OK
);
909 fnum
= op
.ntcreatex
.out
.file
.fnum
;
911 printf("read with FLAGS2_READ_PERMIT_EXECUTE\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
= true;
919 rd
.readx
.out
.data
= buf
;
920 status
= smb_raw_read(cli
->tree
, &rd
);
921 CHECK_STATUS(status
, NT_STATUS_OK
);
922 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
923 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
924 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
926 printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
927 rd
.generic
.level
= RAW_READ_READX
;
928 rd
.readx
.in
.file
.fnum
= fnum
;
929 rd
.readx
.in
.mincnt
= 0;
930 rd
.readx
.in
.maxcnt
= maxsize
;
931 rd
.readx
.in
.offset
= 0;
932 rd
.readx
.in
.remaining
= 0;
933 rd
.readx
.in
.read_for_execute
= false;
934 rd
.readx
.out
.data
= buf
;
935 status
= smb_raw_read(cli
->tree
, &rd
);
936 CHECK_STATUS(status
, NT_STATUS_OK
);
937 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
938 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
939 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
942 smbcli_close(cli
->tree
, fnum
);
943 smbcli_deltree(cli
->tree
, BASEDIR
);
949 basic testing of read calls
951 struct torture_suite
*torture_raw_read(TALLOC_CTX
*mem_ctx
)
953 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "READ");
955 torture_suite_add_1smb_test(suite
, "read", test_read
);
956 torture_suite_add_1smb_test(suite
, "readx", test_readx
);
957 torture_suite_add_1smb_test(suite
, "lockread", test_lockread
);
958 torture_suite_add_1smb_test(suite
, "readbraw", test_readbraw
);
959 torture_suite_add_1smb_test(suite
, "read for execute",
960 test_read_for_execute
);