2004-11-12 12:37:59 +03:00
/*
Unix SMB / CIFS implementation .
test suite for delayed write update
Copyright ( C ) Volker Lendecke 2004
Copyright ( C ) Andrew Tridgell 2004
2004-11-20 04:51:32 +03:00
Copyright ( C ) Jeremy Allison 2004
2004-11-12 12:37:59 +03:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-11-12 12:37:59 +03:00
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-11-12 12:37:59 +03:00
*/
# include "includes.h"
2006-01-03 16:41:17 +03:00
# include "torture/torture.h"
2004-11-12 12:37:59 +03:00
# include "libcli/raw/libcliraw.h"
2008-04-02 06:53:27 +04:00
# include "libcli/raw/raw_proto.h"
2004-11-12 12:37:59 +03:00
# include "system/time.h"
2005-02-10 08:09:35 +03:00
# include "system/filesys.h"
2006-01-03 18:40:05 +03:00
# include "libcli/libcli.h"
2006-03-17 20:59:58 +03:00
# include "torture/util.h"
2011-03-19 02:42:52 +03:00
# include "torture/basic/proto.h"
2004-11-12 12:37:59 +03:00
# define BASEDIR "\\delaywrite"
2007-10-07 02:28:14 +04:00
static bool test_delayed_write_update ( struct torture_context * tctx , struct smbcli_state * cli )
2004-11-12 12:37:59 +03:00
{
union smb_fileinfo finfo1 , finfo2 ;
const char * fname = BASEDIR " \\ torture_file.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
2007-10-07 02:28:14 +04:00
bool ret = true ;
2004-11-12 12:37:59 +03:00
ssize_t written ;
2008-04-08 12:25:51 +04:00
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-04-08 12:25:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2004-11-12 12:37:59 +03:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2004-11-12 12:37:59 +03:00
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
2014-10-02 17:19:49 +04:00
torture_assert_int_not_equal ( tctx , fnum1 , - 1 , talloc_asprintf ( tctx ,
" Failed to open %s " , fname ) ) ;
2004-11-12 12:37:59 +03:00
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo1 . basic_info . in . file . fnum = fnum1 ;
2004-11-12 12:37:59 +03:00
finfo2 = finfo1 ;
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2014-10-02 17:17:13 +04:00
torture_comment ( tctx , " Initial write time %s \n " ,
nt_time_string ( tctx , finfo1 . basic_info . out . write_time ) ) ;
2004-11-12 12:37:59 +03:00
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
2014-10-02 17:19:49 +04:00
torture_assert_int_equal ( tctx , written , 1 ,
" unexpected number of bytes written " ) ;
2004-11-12 12:37:59 +03:00
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
2014-06-20 14:28:52 +04:00
end = timeval_add ( & start , ( 120 * sec ) , 0 ) ;
2008-04-08 12:25:51 +04:00
while ( ! timeval_expired ( & end ) ) {
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2004-11-12 12:37:59 +03:00
2014-10-02 17:19:49 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2014-10-02 17:17:13 +04:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2014-10-02 17:19:49 +04:00
if ( finfo1 . basic_info . out . write_time ! =
finfo2 . basic_info . out . write_time )
{
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-10-02 17:19:49 +04:00
torture_assert ( tctx ,
diff > = ( used_delay / ( double ) 1000000 ) ,
talloc_asprintf ( tctx ,
" Server updated write_time after %.2f "
" seconds (expected >= %.2f) \n " ,
diff , used_delay / ( double ) 1000000 ) ) ;
2007-12-01 13:39:39 +03:00
2014-06-20 14:28:50 +04:00
torture_comment ( tctx , " Server updated write_time after %.2f seconds (correct) \n " ,
diff ) ;
2004-11-12 12:37:59 +03:00
break ;
}
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2004-11-12 12:37:59 +03:00
}
2014-10-02 17:19:49 +04:00
torture_assert_u64_not_equal ( tctx ,
finfo2 . basic_info . out . write_time ,
finfo1 . basic_info . out . write_time ,
" Server did not update write time within "
" 120 seconds " ) ;
2004-11-12 12:37:59 +03:00
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-08 10:31:34 +04:00
static bool test_delayed_write_update1 ( struct torture_context * tctx , struct smbcli_state * cli )
{
union smb_fileinfo finfo1 , finfo2 , finfo3 , pinfo4 ;
const char * fname = BASEDIR " \\ torture_file1.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-08 10:31:34 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
char buf [ 2048 ] ;
2014-10-02 18:11:27 +04:00
bool first ;
bool updated ;
2008-09-08 10:31:34 +04:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update1 \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-08 10:31:34 +04:00
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
2014-10-02 17:35:09 +04:00
torture_assert_int_not_equal ( tctx , fnum1 , - 1 , talloc_asprintf ( tctx ,
" Failed to open %s " , fname ) ) ;
2008-09-08 10:31:34 +04:00
memset ( buf , ' x ' , 2048 ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , buf , 0 , 2048 ) ;
/* 3 second delay to ensure we get past any 2 second time
granularity ( older systems may have that ) */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2008-09-08 10:31:34 +04:00
finfo1 . all_info . level = RAW_FILEINFO_ALL_INFO ;
finfo1 . all_info . in . file . fnum = fnum1 ;
finfo2 = finfo1 ;
finfo3 = finfo1 ;
pinfo4 . all_info . level = RAW_FILEINFO_ALL_INFO ;
pinfo4 . all_info . in . file . path = fname ;
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 18:32:41 +04:00
torture_assert_u64_equal ( tctx , finfo1 . all_info . out . size , 2048 ,
" file size not as expected after write(2048) " ) ;
2014-10-02 17:25:34 +04:00
torture_comment ( tctx , " Initial write time %s \n " ,
nt_time_string ( tctx , finfo1 . all_info . out . write_time ) ) ;
2008-09-08 10:31:34 +04:00
2009-11-06 02:37:26 +03:00
/* 3 second delay to ensure we get past any 2 second time
granularity ( older systems may have that ) */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2009-11-06 02:37:26 +03:00
2008-09-08 10:31:34 +04:00
/* Do a zero length SMBwrite call to truncate. */
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 1024 , 0 ) ;
2014-10-02 17:35:09 +04:00
torture_assert_int_equal ( tctx , written , 0 ,
" unexpected number of bytes written " ) ;
2008-09-08 10:31:34 +04:00
start = timeval_current ( ) ;
2014-06-20 14:28:52 +04:00
end = timeval_add ( & start , ( 120 * sec ) , 0 ) ;
2014-10-02 18:11:27 +04:00
first = true ;
updated = false ;
2008-09-08 10:31:34 +04:00
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2014-10-02 17:35:09 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 17:35:09 +04:00
torture_assert_u64_equal ( tctx , finfo2 . all_info . out . size , 1024 ,
" file not truncated to expected size "
" (1024) " ) ;
2008-09-08 10:31:34 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 17:25:34 +04:00
nt_time_string ( tctx , finfo2 . all_info . out . write_time ) ) ;
2014-10-02 18:11:27 +04:00
if ( finfo1 . all_info . out . write_time ! =
finfo2 . all_info . out . write_time )
{
updated = true ;
2008-09-08 10:31:34 +04:00
break ;
}
2014-10-02 18:11:27 +04:00
2008-09-08 10:31:34 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2014-10-02 18:11:27 +04:00
first = false ;
2008-09-08 10:31:34 +04:00
}
2014-10-02 18:11:27 +04:00
torture_assert ( tctx , updated ,
" Server did not update write time within 120 seconds " ) ;
torture_assert ( tctx , first , talloc_asprintf ( tctx ,
" Server did not update write time immediately but only "
" after %.2f seconds! " , timeval_elapsed ( & start ) ) ) ;
torture_comment ( tctx , " Server updated write time immediately. Good! \n " ) ;
2008-09-08 10:31:34 +04:00
2009-08-25 05:21:23 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2009-08-25 05:21:23 +04:00
2008-09-08 10:31:34 +04:00
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 0 , 1 ) ;
2014-10-02 17:35:09 +04:00
torture_assert_int_equal ( tctx , written , 1 ,
" unexpected number of bytes written " ) ;
2008-09-08 10:31:34 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 10 * sec ) , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo3 ) ;
2014-10-02 17:35:09 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 17:35:09 +04:00
torture_assert_u64_equal ( tctx , finfo3 . all_info . out . size , 1024 ,
" file not truncated to expected size "
" (1024) " ) ;
2008-09-08 10:31:34 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 17:25:34 +04:00
nt_time_string ( tctx , finfo3 . all_info . out . write_time ) ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 17:58:05 +04:00
torture_assert_u64_equal ( tctx ,
finfo3 . all_info . out . write_time ,
finfo2 . all_info . out . write_time ,
talloc_asprintf ( tctx ,
" Server updated write time "
" after %.2f seconds (wrong!) " ,
timeval_elapsed ( & start ) ) ) ;
2008-09-08 10:31:34 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 10:31:34 +04:00
}
2014-10-02 17:58:05 +04:00
torture_comment ( tctx , " Server did not update write time within 10 "
" seconds. Good! \n " ) ;
2008-09-08 10:31:34 +04:00
2009-11-06 02:37:26 +03:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2009-11-06 02:37:26 +03:00
2008-09-08 10:31:34 +04:00
/* the close should trigger an write time update */
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
status = smb_raw_pathinfo ( cli - > tree , tctx , & pinfo4 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " pathinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 17:35:09 +04:00
torture_assert_u64_not_equal ( tctx ,
pinfo4 . all_info . out . write_time ,
finfo3 . all_info . out . write_time ,
" Server did not update write time on "
" close (wrong!) " ) ;
2014-10-02 17:52:57 +04:00
torture_assert ( tctx ,
pinfo4 . all_info . out . write_time > finfo3 . all_info . out . write_time ,
" Server updated write time on close, but to an earlier point "
" in time " ) ;
torture_comment ( tctx , " Server updated write time on close (correct) \n " ) ;
2008-09-08 10:31:34 +04:00
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-06 01:24:36 +04:00
/* Updating with a SMBwrite of zero length
* changes the write time immediately - even on expand . */
static bool test_delayed_write_update1a ( struct torture_context * tctx , struct smbcli_state * cli )
{
2008-09-08 10:31:34 +04:00
union smb_fileinfo finfo1 , finfo2 , finfo3 , pinfo4 ;
2008-09-06 01:24:36 +04:00
const char * fname = BASEDIR " \\ torture_file1a.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-06 01:24:36 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
char buf [ 2048 ] ;
2014-10-02 15:56:43 +04:00
bool first ;
bool updated ;
2008-09-06 01:24:36 +04:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update1a \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-06 01:24:36 +04:00
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
2014-10-02 15:37:02 +04:00
torture_assert_int_not_equal ( tctx , fnum1 , - 1 , talloc_asprintf ( tctx ,
" Failed to open %s " , fname ) ) ;
2008-09-06 01:24:36 +04:00
memset ( buf , ' x ' , 2048 ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , buf , 0 , 2048 ) ;
/* 3 second delay to ensure we get past any 2 second time
granularity ( older systems may have that ) */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2008-09-06 01:24:36 +04:00
finfo1 . all_info . level = RAW_FILEINFO_ALL_INFO ;
finfo1 . all_info . in . file . fnum = fnum1 ;
finfo2 = finfo1 ;
2008-09-08 10:31:34 +04:00
finfo3 = finfo1 ;
pinfo4 . all_info . level = RAW_FILEINFO_ALL_INFO ;
pinfo4 . all_info . in . file . path = fname ;
2008-09-06 01:24:36 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-06 01:24:36 +04:00
2014-10-02 18:33:13 +04:00
torture_assert_u64_equal ( tctx , finfo1 . all_info . out . size , 2048 ,
" file size not as expected after write(2048) " ) ;
2014-10-02 15:32:59 +04:00
torture_comment ( tctx , " Initial write time %s \n " ,
nt_time_string ( tctx , finfo1 . all_info . out . write_time ) ) ;
2008-09-06 01:24:36 +04:00
/* Do a zero length SMBwrite call to truncate. */
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 10240 , 0 ) ;
2014-10-02 15:37:02 +04:00
torture_assert_int_equal ( tctx , written , 0 ,
" unexpected number of bytes written " ) ;
2008-09-06 01:24:36 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 120 * sec ) , 0 ) ;
2014-10-02 15:56:43 +04:00
first = true ;
updated = false ;
2008-09-06 01:24:36 +04:00
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2014-10-02 15:37:02 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-06 01:24:36 +04:00
2014-10-02 15:37:02 +04:00
torture_assert_u64_equal ( tctx , finfo2 . all_info . out . size , 10240 ,
" file not truncated to expected size "
" (10240) " ) ;
2008-09-06 01:24:36 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 15:32:59 +04:00
nt_time_string ( tctx , finfo2 . all_info . out . write_time ) ) ;
2014-10-02 15:37:02 +04:00
2014-10-02 15:56:43 +04:00
if ( finfo1 . all_info . out . write_time ! =
finfo2 . all_info . out . write_time )
{
updated = true ;
2008-09-06 01:24:36 +04:00
break ;
}
2014-10-02 15:56:43 +04:00
2008-09-06 01:24:36 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2014-10-02 15:56:43 +04:00
first = false ;
2008-09-06 01:24:36 +04:00
}
2014-10-02 15:56:43 +04:00
torture_assert ( tctx , updated ,
" Server did not update write time within 120 seconds " ) ;
torture_assert ( tctx , first , talloc_asprintf ( tctx ,
" Server did not update write time immediately but only "
" after %.2f seconds! " , timeval_elapsed ( & start ) ) ) ;
torture_comment ( tctx , " Server updated write time immediately. Good! \n " ) ;
2008-09-06 01:24:36 +04:00
2009-08-25 05:21:23 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2009-08-25 05:21:23 +04:00
2008-09-08 10:31:34 +04:00
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 0 , 1 ) ;
2014-10-02 15:32:59 +04:00
torture_assert_int_equal ( tctx , written , 1 ,
" unexpected number of bytes written " ) ;
2008-09-08 10:31:34 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 10 * sec ) , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo3 ) ;
2014-10-02 15:37:02 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 15:37:02 +04:00
torture_assert_u64_equal ( tctx , finfo3 . all_info . out . size , 10240 ,
" file not truncated to expected size "
" (10240) " ) ;
2008-09-08 10:31:34 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 15:32:59 +04:00
nt_time_string ( tctx , finfo3 . all_info . out . write_time ) ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 15:46:29 +04:00
torture_assert_u64_equal ( tctx ,
finfo3 . all_info . out . write_time ,
finfo2 . all_info . out . write_time ,
talloc_asprintf ( tctx ,
" Server updated write time "
" after %.2f seconds (wrong!) " ,
timeval_elapsed ( & start ) ) ) ;
2008-09-08 10:31:34 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 10:31:34 +04:00
}
2014-10-02 15:46:29 +04:00
torture_comment ( tctx , " Server did not update write time within 10 "
" seconds. Good! \n " ) ;
2008-09-08 10:31:34 +04:00
/* the close should trigger an write time update */
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
status = smb_raw_pathinfo ( cli - > tree , tctx , & pinfo4 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " pathinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 15:37:02 +04:00
torture_assert_u64_not_equal ( tctx ,
pinfo4 . all_info . out . write_time ,
finfo3 . all_info . out . write_time ,
" Server did not update write time on "
" close (wrong!) " ) ;
2014-10-02 17:49:07 +04:00
torture_assert ( tctx ,
pinfo4 . all_info . out . write_time > finfo3 . all_info . out . write_time ,
" Server updated write time on close, but to an earlier point "
" in time " ) ;
torture_comment ( tctx , " Server updated write time on close (correct) \n " ) ;
2008-09-06 01:24:36 +04:00
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
/* Updating with a SET_FILE_END_OF_FILE_INFO
* changes the write time immediately - even on expand . */
static bool test_delayed_write_update1b ( struct torture_context * tctx , struct smbcli_state * cli )
{
2008-09-08 10:31:34 +04:00
union smb_fileinfo finfo1 , finfo2 , finfo3 , pinfo4 ;
2008-09-06 01:24:36 +04:00
const char * fname = BASEDIR " \\ torture_file1b.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-06 01:24:36 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
char buf [ 2048 ] ;
2014-10-02 18:48:40 +04:00
bool first ;
bool updated ;
2008-09-06 01:24:36 +04:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update1b \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-06 01:24:36 +04:00
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
2014-10-02 18:40:26 +04:00
torture_assert_int_not_equal ( tctx , fnum1 , - 1 , talloc_asprintf ( tctx ,
" Failed to open %s " , fname ) ) ;
2008-09-06 01:24:36 +04:00
memset ( buf , ' x ' , 2048 ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , buf , 0 , 2048 ) ;
/* 3 second delay to ensure we get past any 2 second time
granularity ( older systems may have that ) */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2008-09-06 01:24:36 +04:00
finfo1 . all_info . level = RAW_FILEINFO_ALL_INFO ;
finfo1 . all_info . in . file . fnum = fnum1 ;
finfo2 = finfo1 ;
2008-09-08 10:31:34 +04:00
finfo3 = finfo1 ;
pinfo4 . all_info . level = RAW_FILEINFO_ALL_INFO ;
pinfo4 . all_info . in . file . path = fname ;
2008-09-06 01:24:36 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-06 01:24:36 +04:00
2014-10-02 18:53:26 +04:00
torture_assert_u64_equal ( tctx , finfo1 . all_info . out . size , 2048 ,
" file size not as expected after write(2048) " ) ;
2008-09-06 01:24:36 +04:00
torture_comment ( tctx , " Initial write time %s \n " ,
2014-10-02 18:34:19 +04:00
nt_time_string ( tctx , finfo1 . all_info . out . write_time ) ) ;
2008-09-06 01:24:36 +04:00
/* Do a SET_END_OF_FILE_INFO call to truncate. */
status = smbcli_ftruncate ( cli - > tree , fnum1 , ( uint64_t ) 10240 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " SET_END_OF_FILE failed " ) ;
2008-09-06 01:24:36 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 120 * sec ) , 0 ) ;
2014-10-02 18:48:40 +04:00
first = true ;
updated = false ;
2008-09-06 01:24:36 +04:00
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2014-10-02 18:40:26 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-06 01:24:36 +04:00
2014-10-02 18:40:26 +04:00
torture_assert_u64_equal ( tctx , finfo2 . all_info . out . size , 10240 ,
" file not truncated to expected size "
" (10240) " ) ;
2008-09-06 01:24:36 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 18:34:19 +04:00
nt_time_string ( tctx , finfo2 . all_info . out . write_time ) ) ;
2014-10-02 18:48:40 +04:00
if ( finfo1 . all_info . out . write_time ! =
finfo2 . all_info . out . write_time )
{
updated = true ;
2008-09-06 01:24:36 +04:00
break ;
}
2014-10-02 18:48:40 +04:00
2008-09-06 01:24:36 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2014-10-02 18:48:40 +04:00
first = false ;
2008-09-06 01:24:36 +04:00
}
2014-10-02 18:48:40 +04:00
torture_assert ( tctx , updated ,
" Server did not update write time within 120 seconds " ) ;
torture_assert ( tctx , first , talloc_asprintf ( tctx ,
" Server did not update write time immediately but only "
" after %.2f seconds! " , timeval_elapsed ( & start ) ) ) ;
torture_comment ( tctx , " Server updated write time immediately. Good! \n " ) ;
2008-09-06 01:24:36 +04:00
2009-08-25 05:21:23 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2009-08-25 05:21:23 +04:00
2008-09-08 10:31:34 +04:00
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 0 , 1 ) ;
2014-10-02 18:34:19 +04:00
torture_assert_int_equal ( tctx , written , 1 ,
" unexpected number of bytes written " ) ;
2008-09-08 10:31:34 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 10 * sec ) , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo3 ) ;
2014-10-02 18:40:26 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 18:40:26 +04:00
torture_assert_u64_equal ( tctx , finfo3 . all_info . out . size , 10240 ,
" file not truncated to expected size "
" (10240) " ) ;
2008-09-08 10:31:34 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 18:34:19 +04:00
nt_time_string ( tctx , finfo3 . all_info . out . write_time ) ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 18:46:18 +04:00
torture_assert_u64_equal ( tctx ,
finfo3 . all_info . out . write_time ,
finfo2 . all_info . out . write_time ,
talloc_asprintf ( tctx ,
" Server updated write time "
" after %.2f seconds (wrong!) " ,
timeval_elapsed ( & start ) ) ) ;
2008-09-08 10:31:34 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 10:31:34 +04:00
}
2014-10-02 18:46:18 +04:00
torture_comment ( tctx , " Server did not update write time within 10 "
" seconds. Good! \n " ) ;
2008-09-08 10:31:34 +04:00
/* the close should trigger an write time update */
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
status = smb_raw_pathinfo ( cli - > tree , tctx , & pinfo4 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " pathinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 18:40:26 +04:00
torture_assert_u64_not_equal ( tctx ,
pinfo4 . all_info . out . write_time ,
finfo3 . all_info . out . write_time ,
" Server did not update write time on "
" close (wrong!) " ) ;
2014-10-02 18:44:34 +04:00
torture_assert ( tctx ,
pinfo4 . all_info . out . write_time > finfo3 . all_info . out . write_time ,
" Server updated write time on close, but to an earlier point "
" in time " ) ;
torture_comment ( tctx , " Server updated write time on close (correct) \n " ) ;
2008-09-06 01:24:36 +04:00
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
/* Updating with a SET_ALLOCATION_INFO (truncate) does so immediately. */
static bool test_delayed_write_update1c ( struct torture_context * tctx , struct smbcli_state * cli )
{
union smb_setfileinfo parms ;
2008-09-08 10:31:34 +04:00
union smb_fileinfo finfo1 , finfo2 , finfo3 , pinfo4 ;
2008-09-06 01:24:36 +04:00
const char * fname = BASEDIR " \\ torture_file1c.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-06 01:24:36 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
char buf [ 2048 ] ;
2014-10-02 19:15:04 +04:00
bool first ;
bool updated ;
2008-09-06 01:24:36 +04:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update1c \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-06 01:24:36 +04:00
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
2014-10-02 19:08:12 +04:00
torture_assert_int_not_equal ( tctx , fnum1 , - 1 , talloc_asprintf ( tctx ,
" Failed to open %s " , fname ) ) ;
2008-09-06 01:24:36 +04:00
memset ( buf , ' x ' , 2048 ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , buf , 0 , 2048 ) ;
/* 3 second delay to ensure we get past any 2 second time
granularity ( older systems may have that ) */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2008-09-06 01:24:36 +04:00
finfo1 . all_info . level = RAW_FILEINFO_ALL_INFO ;
finfo1 . all_info . in . file . fnum = fnum1 ;
finfo2 = finfo1 ;
2008-09-08 10:31:34 +04:00
finfo3 = finfo1 ;
pinfo4 . all_info . level = RAW_FILEINFO_ALL_INFO ;
pinfo4 . all_info . in . file . path = fname ;
2008-09-06 01:24:36 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-06 01:24:36 +04:00
2014-10-02 19:10:32 +04:00
torture_assert_u64_equal ( tctx , finfo1 . all_info . out . size , 2048 ,
" file size not as expected after write(2048) " ) ;
2008-09-06 01:24:36 +04:00
torture_comment ( tctx , " Initial write time %s \n " ,
2014-10-02 19:02:38 +04:00
nt_time_string ( tctx , finfo1 . all_info . out . write_time ) ) ;
2008-09-06 01:24:36 +04:00
/* Do a SET_ALLOCATION_SIZE call to truncate. */
parms . allocation_info . level = RAW_SFILEINFO_ALLOCATION_INFO ;
parms . allocation_info . in . file . fnum = fnum1 ;
parms . allocation_info . in . alloc_size = 0 ;
2008-09-18 18:05:46 +04:00
status = smb_raw_setfileinfo ( cli - > tree , & parms ) ;
2008-09-06 01:24:36 +04:00
2014-10-02 19:02:38 +04:00
torture_assert_ntstatus_ok ( tctx , status ,
" RAW_SFILEINFO_ALLOCATION_INFO failed " ) ;
2008-09-06 01:24:36 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 120 * sec ) , 0 ) ;
2014-10-02 19:15:04 +04:00
first = true ;
updated = false ;
2008-09-06 01:24:36 +04:00
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2014-10-02 19:08:12 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-06 01:24:36 +04:00
2014-10-02 19:08:12 +04:00
torture_assert_u64_equal ( tctx , finfo2 . all_info . out . size , 0 ,
" file not truncated to expected size "
" (0) " ) ;
2008-09-06 01:24:36 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 19:02:38 +04:00
nt_time_string ( tctx , finfo2 . all_info . out . write_time ) ) ;
2014-10-02 19:15:04 +04:00
if ( finfo1 . all_info . out . write_time ! =
finfo2 . all_info . out . write_time )
{
updated = true ;
2008-09-06 01:24:36 +04:00
break ;
}
2014-10-02 19:15:04 +04:00
2008-09-06 01:24:36 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2014-10-02 19:15:04 +04:00
first = false ;
2008-09-06 01:24:36 +04:00
}
2014-10-02 19:15:04 +04:00
torture_assert ( tctx , updated ,
" Server did not update write time within 120 seconds " ) ;
torture_assert ( tctx , first , talloc_asprintf ( tctx ,
" Server did not update write time immediately but only "
" after %.2f seconds! " , timeval_elapsed ( & start ) ) ) ;
torture_comment ( tctx , " Server updated write time immediately. Good! \n " ) ;
2008-09-06 01:24:36 +04:00
2009-08-25 05:21:23 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2009-08-25 05:21:23 +04:00
2008-09-08 10:31:34 +04:00
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 0 , 1 ) ;
2014-10-02 19:02:38 +04:00
torture_assert_int_equal ( tctx , written , 1 ,
" Unexpected number of bytes written " ) ;
2008-09-08 10:31:34 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 10 * sec ) , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo3 ) ;
2014-10-02 19:08:12 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 19:08:12 +04:00
torture_assert_u64_equal ( tctx , finfo3 . all_info . out . size , 1 ,
" file not expaneded " ) ;
2008-09-08 10:31:34 +04:00
torture_comment ( tctx , " write time %s \n " ,
2014-10-02 19:02:38 +04:00
nt_time_string ( tctx , finfo3 . all_info . out . write_time ) ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 19:13:21 +04:00
torture_assert_u64_equal ( tctx ,
finfo3 . all_info . out . write_time ,
finfo2 . all_info . out . write_time ,
talloc_asprintf ( tctx ,
" Server updated write time "
" after %.2f seconds (wrong!) " ,
timeval_elapsed ( & start ) ) ) ;
2008-09-08 10:31:34 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 10:31:34 +04:00
}
2014-10-02 19:13:21 +04:00
torture_comment ( tctx , " Server did not update write time within 10 "
" seconds. Good! \n " ) ;
2008-09-08 10:31:34 +04:00
/* the close should trigger an write time update */
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
status = smb_raw_pathinfo ( cli - > tree , tctx , & pinfo4 ) ;
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " pathinfo failed " ) ;
2008-09-08 10:31:34 +04:00
2014-10-02 19:08:12 +04:00
torture_assert_u64_not_equal ( tctx ,
pinfo4 . all_info . out . write_time ,
finfo3 . all_info . out . write_time ,
" Server did not update write time on "
" close (wrong!) " ) ;
2014-10-02 19:09:18 +04:00
torture_assert ( tctx ,
pinfo4 . all_info . out . write_time > finfo3 . all_info . out . write_time ,
" Server updated write time on close, but to an earlier point "
" in time " ) ;
2008-09-06 01:24:36 +04:00
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
/*
2004-11-20 04:09:25 +03:00
* Do as above , but using 2 connections .
*/
2007-10-07 02:28:14 +04:00
static bool test_delayed_write_update2 ( struct torture_context * tctx , struct smbcli_state * cli ,
2006-10-16 17:06:41 +04:00
struct smbcli_state * cli2 )
2004-11-20 04:09:25 +03:00
{
union smb_fileinfo finfo1 , finfo2 ;
const char * fname = BASEDIR " \\ torture_file.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
2005-03-11 00:42:20 +03:00
int fnum2 = - 1 ;
2007-10-07 02:28:14 +04:00
bool ret = true ;
2004-11-20 04:09:25 +03:00
ssize_t written ;
2008-04-08 12:25:51 +04:00
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-04-08 12:25:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2006-03-10 23:49:20 +03:00
union smb_flush flsh ;
2004-11-20 04:09:25 +03:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update2 \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2004-11-20 04:09:25 +03:00
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Failed to open %s \n " , fname ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-11-20 04:09:25 +03:00
}
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo1 . basic_info . in . file . fnum = fnum1 ;
2004-11-20 04:09:25 +03:00
finfo2 = finfo1 ;
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2004-11-20 04:09:25 +03:00
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
2004-11-20 04:09:25 +03:00
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Initial write time %s \n " ,
nt_time_string ( tctx , finfo1 . basic_info . out . write_time ) ) ;
2004-11-20 04:09:25 +03:00
/* 3 second delay to ensure we get past any 2 second time
granularity ( older systems may have that ) */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2004-11-20 04:09:25 +03:00
2004-11-20 04:51:32 +03:00
{
/* Try using setfileinfo instead of write to update write time. */
union smb_setfileinfo sfinfo ;
time_t t_set = time ( NULL ) ;
sfinfo . basic_info . level = RAW_SFILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
sfinfo . basic_info . in . file . fnum = fnum1 ;
2004-11-20 04:51:32 +03:00
sfinfo . basic_info . in . create_time = finfo1 . basic_info . out . create_time ;
sfinfo . basic_info . in . access_time = finfo1 . basic_info . out . access_time ;
/* I tried this with both + and - ve to see if it makes a different.
It doesn ' t - once the filetime is set via setfileinfo it stays that way . */
# if 1
unix_to_nt_time ( & sfinfo . basic_info . in . write_time , t_set - 30000 ) ;
# else
unix_to_nt_time ( & sfinfo . basic_info . in . write_time , t_set + 30000 ) ;
# endif
sfinfo . basic_info . in . change_time = finfo1 . basic_info . out . change_time ;
sfinfo . basic_info . in . attrib = finfo1 . basic_info . out . attrib ;
status = smb_raw_setfileinfo ( cli - > tree , & sfinfo ) ;
2004-11-20 04:09:25 +03:00
2008-09-18 18:05:46 +04:00
torture_assert_ntstatus_ok ( tctx , status , " sfileinfo failed " ) ;
2004-11-20 04:09:25 +03:00
}
2007-12-01 13:39:39 +03:00
finfo2 . basic_info . in . file . path = fname ;
2004-11-20 04:09:25 +03:00
2007-12-01 13:39:39 +03:00
status = smb_raw_pathinfo ( cli2 - > tree , tctx , & finfo2 ) ;
2004-11-20 04:09:25 +03:00
2007-12-01 13:39:39 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
return false ;
2004-11-20 04:09:25 +03:00
}
2007-12-01 13:39:39 +03:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
if ( finfo1 . basic_info . out . write_time ! = finfo2 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server updated write_time (correct) \n " ) ;
} else {
2008-09-18 18:05:46 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server did not update write time (wrong!) \n " ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-20 04:09:25 +03:00
}
2004-11-20 04:51:32 +03:00
/* Now try a write to see if the write time gets reset. */
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo1 . basic_info . in . file . fnum = fnum1 ;
2004-11-20 04:51:32 +03:00
finfo2 = finfo1 ;
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2004-11-20 04:51:32 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-11-20 04:51:32 +03:00
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Modified write time %s \n " ,
nt_time_string ( tctx , finfo1 . basic_info . out . write_time ) ) ;
2004-11-20 04:51:32 +03:00
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Doing a 10 byte write to extend the file and see if this changes the last write time. \n " ) ;
2004-11-20 04:51:32 +03:00
2004-11-20 05:33:12 +03:00
written = smbcli_write ( cli - > tree , fnum1 , 0 , " 0123456789 " , 1 , 10 ) ;
if ( written ! = 10 ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " write failed - wrote %d bytes (%s) \n " ,
2005-07-17 13:20:52 +04:00
( int ) written , __location__ ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-11-20 04:51:32 +03:00
}
2004-11-20 05:33:12 +03:00
/* Just to prove to tridge that the an smbflush has no effect on
the write time : - ) . The setfileinfo IS STICKY . JRA . */
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Doing flush after write \n " ) ;
2004-11-20 05:33:12 +03:00
2006-05-19 19:10:39 +04:00
flsh . flush . level = RAW_FLUSH_FLUSH ;
2006-03-13 01:48:25 +03:00
flsh . flush . in . file . fnum = fnum1 ;
2004-11-20 05:33:12 +03:00
status = smb_raw_flush ( cli - > tree , & flsh ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " smbflush failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2004-11-20 05:33:12 +03:00
}
2004-11-20 04:51:32 +03:00
/* Once the time was set using setfileinfo then it stays set - writes
don ' t have any effect . But make sure . */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 15 * sec ) , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2004-11-20 04:51:32 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-20 04:51:32 +03:00
break ;
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2004-11-20 04:51:32 +03:00
if ( finfo1 . basic_info . out . write_time ! = finfo2 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:39:39 +03:00
ret = false ;
2004-11-20 04:51:32 +03:00
break ;
}
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2004-11-20 04:51:32 +03:00
}
if ( finfo1 . basic_info . out . write_time = = finfo2 . basic_info . out . write_time ) {
2007-12-01 13:39:39 +03:00
torture_comment ( tctx , " Server did not update write time (correct) \n " ) ;
2005-03-11 00:42:20 +03:00
}
2009-08-25 05:21:23 +04:00
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2009-08-25 05:21:23 +04:00
2005-03-11 00:42:20 +03:00
fnum2 = smbcli_open ( cli - > tree , fname , O_RDWR , DENY_NONE ) ;
if ( fnum2 = = - 1 ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Failed to open %s \n " , fname ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
2006-10-16 17:06:41 +04:00
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 " ) ;
2005-03-11 00:42:20 +03:00
written = smbcli_write ( cli - > tree , fnum2 , 0 , " 0123456789 " , 11 , 10 ) ;
if ( written ! = 10 ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " write failed - wrote %d bytes (%s) \n " ,
2005-07-17 13:20:52 +04:00
( int ) written , __location__ ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2005-03-11 00:42:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2005-03-11 00:42:20 +03:00
if ( finfo1 . basic_info . out . write_time ! = finfo2 . basic_info . out . write_time ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time (wrong!) \n " ) ;
2007-12-01 13:39:39 +03:00
ret = false ;
2005-03-11 00:42:20 +03:00
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Closing the first fd to see if write time updated. \n " ) ;
2005-03-11 00:42:20 +03:00
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
2006-10-16 17:06:41 +04:00
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 " ) ;
2005-03-11 00:42:20 +03:00
written = smbcli_write ( cli - > tree , fnum2 , 0 , " 0123456789 " , 21 , 10 ) ;
if ( written ! = 10 ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " write failed - wrote %d bytes (%s) \n " ,
2005-07-17 13:20:52 +04:00
( int ) written , __location__ ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo1 . basic_info . in . file . fnum = fnum2 ;
2005-03-11 00:42:20 +03:00
finfo2 = finfo1 ;
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2005-03-11 00:42:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2005-03-11 00:42:20 +03:00
if ( finfo1 . basic_info . out . write_time ! = finfo2 . basic_info . out . write_time ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time (wrong!) \n " ) ;
2007-12-01 13:39:39 +03:00
ret = false ;
2005-03-11 00:42:20 +03:00
}
/* Once the time was set using setfileinfo then it stays set - writes
don ' t have any effect . But make sure . */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 15 * sec ) , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2005-03-11 00:42:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2005-03-11 00:42:20 +03:00
break ;
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2005-03-11 00:42:20 +03:00
if ( finfo1 . basic_info . out . write_time ! = finfo2 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:39:39 +03:00
ret = false ;
2005-03-11 00:42:20 +03:00
break ;
}
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2005-03-11 00:42:20 +03:00
}
if ( finfo1 . basic_info . out . write_time = = finfo2 . basic_info . out . write_time ) {
2007-12-01 13:39:39 +03:00
torture_comment ( tctx , " Server did not update write time (correct) \n " ) ;
2005-03-11 00:42:20 +03:00
}
2007-12-01 13:39:39 +03:00
torture_comment ( tctx , " Closing second fd to see if write time updated. \n " ) ;
2005-03-11 00:42:20 +03:00
smbcli_close ( cli - > tree , fnum2 ) ;
fnum2 = - 1 ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Failed to open %s \n " , fname ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo1 . basic_info . in . file . fnum = fnum1 ;
2005-03-11 00:42:20 +03:00
finfo2 = finfo1 ;
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2005-03-11 00:42:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Second open initial write time %s \n " ,
nt_time_string ( tctx , finfo1 . basic_info . out . write_time ) ) ;
2005-03-11 00:42:20 +03:00
2010-09-16 23:36:37 +04:00
smb_msleep ( 10 * msec ) ;
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " Doing a 10 byte write to extend the file to see if this changes the last write time. \n " ) ;
2005-03-11 00:42:20 +03:00
written = smbcli_write ( cli - > tree , fnum1 , 0 , " 0123456789 " , 31 , 10 ) ;
if ( written ! = 10 ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " write failed - wrote %d bytes (%s) \n " ,
2005-07-17 13:20:52 +04:00
( int ) written , __location__ ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo1 . basic_info . in . file . fnum = fnum1 ;
2005-03-11 00:42:20 +03:00
finfo2 = finfo1 ;
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2005-03-11 00:42:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2005-03-11 00:42:20 +03:00
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2005-03-11 00:42:20 +03:00
if ( finfo1 . basic_info . out . write_time ! = finfo2 . basic_info . out . write_time ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time (wrong!) \n " ) ;
2007-12-01 13:39:39 +03:00
ret = false ;
2005-03-11 00:42:20 +03:00
}
2007-12-01 13:39:39 +03:00
/* Now the write time should be updated again */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , ( 15 * sec ) , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
2005-03-11 00:42:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " fileinfo failed: %s \n " , nt_errstr ( status ) ) ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2005-03-11 00:42:20 +03:00
break ;
}
2006-10-16 17:06:41 +04:00
torture_comment ( tctx , " write time %s \n " ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2005-03-11 00:42:20 +03:00
if ( finfo1 . basic_info . out . write_time ! = finfo2 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-20 14:28:51 +04:00
if ( diff < ( used_delay / ( double ) 1000000 ) ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:50 +04:00
" (expected > %.2f) (wrong!) \n " ,
diff , used_delay / ( double ) 1000000 ) ;
2007-12-01 13:39:39 +03:00
ret = false ;
break ;
}
2008-04-08 12:25:51 +04:00
torture_comment ( tctx , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (correct) \n " ,
diff ) ;
2005-03-11 00:42:20 +03:00
break ;
}
fflush ( stdout ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2005-03-11 00:42:20 +03:00
}
if ( finfo1 . basic_info . out . write_time = = finfo2 . basic_info . out . write_time ) {
2008-09-18 18:05:46 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server did not update write time (wrong!) \n " ) ;
2007-12-01 13:39:39 +03:00
ret = false ;
2004-11-20 04:51:32 +03:00
}
2005-03-11 00:42:20 +03:00
2004-11-20 04:51:32 +03:00
/* One more test to do. We should read the filetime via findfirst on the
second connection to ensure it ' s the same . This is very easy for a Windows
server but a bastard to get right on a POSIX server . JRA . */
2004-11-20 04:09:25 +03:00
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2004-11-12 12:37:59 +03:00
/* Windows does obviously not update the stat info during a write call. I
* * think * this is the problem causing a spurious Excel 2003 on XP error
* message when saving a file . Excel does a setfileinfo , writes , and then does
* a getpath ( ! ) info . Or so . . . For Samba sometimes it displays an error message
* that the file might have been changed in between . What i ' ve been able to
* trace down is that this happens if the getpathinfo after the write shows a
* different last write time than the setfileinfo showed . This is really
* nasty . . . .
*/
2007-10-07 02:28:14 +04:00
static bool test_finfo_after_write ( struct torture_context * tctx , struct smbcli_state * cli ,
2006-10-16 17:06:41 +04:00
struct smbcli_state * cli2 )
2004-11-12 12:37:59 +03:00
{
union smb_fileinfo finfo1 , finfo2 ;
const char * fname = BASEDIR " \\ torture_file.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
int fnum2 ;
2007-10-07 02:28:14 +04:00
bool ret = true ;
2004-11-12 12:37:59 +03:00
ssize_t written ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-04-08 12:25:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2004-11-12 12:37:59 +03:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_finfo_after_write \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2004-11-12 12:37:59 +03:00
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
2007-10-07 02:28:14 +04:00
ret = false ;
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
2004-11-12 12:37:59 +03:00
goto done ;
}
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo1 . basic_info . in . file . fnum = fnum1 ;
2004-11-12 12:37:59 +03:00
2006-10-16 17:06:41 +04:00
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
2004-11-12 12:37:59 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-10-07 02:28:14 +04:00
ret = false ;
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : fileinfo failed: %s " , nt_errstr ( status ) ) ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2004-11-12 12:37:59 +03:00
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
fnum2 = smbcli_open ( cli2 - > tree , fname , O_RDWR , DENY_NONE ) ;
if ( fnum2 = = - 1 ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : failed to open 2nd time - %s " ,
smbcli_errstr ( cli2 - > tree ) ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
written = smbcli_write ( cli2 - > tree , fnum2 , 0 , " x " , 0 , 1 ) ;
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
if ( written ! = 1 ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " ,
( int ) written ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
finfo2 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo2 . basic_info . in . file . path = fname ;
2012-09-13 18:52:44 +04:00
2006-10-16 17:06:41 +04:00
status = smb_raw_pathinfo ( cli2 - > tree , tctx , & finfo2 ) ;
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : fileinfo failed: %s " ,
nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
if ( finfo1 . basic_info . out . create_time ! =
finfo2 . basic_info . out . create_time ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : create_time changed " ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
if ( finfo1 . basic_info . out . access_time ! =
finfo2 . basic_info . out . access_time ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : access_time changed " ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
if ( finfo1 . basic_info . out . write_time ! =
finfo2 . basic_info . out . write_time ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : write_time changed: \n "
" write time conn 1 = %s, conn 2 = %s " ,
2006-10-16 17:06:41 +04:00
nt_time_string ( tctx , finfo1 . basic_info . out . write_time ) ,
nt_time_string ( tctx , finfo2 . basic_info . out . write_time ) ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
if ( finfo1 . basic_info . out . change_time ! =
finfo2 . basic_info . out . change_time ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : change_time changed " ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
/* One of the two following calls updates the qpathinfo. */
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
/* If you had skipped the smbcli_write on fnum2, it would
* * not * have updated the stat on disk */
2012-09-13 18:52:44 +04:00
2004-11-12 12:37:59 +03:00
smbcli_close ( cli2 - > tree , fnum2 ) ;
cli2 = NULL ;
/* This call is only for the people looking at ethereal :-) */
finfo2 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
2006-03-13 01:48:25 +03:00
finfo2 . basic_info . in . file . path = fname ;
2004-11-12 12:37:59 +03:00
2006-10-16 17:06:41 +04:00
status = smb_raw_pathinfo ( cli - > tree , tctx , & finfo2 ) ;
2004-11-12 12:37:59 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2007-03-06 00:28:55 +03:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : fileinfo failed: %s " , nt_errstr ( status ) ) ;
2007-10-07 02:28:14 +04:00
ret = false ;
2004-11-12 12:37:59 +03:00
goto done ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2007-12-01 13:43:38 +03:00
# define COMPARE_WRITE_TIME_CMP(given, correct, cmp) do { \
2008-04-08 21:04:44 +04:00
uint64_t r = 10 * 1000 * 1000 ; \
2007-12-01 13:43:38 +03:00
NTTIME g = ( given ) . basic_info . out . write_time ; \
2008-04-08 21:04:44 +04:00
NTTIME gr = ( g / r ) * r ; \
2007-12-01 13:43:38 +03:00
NTTIME c = ( correct ) . basic_info . out . write_time ; \
2008-04-08 21:04:44 +04:00
NTTIME cr = ( c / r ) * r ; \
bool strict = torture_setting_bool ( tctx , " strict mode " , false ) ; \
bool err = false ; \
if ( strict & & ( g cmp c ) ) { \
err = true ; \
2008-06-03 16:01:02 +04:00
} else if ( ( g cmp c ) & & ( gr cmp cr ) ) { \
2008-04-08 21:04:44 +04:00
/* handle filesystem without high resolution timestamps */ \
err = true ; \
} \
if ( err ) { \
2008-04-08 12:25:51 +04:00
torture_result ( tctx , TORTURE_FAIL , __location__ " : wrong write_time (%s)%s(%llu) %s (%s)%s(%llu) " , \
# given, nt_time_string(tctx, g), (unsigned long long)g, \
# cmp, #correct, nt_time_string(tctx, c), (unsigned long long)c); \
2007-12-01 13:43:38 +03:00
ret = false ; \
goto done ; \
} \
} while ( 0 )
# define COMPARE_WRITE_TIME_EQUAL(given,correct) \
COMPARE_WRITE_TIME_CMP ( given , correct , ! = )
# define COMPARE_WRITE_TIME_GREATER(given,correct) \
COMPARE_WRITE_TIME_CMP ( given , correct , < = )
# define COMPARE_WRITE_TIME_LESS(given,correct) \
COMPARE_WRITE_TIME_CMP ( given , correct , > = )
2007-12-06 15:17:34 +03:00
# define COMPARE_ACCESS_TIME_CMP(given, correct, cmp) do { \
NTTIME g = ( given ) . basic_info . out . access_time ; \
NTTIME c = ( correct ) . basic_info . out . access_time ; \
if ( g cmp c ) { \
torture_result ( tctx , TORTURE_FAIL , __location__ " : wrong access_time (%s)%s %s (%s)%s " , \
# given, nt_time_string(tctx, g), \
# cmp, #correct, nt_time_string(tctx, c)); \
ret = false ; \
goto done ; \
} \
} while ( 0 )
# define COMPARE_ACCESS_TIME_EQUAL(given,correct) \
COMPARE_ACCESS_TIME_CMP ( given , correct , ! = )
# define COMPARE_BOTH_TIMES_EQUAL(given,correct) do { \
COMPARE_ACCESS_TIME_EQUAL ( given , correct ) ; \
COMPARE_WRITE_TIME_EQUAL ( given , correct ) ; \
} while ( 0 )
2007-12-01 13:43:38 +03:00
# define GET_INFO_FILE(finfo) do { \
NTSTATUS _status ; \
_status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo ) ; \
if ( ! NT_STATUS_IS_OK ( _status ) ) { \
ret = false ; \
torture_result ( tctx , TORTURE_FAIL , __location__ " : fileinfo failed: %s " , \
nt_errstr ( _status ) ) ; \
goto done ; \
} \
2007-12-06 15:17:34 +03:00
torture_comment ( tctx , " fileinfo: Access(%s) Write(%s) \n " , \
nt_time_string ( tctx , finfo . basic_info . out . access_time ) , \
2007-12-01 13:43:38 +03:00
nt_time_string ( tctx , finfo . basic_info . out . write_time ) ) ; \
} while ( 0 )
2009-11-06 02:37:26 +03:00
# define GET_INFO_FILE2(finfo) do { \
NTSTATUS _status ; \
_status = smb_raw_fileinfo ( cli2 - > tree , tctx , & finfo ) ; \
if ( ! NT_STATUS_IS_OK ( _status ) ) { \
ret = false ; \
torture_result ( tctx , TORTURE_FAIL , __location__ " : fileinfo failed: %s " , \
nt_errstr ( _status ) ) ; \
goto done ; \
} \
torture_comment ( tctx , " fileinfo: Access(%s) Write(%s) \n " , \
nt_time_string ( tctx , finfo . basic_info . out . access_time ) , \
nt_time_string ( tctx , finfo . basic_info . out . write_time ) ) ; \
} while ( 0 )
2007-12-01 13:43:38 +03:00
# define GET_INFO_PATH(pinfo) do { \
NTSTATUS _status ; \
_status = smb_raw_pathinfo ( cli2 - > tree , tctx , & pinfo ) ; \
if ( ! NT_STATUS_IS_OK ( _status ) ) { \
torture_result ( tctx , TORTURE_FAIL , __location__ " : pathinfo failed: %s " , \
nt_errstr ( _status ) ) ; \
ret = false ; \
goto done ; \
} \
2007-12-06 15:17:34 +03:00
torture_comment ( tctx , " pathinfo: Access(%s) Write(%s) \n " , \
nt_time_string ( tctx , pinfo . basic_info . out . access_time ) , \
2007-12-01 13:43:38 +03:00
nt_time_string ( tctx , pinfo . basic_info . out . write_time ) ) ; \
} while ( 0 )
# define GET_INFO_BOTH(finfo,pinfo) do { \
GET_INFO_FILE ( finfo ) ; \
GET_INFO_PATH ( pinfo ) ; \
2007-12-06 15:17:34 +03:00
COMPARE_BOTH_TIMES_EQUAL ( finfo , pinfo ) ; \
2007-12-01 13:43:38 +03:00
} while ( 0 )
# define SET_INFO_FILE_EX(finfo, wrtime, tree, tfnum) do { \
NTSTATUS _status ; \
union smb_setfileinfo sfinfo ; \
sfinfo . basic_info . level = RAW_SFILEINFO_BASIC_INFO ; \
sfinfo . basic_info . in . file . fnum = tfnum ; \
2007-12-06 17:06:36 +03:00
sfinfo . basic_info . in . create_time = 0 ; \
sfinfo . basic_info . in . access_time = 0 ; \
2007-12-01 13:43:38 +03:00
unix_to_nt_time ( & sfinfo . basic_info . in . write_time , ( wrtime ) ) ; \
2007-12-06 17:06:36 +03:00
sfinfo . basic_info . in . change_time = 0 ; \
2007-12-01 13:43:38 +03:00
sfinfo . basic_info . in . attrib = finfo1 . basic_info . out . attrib ; \
_status = smb_raw_setfileinfo ( tree , & sfinfo ) ; \
if ( ! NT_STATUS_IS_OK ( _status ) ) { \
torture_result ( tctx , TORTURE_FAIL , __location__ " : setfileinfo failed: %s " , \
nt_errstr ( _status ) ) ; \
ret = false ; \
goto done ; \
} \
} while ( 0 )
# define SET_INFO_FILE(finfo, wrtime) \
SET_INFO_FILE_EX ( finfo , wrtime , cli - > tree , fnum1 )
2009-09-15 05:45:16 +04:00
# define SET_INFO_FILE_NS(finfo, wrtime, ns, tree, tfnum) do { \
NTSTATUS _status ; \
union smb_setfileinfo sfinfo ; \
sfinfo . basic_info . level = RAW_SFILEINFO_BASIC_INFO ; \
sfinfo . basic_info . in . file . fnum = tfnum ; \
sfinfo . basic_info . in . create_time = 0 ; \
sfinfo . basic_info . in . access_time = 0 ; \
unix_to_nt_time ( & sfinfo . basic_info . in . write_time , ( wrtime ) ) ; \
sfinfo . basic_info . in . write_time + = ( ns ) ; \
sfinfo . basic_info . in . change_time = 0 ; \
sfinfo . basic_info . in . attrib = finfo1 . basic_info . out . attrib ; \
_status = smb_raw_setfileinfo ( tree , & sfinfo ) ; \
if ( ! NT_STATUS_IS_OK ( _status ) ) { \
torture_result ( tctx , TORTURE_FAIL , __location__ " : setfileinfo failed: %s " , \
nt_errstr ( _status ) ) ; \
ret = false ; \
goto done ; \
} \
} while ( 0 )
2007-12-01 13:43:38 +03:00
static bool test_delayed_write_update3 ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
2011-11-22 01:06:00 +04:00
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_file3.txt " ;
2007-12-01 13:43:38 +03:00
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
2008-04-08 12:25:51 +04:00
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-04-08 12:25:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2007-12-01 13:43:38 +03:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update3 \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2007-12-01 13:43:38 +03:00
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/*
* make sure the write time is updated 2 seconds later
* calcuated from the first write
* ( but expect upto 5 seconds extra time for a busy server )
*/
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , 7 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_FILE ( finfo1 ) ;
if ( finfo1 . basic_info . out . write_time > finfo0 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-20 14:28:51 +04:00
if ( diff < ( used_delay / ( double ) 1000000 ) ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:50 +04:00
" (write time update delay == %.2f) (wrong!) \n " ,
diff , used_delay / ( double ) 1000000 ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2008-04-08 12:25:51 +04:00
torture_comment ( tctx , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (correct) \n " ,
diff ) ;
2007-12-01 13:43:38 +03:00
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 0.5 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
2008-05-05 17:05:41 +04:00
COMPARE_WRITE_TIME_GREATER ( pinfo1 , pinfo0 ) ;
2007-12-01 13:43:38 +03:00
/* sure any further write doesn't update the write time */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
if ( finfo2 . basic_info . out . write_time > finfo1 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo2 , finfo1 ) ;
if ( finfo2 . basic_info . out . write_time = = finfo1 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2007-12-01 13:43:38 +03:00
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
/*
* the close updates the write time to the time of the close
* and not to the time of the last write !
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo4 ) ;
COMPARE_WRITE_TIME_GREATER ( pinfo4 , pinfo3 ) ;
if ( pinfo4 . basic_info . out . write_time > pinfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server updated the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
* Show that a truncate write always updates the write time even
* if an initial write has already updated the write time .
*/
2008-09-08 15:59:51 +04:00
static bool test_delayed_write_update3a ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
2011-11-22 01:06:00 +04:00
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_file3a.txt " ;
2008-09-08 15:59:51 +04:00
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
int i ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-08 15:59:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update3a \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-08 15:59:51 +04:00
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/*
* sleep some time , to demonstrate the handling of write times
* doesn ' t depend on the time since the open
*/
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 15:59:51 +04:00
/* get the initial times */
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo0 ) ;
/*
* make sure the write time is updated 2 seconds later
* calcuated from the first write
* ( but expect upto 5 seconds extra time for a busy server )
*/
start = timeval_current ( ) ;
end = timeval_add ( & start , 7 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_FILE ( finfo1 ) ;
if ( finfo1 . basic_info . out . write_time > finfo0 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-20 14:28:51 +04:00
if ( diff < ( used_delay / ( double ) 1000000 ) ) {
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2008-09-08 15:59:51 +04:00
" (1sec == %.2f) (wrong!) \n " ,
diff , sec ) ;
ret = false ;
break ;
}
torture_comment ( tctx , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (correct) \n " ,
diff ) ;
2008-09-08 15:59:51 +04:00
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 0.5 * msec ) ;
2008-09-08 15:59:51 +04:00
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_GREATER ( pinfo1 , pinfo0 ) ;
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2009-11-06 02:37:26 +03:00
2008-09-08 15:59:51 +04:00
/*
* demonstrate that a truncate write always
* updates the write time immediately
*/
for ( i = 0 ; i < 3 ; i + + ) {
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2008-09-08 15:59:51 +04:00
/* do a write */
torture_comment ( tctx , " Do a truncate SMBwrite [%d] on the file handle \n " , i ) ;
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 10240 , 0 ) ;
if ( written ! = 0 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 0 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_GREATER ( finfo2 , finfo1 ) ;
finfo1 = finfo2 ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2009-11-06 02:37:26 +03:00
2008-09-08 15:59:51 +04:00
/* sure any further write doesn't update the write time */
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
if ( finfo2 . basic_info . out . write_time > finfo1 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2008-09-08 15:59:51 +04:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 15:59:51 +04:00
}
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo2 , finfo1 ) ;
if ( finfo2 . basic_info . out . write_time = = finfo1 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2008-09-08 15:59:51 +04:00
/* get the initial times */
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo2 ) ;
/*
* demonstrate that a truncate write always
* updates the write time immediately
*/
for ( i = 0 ; i < 3 ; i + + ) {
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2008-09-08 15:59:51 +04:00
/* do a write */
torture_comment ( tctx , " Do a truncate SMBwrite [%d] on the file handle \n " , i ) ;
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 512 , 0 ) ;
if ( written ! = 0 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 0 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_GREATER ( finfo2 , finfo1 ) ;
finfo1 = finfo2 ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2008-09-08 15:59:51 +04:00
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
/*
* the close doesn ' t update the write time
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo4 ) ;
COMPARE_WRITE_TIME_EQUAL ( pinfo4 , pinfo3 ) ;
if ( pinfo4 . basic_info . out . write_time = = pinfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
* Show a close after write updates the write timestamp to
* the close time , not the last write time .
*/
2008-09-08 14:12:25 +04:00
static bool test_delayed_write_update3b ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
2011-11-22 01:06:00 +04:00
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_file3b.txt " ;
2008-09-08 14:12:25 +04:00
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-08 14:12:25 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update3b \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-08 14:12:25 +04:00
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/*
* sleep some time , to demonstrate the handling of write times
* doesn ' t depend on the time since the open
*/
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 14:12:25 +04:00
/* get the initial times */
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo0 ) ;
/*
* make sure the write time is updated 2 seconds later
* calcuated from the first write
* ( but expect upto 5 seconds extra time for a busy server )
*/
start = timeval_current ( ) ;
end = timeval_add ( & start , 7 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_FILE ( finfo1 ) ;
if ( finfo1 . basic_info . out . write_time > finfo0 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-20 14:28:51 +04:00
if ( diff < ( used_delay / ( double ) 1000000 ) ) {
2014-06-20 14:28:50 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
" (expected > %.2f) (wrong!) \n " ,
diff , used_delay / ( double ) 1000000 ) ;
2008-09-08 14:12:25 +04:00
ret = false ;
break ;
}
torture_comment ( tctx , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:50 +04:00
" (write time update delay == %.2f) (correct) \n " ,
diff , used_delay / ( double ) 1000000 ) ;
2008-09-08 14:12:25 +04:00
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 0.5 * msec ) ;
2008-09-08 14:12:25 +04:00
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_GREATER ( pinfo1 , pinfo0 ) ;
/* sure any further write doesn't update the write time */
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
if ( finfo2 . basic_info . out . write_time > finfo1 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2008-09-08 14:12:25 +04:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 14:12:25 +04:00
}
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo2 , finfo1 ) ;
if ( finfo2 . basic_info . out . write_time = = finfo1 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 14:12:25 +04:00
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
/*
* the close updates the write time to the time of the close
* and not to the time of the last write !
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo4 ) ;
COMPARE_WRITE_TIME_GREATER ( pinfo4 , pinfo3 ) ;
if ( pinfo4 . basic_info . out . write_time > pinfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server updated the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
* Check that a write after a truncate write doesn ' t update
* the timestamp , but a truncate write after a write does .
* Also prove that a close after a truncate write updates the
* timestamp to current , not the time of last write .
*/
2008-09-08 16:11:17 +04:00
static bool test_delayed_write_update3c ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
2014-10-02 16:53:01 +04:00
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_file3c.txt " ;
2008-09-08 16:11:17 +04:00
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
int i ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-08 16:11:17 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update3c \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-08 16:11:17 +04:00
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/*
* sleep some time , to demonstrate the handling of write times
* doesn ' t depend on the time since the open
*/
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 16:11:17 +04:00
/* get the initial times */
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo0 ) ;
/*
* demonstrate that a truncate write always
* updates the write time immediately
*/
for ( i = 0 ; i < 3 ; i + + ) {
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2008-09-08 16:11:17 +04:00
/* do a write */
torture_comment ( tctx , " Do a truncate SMBwrite [%d] on the file handle \n " , i ) ;
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 512 , 0 ) ;
if ( written ! = 0 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 0 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_GREATER ( finfo2 , finfo1 ) ;
finfo1 = finfo2 ;
}
start = timeval_current ( ) ;
end = timeval_add ( & start , 7 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_FILE ( finfo2 ) ;
if ( finfo2 . basic_info . out . write_time > finfo1 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2008-09-08 16:11:17 +04:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 16:11:17 +04:00
}
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo2 , finfo1 ) ;
if ( finfo2 . basic_info . out . write_time = = finfo1 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 16:11:17 +04:00
/* get the initial times */
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo2 ) ;
/*
* demonstrate that a truncate write always
* updates the write time immediately
*/
for ( i = 0 ; i < 3 ; i + + ) {
2010-09-16 23:36:37 +04:00
smb_msleep ( 2 * msec ) ;
2008-09-08 16:11:17 +04:00
/* do a write */
torture_comment ( tctx , " Do a truncate write [%d] on the file handle \n " , i ) ;
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 512 , 0 ) ;
if ( written ! = 0 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 0 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_GREATER ( finfo2 , finfo1 ) ;
finfo1 = finfo2 ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 16:11:17 +04:00
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo2 , finfo1 ) ;
/* sure any further write doesn't update the write time */
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
if ( finfo2 . basic_info . out . write_time > finfo1 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2008-09-08 16:11:17 +04:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 16:11:17 +04:00
}
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo2 , finfo1 ) ;
if ( finfo2 . basic_info . out . write_time = = finfo1 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 16:11:17 +04:00
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
/*
* the close updates the write time to the time of the close
* and not to the time of the last write !
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo4 ) ;
COMPARE_WRITE_TIME_GREATER ( pinfo4 , pinfo3 ) ;
if ( pinfo4 . basic_info . out . write_time > pinfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server updated the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
* Show only the first write updates the timestamp , and a close
* after writes updates to current ( I think this is the same
* as test 3 b . JRA ) .
*/
2007-12-01 13:43:38 +03:00
static bool test_delayed_write_update4 ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
2011-11-22 01:06:00 +04:00
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_file4.txt " ;
2007-12-01 13:43:38 +03:00
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
2008-04-08 12:25:51 +04:00
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-04-08 12:25:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2007-12-01 13:43:38 +03:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update4 \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2007-12-01 13:43:38 +03:00
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/* sleep a bit */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2007-12-01 13:43:38 +03:00
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo0 ) ;
/*
* make sure the write time is updated 2 seconds later
* calcuated from the first write
* ( but expect upto 3 seconds extra time for a busy server )
*/
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , 5 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* get the times after the first write */
GET_INFO_FILE ( finfo1 ) ;
if ( finfo1 . basic_info . out . write_time > finfo0 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-20 14:28:51 +04:00
if ( diff < ( used_delay / ( double ) 1000000 ) ) {
2014-06-20 14:28:50 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
" (expected > %.2f) (wrong!) \n " ,
diff , used_delay / ( double ) 1000000 ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2008-04-08 12:25:51 +04:00
torture_comment ( tctx , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:50 +04:00
" (write time update delay == %.2f) (correct) \n " ,
diff , used_delay / ( double ) 1000000 ) ;
2007-12-01 13:43:38 +03:00
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 0.5 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
2008-05-05 17:05:41 +04:00
COMPARE_WRITE_TIME_GREATER ( pinfo1 , pinfo0 ) ;
2007-12-01 13:43:38 +03:00
/* sure any further write doesn't update the write time */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
if ( finfo2 . basic_info . out . write_time > finfo1 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo2 , finfo1 ) ;
if ( finfo2 . basic_info . out . write_time = = finfo1 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not updatewrite_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2007-12-01 13:43:38 +03:00
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
/*
* the close updates the write time to the time of the close
* and not to the time of the last write !
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo4 ) ;
COMPARE_WRITE_TIME_GREATER ( pinfo4 , pinfo3 ) ;
if ( pinfo4 . basic_info . out . write_time > pinfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server updated the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
* Show writes and closes have no effect on updating times once a SETWRITETIME is done .
*/
2007-12-01 13:43:38 +03:00
static bool test_delayed_write_update5 ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 , finfo4 , finfo5 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 , pinfo5 , pinfo6 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_file5.txt " ;
2007-12-01 13:43:38 +03:00
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
2008-04-08 12:25:51 +04:00
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-04-08 12:25:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2007-12-01 13:43:38 +03:00
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update5 \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2007-12-01 13:43:38 +03:00
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
finfo4 = finfo0 ;
finfo5 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
pinfo5 = pinfo0 ;
pinfo6 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo0 ) ;
torture_comment ( tctx , " Set write time in the future on the file handle \n " ) ;
SET_INFO_FILE ( finfo0 , time ( NULL ) + 86400 ) ;
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_GREATER ( finfo2 , finfo1 ) ;
torture_comment ( tctx , " Set write time in the past on the file handle \n " ) ;
SET_INFO_FILE ( finfo0 , time ( NULL ) - 86400 ) ;
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_LESS ( finfo2 , finfo1 ) ;
/* make sure the 2 second delay from the first write are canceled */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* get the times after the first write */
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
if ( finfo3 . basic_info . out . write_time > finfo2 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
2008-09-06 08:47:06 +04:00
if ( finfo3 . basic_info . out . write_time = = finfo2 . basic_info . out . write_time ) {
2007-12-01 13:43:38 +03:00
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sure any further write doesn't update the write time */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo4 , pinfo4 ) ;
if ( finfo4 . basic_info . out . write_time > finfo3 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo4 , pinfo4 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo4 , finfo3 ) ;
if ( finfo4 . basic_info . out . write_time = = finfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2007-12-01 13:43:38 +03:00
GET_INFO_BOTH ( finfo5 , pinfo5 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo5 , finfo4 ) ;
/*
* the close doesn ' t update the write time
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo6 ) ;
COMPARE_WRITE_TIME_EQUAL ( pinfo6 , pinfo5 ) ;
if ( pinfo6 . basic_info . out . write_time = = pinfo5 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
* Show truncate writes and closes have no effect on updating times once a SETWRITETIME is done .
*/
2008-09-08 14:27:43 +04:00
static bool test_delayed_write_update5b ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 , finfo4 , finfo5 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 , pinfo5 , pinfo6 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_fileb.txt " ;
2008-09-08 14:27:43 +04:00
int fnum1 = - 1 ;
bool ret = true ;
ssize_t written ;
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-09-08 14:27:43 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update5b \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2008-09-08 14:27:43 +04:00
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
finfo4 = finfo0 ;
finfo5 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
pinfo5 = pinfo0 ;
pinfo6 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo0 ) ;
torture_comment ( tctx , " Set write time in the future on the file handle \n " ) ;
SET_INFO_FILE ( finfo0 , time ( NULL ) + 86400 ) ;
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_GREATER ( finfo2 , finfo1 ) ;
torture_comment ( tctx , " Set write time in the past on the file handle \n " ) ;
SET_INFO_FILE ( finfo0 , time ( NULL ) - 86400 ) ;
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_LESS ( finfo2 , finfo1 ) ;
/* make sure the 2 second delay from the first write are canceled */
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* get the times after the first write */
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
if ( finfo3 . basic_info . out . write_time > finfo2 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2008-09-08 14:27:43 +04:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 14:27:43 +04:00
}
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
if ( finfo3 . basic_info . out . write_time = = finfo2 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
2008-09-13 01:59:32 +04:00
/* Do any further write (truncates) update the write time ? */
2008-09-08 14:27:43 +04:00
start = timeval_current ( ) ;
end = timeval_add ( & start , 15 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a truncate write on the file handle \n " ) ;
2008-09-10 08:24:34 +04:00
written = smbcli_smbwrite ( cli - > tree , fnum1 , " x " , 1024 , 0 ) ;
2008-09-08 14:27:43 +04:00
if ( written ! = 0 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo4 , pinfo4 ) ;
if ( finfo4 . basic_info . out . write_time > finfo3 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2008-09-08 14:27:43 +04:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2008-09-08 14:27:43 +04:00
}
GET_INFO_BOTH ( finfo4 , pinfo4 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo4 , finfo3 ) ;
if ( finfo4 . basic_info . out . write_time = = finfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2008-09-08 14:27:43 +04:00
GET_INFO_BOTH ( finfo5 , pinfo5 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo5 , finfo4 ) ;
/*
* the close doesn ' t update the write time
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo6 ) ;
COMPARE_WRITE_TIME_EQUAL ( pinfo6 , pinfo5 ) ;
if ( pinfo6 . basic_info . out . write_time = = pinfo5 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
* Open 2 handles on a file . Write one one and then set the
* WRITE TIME explicitly on the other . Ensure the write time
* update is cancelled . Ensure the write time is updated to
* the close time when the non - explicit set handle is closed .
*
*/
2007-12-01 13:43:38 +03:00
static bool test_delayed_write_update6 ( struct torture_context * tctx ,
struct smbcli_state * cli ,
struct smbcli_state * cli2 )
{
union smb_fileinfo finfo0 , finfo1 , finfo2 , finfo3 , finfo4 , finfo5 ;
union smb_fileinfo pinfo0 , pinfo1 , pinfo2 , pinfo3 , pinfo4 , pinfo5 , pinfo6 , pinfo7 ;
2008-09-09 01:58:58 +04:00
const char * fname = BASEDIR " \\ torture_file6.txt " ;
2007-12-01 13:43:38 +03:00
int fnum1 = - 1 ;
int fnum2 = - 1 ;
bool ret = true ;
ssize_t written ;
2008-04-08 12:25:51 +04:00
struct timeval start ;
struct timeval end ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2008-04-08 12:25:51 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
2007-12-01 13:43:38 +03:00
bool first = true ;
2008-09-09 01:58:58 +04:00
torture_comment ( tctx , " \n Running test_delayed_write_update6 \n " ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2007-12-01 13:43:38 +03:00
again :
torture_comment ( tctx , " Open the file handle \n " ) ;
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
if ( fnum2 = = - 1 ) {
torture_comment ( tctx , " Open the 2nd file handle on 2nd connection \n " ) ;
fnum2 = smbcli_open ( cli2 - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum2 = = - 1 ) {
ret = false ;
torture_result ( tctx , TORTURE_FAIL , __location__ " : unable to open %s " , fname ) ;
goto done ;
}
}
finfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo0 . basic_info . in . file . fnum = fnum1 ;
finfo1 = finfo0 ;
finfo2 = finfo0 ;
finfo3 = finfo0 ;
finfo4 = finfo0 ;
finfo5 = finfo0 ;
pinfo0 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
pinfo0 . basic_info . in . file . path = fname ;
pinfo1 = pinfo0 ;
pinfo2 = pinfo0 ;
pinfo3 = pinfo0 ;
pinfo4 = pinfo0 ;
pinfo5 = pinfo0 ;
pinfo6 = pinfo0 ;
pinfo7 = pinfo0 ;
/* get the initial times */
GET_INFO_BOTH ( finfo0 , pinfo0 ) ;
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
GET_INFO_BOTH ( finfo1 , pinfo1 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo1 , finfo0 ) ;
torture_comment ( tctx , " Set write time in the future on the 2nd file handle \n " ) ;
SET_INFO_FILE_EX ( finfo0 , time ( NULL ) + 86400 , cli2 - > tree , fnum2 ) ;
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_GREATER ( finfo2 , finfo1 ) ;
torture_comment ( tctx , " Set write time in the past on the 2nd file handle \n " ) ;
SET_INFO_FILE_EX ( finfo0 , time ( NULL ) - 86400 , cli2 - > tree , fnum2 ) ;
GET_INFO_BOTH ( finfo2 , pinfo2 ) ;
COMPARE_WRITE_TIME_LESS ( finfo2 , finfo1 ) ;
/* make sure the 2 second delay from the first write are canceled */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
2009-11-06 02:37:26 +03:00
end = timeval_add ( & start , 10 * sec , 0 ) ;
2008-04-08 12:25:51 +04:00
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* get the times after the first write */
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
if ( finfo3 . basic_info . out . write_time > finfo2 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo3 , pinfo3 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo3 , finfo2 ) ;
2008-09-06 08:47:06 +04:00
if ( finfo3 . basic_info . out . write_time = = finfo2 . basic_info . out . write_time ) {
2007-12-01 13:43:38 +03:00
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sure any further write doesn't update the write time */
2008-04-08 12:25:51 +04:00
start = timeval_current ( ) ;
2009-11-06 02:37:26 +03:00
end = timeval_add ( & start , 10 * sec , 0 ) ;
2008-04-08 12:25:51 +04:00
while ( ! timeval_expired ( & end ) ) {
2007-12-01 13:43:38 +03:00
/* do a write */
torture_comment ( tctx , " Do a write on the file handle \n " ) ;
written = smbcli_write ( cli - > tree , fnum1 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_BOTH ( finfo4 , pinfo4 ) ;
if ( finfo4 . basic_info . out . write_time > finfo3 . basic_info . out . write_time ) {
2008-04-08 12:25:51 +04:00
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2007-12-01 13:43:38 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2007-12-01 13:43:38 +03:00
}
GET_INFO_BOTH ( finfo4 , pinfo4 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo4 , finfo3 ) ;
if ( finfo4 . basic_info . out . write_time = = finfo3 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update write_time (correct) \n " ) ;
}
/* sleep */
2010-09-16 23:36:37 +04:00
smb_msleep ( 5 * msec ) ;
2007-12-01 13:43:38 +03:00
GET_INFO_BOTH ( finfo5 , pinfo5 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo5 , finfo4 ) ;
/*
* the close updates the write time to the time of the close
* as the write time was set on the 2 nd handle
*/
torture_comment ( tctx , " Close the file handle \n " ) ;
smbcli_close ( cli - > tree , fnum1 ) ;
fnum1 = - 1 ;
GET_INFO_PATH ( pinfo6 ) ;
COMPARE_WRITE_TIME_GREATER ( pinfo6 , pinfo5 ) ;
if ( pinfo6 . basic_info . out . write_time > pinfo5 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server updated the write_time on close (correct) \n " ) ;
}
2009-11-06 02:37:26 +03:00
/* See what the second write handle thinks the time is ? */
finfo5 . basic_info . in . file . fnum = fnum2 ;
GET_INFO_FILE2 ( finfo5 ) ;
COMPARE_WRITE_TIME_EQUAL ( finfo5 , pinfo6 ) ;
/* See if we have lost the sticky write time on handle2 */
2010-09-16 23:36:37 +04:00
smb_msleep ( 3 * msec ) ;
2009-11-06 02:37:26 +03:00
torture_comment ( tctx , " Have we lost the sticky write time ? \n " ) ;
/* Make sure any further normal write doesn't update the write time */
start = timeval_current ( ) ;
end = timeval_add ( & start , 10 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a write on the second file handle \n " ) ;
written = smbcli_write ( cli2 - > tree , fnum2 , 0 , " x " , 0 , 1 ) ;
if ( written ! = 1 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_FILE2 ( finfo5 ) ;
GET_INFO_PATH ( pinfo6 ) ;
if ( finfo5 . basic_info . out . write_time > pinfo6 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2009-11-06 02:37:26 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2009-11-06 02:37:26 +03:00
}
/* What about a truncate write ? */
start = timeval_current ( ) ;
end = timeval_add ( & start , 10 * sec , 0 ) ;
while ( ! timeval_expired ( & end ) ) {
/* do a write */
torture_comment ( tctx , " Do a truncate write on the second file handle \n " ) ;
written = smbcli_write ( cli2 - > tree , fnum2 , 0 , " x " , 0 , 0 ) ;
if ( written ! = 0 ) {
torture_result ( tctx , TORTURE_FAIL , __location__ " : written gave %d - should have been 1 " , ( int ) written ) ;
ret = false ;
goto done ;
}
/* get the times after the write */
GET_INFO_FILE2 ( finfo5 ) ;
GET_INFO_PATH ( pinfo6 ) ;
if ( finfo5 . basic_info . out . write_time > pinfo6 . basic_info . out . write_time ) {
double diff = timeval_elapsed ( & start ) ;
2014-06-11 12:51:30 +04:00
torture_result ( tctx , TORTURE_FAIL , " Server updated write_time after %.2f seconds "
2014-06-20 14:28:53 +04:00
" (wrong!) \n " ,
diff ) ;
2009-11-06 02:37:26 +03:00
ret = false ;
break ;
}
2010-09-16 23:36:37 +04:00
smb_msleep ( 1 * msec ) ;
2009-11-06 02:37:26 +03:00
}
2007-12-01 13:43:38 +03:00
/* keep the 2nd handle open and rerun tests */
if ( first ) {
first = false ;
goto again ;
}
/*
* closing the 2 nd handle will cause no write time update
* as the write time was explicit set on this handle
*/
torture_comment ( tctx , " Close the 2nd file handle \n " ) ;
smbcli_close ( cli2 - > tree , fnum2 ) ;
fnum2 = - 1 ;
GET_INFO_PATH ( pinfo7 ) ;
COMPARE_WRITE_TIME_EQUAL ( pinfo7 , pinfo6 ) ;
if ( pinfo7 . basic_info . out . write_time = = pinfo6 . basic_info . out . write_time ) {
torture_comment ( tctx , " Server did not update the write_time on close (correct) \n " ) ;
}
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
if ( fnum2 ! = - 1 )
smbcli_close ( cli2 - > tree , fnum2 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2009-09-15 05:45:16 +04:00
static bool test_delayed_write_update7 ( struct torture_context * tctx , struct smbcli_state * cli )
{
union smb_open open_parms ;
union smb_fileinfo finfo1 , finfo2 , finfo3 ;
const char * fname = BASEDIR " \\ torture_file7.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
bool ret = true ;
TALLOC_CTX * mem_ctx ;
torture_comment ( tctx , " \n Running test_delayed_write_update7 (timestamp resolution test) \n " ) ;
mem_ctx = talloc_init ( " test_delayed_write_update7 " ) ;
if ( ! mem_ctx ) return false ;
ZERO_STRUCT ( finfo1 ) ;
ZERO_STRUCT ( finfo2 ) ;
ZERO_STRUCT ( finfo3 ) ;
ZERO_STRUCT ( open_parms ) ;
2012-05-18 09:43:31 +04:00
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
2009-09-15 05:45:16 +04:00
/* Create the file. */
fnum1 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum1 = = - 1 ) {
torture_result ( tctx , TORTURE_FAIL , " Failed to open %s " , fname ) ;
return false ;
}
finfo1 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
finfo1 . basic_info . in . file . fnum = fnum1 ;
finfo2 = finfo1 ;
finfo3 = finfo1 ;
/* Get the initial timestamps. */
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo1 ) ;
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
/* Set the pending write time to a value with ns. */
SET_INFO_FILE_NS ( finfo , time ( NULL ) + 86400 , 103 , cli - > tree , fnum1 ) ;
/* Get the current pending write time by fnum. */
status = smb_raw_fileinfo ( cli - > tree , tctx , & finfo2 ) ;
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
/* Ensure the time is actually different. */
if ( finfo1 . basic_info . out . write_time = = finfo2 . basic_info . out . write_time ) {
torture_result ( tctx , TORTURE_FAIL ,
" setfileinfo time matches original fileinfo time " ) ;
ret = false ;
}
/* Get the current pending write time by path. */
finfo3 . basic_info . in . file . path = fname ;
status = smb_raw_pathinfo ( cli - > tree , tctx , & finfo3 ) ;
if ( finfo2 . basic_info . out . write_time ! = finfo3 . basic_info . out . write_time ) {
torture_result ( tctx , TORTURE_FAIL ,
" qpathinfo time doens't match fileinfo time " ) ;
ret = false ;
}
/* Now close the file. Re-open and check that the write
time is identical to the one we wrote . */
smbcli_close ( cli - > tree , fnum1 ) ;
open_parms . ntcreatex . level = RAW_OPEN_NTCREATEX ;
open_parms . ntcreatex . in . flags = 0 ;
open_parms . ntcreatex . in . access_mask = SEC_GENERIC_READ ;
open_parms . ntcreatex . in . file_attr = 0 ;
open_parms . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE ;
open_parms . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
open_parms . ntcreatex . in . create_options = 0 ;
open_parms . ntcreatex . in . fname = fname ;
status = smb_raw_open ( cli - > tree , mem_ctx , & open_parms ) ;
talloc_free ( mem_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
torture_result ( tctx , TORTURE_FAIL ,
" setfileinfo time matches original fileinfo time " ) ;
ret = false ;
}
fnum1 = open_parms . ntcreatex . out . file . fnum ;
/* Check the returned time matches. */
if ( open_parms . ntcreatex . out . write_time ! = finfo2 . basic_info . out . write_time ) {
torture_result ( tctx , TORTURE_FAIL ,
" final open time does not match set time " ) ;
ret = false ;
}
done :
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2013-12-04 05:26:26 +04:00
/*
Test if creating a file in a directory with an open handle updates the
write timestamp ( it should ) .
*/
static bool test_directory_update8 ( struct torture_context * tctx , struct smbcli_state * cli )
{
union smb_fileinfo dir_info1 , dir_info2 ;
union smb_open open_parms ;
const char * fname = BASEDIR " \\ torture_file.txt " ;
NTSTATUS status ;
int fnum1 = - 1 ;
int fnum2 = - 1 ;
bool ret = true ;
2014-06-20 14:28:48 +04:00
double used_delay = torture_setting_int ( tctx , " writetimeupdatedelay " , 2000000 ) ;
2013-12-04 05:26:26 +04:00
int normal_delay = 2000000 ;
double sec = ( ( double ) used_delay ) / ( ( double ) normal_delay ) ;
int msec = 1000 * sec ;
TALLOC_CTX * mem_ctx = talloc_init ( " test_delayed_write_update8 " ) ;
if ( ! mem_ctx ) return false ;
torture_comment ( tctx , " \n Running test directory write update \n " ) ;
torture_assert ( tctx , torture_setup_dir ( cli , BASEDIR ) , " Failed to setup up test directory: " BASEDIR ) ;
/* Open a handle on the directory - and leave it open. */
ZERO_STRUCT ( open_parms ) ;
open_parms . ntcreatex . level = RAW_OPEN_NTCREATEX ;
open_parms . ntcreatex . in . flags = 0 ;
open_parms . ntcreatex . in . access_mask = SEC_RIGHTS_FILE_READ ;
open_parms . ntcreatex . in . file_attr = 0 ;
open_parms . ntcreatex . in . share_access = NTCREATEX_SHARE_ACCESS_DELETE |
NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE ;
open_parms . ntcreatex . in . open_disposition = NTCREATEX_DISP_OPEN ;
open_parms . ntcreatex . in . create_options = NTCREATEX_OPTIONS_DIRECTORY ;
open_parms . ntcreatex . in . fname = BASEDIR ;
status = smb_raw_open ( cli - > tree , mem_ctx , & open_parms ) ;
talloc_free ( mem_ctx ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
torture_result ( tctx , TORTURE_FAIL ,
" failed to open directory handle " ) ;
ret = false ;
goto done ;
}
fnum1 = open_parms . ntcreatex . out . file . fnum ;
/* Store the returned write time. */
ZERO_STRUCT ( dir_info1 ) ;
dir_info1 . basic_info . out . write_time = open_parms . ntcreatex . out . write_time ;
torture_comment ( tctx , " Initial write time %s \n " ,
nt_time_string ( tctx , dir_info1 . basic_info . out . write_time ) ) ;
/* sleep */
smb_msleep ( 3 * msec ) ;
/* Now create a file within the directory. */
fnum2 = smbcli_open ( cli - > tree , fname , O_RDWR | O_CREAT , DENY_NONE ) ;
if ( fnum2 = = - 1 ) {
torture_result ( tctx , TORTURE_FAIL , " Failed to open %s " , fname ) ;
ret = false ;
goto done ;
}
smbcli_close ( cli - > tree , fnum2 ) ;
/* Read the directory write time again. */
ZERO_STRUCT ( dir_info2 ) ;
dir_info2 . basic_info . level = RAW_FILEINFO_BASIC_INFO ;
dir_info2 . basic_info . in . file . fnum = fnum1 ;
status = smb_raw_fileinfo ( cli - > tree , tctx , & dir_info2 ) ;
torture_assert_ntstatus_ok ( tctx , status , " fileinfo failed " ) ;
/* Ensure it's been incremented. */
COMPARE_WRITE_TIME_GREATER ( dir_info2 , dir_info1 ) ;
torture_comment ( tctx , " Updated write time %s \n " ,
nt_time_string ( tctx , dir_info2 . basic_info . out . write_time ) ) ;
done :
if ( fnum1 ! = - 1 )
smbcli_close ( cli - > tree , fnum1 ) ;
smbcli_unlink ( cli - > tree , fname ) ;
smbcli_deltree ( cli - > tree , BASEDIR ) ;
return ret ;
}
2008-09-13 01:59:32 +04:00
/*
2004-11-12 12:37:59 +03:00
testing of delayed update of write_time
*/
2017-04-25 01:07:49 +03:00
struct torture_suite * torture_delay_write ( TALLOC_CTX * ctx )
2004-11-12 12:37:59 +03:00
{
2017-04-25 01:07:49 +03:00
struct torture_suite * suite = torture_suite_create ( ctx , " delaywrite " ) ;
2004-11-12 12:37:59 +03:00
2006-10-16 17:06:41 +04:00
torture_suite_add_2smb_test ( suite , " finfo update on close " , test_finfo_after_write ) ;
torture_suite_add_1smb_test ( suite , " delayed update of write time " , test_delayed_write_update ) ;
2008-09-18 18:05:46 +04:00
torture_suite_add_1smb_test ( suite , " update of write time and SMBwrite truncate " , test_delayed_write_update1 ) ;
2008-09-08 10:31:34 +04:00
torture_suite_add_1smb_test ( suite , " update of write time and SMBwrite truncate expand " , test_delayed_write_update1a ) ;
2008-09-06 01:24:36 +04:00
torture_suite_add_1smb_test ( suite , " update of write time using SET_END_OF_FILE " , test_delayed_write_update1b ) ;
torture_suite_add_1smb_test ( suite , " update of write time using SET_ALLOCATION_SIZE " , test_delayed_write_update1c ) ;
2006-10-16 17:06:41 +04:00
torture_suite_add_2smb_test ( suite , " delayed update of write time using 2 connections " , test_delayed_write_update2 ) ;
2007-12-01 13:43:38 +03:00
torture_suite_add_2smb_test ( suite , " delayed update of write time 3 " , test_delayed_write_update3 ) ;
2008-09-08 15:59:51 +04:00
torture_suite_add_2smb_test ( suite , " delayed update of write time 3a " , test_delayed_write_update3a ) ;
2008-09-08 14:12:25 +04:00
torture_suite_add_2smb_test ( suite , " delayed update of write time 3b " , test_delayed_write_update3b ) ;
2008-09-08 16:11:17 +04:00
torture_suite_add_2smb_test ( suite , " delayed update of write time 3c " , test_delayed_write_update3c ) ;
2007-12-01 13:43:38 +03:00
torture_suite_add_2smb_test ( suite , " delayed update of write time 4 " , test_delayed_write_update4 ) ;
torture_suite_add_2smb_test ( suite , " delayed update of write time 5 " , test_delayed_write_update5 ) ;
2008-09-08 14:27:43 +04:00
torture_suite_add_2smb_test ( suite , " delayed update of write time 5b " , test_delayed_write_update5b ) ;
2007-12-01 13:43:38 +03:00
torture_suite_add_2smb_test ( suite , " delayed update of write time 6 " , test_delayed_write_update6 ) ;
2009-09-15 05:45:16 +04:00
torture_suite_add_1smb_test ( suite , " timestamp resolution test " , test_delayed_write_update7 ) ;
2013-12-04 05:26:26 +04:00
torture_suite_add_1smb_test ( suite , " directory timestamp update test " , test_directory_update8 ) ;
2004-11-12 12:37:59 +03:00
2006-10-16 17:06:41 +04:00
return suite ;
2004-11-12 12:37:59 +03:00
}