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 cli_close(cli, fnum);
202 smb_raw_exit(cli->session);
203 cli_deltree(cli, BASEDIR);
211 static BOOL test_writex(struct cli_state *cli, TALLOC_CTX *mem_ctx)
218 const int maxsize = 90000;
219 const char *fname = BASEDIR "\\test.txt";
220 unsigned seed = time(NULL);
221 union smb_fileinfo finfo;
223 buf = talloc_zero(mem_ctx, maxsize);
225 if (cli_deltree(cli, BASEDIR) == -1 ||
226 !cli_mkdir(cli, BASEDIR)) {
227 printf("Unable to setup %s - %s\n", BASEDIR, cli_errstr(cli));
231 printf("Testing RAW_WRITE_WRITEX\n");
232 io.generic.level = RAW_WRITE_WRITEX;
234 fnum = cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE);
236 printf("Failed to create %s - %s\n", fname, cli_errstr(cli));
241 printf("Trying zero write\n");
242 io.writex.in.fnum = fnum;
243 io.writex.in.offset = 0;
244 io.writex.in.wmode = 0;
245 io.writex.in.remaining = 0;
246 io.writex.in.count = 0;
247 io.writex.in.data = buf;
248 status = smb_raw_write(cli->tree, &io);
249 CHECK_STATUS(status, NT_STATUS_OK);
250 CHECK_VALUE(io.writex.out.nwritten, 0);
252 setup_buffer(buf, seed, maxsize);
254 printf("Trying small write\n");
255 io.writex.in.count = 9;
256 io.writex.in.offset = 4;
257 io.writex.in.data = buf;
258 status = smb_raw_write(cli->tree, &io);
259 CHECK_STATUS(status, NT_STATUS_OK);
260 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
262 memset(buf, 0, maxsize);
263 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
264 printf("read failed at %d\n", __LINE__);
268 CHECK_BUFFER(buf+4, seed, 9);
269 CHECK_VALUE(IVAL(buf,0), 0);
271 setup_buffer(buf, seed, maxsize);
273 printf("Trying large write\n");
274 io.writex.in.count = 4000;
275 io.writex.in.offset = 0;
276 io.writex.in.data = buf;
277 status = smb_raw_write(cli->tree, &io);
278 CHECK_STATUS(status, NT_STATUS_OK);
279 CHECK_VALUE(io.writex.out.nwritten, 4000);
281 memset(buf, 0, maxsize);
282 if (cli_read(cli, fnum, buf, 0, 4000) != 4000) {
283 printf("read failed at %d\n", __LINE__);
287 CHECK_BUFFER(buf, seed, 4000);
289 printf("Trying bad fnum\n");
290 io.writex.in.fnum = fnum+1;
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_INVALID_HANDLE);
297 printf("Testing wmode\n");
298 io.writex.in.fnum = fnum;
299 io.writex.in.count = 1;
300 io.writex.in.offset = 0;
301 io.writex.in.wmode = 1;
302 io.writex.in.data = buf;
303 status = smb_raw_write(cli->tree, &io);
304 CHECK_STATUS(status, NT_STATUS_OK);
305 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
307 io.writex.in.wmode = 2;
308 status = smb_raw_write(cli->tree, &io);
309 CHECK_STATUS(status, NT_STATUS_OK);
310 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
313 printf("Trying locked region\n");
315 if (!cli_lock(cli, fnum, 3, 1, 0, WRITE_LOCK)) {
316 printf("Failed to lock file at %d\n", __LINE__);
321 io.writex.in.wmode = 0;
322 io.writex.in.count = 4;
323 io.writex.in.offset = 0;
324 status = smb_raw_write(cli->tree, &io);
325 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
327 printf("Setting file as sparse\n");
328 status = torture_set_sparse(cli->tree, fnum);
329 CHECK_STATUS(status, NT_STATUS_OK);
331 printf("Trying 2^32 offset\n");
332 setup_buffer(buf, seed, maxsize);
333 io.writex.in.fnum = fnum;
334 io.writex.in.count = 4000;
335 io.writex.in.offset = 0xFFFFFFFF - 2000;
336 io.writex.in.data = buf;
337 status = smb_raw_write(cli->tree, &io);
338 CHECK_STATUS(status, NT_STATUS_OK);
339 CHECK_VALUE(io.writex.out.nwritten, 4000);
340 CHECK_ALL_INFO(io.writex.in.count + (SMB_BIG_UINT)io.writex.in.offset, size);
342 memset(buf, 0, maxsize);
343 if (cli_read(cli, fnum, buf, io.writex.in.offset, 4000) != 4000) {
344 printf("read failed at %d\n", __LINE__);
348 CHECK_BUFFER(buf, seed, 4000);
350 for (i=33;i<64;i++) {
351 printf("Trying 2^%d offset\n", i);
352 setup_buffer(buf, seed+1, maxsize);
353 io.writex.in.fnum = fnum;
354 io.writex.in.count = 4000;
355 io.writex.in.offset = ((SMB_BIG_UINT)1) << i;
356 io.writex.in.data = buf;
357 status = smb_raw_write(cli->tree, &io);
358 CHECK_STATUS(status, NT_STATUS_OK);
359 CHECK_VALUE(io.writex.out.nwritten, 4000);
360 CHECK_ALL_INFO(io.writex.in.count + (SMB_BIG_UINT)io.writex.in.offset, size);
362 memset(buf, 0, maxsize);
363 if (cli_read(cli, fnum, buf, io.writex.in.offset, 4000) != 4000) {
364 printf("read failed at %d\n", __LINE__);
368 CHECK_BUFFER(buf, seed+1, 4000);
372 setup_buffer(buf, seed, maxsize);
375 cli_close(cli, fnum);
376 smb_raw_exit(cli->session);
377 cli_deltree(cli, BASEDIR);
383 test write unlock ops
385 static BOOL test_writeunlock(struct cli_state *cli, TALLOC_CTX *mem_ctx)
392 const int maxsize = 90000;
393 const char *fname = BASEDIR "\\test.txt";
394 unsigned seed = time(NULL);
395 union smb_fileinfo finfo;
397 buf = talloc_zero(mem_ctx, maxsize);
399 if (cli_deltree(cli, BASEDIR) == -1 ||
400 !cli_mkdir(cli, BASEDIR)) {
401 printf("Unable to setup %s - %s\n", BASEDIR, cli_errstr(cli));
405 printf("Testing RAW_WRITE_WRITEUNLOCK\n");
406 io.generic.level = RAW_WRITE_WRITEUNLOCK;
408 fnum = cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE);
410 printf("Failed to create %s - %s\n", fname, cli_errstr(cli));
415 printf("Trying zero write\n");
416 io.writeunlock.in.fnum = fnum;
417 io.writeunlock.in.count = 0;
418 io.writeunlock.in.offset = 0;
419 io.writeunlock.in.remaining = 0;
420 io.writeunlock.in.data = buf;
421 status = smb_raw_write(cli->tree, &io);
422 CHECK_STATUS(status, NT_STATUS_OK);
423 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
425 setup_buffer(buf, seed, maxsize);
427 printf("Trying small write\n");
428 io.writeunlock.in.count = 9;
429 io.writeunlock.in.offset = 4;
430 io.writeunlock.in.data = buf;
431 status = smb_raw_write(cli->tree, &io);
432 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
433 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
434 printf("read failed at %d\n", __LINE__);
438 CHECK_BUFFER(buf+4, seed, 9);
439 CHECK_VALUE(IVAL(buf,0), 0);
441 setup_buffer(buf, seed, maxsize);
442 cli_lock(cli, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
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 memset(buf, 0, maxsize);
449 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
450 printf("read failed at %d\n", __LINE__);
454 CHECK_BUFFER(buf+4, seed, 9);
455 CHECK_VALUE(IVAL(buf,0), 0);
457 setup_buffer(buf, seed, maxsize);
459 printf("Trying large write\n");
460 io.writeunlock.in.count = 4000;
461 io.writeunlock.in.offset = 0;
462 io.writeunlock.in.data = buf;
463 cli_lock(cli, 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, 4000);
469 status = smb_raw_write(cli->tree, &io);
470 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
472 memset(buf, 0, maxsize);
473 if (cli_read(cli, fnum, buf, 0, 4000) != 4000) {
474 printf("read failed at %d\n", __LINE__);
478 CHECK_BUFFER(buf, seed, 4000);
480 printf("Trying bad fnum\n");
481 io.writeunlock.in.fnum = fnum+1;
482 io.writeunlock.in.count = 4000;
483 io.writeunlock.in.offset = 0;
484 io.writeunlock.in.data = buf;
485 status = smb_raw_write(cli->tree, &io);
486 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
488 printf("Setting file as sparse\n");
489 status = torture_set_sparse(cli->tree, fnum);
490 CHECK_STATUS(status, NT_STATUS_OK);
492 printf("Trying 2^32 offset\n");
493 setup_buffer(buf, seed, maxsize);
494 io.writeunlock.in.fnum = fnum;
495 io.writeunlock.in.count = 4000;
496 io.writeunlock.in.offset = 0xFFFFFFFF - 2000;
497 io.writeunlock.in.data = buf;
498 cli_lock(cli, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
500 status = smb_raw_write(cli->tree, &io);
501 CHECK_STATUS(status, NT_STATUS_OK);
502 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
503 CHECK_ALL_INFO(io.writeunlock.in.count + (SMB_BIG_UINT)io.writeunlock.in.offset, size);
505 memset(buf, 0, maxsize);
506 if (cli_read(cli, fnum, buf, io.writeunlock.in.offset, 4000) != 4000) {
507 printf("read failed at %d\n", __LINE__);
511 CHECK_BUFFER(buf, seed, 4000);
514 cli_close(cli, fnum);
515 smb_raw_exit(cli->session);
516 cli_deltree(cli, BASEDIR);
524 static BOOL test_writeclose(struct cli_state *cli, TALLOC_CTX *mem_ctx)
531 const int maxsize = 90000;
532 const char *fname = BASEDIR "\\test.txt";
533 unsigned seed = time(NULL);
534 union smb_fileinfo finfo;
536 buf = talloc_zero(mem_ctx, maxsize);
538 if (cli_deltree(cli, BASEDIR) == -1 ||
539 !cli_mkdir(cli, BASEDIR)) {
540 printf("Unable to setup %s - %s\n", BASEDIR, cli_errstr(cli));
544 printf("Testing RAW_WRITE_WRITECLOSE\n");
545 io.generic.level = RAW_WRITE_WRITECLOSE;
547 fnum = cli_open(cli, fname, O_RDWR|O_CREAT, DENY_NONE);
549 printf("Failed to create %s - %s\n", fname, cli_errstr(cli));
554 printf("Trying zero write\n");
555 io.writeclose.in.fnum = fnum;
556 io.writeclose.in.count = 0;
557 io.writeclose.in.offset = 0;
558 io.writeclose.in.mtime = 0;
559 io.writeclose.in.data = buf;
560 status = smb_raw_write(cli->tree, &io);
561 CHECK_STATUS(status, NT_STATUS_OK);
562 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
564 status = smb_raw_write(cli->tree, &io);
565 CHECK_STATUS(status, NT_STATUS_OK);
566 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
568 setup_buffer(buf, seed, maxsize);
570 printf("Trying small write\n");
571 io.writeclose.in.count = 9;
572 io.writeclose.in.offset = 4;
573 io.writeclose.in.data = buf;
574 status = smb_raw_write(cli->tree, &io);
575 CHECK_STATUS(status, NT_STATUS_OK);
577 status = smb_raw_write(cli->tree, &io);
578 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
580 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
581 io.writeclose.in.fnum = fnum;
583 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
584 printf("read failed at %d\n", __LINE__);
588 CHECK_BUFFER(buf+4, seed, 9);
589 CHECK_VALUE(IVAL(buf,0), 0);
591 setup_buffer(buf, seed, maxsize);
592 status = smb_raw_write(cli->tree, &io);
593 CHECK_STATUS(status, NT_STATUS_OK);
594 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
596 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
597 io.writeclose.in.fnum = fnum;
599 memset(buf, 0, maxsize);
600 if (cli_read(cli, fnum, buf, 0, 13) != 13) {
601 printf("read failed at %d\n", __LINE__);
605 CHECK_BUFFER(buf+4, seed, 9);
606 CHECK_VALUE(IVAL(buf,0), 0);
608 setup_buffer(buf, seed, maxsize);
610 printf("Trying large write\n");
611 io.writeclose.in.count = 4000;
612 io.writeclose.in.offset = 0;
613 io.writeclose.in.data = buf;
614 status = smb_raw_write(cli->tree, &io);
615 CHECK_STATUS(status, NT_STATUS_OK);
616 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
618 status = smb_raw_write(cli->tree, &io);
619 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
621 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
622 io.writeclose.in.fnum = fnum;
624 memset(buf, 0, maxsize);
625 if (cli_read(cli, fnum, buf, 0, 4000) != 4000) {
626 printf("read failed at %d\n", __LINE__);
630 CHECK_BUFFER(buf, seed, 4000);
632 printf("Trying bad fnum\n");
633 io.writeclose.in.fnum = fnum+1;
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_INVALID_HANDLE);
640 printf("Setting file as sparse\n");
641 status = torture_set_sparse(cli->tree, fnum);
642 CHECK_STATUS(status, NT_STATUS_OK);
644 printf("Trying 2^32 offset\n");
645 setup_buffer(buf, seed, maxsize);
646 io.writeclose.in.fnum = fnum;
647 io.writeclose.in.count = 4000;
648 io.writeclose.in.offset = 0xFFFFFFFF - 2000;
649 io.writeclose.in.data = buf;
650 status = smb_raw_write(cli->tree, &io);
651 CHECK_STATUS(status, NT_STATUS_OK);
652 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
653 CHECK_ALL_INFO(io.writeclose.in.count + (SMB_BIG_UINT)io.writeclose.in.offset, size);
655 fnum = cli_open(cli, fname, O_RDWR, DENY_NONE);
656 io.writeclose.in.fnum = fnum;
658 memset(buf, 0, maxsize);
659 if (cli_read(cli, fnum, buf, io.writeclose.in.offset, 4000) != 4000) {
660 printf("read failed at %d\n", __LINE__);
664 CHECK_BUFFER(buf, seed, 4000);
667 cli_close(cli, fnum);
668 smb_raw_exit(cli->session);
669 cli_deltree(cli, BASEDIR);
675 basic testing of write calls
677 BOOL torture_raw_write(int dummy)
679 struct cli_state *cli;
683 if (!torture_open_connection(&cli)) {
687 mem_ctx = talloc_init("torture_raw_write");
689 if (!test_write(cli, mem_ctx)) {
693 if (!test_writeunlock(cli, mem_ctx)) {
697 if (!test_writeclose(cli, mem_ctx)) {
701 if (!test_writex(cli, mem_ctx)) {
705 torture_close_connection(cli);
706 talloc_destroy(mem_ctx);