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 (io
.readx
.out
.nread
== io
.readx
.in
.maxcnt
) {
528 printf("SAMBA: large read extension\n");
529 CHECK_VALUE(io
.readx
.out
.nread
, 80000);
531 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
533 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
535 printf("Trying mincnt > maxcnt\n");
536 memset(buf
, 0, maxsize
);
537 io
.readx
.in
.offset
= 0;
538 io
.readx
.in
.mincnt
= 30000;
539 io
.readx
.in
.maxcnt
= 20000;
540 status
= smb_raw_read(cli
->tree
, &io
);
541 CHECK_STATUS(status
, NT_STATUS_OK
);
542 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
543 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
544 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
545 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
547 printf("Trying mincnt < maxcnt\n");
548 memset(buf
, 0, maxsize
);
549 io
.readx
.in
.offset
= 0;
550 io
.readx
.in
.mincnt
= 20000;
551 io
.readx
.in
.maxcnt
= 30000;
552 status
= smb_raw_read(cli
->tree
, &io
);
553 CHECK_STATUS(status
, NT_STATUS_OK
);
554 CHECK_VALUE(io
.readx
.out
.remaining
, 0xFFFF);
555 CHECK_VALUE(io
.readx
.out
.compaction_mode
, 0);
556 CHECK_VALUE(io
.readx
.out
.nread
, io
.readx
.in
.maxcnt
);
557 CHECK_BUFFER(buf
, seed
, io
.readx
.out
.nread
);
559 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_READX
) {
560 printf("Trying large readx\n");
561 io
.readx
.in
.offset
= 0;
562 io
.readx
.in
.mincnt
= 0;
563 io
.readx
.in
.maxcnt
= 0x10000 - 1;
564 status
= smb_raw_read(cli
->tree
, &io
);
565 CHECK_STATUS(status
, NT_STATUS_OK
);
566 CHECK_VALUE(io
.readx
.out
.nread
, 0xFFFF);
568 io
.readx
.in
.maxcnt
= 0x10000;
569 status
= smb_raw_read(cli
->tree
, &io
);
570 CHECK_STATUS(status
, NT_STATUS_OK
);
571 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
573 io
.readx
.in
.maxcnt
= 0x10001;
574 status
= smb_raw_read(cli
->tree
, &io
);
575 CHECK_STATUS(status
, NT_STATUS_OK
);
576 if (io
.readx
.out
.nread
== io
.readx
.in
.maxcnt
) {
577 printf("SAMBA: large read extension\n");
578 CHECK_VALUE(io
.readx
.out
.nread
, 0x10001);
580 CHECK_VALUE(io
.readx
.out
.nread
, 0x10000);
583 printf("Server does not support the CAP_LARGE_READX extension\n");
586 printf("Trying locked region\n");
588 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
589 printf("Failed to lock file at %d\n", __LINE__
);
594 memset(buf
, 0, maxsize
);
595 io
.readx
.in
.offset
= 0;
596 io
.readx
.in
.mincnt
= 100;
597 io
.readx
.in
.maxcnt
= 200;
598 status
= smb_raw_read(cli
->tree
, &io
);
599 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
601 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
602 printf("skipping large file tests - CAP_LARGE_FILES not set\n");
606 printf("Trying large offset read\n");
607 io
.readx
.in
.offset
= ((uint64_t)0x2) << 32;
608 io
.readx
.in
.mincnt
= 10;
609 io
.readx
.in
.maxcnt
= 10;
610 status
= smb_raw_read(cli
->tree
, &io
);
611 CHECK_STATUS(status
, NT_STATUS_OK
);
612 CHECK_VALUE(io
.readx
.out
.nread
, 0);
614 if (NT_STATUS_IS_ERR(smbcli_lock64(cli
->tree
, fnum
, io
.readx
.in
.offset
, 1, 0, WRITE_LOCK
))) {
615 printf("Failed to lock file at %d\n", __LINE__
);
620 status
= smb_raw_read(cli
->tree
, &io
);
621 CHECK_STATUS(status
, NT_STATUS_OK
);
622 CHECK_VALUE(io
.readx
.out
.nread
, 0);
625 smbcli_close(cli
->tree
, fnum
);
626 smbcli_deltree(cli
->tree
, BASEDIR
);
634 static bool test_readbraw(struct torture_context
*tctx
,
635 struct smbcli_state
*cli
)
642 const int maxsize
= 90000;
643 const char *fname
= BASEDIR
"\\test.txt";
644 const char *test_data
= "TEST DATA";
645 unsigned int seed
= time(NULL
);
647 if (!cli
->transport
->negotiate
.readbraw_supported
) {
648 printf("Server does not support readbraw - skipping\n");
652 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
654 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
656 printf("Testing RAW_READ_READBRAW\n");
658 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
660 printf("Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
));
665 printf("Trying empty file read\n");
666 io
.generic
.level
= RAW_READ_READBRAW
;
667 io
.readbraw
.in
.file
.fnum
= fnum
;
668 io
.readbraw
.in
.mincnt
= 1;
669 io
.readbraw
.in
.maxcnt
= 1;
670 io
.readbraw
.in
.offset
= 0;
671 io
.readbraw
.in
.timeout
= 0;
672 io
.readbraw
.out
.data
= buf
;
673 status
= smb_raw_read(cli
->tree
, &io
);
675 CHECK_STATUS(status
, NT_STATUS_OK
);
676 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
678 printf("Trying zero file read\n");
679 io
.readbraw
.in
.mincnt
= 0;
680 io
.readbraw
.in
.maxcnt
= 0;
681 status
= smb_raw_read(cli
->tree
, &io
);
682 CHECK_STATUS(status
, NT_STATUS_OK
);
683 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
685 printf("Trying bad fnum\n");
686 io
.readbraw
.in
.file
.fnum
= fnum
+1;
687 status
= smb_raw_read(cli
->tree
, &io
);
688 CHECK_STATUS(status
, NT_STATUS_OK
);
689 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
690 io
.readbraw
.in
.file
.fnum
= fnum
;
692 smbcli_write(cli
->tree
, fnum
, 0, test_data
, 0, strlen(test_data
));
694 printf("Trying small read\n");
695 io
.readbraw
.in
.file
.fnum
= fnum
;
696 io
.readbraw
.in
.offset
= 0;
697 io
.readbraw
.in
.mincnt
= strlen(test_data
);
698 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
699 status
= smb_raw_read(cli
->tree
, &io
);
700 CHECK_STATUS(status
, NT_STATUS_OK
);
701 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
));
702 if (memcmp(buf
, test_data
, strlen(test_data
)) != 0) {
704 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
, buf
);
708 printf("Trying short read\n");
709 io
.readbraw
.in
.offset
= 1;
710 io
.readbraw
.in
.mincnt
= strlen(test_data
);
711 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
712 status
= smb_raw_read(cli
->tree
, &io
);
713 CHECK_STATUS(status
, NT_STATUS_OK
);
714 CHECK_VALUE(io
.readbraw
.out
.nread
, strlen(test_data
)-1);
715 if (memcmp(buf
, test_data
+1, strlen(test_data
)-1) != 0) {
717 printf("incorrect data at %d!? (%s:%s)\n", __LINE__
, test_data
+1, buf
);
721 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
722 printf("Trying max offset\n");
723 io
.readbraw
.in
.offset
= ~0;
724 io
.readbraw
.in
.mincnt
= strlen(test_data
);
725 io
.readbraw
.in
.maxcnt
= strlen(test_data
);
726 status
= smb_raw_read(cli
->tree
, &io
);
727 CHECK_STATUS(status
, NT_STATUS_OK
);
728 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
731 setup_buffer(buf
, seed
, maxsize
);
732 smbcli_write(cli
->tree
, fnum
, 0, buf
, 0, maxsize
);
733 memset(buf
, 0, maxsize
);
735 printf("Trying large read\n");
736 io
.readbraw
.in
.offset
= 0;
737 io
.readbraw
.in
.mincnt
= ~0;
738 io
.readbraw
.in
.maxcnt
= ~0;
739 status
= smb_raw_read(cli
->tree
, &io
);
740 CHECK_STATUS(status
, NT_STATUS_OK
);
741 CHECK_VALUE(io
.readbraw
.out
.nread
, 0xFFFF);
742 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
744 printf("Trying mincnt > maxcnt\n");
745 memset(buf
, 0, maxsize
);
746 io
.readbraw
.in
.offset
= 0;
747 io
.readbraw
.in
.mincnt
= 30000;
748 io
.readbraw
.in
.maxcnt
= 20000;
749 status
= smb_raw_read(cli
->tree
, &io
);
750 CHECK_STATUS(status
, NT_STATUS_OK
);
751 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
752 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
754 printf("Trying mincnt < maxcnt\n");
755 memset(buf
, 0, maxsize
);
756 io
.readbraw
.in
.offset
= 0;
757 io
.readbraw
.in
.mincnt
= 20000;
758 io
.readbraw
.in
.maxcnt
= 30000;
759 status
= smb_raw_read(cli
->tree
, &io
);
760 CHECK_STATUS(status
, NT_STATUS_OK
);
761 CHECK_VALUE(io
.readbraw
.out
.nread
, io
.readbraw
.in
.maxcnt
);
762 CHECK_BUFFER(buf
, seed
, io
.readbraw
.out
.nread
);
764 printf("Trying locked region\n");
766 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 103, 1, 0, WRITE_LOCK
))) {
767 printf("Failed to lock file at %d\n", __LINE__
);
772 memset(buf
, 0, maxsize
);
773 io
.readbraw
.in
.offset
= 0;
774 io
.readbraw
.in
.mincnt
= 100;
775 io
.readbraw
.in
.maxcnt
= 200;
776 status
= smb_raw_read(cli
->tree
, &io
);
777 CHECK_STATUS(status
, NT_STATUS_OK
);
778 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
780 printf("Trying locked region with timeout\n");
781 memset(buf
, 0, maxsize
);
782 io
.readbraw
.in
.offset
= 0;
783 io
.readbraw
.in
.mincnt
= 100;
784 io
.readbraw
.in
.maxcnt
= 200;
785 io
.readbraw
.in
.timeout
= 10000;
786 status
= smb_raw_read(cli
->tree
, &io
);
787 CHECK_STATUS(status
, NT_STATUS_OK
);
788 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
790 if (cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
) {
791 printf("Trying large offset read\n");
792 io
.readbraw
.in
.offset
= ((uint64_t)0x2) << 32;
793 io
.readbraw
.in
.mincnt
= 10;
794 io
.readbraw
.in
.maxcnt
= 10;
795 io
.readbraw
.in
.timeout
= 0;
796 status
= smb_raw_read(cli
->tree
, &io
);
797 CHECK_STATUS(status
, NT_STATUS_OK
);
798 CHECK_VALUE(io
.readbraw
.out
.nread
, 0);
802 smbcli_close(cli
->tree
, fnum
);
803 smbcli_deltree(cli
->tree
, BASEDIR
);
808 test read for execute
810 static bool test_read_for_execute(struct torture_context
*tctx
,
811 struct smbcli_state
*cli
)
820 const int maxsize
= 900;
821 const char *fname
= BASEDIR
"\\test.txt";
822 const uint8_t data
[] = "TEST DATA";
824 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
826 torture_assert(tctx
, torture_setup_dir(cli
, BASEDIR
), "Failed to setup up test directory: " BASEDIR
);
828 printf("Testing RAW_READ_READX with read_for_execute\n");
830 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
831 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
832 op
.ntcreatex
.in
.flags
= 0;
833 op
.ntcreatex
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
834 op
.ntcreatex
.in
.create_options
= 0;
835 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
836 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
837 op
.ntcreatex
.in
.alloc_size
= 0;
838 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_CREATE
;
839 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
840 op
.ntcreatex
.in
.security_flags
= 0;
841 op
.ntcreatex
.in
.fname
= fname
;
842 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
843 CHECK_STATUS(status
, NT_STATUS_OK
);
844 fnum
= op
.ntcreatex
.out
.file
.fnum
;
846 wr
.generic
.level
= RAW_WRITE_WRITEX
;
847 wr
.writex
.in
.file
.fnum
= fnum
;
848 wr
.writex
.in
.offset
= 0;
849 wr
.writex
.in
.wmode
= 0;
850 wr
.writex
.in
.remaining
= 0;
851 wr
.writex
.in
.count
= ARRAY_SIZE(data
);
852 wr
.writex
.in
.data
= data
;
853 status
= smb_raw_write(cli
->tree
, &wr
);
854 CHECK_STATUS(status
, NT_STATUS_OK
);
855 CHECK_VALUE(wr
.writex
.out
.nwritten
, ARRAY_SIZE(data
));
857 status
= smbcli_close(cli
->tree
, fnum
);
858 CHECK_STATUS(status
, NT_STATUS_OK
);
860 printf("open file with SEC_FILE_EXECUTE\n");
861 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
862 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
863 op
.ntcreatex
.in
.flags
= 0;
864 op
.ntcreatex
.in
.access_mask
= SEC_FILE_EXECUTE
;
865 op
.ntcreatex
.in
.create_options
= 0;
866 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
867 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
868 op
.ntcreatex
.in
.alloc_size
= 0;
869 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
870 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
871 op
.ntcreatex
.in
.security_flags
= 0;
872 op
.ntcreatex
.in
.fname
= fname
;
873 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
874 CHECK_STATUS(status
, NT_STATUS_OK
);
875 fnum
= op
.ntcreatex
.out
.file
.fnum
;
877 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
878 rd
.generic
.level
= RAW_READ_READX
;
879 rd
.readx
.in
.file
.fnum
= fnum
;
880 rd
.readx
.in
.mincnt
= 0;
881 rd
.readx
.in
.maxcnt
= maxsize
;
882 rd
.readx
.in
.offset
= 0;
883 rd
.readx
.in
.remaining
= 0;
884 rd
.readx
.in
.read_for_execute
= true;
885 rd
.readx
.out
.data
= buf
;
886 status
= smb_raw_read(cli
->tree
, &rd
);
887 CHECK_STATUS(status
, NT_STATUS_OK
);
888 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
889 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
890 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
892 printf("read without FLAGS2_READ_PERMIT_EXECUTE (should fail)\n");
893 rd
.generic
.level
= RAW_READ_READX
;
894 rd
.readx
.in
.file
.fnum
= fnum
;
895 rd
.readx
.in
.mincnt
= 0;
896 rd
.readx
.in
.maxcnt
= maxsize
;
897 rd
.readx
.in
.offset
= 0;
898 rd
.readx
.in
.remaining
= 0;
899 rd
.readx
.in
.read_for_execute
= false;
900 rd
.readx
.out
.data
= buf
;
901 status
= smb_raw_read(cli
->tree
, &rd
);
902 CHECK_STATUS(status
, NT_STATUS_ACCESS_DENIED
);
904 status
= smbcli_close(cli
->tree
, fnum
);
905 CHECK_STATUS(status
, NT_STATUS_OK
);
907 printf("open file with SEC_FILE_READ_DATA\n");
908 op
.generic
.level
= RAW_OPEN_NTCREATEX
;
909 op
.ntcreatex
.in
.root_fid
.fnum
= 0;
910 op
.ntcreatex
.in
.flags
= 0;
911 op
.ntcreatex
.in
.access_mask
= SEC_FILE_READ_DATA
;
912 op
.ntcreatex
.in
.create_options
= 0;
913 op
.ntcreatex
.in
.file_attr
= FILE_ATTRIBUTE_NORMAL
;
914 op
.ntcreatex
.in
.share_access
= NTCREATEX_SHARE_ACCESS_READ
| NTCREATEX_SHARE_ACCESS_WRITE
;
915 op
.ntcreatex
.in
.alloc_size
= 0;
916 op
.ntcreatex
.in
.open_disposition
= NTCREATEX_DISP_OPEN
;
917 op
.ntcreatex
.in
.impersonation
= NTCREATEX_IMPERSONATION_ANONYMOUS
;
918 op
.ntcreatex
.in
.security_flags
= 0;
919 op
.ntcreatex
.in
.fname
= fname
;
920 status
= smb_raw_open(cli
->tree
, tctx
, &op
);
921 CHECK_STATUS(status
, NT_STATUS_OK
);
922 fnum
= op
.ntcreatex
.out
.file
.fnum
;
924 printf("read with FLAGS2_READ_PERMIT_EXECUTE\n");
925 rd
.generic
.level
= RAW_READ_READX
;
926 rd
.readx
.in
.file
.fnum
= fnum
;
927 rd
.readx
.in
.mincnt
= 0;
928 rd
.readx
.in
.maxcnt
= maxsize
;
929 rd
.readx
.in
.offset
= 0;
930 rd
.readx
.in
.remaining
= 0;
931 rd
.readx
.in
.read_for_execute
= true;
932 rd
.readx
.out
.data
= buf
;
933 status
= smb_raw_read(cli
->tree
, &rd
);
934 CHECK_STATUS(status
, NT_STATUS_OK
);
935 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
936 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
937 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
939 printf("read without FLAGS2_READ_PERMIT_EXECUTE\n");
940 rd
.generic
.level
= RAW_READ_READX
;
941 rd
.readx
.in
.file
.fnum
= fnum
;
942 rd
.readx
.in
.mincnt
= 0;
943 rd
.readx
.in
.maxcnt
= maxsize
;
944 rd
.readx
.in
.offset
= 0;
945 rd
.readx
.in
.remaining
= 0;
946 rd
.readx
.in
.read_for_execute
= false;
947 rd
.readx
.out
.data
= buf
;
948 status
= smb_raw_read(cli
->tree
, &rd
);
949 CHECK_STATUS(status
, NT_STATUS_OK
);
950 CHECK_VALUE(rd
.readx
.out
.nread
, ARRAY_SIZE(data
));
951 CHECK_VALUE(rd
.readx
.out
.remaining
, 0xFFFF);
952 CHECK_VALUE(rd
.readx
.out
.compaction_mode
, 0);
955 smbcli_close(cli
->tree
, fnum
);
956 smbcli_deltree(cli
->tree
, BASEDIR
);
962 basic testing of read calls
964 struct torture_suite
*torture_raw_read(TALLOC_CTX
*mem_ctx
)
966 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "read");
968 torture_suite_add_1smb_test(suite
, "read", test_read
);
969 torture_suite_add_1smb_test(suite
, "readx", test_readx
);
970 torture_suite_add_1smb_test(suite
, "lockread", test_lockread
);
971 torture_suite_add_1smb_test(suite
, "readbraw", test_readbraw
);
972 torture_suite_add_1smb_test(suite
, "read for execute",
973 test_read_for_execute
);