diff options
author | Jeremy Allison <jra@samba.org> | 2009-11-05 16:20:11 -0800 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2009-11-05 16:20:11 -0800 |
commit | 7f9fe127ba31e6dd064d090d5ffc8eeb377627ab (patch) | |
tree | 6b2c63f2d022c82c14ea517bac06e49a605b4f5e | |
parent | c2df97f57ce205935c37cd5a90cfeddb129cd92b (diff) | |
download | samba-7f9fe127ba31e6dd064d090d5ffc8eeb377627ab.tar.gz samba-7f9fe127ba31e6dd064d090d5ffc8eeb377627ab.tar.bz2 samba-7f9fe127ba31e6dd064d090d5ffc8eeb377627ab.zip |
Get closer to an accurate model of Windows timestamp changes.
"Normal" non truncate writes always cause the timestamp to
be set on close. Once a close is done on a handle this can
reset the sticky write time to current time also.
Updated smbtorture4 confirms this.
Jeremy.
-rw-r--r-- | source3/include/proto.h | 5 | ||||
-rw-r--r-- | source3/smbd/close.c | 21 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 16 | ||||
-rw-r--r-- | source3/smbd/fileio.c | 38 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 6 |
6 files changed, 56 insertions, 32 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index d08ed79050..ef811e5774 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6108,7 +6108,9 @@ NTSTATUS change_oem_password(struct samu *hnd, char *old_passwd, char *new_passw /* The following definitions come from smbd/close.c */ -void set_close_write_time(struct files_struct *fsp, struct timespec ts); +void set_close_write_time(struct share_mode_lock *lck, + struct files_struct *fsp, + struct timespec ts); NTSTATUS close_file(struct smb_request *req, files_struct *fsp, enum file_close_type close_type); void msg_close_file(struct messaging_context *msg_ctx, @@ -6249,7 +6251,6 @@ int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname, bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime); bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime); -bool update_write_time(struct files_struct *fsp); NTSTATUS set_create_timespec_ea(connection_struct *conn, struct files_struct *fsp, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 642864f27e..c1623ce290 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -291,7 +291,15 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, } if (fsp->write_time_forced) { - set_close_write_time(fsp, lck->changed_write_time); + DEBUG(10,("close_remove_share_mode: write time forced " + "for file %s\n", + fsp_str_dbg(fsp))); + set_close_write_time(lck, fsp, lck->changed_write_time); + } else if (fsp->update_write_time_on_close) { + DEBUG(10,("close_remove_share_mode: update_write_time_on_close " + "set for file %s\n", + fsp_str_dbg(fsp))); + set_close_write_time(lck, fsp, timespec_current()); } if (!del_share_mode(lck, fsp)) { @@ -468,7 +476,8 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, return status; } -void set_close_write_time(struct files_struct *fsp, struct timespec ts) +void set_close_write_time(struct share_mode_lock *lck, + struct files_struct *fsp, struct timespec ts) { DEBUG(6,("close_write_time: %s" , time_to_asc(convert_timespec_to_time_t(ts)))); @@ -483,6 +492,14 @@ void set_close_write_time(struct files_struct *fsp, struct timespec ts) fsp->update_write_time_on_close = true; fsp->close_write_time = ts; + + /* On close if we're changing the real file time we + * must update it in the open file db too. */ + (void)set_write_time(fsp->file_id, ts); + /* If someone has a sticky write time then update it as well. */ + if (lck && !null_timespec(lck->changed_write_time)) { + (void)set_sticky_write_time(fsp->file_id, ts); + } } static NTSTATUS update_write_time_on_close(struct files_struct *fsp) diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c index 949c438f4f..e10f23918d 100644 --- a/source3/smbd/dosmode.c +++ b/source3/smbd/dosmode.c @@ -849,22 +849,6 @@ bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime) } /****************************************************************** - Update a write time immediately, without the 2 second delay. -******************************************************************/ - -bool update_write_time(struct files_struct *fsp) -{ - if (!set_write_time(fsp->file_id, timespec_current())) { - return false; - } - - notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, - FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name->base_name); - - return true; -} - -/****************************************************************** Set a create time EA. ******************************************************************/ diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index bd609d3e86..62e9a98a8d 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -180,10 +180,15 @@ static void update_write_time_handler(struct event_context *ctx, /* Remove the timed event handler. */ TALLOC_FREE(fsp->update_write_time_event); + DEBUG(5, ("Update write time on %s\n", fsp_str_dbg(fsp))); - /* change the write time if not already changed by someone else */ - update_write_time(fsp); + /* change the write time in the open file db. */ + (void)set_write_time(fsp->file_id, timespec_current()); + + /* And notify. */ + notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, + FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name->base_name); } /********************************************************* @@ -207,11 +212,16 @@ void trigger_write_time_update(struct files_struct *fsp) return; } + /* We need to remember someone did a write + * and update to current time on close. */ + + fsp->update_write_time_on_close = true; + if (fsp->update_write_time_triggered) { /* - * We only update the write time - * on the first write. After that - * no other writes affect this. + * We only update the write time after 2 seconds + * on the first normal write. After that + * no other writes affect this until close. */ return; } @@ -221,8 +231,10 @@ void trigger_write_time_update(struct files_struct *fsp) "smbd", "writetimeupdatedelay", WRITE_TIME_UPDATE_USEC_DELAY); + DEBUG(5, ("Update write time %d usec later on %s\n", + delay, fsp_str_dbg(fsp))); + /* 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(0, delay), @@ -231,6 +243,8 @@ void trigger_write_time_update(struct files_struct *fsp) void trigger_write_time_update_immediate(struct files_struct *fsp) { + struct smb_file_time ft; + if (fsp->posix_open) { /* Don't use delayed writes on POSIX files. */ return; @@ -248,10 +262,18 @@ void trigger_write_time_update_immediate(struct files_struct *fsp) DEBUG(5, ("Update write time immediate on %s\n", fsp_str_dbg(fsp))); + /* After an immediate update, reset the trigger. */ fsp->update_write_time_triggered = true; - fsp->update_write_time_on_close = false; - update_write_time(fsp); + + ZERO_STRUCT(ft); + ft.mtime = timespec_current(); + + /* Update the time in the open file db. */ + (void)set_write_time(fsp->file_id, ft.mtime); + + /* Now set on disk - takes care of notify. */ + (void)smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false); } /**************************************************************************** diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index 66102fa96c..a1e7889119 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -1296,7 +1296,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx, close_file(NULL, fsp1, NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime); + set_close_write_time(NULL, fsp2, smb_fname_src->st.st_ex_mtime); status = close_file(NULL, fsp2, NORMAL_CLOSE); diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 984cf56c11..37634acc2c 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4646,7 +4646,7 @@ void reply_close(struct smb_request *req) */ t = srv_make_unix_date3(req->vwv+1); - set_close_write_time(fsp, convert_time_t_to_timespec(t)); + set_close_write_time(NULL, fsp, convert_time_t_to_timespec(t)); /* * close_file() returns the unix errno if an error @@ -4723,7 +4723,7 @@ void reply_writeclose(struct smb_request *req) nwritten = write_file(req,fsp,data,startpos,numtowrite); - set_close_write_time(fsp, mtime); + set_close_write_time(NULL, fsp, mtime); /* * More insanity. W2K only closes the file if writelen > 0. @@ -6691,7 +6691,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx, close_file(NULL, fsp1, NORMAL_CLOSE); /* Ensure the modtime is set correctly on the destination file. */ - set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime); + set_close_write_time(NULL, fsp2, smb_fname_src->st.st_ex_mtime); /* * As we are opening fsp1 read-only we only expect |