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 if (!NT_STATUS_EQUAL(status, correct)) { \
30 printf("(%s) Incorrect status %s - should be %s\n", \
31 __location__, nt_errstr(status), nt_errstr(correct)); \
36 #define CHECK_VALUE(v, correct) do { \
37 if ((v) != (correct)) { \
38 printf("(%s) Incorrect value %s=%ld - should be %ld\n", \
39 __location__, #v, (long)v, (long)correct); \
44 #define CHECK_BUFFER(buf, seed, len) do { \
45 if (!check_buffer(buf, seed, len, __LINE__)) { \
50 #define BASEDIR "\\testread"
54 setup a random buffer based on a seed
56 static void setup_buffer(uint8_t *buf
, unsigned int seed
, int len
)
60 for (i
=0;i
<len
;i
++) buf
[i
] = random();
64 check a random buffer based on a seed
66 static bool check_buffer(uint8_t *buf
, unsigned int seed
, int len
, int line
)
73 printf("Buffer incorrect at line %d! ofs=%d v1=0x%x v2=0x%x\n",
84 static bool test_read(struct torture_context
*tctx
, struct smbcli_state
*cli
)
91 const int maxsize
= 90000;
92 const char *fname
= BASEDIR
"\\test.txt";
93 const char *test_data
= "TEST DATA";
94 unsigned int seed
= time(NULL
);
96 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
98 if (!torture_setting_bool(tctx
, "read_support", true)) {
99 printf("server refuses to support READ\n");
103 if (!torture_setup_dir(cli
, BASEDIR
)) {
107 printf("Testing RAW_READ_READ\n");
108 io
.generic
.level
= RAW_READ_READ
;
110 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
112 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
117 printf("Trying empty file read\n");
118 io
.read
.in
.file
.fnum
= fnum
;
119 io
.read
.in
.count
= 1;
120 io
.read
.in
.offset
= 0;
121 io
.read
.in
.remaining
= 0;
122 io
.read
.out
.data
= buf
;
123 status
= smb_raw_read(cli
->tree
, &io
);
125 CHECK_STATUS(status
, NT_STATUS_OK
);
126 CHECK_VALUE(io
.read
.out
.nread
, 0);
128 printf("Trying zero file read\n");
129 io
.read
.in
.count
= 0;
130 status
= smb_raw_read(cli
->tree
, &io
);
131 CHECK_STATUS(status
, NT_STATUS_OK
);
132 CHECK_VALUE(io
.read
.out
.nread
, 0);
134 printf("Trying bad fnum\n");
135 io
.read
.in
.file
.fnum
= fnum
+1;
136 status
= smb_raw_read(cli
->tree
, &io
);
137 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
138 io
.read
.in
.file
.fnum
= fnum
;
140 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
142 printf("Trying small read\n");
143 io
.read
.in
.file
.fnum
= fnum
;
144 io
.read
.in
.offset
= 0;
145 io
.read
.in
.remaining
= 0;
146 io
.read
.in
.count
= strlen(test_data
);
147 status
= smb_raw_read(cli
->tree
, &io
);
148 CHECK_STATUS(status
, NT_STATUS_OK
);
149 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
));
150 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
152 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
156 printf("Trying short read\n");
157 io
.read
.in
.offset
= 1;
158 io
.read
.in
.count
= strlen(test_data
);
159 status
= smb_raw_read(cli
->tree
, &io
);
160 CHECK_STATUS(status
, NT_STATUS_OK
);
161 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
)-1);
162 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
164 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
168 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
169 printf("Trying max offset\n");
170 io
.read
.in
.offset
= ~0;
171 io
.read
.in
.count
= strlen(test_data
);
172 status
= smb_raw_read(cli
->tree
, &io
);
173 CHECK_STATUS(status
, NT_STATUS_OK
);
174 CHECK_VALUE(io
.read
.out
.nread
, 0);
177 setup_buffer(buf
, seed
, maxsize
);
178 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
179 memset(buf
, 0, maxsize
);
181 printf("Trying large read\n");
182 io
.read
.in
.offset
= 0;
183 io
.read
.in
.count
= ~0;
184 status
= smb_raw_read(cli
->tree
, &io
);
185 CHECK_STATUS(status
, NT_STATUS_OK
);
186 CHECK_BUFFER(buf
, seed
, io
.read
.out
.nread
);
189 printf("Trying locked region\n");
191 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
192 printf("Failed to lock file at %d\n", __LINE__
);
197 memset(buf
, 0, maxsize
);
198 io
.read
.in
.offset
= 0;
199 io
.read
.in
.count
= ~0;
200 status
= smb_raw_read(cli
->tree
, &io
);
201 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
205 smbcli_close(cli
->tree
, fnum
);
206 smb_raw_exit(cli
->session
);
207 smbcli_deltree(cli
->tree
, BASEDIR
);
215 static bool test_lockread(struct torture_context
*tctx
,
216 struct smbcli_state
*cli
)
223 const int maxsize
= 90000;
224 const char *fname
= BASEDIR
"\\test.txt";
225 const char *test_data
= "TEST DATA";
226 unsigned int seed
= time(NULL
);
228 if (!cli
->transport
->negotiate
.lockread_supported
) {
229 printf("Server does not support lockread - skipping\n");
233 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
235 if (!torture_setup_dir(cli
, 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
);
378 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
380 if (!torture_setup_dir(cli
, 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);
409 printf("Trying zero file read\n");
410 io
.readx
.in
.mincnt
= 0;
411 io
.readx
.in
.maxcnt
= 0;
412 status
= smb_raw_read(cli
->tree
, &io
);
413 CHECK_STATUS(status
, NT_STATUS_OK
);
414 CHECK_VALUE(io
.readx
.out
.nread
, 0);
415 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
416 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
418 printf("Trying bad fnum\n");
419 io
.readx
.in
.file
.fnum
= fnum
+1;
420 status
= smb_raw_read(cli
->tree
, &io
);
421 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
422 io
.readx
.in
.file
.fnum
= fnum
;
424 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
426 printf("Trying small read\n");
427 io
.readx
.in
.file
.fnum
= fnum
;
428 io
.readx
.in
.offset
= 0;
429 io
.readx
.in
.remaining
= 0;
430 io
.readx
.in
.read_for_execute
= false;
431 io
.readx
.in
.mincnt
= strlen(test_data
);
432 io
.readx
.in
.maxcnt
= strlen(test_data
);
433 status
= smb_raw_read(cli
->tree
, &io
);
434 CHECK_STATUS(status
, NT_STATUS_OK
);
435 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
436 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
437 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
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 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
455 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
459 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
460 printf("Trying max offset\n");
461 io
.readx
.in
.offset
= 0xffffffff;
462 io
.readx
.in
.mincnt
= strlen(test_data
);
463 io
.readx
.in
.maxcnt
= strlen(test_data
);
464 status
= smb_raw_read(cli
->tree
, &io
);
465 CHECK_STATUS(status
, NT_STATUS_OK
);
466 CHECK_VALUE(io
.readx
.out
.nread
, 0);
467 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
468 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
471 printf("Trying mincnt past EOF\n");
472 memset(buf
, 0, maxsize
);
473 io
.readx
.in
.offset
= 0;
474 io
.readx
.in
.mincnt
= 100;
475 io
.readx
.in
.maxcnt
= 110;
476 status
= smb_raw_read(cli
->tree
, &io
);
477 CHECK_STATUS(status
, NT_STATUS_OK
);
478 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
479 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
480 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
481 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
483 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
488 setup_buffer(buf
, seed
, maxsize
);
489 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
490 memset(buf
, 0, maxsize
);
492 printf("Trying page sized read\n");
493 io
.readx
.in
.offset
= 0;
494 io
.readx
.in
.mincnt
= 0x1000;
495 io
.readx
.in
.maxcnt
= 0x1000;
496 status
= smb_raw_read(cli
->tree
, &io
);
497 CHECK_STATUS(status
, NT_STATUS_OK
);
498 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
499 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
500 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
501 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
503 printf("Trying page + 1 sized read (check alignment)\n");
504 io
.readx
.in
.offset
= 0;
505 io
.readx
.in
.mincnt
= 0x1001;
506 io
.readx
.in
.maxcnt
= 0x1001;
507 status
= smb_raw_read(cli
->tree
, &io
);
508 CHECK_STATUS(status
, NT_STATUS_OK
);
509 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
510 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
511 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
512 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
514 printf("Trying large read (UINT16_MAX)\n");
515 io
.readx
.in
.offset
= 0;
516 io
.readx
.in
.mincnt
= 0xFFFF;
517 io
.readx
.in
.maxcnt
= 0xFFFF;
518 status
= smb_raw_read(cli
->tree
, &io
);
519 CHECK_STATUS(status
, NT_STATUS_OK
);
520 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
521 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
522 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
523 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
525 printf("Trying extra large read\n");
526 io
.readx
.in
.offset
= 0;
527 io
.readx
.in
.mincnt
= 100;
528 io
.readx
.in
.maxcnt
= 80000;
529 status
= smb_raw_read(cli
->tree
, &io
);
530 CHECK_STATUS(status
, NT_STATUS_OK
);
531 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
532 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
533 if (torture_setting_bool(tctx
, "samba3", false) ||
534 torture_setting_bool(tctx
, "samba4", false)) {
535 printf("SAMBA: large read extension\n");
536 CHECK_VALUE(io
.readx
.out
.nread
, 80000);
538 CHECK_VALUE(io
.readx
.out
.nread
, 0);
540 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
542 printf("Trying mincnt > maxcnt\n");
543 memset(buf
, 0, maxsize
);
544 io
.readx
.in
.offset
= 0;
545 io
.readx
.in
.mincnt
= 30000;
546 io
.readx
.in
.maxcnt
= 20000;
547 status
= smb_raw_read(cli
->tree
, &io
);
548 CHECK_STATUS(status
, NT_STATUS_OK
);
549 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
550 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
551 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
552 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
554 printf("Trying mincnt < maxcnt\n");
555 memset(buf
, 0, maxsize
);
556 io
.readx
.in
.offset
= 0;
557 io
.readx
.in
.mincnt
= 20000;
558 io
.readx
.in
.maxcnt
= 30000;
559 status
= smb_raw_read(cli
->tree
, &io
);
560 CHECK_STATUS(status
, NT_STATUS_OK
);
561 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
562 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
563 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
564 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
566 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_READX
) {
567 printf("Trying large readx\n");
568 io
.readx
.in
.offset
= 0;
569 io
.readx
.in
.mincnt
= 0;
570 io
.readx
.in
.maxcnt
= 0x10000 - 1;
571 status
= smb_raw_read(cli
->tree
, &io
);
572 CHECK_STATUS(status
, NT_STATUS_OK
);
573 CHECK_VALUE(io
.readx
.out
.nread
, 0xFFFF);
575 io
.readx
.in
.maxcnt
= 0x10000;
576 status
= smb_raw_read(cli
->tree
, &io
);
577 CHECK_STATUS(status
, NT_STATUS_OK
);
578 if (torture_setting_bool(tctx
, "samba3", false) ||
579 torture_setting_bool(tctx
, "samba4", false)) {
580 printf("SAMBA: large read extension\n");
581 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
583 CHECK_VALUE(io
.readx
.out
.nread
, 0);
586 io
.readx
.in
.maxcnt
= 0x10001;
587 status
= smb_raw_read(cli
->tree
, &io
);
588 CHECK_STATUS(status
, NT_STATUS_OK
);
589 if (torture_setting_bool(tctx
, "samba3", false) ||
590 torture_setting_bool(tctx
, "samba4", false)) {
591 printf("SAMBA: large read extension\n");
592 CHECK_VALUE(io
.readx
.out
.nread
, 0x10001);
594 CHECK_VALUE(io
.readx
.out
.nread
, 0);
597 printf("Server does not support the CAP_LARGE_READX extension\n");
600 printf("Trying locked region\n");
602 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
603 printf("Failed to lock file at %d\n", __LINE__
);
608 memset(buf
, 0, maxsize
);
609 io
.readx
.in
.offset
= 0;
610 io
.readx
.in
.mincnt
= 100;
611 io
.readx
.in
.maxcnt
= 200;
612 status
= smb_raw_read(cli
->tree
, &io
);
613 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
615 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
616 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
620 printf("Trying large offset read\n");
621 io
.readx
.in
.offset
= ((uint64_t)0x2) << 32;
622 io
.readx
.in
.mincnt
= 10;
623 io
.readx
.in
.maxcnt
= 10;
624 status
= smb_raw_read(cli
->tree
, &io
);
625 CHECK_STATUS(status
, NT_STATUS_OK
);
626 CHECK_VALUE(io
.readx
.out
.nread
, 0);
628 if (NT_STATUS_IS_ERR(smbcli_lock64(cli
->tree
, fnum
, io
.readx
.in
.offset
, 1, 0, WRITE_LOCK
))) {
629 printf("Failed to lock file at %d\n", __LINE__
);
634 status
= smb_raw_read(cli
->tree
, &io
);
635 CHECK_STATUS(status
, NT_STATUS_OK
);
636 CHECK_VALUE(io
.readx
.out
.nread
, 0);
639 smbcli_close(cli
->tree
, fnum
);
640 smbcli_deltree(cli
->tree
, BASEDIR
);
648 static bool test_readbraw(struct torture_context
*tctx
,
649 struct smbcli_state
*cli
)
656 const int maxsize
= 90000;
657 const char *fname
= BASEDIR
"\\test.txt";
658 const char *test_data
= "TEST DATA";
659 unsigned int seed
= time(NULL
);
661 if (!cli
->transport
->negotiate
.readbraw_supported
) {
662 printf("Server does not support readbraw - skipping\n");
666 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
668 if (!torture_setup_dir(cli
, BASEDIR
)) {
672 printf("Testing RAW_READ_READBRAW\n");
674 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
676 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
681 printf("Trying empty file read\n");
682 io
.generic
.level
= RAW_READ_READBRAW
;
683 io
.readbraw
.in
.file
.fnum
= fnum
;
684 io
.readbraw
.in
.mincnt
= 1;
685 io
.readbraw
.in
.maxcnt
= 1;
686 io
.readbraw
.in
.offset
= 0;
687 io
.readbraw
.in
.timeout
= 0;
688 io
.readbraw
.out
.data
= buf
;
689 status
= smb_raw_read(cli
->tree
, &io
);
691 CHECK_STATUS(status
, NT_STATUS_OK
);
692 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
694 printf("Trying zero file read\n");
695 io
.readbraw
.in
.mincnt
= 0;
696 io
.readbraw
.in
.maxcnt
= 0;
697 status
= smb_raw_read(cli
->tree
, &io
);
698 CHECK_STATUS(status
, NT_STATUS_OK
);
699 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
701 printf("Trying bad fnum\n");
702 io
.readbraw
.in
.file
.fnum
= fnum
+1;
703 status
= smb_raw_read(cli
->tree
, &io
);
704 CHECK_STATUS(status
, NT_STATUS_OK
);
705 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
706 io
.readbraw
.in
.file
.fnum
= fnum
;
708 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
710 printf("Trying small read\n");
711 io
.readbraw
.in
.file
.fnum
= fnum
;
712 io
.readbraw
.in
.offset
= 0;
713 io
.readbraw
.in
.mincnt
= strlen(test_data
);
714 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
715 status
= smb_raw_read(cli
->tree
, &io
);
716 CHECK_STATUS(status
, NT_STATUS_OK
);
717 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
));
718 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
720 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
724 printf("Trying short read\n");
725 io
.readbraw
.in
.offset
= 1;
726 io
.readbraw
.in
.mincnt
= strlen(test_data
);
727 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
728 status
= smb_raw_read(cli
->tree
, &io
);
729 CHECK_STATUS(status
, NT_STATUS_OK
);
730 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
)-1);
731 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
733 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
737 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
738 printf("Trying max offset\n");
739 io
.readbraw
.in
.offset
= ~0;
740 io
.readbraw
.in
.mincnt
= strlen(test_data
);
741 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
742 status
= smb_raw_read(cli
->tree
, &io
);
743 CHECK_STATUS(status
, NT_STATUS_OK
);
744 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
747 setup_buffer(buf
, seed
, maxsize
);
748 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
749 memset(buf
, 0, maxsize
);
751 printf("Trying large read\n");
752 io
.readbraw
.in
.offset
= 0;
753 io
.readbraw
.in
.mincnt
= ~0;
754 io
.readbraw
.in
.maxcnt
= ~0;
755 status
= smb_raw_read(cli
->tree
, &io
);
756 CHECK_STATUS(status
, NT_STATUS_OK
);
757 CHECK_VALUE(io
.readbraw
.out
.nread
, 0xFFFF);
758 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
760 printf("Trying mincnt > maxcnt\n");
761 memset(buf
, 0, maxsize
);
762 io
.readbraw
.in
.offset
= 0;
763 io
.readbraw
.in
.mincnt
= 30000;
764 io
.readbraw
.in
.maxcnt
= 20000;
765 status
= smb_raw_read(cli
->tree
, &io
);
766 CHECK_STATUS(status
, NT_STATUS_OK
);
767 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
768 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
770 printf("Trying mincnt < maxcnt\n");
771 memset(buf
, 0, maxsize
);
772 io
.readbraw
.in
.offset
= 0;
773 io
.readbraw
.in
.mincnt
= 20000;
774 io
.readbraw
.in
.maxcnt
= 30000;
775 status
= smb_raw_read(cli
->tree
, &io
);
776 CHECK_STATUS(status
, NT_STATUS_OK
);
777 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
778 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
780 printf("Trying locked region\n");
782 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
783 printf("Failed to lock file at %d\n", __LINE__
);
788 memset(buf
, 0, maxsize
);
789 io
.readbraw
.in
.offset
= 0;
790 io
.readbraw
.in
.mincnt
= 100;
791 io
.readbraw
.in
.maxcnt
= 200;
792 status
= smb_raw_read(cli
->tree
, &io
);
793 CHECK_STATUS(status
, NT_STATUS_OK
);
794 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
796 printf("Trying locked region with timeout\n");
797 memset(buf
, 0, maxsize
);
798 io
.readbraw
.in
.offset
= 0;
799 io
.readbraw
.in
.mincnt
= 100;
800 io
.readbraw
.in
.maxcnt
= 200;
801 io
.readbraw
.in
.timeout
= 10000;
802 status
= smb_raw_read(cli
->tree
, &io
);
803 CHECK_STATUS(status
, NT_STATUS_OK
);
804 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
806 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
807 printf("Trying large offset read\n");
808 io
.readbraw
.in
.offset
= ((uint64_t)0x2) << 32;
809 io
.readbraw
.in
.mincnt
= 10;
810 io
.readbraw
.in
.maxcnt
= 10;
811 io
.readbraw
.in
.timeout
= 0;
812 status
= smb_raw_read(cli
->tree
, &io
);
813 CHECK_STATUS(status
, NT_STATUS_OK
);
814 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
818 smbcli_close(cli
->tree
, fnum
);
819 smbcli_deltree(cli
->tree
, BASEDIR
);
824 test read for execute
826 static bool test_read_for_execute(struct torture_context
*tctx
,
827 struct smbcli_state
*cli
)
836 const int maxsize
= 900;
837 const char *fname
= BASEDIR
"\\test.txt";
838 const uint8_t data
[] = "TEST DATA";
840 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
842 if (!torture_setup_dir(cli
, BASEDIR
)) {
846 printf("Testing RAW_READ_READX with read_for_execute\n");
848 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
849 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
850 op
.ntcreatex
.in
.flags
= 0;
851 op
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
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_CREATE
;
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 wr
.generic
.level
= RAW_WRITE_WRITEX
;
865 wr
.writex
.in
.file
.fnum
= fnum
;
866 wr
.writex
.in
.offset
= 0;
867 wr
.writex
.in
.wmode
= 0;
868 wr
.writex
.in
.remaining
= 0;
869 wr
.writex
.in
.count
= ARRAY_SIZE(data
);
870 wr
.writex
.in
.data
= data
;
871 status
= smb_raw_write(cli
->tree
, &wr
);
872 CHECK_STATUS(status
, NT_STATUS_OK
);
873 CHECK_VALUE(wr
.writex
.out
.nwritten
, ARRAY_SIZE(data
));
875 status
= smbcli_close(cli
->tree
, fnum
);
876 CHECK_STATUS(status
, NT_STATUS_OK
);
878 printf("open file with SEC_FILE_EXECUTE\n");
879 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
880 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
881 op
.ntcreatex
.in
.flags
= 0;
882 op
.ntcreatex
.in
.access_mask
= SEC_FILE_EXECUTE
;
883 op
.ntcreatex
.in
.create_options
= 0;
884 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
885 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
886 op
.ntcreatex
.in
.alloc_size
= 0;
887 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
888 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
889 op
.ntcreatex
.in
.security_flags
= 0;
890 op
.ntcreatex
.in
.fname
= fname
;
891 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
892 CHECK_STATUS(status
, NT_STATUS_OK
);
893 fnum
= op
.ntcreatex
.out
.file
.fnum
;
895 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
896 rd
.generic
.level
= RAW_READ_READX
;
897 rd
.readx
.in
.file
.fnum
= fnum
;
898 rd
.readx
.in
.mincnt
= 0;
899 rd
.readx
.in
.maxcnt
= maxsize
;
900 rd
.readx
.in
.offset
= 0;
901 rd
.readx
.in
.remaining
= 0;
902 rd
.readx
.in
.read_for_execute
= true;
903 rd
.readx
.out
.data
= buf
;
904 status
= smb_raw_read(cli
->tree
, &rd
);
905 CHECK_STATUS(status
, NT_STATUS_OK
);
906 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
907 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
908 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
910 printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
911 rd
.generic
.level
= RAW_READ_READX
;
912 rd
.readx
.in
.file
.fnum
= fnum
;
913 rd
.readx
.in
.mincnt
= 0;
914 rd
.readx
.in
.maxcnt
= maxsize
;
915 rd
.readx
.in
.offset
= 0;
916 rd
.readx
.in
.remaining
= 0;
917 rd
.readx
.in
.read_for_execute
= false;
918 rd
.readx
.out
.data
= buf
;
919 status
= smb_raw_read(cli
->tree
, &rd
);
920 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
922 status
= smbcli_close(cli
->tree
, fnum
);
923 CHECK_STATUS(status
, NT_STATUS_OK
);
925 printf("open file with SEC_FILE_READ_DATA\n");
926 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
927 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
928 op
.ntcreatex
.in
.flags
= 0;
929 op
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
930 op
.ntcreatex
.in
.create_options
= 0;
931 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
932 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
933 op
.ntcreatex
.in
.alloc_size
= 0;
934 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
935 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
936 op
.ntcreatex
.in
.security_flags
= 0;
937 op
.ntcreatex
.in
.fname
= fname
;
938 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
939 CHECK_STATUS(status
, NT_STATUS_OK
);
940 fnum
= op
.ntcreatex
.out
.file
.fnum
;
942 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
943 rd
.generic
.level
= RAW_READ_READX
;
944 rd
.readx
.in
.file
.fnum
= fnum
;
945 rd
.readx
.in
.mincnt
= 0;
946 rd
.readx
.in
.maxcnt
= maxsize
;
947 rd
.readx
.in
.offset
= 0;
948 rd
.readx
.in
.remaining
= 0;
949 rd
.readx
.in
.read_for_execute
= true;
950 rd
.readx
.out
.data
= buf
;
951 status
= smb_raw_read(cli
->tree
, &rd
);
952 CHECK_STATUS(status
, NT_STATUS_OK
);
953 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
954 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
955 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
957 printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
958 rd
.generic
.level
= RAW_READ_READX
;
959 rd
.readx
.in
.file
.fnum
= fnum
;
960 rd
.readx
.in
.mincnt
= 0;
961 rd
.readx
.in
.maxcnt
= maxsize
;
962 rd
.readx
.in
.offset
= 0;
963 rd
.readx
.in
.remaining
= 0;
964 rd
.readx
.in
.read_for_execute
= false;
965 rd
.readx
.out
.data
= buf
;
966 status
= smb_raw_read(cli
->tree
, &rd
);
967 CHECK_STATUS(status
, NT_STATUS_OK
);
968 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
969 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
970 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
973 smbcli_close(cli
->tree
, fnum
);
974 smbcli_deltree(cli
->tree
, BASEDIR
);
980 basic testing of read calls
982 struct torture_suite
*torture_raw_read(TALLOC_CTX
*mem_ctx
)
984 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "read");
986 torture_suite_add_1smb_test(suite
, "read", test_read
);
987 torture_suite_add_1smb_test(suite
, "readx", test_readx
);
988 torture_suite_add_1smb_test(suite
, "lockread", test_lockread
);
989 torture_suite_add_1smb_test(suite
, "readbraw", test_readbraw
);
990 torture_suite_add_1smb_test(suite
, "read for execute",
991 test_read_for_execute
);