2 Unix SMB/CIFS implementation.
4 test suite for delayed write update
6 Copyright (C) Volker Lendecke 2004
7 Copyright (C) Andrew Tridgell 2004
8 Copyright (C) Jeremy Allison 2004
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 #include "torture/torture.h"
26 #include "libcli/raw/libcliraw.h"
27 #include "libcli/raw/raw_proto.h"
28 #include "system/time.h"
29 #include "system/filesys.h"
30 #include "libcli/libcli.h"
31 #include "torture/util.h"
33 #define W2K8R2_TIMEDELAY_SECS 1
34 #define W2K3_TIMEDELAY_SECS 2
35 #define TIMEDELAY_SECS W2K3_TIMEDELAY_SECS
37 #define BASEDIR "\\delaywrite"
39 static bool test_delayed_write_update(struct torture_context *tctx, struct smbcli_state *cli)
41 union smb_fileinfo finfo1, finfo2;
42 const char *fname = BASEDIR "\\torture_file.txt";
49 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
50 int normal_delay = 2000000;
51 double sec = ((double)used_delay) / ((double)normal_delay);
52 int msec = 1000 * sec;
54 torture_comment(tctx, "\nRunning test_delayed_write_update\n");
56 if (!torture_setup_dir(cli, BASEDIR)) {
60 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
62 torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
66 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
67 finfo1.basic_info.in.file.fnum = fnum1;
70 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
72 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
74 torture_comment(tctx, "Initial write time %s\n",
75 nt_time_string(tctx, finfo1.basic_info.out.write_time));
77 /* 3 second delay to ensure we get past any 2 second time
78 granularity (older systems may have that) */
81 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
84 torture_result(tctx, TORTURE_FAIL,
85 "write failed - wrote %d bytes (%s)\n",
86 (int)written, __location__);
90 start = timeval_current();
91 end = timeval_add(&start, (120*sec), 0);
92 while (!timeval_expired(&end)) {
93 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
95 if (!NT_STATUS_IS_OK(status)) {
96 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
100 torture_comment(tctx, "write time %s\n",
101 nt_time_string(tctx, finfo2.basic_info.out.write_time));
102 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
103 double diff = timeval_elapsed(&start);
104 if (diff < (TIMEDELAY_SECS * sec * 0.75)) { /* 0.75 to cope with vmware timing */
105 torture_comment(tctx, "Server updated write_time after %.2f seconds"
106 "(1 sec == %.2f)(wrong!)\n",
112 torture_comment(tctx, "Server updated write_time after %.2f seconds"
113 "(1 sec == %.2f)(correct)\n",
121 if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
122 torture_result(tctx, TORTURE_FAIL,
123 "Server did not update write time (wrong!)");
129 smbcli_close(cli->tree, fnum1);
130 smbcli_unlink(cli->tree, fname);
131 smbcli_deltree(cli->tree, BASEDIR);
136 static bool test_delayed_write_update1(struct torture_context *tctx, struct smbcli_state *cli)
138 union smb_fileinfo finfo1, finfo2, finfo3, pinfo4;
139 const char *fname = BASEDIR "\\torture_file1.txt";
144 struct timeval start;
146 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
147 int normal_delay = 2000000;
148 double sec = ((double)used_delay) / ((double)normal_delay);
149 int msec = 1000 * sec;
152 torture_comment(tctx, "\nRunning test_delayed_write_update1\n");
154 if (!torture_setup_dir(cli, BASEDIR)) {
158 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
160 torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
164 memset(buf, 'x', 2048);
165 written = smbcli_write(cli->tree, fnum1, 0, buf, 0, 2048);
167 /* 3 second delay to ensure we get past any 2 second time
168 granularity (older systems may have that) */
171 finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
172 finfo1.all_info.in.file.fnum = fnum1;
175 pinfo4.all_info.level = RAW_FILEINFO_ALL_INFO;
176 pinfo4.all_info.in.file.path = fname;
178 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
180 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
182 torture_comment(tctx, "Initial write time %s\n",
183 nt_time_string(tctx, finfo1.all_info.out.write_time));
185 /* Do a zero length SMBwrite call to truncate. */
186 written = smbcli_smbwrite(cli->tree, fnum1, "x", 1024, 0);
189 torture_result(tctx, TORTURE_FAIL,
190 "write failed - wrote %d bytes (%s)\n",
191 (int)written, __location__);
195 start = timeval_current();
196 end = timeval_add(&start, (120*sec), 0);
197 while (!timeval_expired(&end)) {
198 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
200 if (!NT_STATUS_IS_OK(status)) {
201 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
206 if (finfo2.all_info.out.size != 1024) {
207 torture_result(tctx, TORTURE_FAIL,
208 "file not truncated, size = %u (should be 1024)",
209 (unsigned int)finfo2.all_info.out.size);
214 torture_comment(tctx, "write time %s\n",
215 nt_time_string(tctx, finfo2.all_info.out.write_time));
216 if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
217 double diff = timeval_elapsed(&start);
218 if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
219 torture_comment(tctx, "After SMBwrite truncate "
220 "server updated write_time after %.2f seconds"
221 "(1 sec == %.2f)(wrong!)\n",
227 torture_comment(tctx, "After SMBwrite truncate "
228 "server updated write_time after %.2f seconds"
229 "(1 sec == %.2f)(correct)\n",
237 if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
238 torture_result(tctx, TORTURE_FAIL,
239 "Server did not update write time (wrong!)");
246 /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
247 written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
250 torture_result(tctx, TORTURE_FAIL,
251 "write failed - wrote %d bytes (%s)",
252 (int)written, __location__);
256 start = timeval_current();
257 end = timeval_add(&start, (10*sec), 0);
258 while (!timeval_expired(&end)) {
259 status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
261 if (!NT_STATUS_IS_OK(status)) {
262 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
267 if (finfo3.all_info.out.size != 1024) {
268 DEBUG(0, ("file not truncated, size = %u (should be 1024)\n",
269 (unsigned int)finfo3.all_info.out.size));
274 torture_comment(tctx, "write time %s\n",
275 nt_time_string(tctx, finfo3.all_info.out.write_time));
276 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
277 double diff = timeval_elapsed(&start);
279 torture_comment(tctx, "server updated write_time after %.2f seconds"
280 "(1 sec == %.2f)(correct)\n",
288 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
289 torture_result(tctx, TORTURE_FAIL,
290 "Server updated write time (wrong!)");
294 /* the close should trigger an write time update */
295 smbcli_close(cli->tree, fnum1);
298 status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
299 torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
301 if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
302 torture_result(tctx, TORTURE_FAIL,
303 "Server did not update write time on close (wrong!)");
305 } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
306 torture_comment(tctx, "Server updated write time on close (correct)\n");
310 smbcli_close(cli->tree, fnum1);
311 smbcli_unlink(cli->tree, fname);
312 smbcli_deltree(cli->tree, BASEDIR);
317 /* Updating with a SMBwrite of zero length
318 * changes the write time immediately - even on expand. */
320 static bool test_delayed_write_update1a(struct torture_context *tctx, struct smbcli_state *cli)
322 union smb_fileinfo finfo1, finfo2, finfo3, pinfo4;
323 const char *fname = BASEDIR "\\torture_file1a.txt";
328 struct timeval start;
330 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
331 int normal_delay = 2000000;
332 double sec = ((double)used_delay) / ((double)normal_delay);
333 int msec = 1000 * sec;
336 torture_comment(tctx, "\nRunning test_delayed_write_update1a\n");
338 if (!torture_setup_dir(cli, BASEDIR)) {
342 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
344 torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
348 memset(buf, 'x', 2048);
349 written = smbcli_write(cli->tree, fnum1, 0, buf, 0, 2048);
351 /* 3 second delay to ensure we get past any 2 second time
352 granularity (older systems may have that) */
355 finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
356 finfo1.all_info.in.file.fnum = fnum1;
359 pinfo4.all_info.level = RAW_FILEINFO_ALL_INFO;
360 pinfo4.all_info.in.file.path = fname;
362 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
364 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
366 torture_comment(tctx, "Initial write time %s\n",
367 nt_time_string(tctx, finfo1.all_info.out.write_time));
369 /* Do a zero length SMBwrite call to truncate. */
370 written = smbcli_smbwrite(cli->tree, fnum1, "x", 10240, 0);
373 torture_result(tctx, TORTURE_FAIL, "write failed - wrote %d bytes (%s)",
374 (int)written, __location__);
378 start = timeval_current();
379 end = timeval_add(&start, (120*sec), 0);
380 while (!timeval_expired(&end)) {
381 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
383 if (!NT_STATUS_IS_OK(status)) {
384 torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s",
390 if (finfo2.all_info.out.size != 10240) {
391 torture_result(tctx, TORTURE_FAIL,
392 "file not truncated, size = %u (should be 10240)",
393 (unsigned int)finfo2.all_info.out.size);
398 torture_comment(tctx, "write time %s\n",
399 nt_time_string(tctx, finfo2.all_info.out.write_time));
400 if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
401 double diff = timeval_elapsed(&start);
402 if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
403 torture_comment(tctx, "After SMBwrite truncate "
404 "server updated write_time after %.2f seconds"
405 "(1 sec == %.2f)(wrong!)\n",
411 torture_comment(tctx, "After SMBwrite truncate "
412 "server updated write_time after %.2f seconds"
413 "(1 sec == %.2f)(correct)\n",
421 if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
422 torture_result(tctx, TORTURE_FAIL,
423 "Server did not update write time (wrong!)");
430 /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
431 written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
433 torture_assert_int_equal(tctx, written, 1,
434 "unexpected number of bytes written");
436 start = timeval_current();
437 end = timeval_add(&start, (10*sec), 0);
438 while (!timeval_expired(&end)) {
439 status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
441 if (!NT_STATUS_IS_OK(status)) {
442 torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s\n",
448 if (finfo3.all_info.out.size != 10240) {
449 torture_result(tctx, TORTURE_FAIL,
450 "file not truncated, size = %u (should be 10240)",
451 (unsigned int)finfo3.all_info.out.size);
456 torture_comment(tctx, "write time %s\n",
457 nt_time_string(tctx, finfo3.all_info.out.write_time));
458 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
459 double diff = timeval_elapsed(&start);
461 torture_comment(tctx, "server updated write_time after %.2f seconds"
462 "(1 sec == %.2f)(correct)\n",
470 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
471 torture_result(tctx, TORTURE_FAIL,
472 "Server updated write time (wrong!)");
476 /* the close should trigger an write time update */
477 smbcli_close(cli->tree, fnum1);
480 status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
481 torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
483 if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
484 torture_result(tctx, TORTURE_FAIL,
485 "Server did not update write time on close (wrong!)");
487 } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
488 torture_comment(tctx, "Server updated write time on close (correct)\n");
492 smbcli_close(cli->tree, fnum1);
493 smbcli_unlink(cli->tree, fname);
494 smbcli_deltree(cli->tree, BASEDIR);
499 /* Updating with a SET_FILE_END_OF_FILE_INFO
500 * changes the write time immediately - even on expand. */
502 static bool test_delayed_write_update1b(struct torture_context *tctx, struct smbcli_state *cli)
504 union smb_fileinfo finfo1, finfo2, finfo3, pinfo4;
505 const char *fname = BASEDIR "\\torture_file1b.txt";
510 struct timeval start;
512 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
513 int normal_delay = 2000000;
514 double sec = ((double)used_delay) / ((double)normal_delay);
515 int msec = 1000 * sec;
518 torture_comment(tctx, "\nRunning test_delayed_write_update1b\n");
520 if (!torture_setup_dir(cli, BASEDIR)) {
524 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
526 torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
530 memset(buf, 'x', 2048);
531 written = smbcli_write(cli->tree, fnum1, 0, buf, 0, 2048);
533 /* 3 second delay to ensure we get past any 2 second time
534 granularity (older systems may have that) */
537 finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
538 finfo1.all_info.in.file.fnum = fnum1;
541 pinfo4.all_info.level = RAW_FILEINFO_ALL_INFO;
542 pinfo4.all_info.in.file.path = fname;
544 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
546 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
548 torture_comment(tctx, "Initial write time %s\n",
549 nt_time_string(tctx, finfo1.all_info.out.write_time));
551 /* Do a SET_END_OF_FILE_INFO call to truncate. */
552 status = smbcli_ftruncate(cli->tree, fnum1, (uint64_t)10240);
554 torture_assert_ntstatus_ok(tctx, status, "SET_END_OF_FILE failed");
556 start = timeval_current();
557 end = timeval_add(&start, (120*sec), 0);
558 while (!timeval_expired(&end)) {
559 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
561 if (!NT_STATUS_IS_OK(status)) {
562 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
567 if (finfo2.all_info.out.size != 10240) {
568 torture_result(tctx, TORTURE_FAIL,
569 "file not truncated (size = %u, should be 10240)",
570 (unsigned int)finfo2.all_info.out.size );
575 torture_comment(tctx, "write time %s\n",
576 nt_time_string(tctx, finfo2.all_info.out.write_time));
577 if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
578 double diff = timeval_elapsed(&start);
579 if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
580 torture_result(tctx, TORTURE_FAIL,
581 "After SET_END_OF_FILE truncate "
582 "server updated write_time after %.2f seconds"
583 "(1 sec == %.2f)(wrong!)",
589 torture_comment(tctx, "After SET_END_OF_FILE truncate "
590 "server updated write_time after %.2f seconds"
591 "(1 sec == %.2f)(correct)\n",
599 if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
600 torture_result(tctx, TORTURE_FAIL,
601 "Server did not update write time (wrong!)");
608 /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
609 written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
611 torture_assert_int_equal(tctx, written, 1,
612 "unexpected number of bytes written");
614 start = timeval_current();
615 end = timeval_add(&start, (10*sec), 0);
616 while (!timeval_expired(&end)) {
617 status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
619 if (!NT_STATUS_IS_OK(status)) {
620 torture_result(tctx, TORTURE_FAIL,
621 "fileinfo failed: %s", nt_errstr(status));
626 if (finfo3.all_info.out.size != 10240) {
627 DEBUG(0, ("file not truncated (size = %u, should be 10240)\n",
628 (unsigned int)finfo3.all_info.out.size ));
633 torture_comment(tctx, "write time %s\n",
634 nt_time_string(tctx, finfo3.all_info.out.write_time));
635 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
636 double diff = timeval_elapsed(&start);
638 torture_comment(tctx, "server updated write_time after %.2f seconds"
639 "(1 sec == %.2f)(correct)\n",
647 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
648 torture_result(tctx, TORTURE_FAIL, "Server updated write time (wrong!)\n");
652 /* the close should trigger an write time update */
653 smbcli_close(cli->tree, fnum1);
656 status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
657 torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
659 if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
660 torture_result(tctx, TORTURE_FAIL, "Server did not update write time on close (wrong!)\n");
662 } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
663 torture_comment(tctx, "Server updated write time on close (correct)\n");
667 smbcli_close(cli->tree, fnum1);
668 smbcli_unlink(cli->tree, fname);
669 smbcli_deltree(cli->tree, BASEDIR);
674 /* Updating with a SET_ALLOCATION_INFO (truncate) does so immediately. */
676 static bool test_delayed_write_update1c(struct torture_context *tctx, struct smbcli_state *cli)
678 union smb_setfileinfo parms;
679 union smb_fileinfo finfo1, finfo2, finfo3, pinfo4;
680 const char *fname = BASEDIR "\\torture_file1c.txt";
685 struct timeval start;
687 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
688 int normal_delay = 2000000;
689 double sec = ((double)used_delay) / ((double)normal_delay);
690 int msec = 1000 * sec;
693 torture_comment(tctx, "\nRunning test_delayed_write_update1c\n");
695 if (!torture_setup_dir(cli, BASEDIR)) {
699 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
701 torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
705 memset(buf, 'x', 2048);
706 written = smbcli_write(cli->tree, fnum1, 0, buf, 0, 2048);
708 /* 3 second delay to ensure we get past any 2 second time
709 granularity (older systems may have that) */
712 finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
713 finfo1.all_info.in.file.fnum = fnum1;
716 pinfo4.all_info.level = RAW_FILEINFO_ALL_INFO;
717 pinfo4.all_info.in.file.path = fname;
719 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
721 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
723 torture_comment(tctx, "Initial write time %s\n",
724 nt_time_string(tctx, finfo1.all_info.out.write_time));
726 /* Do a SET_ALLOCATION_SIZE call to truncate. */
727 parms.allocation_info.level = RAW_SFILEINFO_ALLOCATION_INFO;
728 parms.allocation_info.in.file.fnum = fnum1;
729 parms.allocation_info.in.alloc_size = 0;
731 status = smb_raw_setfileinfo(cli->tree, &parms);
733 torture_assert_ntstatus_ok(tctx, status,
734 "RAW_SFILEINFO_ALLOCATION_INFO failed");
736 start = timeval_current();
737 end = timeval_add(&start, (120*sec), 0);
738 while (!timeval_expired(&end)) {
739 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
741 if (!NT_STATUS_IS_OK(status)) {
742 torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s",
748 if (finfo2.all_info.out.size != 0) {
749 torture_result(tctx, TORTURE_FAIL,
750 "file not truncated (size = %u, should be 10240)",
751 (unsigned int)finfo2.all_info.out.size);
756 torture_comment(tctx, "write time %s\n",
757 nt_time_string(tctx, finfo2.all_info.out.write_time));
758 if (finfo1.all_info.out.write_time != finfo2.all_info.out.write_time) {
759 double diff = timeval_elapsed(&start);
760 if (diff > (0.25 * sec * 0.75)) { /* 0.75 to cope with vmware timing */
761 torture_comment(tctx, "After SET_ALLOCATION_INFO truncate "
762 "server updated write_time after %.2f seconds"
763 "(1 sec == %.2f)(wrong!)\n",
769 torture_comment(tctx, "After SET_ALLOCATION_INFO truncate "
770 "server updated write_time after %.2f seconds"
771 "(1 sec == %.2f)(correct)\n",
779 if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
780 torture_result(tctx, TORTURE_FAIL,
781 "Server did not update write time (wrong!)");
788 /* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
789 written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
790 torture_assert_int_equal(tctx, written, 1,
791 "Unexpected number of bytes written");
793 start = timeval_current();
794 end = timeval_add(&start, (10*sec), 0);
795 while (!timeval_expired(&end)) {
796 status = smb_raw_fileinfo(cli->tree, tctx, &finfo3);
798 if (!NT_STATUS_IS_OK(status)) {
799 torture_result(tctx, TORTURE_FAIL, "fileinfo failed: %s",
805 if (finfo3.all_info.out.size != 1) {
806 torture_result(tctx, TORTURE_FAIL, "file not expanded");
811 torture_comment(tctx, "write time %s\n",
812 nt_time_string(tctx, finfo3.all_info.out.write_time));
813 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
814 double diff = timeval_elapsed(&start);
816 torture_comment(tctx, "server updated write_time after %.2f seconds"
817 "(1 sec == %.2f)(correct)\n",
825 if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
826 torture_result(tctx, TORTURE_FAIL,
827 "Server updated write time (wrong!)");
831 /* the close should trigger an write time update */
832 smbcli_close(cli->tree, fnum1);
835 status = smb_raw_pathinfo(cli->tree, tctx, &pinfo4);
836 torture_assert_ntstatus_ok(tctx, status, "pathinfo failed");
838 if (finfo3.all_info.out.write_time == pinfo4.all_info.out.write_time) {
839 torture_result(tctx, TORTURE_FAIL, "Server did not update write time on close (wrong!)\n");
841 } else if (finfo3.all_info.out.write_time < pinfo4.all_info.out.write_time) {
842 torture_comment(tctx, "Server updated write time on close (correct)\n");
846 smbcli_close(cli->tree, fnum1);
847 smbcli_unlink(cli->tree, fname);
848 smbcli_deltree(cli->tree, BASEDIR);
854 * Do as above, but using 2 connections.
857 static bool test_delayed_write_update2(struct torture_context *tctx, struct smbcli_state *cli,
858 struct smbcli_state *cli2)
860 union smb_fileinfo finfo1, finfo2;
861 const char *fname = BASEDIR "\\torture_file.txt";
867 struct timeval start;
869 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
870 int normal_delay = 2000000;
871 double sec = ((double)used_delay) / ((double)normal_delay);
872 int msec = 1000 * sec;
873 union smb_flush flsh;
875 torture_comment(tctx, "\nRunning test_delayed_write_update2\n");
877 if (!torture_setup_dir(cli, BASEDIR)) {
881 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
883 torture_comment(tctx, "Failed to open %s\n", fname);
887 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
888 finfo1.basic_info.in.file.fnum = fnum1;
891 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
893 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
895 torture_comment(tctx, "Initial write time %s\n",
896 nt_time_string(tctx, finfo1.basic_info.out.write_time));
898 /* 3 second delay to ensure we get past any 2 second time
899 granularity (older systems may have that) */
903 /* Try using setfileinfo instead of write to update write time. */
904 union smb_setfileinfo sfinfo;
905 time_t t_set = time(NULL);
906 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFO;
907 sfinfo.basic_info.in.file.fnum = fnum1;
908 sfinfo.basic_info.in.create_time = finfo1.basic_info.out.create_time;
909 sfinfo.basic_info.in.access_time = finfo1.basic_info.out.access_time;
911 /* I tried this with both + and - ve to see if it makes a different.
912 It doesn't - once the filetime is set via setfileinfo it stays that way. */
914 unix_to_nt_time(&sfinfo.basic_info.in.write_time, t_set - 30000);
916 unix_to_nt_time(&sfinfo.basic_info.in.write_time, t_set + 30000);
918 sfinfo.basic_info.in.change_time = finfo1.basic_info.out.change_time;
919 sfinfo.basic_info.in.attrib = finfo1.basic_info.out.attrib;
921 status = smb_raw_setfileinfo(cli->tree, &sfinfo);
923 torture_assert_ntstatus_ok(tctx, status, "sfileinfo failed");
926 finfo2.basic_info.in.file.path = fname;
928 status = smb_raw_pathinfo(cli2->tree, tctx, &finfo2);
930 if (!NT_STATUS_IS_OK(status)) {
931 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
934 torture_comment(tctx, "write time %s\n",
935 nt_time_string(tctx, finfo2.basic_info.out.write_time));
937 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
938 torture_comment(tctx, "Server updated write_time (correct)\n");
940 torture_result(tctx, TORTURE_FAIL, "Server did not update write time (wrong!)\n");
944 /* Now try a write to see if the write time gets reset. */
946 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
947 finfo1.basic_info.in.file.fnum = fnum1;
950 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
952 if (!NT_STATUS_IS_OK(status)) {
953 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
957 torture_comment(tctx, "Modified write time %s\n",
958 nt_time_string(tctx, finfo1.basic_info.out.write_time));
961 torture_comment(tctx, "Doing a 10 byte write to extend the file and see if this changes the last write time.\n");
963 written = smbcli_write(cli->tree, fnum1, 0, "0123456789", 1, 10);
966 torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
967 (int)written, __location__);
971 /* Just to prove to tridge that the an smbflush has no effect on
972 the write time :-). The setfileinfo IS STICKY. JRA. */
974 torture_comment(tctx, "Doing flush after write\n");
976 flsh.flush.level = RAW_FLUSH_FLUSH;
977 flsh.flush.in.file.fnum = fnum1;
978 status = smb_raw_flush(cli->tree, &flsh);
979 if (!NT_STATUS_IS_OK(status)) {
980 DEBUG(0, ("smbflush failed: %s\n", nt_errstr(status)));
984 /* Once the time was set using setfileinfo then it stays set - writes
985 don't have any effect. But make sure. */
986 start = timeval_current();
987 end = timeval_add(&start, (15*sec), 0);
988 while (!timeval_expired(&end)) {
989 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
991 if (!NT_STATUS_IS_OK(status)) {
992 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
996 torture_comment(tctx, "write time %s\n",
997 nt_time_string(tctx, finfo2.basic_info.out.write_time));
998 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
999 double diff = timeval_elapsed(&start);
1000 torture_comment(tctx, "Server updated write_time after %.2f seconds"
1001 "(1sec == %.2f) (wrong!)\n",
1010 if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
1011 torture_comment(tctx, "Server did not update write time (correct)\n");
1017 fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
1019 torture_comment(tctx, "Failed to open %s\n", fname);
1023 torture_comment(tctx, "Doing a 10 byte write to extend the file via second fd and see if this changes the last write time.\n");
1025 written = smbcli_write(cli->tree, fnum2, 0, "0123456789", 11, 10);
1027 if (written != 10) {
1028 torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
1029 (int)written, __location__);
1033 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
1035 if (!NT_STATUS_IS_OK(status)) {
1036 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
1039 torture_comment(tctx, "write time %s\n",
1040 nt_time_string(tctx, finfo2.basic_info.out.write_time));
1041 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
1042 torture_comment(tctx, "Server updated write_time (wrong!)\n");
1046 torture_comment(tctx, "Closing the first fd to see if write time updated.\n");
1047 smbcli_close(cli->tree, fnum1);
1050 torture_comment(tctx, "Doing a 10 byte write to extend the file via second fd and see if this changes the last write time.\n");
1052 written = smbcli_write(cli->tree, fnum2, 0, "0123456789", 21, 10);
1054 if (written != 10) {
1055 torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
1056 (int)written, __location__);
1060 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1061 finfo1.basic_info.in.file.fnum = fnum2;
1063 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
1065 if (!NT_STATUS_IS_OK(status)) {
1066 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
1069 torture_comment(tctx, "write time %s\n",
1070 nt_time_string(tctx, finfo2.basic_info.out.write_time));
1071 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
1072 torture_comment(tctx, "Server updated write_time (wrong!)\n");
1076 /* Once the time was set using setfileinfo then it stays set - writes
1077 don't have any effect. But make sure. */
1078 start = timeval_current();
1079 end = timeval_add(&start, (15*sec), 0);
1080 while (!timeval_expired(&end)) {
1081 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
1083 if (!NT_STATUS_IS_OK(status)) {
1084 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
1088 torture_comment(tctx, "write time %s\n",
1089 nt_time_string(tctx, finfo2.basic_info.out.write_time));
1090 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
1091 double diff = timeval_elapsed(&start);
1092 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1093 "(1sec == %.2f) (wrong!)\n",
1102 if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
1103 torture_comment(tctx, "Server did not update write time (correct)\n");
1106 torture_comment(tctx, "Closing second fd to see if write time updated.\n");
1108 smbcli_close(cli->tree, fnum2);
1111 fnum1 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
1113 torture_comment(tctx, "Failed to open %s\n", fname);
1117 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1118 finfo1.basic_info.in.file.fnum = fnum1;
1121 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
1123 if (!NT_STATUS_IS_OK(status)) {
1124 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
1128 torture_comment(tctx, "Second open initial write time %s\n",
1129 nt_time_string(tctx, finfo1.basic_info.out.write_time));
1132 torture_comment(tctx, "Doing a 10 byte write to extend the file to see if this changes the last write time.\n");
1134 written = smbcli_write(cli->tree, fnum1, 0, "0123456789", 31, 10);
1136 if (written != 10) {
1137 torture_comment(tctx, "write failed - wrote %d bytes (%s)\n",
1138 (int)written, __location__);
1142 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1143 finfo1.basic_info.in.file.fnum = fnum1;
1145 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
1147 if (!NT_STATUS_IS_OK(status)) {
1148 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
1151 torture_comment(tctx, "write time %s\n",
1152 nt_time_string(tctx, finfo2.basic_info.out.write_time));
1153 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
1154 torture_comment(tctx, "Server updated write_time (wrong!)\n");
1158 /* Now the write time should be updated again */
1159 start = timeval_current();
1160 end = timeval_add(&start, (15*sec), 0);
1161 while (!timeval_expired(&end)) {
1162 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
1164 if (!NT_STATUS_IS_OK(status)) {
1165 DEBUG(0, ("fileinfo failed: %s\n", nt_errstr(status)));
1169 torture_comment(tctx, "write time %s\n",
1170 nt_time_string(tctx, finfo2.basic_info.out.write_time));
1171 if (finfo1.basic_info.out.write_time != finfo2.basic_info.out.write_time) {
1172 double diff = timeval_elapsed(&start);
1173 if (diff < (TIMEDELAY_SECS * sec * 0.75)) { /* 0.75 to cope with vmware timing */
1174 torture_comment(tctx, "Server updated write_time after %.2f seconds"
1175 "(1sec == %.2f) (wrong!)\n",
1181 torture_comment(tctx, "Server updated write_time after %.2f seconds"
1182 "(1sec == %.2f) (correct)\n",
1190 if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
1191 torture_result(tctx, TORTURE_FAIL, "Server did not update write time (wrong!)\n");
1196 /* One more test to do. We should read the filetime via findfirst on the
1197 second connection to ensure it's the same. This is very easy for a Windows
1198 server but a bastard to get right on a POSIX server. JRA. */
1201 smbcli_close(cli->tree, fnum1);
1202 smbcli_unlink(cli->tree, fname);
1203 smbcli_deltree(cli->tree, BASEDIR);
1209 /* Windows does obviously not update the stat info during a write call. I
1210 * *think* this is the problem causing a spurious Excel 2003 on XP error
1211 * message when saving a file. Excel does a setfileinfo, writes, and then does
1212 * a getpath(!)info. Or so... For Samba sometimes it displays an error message
1213 * that the file might have been changed in between. What i've been able to
1214 * trace down is that this happens if the getpathinfo after the write shows a
1215 * different last write time than the setfileinfo showed. This is really
1219 static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_state *cli,
1220 struct smbcli_state *cli2)
1222 union smb_fileinfo finfo1, finfo2;
1223 const char *fname = BASEDIR "\\torture_file.txt";
1229 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
1230 int normal_delay = 2000000;
1231 double sec = ((double)used_delay) / ((double)normal_delay);
1232 int msec = 1000 * sec;
1234 torture_comment(tctx, "\nRunning test_finfo_after_write\n");
1236 if (!torture_setup_dir(cli, BASEDIR)) {
1240 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1243 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
1247 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1248 finfo1.basic_info.in.file.fnum = fnum1;
1250 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
1252 if (!NT_STATUS_IS_OK(status)) {
1254 torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", nt_errstr(status));
1260 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
1263 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
1268 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR, DENY_NONE);
1270 torture_result(tctx, TORTURE_FAIL, __location__": failed to open 2nd time - %s",
1271 smbcli_errstr(cli2->tree));
1276 written = smbcli_write(cli2->tree, fnum2, 0, "x", 0, 1);
1279 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1",
1285 finfo2.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1286 finfo2.basic_info.in.file.path = fname;
1288 status = smb_raw_pathinfo(cli2->tree, tctx, &finfo2);
1290 if (!NT_STATUS_IS_OK(status)) {
1291 torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s",
1297 if (finfo1.basic_info.out.create_time !=
1298 finfo2.basic_info.out.create_time) {
1299 torture_result(tctx, TORTURE_FAIL, __location__": create_time changed");
1304 if (finfo1.basic_info.out.access_time !=
1305 finfo2.basic_info.out.access_time) {
1306 torture_result(tctx, TORTURE_FAIL, __location__": access_time changed");
1311 if (finfo1.basic_info.out.write_time !=
1312 finfo2.basic_info.out.write_time) {
1313 torture_result(tctx, TORTURE_FAIL, __location__": write_time changed:\n"
1314 "write time conn 1 = %s, conn 2 = %s",
1315 nt_time_string(tctx, finfo1.basic_info.out.write_time),
1316 nt_time_string(tctx, finfo2.basic_info.out.write_time));
1321 if (finfo1.basic_info.out.change_time !=
1322 finfo2.basic_info.out.change_time) {
1323 torture_result(tctx, TORTURE_FAIL, __location__": change_time changed");
1328 /* One of the two following calls updates the qpathinfo. */
1330 /* If you had skipped the smbcli_write on fnum2, it would
1331 * *not* have updated the stat on disk */
1333 smbcli_close(cli2->tree, fnum2);
1336 /* This call is only for the people looking at ethereal :-) */
1337 finfo2.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1338 finfo2.basic_info.in.file.path = fname;
1340 status = smb_raw_pathinfo(cli->tree, tctx, &finfo2);
1342 if (!NT_STATUS_IS_OK(status)) {
1343 torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", nt_errstr(status));
1350 smbcli_close(cli->tree, fnum1);
1351 smbcli_unlink(cli->tree, fname);
1352 smbcli_deltree(cli->tree, BASEDIR);
1357 #define COMPARE_WRITE_TIME_CMP(given, correct, cmp) do { \
1358 uint64_t r = 10*1000*1000; \
1359 NTTIME g = (given).basic_info.out.write_time; \
1360 NTTIME gr = (g / r) * r; \
1361 NTTIME c = (correct).basic_info.out.write_time; \
1362 NTTIME cr = (c / r) * r; \
1363 bool strict = torture_setting_bool(tctx, "strict mode", false); \
1365 if (strict && (g cmp c)) { \
1367 } else if ((g cmp c) && (gr cmp cr)) { \
1368 /* handle filesystem without high resolution timestamps */ \
1372 torture_result(tctx, TORTURE_FAIL, __location__": wrong write_time (%s)%s(%llu) %s (%s)%s(%llu)", \
1373 #given, nt_time_string(tctx, g), (unsigned long long)g, \
1374 #cmp, #correct, nt_time_string(tctx, c), (unsigned long long)c); \
1379 #define COMPARE_WRITE_TIME_EQUAL(given,correct) \
1380 COMPARE_WRITE_TIME_CMP(given,correct,!=)
1381 #define COMPARE_WRITE_TIME_GREATER(given,correct) \
1382 COMPARE_WRITE_TIME_CMP(given,correct,<=)
1383 #define COMPARE_WRITE_TIME_LESS(given,correct) \
1384 COMPARE_WRITE_TIME_CMP(given,correct,>=)
1386 #define COMPARE_ACCESS_TIME_CMP(given, correct, cmp) do { \
1387 NTTIME g = (given).basic_info.out.access_time; \
1388 NTTIME c = (correct).basic_info.out.access_time; \
1390 torture_result(tctx, TORTURE_FAIL, __location__": wrong access_time (%s)%s %s (%s)%s", \
1391 #given, nt_time_string(tctx, g), \
1392 #cmp, #correct, nt_time_string(tctx, c)); \
1397 #define COMPARE_ACCESS_TIME_EQUAL(given,correct) \
1398 COMPARE_ACCESS_TIME_CMP(given,correct,!=)
1400 #define COMPARE_BOTH_TIMES_EQUAL(given,correct) do { \
1401 COMPARE_ACCESS_TIME_EQUAL(given,correct); \
1402 COMPARE_WRITE_TIME_EQUAL(given,correct); \
1405 #define GET_INFO_FILE(finfo) do { \
1407 _status = smb_raw_fileinfo(cli->tree, tctx, &finfo); \
1408 if (!NT_STATUS_IS_OK(_status)) { \
1410 torture_result(tctx, TORTURE_FAIL, __location__": fileinfo failed: %s", \
1411 nt_errstr(_status)); \
1414 torture_comment(tctx, "fileinfo: Access(%s) Write(%s)\n", \
1415 nt_time_string(tctx, finfo.basic_info.out.access_time), \
1416 nt_time_string(tctx, finfo.basic_info.out.write_time)); \
1418 #define GET_INFO_PATH(pinfo) do { \
1420 _status = smb_raw_pathinfo(cli2->tree, tctx, &pinfo); \
1421 if (!NT_STATUS_IS_OK(_status)) { \
1422 torture_result(tctx, TORTURE_FAIL, __location__": pathinfo failed: %s", \
1423 nt_errstr(_status)); \
1427 torture_comment(tctx, "pathinfo: Access(%s) Write(%s)\n", \
1428 nt_time_string(tctx, pinfo.basic_info.out.access_time), \
1429 nt_time_string(tctx, pinfo.basic_info.out.write_time)); \
1431 #define GET_INFO_BOTH(finfo,pinfo) do { \
1432 GET_INFO_FILE(finfo); \
1433 GET_INFO_PATH(pinfo); \
1434 COMPARE_BOTH_TIMES_EQUAL(finfo,pinfo); \
1437 #define SET_INFO_FILE_EX(finfo, wrtime, tree, tfnum) do { \
1439 union smb_setfileinfo sfinfo; \
1440 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFO; \
1441 sfinfo.basic_info.in.file.fnum = tfnum; \
1442 sfinfo.basic_info.in.create_time = 0; \
1443 sfinfo.basic_info.in.access_time = 0; \
1444 unix_to_nt_time(&sfinfo.basic_info.in.write_time, (wrtime)); \
1445 sfinfo.basic_info.in.change_time = 0; \
1446 sfinfo.basic_info.in.attrib = finfo1.basic_info.out.attrib; \
1447 _status = smb_raw_setfileinfo(tree, &sfinfo); \
1448 if (!NT_STATUS_IS_OK(_status)) { \
1449 torture_result(tctx, TORTURE_FAIL, __location__": setfileinfo failed: %s", \
1450 nt_errstr(_status)); \
1455 #define SET_INFO_FILE(finfo, wrtime) \
1456 SET_INFO_FILE_EX(finfo, wrtime, cli->tree, fnum1)
1458 #define SET_INFO_FILE_NS(finfo, wrtime, ns, tree, tfnum) do { \
1460 union smb_setfileinfo sfinfo; \
1461 sfinfo.basic_info.level = RAW_SFILEINFO_BASIC_INFO; \
1462 sfinfo.basic_info.in.file.fnum = tfnum; \
1463 sfinfo.basic_info.in.create_time = 0; \
1464 sfinfo.basic_info.in.access_time = 0; \
1465 unix_to_nt_time(&sfinfo.basic_info.in.write_time, (wrtime)); \
1466 sfinfo.basic_info.in.write_time += (ns); \
1467 sfinfo.basic_info.in.change_time = 0; \
1468 sfinfo.basic_info.in.attrib = finfo1.basic_info.out.attrib; \
1469 _status = smb_raw_setfileinfo(tree, &sfinfo); \
1470 if (!NT_STATUS_IS_OK(_status)) { \
1471 torture_result(tctx, TORTURE_FAIL, __location__": setfileinfo failed: %s", \
1472 nt_errstr(_status)); \
1478 static bool test_delayed_write_update3(struct torture_context *tctx,
1479 struct smbcli_state *cli,
1480 struct smbcli_state *cli2)
1482 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
1483 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
1484 const char *fname = BASEDIR "\\torture_file3.txt";
1488 struct timeval start;
1490 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
1491 int normal_delay = 2000000;
1492 double sec = ((double)used_delay) / ((double)normal_delay);
1493 int msec = 1000 * sec;
1495 torture_comment(tctx, "\nRunning test_delayed_write_update3\n");
1497 if (!torture_setup_dir(cli, BASEDIR)) {
1501 torture_comment(tctx, "Open the file handle\n");
1502 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1505 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
1509 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1510 finfo0.basic_info.in.file.fnum = fnum1;
1515 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1516 pinfo0.basic_info.in.file.path = fname;
1523 /* get the initial times */
1524 GET_INFO_BOTH(finfo0,pinfo0);
1527 * make sure the write time is updated 2 seconds later
1528 * calcuated from the first write
1529 * (but expect upto 5 seconds extra time for a busy server)
1531 start = timeval_current();
1532 end = timeval_add(&start, 7 * sec, 0);
1533 while (!timeval_expired(&end)) {
1535 torture_comment(tctx, "Do a write on the file handle\n");
1536 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
1538 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
1542 /* get the times after the write */
1543 GET_INFO_FILE(finfo1);
1545 if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
1546 double diff = timeval_elapsed(&start);
1547 if (diff < (TIMEDELAY_SECS * sec * 0.75)) { /* 0.75 to cope with vmware timing */
1548 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1549 "(1sec == %.2f) (wrong!)\n",
1555 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1556 "(1sec == %.2f) (correct)\n",
1563 GET_INFO_BOTH(finfo1,pinfo1);
1564 COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0);
1566 /* sure any further write doesn't update the write time */
1567 start = timeval_current();
1568 end = timeval_add(&start, 15 * sec, 0);
1569 while (!timeval_expired(&end)) {
1571 torture_comment(tctx, "Do a write on the file handle\n");
1572 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
1574 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
1578 /* get the times after the write */
1579 GET_INFO_BOTH(finfo2,pinfo2);
1581 if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
1582 double diff = timeval_elapsed(&start);
1583 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1584 "(1sec == %.2f) (wrong!)\n",
1592 GET_INFO_BOTH(finfo2,pinfo2);
1593 COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
1594 if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
1595 torture_comment(tctx, "Server did not update write_time (correct)\n");
1601 GET_INFO_BOTH(finfo3,pinfo3);
1602 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
1605 * the close updates the write time to the time of the close
1606 * and not to the time of the last write!
1608 torture_comment(tctx, "Close the file handle\n");
1609 smbcli_close(cli->tree, fnum1);
1612 GET_INFO_PATH(pinfo4);
1613 COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);
1615 if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
1616 torture_comment(tctx, "Server updated the write_time on close (correct)\n");
1621 smbcli_close(cli->tree, fnum1);
1622 smbcli_unlink(cli->tree, fname);
1623 smbcli_deltree(cli->tree, BASEDIR);
1629 * Show that a truncate write always updates the write time even
1630 * if an initial write has already updated the write time.
1633 static bool test_delayed_write_update3a(struct torture_context *tctx,
1634 struct smbcli_state *cli,
1635 struct smbcli_state *cli2)
1637 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
1638 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
1639 const char *fname = BASEDIR "\\torture_file3a.txt";
1644 struct timeval start;
1646 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
1647 int normal_delay = 2000000;
1648 double sec = ((double)used_delay) / ((double)normal_delay);
1649 int msec = 1000 * sec;
1651 torture_comment(tctx, "\nRunning test_delayed_write_update3a\n");
1653 if (!torture_setup_dir(cli, BASEDIR)) {
1657 torture_comment(tctx, "Open the file handle\n");
1658 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1661 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
1665 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1666 finfo0.basic_info.in.file.fnum = fnum1;
1671 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1672 pinfo0.basic_info.in.file.path = fname;
1679 /* get the initial times */
1680 GET_INFO_BOTH(finfo0,pinfo0);
1683 * sleep some time, to demonstrate the handling of write times
1684 * doesn't depend on the time since the open
1688 /* get the initial times */
1689 GET_INFO_BOTH(finfo1,pinfo1);
1690 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
1693 * make sure the write time is updated 2 seconds later
1694 * calcuated from the first write
1695 * (but expect upto 5 seconds extra time for a busy server)
1697 start = timeval_current();
1698 end = timeval_add(&start, 7 * sec, 0);
1699 while (!timeval_expired(&end)) {
1701 torture_comment(tctx, "Do a write on the file handle\n");
1702 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
1704 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
1708 /* get the times after the write */
1709 GET_INFO_FILE(finfo1);
1711 if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
1712 double diff = timeval_elapsed(&start);
1713 if (diff < (TIMEDELAY_SECS * sec * 0.75)) { /* 0.75 to cope with vmware timing */
1714 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1715 "(1sec == %.2f) (wrong!)\n",
1721 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1722 "(1sec == %.2f) (correct)\n",
1729 GET_INFO_BOTH(finfo1,pinfo1);
1730 COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0);
1733 * demonstrate that a truncate write always
1734 * updates the write time immediately
1736 for (i=0; i < 3; i++) {
1739 torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
1740 written = smbcli_smbwrite(cli->tree, fnum1, "x", 10240, 0);
1742 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
1746 /* get the times after the write */
1747 GET_INFO_BOTH(finfo2,pinfo2);
1748 COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
1752 /* sure any further write doesn't update the write time */
1753 start = timeval_current();
1754 end = timeval_add(&start, 15 * sec, 0);
1755 while (!timeval_expired(&end)) {
1757 torture_comment(tctx, "Do a write on the file handle\n");
1758 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
1760 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
1764 /* get the times after the write */
1765 GET_INFO_BOTH(finfo2,pinfo2);
1767 if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
1768 double diff = timeval_elapsed(&start);
1769 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1770 "(1sec == %.2f) (wrong!)\n",
1778 GET_INFO_BOTH(finfo2,pinfo2);
1779 COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
1780 if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
1781 torture_comment(tctx, "Server did not update write_time (correct)\n");
1787 /* get the initial times */
1788 GET_INFO_BOTH(finfo1,pinfo1);
1789 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo2);
1792 * demonstrate that a truncate write always
1793 * updates the write time immediately
1795 for (i=0; i < 3; i++) {
1798 torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
1799 written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
1801 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
1805 /* get the times after the write */
1806 GET_INFO_BOTH(finfo2,pinfo2);
1807 COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
1814 GET_INFO_BOTH(finfo3,pinfo3);
1815 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
1818 * the close doesn't update the write time
1820 torture_comment(tctx, "Close the file handle\n");
1821 smbcli_close(cli->tree, fnum1);
1824 GET_INFO_PATH(pinfo4);
1825 COMPARE_WRITE_TIME_EQUAL(pinfo4, pinfo3);
1827 if (pinfo4.basic_info.out.write_time == pinfo3.basic_info.out.write_time) {
1828 torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
1833 smbcli_close(cli->tree, fnum1);
1834 smbcli_unlink(cli->tree, fname);
1835 smbcli_deltree(cli->tree, BASEDIR);
1841 * Show a close after write updates the write timestamp to
1842 * the close time, not the last write time.
1845 static bool test_delayed_write_update3b(struct torture_context *tctx,
1846 struct smbcli_state *cli,
1847 struct smbcli_state *cli2)
1849 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
1850 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
1851 const char *fname = BASEDIR "\\torture_file3b.txt";
1855 struct timeval start;
1857 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
1858 int normal_delay = 2000000;
1859 double sec = ((double)used_delay) / ((double)normal_delay);
1860 int msec = 1000 * sec;
1862 torture_comment(tctx, "\nRunning test_delayed_write_update3b\n");
1864 if (!torture_setup_dir(cli, BASEDIR)) {
1868 torture_comment(tctx, "Open the file handle\n");
1869 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
1872 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
1876 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1877 finfo0.basic_info.in.file.fnum = fnum1;
1882 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
1883 pinfo0.basic_info.in.file.path = fname;
1890 /* get the initial times */
1891 GET_INFO_BOTH(finfo0,pinfo0);
1894 * sleep some time, to demonstrate the handling of write times
1895 * doesn't depend on the time since the open
1899 /* get the initial times */
1900 GET_INFO_BOTH(finfo1,pinfo1);
1901 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
1904 * make sure the write time is updated 2 seconds later
1905 * calcuated from the first write
1906 * (but expect upto 5 seconds extra time for a busy server)
1908 start = timeval_current();
1909 end = timeval_add(&start, 7 * sec, 0);
1910 while (!timeval_expired(&end)) {
1912 torture_comment(tctx, "Do a write on the file handle\n");
1913 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
1915 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
1919 /* get the times after the write */
1920 GET_INFO_FILE(finfo1);
1922 if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
1923 double diff = timeval_elapsed(&start);
1924 if (diff < (TIMEDELAY_SECS * sec * 0.75)) { /* 0.75 to cope with vmware timing */
1925 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1926 "(1sec == %.2f) (wrong!)\n",
1932 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1933 "(1sec == %.2f) (correct)\n",
1940 GET_INFO_BOTH(finfo1,pinfo1);
1941 COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0);
1943 /* sure any further write doesn't update the write time */
1944 start = timeval_current();
1945 end = timeval_add(&start, 15 * sec, 0);
1946 while (!timeval_expired(&end)) {
1948 torture_comment(tctx, "Do a write on the file handle\n");
1949 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
1951 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
1955 /* get the times after the write */
1956 GET_INFO_BOTH(finfo2,pinfo2);
1958 if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
1959 double diff = timeval_elapsed(&start);
1960 torture_comment(tctx, "Server updated write_time after %.2f seconds "
1961 "(1sec == %.2f) (wrong!)\n",
1969 GET_INFO_BOTH(finfo2,pinfo2);
1970 COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
1971 if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
1972 torture_comment(tctx, "Server did not update write_time (correct)\n");
1978 GET_INFO_BOTH(finfo3,pinfo3);
1979 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
1982 * the close updates the write time to the time of the close
1983 * and not to the time of the last write!
1985 torture_comment(tctx, "Close the file handle\n");
1986 smbcli_close(cli->tree, fnum1);
1989 GET_INFO_PATH(pinfo4);
1990 COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);
1992 if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
1993 torture_comment(tctx, "Server updated the write_time on close (correct)\n");
1998 smbcli_close(cli->tree, fnum1);
1999 smbcli_unlink(cli->tree, fname);
2000 smbcli_deltree(cli->tree, BASEDIR);
2006 * Check that a write after a truncate write doesn't update
2007 * the timestamp, but a truncate write after a write does.
2008 * Also prove that a close after a truncate write updates the
2009 * timestamp to current, not the time of last write.
2012 static bool test_delayed_write_update3c(struct torture_context *tctx,
2013 struct smbcli_state *cli,
2014 struct smbcli_state *cli2)
2016 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
2017 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
2018 const char *fname = BASEDIR "\\torture_file3c.txt";
2023 struct timeval start;
2025 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
2026 int normal_delay = 2000000;
2027 double sec = ((double)used_delay) / ((double)normal_delay);
2028 int msec = 1000 * sec;
2030 torture_comment(tctx, "\nRunning test_delayed_write_update3c\n");
2032 if (!torture_setup_dir(cli, BASEDIR)) {
2036 torture_comment(tctx, "Open the file handle\n");
2037 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2040 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
2044 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2045 finfo0.basic_info.in.file.fnum = fnum1;
2050 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2051 pinfo0.basic_info.in.file.path = fname;
2058 /* get the initial times */
2059 GET_INFO_BOTH(finfo0,pinfo0);
2062 * sleep some time, to demonstrate the handling of write times
2063 * doesn't depend on the time since the open
2067 /* get the initial times */
2068 GET_INFO_BOTH(finfo1,pinfo1);
2069 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
2072 * demonstrate that a truncate write always
2073 * updates the write time immediately
2075 for (i=0; i < 3; i++) {
2078 torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
2079 written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
2081 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
2085 /* get the times after the write */
2086 GET_INFO_BOTH(finfo2,pinfo2);
2087 COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
2091 start = timeval_current();
2092 end = timeval_add(&start, 7 * sec, 0);
2093 while (!timeval_expired(&end)) {
2095 torture_comment(tctx, "Do a write on the file handle\n");
2096 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2098 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2102 /* get the times after the write */
2103 GET_INFO_FILE(finfo2);
2105 if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
2106 double diff = timeval_elapsed(&start);
2107 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2108 "(1sec == %.2f) (wrong!)\n",
2116 GET_INFO_BOTH(finfo2,pinfo2);
2117 COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
2118 if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
2119 torture_comment(tctx, "Server did not update write_time (correct)\n");
2125 /* get the initial times */
2126 GET_INFO_BOTH(finfo1,pinfo1);
2127 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo2);
2130 * demonstrate that a truncate write always
2131 * updates the write time immediately
2133 for (i=0; i < 3; i++) {
2136 torture_comment(tctx, "Do a truncate write [%d] on the file handle\n", i);
2137 written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
2139 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 0", (int)written);
2143 /* get the times after the write */
2144 GET_INFO_BOTH(finfo2,pinfo2);
2145 COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
2152 GET_INFO_BOTH(finfo2,pinfo2);
2153 COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
2155 /* sure any further write doesn't update the write time */
2156 start = timeval_current();
2157 end = timeval_add(&start, 15 * sec, 0);
2158 while (!timeval_expired(&end)) {
2160 torture_comment(tctx, "Do a write on the file handle\n");
2161 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2163 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2167 /* get the times after the write */
2168 GET_INFO_BOTH(finfo2,pinfo2);
2170 if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
2171 double diff = timeval_elapsed(&start);
2172 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2173 "(1sec == %.2f) (wrong!)\n",
2181 GET_INFO_BOTH(finfo2,pinfo2);
2182 COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
2183 if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
2184 torture_comment(tctx, "Server did not update write_time (correct)\n");
2190 GET_INFO_BOTH(finfo3,pinfo3);
2191 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
2194 * the close updates the write time to the time of the close
2195 * and not to the time of the last write!
2197 torture_comment(tctx, "Close the file handle\n");
2198 smbcli_close(cli->tree, fnum1);
2201 GET_INFO_PATH(pinfo4);
2202 COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);
2204 if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
2205 torture_comment(tctx, "Server updated the write_time on close (correct)\n");
2210 smbcli_close(cli->tree, fnum1);
2211 smbcli_unlink(cli->tree, fname);
2212 smbcli_deltree(cli->tree, BASEDIR);
2218 * Show only the first write updates the timestamp, and a close
2219 * after writes updates to current (I think this is the same
2223 static bool test_delayed_write_update4(struct torture_context *tctx,
2224 struct smbcli_state *cli,
2225 struct smbcli_state *cli2)
2227 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4;
2228 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5;
2229 const char *fname = BASEDIR "\\torture_file4.txt";
2233 struct timeval start;
2235 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
2236 int normal_delay = 2000000;
2237 double sec = ((double)used_delay) / ((double)normal_delay);
2238 int msec = 1000 * sec;
2240 torture_comment(tctx, "\nRunning test_delayed_write_update4\n");
2242 if (!torture_setup_dir(cli, BASEDIR)) {
2246 torture_comment(tctx, "Open the file handle\n");
2247 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2250 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
2254 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2255 finfo0.basic_info.in.file.fnum = fnum1;
2260 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2261 pinfo0.basic_info.in.file.path = fname;
2268 /* get the initial times */
2269 GET_INFO_BOTH(finfo0,pinfo0);
2275 torture_comment(tctx, "Do a write on the file handle\n");
2276 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2278 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2283 GET_INFO_BOTH(finfo1,pinfo1);
2284 COMPARE_WRITE_TIME_EQUAL(finfo1,finfo0);
2287 * make sure the write time is updated 2 seconds later
2288 * calcuated from the first write
2289 * (but expect upto 3 seconds extra time for a busy server)
2291 start = timeval_current();
2292 end = timeval_add(&start, 5 * sec, 0);
2293 while (!timeval_expired(&end)) {
2294 /* get the times after the first write */
2295 GET_INFO_FILE(finfo1);
2297 if (finfo1.basic_info.out.write_time > finfo0.basic_info.out.write_time) {
2298 double diff = timeval_elapsed(&start);
2299 if (diff < (TIMEDELAY_SECS * sec * 0.75)) { /* 0.75 to cope with vmware timing */
2300 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2301 "(1sec == %.2f) (wrong!)\n",
2307 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2308 "(1sec == %.2f) (correct)\n",
2315 GET_INFO_BOTH(finfo1,pinfo1);
2316 COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0);
2318 /* sure any further write doesn't update the write time */
2319 start = timeval_current();
2320 end = timeval_add(&start, 15 * sec, 0);
2321 while (!timeval_expired(&end)) {
2323 torture_comment(tctx, "Do a write on the file handle\n");
2324 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2326 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2330 /* get the times after the write */
2331 GET_INFO_BOTH(finfo2,pinfo2);
2333 if (finfo2.basic_info.out.write_time > finfo1.basic_info.out.write_time) {
2334 double diff = timeval_elapsed(&start);
2335 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2336 "(1sec == %.2f) (wrong!)\n",
2344 GET_INFO_BOTH(finfo2,pinfo2);
2345 COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
2346 if (finfo2.basic_info.out.write_time == finfo1.basic_info.out.write_time) {
2347 torture_comment(tctx, "Server did not updatewrite_time (correct)\n");
2353 GET_INFO_BOTH(finfo3,pinfo3);
2354 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
2357 * the close updates the write time to the time of the close
2358 * and not to the time of the last write!
2360 torture_comment(tctx, "Close the file handle\n");
2361 smbcli_close(cli->tree, fnum1);
2364 GET_INFO_PATH(pinfo4);
2365 COMPARE_WRITE_TIME_GREATER(pinfo4, pinfo3);
2367 if (pinfo4.basic_info.out.write_time > pinfo3.basic_info.out.write_time) {
2368 torture_comment(tctx, "Server updated the write_time on close (correct)\n");
2373 smbcli_close(cli->tree, fnum1);
2374 smbcli_unlink(cli->tree, fname);
2375 smbcli_deltree(cli->tree, BASEDIR);
2381 * Show writes and closes have no effect on updating times once a SETWRITETIME is done.
2384 static bool test_delayed_write_update5(struct torture_context *tctx,
2385 struct smbcli_state *cli,
2386 struct smbcli_state *cli2)
2388 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
2389 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6;
2390 const char *fname = BASEDIR "\\torture_file5.txt";
2394 struct timeval start;
2396 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
2397 int normal_delay = 2000000;
2398 double sec = ((double)used_delay) / ((double)normal_delay);
2399 int msec = 1000 * sec;
2401 torture_comment(tctx, "\nRunning test_delayed_write_update5\n");
2403 if (!torture_setup_dir(cli, BASEDIR)) {
2407 torture_comment(tctx, "Open the file handle\n");
2408 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2411 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
2415 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2416 finfo0.basic_info.in.file.fnum = fnum1;
2422 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2423 pinfo0.basic_info.in.file.path = fname;
2431 /* get the initial times */
2432 GET_INFO_BOTH(finfo0,pinfo0);
2435 torture_comment(tctx, "Do a write on the file handle\n");
2436 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2438 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2443 GET_INFO_BOTH(finfo1,pinfo1);
2444 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
2446 torture_comment(tctx, "Set write time in the future on the file handle\n");
2447 SET_INFO_FILE(finfo0, time(NULL) + 86400);
2448 GET_INFO_BOTH(finfo2,pinfo2);
2449 COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
2451 torture_comment(tctx, "Set write time in the past on the file handle\n");
2452 SET_INFO_FILE(finfo0, time(NULL) - 86400);
2453 GET_INFO_BOTH(finfo2,pinfo2);
2454 COMPARE_WRITE_TIME_LESS(finfo2, finfo1);
2456 /* make sure the 2 second delay from the first write are canceled */
2457 start = timeval_current();
2458 end = timeval_add(&start, 15 * sec, 0);
2459 while (!timeval_expired(&end)) {
2461 /* get the times after the first write */
2462 GET_INFO_BOTH(finfo3,pinfo3);
2464 if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
2465 double diff = timeval_elapsed(&start);
2466 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2467 "(1sec == %.2f) (wrong!)\n",
2475 GET_INFO_BOTH(finfo3,pinfo3);
2476 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
2477 if (finfo3.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
2478 torture_comment(tctx, "Server did not update write_time (correct)\n");
2481 /* sure any further write doesn't update the write time */
2482 start = timeval_current();
2483 end = timeval_add(&start, 15 * sec, 0);
2484 while (!timeval_expired(&end)) {
2486 torture_comment(tctx, "Do a write on the file handle\n");
2487 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2489 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2493 /* get the times after the write */
2494 GET_INFO_BOTH(finfo4,pinfo4);
2496 if (finfo4.basic_info.out.write_time > finfo3.basic_info.out.write_time) {
2497 double diff = timeval_elapsed(&start);
2498 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2499 "(1sec == %.2f) (wrong!)\n",
2507 GET_INFO_BOTH(finfo4,pinfo4);
2508 COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
2509 if (finfo4.basic_info.out.write_time == finfo3.basic_info.out.write_time) {
2510 torture_comment(tctx, "Server did not update write_time (correct)\n");
2516 GET_INFO_BOTH(finfo5,pinfo5);
2517 COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
2520 * the close doesn't update the write time
2522 torture_comment(tctx, "Close the file handle\n");
2523 smbcli_close(cli->tree, fnum1);
2526 GET_INFO_PATH(pinfo6);
2527 COMPARE_WRITE_TIME_EQUAL(pinfo6, pinfo5);
2529 if (pinfo6.basic_info.out.write_time == pinfo5.basic_info.out.write_time) {
2530 torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
2535 smbcli_close(cli->tree, fnum1);
2536 smbcli_unlink(cli->tree, fname);
2537 smbcli_deltree(cli->tree, BASEDIR);
2543 * Show truncate writes and closes have no effect on updating times once a SETWRITETIME is done.
2546 static bool test_delayed_write_update5b(struct torture_context *tctx,
2547 struct smbcli_state *cli,
2548 struct smbcli_state *cli2)
2550 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
2551 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6;
2552 const char *fname = BASEDIR "\\torture_fileb.txt";
2556 struct timeval start;
2558 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
2559 int normal_delay = 2000000;
2560 double sec = ((double)used_delay) / ((double)normal_delay);
2561 int msec = 1000 * sec;
2563 torture_comment(tctx, "\nRunning test_delayed_write_update5b\n");
2565 if (!torture_setup_dir(cli, BASEDIR)) {
2569 torture_comment(tctx, "Open the file handle\n");
2570 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2573 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
2577 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2578 finfo0.basic_info.in.file.fnum = fnum1;
2584 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2585 pinfo0.basic_info.in.file.path = fname;
2593 /* get the initial times */
2594 GET_INFO_BOTH(finfo0,pinfo0);
2597 torture_comment(tctx, "Do a write on the file handle\n");
2598 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2600 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2605 GET_INFO_BOTH(finfo1,pinfo1);
2606 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
2608 torture_comment(tctx, "Set write time in the future on the file handle\n");
2609 SET_INFO_FILE(finfo0, time(NULL) + 86400);
2610 GET_INFO_BOTH(finfo2,pinfo2);
2611 COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
2613 torture_comment(tctx, "Set write time in the past on the file handle\n");
2614 SET_INFO_FILE(finfo0, time(NULL) - 86400);
2615 GET_INFO_BOTH(finfo2,pinfo2);
2616 COMPARE_WRITE_TIME_LESS(finfo2, finfo1);
2618 /* make sure the 2 second delay from the first write are canceled */
2619 start = timeval_current();
2620 end = timeval_add(&start, 15 * sec, 0);
2621 while (!timeval_expired(&end)) {
2623 /* get the times after the first write */
2624 GET_INFO_BOTH(finfo3,pinfo3);
2626 if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
2627 double diff = timeval_elapsed(&start);
2628 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2629 "(1sec == %.2f) (wrong!)\n",
2637 GET_INFO_BOTH(finfo3,pinfo3);
2638 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
2639 if (finfo3.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
2640 torture_comment(tctx, "Server did not update write_time (correct)\n");
2643 /* Do any further write (truncates) update the write time ? */
2644 start = timeval_current();
2645 end = timeval_add(&start, 15 * sec, 0);
2646 while (!timeval_expired(&end)) {
2648 torture_comment(tctx, "Do a truncate write on the file handle\n");
2649 written = smbcli_smbwrite(cli->tree, fnum1, "x", 1024, 0);
2651 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2655 /* get the times after the write */
2656 GET_INFO_BOTH(finfo4,pinfo4);
2658 if (finfo4.basic_info.out.write_time > finfo3.basic_info.out.write_time) {
2659 double diff = timeval_elapsed(&start);
2660 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2661 "(1sec == %.2f) (wrong!)\n",
2669 GET_INFO_BOTH(finfo4,pinfo4);
2670 COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
2671 if (finfo4.basic_info.out.write_time == finfo3.basic_info.out.write_time) {
2672 torture_comment(tctx, "Server did not update write_time (correct)\n");
2678 GET_INFO_BOTH(finfo5,pinfo5);
2679 COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
2682 * the close doesn't update the write time
2684 torture_comment(tctx, "Close the file handle\n");
2685 smbcli_close(cli->tree, fnum1);
2688 GET_INFO_PATH(pinfo6);
2689 COMPARE_WRITE_TIME_EQUAL(pinfo6, pinfo5);
2691 if (pinfo6.basic_info.out.write_time == pinfo5.basic_info.out.write_time) {
2692 torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
2697 smbcli_close(cli->tree, fnum1);
2698 smbcli_unlink(cli->tree, fname);
2699 smbcli_deltree(cli->tree, BASEDIR);
2705 * Open 2 handles on a file. Write one one and then set the
2706 * WRITE TIME explicitly on the other. Ensure the write time
2707 * update is cancelled. Ensure the write time is updated to
2708 * the close time when the non-explicit set handle is closed.
2712 static bool test_delayed_write_update6(struct torture_context *tctx,
2713 struct smbcli_state *cli,
2714 struct smbcli_state *cli2)
2716 union smb_fileinfo finfo0, finfo1, finfo2, finfo3, finfo4, finfo5;
2717 union smb_fileinfo pinfo0, pinfo1, pinfo2, pinfo3, pinfo4, pinfo5, pinfo6, pinfo7;
2718 const char *fname = BASEDIR "\\torture_file6.txt";
2723 struct timeval start;
2725 int used_delay = torture_setting_int(tctx, "writetimeupdatedelay", 2000000);
2726 int normal_delay = 2000000;
2727 double sec = ((double)used_delay) / ((double)normal_delay);
2728 int msec = 1000 * sec;
2731 torture_comment(tctx, "\nRunning test_delayed_write_update6\n");
2733 if (!torture_setup_dir(cli, BASEDIR)) {
2737 torture_comment(tctx, "Open the file handle\n");
2738 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2741 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
2746 torture_comment(tctx, "Open the 2nd file handle on 2nd connection\n");
2747 fnum2 = smbcli_open(cli2->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2750 torture_result(tctx, TORTURE_FAIL, __location__": unable to open %s", fname);
2755 finfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2756 finfo0.basic_info.in.file.fnum = fnum1;
2762 pinfo0.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2763 pinfo0.basic_info.in.file.path = fname;
2772 /* get the initial times */
2773 GET_INFO_BOTH(finfo0,pinfo0);
2776 torture_comment(tctx, "Do a write on the file handle\n");
2777 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2779 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2784 GET_INFO_BOTH(finfo1,pinfo1);
2785 COMPARE_WRITE_TIME_EQUAL(finfo1, finfo0);
2787 torture_comment(tctx, "Set write time in the future on the 2nd file handle\n");
2788 SET_INFO_FILE_EX(finfo0, time(NULL) + 86400, cli2->tree, fnum2);
2789 GET_INFO_BOTH(finfo2,pinfo2);
2790 COMPARE_WRITE_TIME_GREATER(finfo2, finfo1);
2792 torture_comment(tctx, "Set write time in the past on the 2nd file handle\n");
2793 SET_INFO_FILE_EX(finfo0, time(NULL) - 86400, cli2->tree, fnum2);
2794 GET_INFO_BOTH(finfo2,pinfo2);
2795 COMPARE_WRITE_TIME_LESS(finfo2, finfo1);
2797 /* make sure the 2 second delay from the first write are canceled */
2798 start = timeval_current();
2799 end = timeval_add(&start, 15 * sec, 0);
2800 while (!timeval_expired(&end)) {
2802 /* get the times after the first write */
2803 GET_INFO_BOTH(finfo3,pinfo3);
2805 if (finfo3.basic_info.out.write_time > finfo2.basic_info.out.write_time) {
2806 double diff = timeval_elapsed(&start);
2807 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2808 "(1sec == %.2f) (wrong!)\n",
2816 GET_INFO_BOTH(finfo3,pinfo3);
2817 COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
2818 if (finfo3.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
2819 torture_comment(tctx, "Server did not update write_time (correct)\n");
2822 /* sure any further write doesn't update the write time */
2823 start = timeval_current();
2824 end = timeval_add(&start, 15 * sec, 0);
2825 while (!timeval_expired(&end)) {
2827 torture_comment(tctx, "Do a write on the file handle\n");
2828 written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
2830 torture_result(tctx, TORTURE_FAIL, __location__": written gave %d - should have been 1", (int)written);
2834 /* get the times after the write */
2835 GET_INFO_BOTH(finfo4,pinfo4);
2837 if (finfo4.basic_info.out.write_time > finfo3.basic_info.out.write_time) {
2838 double diff = timeval_elapsed(&start);
2839 torture_comment(tctx, "Server updated write_time after %.2f seconds "
2840 "(1sec == %.2f) (wrong!)\n",
2848 GET_INFO_BOTH(finfo4,pinfo4);
2849 COMPARE_WRITE_TIME_EQUAL(finfo4, finfo3);
2850 if (finfo4.basic_info.out.write_time == finfo3.basic_info.out.write_time) {
2851 torture_comment(tctx, "Server did not update write_time (correct)\n");
2857 GET_INFO_BOTH(finfo5,pinfo5);
2858 COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
2861 * the close updates the write time to the time of the close
2862 * as the write time was set on the 2nd handle
2864 torture_comment(tctx, "Close the file handle\n");
2865 smbcli_close(cli->tree, fnum1);
2868 GET_INFO_PATH(pinfo6);
2869 COMPARE_WRITE_TIME_GREATER(pinfo6, pinfo5);
2871 if (pinfo6.basic_info.out.write_time > pinfo5.basic_info.out.write_time) {
2872 torture_comment(tctx, "Server updated the write_time on close (correct)\n");
2875 /* keep the 2nd handle open and rerun tests */
2882 * closing the 2nd handle will cause no write time update
2883 * as the write time was explicit set on this handle
2885 torture_comment(tctx, "Close the 2nd file handle\n");
2886 smbcli_close(cli2->tree, fnum2);
2889 GET_INFO_PATH(pinfo7);
2890 COMPARE_WRITE_TIME_EQUAL(pinfo7, pinfo6);
2892 if (pinfo7.basic_info.out.write_time == pinfo6.basic_info.out.write_time) {
2893 torture_comment(tctx, "Server did not update the write_time on close (correct)\n");
2898 smbcli_close(cli->tree, fnum1);
2900 smbcli_close(cli2->tree, fnum2);
2901 smbcli_unlink(cli->tree, fname);
2902 smbcli_deltree(cli->tree, BASEDIR);
2907 static bool test_delayed_write_update7(struct torture_context *tctx, struct smbcli_state *cli)
2909 union smb_open open_parms;
2910 union smb_fileinfo finfo1, finfo2, finfo3;
2911 const char *fname = BASEDIR "\\torture_file7.txt";
2915 TALLOC_CTX *mem_ctx;
2917 torture_comment(tctx, "\nRunning test_delayed_write_update7 (timestamp resolution test)\n");
2919 mem_ctx = talloc_init("test_delayed_write_update7");
2920 if (!mem_ctx) return false;
2922 ZERO_STRUCT(finfo1);
2923 ZERO_STRUCT(finfo2);
2924 ZERO_STRUCT(finfo3);
2925 ZERO_STRUCT(open_parms);
2927 if (!torture_setup_dir(cli, BASEDIR)) {
2931 /* Create the file. */
2932 fnum1 = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
2934 torture_result(tctx, TORTURE_FAIL, "Failed to open %s", fname);
2938 finfo1.basic_info.level = RAW_FILEINFO_BASIC_INFO;
2939 finfo1.basic_info.in.file.fnum = fnum1;
2943 /* Get the initial timestamps. */
2944 status = smb_raw_fileinfo(cli->tree, tctx, &finfo1);
2946 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
2948 /* Set the pending write time to a value with ns. */
2949 SET_INFO_FILE_NS(finfo, time(NULL) + 86400, 103, cli->tree, fnum1);
2951 /* Get the current pending write time by fnum. */
2952 status = smb_raw_fileinfo(cli->tree, tctx, &finfo2);
2954 torture_assert_ntstatus_ok(tctx, status, "fileinfo failed");
2956 /* Ensure the time is actually different. */
2957 if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
2958 torture_result(tctx, TORTURE_FAIL,
2959 "setfileinfo time matches original fileinfo time");
2963 /* Get the current pending write time by path. */
2964 finfo3.basic_info.in.file.path = fname;
2965 status = smb_raw_pathinfo(cli->tree, tctx, &finfo3);
2967 if (finfo2.basic_info.out.write_time != finfo3.basic_info.out.write_time) {
2968 torture_result(tctx, TORTURE_FAIL,
2969 "qpathinfo time doens't match fileinfo time");
2973 /* Now close the file. Re-open and check that the write
2974 time is identical to the one we wrote. */
2976 smbcli_close(cli->tree, fnum1);
2978 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
2979 open_parms.ntcreatex.in.flags = 0;
2980 open_parms.ntcreatex.in.access_mask = SEC_GENERIC_READ;
2981 open_parms.ntcreatex.in.file_attr = 0;
2982 open_parms.ntcreatex.in.share_access = NTCREATEX_SHARE_ACCESS_DELETE|
2983 NTCREATEX_SHARE_ACCESS_READ|
2984 NTCREATEX_SHARE_ACCESS_WRITE;
2985 open_parms.ntcreatex.in.open_disposition = NTCREATEX_DISP_OPEN;
2986 open_parms.ntcreatex.in.create_options = 0;
2987 open_parms.ntcreatex.in.fname = fname;
2989 status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
2990 talloc_free(mem_ctx);
2992 if (!NT_STATUS_IS_OK(status)) {
2993 torture_result(tctx, TORTURE_FAIL,
2994 "setfileinfo time matches original fileinfo time");
2998 fnum1 = open_parms.ntcreatex.out.file.fnum;
3000 /* Check the returned time matches. */
3001 if (open_parms.ntcreatex.out.write_time != finfo2.basic_info.out.write_time) {
3002 torture_result(tctx, TORTURE_FAIL,
3003 "final open time does not match set time");
3009 smbcli_close(cli->tree, fnum1);
3011 smbcli_unlink(cli->tree, fname);
3012 smbcli_deltree(cli->tree, BASEDIR);
3017 testing of delayed update of write_time
3019 struct torture_suite *torture_delay_write(void)
3021 struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "DELAYWRITE");
3023 torture_suite_add_2smb_test(suite, "finfo update on close", test_finfo_after_write);
3024 torture_suite_add_1smb_test(suite, "delayed update of write time", test_delayed_write_update);
3025 torture_suite_add_1smb_test(suite, "update of write time and SMBwrite truncate", test_delayed_write_update1);
3026 torture_suite_add_1smb_test(suite, "update of write time and SMBwrite truncate expand", test_delayed_write_update1a);
3027 torture_suite_add_1smb_test(suite, "update of write time using SET_END_OF_FILE", test_delayed_write_update1b);
3028 torture_suite_add_1smb_test(suite, "update of write time using SET_ALLOCATION_SIZE", test_delayed_write_update1c);
3029 torture_suite_add_2smb_test(suite, "delayed update of write time using 2 connections", test_delayed_write_update2);
3030 torture_suite_add_2smb_test(suite, "delayed update of write time 3", test_delayed_write_update3);
3031 torture_suite_add_2smb_test(suite, "delayed update of write time 3a", test_delayed_write_update3a);
3032 torture_suite_add_2smb_test(suite, "delayed update of write time 3b", test_delayed_write_update3b);
3033 torture_suite_add_2smb_test(suite, "delayed update of write time 3c", test_delayed_write_update3c);
3034 torture_suite_add_2smb_test(suite, "delayed update of write time 4", test_delayed_write_update4);
3035 torture_suite_add_2smb_test(suite, "delayed update of write time 5", test_delayed_write_update5);
3036 torture_suite_add_2smb_test(suite, "delayed update of write time 5b", test_delayed_write_update5b);
3037 torture_suite_add_2smb_test(suite, "delayed update of write time 6", test_delayed_write_update6);
3038 torture_suite_add_1smb_test(suite, "timestamp resolution test", test_delayed_write_update7);
3039 torture_suite_add_1smb_test(suite, "timestamp resolution test", test_delayed_write_update7);