summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-11-05 16:20:11 -0800
committerJeremy Allison <jra@samba.org>2009-11-05 16:20:11 -0800
commit7f9fe127ba31e6dd064d090d5ffc8eeb377627ab (patch)
tree6b2c63f2d022c82c14ea517bac06e49a605b4f5e /source3/smbd
parentc2df97f57ce205935c37cd5a90cfeddb129cd92b (diff)
downloadsamba-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.
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/close.c21
-rw-r--r--source3/smbd/dosmode.c16
-rw-r--r--source3/smbd/fileio.c38
-rw-r--r--source3/smbd/nttrans.c2
-rw-r--r--source3/smbd/reply.c6
5 files changed, 53 insertions, 30 deletions
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