diff options
-rw-r--r-- | source3/include/smb.h | 10 | ||||
-rw-r--r-- | source3/smbd/close.c | 78 | ||||
-rw-r--r-- | source3/smbd/dir.c | 8 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 42 | ||||
-rw-r--r-- | source3/smbd/fileio.c | 60 | ||||
-rw-r--r-- | source3/smbd/files.c | 29 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 61 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 85 |
9 files changed, 242 insertions, 133 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h index 73695da7f0..d52d8493d0 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -485,9 +485,13 @@ typedef struct files_struct { struct timeval open_time; uint32 access_mask; /* NTCreateX access bits (FILE_READ_DATA etc.) */ uint32 share_access; /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */ - bool pending_modtime_owner; - struct timespec pending_modtime; - struct timespec last_write_time; + + bool update_write_time_triggered; + struct timed_event *update_write_time_event; + bool update_write_time_on_close; + struct timespec close_write_time; + bool write_time_forced; + int oplock_type; int sent_oplock_break; struct timed_event *oplock_timeout; diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 8a5c82cc93..3afc037f69 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -255,6 +255,10 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, return NT_STATUS_INVALID_PARAMETER; } + if (fsp->write_time_forced) { + set_close_write_time(fsp, lck->changed_write_time); + } + if (!del_share_mode(lck, fsp)) { DEBUG(0, ("close_remove_share_mode: Could not delete share " "entry for file %s\n", fsp->fsp_name)); @@ -317,6 +321,11 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set " "- deleting file.\n", fsp->fsp_name)); + /* + * Don't try to update the write time when we delete the file + */ + fsp->update_write_time_on_close = false; + if (!unix_token_equal(lck->delete_token, ¤t_user.ut)) { /* Become the user who requested the delete. */ @@ -428,6 +437,66 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, return status; } +void set_close_write_time(struct files_struct *fsp, struct timespec ts) +{ + DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts)))); + + if (null_timespec(ts)) { + return; + } + /* + * if the write time on close is explict set, then don't + * need to fix it up to the value in the locking db + */ + fsp->write_time_forced = false; + + fsp->update_write_time_on_close = true; + fsp->close_write_time = ts; +} + +static NTSTATUS update_write_time_on_close(struct files_struct *fsp) +{ + SMB_STRUCT_STAT sbuf; + struct timespec ts[2]; + NTSTATUS status; + + ZERO_STRUCT(sbuf); + ZERO_STRUCT(ts); + + if (!fsp->update_write_time_on_close) { + return NT_STATUS_OK; + } + + if (null_timespec(fsp->close_write_time)) { + fsp->close_write_time = timespec_current(); + } + + /* Ensure we have a valid stat struct for the source. */ + if (fsp->fh->fd != -1) { + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + return map_nt_error_from_unix(errno); + } + } else { + if (SMB_VFS_STAT(fsp->conn,fsp->fsp_name,&sbuf) == -1) { + return map_nt_error_from_unix(errno); + } + } + + if (!VALID_STAT(sbuf)) { + /* if it doesn't seem to be a real file */ + return NT_STATUS_OK; + } + + ts[1] = fsp->close_write_time; + status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, + &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + return NT_STATUS_OK; +} + /**************************************************************************** Close a file. @@ -442,6 +511,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ NTSTATUS saved_status1 = NT_STATUS_OK; NTSTATUS saved_status2 = NT_STATUS_OK; NTSTATUS saved_status3 = NT_STATUS_OK; + NTSTATUS saved_status4 = NT_STATUS_OK; connection_struct *conn = fsp->conn; if (fsp->aio_write_behind) { @@ -496,11 +566,7 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ * Ensure pending modtime is set after close. */ - if (fsp->pending_modtime_owner && !null_timespec(fsp->pending_modtime)) { - set_filetime(conn, fsp->fsp_name, fsp->pending_modtime); - } else if (!null_timespec(fsp->last_write_time)) { - set_filetime(conn, fsp->fsp_name, fsp->last_write_time); - } + saved_status4 = update_write_time_on_close(fsp); if (NT_STATUS_IS_OK(status)) { if (!NT_STATUS_IS_OK(saved_status1)) { @@ -509,6 +575,8 @@ static NTSTATUS close_normal_file(files_struct *fsp, enum file_close_type close_ status = saved_status2; } else if (!NT_STATUS_IS_OK(saved_status3)) { status = saved_status3; + } else if (!NT_STATUS_IS_OK(saved_status4)) { + status = saved_status4; } } diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index ca6f8bfd8d..8531d6250d 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -841,6 +841,8 @@ bool get_dir_entry(TALLOC_CTX *ctx, mask_match_search(filename,mask,False) || mangle_mask_match(conn,filename,mask)) { char mname[13]; + struct timespec write_time_ts; + struct file_id fileid; if (!mangle_is_8_3(filename, False, conn->params)) { if (!name_to_8_3(filename,mname,False, @@ -883,6 +885,12 @@ bool get_dir_entry(TALLOC_CTX *ctx, *size = sbuf.st_size; *date = sbuf.st_mtime; + fileid = vfs_file_id_from_sbuf(conn, &sbuf); + write_time_ts = get_write_time(fileid); + if (!null_timespec(write_time_ts)) { + *date = convert_timespec_to_time_t(write_time_ts); + } + DEBUG(3,("get_dir_entry mask=[%s] found %s " "fname=%s (%s)\n", mask, diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index a2e617c117..0ac3873275 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -571,6 +571,11 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe errno = 0; ZERO_STRUCT(sbuf); + DEBUG(6, ("file_ntime: actime: %s", + time_to_asc(convert_timespec_to_time_t(ts[0])))); + DEBUG(6, ("file_ntime: modtime: %s", + time_to_asc(convert_timespec_to_time_t(ts[1])))); + /* Don't update the time on read-only shares */ /* We need this as set_filetime (which can be called on close and other paths) can end up calling this function @@ -615,26 +620,35 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe Change a filetime - possibly allowing DOS semantics. *******************************************************************/ -bool set_filetime(connection_struct *conn, const char *fname, - const struct timespec mtime) +bool set_write_time_path(connection_struct *conn, const char *fname, + struct file_id fileid, const struct timespec mtime, + bool overwrite) { - struct timespec ts[2]; - if (null_timespec(mtime)) { - return(True); + return true; } - ts[1] = mtime; /* mtime. */ - ts[0] = ts[1]; /* atime. */ - - if (file_ntimes(conn, fname, ts)) { - DEBUG(4,("set_filetime(%s) failed: %s\n", - fname,strerror(errno))); - return False; + if (!set_write_time(fileid, mtime, overwrite)) { + return false; } - notify_fname(conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_LAST_WRITE, fname); + /* in the overwrite case the caller should trigger the notify */ + if (!overwrite) { + notify_fname(conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_LAST_WRITE, fname); + } return true; } + +bool set_write_time_fsp(struct files_struct *fsp, const struct timespec mtime, + bool overwrite) +{ + if (overwrite) { + fsp->write_time_forced = true; + TALLOC_FREE(fsp->update_write_time_event); + } + + return set_write_time_path(fsp->conn, fsp->fsp_name, fsp->file_id, + mtime, overwrite); +} diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 8cea4989f5..93a303f6c8 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -142,27 +142,6 @@ static ssize_t real_write_file(struct smb_request *req, if (ret != -1) { fsp->fh->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 (!null_timespec(fsp->pending_modtime)) { - set_filetime(fsp->conn, fsp->fsp_name, - fsp->pending_modtime); - - /* If we didn't get the "set modtime" call ourselves, we must - store the last write time to restore on close. JRA. */ - if (!fsp->pending_modtime_owner) { - fsp->last_write_time = timespec_current(); - } - } - /* Yes - this is correct - writes don't update this. JRA. */ /* Found by Samba4 tests. */ #if 0 @@ -192,6 +171,41 @@ static int wcp_file_size_change(files_struct *fsp) return ret; } +static void update_write_time_handler(struct event_context *ctx, + struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + files_struct *fsp = (files_struct *)private_data; + + /* Remove the timed event handler. */ + TALLOC_FREE(fsp->update_write_time_event); + DEBUG(5, ("Update write time on %s\n", fsp->fsp_name)); + + /* change the write time if not already changed by someoneelse */ + set_write_time_fsp(fsp, timespec_current(), false); +} + +void trigger_write_time_update(struct files_struct *fsp) +{ + if (fsp->write_time_forced) { + return; + } + + if (fsp->update_write_time_triggered) { + return; + } + fsp->update_write_time_triggered = true; + + /* trigger the update 2 seconds later */ + fsp->update_write_time_on_close = true; + fsp->update_write_time_event = + event_add_timed(smbd_event_context(), NULL, + timeval_current_ofs(2, 0), + "update_write_time_handler", + update_write_time_handler, fsp); +} + /**************************************************************************** Write to a file. ****************************************************************************/ @@ -230,7 +244,9 @@ ssize_t write_file(struct smb_request *req, fsp->modified = True; if (SMB_VFS_FSTAT(fsp, &st) == 0) { - int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); + int dosmode; + trigger_write_time_update(fsp); + dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st); if ((lp_store_dos_attributes(SNUM(fsp->conn)) || MAP_ARCHIVE(fsp->conn)) && !IS_DOS_ARCHIVE(dosmode)) { diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 95f01b88ce..d6e91c67be 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -375,29 +375,6 @@ files_struct *file_find_print(void) } /**************************************************************************** - Set a pending modtime across all files with a given dev/ino pair. - Record the owner of that modtime. -****************************************************************************/ - -void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod) -{ - files_struct *fsp; - - if (null_timespec(mod)) { - return; - } - - for (fsp = Files;fsp;fsp=fsp->next) { - if ( fsp->fh->fd != -1 && file_id_equal(&fsp->file_id, &tfsp->file_id)) { - fsp->pending_modtime = mod; - fsp->pending_modtime_owner = False; - } - } - - tfsp->pending_modtime_owner = True; -} - -/**************************************************************************** Sync open files on a connection. ****************************************************************************/ @@ -441,6 +418,9 @@ void file_free(files_struct *fsp) /* Ensure this event will never fire. */ TALLOC_FREE(fsp->oplock_timeout); + /* Ensure this event will never fire. */ + TALLOC_FREE(fsp->update_write_time_event); + bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET); files_used--; @@ -548,9 +528,6 @@ NTSTATUS dup_file_fsp(files_struct *fsp, dup_fsp->open_time = fsp->open_time; dup_fsp->access_mask = access_mask; dup_fsp->share_access = share_access; - dup_fsp->pending_modtime_owner = fsp->pending_modtime_owner; - dup_fsp->pending_modtime = fsp->pending_modtime; - dup_fsp->last_write_time = fsp->last_write_time; dup_fsp->oplock_type = fsp->oplock_type; dup_fsp->can_lock = fsp->can_lock; dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False; diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 60e546450b..05c0957e4f 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1233,7 +1233,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1)); + set_close_write_time(fsp2, get_mtimespec(&sbuf1)); status = close_file(fsp2,NORMAL_CLOSE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index b300c09f4f..411eb98ac5 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -1042,6 +1042,7 @@ void reply_getatr(struct smb_request *req) void reply_setatr(struct smb_request *req) { + struct timespec ts[2]; connection_struct *conn = req->conn; char *fname = NULL; int mode; @@ -1053,6 +1054,8 @@ void reply_setatr(struct smb_request *req) START_PROFILE(SMBsetatr); + ZERO_STRUCT(ts); + if (req->wct < 2) { reply_nterror(req, NT_STATUS_INVALID_PARAMETER); return; @@ -1110,7 +1113,10 @@ void reply_setatr(struct smb_request *req) mode = SVAL(req->inbuf,smb_vwv0); mtime = srv_make_unix_date3(req->inbuf+smb_vwv1); - if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) { + ts[1] = convert_time_t_to_timespec(mtime); + status = smb_set_file_time(conn, NULL, fname, + &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { reply_unixerror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsetatr); return; @@ -1985,7 +1991,12 @@ void reply_mknew(struct smb_request *req) } ts[0] = get_atimespec(&sbuf); /* atime. */ - file_ntimes(conn, fsp->fsp_name, ts); + status = smb_set_file_time(conn, fsp, fname, &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { + END_PROFILE(SMBcreate); + reply_openerror(req, status); + return; + } reply_outbuf(req, 1, 0); SSVAL(req->outbuf,smb_vwv0,fsp->fnum); @@ -4239,6 +4250,7 @@ void reply_close(struct smb_request *req) DEBUG(3,("close directory fnum=%d\n", fsp->fnum)); status = close_file(fsp,NORMAL_CLOSE); } else { + time_t t; /* * Close ordinary file. */ @@ -4251,9 +4263,8 @@ void reply_close(struct smb_request *req) * Take care of any time sent in the close. */ - fsp_set_pending_modtime(fsp, convert_time_t_to_timespec( - srv_make_unix_date3( - req->inbuf+smb_vwv1))); + t = srv_make_unix_date3(req->inbuf+smb_vwv1); + set_close_write_time(fsp, convert_time_t_to_timespec(t)); /* * close_file() returns the unix errno if an error @@ -4326,8 +4337,8 @@ void reply_writeclose(struct smb_request *req) nwritten = write_file(req,fsp,data,startpos,numtowrite); - set_filetime(conn, fsp->fsp_name, mtime); - + set_close_write_time(fsp, mtime); + /* * More insanity. W2K only closes the file if writelen > 0. * JRA. @@ -6078,7 +6089,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, close_file(fsp1,NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf)); + set_close_write_time(fsp2, get_mtimespec(&src_sbuf)); /* * As we are opening fsp1 read-only we only expect @@ -6961,6 +6972,8 @@ void reply_setattrE(struct smb_request *req) connection_struct *conn = req->conn; struct timespec ts[2]; files_struct *fsp; + SMB_STRUCT_STAT sbuf; + NTSTATUS status; START_PROFILE(SMBsetattrE); @@ -6996,23 +7009,27 @@ void reply_setattrE(struct smb_request *req) * Sometimes times are sent as zero - ignore them. */ - if (null_timespec(ts[0]) && null_timespec(ts[1])) { - /* Ignore request */ - if( DEBUGLVL( 3 ) ) { - dbgtext( "reply_setattrE fnum=%d ", fsp->fnum); - dbgtext( "ignoring zero request - not setting timestamps of 0\n" ); + /* Ensure we have a valid stat struct for the source. */ + if (fsp->fh->fd != -1) { + if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) { + status = map_nt_error_from_unix(errno); + reply_nterror(req, status); + END_PROFILE(SMBsetattrE); + return; + } + } else { + if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) { + status = map_nt_error_from_unix(errno); + reply_nterror(req, status) + END_PROFILE(SMBsetattrE); + return; } - END_PROFILE(SMBsetattrE); - return; - } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) { - /* set modify time = to access time if modify time was unset */ - ts[1] = ts[0]; } - /* Set the date on this file */ - /* Should we set pending modtime here ? JRA */ - if(file_ntimes(conn, fsp->fsp_name, ts)) { - reply_doserror(req, ERRDOS, ERRnoaccess); + status = smb_set_file_time(conn, fsp, fsp->fsp_name, + &sbuf, ts, true); + if (!NT_STATUS_IS_OK(status)) { + reply_doserror(req, ERRDOS, ERRnoaccess) END_PROFILE(SMBsetattrE); return; } diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 308ba271b8..06bb31622f 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -1238,6 +1238,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/'); bool check_mangled_names = lp_manglednames(conn->params); char mangled_name[13]; /* mangled 8.3 name. */ + struct timespec write_time_ts; *out_of_space = False; *got_exact_match = False; @@ -1397,6 +1398,12 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx, adate_ts = get_atimespec(&sbuf); create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn))); + write_time_ts = get_write_time( + vfs_file_id_from_sbuf(conn, &sbuf)); + if (!null_timespec(write_time_ts)) { + mdate_ts = write_time_ts; + } + if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_date_ts); dos_filetime_timespec(&mdate_ts); @@ -3784,6 +3791,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, int len; time_t create_time, mtime, atime; struct timespec create_time_ts, mtime_ts, atime_ts; + struct timespec write_time_ts; files_struct *fsp = NULL; struct file_id fileid; struct ea_list *ea_list = NULL; @@ -3797,6 +3805,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, } ZERO_STRUCT(sbuf); + ZERO_STRUCT(write_time_ts); if (tran_call == TRANSACT2_QFILEINFO) { if (total_params < 4) { @@ -3862,6 +3871,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, fileid = vfs_file_id_from_sbuf(conn, &sbuf); delete_pending = get_delete_on_close_flag(fileid); + write_time_ts = get_write_time(fileid); } else { /* * Original code - this is an open file. @@ -3878,6 +3888,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, pos = fsp->fh->position_information; fileid = vfs_file_id_from_sbuf(conn, &sbuf); delete_pending = get_delete_on_close_flag(fileid); + write_time_ts = get_write_time(fileid); access_mask = fsp->access_mask; } @@ -3953,6 +3964,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn, reply_nterror(req, NT_STATUS_DELETE_PENDING); return; } + write_time_ts = get_write_time(fileid); } if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) { @@ -4073,25 +4085,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd allocation_size = get_allocation_size(conn,fsp,&sbuf); - if (fsp) { - if (!null_timespec(fsp->pending_modtime)) { - /* the pending modtime overrides the current modtime */ - mtime_ts = fsp->pending_modtime; - } - } else { - files_struct *fsp1; + if (!fsp) { /* Do we have this path open ? */ + files_struct *fsp1; fileid = vfs_file_id_from_sbuf(conn, &sbuf); fsp1 = file_find_di_first(fileid); - if (fsp1 && !null_timespec(fsp1->pending_modtime)) { - /* the pending modtime overrides the current modtime */ - mtime_ts = fsp1->pending_modtime; - } if (fsp1 && fsp1->initial_allocation_size) { allocation_size = get_allocation_size(conn, fsp1, &sbuf); } } + if (!null_timespec(write_time_ts)) { + mtime_ts = write_time_ts; + } + if (lp_dos_filetime_resolution(SNUM(conn))) { dos_filetime_timespec(&create_time_ts); dos_filetime_timespec(&mtime_ts); @@ -4781,12 +4788,12 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx, Deal with setting the time from any of the setfilepathinfo functions. ****************************************************************************/ -static NTSTATUS smb_set_file_time(connection_struct *conn, - files_struct *fsp, - const char *fname, - const SMB_STRUCT_STAT *psbuf, - struct timespec ts[2], - bool setting_write_time) +NTSTATUS smb_set_file_time(connection_struct *conn, + files_struct *fsp, + const char *fname, + const SMB_STRUCT_STAT *psbuf, + struct timespec ts[2], + bool setting_write_time) { uint32 action = FILE_NOTIFY_CHANGE_LAST_ACCESS @@ -4828,7 +4835,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, } } - if(fsp != NULL) { + if (setting_write_time) { /* * This was a setfileinfo on an open file. * NT does this a lot. We also need to @@ -4839,13 +4846,18 @@ static NTSTATUS smb_set_file_time(connection_struct *conn, * away and will set it on file close and after a write. JRA. */ - if (!null_timespec(ts[1])) { - DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", - time_to_asc(convert_timespec_to_time_t(ts[1])) )); - fsp_set_pending_modtime(fsp, ts[1]); - } + DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n", + time_to_asc(convert_timespec_to_time_t(ts[1])) )); + if (fsp != NULL) { + set_write_time_fsp(fsp, ts[1], true); + } else { + set_write_time_path(conn, fname, + vfs_file_id_from_sbuf(conn, psbuf), + ts[1], true); + } } + DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n")); if(file_ntimes(conn, fname, ts)!=0) { @@ -5670,14 +5682,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, } } /* But always update the time. */ - if (null_timespec(fsp->pending_modtime)) { - /* - * This is equivalent to a write. Ensure it's seen immediately - * if there are no pending writes. - */ - set_filetime(fsp->conn, fsp->fsp_name, - timespec_current()); - } + /* + * This is equivalent to a write. Ensure it's seen immediately + * if there are no pending writes. + */ + trigger_write_time_update(fsp); return NT_STATUS_OK; } @@ -5707,10 +5716,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn, } /* Changing the allocation size should set the last mod time. */ - /* Don't need to call set_filetime as this will be flushed on - * close. */ - - fsp_set_pending_modtime(new_fsp, timespec_current()); + /* + * This is equivalent to a write. Ensure it's seen immediately + * if there are no pending writes. + */ + trigger_write_time_update(new_fsp); close_file(new_fsp,NORMAL_CLOSE); return NT_STATUS_OK; @@ -6658,11 +6668,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn, SSVAL(params,0,0); - if (fsp && !null_timespec(fsp->pending_modtime)) { - /* the pending modtime overrides the current modtime */ - set_mtimespec(&sbuf, fsp->pending_modtime); - } - switch (info_level) { case SMB_INFO_STANDARD: |