libcli:util: Update HRESULT definitions
[Samba.git] / source4 / torture / raw / write.c
blobe47225af28b7552e56c0da35dcbe445cf8524ca2
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"
28 #include "libcli/raw/raw_proto.h"
30 #define CHECK_STATUS(status, correct) do { \
31 if (!NT_STATUS_EQUAL(status, correct)) { \
32 torture_fail(tctx, talloc_asprintf(tctx, "(%s) Incorrect status %s - should be %s\n", \
33 __location__, nt_errstr(status), nt_errstr(correct))); \
34 ret = false; \
35 goto done; \
36 }} while (0)
38 #define CHECK_VALUE(v, correct) do { \
39 if ((v) != (correct)) { \
40 torture_fail(tctx, talloc_asprintf(tctx, "(%s) Incorrect value %s=%d - should be %d\n", \
41 __location__, #v, v, correct)); \
42 ret = false; \
43 goto done; \
44 }} while (0)
46 #define CHECK_BUFFER(buf, seed, len) do { \
47 if (!check_buffer(tctx, buf, seed, len, __location__)) { \
48 ret = false; \
49 goto done; \
50 }} while (0)
52 #define CHECK_ALL_INFO(v, field) do { \
53 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
54 finfo.all_info.in.file.path = fname; \
55 status = smb_raw_pathinfo(cli->tree, tctx, &finfo); \
56 CHECK_STATUS(status, NT_STATUS_OK); \
57 if ((v) != finfo.all_info.out.field) { \
58 torture_comment(tctx, "(%s) wrong value for field %s %.0f - %.0f\n", \
59 __location__, #field, (double)v, (double)finfo.all_info.out.field); \
60 dump_all_info(tctx, &finfo); \
61 ret = false; \
62 }} while (0)
65 #define BASEDIR "\\testwrite"
69 setup a random buffer based on a seed
71 static void setup_buffer(uint8_t *buf, unsigned int seed, int len)
73 int i;
74 srandom(seed);
75 for (i=0;i<len;i++) buf[i] = random();
79 check a random buffer based on a seed
81 static bool check_buffer(struct torture_context *tctx,
82 uint8_t *buf, unsigned int seed, int len, const char *location)
84 int i;
85 srandom(seed);
86 for (i=0;i<len;i++) {
87 uint8_t v = random();
88 if (buf[i] != v) {
89 torture_fail(tctx, talloc_asprintf(tctx, "Buffer incorrect at %s! ofs=%d buf=0x%x correct=0x%x\n",
90 location, i, buf[i], v));
91 return false;
94 return true;
98 test write ops
100 static bool test_write(struct torture_context *tctx,
101 struct smbcli_state *cli)
103 union smb_write io;
104 NTSTATUS status;
105 bool ret = true;
106 int fnum;
107 uint8_t *buf;
108 const int maxsize = 90000;
109 const char *fname = BASEDIR "\\test.txt";
110 unsigned int seed = time(NULL);
111 union smb_fileinfo finfo;
113 buf = talloc_zero_array(tctx, uint8_t, maxsize);
115 if (!torture_setup_dir(cli, BASEDIR)) {
116 torture_fail(tctx, "failed to setup basedir");
119 torture_comment(tctx, "Testing RAW_WRITE_WRITE\n");
120 io.generic.level = RAW_WRITE_WRITE;
122 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
123 if (fnum == -1) {
124 ret = false;
125 torture_fail_goto(tctx, done,
126 talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
129 torture_comment(tctx, "Trying zero write\n");
130 io.write.in.file.fnum = fnum;
131 io.write.in.count = 0;
132 io.write.in.offset = 0;
133 io.write.in.remaining = 0;
134 io.write.in.data = buf;
135 status = smb_raw_write(cli->tree, &io);
136 CHECK_STATUS(status, NT_STATUS_OK);
137 CHECK_VALUE(io.write.out.nwritten, 0);
139 setup_buffer(buf, seed, maxsize);
141 torture_comment(tctx, "Trying small write\n");
142 io.write.in.count = 9;
143 io.write.in.offset = 4;
144 io.write.in.data = buf;
145 status = smb_raw_write(cli->tree, &io);
146 CHECK_STATUS(status, NT_STATUS_OK);
147 CHECK_VALUE(io.write.out.nwritten, io.write.in.count);
149 memset(buf, 0, maxsize);
150 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
151 ret = false;
152 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
154 CHECK_BUFFER(buf+4, seed, 9);
155 CHECK_VALUE(IVAL(buf,0), 0);
157 setup_buffer(buf, seed, maxsize);
159 torture_comment(tctx, "Trying large write\n");
160 io.write.in.count = 4000;
161 io.write.in.offset = 0;
162 io.write.in.data = buf;
163 status = smb_raw_write(cli->tree, &io);
164 CHECK_STATUS(status, NT_STATUS_OK);
165 CHECK_VALUE(io.write.out.nwritten, 4000);
167 memset(buf, 0, maxsize);
168 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
169 ret = false;
170 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
172 CHECK_BUFFER(buf, seed, 4000);
174 torture_comment(tctx, "Trying bad fnum\n");
175 io.write.in.file.fnum = fnum+1;
176 io.write.in.count = 4000;
177 io.write.in.offset = 0;
178 io.write.in.data = buf;
179 status = smb_raw_write(cli->tree, &io);
180 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
182 torture_comment(tctx, "Setting file as sparse\n");
183 status = torture_set_sparse(cli->tree, fnum);
184 CHECK_STATUS(status, NT_STATUS_OK);
186 if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
187 torture_comment(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
188 goto done;
191 torture_comment(tctx, "Trying 2^32 offset\n");
192 setup_buffer(buf, seed, maxsize);
193 io.write.in.file.fnum = fnum;
194 io.write.in.count = 4000;
195 io.write.in.offset = 0xFFFFFFFF - 2000;
196 io.write.in.data = buf;
197 status = smb_raw_write(cli->tree, &io);
198 CHECK_STATUS(status, NT_STATUS_OK);
199 CHECK_VALUE(io.write.out.nwritten, 4000);
200 CHECK_ALL_INFO(io.write.in.count + (uint64_t)io.write.in.offset, size);
202 memset(buf, 0, maxsize);
203 if (smbcli_read(cli->tree, fnum, buf, io.write.in.offset, 4000) != 4000) {
204 ret = false;
205 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
207 CHECK_BUFFER(buf, seed, 4000);
209 done:
210 smbcli_close(cli->tree, fnum);
211 smb_raw_exit(cli->session);
212 smbcli_deltree(cli->tree, BASEDIR);
213 return ret;
218 test writex ops
220 static bool test_writex(struct torture_context *tctx,
221 struct smbcli_state *cli)
223 union smb_write io;
224 NTSTATUS status;
225 bool ret = true;
226 int fnum, i;
227 uint8_t *buf;
228 const int maxsize = 90000;
229 const char *fname = BASEDIR "\\test.txt";
230 unsigned int seed = time(NULL);
231 union smb_fileinfo finfo;
232 int max_bits=63;
234 if (!torture_setting_bool(tctx, "dangerous", false)) {
235 max_bits=33;
236 torture_comment(tctx, "dangerous not set - limiting range of test to 2^%d\n", max_bits);
239 buf = talloc_zero_array(tctx, uint8_t, maxsize);
241 if (!cli->transport->negotiate.lockread_supported) {
242 torture_comment(tctx, "Server does not support writeunlock - skipping\n");
243 return true;
246 if (!torture_setup_dir(cli, BASEDIR)) {
247 torture_fail(tctx, "failed to setup basedir");
250 torture_comment(tctx, "Testing RAW_WRITE_WRITEX\n");
251 io.generic.level = RAW_WRITE_WRITEX;
253 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
254 if (fnum == -1) {
255 ret = false;
256 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
259 torture_comment(tctx, "Trying zero write\n");
260 io.writex.in.file.fnum = fnum;
261 io.writex.in.offset = 0;
262 io.writex.in.wmode = 0;
263 io.writex.in.remaining = 0;
264 io.writex.in.count = 0;
265 io.writex.in.data = buf;
266 status = smb_raw_write(cli->tree, &io);
267 CHECK_STATUS(status, NT_STATUS_OK);
268 CHECK_VALUE(io.writex.out.nwritten, 0);
270 setup_buffer(buf, seed, maxsize);
272 torture_comment(tctx, "Trying small write\n");
273 io.writex.in.count = 9;
274 io.writex.in.offset = 4;
275 io.writex.in.data = buf;
276 status = smb_raw_write(cli->tree, &io);
277 CHECK_STATUS(status, NT_STATUS_OK);
278 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
280 memset(buf, 0, maxsize);
281 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
282 ret = false;
283 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
285 CHECK_BUFFER(buf+4, seed, 9);
286 CHECK_VALUE(IVAL(buf,0), 0);
288 setup_buffer(buf, seed, maxsize);
290 torture_comment(tctx, "Trying large write\n");
291 io.writex.in.count = 4000;
292 io.writex.in.offset = 0;
293 io.writex.in.data = buf;
294 status = smb_raw_write(cli->tree, &io);
295 CHECK_STATUS(status, NT_STATUS_OK);
296 CHECK_VALUE(io.writex.out.nwritten, 4000);
298 memset(buf, 0, maxsize);
299 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
300 ret = false;
301 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
303 CHECK_BUFFER(buf, seed, 4000);
305 torture_comment(tctx, "Trying bad fnum\n");
306 io.writex.in.file.fnum = fnum+1;
307 io.writex.in.count = 4000;
308 io.writex.in.offset = 0;
309 io.writex.in.data = buf;
310 status = smb_raw_write(cli->tree, &io);
311 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
313 torture_comment(tctx, "Testing wmode\n");
314 io.writex.in.file.fnum = fnum;
315 io.writex.in.count = 1;
316 io.writex.in.offset = 0;
317 io.writex.in.wmode = 1;
318 io.writex.in.data = buf;
319 status = smb_raw_write(cli->tree, &io);
320 CHECK_STATUS(status, NT_STATUS_OK);
321 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
323 io.writex.in.wmode = 2;
324 status = smb_raw_write(cli->tree, &io);
325 CHECK_STATUS(status, NT_STATUS_OK);
326 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
329 torture_comment(tctx, "Trying locked region\n");
330 cli->session->pid++;
331 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 3, 1, 0, WRITE_LOCK))) {
332 ret = false;
333 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to lock file at %s\n", __location__));
335 cli->session->pid--;
336 io.writex.in.wmode = 0;
337 io.writex.in.count = 4;
338 io.writex.in.offset = 0;
339 status = smb_raw_write(cli->tree, &io);
340 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
342 torture_comment(tctx, "Setting file as sparse\n");
343 status = torture_set_sparse(cli->tree, fnum);
344 CHECK_STATUS(status, NT_STATUS_OK);
346 if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
347 torture_skip(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
350 torture_comment(tctx, "Trying 2^32 offset\n");
351 setup_buffer(buf, seed, maxsize);
352 io.writex.in.file.fnum = fnum;
353 io.writex.in.count = 4000;
354 io.writex.in.offset = 0xFFFFFFFF - 2000;
355 io.writex.in.data = buf;
356 status = smb_raw_write(cli->tree, &io);
357 CHECK_STATUS(status, NT_STATUS_OK);
358 CHECK_VALUE(io.writex.out.nwritten, 4000);
359 CHECK_ALL_INFO(io.writex.in.count + (uint64_t)io.writex.in.offset, size);
361 memset(buf, 0, maxsize);
362 if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
363 ret = false;
364 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
366 CHECK_BUFFER(buf, seed, 4000);
368 for (i=33;i<max_bits;i++) {
369 torture_comment(tctx, "Trying 2^%d offset\n", i);
370 setup_buffer(buf, seed+1, maxsize);
371 io.writex.in.file.fnum = fnum;
372 io.writex.in.count = 4000;
373 io.writex.in.offset = ((uint64_t)1) << i;
374 io.writex.in.data = buf;
375 status = smb_raw_write(cli->tree, &io);
376 if (i>33 &&
377 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
378 break;
380 CHECK_STATUS(status, NT_STATUS_OK);
381 CHECK_VALUE(io.writex.out.nwritten, 4000);
382 CHECK_ALL_INFO(io.writex.in.count + (uint64_t)io.writex.in.offset, size);
384 memset(buf, 0, maxsize);
385 if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
386 ret = false;
387 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
389 CHECK_BUFFER(buf, seed+1, 4000);
391 torture_comment(tctx, "limit is 2^%d\n", i);
393 setup_buffer(buf, seed, maxsize);
395 done:
396 smbcli_close(cli->tree, fnum);
397 smb_raw_exit(cli->session);
398 smbcli_deltree(cli->tree, BASEDIR);
399 return ret;
404 test write unlock ops
406 static bool test_writeunlock(struct torture_context *tctx,
407 struct smbcli_state *cli)
409 union smb_write io;
410 NTSTATUS status;
411 bool ret = true;
412 int fnum;
413 uint8_t *buf;
414 const int maxsize = 90000;
415 const char *fname = BASEDIR "\\test.txt";
416 unsigned int seed = time(NULL);
417 union smb_fileinfo finfo;
419 buf = talloc_zero_array(tctx, uint8_t, maxsize);
421 if (!cli->transport->negotiate.lockread_supported) {
422 torture_skip(tctx, "Server does not support writeunlock - skipping\n");
425 if (!torture_setup_dir(cli, BASEDIR)) {
426 torture_fail(tctx, "failed to setup basedir");
429 torture_comment(tctx, "Testing RAW_WRITE_WRITEUNLOCK\n");
430 io.generic.level = RAW_WRITE_WRITEUNLOCK;
432 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
433 if (fnum == -1) {
434 ret = false;
435 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
438 torture_comment(tctx, "Trying zero write\n");
439 io.writeunlock.in.file.fnum = fnum;
440 io.writeunlock.in.count = 0;
441 io.writeunlock.in.offset = 0;
442 io.writeunlock.in.remaining = 0;
443 io.writeunlock.in.data = buf;
444 status = smb_raw_write(cli->tree, &io);
445 CHECK_STATUS(status, NT_STATUS_OK);
446 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
448 setup_buffer(buf, seed, maxsize);
450 torture_comment(tctx, "Trying small write\n");
451 io.writeunlock.in.count = 9;
452 io.writeunlock.in.offset = 4;
453 io.writeunlock.in.data = buf;
454 status = smb_raw_write(cli->tree, &io);
455 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
456 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
457 ret = false;
458 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
460 CHECK_BUFFER(buf+4, seed, 9);
461 CHECK_VALUE(IVAL(buf,0), 0);
463 setup_buffer(buf, seed, maxsize);
464 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
465 0, WRITE_LOCK);
466 status = smb_raw_write(cli->tree, &io);
467 CHECK_STATUS(status, NT_STATUS_OK);
468 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
470 memset(buf, 0, maxsize);
471 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
472 ret = false;
473 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
475 CHECK_BUFFER(buf+4, seed, 9);
476 CHECK_VALUE(IVAL(buf,0), 0);
478 setup_buffer(buf, seed, maxsize);
480 torture_comment(tctx, "Trying large write\n");
481 io.writeunlock.in.count = 4000;
482 io.writeunlock.in.offset = 0;
483 io.writeunlock.in.data = buf;
484 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
485 0, WRITE_LOCK);
486 status = smb_raw_write(cli->tree, &io);
487 CHECK_STATUS(status, NT_STATUS_OK);
488 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
490 status = smb_raw_write(cli->tree, &io);
491 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
493 memset(buf, 0, maxsize);
494 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
495 ret = false;
496 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
498 CHECK_BUFFER(buf, seed, 4000);
500 torture_comment(tctx, "Trying bad fnum\n");
501 io.writeunlock.in.file.fnum = fnum+1;
502 io.writeunlock.in.count = 4000;
503 io.writeunlock.in.offset = 0;
504 io.writeunlock.in.data = buf;
505 status = smb_raw_write(cli->tree, &io);
506 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
508 torture_comment(tctx, "Setting file as sparse\n");
509 status = torture_set_sparse(cli->tree, fnum);
510 CHECK_STATUS(status, NT_STATUS_OK);
512 if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
513 torture_skip(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
516 torture_comment(tctx, "Trying 2^32 offset\n");
517 setup_buffer(buf, seed, maxsize);
518 io.writeunlock.in.file.fnum = fnum;
519 io.writeunlock.in.count = 4000;
520 io.writeunlock.in.offset = 0xFFFFFFFF - 2000;
521 io.writeunlock.in.data = buf;
522 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
523 0, WRITE_LOCK);
524 status = smb_raw_write(cli->tree, &io);
525 CHECK_STATUS(status, NT_STATUS_OK);
526 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
527 CHECK_ALL_INFO(io.writeunlock.in.count + (uint64_t)io.writeunlock.in.offset, size);
529 memset(buf, 0, maxsize);
530 if (smbcli_read(cli->tree, fnum, buf, io.writeunlock.in.offset, 4000) != 4000) {
531 ret = false;
532 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
534 CHECK_BUFFER(buf, seed, 4000);
536 done:
537 smbcli_close(cli->tree, fnum);
538 smb_raw_exit(cli->session);
539 smbcli_deltree(cli->tree, BASEDIR);
540 return ret;
545 test write close ops
547 static bool test_writeclose(struct torture_context *tctx,
548 struct smbcli_state *cli)
550 union smb_write io;
551 NTSTATUS status;
552 bool ret = true;
553 int fnum;
554 uint8_t *buf;
555 const int maxsize = 90000;
556 const char *fname = BASEDIR "\\test.txt";
557 unsigned int seed = time(NULL);
558 union smb_fileinfo finfo;
560 buf = talloc_zero_array(tctx, uint8_t, maxsize);
562 if (!torture_setting_bool(tctx, "writeclose_support", true)) {
563 torture_skip(tctx, "Server does not support writeclose - skipping\n");
566 if (!torture_setup_dir(cli, BASEDIR)) {
567 torture_fail(tctx, "failed to setup basedir");
570 torture_comment(tctx, "Testing RAW_WRITE_WRITECLOSE\n");
571 io.generic.level = RAW_WRITE_WRITECLOSE;
573 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
574 if (fnum == -1) {
575 ret = false;
576 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree)));
579 torture_comment(tctx, "Trying zero write\n");
580 io.writeclose.in.file.fnum = fnum;
581 io.writeclose.in.count = 0;
582 io.writeclose.in.offset = 0;
583 io.writeclose.in.mtime = 0;
584 io.writeclose.in.data = buf;
585 status = smb_raw_write(cli->tree, &io);
586 CHECK_STATUS(status, NT_STATUS_OK);
587 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
589 status = smb_raw_write(cli->tree, &io);
590 CHECK_STATUS(status, NT_STATUS_OK);
591 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
593 setup_buffer(buf, seed, maxsize);
595 torture_comment(tctx, "Trying small write\n");
596 io.writeclose.in.count = 9;
597 io.writeclose.in.offset = 4;
598 io.writeclose.in.data = buf;
599 status = smb_raw_write(cli->tree, &io);
600 CHECK_STATUS(status, NT_STATUS_OK);
602 status = smb_raw_write(cli->tree, &io);
603 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
605 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
606 io.writeclose.in.file.fnum = fnum;
608 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
609 ret = false;
610 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
612 CHECK_BUFFER(buf+4, seed, 9);
613 CHECK_VALUE(IVAL(buf,0), 0);
615 setup_buffer(buf, seed, maxsize);
616 status = smb_raw_write(cli->tree, &io);
617 CHECK_STATUS(status, NT_STATUS_OK);
618 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
620 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
621 io.writeclose.in.file.fnum = fnum;
623 memset(buf, 0, maxsize);
624 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
625 ret = false;
626 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
628 CHECK_BUFFER(buf+4, seed, 9);
629 CHECK_VALUE(IVAL(buf,0), 0);
631 setup_buffer(buf, seed, maxsize);
633 torture_comment(tctx, "Trying large write\n");
634 io.writeclose.in.count = 4000;
635 io.writeclose.in.offset = 0;
636 io.writeclose.in.data = buf;
637 status = smb_raw_write(cli->tree, &io);
638 CHECK_STATUS(status, NT_STATUS_OK);
639 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
641 status = smb_raw_write(cli->tree, &io);
642 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
644 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
645 io.writeclose.in.file.fnum = fnum;
647 memset(buf, 0, maxsize);
648 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
649 ret = false;
650 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
652 CHECK_BUFFER(buf, seed, 4000);
654 torture_comment(tctx, "Trying bad fnum\n");
655 io.writeclose.in.file.fnum = fnum+1;
656 io.writeclose.in.count = 4000;
657 io.writeclose.in.offset = 0;
658 io.writeclose.in.data = buf;
659 status = smb_raw_write(cli->tree, &io);
660 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
662 torture_comment(tctx, "Setting file as sparse\n");
663 status = torture_set_sparse(cli->tree, fnum);
664 CHECK_STATUS(status, NT_STATUS_OK);
666 if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
667 torture_skip(tctx, "skipping large file tests - CAP_LARGE_FILES not set\n");
670 torture_comment(tctx, "Trying 2^32 offset\n");
671 setup_buffer(buf, seed, maxsize);
672 io.writeclose.in.file.fnum = fnum;
673 io.writeclose.in.count = 4000;
674 io.writeclose.in.offset = 0xFFFFFFFF - 2000;
675 io.writeclose.in.data = buf;
676 status = smb_raw_write(cli->tree, &io);
677 CHECK_STATUS(status, NT_STATUS_OK);
678 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
679 CHECK_ALL_INFO(io.writeclose.in.count + (uint64_t)io.writeclose.in.offset, size);
681 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
682 io.writeclose.in.file.fnum = fnum;
684 memset(buf, 0, maxsize);
685 if (smbcli_read(cli->tree, fnum, buf, io.writeclose.in.offset, 4000) != 4000) {
686 ret = false;
687 torture_fail_goto(tctx, done, talloc_asprintf(tctx, "read failed at %s\n", __location__));
689 CHECK_BUFFER(buf, seed, 4000);
691 done:
692 smbcli_close(cli->tree, fnum);
693 smb_raw_exit(cli->session);
694 smbcli_deltree(cli->tree, BASEDIR);
695 return ret;
699 test a deliberately bad SMB1 write.
701 static bool test_bad_write(struct torture_context *tctx,
702 struct smbcli_state *cli)
704 bool ret = false;
705 int fnum = -1;
706 struct smbcli_request *req = NULL;
707 const char *fname = BASEDIR "\\badwrite.txt";
708 bool ok = false;
710 if (!torture_setup_dir(cli, BASEDIR)) {
711 torture_fail(tctx, "failed to setup basedir");
714 torture_comment(tctx, "Testing RAW_BAD_WRITE\n");
716 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
717 if (fnum == -1) {
718 torture_fail_goto(tctx,
719 done,
720 talloc_asprintf(tctx,
721 "Failed to create %s - %s\n",
722 fname,
723 smbcli_errstr(cli->tree)));
726 req = smbcli_request_setup(cli->tree,
727 SMBwrite,
730 if (req == NULL) {
731 torture_fail_goto(tctx,
732 done,
733 talloc_asprintf(tctx, "talloc fail\n"));
736 SSVAL(req->out.vwv, VWV(0), fnum);
737 SSVAL(req->out.vwv, VWV(1), 65535); /* bad write length. */
738 SIVAL(req->out.vwv, VWV(2), 0); /* offset */
739 SSVAL(req->out.vwv, VWV(4), 0); /* remaining. */
741 if (!smbcli_request_send(req)) {
742 torture_fail_goto(tctx,
743 done,
744 talloc_asprintf(tctx, "Send failed\n"));
747 if (!smbcli_request_receive(req)) {
748 torture_fail_goto(tctx,
749 done,
750 talloc_asprintf(tctx, "Receive failed\n"));
754 * Check for expected error codes.
755 * ntvfs returns NT_STATUS_UNSUCCESSFUL.
757 ok = (NT_STATUS_EQUAL(req->status, NT_STATUS_INVALID_PARAMETER) ||
758 NT_STATUS_EQUAL(req->status, NT_STATUS_UNSUCCESSFUL));
760 if (!ok) {
761 torture_fail_goto(tctx,
762 done,
763 talloc_asprintf(tctx,
764 "Should have returned "
765 "NT_STATUS_INVALID_PARAMETER or "
766 "NT_STATUS_UNSUCCESSFUL "
767 "got %s\n",
768 nt_errstr(req->status)));
771 ret = true;
773 done:
774 if (req != NULL) {
775 smbcli_request_destroy(req);
777 if (fnum != -1) {
778 smbcli_close(cli->tree, fnum);
780 smb_raw_exit(cli->session);
781 smbcli_deltree(cli->tree, BASEDIR);
782 return ret;
786 basic testing of write calls
788 struct torture_suite *torture_raw_write(TALLOC_CTX *mem_ctx)
790 struct torture_suite *suite = torture_suite_create(mem_ctx, "write");
792 torture_suite_add_1smb_test(suite, "write", test_write);
793 torture_suite_add_1smb_test(suite, "write unlock", test_writeunlock);
794 torture_suite_add_1smb_test(suite, "write close", test_writeclose);
795 torture_suite_add_1smb_test(suite, "writex", test_writex);
796 torture_suite_add_1smb_test(suite, "bad-write", test_bad_write);
798 return suite;