WHATSNEW: Update changes since rc3.
[Samba.git] / source4 / torture / raw / write.c
blob0a2f50f425b512e4b0f42a1e285e35c65415e715
1 /*
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/>.
21 #include "includes.h"
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))); \
33 ret = false; \
34 goto done; \
35 }} while (0)
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)); \
41 ret = false; \
42 goto done; \
43 }} while (0)
45 #define CHECK_BUFFER(buf, seed, len) do { \
46 if (!check_buffer(tctx, buf, seed, len, __location__)) { \
47 ret = false; \
48 goto done; \
49 }} while (0)
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); \
60 ret = false; \
61 }} while (0)
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)
72 int i;
73 srandom(seed);
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)
83 int i;
84 srandom(seed);
85 for (i=0;i<len;i++) {
86 uint8_t v = random();
87 if (buf[i] != v) {
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));
90 return false;
93 return true;
97 test write ops
99 static bool test_write(struct torture_context *tctx,
100 struct smbcli_state *cli)
102 union smb_write io;
103 NTSTATUS status;
104 bool ret = true;
105 int fnum;
106 uint8_t *buf;
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);
122 if (fnum == -1) {
123 ret = false;
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) {
150 ret = false;
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) {
168 ret = false;
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");
187 goto done;
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) {
203 ret = false;
204 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
206 CHECK_BUFFER(buf, seed, 4000);
208 done:
209 smbcli_close(cli->tree, fnum);
210 smb_raw_exit(cli->session);
211 smbcli_deltree(cli->tree, BASEDIR);
212 return ret;
217 test writex ops
219 static bool test_writex(struct torture_context *tctx,
220 struct smbcli_state *cli)
222 union smb_write io;
223 NTSTATUS status;
224 bool ret = true;
225 int fnum, i;
226 uint8_t *buf;
227 const int maxsize = 90000;
228 const char *fname = BASEDIR "\\test.txt";
229 unsigned int seed = time(NULL);
230 union smb_fileinfo finfo;
231 int max_bits=63;
233 if (!torture_setting_bool(tctx, "dangerous", false)) {
234 max_bits=33;
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");
242 return true;
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);
253 if (fnum == -1) {
254 ret = false;
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) {
281 ret = false;
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) {
299 ret = false;
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");
329 cli->session->pid++;
330 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 3, 1, 0, WRITE_LOCK))) {
331 ret = false;
332 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to lock file at %s\n", __location__));
334 cli->session->pid--;
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) {
362 ret = false;
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);
375 if (i>33 &&
376 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
377 break;
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) {
385 ret = false;
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);
394 done:
395 smbcli_close(cli->tree, fnum);
396 smb_raw_exit(cli->session);
397 smbcli_deltree(cli->tree, BASEDIR);
398 return ret;
403 test write unlock ops
405 static bool test_writeunlock(struct torture_context *tctx,
406 struct smbcli_state *cli)
408 union smb_write io;
409 NTSTATUS status;
410 bool ret = true;
411 int fnum;
412 uint8_t *buf;
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);
432 if (fnum == -1) {
433 ret = false;
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) {
456 ret = false;
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,
464 0, WRITE_LOCK);
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) {
471 ret = false;
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,
484 0, WRITE_LOCK);
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) {
494 ret = false;
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,
522 0, WRITE_LOCK);
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) {
530 ret = false;
531 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
533 CHECK_BUFFER(buf, seed, 4000);
535 done:
536 smbcli_close(cli->tree, fnum);
537 smb_raw_exit(cli->session);
538 smbcli_deltree(cli->tree, BASEDIR);
539 return ret;
544 test write close ops
546 static bool test_writeclose(struct torture_context *tctx,
547 struct smbcli_state *cli)
549 union smb_write io;
550 NTSTATUS status;
551 bool ret = true;
552 int fnum;
553 uint8_t *buf;
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);
573 if (fnum == -1) {
574 ret = false;
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) {
608 ret = false;
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) {
624 ret = false;
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) {
648 ret = false;
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) {
685 ret = false;
686 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
688 CHECK_BUFFER(buf, seed, 4000);
690 done:
691 smbcli_close(cli->tree, fnum);
692 smb_raw_exit(cli->session);
693 smbcli_deltree(cli->tree, BASEDIR);
694 return ret;
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);
709 return suite;