Author: jra Date: 2004-11-20 21:24:52 +0000 (Sat, 20 Nov 2004) New Revision: 3895
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=3895 Log: Fix for bug #2045. May also fix other timestamp bugs with Excel (Volker please test). Setting a last write timestamp from Windows overrides any subsequent write timestamp changes and must be immediately seen by and findfirst/findnexts. This is a racy solution, but should work most of the time. This may also fix #1061, not sure. Jeremy. Modified: branches/SAMBA_3_0/source/smbd/fileio.c branches/SAMBA_3_0/source/smbd/trans2.c Changeset: Modified: branches/SAMBA_3_0/source/smbd/fileio.c =================================================================== --- branches/SAMBA_3_0/source/smbd/fileio.c 2004-11-20 21:24:43 UTC (rev 3894) +++ branches/SAMBA_3_0/source/smbd/fileio.c 2004-11-20 21:24:52 UTC (rev 3895) @@ -130,6 +130,20 @@ if (ret != -1) { fsp->pos += ret; + /* + * It turns out that setting the last write time from a Windows + * client stops any subsequent writes from updating the write time. + * Doing this after the write gives a race condition here where + * a stat may see the changed write time before we reset it here, + * but it's cheaper than having to store the write time in shared + * memory and look it up using dev/inode across all running smbd's. + * The 99% solution will hopefully be good enough in this case. JRA. + */ + + if (fsp->pending_modtime) { + set_filetime(fsp->conn, fsp->fsp_name, fsp->pending_modtime); + } + /* Yes - this is correct - writes don't update this. JRA. */ /* Found by Samba4 tests. */ #if 0 Modified: branches/SAMBA_3_0/source/smbd/trans2.c =================================================================== --- branches/SAMBA_3_0/source/smbd/trans2.c 2004-11-20 21:24:43 UTC (rev 3894) +++ branches/SAMBA_3_0/source/smbd/trans2.c 2004-11-20 21:24:52 UTC (rev 3895) @@ -2540,6 +2540,11 @@ c_time = get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + if (fsp && fsp->pending_modtime) { + /* the pending modtime overrides the current modtime */ + sbuf.st_mtime = fsp->pending_modtime; + } + if (lp_dos_filetime_resolution(SNUM(conn))) { c_time &= ~1; sbuf.st_atime &= ~1; @@ -3904,10 +3909,12 @@ if(fsp != NULL) { /* * This was a setfileinfo on an open file. - * NT does this a lot. It's actually pointless - * setting the time here, as it will be overwritten - * on the next write, so we save the request - * away and will set it on file close. JRA. + * NT does this a lot. We also need to + * set the time here, as it can be read by + * FindFirst/FindNext and with the patch for bug #2045 + * in smbd/fileio.c it ensures that this timestamp is + * kept sticky even after a write. We save the request + * away and will set it on file close and after a write. JRA. */ if (tvs.modtime != (time_t)0 && tvs.modtime != (time_t)-1) { @@ -3915,12 +3922,11 @@ fsp->pending_modtime = tvs.modtime; } - } else { - DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n")); - if(file_utime(conn, fname, &tvs)!=0) + if(file_utime(conn, fname, &tvs)!=0) { return(UNIXERROR(ERRDOS,ERRnoaccess)); + } } }