summaryrefslogtreecommitdiff
path: root/source3/smbd/close.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2008-03-12 15:39:38 +0100
committerStefan Metzmacher <metze@samba.org>2008-04-07 12:29:26 +0200
commitd03453864ab1bc5fd3b4a3abaf96176a006c102b (patch)
tree13389e06bd05336a1937b98d3e821ad995eef019 /source3/smbd/close.c
parent2ccf50256e31bd7b9da0f7a7c223bebca5bca062 (diff)
downloadsamba-d03453864ab1bc5fd3b4a3abaf96176a006c102b.tar.gz
samba-d03453864ab1bc5fd3b4a3abaf96176a006c102b.tar.bz2
samba-d03453864ab1bc5fd3b4a3abaf96176a006c102b.zip
smbd: implement the strange write time update logic
We now never call file_ntimes() directly, every update is done via smb_set_file_time(). This let samba3 pass the BASE-DELAYWRITE test. The write time is only updated 2 seconds after the first write() on any open handle to the current time (not the time of the first write). Each handle which had write requests updates the write time to the current time on close(). If the write time is set explicit via setfileinfo or setpathinfo the write time is visible directly and a following close on the same handle doesn't update the write time. metze (This used to be commit 2eab212ea2e1bfd8fa716c2c89b2c042f7ba12ea)
Diffstat (limited to 'source3/smbd/close.c')
-rw-r--r--source3/smbd/close.c78
1 files changed, 73 insertions, 5 deletions
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, &current_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;
}
}