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("(%s) Incorrect status %s - should be %s\n", \
26 __location__, nt_errstr(status), nt_errstr(correct)); \
31 #define CHECK_VALUE(v, correct) do { \
32 if ((v) != (correct)) { \
33 printf("(%s) Incorrect value %s=%d - should be %d\n", \
34 __location__, #v, v, correct); \
39 #define CHECK_BUFFER(buf, seed, len) do { \
40 if (!check_buffer(buf, seed, len, __location__)) { \
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("(%s) wrong value for field %s %.0f - %.0f\n", \
52 __location__, #field, (double)v, (double)finfo.all_info.out.field); \
53 dump_all_info(mem_ctx, &finfo); \
58 #define BASEDIR "\\testwrite"
61 static BOOL setup_dir(struct smbcli_state *cli, const char *dname)
63 smb_raw_exit(cli->session);
64 if (smbcli_deltree(cli->tree, dname) == -1 ||
65 NT_STATUS_IS_ERR(smbcli_mkdir(cli->tree, dname))) {
66 printf("Unable to setup %s - %s\n", dname, smbcli_errstr(cli->tree));
74 setup a random buffer based on a seed
76 static void setup_buffer(char *buf, uint_t seed, int len)
80 for (i=0;i<len;i++) buf[i] = random();
84 check a random buffer based on a seed
86 static BOOL check_buffer(char *buf, uint_t seed, int len, const char *location)
93 printf("Buffer incorrect at %s! ofs=%d buf=0x%x correct=0x%x\n",
94 location, i, buf[i], v);
104 static BOOL test_write(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
111 const int maxsize = 90000;
112 const char *fname = BASEDIR "\\test.txt";
113 uint_t seed = time(NULL);
114 union smb_fileinfo finfo;
116 buf = talloc_zero(mem_ctx, maxsize);
118 if (!setup_dir(cli, BASEDIR)) {
122 printf("Testing RAW_WRITE_WRITE\n");
123 io.generic.level = RAW_WRITE_WRITE;
125 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
127 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
132 printf("Trying zero write\n");
133 io.write.in.fnum = fnum;
134 io.write.in.count = 0;
135 io.write.in.offset = 0;
136 io.write.in.remaining = 0;
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, 0);
142 setup_buffer(buf, seed, maxsize);
144 printf("Trying small write\n");
145 io.write.in.count = 9;
146 io.write.in.offset = 4;
147 io.write.in.data = buf;
148 status = smb_raw_write(cli->tree, &io);
149 CHECK_STATUS(status, NT_STATUS_OK);
150 CHECK_VALUE(io.write.out.nwritten, io.write.in.count);
152 memset(buf, 0, maxsize);
153 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
154 printf("read failed at %s\n", __location__);
158 CHECK_BUFFER(buf+4, seed, 9);
159 CHECK_VALUE(IVAL(buf,0), 0);
161 setup_buffer(buf, seed, maxsize);
163 printf("Trying large write\n");
164 io.write.in.count = 4000;
165 io.write.in.offset = 0;
166 io.write.in.data = buf;
167 status = smb_raw_write(cli->tree, &io);
168 CHECK_STATUS(status, NT_STATUS_OK);
169 CHECK_VALUE(io.write.out.nwritten, 4000);
171 memset(buf, 0, maxsize);
172 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
173 printf("read failed at %s\n", __location__);
177 CHECK_BUFFER(buf, seed, 4000);
179 printf("Trying bad fnum\n");
180 io.write.in.fnum = fnum+1;
181 io.write.in.count = 4000;
182 io.write.in.offset = 0;
183 io.write.in.data = buf;
184 status = smb_raw_write(cli->tree, &io);
185 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
187 printf("Setting file as sparse\n");
188 status = torture_set_sparse(cli->tree, fnum);
189 CHECK_STATUS(status, NT_STATUS_OK);
191 printf("Trying 2^32 offset\n");
192 setup_buffer(buf, seed, maxsize);
193 io.write.in.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 printf("read failed at %s\n", __location__);
208 CHECK_BUFFER(buf, seed, 4000);
211 smbcli_close(cli->tree, fnum);
212 smb_raw_exit(cli->session);
213 smbcli_deltree(cli->tree, BASEDIR);
221 static BOOL test_writex(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
228 const int maxsize = 90000;
229 const char *fname = BASEDIR "\\test.txt";
230 uint_t seed = time(NULL);
231 union smb_fileinfo finfo;
233 buf = talloc_zero(mem_ctx, maxsize);
235 if (!setup_dir(cli, BASEDIR)) {
239 printf("Testing RAW_WRITE_WRITEX\n");
240 io.generic.level = RAW_WRITE_WRITEX;
242 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
244 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
249 printf("Trying zero write\n");
250 io.writex.in.fnum = fnum;
251 io.writex.in.offset = 0;
252 io.writex.in.wmode = 0;
253 io.writex.in.remaining = 0;
254 io.writex.in.count = 0;
255 io.writex.in.data = buf;
256 status = smb_raw_write(cli->tree, &io);
257 CHECK_STATUS(status, NT_STATUS_OK);
258 CHECK_VALUE(io.writex.out.nwritten, 0);
260 setup_buffer(buf, seed, maxsize);
262 printf("Trying small write\n");
263 io.writex.in.count = 9;
264 io.writex.in.offset = 4;
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, io.writex.in.count);
270 memset(buf, 0, maxsize);
271 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
272 printf("read failed at %s\n", __location__);
276 CHECK_BUFFER(buf+4, seed, 9);
277 CHECK_VALUE(IVAL(buf,0), 0);
279 setup_buffer(buf, seed, maxsize);
281 printf("Trying large write\n");
282 io.writex.in.count = 4000;
283 io.writex.in.offset = 0;
284 io.writex.in.data = buf;
285 status = smb_raw_write(cli->tree, &io);
286 CHECK_STATUS(status, NT_STATUS_OK);
287 CHECK_VALUE(io.writex.out.nwritten, 4000);
289 memset(buf, 0, maxsize);
290 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
291 printf("read failed at %s\n", __location__);
295 CHECK_BUFFER(buf, seed, 4000);
297 printf("Trying bad fnum\n");
298 io.writex.in.fnum = fnum+1;
299 io.writex.in.count = 4000;
300 io.writex.in.offset = 0;
301 io.writex.in.data = buf;
302 status = smb_raw_write(cli->tree, &io);
303 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
305 printf("Testing wmode\n");
306 io.writex.in.fnum = fnum;
307 io.writex.in.count = 1;
308 io.writex.in.offset = 0;
309 io.writex.in.wmode = 1;
310 io.writex.in.data = buf;
311 status = smb_raw_write(cli->tree, &io);
312 CHECK_STATUS(status, NT_STATUS_OK);
313 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
315 io.writex.in.wmode = 2;
316 status = smb_raw_write(cli->tree, &io);
317 CHECK_STATUS(status, NT_STATUS_OK);
318 CHECK_VALUE(io.writex.out.nwritten, io.writex.in.count);
321 printf("Trying locked region\n");
323 if (NT_STATUS_IS_ERR(smbcli_lock(cli->tree, fnum, 3, 1, 0, WRITE_LOCK))) {
324 printf("Failed to lock file at %s\n", __location__);
329 io.writex.in.wmode = 0;
330 io.writex.in.count = 4;
331 io.writex.in.offset = 0;
332 status = smb_raw_write(cli->tree, &io);
333 CHECK_STATUS(status, NT_STATUS_FILE_LOCK_CONFLICT);
335 printf("Setting file as sparse\n");
336 status = torture_set_sparse(cli->tree, fnum);
337 CHECK_STATUS(status, NT_STATUS_OK);
339 printf("Trying 2^32 offset\n");
340 setup_buffer(buf, seed, maxsize);
341 io.writex.in.fnum = fnum;
342 io.writex.in.count = 4000;
343 io.writex.in.offset = 0xFFFFFFFF - 2000;
344 io.writex.in.data = buf;
345 status = smb_raw_write(cli->tree, &io);
346 CHECK_STATUS(status, NT_STATUS_OK);
347 CHECK_VALUE(io.writex.out.nwritten, 4000);
348 CHECK_ALL_INFO(io.writex.in.count + (uint64_t)io.writex.in.offset, size);
350 memset(buf, 0, maxsize);
351 if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
352 printf("read failed at %s\n", __location__);
356 CHECK_BUFFER(buf, seed, 4000);
358 for (i=33;i<64;i++) {
359 printf("Trying 2^%d offset\n", i);
360 setup_buffer(buf, seed+1, maxsize);
361 io.writex.in.fnum = fnum;
362 io.writex.in.count = 4000;
363 io.writex.in.offset = ((uint64_t)1) << i;
364 io.writex.in.data = buf;
365 status = smb_raw_write(cli->tree, &io);
367 NT_STATUS_EQUAL(status, NT_STATUS_INVALID_PARAMETER)) {
370 CHECK_STATUS(status, NT_STATUS_OK);
371 CHECK_VALUE(io.writex.out.nwritten, 4000);
372 CHECK_ALL_INFO(io.writex.in.count + (uint64_t)io.writex.in.offset, size);
374 memset(buf, 0, maxsize);
375 if (smbcli_read(cli->tree, fnum, buf, io.writex.in.offset, 4000) != 4000) {
376 printf("read failed at %s\n", __location__);
380 CHECK_BUFFER(buf, seed+1, 4000);
382 printf("limit is 2^%d\n", i);
384 setup_buffer(buf, seed, maxsize);
387 smbcli_close(cli->tree, fnum);
388 smb_raw_exit(cli->session);
389 smbcli_deltree(cli->tree, BASEDIR);
395 test write unlock ops
397 static BOOL test_writeunlock(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
404 const int maxsize = 90000;
405 const char *fname = BASEDIR "\\test.txt";
406 uint_t seed = time(NULL);
407 union smb_fileinfo finfo;
409 buf = talloc_zero(mem_ctx, maxsize);
411 if (!setup_dir(cli, BASEDIR)) {
415 printf("Testing RAW_WRITE_WRITEUNLOCK\n");
416 io.generic.level = RAW_WRITE_WRITEUNLOCK;
418 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
420 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
425 printf("Trying zero write\n");
426 io.writeunlock.in.fnum = fnum;
427 io.writeunlock.in.count = 0;
428 io.writeunlock.in.offset = 0;
429 io.writeunlock.in.remaining = 0;
430 io.writeunlock.in.data = buf;
431 status = smb_raw_write(cli->tree, &io);
432 CHECK_STATUS(status, NT_STATUS_OK);
433 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
435 setup_buffer(buf, seed, maxsize);
437 printf("Trying small write\n");
438 io.writeunlock.in.count = 9;
439 io.writeunlock.in.offset = 4;
440 io.writeunlock.in.data = buf;
441 status = smb_raw_write(cli->tree, &io);
442 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
443 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
444 printf("read failed at %s\n", __location__);
448 CHECK_BUFFER(buf+4, seed, 9);
449 CHECK_VALUE(IVAL(buf,0), 0);
451 setup_buffer(buf, seed, maxsize);
452 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
454 status = smb_raw_write(cli->tree, &io);
455 CHECK_STATUS(status, NT_STATUS_OK);
456 CHECK_VALUE(io.writeunlock.out.nwritten, io.writeunlock.in.count);
458 memset(buf, 0, maxsize);
459 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
460 printf("read failed at %s\n", __location__);
464 CHECK_BUFFER(buf+4, seed, 9);
465 CHECK_VALUE(IVAL(buf,0), 0);
467 setup_buffer(buf, seed, maxsize);
469 printf("Trying large write\n");
470 io.writeunlock.in.count = 4000;
471 io.writeunlock.in.offset = 0;
472 io.writeunlock.in.data = buf;
473 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
475 status = smb_raw_write(cli->tree, &io);
476 CHECK_STATUS(status, NT_STATUS_OK);
477 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
479 status = smb_raw_write(cli->tree, &io);
480 CHECK_STATUS(status, NT_STATUS_RANGE_NOT_LOCKED);
482 memset(buf, 0, maxsize);
483 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
484 printf("read failed at %s\n", __location__);
488 CHECK_BUFFER(buf, seed, 4000);
490 printf("Trying bad fnum\n");
491 io.writeunlock.in.fnum = fnum+1;
492 io.writeunlock.in.count = 4000;
493 io.writeunlock.in.offset = 0;
494 io.writeunlock.in.data = buf;
495 status = smb_raw_write(cli->tree, &io);
496 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
498 printf("Setting file as sparse\n");
499 status = torture_set_sparse(cli->tree, fnum);
500 CHECK_STATUS(status, NT_STATUS_OK);
502 printf("Trying 2^32 offset\n");
503 setup_buffer(buf, seed, maxsize);
504 io.writeunlock.in.fnum = fnum;
505 io.writeunlock.in.count = 4000;
506 io.writeunlock.in.offset = 0xFFFFFFFF - 2000;
507 io.writeunlock.in.data = buf;
508 smbcli_lock(cli->tree, fnum, io.writeunlock.in.offset, io.writeunlock.in.count,
510 status = smb_raw_write(cli->tree, &io);
511 CHECK_STATUS(status, NT_STATUS_OK);
512 CHECK_VALUE(io.writeunlock.out.nwritten, 4000);
513 CHECK_ALL_INFO(io.writeunlock.in.count + (uint64_t)io.writeunlock.in.offset, size);
515 memset(buf, 0, maxsize);
516 if (smbcli_read(cli->tree, fnum, buf, io.writeunlock.in.offset, 4000) != 4000) {
517 printf("read failed at %s\n", __location__);
521 CHECK_BUFFER(buf, seed, 4000);
524 smbcli_close(cli->tree, fnum);
525 smb_raw_exit(cli->session);
526 smbcli_deltree(cli->tree, BASEDIR);
534 static BOOL test_writeclose(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
541 const int maxsize = 90000;
542 const char *fname = BASEDIR "\\test.txt";
543 uint_t seed = time(NULL);
544 union smb_fileinfo finfo;
546 buf = talloc_zero(mem_ctx, maxsize);
548 if (!setup_dir(cli, BASEDIR)) {
552 printf("Testing RAW_WRITE_WRITECLOSE\n");
553 io.generic.level = RAW_WRITE_WRITECLOSE;
555 fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
557 printf("Failed to create %s - %s\n", fname, smbcli_errstr(cli->tree));
562 printf("Trying zero write\n");
563 io.writeclose.in.fnum = fnum;
564 io.writeclose.in.count = 0;
565 io.writeclose.in.offset = 0;
566 io.writeclose.in.mtime = 0;
567 io.writeclose.in.data = buf;
568 status = smb_raw_write(cli->tree, &io);
569 CHECK_STATUS(status, NT_STATUS_OK);
570 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
572 status = smb_raw_write(cli->tree, &io);
573 CHECK_STATUS(status, NT_STATUS_OK);
574 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
576 setup_buffer(buf, seed, maxsize);
578 printf("Trying small write\n");
579 io.writeclose.in.count = 9;
580 io.writeclose.in.offset = 4;
581 io.writeclose.in.data = buf;
582 status = smb_raw_write(cli->tree, &io);
583 CHECK_STATUS(status, NT_STATUS_OK);
585 status = smb_raw_write(cli->tree, &io);
586 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
588 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
589 io.writeclose.in.fnum = fnum;
591 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
592 printf("read failed at %s\n", __location__);
596 CHECK_BUFFER(buf+4, seed, 9);
597 CHECK_VALUE(IVAL(buf,0), 0);
599 setup_buffer(buf, seed, maxsize);
600 status = smb_raw_write(cli->tree, &io);
601 CHECK_STATUS(status, NT_STATUS_OK);
602 CHECK_VALUE(io.writeclose.out.nwritten, io.writeclose.in.count);
604 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
605 io.writeclose.in.fnum = fnum;
607 memset(buf, 0, maxsize);
608 if (smbcli_read(cli->tree, fnum, buf, 0, 13) != 13) {
609 printf("read failed at %s\n", __location__);
613 CHECK_BUFFER(buf+4, seed, 9);
614 CHECK_VALUE(IVAL(buf,0), 0);
616 setup_buffer(buf, seed, maxsize);
618 printf("Trying large write\n");
619 io.writeclose.in.count = 4000;
620 io.writeclose.in.offset = 0;
621 io.writeclose.in.data = buf;
622 status = smb_raw_write(cli->tree, &io);
623 CHECK_STATUS(status, NT_STATUS_OK);
624 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
626 status = smb_raw_write(cli->tree, &io);
627 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
629 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
630 io.writeclose.in.fnum = fnum;
632 memset(buf, 0, maxsize);
633 if (smbcli_read(cli->tree, fnum, buf, 0, 4000) != 4000) {
634 printf("read failed at %s\n", __location__);
638 CHECK_BUFFER(buf, seed, 4000);
640 printf("Trying bad fnum\n");
641 io.writeclose.in.fnum = fnum+1;
642 io.writeclose.in.count = 4000;
643 io.writeclose.in.offset = 0;
644 io.writeclose.in.data = buf;
645 status = smb_raw_write(cli->tree, &io);
646 CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
648 printf("Setting file as sparse\n");
649 status = torture_set_sparse(cli->tree, fnum);
650 CHECK_STATUS(status, NT_STATUS_OK);
652 printf("Trying 2^32 offset\n");
653 setup_buffer(buf, seed, maxsize);
654 io.writeclose.in.fnum = fnum;
655 io.writeclose.in.count = 4000;
656 io.writeclose.in.offset = 0xFFFFFFFF - 2000;
657 io.writeclose.in.data = buf;
658 status = smb_raw_write(cli->tree, &io);
659 CHECK_STATUS(status, NT_STATUS_OK);
660 CHECK_VALUE(io.writeclose.out.nwritten, 4000);
661 CHECK_ALL_INFO(io.writeclose.in.count + (uint64_t)io.writeclose.in.offset, size);
663 fnum = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
664 io.writeclose.in.fnum = fnum;
666 memset(buf, 0, maxsize);
667 if (smbcli_read(cli->tree, fnum, buf, io.writeclose.in.offset, 4000) != 4000) {
668 printf("read failed at %s\n", __location__);
672 CHECK_BUFFER(buf, seed, 4000);
675 smbcli_close(cli->tree, fnum);
676 smb_raw_exit(cli->session);
677 smbcli_deltree(cli->tree, BASEDIR);
681 static BOOL test_delayed_write_update(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
683 union smb_fileinfo finfo1, finfo2;
684 const char *fname = BASEDIR "\\torture_file.txt";
691 printf("Testing delayed update of write time\n");
693 if (!setup_dir(cli, BASEDIR)) {
697 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
699 printf("Failed to open %s\n", fname);
703 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
704 finfo1.basic_info.in.fnum = fnum1;
707 status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo1);
709 if (!NT_STATUS_IS_OK(status)) {
710 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
714 printf("Initial write time %s\n",
715 nt_time_string(mem_ctx, finfo1.basic_info.out.write_time));
717 /* 3 second delay to ensure we get past any 2 second time
718 granularity (older systems may have that) */
721 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
724 printf("write failed - wrote %d bytes (%s)\n", written, __location__);
730 while (time(NULL) < t+120) {
731 status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo2);
733 if (!NT_STATUS_IS_OK(status)) {
734 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
738 printf("write time %s\n",
739 nt_time_string(mem_ctx, finfo2.basic_info.out.write_time));
740 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
741 printf("Server updated write_time after %d seconds\n",
742 (int)(time(NULL) - t));
749 if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
750 printf("Server did not update write time?!\n");
756 smbcli_close(cli->tree, fnum1);
757 smbcli_unlink(cli->tree, fname);
758 smbcli_deltree(cli->tree, BASEDIR);
764 /* Windows does obviously not update the stat info during a write call. I
765 * *think* this is the problem causing a spurious Excel 2003 on XP error
766 * message when saving a file. Excel does a setfileinfo, writes, and then does
767 * a getpath(!)info. Or so... For Samba sometimes it displays an error message
768 * that the file might have been changed in between. What i've been able to
769 * trace down is that this happens if the getpathinfo after the write shows a
770 * different last write time than the setfileinfo showed. This is really
774 static BOOL test_finfo_after_write(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
776 union smb_fileinfo finfo1, finfo2;
777 const char *fname = BASEDIR "\\torture_file.txt";
783 struct smbcli_state *cli2=NULL;
785 printf("Testing finfo update on close\n");
787 if (!setup_dir(cli, BASEDIR)) {
791 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
797 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
798 finfo1.basic_info.in.fnum = fnum1;
800 status = smb_raw_fileinfo(cli->tree, mem_ctx, &finfo1);
802 if (!NT_STATUS_IS_OK(status)) {
803 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
810 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
813 printf("(%s) written gave %d - should have been 1\n",
814 __location__, written);
819 if (!torture_open_connection(&cli2)) {
823 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
825 printf("(%s) failed to open 2nd time - %s\n",
826 __location__, smbcli_errstr(cli2->tree));
831 written = smbcli_write(cli2->tree, fnum2, 0, "x", 0, 1);
834 printf("(%s) written gave %d - should have been 1\n",
835 __location__, written);
840 finfo2.basic_info.level = RAW_FILEINFO_BASIC_INFO;
841 finfo2.basic_info.in.fname = fname;
843 status = smb_raw_pathinfo(cli2->tree, mem_ctx, &finfo2);
845 if (!NT_STATUS_IS_OK(status)) {
846 DEBUG(0, ("(%s) fileinfo failed: %s\n",
847 __location__, nt_errstr(status)));
852 if (finfo1.basic_info.out.create_time !=
853 finfo2.basic_info.out.create_time) {
854 printf("(%s) create_time changed\n", __location__);
859 if (finfo1.basic_info.out.access_time !=
860 finfo2.basic_info.out.access_time) {
861 printf("(%s) access_time changed\n", __location__);
866 if (finfo1.basic_info.out.write_time !=
867 finfo2.basic_info.out.write_time) {
868 printf("(%s) write_time changed\n", __location__);
873 if (finfo1.basic_info.out.change_time !=
874 finfo2.basic_info.out.change_time) {
875 printf("(%s) change_time changed\n", __location__);
880 /* One of the two following calls updates the qpathinfo. */
882 /* If you had skipped the smbcli_write on fnum2, it would
883 * *not* have updated the stat on disk */
885 smbcli_close(cli2->tree, fnum2);
886 torture_close_connection(cli2);
889 /* This call is only for the people looking at ethereal :-) */
890 finfo2.basic_info.level = RAW_FILEINFO_BASIC_INFO;
891 finfo2.basic_info.in.fname = fname;
893 status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo2);
895 if (!NT_STATUS_IS_OK(status)) {
896 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
903 smbcli_close(cli->tree, fnum1);
904 smbcli_unlink(cli->tree, fname);
905 smbcli_deltree(cli->tree, BASEDIR);
907 torture_close_connection(cli2);
914 basic testing of write calls
916 BOOL torture_raw_write(int dummy)
918 struct smbcli_state *cli;
922 if (!torture_open_connection(&cli)) {
926 mem_ctx = talloc_init("torture_raw_write");
928 ret &= test_finfo_after_write(cli, mem_ctx);
929 ret &= test_delayed_write_update(cli, mem_ctx);
930 ret &= test_write(cli, mem_ctx);
931 ret &= test_writeunlock(cli, mem_ctx);
932 ret &= test_writeclose(cli, mem_ctx);
933 ret &= test_writex(cli, mem_ctx);
935 torture_close_connection(cli);
936 talloc_destroy(mem_ctx);