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"
27 #include "torture/raw/proto.h"
29 #define CHECK_STATUS(status, correct) do { \
30 if (!NT_STATUS_EQUAL(status, correct)) { \
31 torture_fail(tctx, talloc_asprintf(tctx, "(%s) Incorrect status %s - should be %s\n", \
32 __location__, nt_errstr(status), nt_errstr(correct))); \
37 #define CHECK_VALUE(v, correct) do { \
38 if ((v) != (correct)) { \
39 torture_fail(tctx, talloc_asprintf(tctx, "(%s) Incorrect value %s=%d - should be %d\n", \
40 __location__, #v, v, correct)); \
45 #define CHECK_BUFFER(buf, seed, len) do { \
46 if (!check_buffer(tctx, buf, seed, len, __location__)) { \
51 #define CHECK_ALL_INFO(v, field) do { \
52 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
53 finfo.all_info.in.file.path = fname; \
54 status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
55 CHECK_STATUS(status, NT_STATUS_OK); \
56 if ((v) != finfo.all_info.out.field) { \
57 torture_comment(tctx, "(%s) wrong value for field %s %.0f - %.0f\n", \
58 __location__, #field, (double)v, (double)finfo.all_info.out.field); \
59 dump_all_info(tctx, &finfo); \
64 #define BASEDIR "\\testwrite"
68 setup a random buffer based on a seed
70 static void setup_buffer(uint8_t *buf
, unsigned int seed
, int len
)
74 for (i
=0;i
<len
;i
++) buf
[i
] = random();
78 check a random buffer based on a seed
80 static bool check_buffer(struct torture_context
*tctx
,
81 uint8_t *buf
, unsigned int seed
, int len
, const char *location
)
88 torture_fail(tctx
, talloc_asprintf(tctx
, "Buffer incorrect at %s! ofs=%d buf=0x%x correct=0x%x\n",
89 location
, i
, buf
[i
], v
));
99 static bool test_write(struct torture_context
*tctx
,
100 struct smbcli_state
*cli
)
107 const int maxsize
= 90000;
108 const char *fname
= BASEDIR
"\\test.txt";
109 unsigned int seed
= time(NULL
);
110 union smb_fileinfo finfo
;
112 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
114 if (!torture_setup_dir(cli
, BASEDIR
)) {
115 torture_fail(tctx
, "failed to setup basedir");
118 torture_comment(tctx
, "Testing RAW_WRITE_WRITE\n");
119 io
.generic
.level
= RAW_WRITE_WRITE
;
121 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
124 torture_fail_goto(tctx
, done
,
125 talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
128 torture_comment(tctx
, "Trying zero write\n");
129 io
.write
.in
.file
.fnum
= fnum
;
130 io
.write
.in
.count
= 0;
131 io
.write
.in
.offset
= 0;
132 io
.write
.in
.remaining
= 0;
133 io
.write
.in
.data
= buf
;
134 status
= smb_raw_write(cli
->tree
, &io
);
135 CHECK_STATUS(status
, NT_STATUS_OK
);
136 CHECK_VALUE(io
.write
.out
.nwritten
, 0);
138 setup_buffer(buf
, seed
, maxsize
);
140 torture_comment(tctx
, "Trying small write\n");
141 io
.write
.in
.count
= 9;
142 io
.write
.in
.offset
= 4;
143 io
.write
.in
.data
= buf
;
144 status
= smb_raw_write(cli
->tree
, &io
);
145 CHECK_STATUS(status
, NT_STATUS_OK
);
146 CHECK_VALUE(io
.write
.out
.nwritten
, io
.write
.in
.count
);
148 memset(buf
, 0, maxsize
);
149 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
151 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
153 CHECK_BUFFER(buf
+4, seed
, 9);
154 CHECK_VALUE(IVAL(buf
,0), 0);
156 setup_buffer(buf
, seed
, maxsize
);
158 torture_comment(tctx
, "Trying large write\n");
159 io
.write
.in
.count
= 4000;
160 io
.write
.in
.offset
= 0;
161 io
.write
.in
.data
= buf
;
162 status
= smb_raw_write(cli
->tree
, &io
);
163 CHECK_STATUS(status
, NT_STATUS_OK
);
164 CHECK_VALUE(io
.write
.out
.nwritten
, 4000);
166 memset(buf
, 0, maxsize
);
167 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
169 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
171 CHECK_BUFFER(buf
, seed
, 4000);
173 torture_comment(tctx
, "Trying bad fnum\n");
174 io
.write
.in
.file
.fnum
= fnum
+1;
175 io
.write
.in
.count
= 4000;
176 io
.write
.in
.offset
= 0;
177 io
.write
.in
.data
= buf
;
178 status
= smb_raw_write(cli
->tree
, &io
);
179 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
181 torture_comment(tctx
, "Setting file as sparse\n");
182 status
= torture_set_sparse(cli
->tree
, fnum
);
183 CHECK_STATUS(status
, NT_STATUS_OK
);
185 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
186 torture_comment(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
190 torture_comment(tctx
, "Trying 2^32 offset\n");
191 setup_buffer(buf
, seed
, maxsize
);
192 io
.write
.in
.file
.fnum
= fnum
;
193 io
.write
.in
.count
= 4000;
194 io
.write
.in
.offset
= 0xFFFFFFFF - 2000;
195 io
.write
.in
.data
= buf
;
196 status
= smb_raw_write(cli
->tree
, &io
);
197 CHECK_STATUS(status
, NT_STATUS_OK
);
198 CHECK_VALUE(io
.write
.out
.nwritten
, 4000);
199 CHECK_ALL_INFO(io
.write
.in
.count
+ (uint64_t)io
.write
.in
.offset
, size
);
201 memset(buf
, 0, maxsize
);
202 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.write
.in
.offset
, 4000) != 4000) {
204 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
206 CHECK_BUFFER(buf
, seed
, 4000);
209 smbcli_close(cli
->tree
, fnum
);
210 smb_raw_exit(cli
->session
);
211 smbcli_deltree(cli
->tree
, BASEDIR
);
219 static bool test_writex(struct torture_context
*tctx
,
220 struct smbcli_state
*cli
)
227 const int maxsize
= 90000;
228 const char *fname
= BASEDIR
"\\test.txt";
229 unsigned int seed
= time(NULL
);
230 union smb_fileinfo finfo
;
233 if (!torture_setting_bool(tctx
, "dangerous", false)) {
235 torture_comment(tctx
, "dangerous not set - limiting range of test to 2^%d\n", max_bits
);
238 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
240 if (!cli
->transport
->negotiate
.lockread_supported
) {
241 torture_comment(tctx
, "Server does not support writeunlock - skipping\n");
245 if (!torture_setup_dir(cli
, BASEDIR
)) {
246 torture_fail(tctx
, "failed to setup basedir");
249 torture_comment(tctx
, "Testing RAW_WRITE_WRITEX\n");
250 io
.generic
.level
= RAW_WRITE_WRITEX
;
252 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
255 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
258 torture_comment(tctx
, "Trying zero write\n");
259 io
.writex
.in
.file
.fnum
= fnum
;
260 io
.writex
.in
.offset
= 0;
261 io
.writex
.in
.wmode
= 0;
262 io
.writex
.in
.remaining
= 0;
263 io
.writex
.in
.count
= 0;
264 io
.writex
.in
.data
= buf
;
265 status
= smb_raw_write(cli
->tree
, &io
);
266 CHECK_STATUS(status
, NT_STATUS_OK
);
267 CHECK_VALUE(io
.writex
.out
.nwritten
, 0);
269 setup_buffer(buf
, seed
, maxsize
);
271 torture_comment(tctx
, "Trying small write\n");
272 io
.writex
.in
.count
= 9;
273 io
.writex
.in
.offset
= 4;
274 io
.writex
.in
.data
= buf
;
275 status
= smb_raw_write(cli
->tree
, &io
);
276 CHECK_STATUS(status
, NT_STATUS_OK
);
277 CHECK_VALUE(io
.writex
.out
.nwritten
, io
.writex
.in
.count
);
279 memset(buf
, 0, maxsize
);
280 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
282 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
284 CHECK_BUFFER(buf
+4, seed
, 9);
285 CHECK_VALUE(IVAL(buf
,0), 0);
287 setup_buffer(buf
, seed
, maxsize
);
289 torture_comment(tctx
, "Trying large write\n");
290 io
.writex
.in
.count
= 4000;
291 io
.writex
.in
.offset
= 0;
292 io
.writex
.in
.data
= buf
;
293 status
= smb_raw_write(cli
->tree
, &io
);
294 CHECK_STATUS(status
, NT_STATUS_OK
);
295 CHECK_VALUE(io
.writex
.out
.nwritten
, 4000);
297 memset(buf
, 0, maxsize
);
298 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
300 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
302 CHECK_BUFFER(buf
, seed
, 4000);
304 torture_comment(tctx
, "Trying bad fnum\n");
305 io
.writex
.in
.file
.fnum
= fnum
+1;
306 io
.writex
.in
.count
= 4000;
307 io
.writex
.in
.offset
= 0;
308 io
.writex
.in
.data
= buf
;
309 status
= smb_raw_write(cli
->tree
, &io
);
310 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
312 torture_comment(tctx
, "Testing wmode\n");
313 io
.writex
.in
.file
.fnum
= fnum
;
314 io
.writex
.in
.count
= 1;
315 io
.writex
.in
.offset
= 0;
316 io
.writex
.in
.wmode
= 1;
317 io
.writex
.in
.data
= buf
;
318 status
= smb_raw_write(cli
->tree
, &io
);
319 CHECK_STATUS(status
, NT_STATUS_OK
);
320 CHECK_VALUE(io
.writex
.out
.nwritten
, io
.writex
.in
.count
);
322 io
.writex
.in
.wmode
= 2;
323 status
= smb_raw_write(cli
->tree
, &io
);
324 CHECK_STATUS(status
, NT_STATUS_OK
);
325 CHECK_VALUE(io
.writex
.out
.nwritten
, io
.writex
.in
.count
);
328 torture_comment(tctx
, "Trying locked region\n");
330 if (NT_STATUS_IS_ERR(smbcli_lock(cli
->tree
, fnum
, 3, 1, 0, WRITE_LOCK
))) {
332 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to lock file at %s\n", __location__
));
335 io
.writex
.in
.wmode
= 0;
336 io
.writex
.in
.count
= 4;
337 io
.writex
.in
.offset
= 0;
338 status
= smb_raw_write(cli
->tree
, &io
);
339 CHECK_STATUS(status
, NT_STATUS_FILE_LOCK_CONFLICT
);
341 torture_comment(tctx
, "Setting file as sparse\n");
342 status
= torture_set_sparse(cli
->tree
, fnum
);
343 CHECK_STATUS(status
, NT_STATUS_OK
);
345 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
346 torture_skip(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
349 torture_comment(tctx
, "Trying 2^32 offset\n");
350 setup_buffer(buf
, seed
, maxsize
);
351 io
.writex
.in
.file
.fnum
= fnum
;
352 io
.writex
.in
.count
= 4000;
353 io
.writex
.in
.offset
= 0xFFFFFFFF - 2000;
354 io
.writex
.in
.data
= buf
;
355 status
= smb_raw_write(cli
->tree
, &io
);
356 CHECK_STATUS(status
, NT_STATUS_OK
);
357 CHECK_VALUE(io
.writex
.out
.nwritten
, 4000);
358 CHECK_ALL_INFO(io
.writex
.in
.count
+ (uint64_t)io
.writex
.in
.offset
, size
);
360 memset(buf
, 0, maxsize
);
361 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writex
.in
.offset
, 4000) != 4000) {
363 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
365 CHECK_BUFFER(buf
, seed
, 4000);
367 for (i
=33;i
<max_bits
;i
++) {
368 torture_comment(tctx
, "Trying 2^%d offset\n", i
);
369 setup_buffer(buf
, seed
+1, maxsize
);
370 io
.writex
.in
.file
.fnum
= fnum
;
371 io
.writex
.in
.count
= 4000;
372 io
.writex
.in
.offset
= ((uint64_t)1) << i
;
373 io
.writex
.in
.data
= buf
;
374 status
= smb_raw_write(cli
->tree
, &io
);
376 NT_STATUS_EQUAL(status
, NT_STATUS_INVALID_PARAMETER
)) {
379 CHECK_STATUS(status
, NT_STATUS_OK
);
380 CHECK_VALUE(io
.writex
.out
.nwritten
, 4000);
381 CHECK_ALL_INFO(io
.writex
.in
.count
+ (uint64_t)io
.writex
.in
.offset
, size
);
383 memset(buf
, 0, maxsize
);
384 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writex
.in
.offset
, 4000) != 4000) {
386 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
388 CHECK_BUFFER(buf
, seed
+1, 4000);
390 torture_comment(tctx
, "limit is 2^%d\n", i
);
392 setup_buffer(buf
, seed
, maxsize
);
395 smbcli_close(cli
->tree
, fnum
);
396 smb_raw_exit(cli
->session
);
397 smbcli_deltree(cli
->tree
, BASEDIR
);
403 test write unlock ops
405 static bool test_writeunlock(struct torture_context
*tctx
,
406 struct smbcli_state
*cli
)
413 const int maxsize
= 90000;
414 const char *fname
= BASEDIR
"\\test.txt";
415 unsigned int seed
= time(NULL
);
416 union smb_fileinfo finfo
;
418 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
420 if (!cli
->transport
->negotiate
.lockread_supported
) {
421 torture_skip(tctx
, "Server does not support writeunlock - skipping\n");
424 if (!torture_setup_dir(cli
, BASEDIR
)) {
425 torture_fail(tctx
, "failed to setup basedir");
428 torture_comment(tctx
, "Testing RAW_WRITE_WRITEUNLOCK\n");
429 io
.generic
.level
= RAW_WRITE_WRITEUNLOCK
;
431 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
434 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
437 torture_comment(tctx
, "Trying zero write\n");
438 io
.writeunlock
.in
.file
.fnum
= fnum
;
439 io
.writeunlock
.in
.count
= 0;
440 io
.writeunlock
.in
.offset
= 0;
441 io
.writeunlock
.in
.remaining
= 0;
442 io
.writeunlock
.in
.data
= buf
;
443 status
= smb_raw_write(cli
->tree
, &io
);
444 CHECK_STATUS(status
, NT_STATUS_OK
);
445 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, io
.writeunlock
.in
.count
);
447 setup_buffer(buf
, seed
, maxsize
);
449 torture_comment(tctx
, "Trying small write\n");
450 io
.writeunlock
.in
.count
= 9;
451 io
.writeunlock
.in
.offset
= 4;
452 io
.writeunlock
.in
.data
= buf
;
453 status
= smb_raw_write(cli
->tree
, &io
);
454 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
455 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
457 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
459 CHECK_BUFFER(buf
+4, seed
, 9);
460 CHECK_VALUE(IVAL(buf
,0), 0);
462 setup_buffer(buf
, seed
, maxsize
);
463 smbcli_lock(cli
->tree
, fnum
, io
.writeunlock
.in
.offset
, io
.writeunlock
.in
.count
,
465 status
= smb_raw_write(cli
->tree
, &io
);
466 CHECK_STATUS(status
, NT_STATUS_OK
);
467 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, io
.writeunlock
.in
.count
);
469 memset(buf
, 0, maxsize
);
470 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
472 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
474 CHECK_BUFFER(buf
+4, seed
, 9);
475 CHECK_VALUE(IVAL(buf
,0), 0);
477 setup_buffer(buf
, seed
, maxsize
);
479 torture_comment(tctx
, "Trying large write\n");
480 io
.writeunlock
.in
.count
= 4000;
481 io
.writeunlock
.in
.offset
= 0;
482 io
.writeunlock
.in
.data
= buf
;
483 smbcli_lock(cli
->tree
, fnum
, io
.writeunlock
.in
.offset
, io
.writeunlock
.in
.count
,
485 status
= smb_raw_write(cli
->tree
, &io
);
486 CHECK_STATUS(status
, NT_STATUS_OK
);
487 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, 4000);
489 status
= smb_raw_write(cli
->tree
, &io
);
490 CHECK_STATUS(status
, NT_STATUS_RANGE_NOT_LOCKED
);
492 memset(buf
, 0, maxsize
);
493 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
495 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
497 CHECK_BUFFER(buf
, seed
, 4000);
499 torture_comment(tctx
, "Trying bad fnum\n");
500 io
.writeunlock
.in
.file
.fnum
= fnum
+1;
501 io
.writeunlock
.in
.count
= 4000;
502 io
.writeunlock
.in
.offset
= 0;
503 io
.writeunlock
.in
.data
= buf
;
504 status
= smb_raw_write(cli
->tree
, &io
);
505 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
507 torture_comment(tctx
, "Setting file as sparse\n");
508 status
= torture_set_sparse(cli
->tree
, fnum
);
509 CHECK_STATUS(status
, NT_STATUS_OK
);
511 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
512 torture_skip(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
515 torture_comment(tctx
, "Trying 2^32 offset\n");
516 setup_buffer(buf
, seed
, maxsize
);
517 io
.writeunlock
.in
.file
.fnum
= fnum
;
518 io
.writeunlock
.in
.count
= 4000;
519 io
.writeunlock
.in
.offset
= 0xFFFFFFFF - 2000;
520 io
.writeunlock
.in
.data
= buf
;
521 smbcli_lock(cli
->tree
, fnum
, io
.writeunlock
.in
.offset
, io
.writeunlock
.in
.count
,
523 status
= smb_raw_write(cli
->tree
, &io
);
524 CHECK_STATUS(status
, NT_STATUS_OK
);
525 CHECK_VALUE(io
.writeunlock
.out
.nwritten
, 4000);
526 CHECK_ALL_INFO(io
.writeunlock
.in
.count
+ (uint64_t)io
.writeunlock
.in
.offset
, size
);
528 memset(buf
, 0, maxsize
);
529 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writeunlock
.in
.offset
, 4000) != 4000) {
531 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
533 CHECK_BUFFER(buf
, seed
, 4000);
536 smbcli_close(cli
->tree
, fnum
);
537 smb_raw_exit(cli
->session
);
538 smbcli_deltree(cli
->tree
, BASEDIR
);
546 static bool test_writeclose(struct torture_context
*tctx
,
547 struct smbcli_state
*cli
)
554 const int maxsize
= 90000;
555 const char *fname
= BASEDIR
"\\test.txt";
556 unsigned int seed
= time(NULL
);
557 union smb_fileinfo finfo
;
559 buf
= talloc_zero_array(tctx
, uint8_t, maxsize
);
561 if (!torture_setting_bool(tctx
, "writeclose_support", true)) {
562 torture_skip(tctx
, "Server does not support writeclose - skipping\n");
565 if (!torture_setup_dir(cli
, BASEDIR
)) {
566 torture_fail(tctx
, "failed to setup basedir");
569 torture_comment(tctx
, "Testing RAW_WRITE_WRITECLOSE\n");
570 io
.generic
.level
= RAW_WRITE_WRITECLOSE
;
572 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
|O_CREAT
, DENY_NONE
);
575 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "Failed to create %s - %s\n", fname
, smbcli_errstr(cli
->tree
)));
578 torture_comment(tctx
, "Trying zero write\n");
579 io
.writeclose
.in
.file
.fnum
= fnum
;
580 io
.writeclose
.in
.count
= 0;
581 io
.writeclose
.in
.offset
= 0;
582 io
.writeclose
.in
.mtime
= 0;
583 io
.writeclose
.in
.data
= buf
;
584 status
= smb_raw_write(cli
->tree
, &io
);
585 CHECK_STATUS(status
, NT_STATUS_OK
);
586 CHECK_VALUE(io
.writeclose
.out
.nwritten
, io
.writeclose
.in
.count
);
588 status
= smb_raw_write(cli
->tree
, &io
);
589 CHECK_STATUS(status
, NT_STATUS_OK
);
590 CHECK_VALUE(io
.writeclose
.out
.nwritten
, io
.writeclose
.in
.count
);
592 setup_buffer(buf
, seed
, maxsize
);
594 torture_comment(tctx
, "Trying small write\n");
595 io
.writeclose
.in
.count
= 9;
596 io
.writeclose
.in
.offset
= 4;
597 io
.writeclose
.in
.data
= buf
;
598 status
= smb_raw_write(cli
->tree
, &io
);
599 CHECK_STATUS(status
, NT_STATUS_OK
);
601 status
= smb_raw_write(cli
->tree
, &io
);
602 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
604 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
605 io
.writeclose
.in
.file
.fnum
= fnum
;
607 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
609 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
611 CHECK_BUFFER(buf
+4, seed
, 9);
612 CHECK_VALUE(IVAL(buf
,0), 0);
614 setup_buffer(buf
, seed
, maxsize
);
615 status
= smb_raw_write(cli
->tree
, &io
);
616 CHECK_STATUS(status
, NT_STATUS_OK
);
617 CHECK_VALUE(io
.writeclose
.out
.nwritten
, io
.writeclose
.in
.count
);
619 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
620 io
.writeclose
.in
.file
.fnum
= fnum
;
622 memset(buf
, 0, maxsize
);
623 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 13) != 13) {
625 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
627 CHECK_BUFFER(buf
+4, seed
, 9);
628 CHECK_VALUE(IVAL(buf
,0), 0);
630 setup_buffer(buf
, seed
, maxsize
);
632 torture_comment(tctx
, "Trying large write\n");
633 io
.writeclose
.in
.count
= 4000;
634 io
.writeclose
.in
.offset
= 0;
635 io
.writeclose
.in
.data
= buf
;
636 status
= smb_raw_write(cli
->tree
, &io
);
637 CHECK_STATUS(status
, NT_STATUS_OK
);
638 CHECK_VALUE(io
.writeclose
.out
.nwritten
, 4000);
640 status
= smb_raw_write(cli
->tree
, &io
);
641 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
643 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
644 io
.writeclose
.in
.file
.fnum
= fnum
;
646 memset(buf
, 0, maxsize
);
647 if (smbcli_read(cli
->tree
, fnum
, buf
, 0, 4000) != 4000) {
649 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
651 CHECK_BUFFER(buf
, seed
, 4000);
653 torture_comment(tctx
, "Trying bad fnum\n");
654 io
.writeclose
.in
.file
.fnum
= fnum
+1;
655 io
.writeclose
.in
.count
= 4000;
656 io
.writeclose
.in
.offset
= 0;
657 io
.writeclose
.in
.data
= buf
;
658 status
= smb_raw_write(cli
->tree
, &io
);
659 CHECK_STATUS(status
, NT_STATUS_INVALID_HANDLE
);
661 torture_comment(tctx
, "Setting file as sparse\n");
662 status
= torture_set_sparse(cli
->tree
, fnum
);
663 CHECK_STATUS(status
, NT_STATUS_OK
);
665 if (!(cli
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
666 torture_skip(tctx
, "skipping large file tests - CAP_LARGE_FILES not set\n");
669 torture_comment(tctx
, "Trying 2^32 offset\n");
670 setup_buffer(buf
, seed
, maxsize
);
671 io
.writeclose
.in
.file
.fnum
= fnum
;
672 io
.writeclose
.in
.count
= 4000;
673 io
.writeclose
.in
.offset
= 0xFFFFFFFF - 2000;
674 io
.writeclose
.in
.data
= buf
;
675 status
= smb_raw_write(cli
->tree
, &io
);
676 CHECK_STATUS(status
, NT_STATUS_OK
);
677 CHECK_VALUE(io
.writeclose
.out
.nwritten
, 4000);
678 CHECK_ALL_INFO(io
.writeclose
.in
.count
+ (uint64_t)io
.writeclose
.in
.offset
, size
);
680 fnum
= smbcli_open(cli
->tree
, fname
, O_RDWR
, DENY_NONE
);
681 io
.writeclose
.in
.file
.fnum
= fnum
;
683 memset(buf
, 0, maxsize
);
684 if (smbcli_read(cli
->tree
, fnum
, buf
, io
.writeclose
.in
.offset
, 4000) != 4000) {
686 torture_fail_goto(tctx
, done
, talloc_asprintf(tctx
, "read failed at %s\n", __location__
));
688 CHECK_BUFFER(buf
, seed
, 4000);
691 smbcli_close(cli
->tree
, fnum
);
692 smb_raw_exit(cli
->session
);
693 smbcli_deltree(cli
->tree
, BASEDIR
);
698 basic testing of write calls
700 struct torture_suite
*torture_raw_write(TALLOC_CTX
*mem_ctx
)
702 struct torture_suite
*suite
= torture_suite_create(mem_ctx
, "write");
704 torture_suite_add_1smb_test(suite
, "write", test_write
);
705 torture_suite_add_1smb_test(suite
, "write unlock", test_writeunlock
);
706 torture_suite_add_1smb_test(suite
, "write close", test_writeclose
);
707 torture_suite_add_1smb_test(suite
, "writex", test_writex
);