diff options
-rw-r--r-- | source3/include/proto.h | 8 | ||||
-rw-r--r-- | source3/smbd/close.c | 59 | ||||
-rw-r--r-- | source3/smbd/fileio.c | 8 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 2 | ||||
-rw-r--r-- | source3/smbd/reply.c | 6 |
5 files changed, 50 insertions, 33 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h index ef811e5774..785b9683e4 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -6108,9 +6108,7 @@ 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 share_mode_lock *lck, - struct files_struct *fsp, - struct timespec ts); +void set_close_write_time(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, @@ -6309,6 +6307,10 @@ bool directory_has_default_acl(connection_struct *conn, const char *fname); /* The following definitions come from smbd/fileio.c */ ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n); +void update_write_time_handler(struct event_context *ctx, + struct timed_event *te, + struct timeval now, + void *private_data); void trigger_write_time_update(struct files_struct *fsp); void trigger_write_time_update_immediate(struct files_struct *fsp); ssize_t write_file(struct smb_request *req, diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 0f1bd90dde..a8e3793ea0 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -274,6 +274,14 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, NTSTATUS tmp_status; struct file_id id; + /* Ensure any pending write time updates are done. */ + if (fsp->update_write_time_event) { + update_write_time_handler(smbd_event_context(), + fsp->update_write_time_event, + timeval_current(), + (void *)fsp); + } + /* * Lock the share entries, and determine if we should delete * on close. If so delete whilst the lock is still in effect. @@ -294,15 +302,21 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, 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); + set_close_write_time(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))); + /* Someone had a pending write. */ if (null_timespec(fsp->close_write_time)) { - set_close_write_time(lck, fsp, timespec_current()); + DEBUG(10,("close_remove_share_mode: update to current time " + "for file %s\n", + fsp_str_dbg(fsp))); + /* Update to current time due to "normal" write. */ + set_close_write_time(fsp, timespec_current()); } else { - set_close_write_time(lck, fsp, fsp->close_write_time); + DEBUG(10,("close_remove_share_mode: write time pending " + "for file %s\n", + fsp_str_dbg(fsp))); + /* Update to time set on close call. */ + set_close_write_time(fsp, fsp->close_write_time); } } @@ -480,36 +494,23 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, return status; } -void set_close_write_time(struct share_mode_lock *lck, - struct files_struct *fsp, struct timespec ts) +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; - - /* 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) { struct smb_file_time ft; NTSTATUS status; + struct share_mode_lock *lck = NULL; ZERO_STRUCT(ft); @@ -532,8 +533,22 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp) return NT_STATUS_OK; } + /* 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, fsp->close_write_time); + + lck = get_share_mode_lock(talloc_tos(), fsp->file_id, NULL, NULL, NULL); + if (lck) { + /* Close write times overwrite sticky write times + so we must replace any sticky write time here. */ + if (!null_timespec(lck->changed_write_time)) { + (void)set_sticky_write_time(fsp->file_id, fsp->close_write_time); + } + TALLOC_FREE(lck); + } + ft.mtime = fsp->close_write_time; - status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, true); + status = smb_set_file_time(fsp->conn, fsp, fsp->fsp_name, &ft, false); if (!NT_STATUS_IS_OK(status)) { return status; } diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c index 62e9a98a8d..c0deaebcfc 100644 --- a/source3/smbd/fileio.c +++ b/source3/smbd/fileio.c @@ -171,16 +171,13 @@ static int wcp_file_size_change(files_struct *fsp) return ret; } -static void update_write_time_handler(struct event_context *ctx, +void update_write_time_handler(struct event_context *ctx, struct timed_event *te, 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_str_dbg(fsp))); /* change the write time in the open file db. */ @@ -189,6 +186,9 @@ static void update_write_time_handler(struct event_context *ctx, /* And notify. */ notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED, FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name->base_name); + + /* Remove the timed event handler. */ + TALLOC_FREE(fsp->update_write_time_event); } /********************************************************* diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index a1e7889119..66102fa96c 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(NULL, fsp2, smb_fname_src->st.st_ex_mtime); + set_close_write_time(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 37634acc2c..984cf56c11 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(NULL, fsp, convert_time_t_to_timespec(t)); + set_close_write_time(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(NULL, fsp, mtime); + set_close_write_time(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(NULL, fsp2, smb_fname_src->st.st_ex_mtime); + set_close_write_time(fsp2, smb_fname_src->st.st_ex_mtime); /* * As we are opening fsp1 read-only we only expect |