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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "libcli/raw/libcliraw.h"
24 #include "system/time.h"
26 #define CHECK_STATUS(status, correct) do { \
27 if (!NT_STATUS_EQUAL(status, correct)) { \
28 printf("(%s) Incorrect status %s - should be %s\n", \
29 __location__, nt_errstr(status), nt_errstr(correct)); \
34 #define CHECK_VALUE(v, correct) do { \
35 if ((v) != (correct)) { \
36 printf("(%s) Incorrect value %s=%d - should be %d\n", \
37 __location__, #v, v, correct); \
42 #define CHECK_BUFFER(buf, seed, len) do { \
43 if (!check_buffer(buf, seed, len, __location__)) { \
48 #define CHECK_ALL_INFO(v, field) do { \
49 finfo.all_info.level = RAW_FILEINFO_ALL_INFO; \
50 finfo.all_info.in.fname = fname; \
51 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo); \
52 CHECK_STATUS(status, NT_STATUS_OK); \
53 if ((v) != finfo.all_info.out.field) { \
54 printf("(%s) wrong value for field %s %.0f - %.0f\n", \
55 __location__, #field, (double)v, (double)finfo.all_info.out.field); \
56 dump_all_info(mem_ctx, &finfo); \
61 #define BASEDIR "\\testwrite"
65 setup a random buffer based on a seed
67 static void setup_buffer(uint8_t *buf, uint_t seed, int len)
71 for (i=0;i<len;i++) buf[i] = random();
75 check a random buffer based on a seed
77 static BOOL check_buffer(uint8_t *buf, uint_t seed, int len, const char *location)
84 printf("Buffer incorrect at %s! ofs=%d buf=0x%x correct=0x%x\n",
85 location, i, buf[i], v);
95 static BOOL test_write(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
102 const int maxsize = 90000;
103 const char *fname = BASEDIR "\\test.txt";
104 uint_t seed = time(NULL);
105 union smb_fileinfo finfo;
107 buf = talloc_zero(mem_ctx, maxsize);
109 if (!torture_setup_dir(cli, BASEDIR)) {
113 printf("Testing RAW_WRITE_WRITE\n");
114 io.generic.level = RAW_WRITE_WRITE;
116 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
118 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
123 printf("Trying zero write\n");
124 io.write.in.fnum = fnum;
125 io.write.in.count = 0;
126 io.write.in.offset = 0;
127 io.write.in.remaining = 0;
128 io.write.in.data = buf;
129 status = smb_raw_write(cli->tree, &io);
130 CHECK_STATUS(status, NT_STATUS_OK);
131 CHECK_VALUE(io.write.out.nwritten, 0);
133 setup_buffer(buf, seed, maxsize);
135 printf("Trying small write\n");
136 io.write.in.count = 9;
137 io.write.in.offset = 4;
138 io.write.in.data = buf;
139 status = smb_raw_write(cli->tree, &io);
140 CHECK_STATUS(status, NT_STATUS_OK);
141 CHECK_VALUE(io.write.out.nwritten, io.write.in.count);
143 memset(buf, 0, maxsize);
144 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
145 printf("read failed at %s\n", __location__);
149 CHECK_BUFFER(buf+4, seed, 9);
150 CHECK_VALUE(IVAL(buf,0), 0);
152 setup_buffer(buf, seed, maxsize);
154 printf("Trying large write\n");
155 io.write.in.count = 4000;
156 io.write.in.offset = 0;
157 io.write.in.data = buf;
158 status = smb_raw_write(cli->tree, &io);
159 CHECK_STATUS(status, NT_STATUS_OK);
160 CHECK_VALUE(io.write.out.nwritten, 4000);
162 memset(buf, 0, maxsize);
163 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
164 printf("read failed at %s\n", __location__);
168 CHECK_BUFFER(buf, seed, 4000);
170 printf("Trying bad fnum\n");
171 io.write.in.fnum = fnum+1;
172 io.write.in.count = 4000;
173 io.write.in.offset = 0;
174 io.write.in.data = buf;
175 status = smb_raw_write(cli->tree, &io);
176 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
178 printf("Setting file as sparse\n");
179 status = torture_set_sparse(cli->tree, fnum);
180 CHECK_STATUS(status, NT_STATUS_OK);
182 printf("Trying 2^32 offset\n");
183 setup_buffer(buf, seed, maxsize);
184 io.write.in.fnum = fnum;
185 io.write.in.count = 4000;
186 io.write.in.offset = 0xFFFFFFFF - 2000;
187 io.write.in.data = buf;
188 status = smb_raw_write(cli->tree, &io);
189 CHECK_STATUS(status, NT_STATUS_OK);
190 CHECK_VALUE(io.write.out.nwritten, 4000);
191 CHECK_ALL_INFO(io.write.in.count + (uint64_t)io.write.in.offset, size);
193 memset(buf, 0, maxsize);
194 if (smbcli_read(cli->tree, fnum, buf, io.write.in.offset, 4000) != 4000) {
195 printf("read failed at %s\n", __location__);
199 CHECK_BUFFER(buf, seed, 4000);
202 smbcli_close(cli->tree, fnum);
203 smb_raw_exit(cli->session);
204 smbcli_deltree(cli->tree, BASEDIR);
212 static BOOL test_writex(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
219 const int maxsize = 90000;
220 const char *fname = BASEDIR "\\test.txt";
221 uint_t seed = time(NULL);
222 union smb_fileinfo finfo;
224 buf = talloc_zero(mem_ctx, maxsize);
226 if (!torture_setup_dir(cli, BASEDIR)) {
230 printf("Testing RAW_WRITE_WRITEX\n");
231 io.generic.level = RAW_WRITE_WRITEX;
233 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
235 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
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 (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
263 printf("read failed at %s\n", __location__);
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 (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
282 printf("read failed at %s\n", __location__);
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 (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 3, 1, 0, WRITE_LOCK))) {
315 printf("Failed to lock file at %s\n", __location__);
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 + (uint64_t)io.writex.in.offset, size);
341 memset(buf, 0, maxsize);
342 if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
343 printf("read failed at %s\n", __location__);
347 CHECK_BUFFER(buf, seed, 4000);
349 for (i=33;i<64;i++) {
350 printf("Trying 2^%d offset\n", i);
351 setup_buffer(buf, seed+1, maxsize);
352 io.writex.in.fnum = fnum;
353 io.writex.in.count = 4000;
354 io.writex.in.offset = ((uint64_t)1) << i;
355 io.writex.in.data = buf;
356 status = smb_raw_write(cli->tree, &io);
358 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
361 CHECK_STATUS(status, NT_STATUS_OK);
362 CHECK_VALUE(io.writex.out.nwritten, 4000);
363 CHECK_ALL_INFO(io.writex.in.count + (uint64_t)io.writex.in.offset, size);
365 memset(buf, 0, maxsize);
366 if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
367 printf("read failed at %s\n", __location__);
371 CHECK_BUFFER(buf, seed+1, 4000);
373 printf("limit is 2^%d\n", i);
375 setup_buffer(buf, seed, maxsize);
378 smbcli_close(cli->tree, fnum);
379 smb_raw_exit(cli->session);
380 smbcli_deltree(cli->tree, BASEDIR);
386 test write unlock ops
388 static BOOL test_writeunlock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
395 const int maxsize = 90000;
396 const char *fname = BASEDIR "\\test.txt";
397 uint_t seed = time(NULL);
398 union smb_fileinfo finfo;
400 buf = talloc_zero(mem_ctx, maxsize);
402 if (!torture_setup_dir(cli, BASEDIR)) {
406 printf("Testing RAW_WRITE_WRITEUNLOCK\n");
407 io.generic.level = RAW_WRITE_WRITEUNLOCK;
409 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
411 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
416 printf("Trying zero write\n");
417 io.writeunlock.in.fnum = fnum;
418 io.writeunlock.in.count = 0;
419 io.writeunlock.in.offset = 0;
420 io.writeunlock.in.remaining = 0;
421 io.writeunlock.in.data = buf;
422 status = smb_raw_write(cli->tree, &io);
423 CHECK_STATUS(status, NT_STATUS_OK);
424 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
426 setup_buffer(buf, seed, maxsize);
428 printf("Trying small write\n");
429 io.writeunlock.in.count = 9;
430 io.writeunlock.in.offset = 4;
431 io.writeunlock.in.data = buf;
432 status = smb_raw_write(cli->tree, &io);
433 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
434 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
435 printf("read failed at %s\n", __location__);
439 CHECK_BUFFER(buf+4, seed, 9);
440 CHECK_VALUE(IVAL(buf,0), 0);
442 setup_buffer(buf, seed, maxsize);
443 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
445 status = smb_raw_write(cli->tree, &io);
446 CHECK_STATUS(status, NT_STATUS_OK);
447 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
449 memset(buf, 0, maxsize);
450 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
451 printf("read failed at %s\n", __location__);
455 CHECK_BUFFER(buf+4, seed, 9);
456 CHECK_VALUE(IVAL(buf,0), 0);
458 setup_buffer(buf, seed, maxsize);
460 printf("Trying large write\n");
461 io.writeunlock.in.count = 4000;
462 io.writeunlock.in.offset = 0;
463 io.writeunlock.in.data = buf;
464 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
466 status = smb_raw_write(cli->tree, &io);
467 CHECK_STATUS(status, NT_STATUS_OK);
468 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
470 status = smb_raw_write(cli->tree, &io);
471 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
473 memset(buf, 0, maxsize);
474 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
475 printf("read failed at %s\n", __location__);
479 CHECK_BUFFER(buf, seed, 4000);
481 printf("Trying bad fnum\n");
482 io.writeunlock.in.fnum = fnum+1;
483 io.writeunlock.in.count = 4000;
484 io.writeunlock.in.offset = 0;
485 io.writeunlock.in.data = buf;
486 status = smb_raw_write(cli->tree, &io);
487 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
489 printf("Setting file as sparse\n");
490 status = torture_set_sparse(cli->tree, fnum);
491 CHECK_STATUS(status, NT_STATUS_OK);
493 printf("Trying 2^32 offset\n");
494 setup_buffer(buf, seed, maxsize);
495 io.writeunlock.in.fnum = fnum;
496 io.writeunlock.in.count = 4000;
497 io.writeunlock.in.offset = 0xFFFFFFFF - 2000;
498 io.writeunlock.in.data = buf;
499 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
501 status = smb_raw_write(cli->tree, &io);
502 CHECK_STATUS(status, NT_STATUS_OK);
503 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
504 CHECK_ALL_INFO(io.writeunlock.in.count + (uint64_t)io.writeunlock.in.offset, size);
506 memset(buf, 0, maxsize);
507 if (smbcli_read(cli->tree, fnum, buf, io.writeunlock.in.offset, 4000) != 4000) {
508 printf("read failed at %s\n", __location__);
512 CHECK_BUFFER(buf, seed, 4000);
515 smbcli_close(cli->tree, fnum);
516 smb_raw_exit(cli->session);
517 smbcli_deltree(cli->tree, BASEDIR);
525 static BOOL test_writeclose(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
532 const int maxsize = 90000;
533 const char *fname = BASEDIR "\\test.txt";
534 uint_t seed = time(NULL);
535 union smb_fileinfo finfo;
537 buf = talloc_zero(mem_ctx, maxsize);
539 if (!torture_setup_dir(cli, BASEDIR)) {
543 printf("Testing RAW_WRITE_WRITECLOSE\n");
544 io.generic.level = RAW_WRITE_WRITECLOSE;
546 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
548 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
553 printf("Trying zero write\n");
554 io.writeclose.in.fnum = fnum;
555 io.writeclose.in.count = 0;
556 io.writeclose.in.offset = 0;
557 io.writeclose.in.mtime = 0;
558 io.writeclose.in.data = buf;
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 status = smb_raw_write(cli->tree, &io);
564 CHECK_STATUS(status, NT_STATUS_OK);
565 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
567 setup_buffer(buf, seed, maxsize);
569 printf("Trying small write\n");
570 io.writeclose.in.count = 9;
571 io.writeclose.in.offset = 4;
572 io.writeclose.in.data = buf;
573 status = smb_raw_write(cli->tree, &io);
574 CHECK_STATUS(status, NT_STATUS_OK);
576 status = smb_raw_write(cli->tree, &io);
577 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
579 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
580 io.writeclose.in.fnum = fnum;
582 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
583 printf("read failed at %s\n", __location__);
587 CHECK_BUFFER(buf+4, seed, 9);
588 CHECK_VALUE(IVAL(buf,0), 0);
590 setup_buffer(buf, seed, maxsize);
591 status = smb_raw_write(cli->tree, &io);
592 CHECK_STATUS(status, NT_STATUS_OK);
593 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
595 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
596 io.writeclose.in.fnum = fnum;
598 memset(buf, 0, maxsize);
599 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
600 printf("read failed at %s\n", __location__);
604 CHECK_BUFFER(buf+4, seed, 9);
605 CHECK_VALUE(IVAL(buf,0), 0);
607 setup_buffer(buf, seed, maxsize);
609 printf("Trying large write\n");
610 io.writeclose.in.count = 4000;
611 io.writeclose.in.offset = 0;
612 io.writeclose.in.data = buf;
613 status = smb_raw_write(cli->tree, &io);
614 CHECK_STATUS(status, NT_STATUS_OK);
615 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
617 status = smb_raw_write(cli->tree, &io);
618 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
620 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
621 io.writeclose.in.fnum = fnum;
623 memset(buf, 0, maxsize);
624 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
625 printf("read failed at %s\n", __location__);
629 CHECK_BUFFER(buf, seed, 4000);
631 printf("Trying bad fnum\n");
632 io.writeclose.in.fnum = fnum+1;
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_INVALID_HANDLE);
639 printf("Setting file as sparse\n");
640 status = torture_set_sparse(cli->tree, fnum);
641 CHECK_STATUS(status, NT_STATUS_OK);
643 printf("Trying 2^32 offset\n");
644 setup_buffer(buf, seed, maxsize);
645 io.writeclose.in.fnum = fnum;
646 io.writeclose.in.count = 4000;
647 io.writeclose.in.offset = 0xFFFFFFFF - 2000;
648 io.writeclose.in.data = buf;
649 status = smb_raw_write(cli->tree, &io);
650 CHECK_STATUS(status, NT_STATUS_OK);
651 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
652 CHECK_ALL_INFO(io.writeclose.in.count + (uint64_t)io.writeclose.in.offset, size);
654 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
655 io.writeclose.in.fnum = fnum;
657 memset(buf, 0, maxsize);
658 if (smbcli_read(cli->tree, fnum, buf, io.writeclose.in.offset, 4000) != 4000) {
659 printf("read failed at %s\n", __location__);
663 CHECK_BUFFER(buf, seed, 4000);
666 smbcli_close(cli->tree, fnum);
667 smb_raw_exit(cli->session);
668 smbcli_deltree(cli->tree, BASEDIR);
673 basic testing of write calls
675 BOOL torture_raw_write(void)
677 struct smbcli_state *cli;
681 if (!torture_open_connection(&cli)) {
685 mem_ctx = talloc_init("torture_raw_write");
687 ret &= test_write(cli, mem_ctx);
688 ret &= test_writeunlock(cli, mem_ctx);
689 ret &= test_writeclose(cli, mem_ctx);
690 ret &= test_writex(cli, mem_ctx);
692 torture_close_connection(cli);
693 talloc_destroy(mem_ctx);