2 Unix SMB/CIFS implementation.
3 test suite for various write operations
5 Copyright (C) Andrew Tridgell 2003
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "libcli/raw/libcliraw.h"
23 #include "system/time.h"
24 #include "system/filesys.h"
25 #include "libcli/libcli.h"
26 #include "torture/util.h"
28 #define CHECK_STATUS(status, correct) do { \
29 if (!NT_STATUS_EQUAL(status, correct)) { \
30 torture_fail(tctx, talloc_asprintf(tctx, "(%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 torture_fail(tctx, talloc_asprintf(tctx, "(%s) Incorrect value %s=%d - should be %d\n", \
39 __location__, #v, v, correct)); \
44 #define CHECK_BUFFER(buf, seed, len) do { \
45 if (!check_buffer(tctx, buf, seed, len, __location__)) { \
50 #define CHECK_ALL_INFO(v, field) do { \
51 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
52 finfo.all_info.in.file.path = fname; \
53 status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
54 CHECK_STATUS(status, NT_STATUS_OK); \
55 if ((v) != finfo.all_info.out.field) { \
56 torture_comment(tctx, "(%s) wrong value for field %s %.0f - %.0f\n", \
57 __location__, #field, (double)v, (double)finfo.all_info.out.field); \
58 dump_all_info(tctx, &finfo); \
63 #define BASEDIR "\\testwrite"
67 setup a random buffer based on a seed
69 static void setup_buffer(uint8_t *buf
, unsigned int seed
, int len
)
73 for (i
=0;i
<len
;i
++) buf
[i
] = random();
77 check a random buffer based on a seed
79 static bool check_buffer(struct torture_context
*tctx
,
80 uint8_t *buf
, unsigned int seed
, int len
, const char *location
)
87 torture_fail(tctx
, talloc_asprintf(tctx
, "Buffer incorrect at %s! ofs=%d buf=0x%x correct=0x%x\n",
88 location
, i
, buf
[i
], v
));
98 static bool test_write(struct torture_context
*tctx
,
99 struct smbcli_state
*cli
)
106 const int maxsize
= 90000;
107 const char *fname
= BASEDIR
"\\test.txt";
108 unsigned int seed
= time(NULL
);
109 union smb_fileinfo finfo
;
111 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
113 if (!torture_setup_dir(cli
, BASEDIR
)) {
114 torture_fail(tctx
, "failed to setup basedir");
117 torture_comment(tctx
, "Testing RAW_WRITE_WRITE\n");
118 io
.generic
.level
= RAW_WRITE_WRITE
;
120 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
123 torture_fail_goto(tctx
, done
,
124 talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
127 torture_comment(tctx
, "Trying zero write\n");
128 io
.write
.in
.file
.fnum
= fnum
;
129 io
.write
.in
.count
= 0;
130 io
.write
.in
.offset
= 0;
131 io
.write
.in
.remaining
= 0;
132 io
.write
.in
.data
= buf
;
133 status
= smb_raw_write(cli
->tree
, &io
);
134 CHECK_STATUS(status
, NT_STATUS_OK
);
135 CHECK_VALUE(io
.write
.out
.nwritten
, 0);
137 setup_buffer(buf
, seed
, maxsize
);
139 torture_comment(tctx
, "Trying small write\n");
140 io
.write
.in
.count
= 9;
141 io
.write
.in
.offset
= 4;
142 io
.write
.in
.data
= buf
;
143 status
= smb_raw_write(cli
->tree
, &io
);
144 CHECK_STATUS(status
, NT_STATUS_OK
);
145 CHECK_VALUE(io
.write
.out
.nwritten
, io
.write
.in
.count
);
147 memset(buf
, 0, maxsize
);
148 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
150 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
152 CHECK_BUFFER(buf
+4, seed
, 9);
153 CHECK_VALUE(IVAL(buf
,0), 0);
155 setup_buffer(buf
, seed
, maxsize
);
157 torture_comment(tctx
, "Trying large write\n");
158 io
.write
.in
.count
= 4000;
159 io
.write
.in
.offset
= 0;
160 io
.write
.in
.data
= buf
;
161 status
= smb_raw_write(cli
->tree
, &io
);
162 CHECK_STATUS(status
, NT_STATUS_OK
);
163 CHECK_VALUE(io
.write
.out
.nwritten
, 4000);
165 memset(buf
, 0, maxsize
);
166 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
168 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
170 CHECK_BUFFER(buf
, seed
, 4000);
172 torture_comment(tctx
, "Trying bad fnum\n");
173 io
.write
.in
.file
.fnum
= fnum
+1;
174 io
.write
.in
.count
= 4000;
175 io
.write
.in
.offset
= 0;
176 io
.write
.in
.data
= buf
;
177 status
= smb_raw_write(cli
->tree
, &io
);
178 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
180 torture_comment(tctx
, "Setting file as sparse\n");
181 status
= torture_set_sparse(cli
->tree
, fnum
);
182 CHECK_STATUS(status
, NT_STATUS_OK
);
184 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
185 torture_comment(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
189 torture_comment(tctx
, "Trying 2^32 offset\n");
190 setup_buffer(buf
, seed
, maxsize
);
191 io
.write
.in
.file
.fnum
= fnum
;
192 io
.write
.in
.count
= 4000;
193 io
.write
.in
.offset
= 0xFFFFFFFF - 2000;
194 io
.write
.in
.data
= buf
;
195 status
= smb_raw_write(cli
->tree
, &io
);
196 CHECK_STATUS(status
, NT_STATUS_OK
);
197 CHECK_VALUE(io
.write
.out
.nwritten
, 4000);
198 CHECK_ALL_INFO(io
.write
.in
.count
+ (uint64_t)io
.write
.in
.offset
, size
);
200 memset(buf
, 0, maxsize
);
201 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.write
.in
.offset
, 4000) != 4000) {
203 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
205 CHECK_BUFFER(buf
, seed
, 4000);
208 smbcli_close(cli
->tree
, fnum
);
209 smb_raw_exit(cli
->session
);
210 smbcli_deltree(cli
->tree
, BASEDIR
);
218 static bool test_writex(struct torture_context
*tctx
,
219 struct smbcli_state
*cli
)
226 const int maxsize
= 90000;
227 const char *fname
= BASEDIR
"\\test.txt";
228 unsigned int seed
= time(NULL
);
229 union smb_fileinfo finfo
;
232 if (!torture_setting_bool(tctx
, "dangerous", false)) {
234 torture_comment(tctx
, "dangerous not set - limiting range of test to 2^%d\n", max_bits
);
237 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
239 if (!cli
->transport
->negotiate
.lockread_supported
) {
240 torture_comment(tctx
, "Server does not support writeunlock - skipping\n");
244 if (!torture_setup_dir(cli
, BASEDIR
)) {
245 torture_fail(tctx
, "failed to setup basedir");
248 torture_comment(tctx
, "Testing RAW_WRITE_WRITEX\n");
249 io
.generic
.level
= RAW_WRITE_WRITEX
;
251 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
254 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
257 torture_comment(tctx
, "Trying zero write\n");
258 io
.writex
.in
.file
.fnum
= fnum
;
259 io
.writex
.in
.offset
= 0;
260 io
.writex
.in
.wmode
= 0;
261 io
.writex
.in
.remaining
= 0;
262 io
.writex
.in
.count
= 0;
263 io
.writex
.in
.data
= buf
;
264 status
= smb_raw_write(cli
->tree
, &io
);
265 CHECK_STATUS(status
, NT_STATUS_OK
);
266 CHECK_VALUE(io
.writex
.out
.nwritten
, 0);
268 setup_buffer(buf
, seed
, maxsize
);
270 torture_comment(tctx
, "Trying small write\n");
271 io
.writex
.in
.count
= 9;
272 io
.writex
.in
.offset
= 4;
273 io
.writex
.in
.data
= buf
;
274 status
= smb_raw_write(cli
->tree
, &io
);
275 CHECK_STATUS(status
, NT_STATUS_OK
);
276 CHECK_VALUE(io
.writex
.out
.nwritten
, io
.writex
.in
.count
);
278 memset(buf
, 0, maxsize
);
279 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
281 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
283 CHECK_BUFFER(buf
+4, seed
, 9);
284 CHECK_VALUE(IVAL(buf
,0), 0);
286 setup_buffer(buf
, seed
, maxsize
);
288 torture_comment(tctx
, "Trying large write\n");
289 io
.writex
.in
.count
= 4000;
290 io
.writex
.in
.offset
= 0;
291 io
.writex
.in
.data
= buf
;
292 status
= smb_raw_write(cli
->tree
, &io
);
293 CHECK_STATUS(status
, NT_STATUS_OK
);
294 CHECK_VALUE(io
.writex
.out
.nwritten
, 4000);
296 memset(buf
, 0, maxsize
);
297 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
299 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
301 CHECK_BUFFER(buf
, seed
, 4000);
303 torture_comment(tctx
, "Trying bad fnum\n");
304 io
.writex
.in
.file
.fnum
= fnum
+1;
305 io
.writex
.in
.count
= 4000;
306 io
.writex
.in
.offset
= 0;
307 io
.writex
.in
.data
= buf
;
308 status
= smb_raw_write(cli
->tree
, &io
);
309 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
311 torture_comment(tctx
, "Testing wmode\n");
312 io
.writex
.in
.file
.fnum
= fnum
;
313 io
.writex
.in
.count
= 1;
314 io
.writex
.in
.offset
= 0;
315 io
.writex
.in
.wmode
= 1;
316 io
.writex
.in
.data
= buf
;
317 status
= smb_raw_write(cli
->tree
, &io
);
318 CHECK_STATUS(status
, NT_STATUS_OK
);
319 CHECK_VALUE(io
.writex
.out
.nwritten
, io
.writex
.in
.count
);
321 io
.writex
.in
.wmode
= 2;
322 status
= smb_raw_write(cli
->tree
, &io
);
323 CHECK_STATUS(status
, NT_STATUS_OK
);
324 CHECK_VALUE(io
.writex
.out
.nwritten
, io
.writex
.in
.count
);
327 torture_comment(tctx
, "Trying locked region\n");
329 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 3, 1, 0, WRITE_LOCK
))) {
331 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to lock file at %s\n", __location__
));
334 io
.writex
.in
.wmode
= 0;
335 io
.writex
.in
.count
= 4;
336 io
.writex
.in
.offset
= 0;
337 status
= smb_raw_write(cli
->tree
, &io
);
338 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
340 torture_comment(tctx
, "Setting file as sparse\n");
341 status
= torture_set_sparse(cli
->tree
, fnum
);
342 CHECK_STATUS(status
, NT_STATUS_OK
);
344 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
345 torture_skip(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
348 torture_comment(tctx
, "Trying 2^32 offset\n");
349 setup_buffer(buf
, seed
, maxsize
);
350 io
.writex
.in
.file
.fnum
= fnum
;
351 io
.writex
.in
.count
= 4000;
352 io
.writex
.in
.offset
= 0xFFFFFFFF - 2000;
353 io
.writex
.in
.data
= buf
;
354 status
= smb_raw_write(cli
->tree
, &io
);
355 CHECK_STATUS(status
, NT_STATUS_OK
);
356 CHECK_VALUE(io
.writex
.out
.nwritten
, 4000);
357 CHECK_ALL_INFO(io
.writex
.in
.count
+ (uint64_t)io
.writex
.in
.offset
, size
);
359 memset(buf
, 0, maxsize
);
360 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writex
.in
.offset
, 4000) != 4000) {
362 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
364 CHECK_BUFFER(buf
, seed
, 4000);
366 for (i
=33;i
<max_bits
;i
++) {
367 torture_comment(tctx
, "Trying 2^%d offset\n", i
);
368 setup_buffer(buf
, seed
+1, maxsize
);
369 io
.writex
.in
.file
.fnum
= fnum
;
370 io
.writex
.in
.count
= 4000;
371 io
.writex
.in
.offset
= ((uint64_t)1) << i
;
372 io
.writex
.in
.data
= buf
;
373 status
= smb_raw_write(cli
->tree
, &io
);
375 NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
378 CHECK_STATUS(status
, NT_STATUS_OK
);
379 CHECK_VALUE(io
.writex
.out
.nwritten
, 4000);
380 CHECK_ALL_INFO(io
.writex
.in
.count
+ (uint64_t)io
.writex
.in
.offset
, size
);
382 memset(buf
, 0, maxsize
);
383 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writex
.in
.offset
, 4000) != 4000) {
385 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
387 CHECK_BUFFER(buf
, seed
+1, 4000);
389 torture_comment(tctx
, "limit is 2^%d\n", i
);
391 setup_buffer(buf
, seed
, maxsize
);
394 smbcli_close(cli
->tree
, fnum
);
395 smb_raw_exit(cli
->session
);
396 smbcli_deltree(cli
->tree
, BASEDIR
);
402 test write unlock ops
404 static bool test_writeunlock(struct torture_context
*tctx
,
405 struct smbcli_state
*cli
)
412 const int maxsize
= 90000;
413 const char *fname
= BASEDIR
"\\test.txt";
414 unsigned int seed
= time(NULL
);
415 union smb_fileinfo finfo
;
417 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
419 if (!cli
->transport
->negotiate
.lockread_supported
) {
420 torture_skip(tctx
, "Server does not support writeunlock - skipping\n");
423 if (!torture_setup_dir(cli
, BASEDIR
)) {
424 torture_fail(tctx
, "failed to setup basedir");
427 torture_comment(tctx
, "Testing RAW_WRITE_WRITEUNLOCK\n");
428 io
.generic
.level
= RAW_WRITE_WRITEUNLOCK
;
430 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
433 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
436 torture_comment(tctx
, "Trying zero write\n");
437 io
.writeunlock
.in
.file
.fnum
= fnum
;
438 io
.writeunlock
.in
.count
= 0;
439 io
.writeunlock
.in
.offset
= 0;
440 io
.writeunlock
.in
.remaining
= 0;
441 io
.writeunlock
.in
.data
= buf
;
442 status
= smb_raw_write(cli
->tree
, &io
);
443 CHECK_STATUS(status
, NT_STATUS_OK
);
444 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, io
.writeunlock
.in
.count
);
446 setup_buffer(buf
, seed
, maxsize
);
448 torture_comment(tctx
, "Trying small write\n");
449 io
.writeunlock
.in
.count
= 9;
450 io
.writeunlock
.in
.offset
= 4;
451 io
.writeunlock
.in
.data
= buf
;
452 status
= smb_raw_write(cli
->tree
, &io
);
453 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
454 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
456 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
458 CHECK_BUFFER(buf
+4, seed
, 9);
459 CHECK_VALUE(IVAL(buf
,0), 0);
461 setup_buffer(buf
, seed
, maxsize
);
462 smbcli_lock(cli
->tree
, fnum
, io
.writeunlock
.in
.offset
, io
.writeunlock
.in
.count
,
464 status
= smb_raw_write(cli
->tree
, &io
);
465 CHECK_STATUS(status
, NT_STATUS_OK
);
466 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, io
.writeunlock
.in
.count
);
468 memset(buf
, 0, maxsize
);
469 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
471 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
473 CHECK_BUFFER(buf
+4, seed
, 9);
474 CHECK_VALUE(IVAL(buf
,0), 0);
476 setup_buffer(buf
, seed
, maxsize
);
478 torture_comment(tctx
, "Trying large write\n");
479 io
.writeunlock
.in
.count
= 4000;
480 io
.writeunlock
.in
.offset
= 0;
481 io
.writeunlock
.in
.data
= buf
;
482 smbcli_lock(cli
->tree
, fnum
, io
.writeunlock
.in
.offset
, io
.writeunlock
.in
.count
,
484 status
= smb_raw_write(cli
->tree
, &io
);
485 CHECK_STATUS(status
, NT_STATUS_OK
);
486 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, 4000);
488 status
= smb_raw_write(cli
->tree
, &io
);
489 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
491 memset(buf
, 0, maxsize
);
492 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
494 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
496 CHECK_BUFFER(buf
, seed
, 4000);
498 torture_comment(tctx
, "Trying bad fnum\n");
499 io
.writeunlock
.in
.file
.fnum
= fnum
+1;
500 io
.writeunlock
.in
.count
= 4000;
501 io
.writeunlock
.in
.offset
= 0;
502 io
.writeunlock
.in
.data
= buf
;
503 status
= smb_raw_write(cli
->tree
, &io
);
504 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
506 torture_comment(tctx
, "Setting file as sparse\n");
507 status
= torture_set_sparse(cli
->tree
, fnum
);
508 CHECK_STATUS(status
, NT_STATUS_OK
);
510 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
511 torture_skip(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
514 torture_comment(tctx
, "Trying 2^32 offset\n");
515 setup_buffer(buf
, seed
, maxsize
);
516 io
.writeunlock
.in
.file
.fnum
= fnum
;
517 io
.writeunlock
.in
.count
= 4000;
518 io
.writeunlock
.in
.offset
= 0xFFFFFFFF - 2000;
519 io
.writeunlock
.in
.data
= buf
;
520 smbcli_lock(cli
->tree
, fnum
, io
.writeunlock
.in
.offset
, io
.writeunlock
.in
.count
,
522 status
= smb_raw_write(cli
->tree
, &io
);
523 CHECK_STATUS(status
, NT_STATUS_OK
);
524 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, 4000);
525 CHECK_ALL_INFO(io
.writeunlock
.in
.count
+ (uint64_t)io
.writeunlock
.in
.offset
, size
);
527 memset(buf
, 0, maxsize
);
528 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writeunlock
.in
.offset
, 4000) != 4000) {
530 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
532 CHECK_BUFFER(buf
, seed
, 4000);
535 smbcli_close(cli
->tree
, fnum
);
536 smb_raw_exit(cli
->session
);
537 smbcli_deltree(cli
->tree
, BASEDIR
);
545 static bool test_writeclose(struct torture_context
*tctx
,
546 struct smbcli_state
*cli
)
553 const int maxsize
= 90000;
554 const char *fname
= BASEDIR
"\\test.txt";
555 unsigned int seed
= time(NULL
);
556 union smb_fileinfo finfo
;
558 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
560 if (!torture_setting_bool(tctx
, "writeclose_support", true)) {
561 torture_skip(tctx
, "Server does not support writeclose - skipping\n");
564 if (!torture_setup_dir(cli
, BASEDIR
)) {
565 torture_fail(tctx
, "failed to setup basedir");
568 torture_comment(tctx
, "Testing RAW_WRITE_WRITECLOSE\n");
569 io
.generic
.level
= RAW_WRITE_WRITECLOSE
;
571 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
574 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
577 torture_comment(tctx
, "Trying zero write\n");
578 io
.writeclose
.in
.file
.fnum
= fnum
;
579 io
.writeclose
.in
.count
= 0;
580 io
.writeclose
.in
.offset
= 0;
581 io
.writeclose
.in
.mtime
= 0;
582 io
.writeclose
.in
.data
= buf
;
583 status
= smb_raw_write(cli
->tree
, &io
);
584 CHECK_STATUS(status
, NT_STATUS_OK
);
585 CHECK_VALUE(io
.writeclose
.out
.nwritten
, io
.writeclose
.in
.count
);
587 status
= smb_raw_write(cli
->tree
, &io
);
588 CHECK_STATUS(status
, NT_STATUS_OK
);
589 CHECK_VALUE(io
.writeclose
.out
.nwritten
, io
.writeclose
.in
.count
);
591 setup_buffer(buf
, seed
, maxsize
);
593 torture_comment(tctx
, "Trying small write\n");
594 io
.writeclose
.in
.count
= 9;
595 io
.writeclose
.in
.offset
= 4;
596 io
.writeclose
.in
.data
= buf
;
597 status
= smb_raw_write(cli
->tree
, &io
);
598 CHECK_STATUS(status
, NT_STATUS_OK
);
600 status
= smb_raw_write(cli
->tree
, &io
);
601 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
603 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
604 io
.writeclose
.in
.file
.fnum
= fnum
;
606 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
608 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
610 CHECK_BUFFER(buf
+4, seed
, 9);
611 CHECK_VALUE(IVAL(buf
,0), 0);
613 setup_buffer(buf
, seed
, maxsize
);
614 status
= smb_raw_write(cli
->tree
, &io
);
615 CHECK_STATUS(status
, NT_STATUS_OK
);
616 CHECK_VALUE(io
.writeclose
.out
.nwritten
, io
.writeclose
.in
.count
);
618 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
619 io
.writeclose
.in
.file
.fnum
= fnum
;
621 memset(buf
, 0, maxsize
);
622 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
624 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
626 CHECK_BUFFER(buf
+4, seed
, 9);
627 CHECK_VALUE(IVAL(buf
,0), 0);
629 setup_buffer(buf
, seed
, maxsize
);
631 torture_comment(tctx
, "Trying large write\n");
632 io
.writeclose
.in
.count
= 4000;
633 io
.writeclose
.in
.offset
= 0;
634 io
.writeclose
.in
.data
= buf
;
635 status
= smb_raw_write(cli
->tree
, &io
);
636 CHECK_STATUS(status
, NT_STATUS_OK
);
637 CHECK_VALUE(io
.writeclose
.out
.nwritten
, 4000);
639 status
= smb_raw_write(cli
->tree
, &io
);
640 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
642 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
643 io
.writeclose
.in
.file
.fnum
= fnum
;
645 memset(buf
, 0, maxsize
);
646 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
648 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
650 CHECK_BUFFER(buf
, seed
, 4000);
652 torture_comment(tctx
, "Trying bad fnum\n");
653 io
.writeclose
.in
.file
.fnum
= fnum
+1;
654 io
.writeclose
.in
.count
= 4000;
655 io
.writeclose
.in
.offset
= 0;
656 io
.writeclose
.in
.data
= buf
;
657 status
= smb_raw_write(cli
->tree
, &io
);
658 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
660 torture_comment(tctx
, "Setting file as sparse\n");
661 status
= torture_set_sparse(cli
->tree
, fnum
);
662 CHECK_STATUS(status
, NT_STATUS_OK
);
664 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
665 torture_skip(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
668 torture_comment(tctx
, "Trying 2^32 offset\n");
669 setup_buffer(buf
, seed
, maxsize
);
670 io
.writeclose
.in
.file
.fnum
= fnum
;
671 io
.writeclose
.in
.count
= 4000;
672 io
.writeclose
.in
.offset
= 0xFFFFFFFF - 2000;
673 io
.writeclose
.in
.data
= buf
;
674 status
= smb_raw_write(cli
->tree
, &io
);
675 CHECK_STATUS(status
, NT_STATUS_OK
);
676 CHECK_VALUE(io
.writeclose
.out
.nwritten
, 4000);
677 CHECK_ALL_INFO(io
.writeclose
.in
.count
+ (uint64_t)io
.writeclose
.in
.offset
, size
);
679 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
680 io
.writeclose
.in
.file
.fnum
= fnum
;
682 memset(buf
, 0, maxsize
);
683 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writeclose
.in
.offset
, 4000) != 4000) {
685 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
687 CHECK_BUFFER(buf
, seed
, 4000);
690 smbcli_close(cli
->tree
, fnum
);
691 smb_raw_exit(cli
->session
);
692 smbcli_deltree(cli
->tree
, BASEDIR
);
697 basic testing of write calls
699 struct torture_suite
*torture_raw_write(TALLOC_CTX
*mem_ctx
)
701 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "write");
703 torture_suite_add_1smb_test(suite
, "write", test_write
);
704 torture_suite_add_1smb_test(suite
, "write unlock", test_writeunlock
);
705 torture_suite_add_1smb_test(suite
, "write close", test_writeclose
);
706 torture_suite_add_1smb_test(suite
, "writex", test_writex
);