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
, 0);
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 if (torture_setting_bool(tctx
, "samba3", false) ||
573 torture_setting_bool(tctx
, "samba4", false)) {
574 printf("SAMBA: large read extension\n");
575 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
577 CHECK_VALUE(io
.readx
.out
.nread
, 0);
580 io
.readx
.in
.maxcnt
= 0x10001;
581 status
= smb_raw_read(cli
->tree
, &io
);
582 CHECK_STATUS(status
, NT_STATUS_OK
);
583 if (torture_setting_bool(tctx
, "samba3", false) ||
584 torture_setting_bool(tctx
, "samba4", false)) {
585 printf("SAMBA: large read extension\n");
586 CHECK_VALUE(io
.readx
.out
.nread
, 0x10001);
588 CHECK_VALUE(io
.readx
.out
.nread
, 0);
591 printf("Server does not support the CAP_LARGE_READX extension\n");
594 printf("Trying locked region\n");
596 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
597 printf("Failed to lock file at %d\n", __LINE__
);
602 memset(buf
, 0, maxsize
);
603 io
.readx
.in
.offset
= 0;
604 io
.readx
.in
.mincnt
= 100;
605 io
.readx
.in
.maxcnt
= 200;
606 status
= smb_raw_read(cli
->tree
, &io
);
607 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
609 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
610 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
614 printf("Trying large offset read\n");
615 io
.readx
.in
.offset
= ((uint64_t)0x2) << 32;
616 io
.readx
.in
.mincnt
= 10;
617 io
.readx
.in
.maxcnt
= 10;
618 status
= smb_raw_read(cli
->tree
, &io
);
619 CHECK_STATUS(status
, NT_STATUS_OK
);
620 CHECK_VALUE(io
.readx
.out
.nread
, 0);
622 if (NT_STATUS_IS_ERR(smbcli_lock64(cli
->tree
, fnum
, io
.readx
.in
.offset
, 1, 0, WRITE_LOCK
))) {
623 printf("Failed to lock file at %d\n", __LINE__
);
628 status
= smb_raw_read(cli
->tree
, &io
);
629 CHECK_STATUS(status
, NT_STATUS_OK
);
630 CHECK_VALUE(io
.readx
.out
.nread
, 0);
633 smbcli_close(cli
->tree
, fnum
);
634 smbcli_deltree(cli
->tree
, BASEDIR
);
642 static bool test_readbraw(struct torture_context
*tctx
,
643 struct smbcli_state
*cli
)
650 const int maxsize
= 90000;
651 const char *fname
= BASEDIR
"\\test.txt";
652 const char *test_data
= "TEST DATA";
653 unsigned int seed
= time(NULL
);
655 if (!cli
->transport
->negotiate
.readbraw_supported
) {
656 printf("Server does not support readbraw - skipping\n");
660 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
662 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
664 printf("Testing RAW_READ_READBRAW\n");
666 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
668 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
673 printf("Trying empty file read\n");
674 io
.generic
.level
= RAW_READ_READBRAW
;
675 io
.readbraw
.in
.file
.fnum
= fnum
;
676 io
.readbraw
.in
.mincnt
= 1;
677 io
.readbraw
.in
.maxcnt
= 1;
678 io
.readbraw
.in
.offset
= 0;
679 io
.readbraw
.in
.timeout
= 0;
680 io
.readbraw
.out
.data
= buf
;
681 status
= smb_raw_read(cli
->tree
, &io
);
683 CHECK_STATUS(status
, NT_STATUS_OK
);
684 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
686 printf("Trying zero file read\n");
687 io
.readbraw
.in
.mincnt
= 0;
688 io
.readbraw
.in
.maxcnt
= 0;
689 status
= smb_raw_read(cli
->tree
, &io
);
690 CHECK_STATUS(status
, NT_STATUS_OK
);
691 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
693 printf("Trying bad fnum\n");
694 io
.readbraw
.in
.file
.fnum
= fnum
+1;
695 status
= smb_raw_read(cli
->tree
, &io
);
696 CHECK_STATUS(status
, NT_STATUS_OK
);
697 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
698 io
.readbraw
.in
.file
.fnum
= fnum
;
700 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
702 printf("Trying small read\n");
703 io
.readbraw
.in
.file
.fnum
= fnum
;
704 io
.readbraw
.in
.offset
= 0;
705 io
.readbraw
.in
.mincnt
= strlen(test_data
);
706 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
707 status
= smb_raw_read(cli
->tree
, &io
);
708 CHECK_STATUS(status
, NT_STATUS_OK
);
709 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
));
710 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
712 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
716 printf("Trying short read\n");
717 io
.readbraw
.in
.offset
= 1;
718 io
.readbraw
.in
.mincnt
= strlen(test_data
);
719 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
720 status
= smb_raw_read(cli
->tree
, &io
);
721 CHECK_STATUS(status
, NT_STATUS_OK
);
722 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
)-1);
723 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
725 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
729 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
730 printf("Trying max offset\n");
731 io
.readbraw
.in
.offset
= ~0;
732 io
.readbraw
.in
.mincnt
= strlen(test_data
);
733 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
734 status
= smb_raw_read(cli
->tree
, &io
);
735 CHECK_STATUS(status
, NT_STATUS_OK
);
736 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
739 setup_buffer(buf
, seed
, maxsize
);
740 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
741 memset(buf
, 0, maxsize
);
743 printf("Trying large read\n");
744 io
.readbraw
.in
.offset
= 0;
745 io
.readbraw
.in
.mincnt
= ~0;
746 io
.readbraw
.in
.maxcnt
= ~0;
747 status
= smb_raw_read(cli
->tree
, &io
);
748 CHECK_STATUS(status
, NT_STATUS_OK
);
749 CHECK_VALUE(io
.readbraw
.out
.nread
, 0xFFFF);
750 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
752 printf("Trying mincnt > maxcnt\n");
753 memset(buf
, 0, maxsize
);
754 io
.readbraw
.in
.offset
= 0;
755 io
.readbraw
.in
.mincnt
= 30000;
756 io
.readbraw
.in
.maxcnt
= 20000;
757 status
= smb_raw_read(cli
->tree
, &io
);
758 CHECK_STATUS(status
, NT_STATUS_OK
);
759 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
760 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
762 printf("Trying mincnt < maxcnt\n");
763 memset(buf
, 0, maxsize
);
764 io
.readbraw
.in
.offset
= 0;
765 io
.readbraw
.in
.mincnt
= 20000;
766 io
.readbraw
.in
.maxcnt
= 30000;
767 status
= smb_raw_read(cli
->tree
, &io
);
768 CHECK_STATUS(status
, NT_STATUS_OK
);
769 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
770 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
772 printf("Trying locked region\n");
774 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
775 printf("Failed to lock file at %d\n", __LINE__
);
780 memset(buf
, 0, maxsize
);
781 io
.readbraw
.in
.offset
= 0;
782 io
.readbraw
.in
.mincnt
= 100;
783 io
.readbraw
.in
.maxcnt
= 200;
784 status
= smb_raw_read(cli
->tree
, &io
);
785 CHECK_STATUS(status
, NT_STATUS_OK
);
786 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
788 printf("Trying locked region with timeout\n");
789 memset(buf
, 0, maxsize
);
790 io
.readbraw
.in
.offset
= 0;
791 io
.readbraw
.in
.mincnt
= 100;
792 io
.readbraw
.in
.maxcnt
= 200;
793 io
.readbraw
.in
.timeout
= 10000;
794 status
= smb_raw_read(cli
->tree
, &io
);
795 CHECK_STATUS(status
, NT_STATUS_OK
);
796 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
798 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
799 printf("Trying large offset read\n");
800 io
.readbraw
.in
.offset
= ((uint64_t)0x2) << 32;
801 io
.readbraw
.in
.mincnt
= 10;
802 io
.readbraw
.in
.maxcnt
= 10;
803 io
.readbraw
.in
.timeout
= 0;
804 status
= smb_raw_read(cli
->tree
, &io
);
805 CHECK_STATUS(status
, NT_STATUS_OK
);
806 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
810 smbcli_close(cli
->tree
, fnum
);
811 smbcli_deltree(cli
->tree
, BASEDIR
);
816 test read for execute
818 static bool test_read_for_execute(struct torture_context
*tctx
,
819 struct smbcli_state
*cli
)
828 const int maxsize
= 900;
829 const char *fname
= BASEDIR
"\\test.txt";
830 const uint8_t data
[] = "TEST DATA";
832 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
834 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
836 printf("Testing RAW_READ_READX with read_for_execute\n");
838 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
839 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
840 op
.ntcreatex
.in
.flags
= 0;
841 op
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
842 op
.ntcreatex
.in
.create_options
= 0;
843 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
844 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
845 op
.ntcreatex
.in
.alloc_size
= 0;
846 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
847 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
848 op
.ntcreatex
.in
.security_flags
= 0;
849 op
.ntcreatex
.in
.fname
= fname
;
850 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
851 CHECK_STATUS(status
, NT_STATUS_OK
);
852 fnum
= op
.ntcreatex
.out
.file
.fnum
;
854 wr
.generic
.level
= RAW_WRITE_WRITEX
;
855 wr
.writex
.in
.file
.fnum
= fnum
;
856 wr
.writex
.in
.offset
= 0;
857 wr
.writex
.in
.wmode
= 0;
858 wr
.writex
.in
.remaining
= 0;
859 wr
.writex
.in
.count
= ARRAY_SIZE(data
);
860 wr
.writex
.in
.data
= data
;
861 status
= smb_raw_write(cli
->tree
, &wr
);
862 CHECK_STATUS(status
, NT_STATUS_OK
);
863 CHECK_VALUE(wr
.writex
.out
.nwritten
, ARRAY_SIZE(data
));
865 status
= smbcli_close(cli
->tree
, fnum
);
866 CHECK_STATUS(status
, NT_STATUS_OK
);
868 printf("open file with SEC_FILE_EXECUTE\n");
869 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
870 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
871 op
.ntcreatex
.in
.flags
= 0;
872 op
.ntcreatex
.in
.access_mask
= SEC_FILE_EXECUTE
;
873 op
.ntcreatex
.in
.create_options
= 0;
874 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
875 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
876 op
.ntcreatex
.in
.alloc_size
= 0;
877 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
878 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
879 op
.ntcreatex
.in
.security_flags
= 0;
880 op
.ntcreatex
.in
.fname
= fname
;
881 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
882 CHECK_STATUS(status
, NT_STATUS_OK
);
883 fnum
= op
.ntcreatex
.out
.file
.fnum
;
885 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
886 rd
.generic
.level
= RAW_READ_READX
;
887 rd
.readx
.in
.file
.fnum
= fnum
;
888 rd
.readx
.in
.mincnt
= 0;
889 rd
.readx
.in
.maxcnt
= maxsize
;
890 rd
.readx
.in
.offset
= 0;
891 rd
.readx
.in
.remaining
= 0;
892 rd
.readx
.in
.read_for_execute
= true;
893 rd
.readx
.out
.data
= buf
;
894 status
= smb_raw_read(cli
->tree
, &rd
);
895 CHECK_STATUS(status
, NT_STATUS_OK
);
896 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
897 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
898 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
900 printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
901 rd
.generic
.level
= RAW_READ_READX
;
902 rd
.readx
.in
.file
.fnum
= fnum
;
903 rd
.readx
.in
.mincnt
= 0;
904 rd
.readx
.in
.maxcnt
= maxsize
;
905 rd
.readx
.in
.offset
= 0;
906 rd
.readx
.in
.remaining
= 0;
907 rd
.readx
.in
.read_for_execute
= false;
908 rd
.readx
.out
.data
= buf
;
909 status
= smb_raw_read(cli
->tree
, &rd
);
910 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
912 status
= smbcli_close(cli
->tree
, fnum
);
913 CHECK_STATUS(status
, NT_STATUS_OK
);
915 printf("open file with SEC_FILE_READ_DATA\n");
916 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
917 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
918 op
.ntcreatex
.in
.flags
= 0;
919 op
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
920 op
.ntcreatex
.in
.create_options
= 0;
921 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
922 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
923 op
.ntcreatex
.in
.alloc_size
= 0;
924 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
925 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
926 op
.ntcreatex
.in
.security_flags
= 0;
927 op
.ntcreatex
.in
.fname
= fname
;
928 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
929 CHECK_STATUS(status
, NT_STATUS_OK
);
930 fnum
= op
.ntcreatex
.out
.file
.fnum
;
932 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
933 rd
.generic
.level
= RAW_READ_READX
;
934 rd
.readx
.in
.file
.fnum
= fnum
;
935 rd
.readx
.in
.mincnt
= 0;
936 rd
.readx
.in
.maxcnt
= maxsize
;
937 rd
.readx
.in
.offset
= 0;
938 rd
.readx
.in
.remaining
= 0;
939 rd
.readx
.in
.read_for_execute
= true;
940 rd
.readx
.out
.data
= buf
;
941 status
= smb_raw_read(cli
->tree
, &rd
);
942 CHECK_STATUS(status
, NT_STATUS_OK
);
943 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
944 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
945 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
947 printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
948 rd
.generic
.level
= RAW_READ_READX
;
949 rd
.readx
.in
.file
.fnum
= fnum
;
950 rd
.readx
.in
.mincnt
= 0;
951 rd
.readx
.in
.maxcnt
= maxsize
;
952 rd
.readx
.in
.offset
= 0;
953 rd
.readx
.in
.remaining
= 0;
954 rd
.readx
.in
.read_for_execute
= false;
955 rd
.readx
.out
.data
= buf
;
956 status
= smb_raw_read(cli
->tree
, &rd
);
957 CHECK_STATUS(status
, NT_STATUS_OK
);
958 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
959 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
960 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
963 smbcli_close(cli
->tree
, fnum
);
964 smbcli_deltree(cli
->tree
, BASEDIR
);
970 basic testing of read calls
972 struct torture_suite
*torture_raw_read(TALLOC_CTX
*mem_ctx
)
974 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "read");
976 torture_suite_add_1smb_test(suite
, "read", test_read
);
977 torture_suite_add_1smb_test(suite
, "readx", test_readx
);
978 torture_suite_add_1smb_test(suite
, "lockread", test_lockread
);
979 torture_suite_add_1smb_test(suite
, "readbraw", test_readbraw
);
980 torture_suite_add_1smb_test(suite
, "read for execute",
981 test_read_for_execute
);