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 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
105 printf("Testing RAW_READ_READ\n");
106 io
.generic
.level
= RAW_READ_READ
;
108 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
110 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
115 printf("Trying empty file read\n");
116 io
.read
.in
.file
.fnum
= fnum
;
117 io
.read
.in
.count
= 1;
118 io
.read
.in
.offset
= 0;
119 io
.read
.in
.remaining
= 0;
120 io
.read
.out
.data
= buf
;
121 status
= smb_raw_read(cli
->tree
, &io
);
123 CHECK_STATUS(status
, NT_STATUS_OK
);
124 CHECK_VALUE(io
.read
.out
.nread
, 0);
126 printf("Trying zero file read\n");
127 io
.read
.in
.count
= 0;
128 status
= smb_raw_read(cli
->tree
, &io
);
129 CHECK_STATUS(status
, NT_STATUS_OK
);
130 CHECK_VALUE(io
.read
.out
.nread
, 0);
132 printf("Trying bad fnum\n");
133 io
.read
.in
.file
.fnum
= fnum
+1;
134 status
= smb_raw_read(cli
->tree
, &io
);
135 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
136 io
.read
.in
.file
.fnum
= fnum
;
138 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
140 printf("Trying small read\n");
141 io
.read
.in
.file
.fnum
= fnum
;
142 io
.read
.in
.offset
= 0;
143 io
.read
.in
.remaining
= 0;
144 io
.read
.in
.count
= strlen(test_data
);
145 status
= smb_raw_read(cli
->tree
, &io
);
146 CHECK_STATUS(status
, NT_STATUS_OK
);
147 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
));
148 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
150 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
154 printf("Trying short read\n");
155 io
.read
.in
.offset
= 1;
156 io
.read
.in
.count
= strlen(test_data
);
157 status
= smb_raw_read(cli
->tree
, &io
);
158 CHECK_STATUS(status
, NT_STATUS_OK
);
159 CHECK_VALUE(io
.read
.out
.nread
, strlen(test_data
)-1);
160 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
162 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
166 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
167 printf("Trying max offset\n");
168 io
.read
.in
.offset
= ~0;
169 io
.read
.in
.count
= strlen(test_data
);
170 status
= smb_raw_read(cli
->tree
, &io
);
171 CHECK_STATUS(status
, NT_STATUS_OK
);
172 CHECK_VALUE(io
.read
.out
.nread
, 0);
175 setup_buffer(buf
, seed
, maxsize
);
176 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
177 memset(buf
, 0, maxsize
);
179 printf("Trying large read\n");
180 io
.read
.in
.offset
= 0;
181 io
.read
.in
.count
= ~0;
182 status
= smb_raw_read(cli
->tree
, &io
);
183 CHECK_STATUS(status
, NT_STATUS_OK
);
184 CHECK_BUFFER(buf
, seed
, io
.read
.out
.nread
);
187 printf("Trying locked region\n");
189 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
190 printf("Failed to lock file at %d\n", __LINE__
);
195 memset(buf
, 0, maxsize
);
196 io
.read
.in
.offset
= 0;
197 io
.read
.in
.count
= ~0;
198 status
= smb_raw_read(cli
->tree
, &io
);
199 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
203 smbcli_close(cli
->tree
, fnum
);
204 smb_raw_exit(cli
->session
);
205 smbcli_deltree(cli
->tree
, BASEDIR
);
213 static bool test_lockread(struct torture_context
*tctx
,
214 struct smbcli_state
*cli
)
221 const int maxsize
= 90000;
222 const char *fname
= BASEDIR
"\\test.txt";
223 const char *test_data
= "TEST DATA";
224 unsigned int seed
= time(NULL
);
226 if (!cli
->transport
->negotiate
.lockread_supported
) {
227 printf("Server does not support lockread - skipping\n");
231 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
233 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
235 printf("Testing RAW_READ_LOCKREAD\n");
236 io
.generic
.level
= RAW_READ_LOCKREAD
;
238 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
240 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
245 printf("Trying empty file read\n");
246 io
.lockread
.in
.file
.fnum
= fnum
;
247 io
.lockread
.in
.count
= 1;
248 io
.lockread
.in
.offset
= 1;
249 io
.lockread
.in
.remaining
= 0;
250 io
.lockread
.out
.data
= buf
;
251 status
= smb_raw_read(cli
->tree
, &io
);
253 CHECK_STATUS(status
, NT_STATUS_OK
);
254 CHECK_VALUE(io
.lockread
.out
.nread
, 0);
256 status
= smb_raw_read(cli
->tree
, &io
);
257 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
259 status
= smb_raw_read(cli
->tree
, &io
);
260 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
262 printf("Trying zero file read\n");
263 io
.lockread
.in
.count
= 0;
264 status
= smb_raw_read(cli
->tree
, &io
);
265 CHECK_STATUS(status
, NT_STATUS_OK
);
267 smbcli_unlock(cli
->tree
, fnum
, 1, 1);
269 printf("Trying bad fnum\n");
270 io
.lockread
.in
.file
.fnum
= fnum
+1;
271 status
= smb_raw_read(cli
->tree
, &io
);
272 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
273 io
.lockread
.in
.file
.fnum
= fnum
;
275 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
277 printf("Trying small read\n");
278 io
.lockread
.in
.file
.fnum
= fnum
;
279 io
.lockread
.in
.offset
= 0;
280 io
.lockread
.in
.remaining
= 0;
281 io
.lockread
.in
.count
= strlen(test_data
);
282 status
= smb_raw_read(cli
->tree
, &io
);
283 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
285 smbcli_unlock(cli
->tree
, fnum
, 1, 0);
287 status
= smb_raw_read(cli
->tree
, &io
);
288 CHECK_STATUS(status
, NT_STATUS_OK
);
289 CHECK_VALUE(io
.lockread
.out
.nread
, strlen(test_data
));
290 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
292 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
296 printf("Trying short read\n");
297 io
.lockread
.in
.offset
= 1;
298 io
.lockread
.in
.count
= strlen(test_data
);
299 status
= smb_raw_read(cli
->tree
, &io
);
300 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
301 smbcli_unlock(cli
->tree
, fnum
, 0, strlen(test_data
));
302 status
= smb_raw_read(cli
->tree
, &io
);
303 CHECK_STATUS(status
, NT_STATUS_OK
);
305 CHECK_VALUE(io
.lockread
.out
.nread
, strlen(test_data
)-1);
306 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
308 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
312 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
313 printf("Trying max offset\n");
314 io
.lockread
.in
.offset
= ~0;
315 io
.lockread
.in
.count
= strlen(test_data
);
316 status
= smb_raw_read(cli
->tree
, &io
);
317 CHECK_STATUS(status
, NT_STATUS_OK
);
318 CHECK_VALUE(io
.lockread
.out
.nread
, 0);
321 setup_buffer(buf
, seed
, maxsize
);
322 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
323 memset(buf
, 0, maxsize
);
325 printf("Trying large read\n");
326 io
.lockread
.in
.offset
= 0;
327 io
.lockread
.in
.count
= ~0;
328 status
= smb_raw_read(cli
->tree
, &io
);
329 CHECK_STATUS(status
, NT_STATUS_LOCK_NOT_GRANTED
);
330 smbcli_unlock(cli
->tree
, fnum
, 1, strlen(test_data
));
331 status
= smb_raw_read(cli
->tree
, &io
);
332 CHECK_STATUS(status
, NT_STATUS_OK
);
333 CHECK_BUFFER(buf
, seed
, io
.lockread
.out
.nread
);
334 smbcli_unlock(cli
->tree
, fnum
, 0, 0xFFFF);
337 printf("Trying locked region\n");
339 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
340 printf("Failed to lock file at %d\n", __LINE__
);
345 memset(buf
, 0, maxsize
);
346 io
.lockread
.in
.offset
= 0;
347 io
.lockread
.in
.count
= ~0;
348 status
= smb_raw_read(cli
->tree
, &io
);
349 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
353 smbcli_close(cli
->tree
, fnum
);
354 smbcli_deltree(cli
->tree
, BASEDIR
);
362 static bool test_readx(struct torture_context
*tctx
, struct smbcli_state
*cli
)
369 const int maxsize
= 90000;
370 const char *fname
= BASEDIR
"\\test.txt";
371 const char *test_data
= "TEST DATA";
372 unsigned int seed
= time(NULL
);
374 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
376 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
378 printf("Testing RAW_READ_READX\n");
380 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
382 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
387 printf("Trying empty file read\n");
388 io
.generic
.level
= RAW_READ_READX
;
389 io
.readx
.in
.file
.fnum
= fnum
;
390 io
.readx
.in
.mincnt
= 1;
391 io
.readx
.in
.maxcnt
= 1;
392 io
.readx
.in
.offset
= 0;
393 io
.readx
.in
.remaining
= 0;
394 io
.readx
.in
.read_for_execute
= false;
395 io
.readx
.out
.data
= buf
;
396 status
= smb_raw_read(cli
->tree
, &io
);
398 CHECK_STATUS(status
, NT_STATUS_OK
);
399 CHECK_VALUE(io
.readx
.out
.nread
, 0);
400 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
401 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
403 printf("Trying zero file read\n");
404 io
.readx
.in
.mincnt
= 0;
405 io
.readx
.in
.maxcnt
= 0;
406 status
= smb_raw_read(cli
->tree
, &io
);
407 CHECK_STATUS(status
, NT_STATUS_OK
);
408 CHECK_VALUE(io
.readx
.out
.nread
, 0);
409 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
410 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
412 printf("Trying bad fnum\n");
413 io
.readx
.in
.file
.fnum
= fnum
+1;
414 status
= smb_raw_read(cli
->tree
, &io
);
415 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
416 io
.readx
.in
.file
.fnum
= fnum
;
418 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
420 printf("Trying small read\n");
421 io
.readx
.in
.file
.fnum
= fnum
;
422 io
.readx
.in
.offset
= 0;
423 io
.readx
.in
.remaining
= 0;
424 io
.readx
.in
.read_for_execute
= false;
425 io
.readx
.in
.mincnt
= strlen(test_data
);
426 io
.readx
.in
.maxcnt
= strlen(test_data
);
427 status
= smb_raw_read(cli
->tree
, &io
);
428 CHECK_STATUS(status
, NT_STATUS_OK
);
429 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
430 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
431 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
432 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
434 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
438 printf("Trying short read\n");
439 io
.readx
.in
.offset
= 1;
440 io
.readx
.in
.mincnt
= strlen(test_data
);
441 io
.readx
.in
.maxcnt
= strlen(test_data
);
442 status
= smb_raw_read(cli
->tree
, &io
);
443 CHECK_STATUS(status
, NT_STATUS_OK
);
444 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
)-1);
445 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
446 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
447 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
449 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
453 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
454 printf("Trying max offset\n");
455 io
.readx
.in
.offset
= 0xffffffff;
456 io
.readx
.in
.mincnt
= strlen(test_data
);
457 io
.readx
.in
.maxcnt
= strlen(test_data
);
458 status
= smb_raw_read(cli
->tree
, &io
);
459 CHECK_STATUS(status
, NT_STATUS_OK
);
460 CHECK_VALUE(io
.readx
.out
.nread
, 0);
461 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
462 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
465 printf("Trying mincnt past EOF\n");
466 memset(buf
, 0, maxsize
);
467 io
.readx
.in
.offset
= 0;
468 io
.readx
.in
.mincnt
= 100;
469 io
.readx
.in
.maxcnt
= 110;
470 status
= smb_raw_read(cli
->tree
, &io
);
471 CHECK_STATUS(status
, NT_STATUS_OK
);
472 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
473 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
474 CHECK_VALUE(io
.readx
.out
.nread
, strlen(test_data
));
475 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
477 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
482 setup_buffer(buf
, seed
, maxsize
);
483 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
484 memset(buf
, 0, maxsize
);
486 printf("Trying page sized read\n");
487 io
.readx
.in
.offset
= 0;
488 io
.readx
.in
.mincnt
= 0x1000;
489 io
.readx
.in
.maxcnt
= 0x1000;
490 status
= smb_raw_read(cli
->tree
, &io
);
491 CHECK_STATUS(status
, NT_STATUS_OK
);
492 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
493 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
494 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
495 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
497 printf("Trying page + 1 sized read (check alignment)\n");
498 io
.readx
.in
.offset
= 0;
499 io
.readx
.in
.mincnt
= 0x1001;
500 io
.readx
.in
.maxcnt
= 0x1001;
501 status
= smb_raw_read(cli
->tree
, &io
);
502 CHECK_STATUS(status
, NT_STATUS_OK
);
503 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
504 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
505 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
506 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
508 printf("Trying large read (UINT16_MAX)\n");
509 io
.readx
.in
.offset
= 0;
510 io
.readx
.in
.mincnt
= 0xFFFF;
511 io
.readx
.in
.maxcnt
= 0xFFFF;
512 status
= smb_raw_read(cli
->tree
, &io
);
513 CHECK_STATUS(status
, NT_STATUS_OK
);
514 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
515 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
516 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
517 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
519 printf("Trying extra large read\n");
520 io
.readx
.in
.offset
= 0;
521 io
.readx
.in
.mincnt
= 100;
522 io
.readx
.in
.maxcnt
= 80000;
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 if (torture_setting_bool(tctx
, "samba3", false) ||
528 torture_setting_bool(tctx
, "samba4", false)) {
529 printf("SAMBA: large read extension\n");
530 CHECK_VALUE(io
.readx
.out
.nread
, 80000);
532 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
534 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
536 printf("Trying mincnt > maxcnt\n");
537 memset(buf
, 0, maxsize
);
538 io
.readx
.in
.offset
= 0;
539 io
.readx
.in
.mincnt
= 30000;
540 io
.readx
.in
.maxcnt
= 20000;
541 status
= smb_raw_read(cli
->tree
, &io
);
542 CHECK_STATUS(status
, NT_STATUS_OK
);
543 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
544 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
545 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
546 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
548 printf("Trying mincnt < maxcnt\n");
549 memset(buf
, 0, maxsize
);
550 io
.readx
.in
.offset
= 0;
551 io
.readx
.in
.mincnt
= 20000;
552 io
.readx
.in
.maxcnt
= 30000;
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
);
560 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_READX
) {
561 printf("Trying large readx\n");
562 io
.readx
.in
.offset
= 0;
563 io
.readx
.in
.mincnt
= 0;
564 io
.readx
.in
.maxcnt
= 0x10000 - 1;
565 status
= smb_raw_read(cli
->tree
, &io
);
566 CHECK_STATUS(status
, NT_STATUS_OK
);
567 CHECK_VALUE(io
.readx
.out
.nread
, 0xFFFF);
569 io
.readx
.in
.maxcnt
= 0x10000;
570 status
= smb_raw_read(cli
->tree
, &io
);
571 CHECK_STATUS(status
, NT_STATUS_OK
);
572 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
574 io
.readx
.in
.maxcnt
= 0x10001;
575 status
= smb_raw_read(cli
->tree
, &io
);
576 CHECK_STATUS(status
, NT_STATUS_OK
);
577 if (torture_setting_bool(tctx
, "samba3", false) ||
578 torture_setting_bool(tctx
, "samba4", false)) {
579 printf("SAMBA: large read extension\n");
580 CHECK_VALUE(io
.readx
.out
.nread
, 0x10001);
582 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
585 printf("Server does not support the CAP_LARGE_READX extension\n");
588 printf("Trying locked region\n");
590 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
591 printf("Failed to lock file at %d\n", __LINE__
);
596 memset(buf
, 0, maxsize
);
597 io
.readx
.in
.offset
= 0;
598 io
.readx
.in
.mincnt
= 100;
599 io
.readx
.in
.maxcnt
= 200;
600 status
= smb_raw_read(cli
->tree
, &io
);
601 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
603 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
604 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
608 printf("Trying large offset read\n");
609 io
.readx
.in
.offset
= ((uint64_t)0x2) << 32;
610 io
.readx
.in
.mincnt
= 10;
611 io
.readx
.in
.maxcnt
= 10;
612 status
= smb_raw_read(cli
->tree
, &io
);
613 CHECK_STATUS(status
, NT_STATUS_OK
);
614 CHECK_VALUE(io
.readx
.out
.nread
, 0);
616 if (NT_STATUS_IS_ERR(smbcli_lock64(cli
->tree
, fnum
, io
.readx
.in
.offset
, 1, 0, WRITE_LOCK
))) {
617 printf("Failed to lock file at %d\n", __LINE__
);
622 status
= smb_raw_read(cli
->tree
, &io
);
623 CHECK_STATUS(status
, NT_STATUS_OK
);
624 CHECK_VALUE(io
.readx
.out
.nread
, 0);
627 smbcli_close(cli
->tree
, fnum
);
628 smbcli_deltree(cli
->tree
, BASEDIR
);
636 static bool test_readbraw(struct torture_context
*tctx
,
637 struct smbcli_state
*cli
)
644 const int maxsize
= 90000;
645 const char *fname
= BASEDIR
"\\test.txt";
646 const char *test_data
= "TEST DATA";
647 unsigned int seed
= time(NULL
);
649 if (!cli
->transport
->negotiate
.readbraw_supported
) {
650 printf("Server does not support readbraw - skipping\n");
654 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
656 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
658 printf("Testing RAW_READ_READBRAW\n");
660 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
662 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
667 printf("Trying empty file read\n");
668 io
.generic
.level
= RAW_READ_READBRAW
;
669 io
.readbraw
.in
.file
.fnum
= fnum
;
670 io
.readbraw
.in
.mincnt
= 1;
671 io
.readbraw
.in
.maxcnt
= 1;
672 io
.readbraw
.in
.offset
= 0;
673 io
.readbraw
.in
.timeout
= 0;
674 io
.readbraw
.out
.data
= buf
;
675 status
= smb_raw_read(cli
->tree
, &io
);
677 CHECK_STATUS(status
, NT_STATUS_OK
);
678 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
680 printf("Trying zero file read\n");
681 io
.readbraw
.in
.mincnt
= 0;
682 io
.readbraw
.in
.maxcnt
= 0;
683 status
= smb_raw_read(cli
->tree
, &io
);
684 CHECK_STATUS(status
, NT_STATUS_OK
);
685 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
687 printf("Trying bad fnum\n");
688 io
.readbraw
.in
.file
.fnum
= fnum
+1;
689 status
= smb_raw_read(cli
->tree
, &io
);
690 CHECK_STATUS(status
, NT_STATUS_OK
);
691 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
692 io
.readbraw
.in
.file
.fnum
= fnum
;
694 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
696 printf("Trying small read\n");
697 io
.readbraw
.in
.file
.fnum
= fnum
;
698 io
.readbraw
.in
.offset
= 0;
699 io
.readbraw
.in
.mincnt
= strlen(test_data
);
700 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
701 status
= smb_raw_read(cli
->tree
, &io
);
702 CHECK_STATUS(status
, NT_STATUS_OK
);
703 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
));
704 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
706 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
710 printf("Trying short read\n");
711 io
.readbraw
.in
.offset
= 1;
712 io
.readbraw
.in
.mincnt
= strlen(test_data
);
713 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
714 status
= smb_raw_read(cli
->tree
, &io
);
715 CHECK_STATUS(status
, NT_STATUS_OK
);
716 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
)-1);
717 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
719 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
723 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
724 printf("Trying max offset\n");
725 io
.readbraw
.in
.offset
= ~0;
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
, 0);
733 setup_buffer(buf
, seed
, maxsize
);
734 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
735 memset(buf
, 0, maxsize
);
737 printf("Trying large read\n");
738 io
.readbraw
.in
.offset
= 0;
739 io
.readbraw
.in
.mincnt
= ~0;
740 io
.readbraw
.in
.maxcnt
= ~0;
741 status
= smb_raw_read(cli
->tree
, &io
);
742 CHECK_STATUS(status
, NT_STATUS_OK
);
743 CHECK_VALUE(io
.readbraw
.out
.nread
, 0xFFFF);
744 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
746 printf("Trying mincnt > maxcnt\n");
747 memset(buf
, 0, maxsize
);
748 io
.readbraw
.in
.offset
= 0;
749 io
.readbraw
.in
.mincnt
= 30000;
750 io
.readbraw
.in
.maxcnt
= 20000;
751 status
= smb_raw_read(cli
->tree
, &io
);
752 CHECK_STATUS(status
, NT_STATUS_OK
);
753 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
754 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
756 printf("Trying mincnt < maxcnt\n");
757 memset(buf
, 0, maxsize
);
758 io
.readbraw
.in
.offset
= 0;
759 io
.readbraw
.in
.mincnt
= 20000;
760 io
.readbraw
.in
.maxcnt
= 30000;
761 status
= smb_raw_read(cli
->tree
, &io
);
762 CHECK_STATUS(status
, NT_STATUS_OK
);
763 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
764 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
766 printf("Trying locked region\n");
768 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
769 printf("Failed to lock file at %d\n", __LINE__
);
774 memset(buf
, 0, maxsize
);
775 io
.readbraw
.in
.offset
= 0;
776 io
.readbraw
.in
.mincnt
= 100;
777 io
.readbraw
.in
.maxcnt
= 200;
778 status
= smb_raw_read(cli
->tree
, &io
);
779 CHECK_STATUS(status
, NT_STATUS_OK
);
780 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
782 printf("Trying locked region with timeout\n");
783 memset(buf
, 0, maxsize
);
784 io
.readbraw
.in
.offset
= 0;
785 io
.readbraw
.in
.mincnt
= 100;
786 io
.readbraw
.in
.maxcnt
= 200;
787 io
.readbraw
.in
.timeout
= 10000;
788 status
= smb_raw_read(cli
->tree
, &io
);
789 CHECK_STATUS(status
, NT_STATUS_OK
);
790 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
792 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
793 printf("Trying large offset read\n");
794 io
.readbraw
.in
.offset
= ((uint64_t)0x2) << 32;
795 io
.readbraw
.in
.mincnt
= 10;
796 io
.readbraw
.in
.maxcnt
= 10;
797 io
.readbraw
.in
.timeout
= 0;
798 status
= smb_raw_read(cli
->tree
, &io
);
799 CHECK_STATUS(status
, NT_STATUS_OK
);
800 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
804 smbcli_close(cli
->tree
, fnum
);
805 smbcli_deltree(cli
->tree
, BASEDIR
);
810 test read for execute
812 static bool test_read_for_execute(struct torture_context
*tctx
,
813 struct smbcli_state
*cli
)
822 const int maxsize
= 900;
823 const char *fname
= BASEDIR
"\\test.txt";
824 const uint8_t data
[] = "TEST DATA";
826 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
828 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
830 printf("Testing RAW_READ_READX with read_for_execute\n");
832 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
833 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
834 op
.ntcreatex
.in
.flags
= 0;
835 op
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
836 op
.ntcreatex
.in
.create_options
= 0;
837 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
838 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
839 op
.ntcreatex
.in
.alloc_size
= 0;
840 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
841 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
842 op
.ntcreatex
.in
.security_flags
= 0;
843 op
.ntcreatex
.in
.fname
= fname
;
844 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
845 CHECK_STATUS(status
, NT_STATUS_OK
);
846 fnum
= op
.ntcreatex
.out
.file
.fnum
;
848 wr
.generic
.level
= RAW_WRITE_WRITEX
;
849 wr
.writex
.in
.file
.fnum
= fnum
;
850 wr
.writex
.in
.offset
= 0;
851 wr
.writex
.in
.wmode
= 0;
852 wr
.writex
.in
.remaining
= 0;
853 wr
.writex
.in
.count
= ARRAY_SIZE(data
);
854 wr
.writex
.in
.data
= data
;
855 status
= smb_raw_write(cli
->tree
, &wr
);
856 CHECK_STATUS(status
, NT_STATUS_OK
);
857 CHECK_VALUE(wr
.writex
.out
.nwritten
, ARRAY_SIZE(data
));
859 status
= smbcli_close(cli
->tree
, fnum
);
860 CHECK_STATUS(status
, NT_STATUS_OK
);
862 printf("open file with SEC_FILE_EXECUTE\n");
863 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
864 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
865 op
.ntcreatex
.in
.flags
= 0;
866 op
.ntcreatex
.in
.access_mask
= SEC_FILE_EXECUTE
;
867 op
.ntcreatex
.in
.create_options
= 0;
868 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
869 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
870 op
.ntcreatex
.in
.alloc_size
= 0;
871 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
872 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
873 op
.ntcreatex
.in
.security_flags
= 0;
874 op
.ntcreatex
.in
.fname
= fname
;
875 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
876 CHECK_STATUS(status
, NT_STATUS_OK
);
877 fnum
= op
.ntcreatex
.out
.file
.fnum
;
879 printf("read with FLAGS2_READ_PERMIT_EXECUTE\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
= true;
887 rd
.readx
.out
.data
= buf
;
888 status
= smb_raw_read(cli
->tree
, &rd
);
889 CHECK_STATUS(status
, NT_STATUS_OK
);
890 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
891 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
892 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
894 printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
895 rd
.generic
.level
= RAW_READ_READX
;
896 rd
.readx
.in
.file
.fnum
= fnum
;
897 rd
.readx
.in
.mincnt
= 0;
898 rd
.readx
.in
.maxcnt
= maxsize
;
899 rd
.readx
.in
.offset
= 0;
900 rd
.readx
.in
.remaining
= 0;
901 rd
.readx
.in
.read_for_execute
= false;
902 rd
.readx
.out
.data
= buf
;
903 status
= smb_raw_read(cli
->tree
, &rd
);
904 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
906 status
= smbcli_close(cli
->tree
, fnum
);
907 CHECK_STATUS(status
, NT_STATUS_OK
);
909 printf("open file with SEC_FILE_READ_DATA\n");
910 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
911 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
912 op
.ntcreatex
.in
.flags
= 0;
913 op
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
914 op
.ntcreatex
.in
.create_options
= 0;
915 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
916 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
917 op
.ntcreatex
.in
.alloc_size
= 0;
918 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
919 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
920 op
.ntcreatex
.in
.security_flags
= 0;
921 op
.ntcreatex
.in
.fname
= fname
;
922 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
923 CHECK_STATUS(status
, NT_STATUS_OK
);
924 fnum
= op
.ntcreatex
.out
.file
.fnum
;
926 printf("read with 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
= true;
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);
941 printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
942 rd
.generic
.level
= RAW_READ_READX
;
943 rd
.readx
.in
.file
.fnum
= fnum
;
944 rd
.readx
.in
.mincnt
= 0;
945 rd
.readx
.in
.maxcnt
= maxsize
;
946 rd
.readx
.in
.offset
= 0;
947 rd
.readx
.in
.remaining
= 0;
948 rd
.readx
.in
.read_for_execute
= false;
949 rd
.readx
.out
.data
= buf
;
950 status
= smb_raw_read(cli
->tree
, &rd
);
951 CHECK_STATUS(status
, NT_STATUS_OK
);
952 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
953 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
954 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
957 smbcli_close(cli
->tree
, fnum
);
958 smbcli_deltree(cli
->tree
, BASEDIR
);
964 basic testing of read calls
966 struct torture_suite
*torture_raw_read(TALLOC_CTX
*mem_ctx
)
968 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "read");
970 torture_suite_add_1smb_test(suite
, "read", test_read
);
971 torture_suite_add_1smb_test(suite
, "readx", test_readx
);
972 torture_suite_add_1smb_test(suite
, "lockread", test_lockread
);
973 torture_suite_add_1smb_test(suite
, "readbraw", test_readbraw
);
974 torture_suite_add_1smb_test(suite
, "read for execute",
975 test_read_for_execute
);