mirror of
https://github.com/samba-team/samba.git
synced 2024-12-25 23:21:54 +03:00
r5720: Attempt to fix bug #2382 (Excel shared workbook stops working). Also
incorporates part of the fix created by ke_miyata@itg.hitachi.co.jp for bug #2045 (MS-Office behavior of timestamp). Jeremy.
This commit is contained in:
parent
5c682c665d
commit
4f3b12ac73
@ -37,6 +37,13 @@ static files_struct *oplock_save_chain_fsp = NULL;
|
||||
|
||||
static int files_used;
|
||||
|
||||
/* A singleton cache to speed up searching by dev/inode. */
|
||||
static struct fsp_singleton_cache {
|
||||
files_struct *fsp;
|
||||
SMB_DEV_T dev;
|
||||
SMB_INO_T inode;
|
||||
} fsp_fi_cache;
|
||||
|
||||
/****************************************************************************
|
||||
Return a unique number identifying this fsp over the life of this pid.
|
||||
****************************************************************************/
|
||||
@ -122,6 +129,11 @@ files_struct *file_new(connection_struct *conn)
|
||||
i, fsp->fnum, files_used));
|
||||
|
||||
chain_fsp = fsp;
|
||||
|
||||
/* A new fsp invalidates a negative fsp_fi_cache. */
|
||||
if (fsp_fi_cache.fsp == NULL) {
|
||||
ZERO_STRUCT(fsp_fi_cache);
|
||||
}
|
||||
|
||||
return fsp;
|
||||
}
|
||||
@ -299,19 +311,34 @@ files_struct *file_find_fsp(files_struct *orig_fsp)
|
||||
|
||||
/****************************************************************************
|
||||
Find the first fsp given a device and inode.
|
||||
We use a singleton cache here to speed up searching from getfilepathinfo
|
||||
calls.
|
||||
****************************************************************************/
|
||||
|
||||
files_struct *file_find_di_first(SMB_DEV_T dev, SMB_INO_T inode)
|
||||
{
|
||||
files_struct *fsp;
|
||||
|
||||
if (fsp_fi_cache.dev == dev && fsp_fi_cache.inode == inode) {
|
||||
/* Positive or negative cache hit. */
|
||||
return fsp_fi_cache.fsp;
|
||||
}
|
||||
|
||||
fsp_fi_cache.dev = dev;
|
||||
fsp_fi_cache.inode = inode;
|
||||
|
||||
for (fsp=Files;fsp;fsp=fsp->next) {
|
||||
if ( fsp->fd != -1 &&
|
||||
fsp->dev == dev &&
|
||||
fsp->inode == inode )
|
||||
fsp->inode == inode ) {
|
||||
/* Setup positive cache. */
|
||||
fsp_fi_cache.fsp = fsp;
|
||||
return fsp;
|
||||
}
|
||||
}
|
||||
|
||||
/* Setup negative cache. */
|
||||
fsp_fi_cache.fsp = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -342,12 +369,35 @@ files_struct *file_find_print(void)
|
||||
files_struct *fsp;
|
||||
|
||||
for (fsp=Files;fsp;fsp=fsp->next) {
|
||||
if (fsp->print_file) return fsp;
|
||||
if (fsp->print_file) {
|
||||
return fsp;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Set a pending modtime across all files with a given dev/ino pair.
|
||||
****************************************************************************/
|
||||
|
||||
void fsp_set_pending_modtime(files_struct *tfsp, time_t pmod)
|
||||
{
|
||||
files_struct *fsp;
|
||||
|
||||
if (null_mtime(pmod)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (fsp = Files;fsp;fsp=fsp->next) {
|
||||
if ( fsp->fd != -1 &&
|
||||
fsp->dev == tfsp->dev &&
|
||||
fsp->inode == tfsp->inode ) {
|
||||
fsp->pending_modtime = pmod;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
Sync open files on a connection.
|
||||
****************************************************************************/
|
||||
@ -392,6 +442,11 @@ void file_free(files_struct *fsp)
|
||||
chain_fsp = NULL;
|
||||
}
|
||||
|
||||
/* Closing a file can invalidate the positive cache. */
|
||||
if (fsp == fsp_fi_cache.fsp) {
|
||||
ZERO_STRUCT(fsp_fi_cache);
|
||||
}
|
||||
|
||||
SAFE_FREE(fsp);
|
||||
}
|
||||
|
||||
|
@ -1698,7 +1698,7 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new
|
||||
close_file(fsp1,False);
|
||||
|
||||
/* Ensure the modtime is set correctly on the destination file. */
|
||||
fsp2->pending_modtime = sbuf1.st_mtime;
|
||||
fsp_set_pending_modtime(fsp2, sbuf1.st_mtime);
|
||||
|
||||
close_ret = close_file(fsp2,False);
|
||||
|
||||
|
@ -2875,6 +2875,13 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
fsp->fd, fsp->fnum,
|
||||
conn->num_files_open));
|
||||
|
||||
/*
|
||||
* Take care of any time sent in the close.
|
||||
*/
|
||||
|
||||
mtime = make_unix_date3(inbuf+smb_vwv1);
|
||||
fsp_set_pending_modtime(fsp, mtime);
|
||||
|
||||
/*
|
||||
* close_file() returns the unix errno if an error
|
||||
* was detected on close - normally this is due to
|
||||
@ -2886,16 +2893,6 @@ int reply_close(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
END_PROFILE(SMBclose);
|
||||
return (UNIXERROR(ERRHRD,ERRgeneral));
|
||||
}
|
||||
|
||||
/*
|
||||
* Now take care of any time sent in the close.
|
||||
*/
|
||||
|
||||
mtime = make_unix_date3(inbuf+smb_vwv1);
|
||||
|
||||
/* try and set the date */
|
||||
set_filetime(conn, file_name, mtime);
|
||||
|
||||
}
|
||||
|
||||
/* We have a cached error */
|
||||
@ -4233,7 +4230,7 @@ static BOOL copy_file(char *src,char *dest1,connection_struct *conn, int ofun,
|
||||
close_file(fsp1,False);
|
||||
|
||||
/* Ensure the modtime is set correctly on the destination file. */
|
||||
fsp2->pending_modtime = src_sbuf.st_mtime;
|
||||
fsp_set_pending_modtime( fsp2, src_sbuf.st_mtime);
|
||||
|
||||
/*
|
||||
* As we are opening fsp1 read-only we only expect
|
||||
@ -4917,7 +4914,7 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
* Sometimes times are sent as zero - ignore them.
|
||||
*/
|
||||
|
||||
if ((unix_times.actime == 0) && (unix_times.modtime == 0)) {
|
||||
if (null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
|
||||
/* Ignore request */
|
||||
if( DEBUGLVL( 3 ) ) {
|
||||
dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
|
||||
@ -4925,12 +4922,13 @@ int reply_setattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
}
|
||||
END_PROFILE(SMBsetattrE);
|
||||
return(outsize);
|
||||
} else if ((unix_times.actime != 0) && (unix_times.modtime == 0)) {
|
||||
/* set modify time = to access time if modify time was 0 */
|
||||
} else if (!null_mtime(unix_times.actime) && null_mtime(unix_times.modtime)) {
|
||||
/* set modify time = to access time if modify time was unset */
|
||||
unix_times.modtime = unix_times.actime;
|
||||
}
|
||||
|
||||
/* Set the date on this file */
|
||||
/* Should we set pending modtime here ? JRA */
|
||||
if(file_utime(conn, fsp->fsp_name, &unix_times)) {
|
||||
END_PROFILE(SMBsetattrE);
|
||||
return ERROR_DOS(ERRDOS,ERRnoaccess);
|
||||
@ -5170,6 +5168,7 @@ int reply_getattrE(connection_struct *conn, char *inbuf,char *outbuf, int size,
|
||||
|
||||
put_dos_date2(outbuf,smb_vwv0,get_create_time(&sbuf,lp_fake_dir_create_times(SNUM(conn))));
|
||||
put_dos_date2(outbuf,smb_vwv2,sbuf.st_atime);
|
||||
/* Should we check pending modtime here ? JRA */
|
||||
put_dos_date2(outbuf,smb_vwv4,sbuf.st_mtime);
|
||||
|
||||
if (mode & aDIR) {
|
||||
|
@ -2469,9 +2469,18 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char *
|
||||
|
||||
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 (fsp) {
|
||||
if (fsp->pending_modtime) {
|
||||
/* the pending modtime overrides the current modtime */
|
||||
sbuf.st_mtime = fsp->pending_modtime;
|
||||
}
|
||||
} else {
|
||||
/* Do we have this path open ? */
|
||||
files_struct *fsp1 = file_find_di_first(sbuf.st_dev, sbuf.st_ino);
|
||||
if (fsp1 && fsp1->pending_modtime) {
|
||||
/* the pending modtime overrides the current modtime */
|
||||
sbuf.st_mtime = fsp1->pending_modtime;
|
||||
}
|
||||
}
|
||||
|
||||
if (lp_dos_filetime_resolution(SNUM(conn))) {
|
||||
@ -3323,9 +3332,9 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char
|
||||
tvs.modtime = write_time;
|
||||
}
|
||||
/* Prefer a defined time to an undefined one. */
|
||||
if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
|
||||
tvs.modtime = (write_time == (time_t)0 || write_time == (time_t)-1
|
||||
? changed_time : write_time);
|
||||
if (null_mtime(tvs.modtime)) {
|
||||
tvs.modtime = null_mtime(write_time) ? changed_time : write_time;
|
||||
}
|
||||
|
||||
/* attributes */
|
||||
dosmode = IVAL(pdata,32);
|
||||
@ -3805,11 +3814,13 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
}
|
||||
|
||||
/* get some defaults (no modifications) if any info is zero or -1. */
|
||||
if (tvs.actime == (time_t)0 || tvs.actime == (time_t)-1)
|
||||
if (null_mtime(tvs.actime)) {
|
||||
tvs.actime = sbuf.st_atime;
|
||||
}
|
||||
|
||||
if (tvs.modtime == (time_t)0 || tvs.modtime == (time_t)-1)
|
||||
if (null_mtime(tvs.modtime)) {
|
||||
tvs.modtime = sbuf.st_mtime;
|
||||
}
|
||||
|
||||
DEBUG(6,("actime: %s " , ctime(&tvs.actime)));
|
||||
DEBUG(6,("modtime: %s ", ctime(&tvs.modtime)));
|
||||
@ -3841,30 +3852,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
* Try and set the times, size and mode of this file -
|
||||
* if they are different from the current values
|
||||
*/
|
||||
if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
|
||||
if(fsp != NULL) {
|
||||
/*
|
||||
* This was a setfileinfo on an open file.
|
||||
* 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) {
|
||||
DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
|
||||
fsp->pending_modtime = tvs.modtime;
|
||||
}
|
||||
|
||||
DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
|
||||
|
||||
if(file_utime(conn, fname, &tvs)!=0) {
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check the mode isn't different, before changing it */
|
||||
if ((dosmode != 0) && (dosmode != dos_mode(conn, fname, &sbuf))) {
|
||||
@ -3877,6 +3864,7 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
}
|
||||
}
|
||||
|
||||
/* Now the size. */
|
||||
if (size != get_file_size(sbuf)) {
|
||||
|
||||
int ret;
|
||||
@ -3917,6 +3905,34 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n",
|
||||
return (UNIXERROR(ERRHRD,ERRdiskfull));
|
||||
}
|
||||
|
||||
/*
|
||||
* Finally the times.
|
||||
*/
|
||||
if (sbuf.st_mtime != tvs.modtime || sbuf.st_atime != tvs.actime) {
|
||||
if(fsp != NULL) {
|
||||
/*
|
||||
* This was a setfileinfo on an open file.
|
||||
* 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) {
|
||||
DEBUG(10,("call_trans2setfilepathinfo: setting pending modtime to %s\n", ctime(&tvs.modtime) ));
|
||||
fsp_set_pending_modtime(fsp, tvs.modtime);
|
||||
}
|
||||
|
||||
}
|
||||
DEBUG(10,("call_trans2setfilepathinfo: setting utimes to modified values.\n"));
|
||||
|
||||
if(file_utime(conn, fname, &tvs)!=0) {
|
||||
return(UNIXERROR(ERRDOS,ERRnoaccess));
|
||||
}
|
||||
}
|
||||
|
||||
SSVAL(params,0,0);
|
||||
send_trans2_replies(outbuf, bufsize, params, 2, *ppdata, 0);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user