summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h14
-rw-r--r--source3/include/smb.h1
-rw-r--r--source3/locking/locking.c33
-rw-r--r--source3/smbd/dosmode.c52
-rw-r--r--source3/smbd/fileio.c47
-rw-r--r--source3/smbd/reply.c6
-rw-r--r--source3/smbd/trans2.c12
7 files changed, 117 insertions, 48 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 291afac44d..e94a2178c0 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -5306,8 +5306,8 @@ void set_delete_on_close_token(struct share_mode_lock *lck, UNIX_USER_TOKEN *tok
void set_delete_on_close_lck(struct share_mode_lock *lck, bool delete_on_close, UNIX_USER_TOKEN *tok);
bool set_delete_on_close(files_struct *fsp, bool delete_on_close, UNIX_USER_TOKEN *tok);
bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct *fsp, bool delete_on_close);
-bool set_write_time(struct file_id fileid, struct timespec write_time,
- bool overwrite);
+bool set_sticky_write_time(struct file_id fileid, struct timespec write_time);
+bool set_write_time(struct file_id fileid, struct timespec write_time);
int share_mode_forall(void (*fn)(const struct share_mode_entry *, const char *,
const char *, void *),
void *private_data);
@@ -9616,11 +9616,10 @@ int file_set_dosmode(connection_struct *conn, const char *fname,
const char *parent_dir,
bool newfile);
int file_ntimes(connection_struct *conn, const char *fname, const struct timespec ts[2]);
-bool set_write_time_path(connection_struct *conn, const char *fname,
- struct file_id fileid, const struct timespec mtime,
- bool overwrite);
-bool set_write_time_fsp(struct files_struct *fsp, const struct timespec mtime,
- bool overwrite);
+bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
+ struct file_id fileid, const struct timespec mtime);
+bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime);
+bool update_write_time(struct files_struct *fsp);
/* The following definitions come from smbd/error.c */
@@ -9665,6 +9664,7 @@ bool directory_has_default_acl(connection_struct *conn, const char *fname);
ssize_t read_file(files_struct *fsp,char *data,SMB_OFF_T pos,size_t n);
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,
files_struct *fsp,
const char *data,
diff --git a/source3/include/smb.h b/source3/include/smb.h
index c8c4f8c3cc..d450eb51fa 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -456,7 +456,6 @@ typedef struct files_struct {
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 update_write_time_triggered;
struct timed_event *update_write_time_event;
bool update_write_time_on_close;
struct timespec close_write_time;
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index ca61a886a6..f1f9278668 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -1405,22 +1405,21 @@ bool set_allow_initial_delete_on_close(struct share_mode_lock *lck, files_struct
return True;
}
-bool set_write_time(struct file_id fileid, struct timespec write_time,
- bool overwrite)
+bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
{
struct share_mode_lock *lck;
- DEBUG(5,("set_write_time: %s overwrite=%d id=%s\n",
+ DEBUG(5,("set_sticky_write_time: %s id=%s\n",
timestring(debug_ctx(),
convert_timespec_to_time_t(write_time)),
- overwrite, file_id_string_tos(&fileid)));
+ file_id_string_tos(&fileid)));
lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL);
if (lck == NULL) {
return False;
}
- if (overwrite || null_timespec(lck->changed_write_time)) {
+ if (timespec_compare(&lck->changed_write_time, &write_time) != 0) {
lck->modified = True;
lck->changed_write_time = write_time;
}
@@ -1429,6 +1428,30 @@ bool set_write_time(struct file_id fileid, struct timespec write_time,
return True;
}
+bool set_write_time(struct file_id fileid, struct timespec write_time)
+{
+ struct share_mode_lock *lck;
+
+ DEBUG(5,("set_sticky_write_time: %s id=%s\n",
+ timestring(debug_ctx(),
+ convert_timespec_to_time_t(write_time)),
+ file_id_string_tos(&fileid)));
+
+ lck = get_share_mode_lock(NULL, fileid, NULL, NULL, NULL);
+ if (lck == NULL) {
+ return False;
+ }
+
+ if (timespec_compare(&lck->old_write_time, &write_time) != 0) {
+ lck->modified = True;
+ lck->old_write_time = write_time;
+ }
+
+ TALLOC_FREE(lck);
+ return True;
+}
+
+
struct forall_state {
void (*fn)(const struct share_mode_entry *entry,
const char *sharepath,
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index 0ac3873275..88c6a51770 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -616,39 +616,51 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
return ret;
}
-/*******************************************************************
- Change a filetime - possibly allowing DOS semantics.
-*******************************************************************/
+/******************************************************************
+ Force a "sticky" write time on a pathname. This will always be
+ returned on all future write time queries and set on close.
+******************************************************************/
-bool set_write_time_path(connection_struct *conn, const char *fname,
- struct file_id fileid, const struct timespec mtime,
- bool overwrite)
+bool set_sticky_write_time_path(connection_struct *conn, const char *fname,
+ struct file_id fileid, const struct timespec mtime)
{
if (null_timespec(mtime)) {
return true;
}
- if (!set_write_time(fileid, mtime, overwrite)) {
+ if (!set_sticky_write_time(fileid, mtime)) {
return false;
}
- /* 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)
+/******************************************************************
+ Force a "sticky" write time on an fsp. This will always be
+ returned on all future write time queries and set on close.
+******************************************************************/
+
+bool set_sticky_write_time_fsp(struct files_struct *fsp, const struct timespec mtime)
{
- if (overwrite) {
- fsp->write_time_forced = true;
- TALLOC_FREE(fsp->update_write_time_event);
+ fsp->write_time_forced = true;
+ TALLOC_FREE(fsp->update_write_time_event);
+
+ return set_sticky_write_time_path(fsp->conn, fsp->fsp_name,
+ fsp->file_id, 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;
}
- return set_write_time_path(fsp->conn, fsp->fsp_name, fsp->file_id,
- mtime, overwrite);
+ notify_fname(fsp->conn, NOTIFY_ACTION_MODIFIED,
+ FILE_NOTIFY_CHANGE_LAST_WRITE, fsp->fsp_name);
+
+ return true;
}
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 64cea7f7ce..63850f24eb 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -176,28 +176,38 @@ static void update_write_time_handler(struct event_context *ctx,
const struct timeval *now,
void *private_data)
{
- files_struct *fsp = (files_struct *)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));
+ /* 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);
+ /* change the write time if not already changed by someone else */
+ update_write_time(fsp);
}
+/*********************************************************
+ Schedule a write time update for WRITE_TIME_UPDATE_USEC_DELAY
+ in the future.
+*********************************************************/
+
void trigger_write_time_update(struct files_struct *fsp)
{
int delay;
if (fsp->write_time_forced) {
+ /* No point - "sticky" write times
+ * in effect.
+ */
return;
}
- if (fsp->update_write_time_triggered) {
+ if (fsp->update_write_time_event) {
+ /*
+ * No point - an event is already scheduled.
+ */
return;
}
- fsp->update_write_time_triggered = true;
delay = lp_parm_int(SNUM(fsp->conn),
"smbd", "writetimeupdatedelay",
@@ -212,6 +222,27 @@ void trigger_write_time_update(struct files_struct *fsp)
update_write_time_handler, fsp);
}
+void trigger_write_time_update_immediate(struct files_struct *fsp)
+{
+ if (fsp->write_time_forced) {
+ /*
+ * No point - "sticky" write times
+ * in effect.
+ */
+ return;
+ }
+
+ if (fsp->update_write_time_event) {
+ /*
+ * No point - an event is already scheduled.
+ */
+ return;
+ }
+
+ fsp->update_write_time_on_close = true;
+ update_write_time(fsp);
+}
+
/****************************************************************************
Write to a file.
****************************************************************************/
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 16f8a5b177..6933533672 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -3810,9 +3810,11 @@ void reply_write(struct smb_request *req)
END_PROFILE(SMBwrite);
return;
}
- } else
+ trigger_write_time_update_immediate(fsp);
+ } else {
nwritten = write_file(req,fsp,data,startpos,numtowrite);
-
+ }
+
status = sync_file(conn, fsp, False);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(5,("reply_write: sync_file for %s returned %s\n",
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 881b29c6f0..8d839b66b3 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -4900,11 +4900,11 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
time_to_asc(convert_timespec_to_time_t(ts[1])) ));
if (fsp != NULL) {
- set_write_time_fsp(fsp, ts[1], true);
+ set_sticky_write_time_fsp(fsp, ts[1]);
} else {
- set_write_time_path(conn, fname,
+ set_sticky_write_time_path(conn, fname,
vfs_file_id_from_sbuf(conn, psbuf),
- ts[1], true);
+ ts[1]);
}
}
@@ -4988,6 +4988,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
if (vfs_set_filelen(fsp, size) == -1) {
return map_nt_error_from_unix(errno);
}
+ trigger_write_time_update_immediate(fsp);
return NT_STATUS_OK;
}
@@ -5011,6 +5012,7 @@ static NTSTATUS smb_set_file_size(connection_struct *conn,
return status;
}
+ trigger_write_time_update_immediate(new_fsp);
close_file(new_fsp,NORMAL_CLOSE);
return NT_STATUS_OK;
}
@@ -5737,7 +5739,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
* This is equivalent to a write. Ensure it's seen immediately
* if there are no pending writes.
*/
- trigger_write_time_update(fsp);
+ trigger_write_time_update_immediate(fsp);
return NT_STATUS_OK;
}
@@ -5771,7 +5773,7 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
* This is equivalent to a write. Ensure it's seen immediately
* if there are no pending writes.
*/
- trigger_write_time_update(new_fsp);
+ trigger_write_time_update_immediate(new_fsp);
close_file(new_fsp,NORMAL_CLOSE);
return NT_STATUS_OK;