2 Unix SMB/CIFS implementation.
3 test suite for various write operations
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #define CHECK_STATUS(status, correct) do { \
24 if (!NT_STATUS_EQUAL(status, correct)) { \
25 printf("(%d) Incorrect status %s - should be %s\n", \
26 __LINE__, nt_errstr(status), nt_errstr(correct)); \
31 #define CHECK_VALUE(v, correct) do { \
32 if ((v) != (correct)) { \
33 printf("(%d) Incorrect value %s=%d - should be %d\n", \
34 __LINE__, #v, v, correct); \
39 #define CHECK_BUFFER(buf, seed, len) do { \
40 if (!check_buffer(buf, seed, len, __LINE__)) { \
45 #define CHECK_ALL_INFO(v, field) do { \
46 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
47 finfo.all_info.in.fname = fname; \
48 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
49 CHECK_STATUS(status, NT_STATUS_OK); \
50 if ((v) != finfo.all_info.out.field) { \
51 printf("(%d) wrong value for field %s %.0f - %.0f\n", \
52 __LINE__, #field, (double)v, (double)finfo.all_info.out.field); \
53 dump_all_info(mem_ctx, &finfo); \
58 #define BASEDIR "\\testwrite"
62 setup a random buffer based on a seed
64 static void setup_buffer(char *buf, unsigned seed, int len)
68 for (i=0;i<len;i++) buf[i] = random();
72 check a random buffer based on a seed
74 static BOOL check_buffer(char *buf, unsigned seed, int len, int line)
81 printf("Buffer incorrect at line %d! ofs=%d buf=0x%x correct=0x%x\n",
92 static BOOL test_write(struct cli_state *cli, TALLOC_CTX *mem_ctx)
99 const int maxsize = 90000;
100 const char *fname = BASEDIR "\\test.txt";
101 unsigned seed = time(NULL);
102 union smb_fileinfo finfo;
104 buf = talloc_zero(mem_ctx, maxsize);
106 if (cli_deltree(cli, BASEDIR) == -1 ||
107 !cli_mkdir(cli, BASEDIR)) {
108 printf("Unable to setup %s - %s\n", BASEDIR, cli_errstr(cli));
112 printf("Testing RAW_WRITE_WRITE\n");
113 io.generic.level = RAW_WRITE_WRITE;
115 fnum = cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE);
117 printf("Failed to create %s - %s\n", fname, cli_errstr(cli));
122 printf("Trying zero write\n");
123 io.write.in.fnum = fnum;
124 io.write.in.count = 0;
125 io.write.in.offset = 0;
126 io.write.in.remaining = 0;
127 io.write.in.data = buf;
128 status = smb_raw_write(cli->tree, &io);
129 CHECK_STATUS(status, NT_STATUS_OK);
130 CHECK_VALUE(io.write.out.nwritten, 0);
132 setup_buffer(buf, seed, maxsize);
134 printf("Trying small write\n");
135 io.write.in.count = 9;
136 io.write.in.offset = 4;
137 io.write.in.data = buf;
138 status = smb_raw_write(cli->tree, &io);
139 CHECK_STATUS(status, NT_STATUS_OK);
140 CHECK_VALUE(io.write.out.nwritten, io.write.in.count);
142 memset(buf, 0, maxsize);
143 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
144 printf("read failed at %d\n", __LINE__);
148 CHECK_BUFFER(buf+4, seed, 9);
149 CHECK_VALUE(IVAL(buf,0), 0);
151 setup_buffer(buf, seed, maxsize);
153 printf("Trying large write\n");
154 io.write.in.count = 4000;
155 io.write.in.offset = 0;
156 io.write.in.data = buf;
157 status = smb_raw_write(cli->tree, &io);
158 CHECK_STATUS(status, NT_STATUS_OK);
159 CHECK_VALUE(io.write.out.nwritten, 4000);
161 memset(buf, 0, maxsize);
162 if (cli_read(cli, fnum, buf, 0, 4000) != 4000) {
163 printf("read failed at %d\n", __LINE__);
167 CHECK_BUFFER(buf, seed, 4000);
169 printf("Trying bad fnum\n");
170 io.write.in.fnum = fnum+1;
171 io.write.in.count = 4000;
172 io.write.in.offset = 0;
173 io.write.in.data = buf;
174 status = smb_raw_write(cli->tree, &io);
175 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
177 printf("Setting file as sparse\n");
178 status = torture_set_sparse(cli->tree, fnum);
179 CHECK_STATUS(status, NT_STATUS_OK);
181 printf("Trying 2^32 offset\n");
182 setup_buffer(buf, seed, maxsize);
183 io.write.in.fnum = fnum;
184 io.write.in.count = 4000;
185 io.write.in.offset = 0xFFFFFFFF - 2000;
186 io.write.in.data = buf;
187 status = smb_raw_write(cli->tree, &io);
188 CHECK_STATUS(status, NT_STATUS_OK);
189 CHECK_VALUE(io.write.out.nwritten, 4000);
190 CHECK_ALL_INFO(io.write.in.count + (SMB_BIG_UINT)io.write.in.offset, size);
192 memset(buf, 0, maxsize);
193 if (cli_read(cli, fnum, buf, io.write.in.offset, 4000) != 4000) {
194 printf("read failed at %d\n", __LINE__);
198 CHECK_BUFFER(buf, seed, 4000);
201 smb_raw_exit(cli->session);
202 cli_deltree(cli, BASEDIR);
210 static BOOL test_writex(struct cli_state *cli, TALLOC_CTX *mem_ctx)
217 const int maxsize = 90000;
218 const char *fname = BASEDIR "\\test.txt";
219 unsigned seed = time(NULL);
220 union smb_fileinfo finfo;
222 buf = talloc_zero(mem_ctx, maxsize);
224 if (cli_deltree(cli, BASEDIR) == -1 ||
225 !cli_mkdir(cli, BASEDIR)) {
226 printf("Unable to setup %s - %s\n", BASEDIR, cli_errstr(cli));
230 printf("Testing RAW_WRITE_WRITEX\n");
231 io.generic.level = RAW_WRITE_WRITEX;
233 fnum = cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE);
235 printf("Failed to create %s - %s\n", fname, cli_errstr(cli));
240 printf("Trying zero write\n");
241 io.writex.in.fnum = fnum;
242 io.writex.in.offset = 0;
243 io.writex.in.wmode = 0;
244 io.writex.in.remaining = 0;
245 io.writex.in.count = 0;
246 io.writex.in.data = buf;
247 status = smb_raw_write(cli->tree, &io);
248 CHECK_STATUS(status, NT_STATUS_OK);
249 CHECK_VALUE(io.writex.out.nwritten, 0);
251 setup_buffer(buf, seed, maxsize);
253 printf("Trying small write\n");
254 io.writex.in.count = 9;
255 io.writex.in.offset = 4;
256 io.writex.in.data = buf;
257 status = smb_raw_write(cli->tree, &io);
258 CHECK_STATUS(status, NT_STATUS_OK);
259 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
261 memset(buf, 0, maxsize);
262 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
263 printf("read failed at %d\n", __LINE__);
267 CHECK_BUFFER(buf+4, seed, 9);
268 CHECK_VALUE(IVAL(buf,0), 0);
270 setup_buffer(buf, seed, maxsize);
272 printf("Trying large write\n");
273 io.writex.in.count = 4000;
274 io.writex.in.offset = 0;
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, 4000);
280 memset(buf, 0, maxsize);
281 if (cli_read(cli, fnum, buf, 0, 4000) != 4000) {
282 printf("read failed at %d\n", __LINE__);
286 CHECK_BUFFER(buf, seed, 4000);
288 printf("Trying bad fnum\n");
289 io.writex.in.fnum = fnum+1;
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_INVALID_HANDLE);
296 printf("Testing wmode\n");
297 io.writex.in.fnum = fnum;
298 io.writex.in.count = 1;
299 io.writex.in.offset = 0;
300 io.writex.in.wmode = 1;
301 io.writex.in.data = buf;
302 status = smb_raw_write(cli->tree, &io);
303 CHECK_STATUS(status, NT_STATUS_OK);
304 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
306 io.writex.in.wmode = 2;
307 status = smb_raw_write(cli->tree, &io);
308 CHECK_STATUS(status, NT_STATUS_OK);
309 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
312 printf("Trying locked region\n");
314 if (!cli_lock(cli, fnum, 3, 1, 0, WRITE_LOCK)) {
315 printf("Failed to lock file at %d\n", __LINE__);
320 io.writex.in.wmode = 0;
321 io.writex.in.count = 4;
322 io.writex.in.offset = 0;
323 status = smb_raw_write(cli->tree, &io);
324 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
326 printf("Setting file as sparse\n");
327 status = torture_set_sparse(cli->tree, fnum);
328 CHECK_STATUS(status, NT_STATUS_OK);
330 printf("Trying 2^32 offset\n");
331 setup_buffer(buf, seed, maxsize);
332 io.writex.in.fnum = fnum;
333 io.writex.in.count = 4000;
334 io.writex.in.offset = 0xFFFFFFFF - 2000;
335 io.writex.in.data = buf;
336 status = smb_raw_write(cli->tree, &io);
337 CHECK_STATUS(status, NT_STATUS_OK);
338 CHECK_VALUE(io.writex.out.nwritten, 4000);
339 CHECK_ALL_INFO(io.writex.in.count + (SMB_BIG_UINT)io.writex.in.offset, size);
341 memset(buf, 0, maxsize);
342 if (cli_read(cli, fnum, buf, io.writex.in.offset, 4000) != 4000) {
343 printf("read failed at %d\n", __LINE__);
347 CHECK_BUFFER(buf, seed, 4000);
349 printf("Trying 2^43 offset\n");
350 setup_buffer(buf, seed+1, maxsize);
351 io.writex.in.fnum = fnum;
352 io.writex.in.count = 4000;
353 io.writex.in.offset = ((SMB_BIG_UINT)1) << 43;
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 + (SMB_BIG_UINT)io.writex.in.offset, size);
360 memset(buf, 0, maxsize);
361 if (cli_read(cli, fnum, buf, io.writex.in.offset, 4000) != 4000) {
362 printf("read failed at %d\n", __LINE__);
366 CHECK_BUFFER(buf, seed+1, 4000);
369 setup_buffer(buf, seed, maxsize);
372 smb_raw_exit(cli->session);
373 cli_deltree(cli, BASEDIR);
379 test write unlock ops
381 static BOOL test_writeunlock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
388 const int maxsize = 90000;
389 const char *fname = BASEDIR "\\test.txt";
390 unsigned seed = time(NULL);
391 union smb_fileinfo finfo;
393 buf = talloc_zero(mem_ctx, maxsize);
395 if (cli_deltree(cli, BASEDIR) == -1 ||
396 !cli_mkdir(cli, BASEDIR)) {
397 printf("Unable to setup %s - %s\n", BASEDIR, cli_errstr(cli));
401 printf("Testing RAW_WRITE_WRITEUNLOCK\n");
402 io.generic.level = RAW_WRITE_WRITEUNLOCK;
404 fnum = cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE);
406 printf("Failed to create %s - %s\n", fname, cli_errstr(cli));
411 printf("Trying zero write\n");
412 io.writeunlock.in.fnum = fnum;
413 io.writeunlock.in.count = 0;
414 io.writeunlock.in.offset = 0;
415 io.writeunlock.in.remaining = 0;
416 io.writeunlock.in.data = buf;
417 status = smb_raw_write(cli->tree, &io);
418 CHECK_STATUS(status, NT_STATUS_OK);
419 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
421 setup_buffer(buf, seed, maxsize);
423 printf("Trying small write\n");
424 io.writeunlock.in.count = 9;
425 io.writeunlock.in.offset = 4;
426 io.writeunlock.in.data = buf;
427 status = smb_raw_write(cli->tree, &io);
428 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
429 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
430 printf("read failed at %d\n", __LINE__);
434 CHECK_BUFFER(buf+4, seed, 9);
435 CHECK_VALUE(IVAL(buf,0), 0);
437 setup_buffer(buf, seed, maxsize);
438 cli_lock(cli, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
440 status = smb_raw_write(cli->tree, &io);
441 CHECK_STATUS(status, NT_STATUS_OK);
442 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
444 memset(buf, 0, maxsize);
445 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
446 printf("read failed at %d\n", __LINE__);
450 CHECK_BUFFER(buf+4, seed, 9);
451 CHECK_VALUE(IVAL(buf,0), 0);
453 setup_buffer(buf, seed, maxsize);
455 printf("Trying large write\n");
456 io.writeunlock.in.count = 4000;
457 io.writeunlock.in.offset = 0;
458 io.writeunlock.in.data = buf;
459 cli_lock(cli, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
461 status = smb_raw_write(cli->tree, &io);
462 CHECK_STATUS(status, NT_STATUS_OK);
463 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
465 status = smb_raw_write(cli->tree, &io);
466 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
468 memset(buf, 0, maxsize);
469 if (cli_read(cli, fnum, buf, 0, 4000) != 4000) {
470 printf("read failed at %d\n", __LINE__);
474 CHECK_BUFFER(buf, seed, 4000);
476 printf("Trying bad fnum\n");
477 io.writeunlock.in.fnum = fnum+1;
478 io.writeunlock.in.count = 4000;
479 io.writeunlock.in.offset = 0;
480 io.writeunlock.in.data = buf;
481 status = smb_raw_write(cli->tree, &io);
482 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
484 printf("Setting file as sparse\n");
485 status = torture_set_sparse(cli->tree, fnum);
486 CHECK_STATUS(status, NT_STATUS_OK);
488 printf("Trying 2^32 offset\n");
489 setup_buffer(buf, seed, maxsize);
490 io.writeunlock.in.fnum = fnum;
491 io.writeunlock.in.count = 4000;
492 io.writeunlock.in.offset = 0xFFFFFFFF - 2000;
493 io.writeunlock.in.data = buf;
494 cli_lock(cli, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
496 status = smb_raw_write(cli->tree, &io);
497 CHECK_STATUS(status, NT_STATUS_OK);
498 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
499 CHECK_ALL_INFO(io.writeunlock.in.count + (SMB_BIG_UINT)io.writeunlock.in.offset, size);
501 memset(buf, 0, maxsize);
502 if (cli_read(cli, fnum, buf, io.writeunlock.in.offset, 4000) != 4000) {
503 printf("read failed at %d\n", __LINE__);
507 CHECK_BUFFER(buf, seed, 4000);
510 smb_raw_exit(cli->session);
511 cli_deltree(cli, BASEDIR);
519 static BOOL test_writeclose(struct cli_state *cli, TALLOC_CTX *mem_ctx)
526 const int maxsize = 90000;
527 const char *fname = BASEDIR "\\test.txt";
528 unsigned seed = time(NULL);
529 union smb_fileinfo finfo;
531 buf = talloc_zero(mem_ctx, maxsize);
533 if (cli_deltree(cli, BASEDIR) == -1 ||
534 !cli_mkdir(cli, BASEDIR)) {
535 printf("Unable to setup %s - %s\n", BASEDIR, cli_errstr(cli));
539 printf("Testing RAW_WRITE_WRITECLOSE\n");
540 io.generic.level = RAW_WRITE_WRITECLOSE;
542 fnum = cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE);
544 printf("Failed to create %s - %s\n", fname, cli_errstr(cli));
549 printf("Trying zero write\n");
550 io.writeclose.in.fnum = fnum;
551 io.writeclose.in.count = 0;
552 io.writeclose.in.offset = 0;
553 io.writeclose.in.mtime = 0;
554 io.writeclose.in.data = buf;
555 status = smb_raw_write(cli->tree, &io);
556 CHECK_STATUS(status, NT_STATUS_OK);
557 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
559 status = smb_raw_write(cli->tree, &io);
560 CHECK_STATUS(status, NT_STATUS_OK);
561 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
563 setup_buffer(buf, seed, maxsize);
565 printf("Trying small write\n");
566 io.writeclose.in.count = 9;
567 io.writeclose.in.offset = 4;
568 io.writeclose.in.data = buf;
569 status = smb_raw_write(cli->tree, &io);
570 CHECK_STATUS(status, NT_STATUS_OK);
572 status = smb_raw_write(cli->tree, &io);
573 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
575 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
576 io.writeclose.in.fnum = fnum;
578 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
579 printf("read failed at %d\n", __LINE__);
583 CHECK_BUFFER(buf+4, seed, 9);
584 CHECK_VALUE(IVAL(buf,0), 0);
586 setup_buffer(buf, seed, maxsize);
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 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
592 io.writeclose.in.fnum = fnum;
594 memset(buf, 0, maxsize);
595 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
596 printf("read failed at %d\n", __LINE__);
600 CHECK_BUFFER(buf+4, seed, 9);
601 CHECK_VALUE(IVAL(buf,0), 0);
603 setup_buffer(buf, seed, maxsize);
605 printf("Trying large write\n");
606 io.writeclose.in.count = 4000;
607 io.writeclose.in.offset = 0;
608 io.writeclose.in.data = buf;
609 status = smb_raw_write(cli->tree, &io);
610 CHECK_STATUS(status, NT_STATUS_OK);
611 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
613 status = smb_raw_write(cli->tree, &io);
614 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
616 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
617 io.writeclose.in.fnum = fnum;
619 memset(buf, 0, maxsize);
620 if (cli_read(cli, fnum, buf, 0, 4000) != 4000) {
621 printf("read failed at %d\n", __LINE__);
625 CHECK_BUFFER(buf, seed, 4000);
627 printf("Trying bad fnum\n");
628 io.writeclose.in.fnum = fnum+1;
629 io.writeclose.in.count = 4000;
630 io.writeclose.in.offset = 0;
631 io.writeclose.in.data = buf;
632 status = smb_raw_write(cli->tree, &io);
633 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
635 printf("Setting file as sparse\n");
636 status = torture_set_sparse(cli->tree, fnum);
637 CHECK_STATUS(status, NT_STATUS_OK);
639 printf("Trying 2^32 offset\n");
640 setup_buffer(buf, seed, maxsize);
641 io.writeclose.in.fnum = fnum;
642 io.writeclose.in.count = 4000;
643 io.writeclose.in.offset = 0xFFFFFFFF - 2000;
644 io.writeclose.in.data = buf;
645 status = smb_raw_write(cli->tree, &io);
646 CHECK_STATUS(status, NT_STATUS_OK);
647 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
648 CHECK_ALL_INFO(io.writeclose.in.count + (SMB_BIG_UINT)io.writeclose.in.offset, size);
650 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
651 io.writeclose.in.fnum = fnum;
653 memset(buf, 0, maxsize);
654 if (cli_read(cli, fnum, buf, io.writeclose.in.offset, 4000) != 4000) {
655 printf("read failed at %d\n", __LINE__);
659 CHECK_BUFFER(buf, seed, 4000);
662 smb_raw_exit(cli->session);
663 cli_deltree(cli, BASEDIR);
669 basic testing of write calls
671 BOOL torture_raw_write(int dummy)
673 struct cli_state *cli;
677 if (!torture_open_connection(&cli)) {
681 mem_ctx = talloc_init("torture_raw_write");
683 if (!test_write(cli, mem_ctx)) {
687 if (!test_writeunlock(cli, mem_ctx)) {
691 if (!test_writeclose(cli, mem_ctx)) {
695 if (!test_writex(cli, mem_ctx)) {
699 torture_close_connection(cli);
700 talloc_destroy(mem_ctx);