summaryrefslogtreecommitdiff
path: root/source3/smbd/trans2.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/trans2.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/trans2.c')
-rw-r--r--source3/smbd/trans2.c85
1 files changed, 45 insertions, 40 deletions
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 308ba271b8..06bb31622f 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1238,6 +1238,7 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
bool needslash = ( conn->dirpath[strlen(conn->dirpath) -1] != '/');
bool check_mangled_names = lp_manglednames(conn->params);
char mangled_name[13]; /* mangled 8.3 name. */
+ struct timespec write_time_ts;
*out_of_space = False;
*got_exact_match = False;
@@ -1397,6 +1398,12 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
adate_ts = get_atimespec(&sbuf);
create_date_ts = get_create_timespec(&sbuf,lp_fake_dir_create_times(SNUM(conn)));
+ write_time_ts = get_write_time(
+ vfs_file_id_from_sbuf(conn, &sbuf));
+ if (!null_timespec(write_time_ts)) {
+ mdate_ts = write_time_ts;
+ }
+
if (lp_dos_filetime_resolution(SNUM(conn))) {
dos_filetime_timespec(&create_date_ts);
dos_filetime_timespec(&mdate_ts);
@@ -3784,6 +3791,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
int len;
time_t create_time, mtime, atime;
struct timespec create_time_ts, mtime_ts, atime_ts;
+ struct timespec write_time_ts;
files_struct *fsp = NULL;
struct file_id fileid;
struct ea_list *ea_list = NULL;
@@ -3797,6 +3805,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
}
ZERO_STRUCT(sbuf);
+ ZERO_STRUCT(write_time_ts);
if (tran_call == TRANSACT2_QFILEINFO) {
if (total_params < 4) {
@@ -3862,6 +3871,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
fileid = vfs_file_id_from_sbuf(conn, &sbuf);
delete_pending = get_delete_on_close_flag(fileid);
+ write_time_ts = get_write_time(fileid);
} else {
/*
* Original code - this is an open file.
@@ -3878,6 +3888,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
pos = fsp->fh->position_information;
fileid = vfs_file_id_from_sbuf(conn, &sbuf);
delete_pending = get_delete_on_close_flag(fileid);
+ write_time_ts = get_write_time(fileid);
access_mask = fsp->access_mask;
}
@@ -3953,6 +3964,7 @@ static void call_trans2qfilepathinfo(connection_struct *conn,
reply_nterror(req, NT_STATUS_DELETE_PENDING);
return;
}
+ write_time_ts = get_write_time(fileid);
}
if (INFO_LEVEL_IS_UNIX(info_level) && !lp_unix_extensions()) {
@@ -4073,25 +4085,20 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
allocation_size = get_allocation_size(conn,fsp,&sbuf);
- if (fsp) {
- if (!null_timespec(fsp->pending_modtime)) {
- /* the pending modtime overrides the current modtime */
- mtime_ts = fsp->pending_modtime;
- }
- } else {
- files_struct *fsp1;
+ if (!fsp) {
/* Do we have this path open ? */
+ files_struct *fsp1;
fileid = vfs_file_id_from_sbuf(conn, &sbuf);
fsp1 = file_find_di_first(fileid);
- if (fsp1 && !null_timespec(fsp1->pending_modtime)) {
- /* the pending modtime overrides the current modtime */
- mtime_ts = fsp1->pending_modtime;
- }
if (fsp1 && fsp1->initial_allocation_size) {
allocation_size = get_allocation_size(conn, fsp1, &sbuf);
}
}
+ if (!null_timespec(write_time_ts)) {
+ mtime_ts = write_time_ts;
+ }
+
if (lp_dos_filetime_resolution(SNUM(conn))) {
dos_filetime_timespec(&create_time_ts);
dos_filetime_timespec(&mtime_ts);
@@ -4781,12 +4788,12 @@ NTSTATUS hardlink_internals(TALLOC_CTX *ctx,
Deal with setting the time from any of the setfilepathinfo functions.
****************************************************************************/
-static NTSTATUS smb_set_file_time(connection_struct *conn,
- files_struct *fsp,
- const char *fname,
- const SMB_STRUCT_STAT *psbuf,
- struct timespec ts[2],
- bool setting_write_time)
+NTSTATUS smb_set_file_time(connection_struct *conn,
+ files_struct *fsp,
+ const char *fname,
+ const SMB_STRUCT_STAT *psbuf,
+ struct timespec ts[2],
+ bool setting_write_time)
{
uint32 action =
FILE_NOTIFY_CHANGE_LAST_ACCESS
@@ -4828,7 +4835,7 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
}
}
- if(fsp != NULL) {
+ if (setting_write_time) {
/*
* This was a setfileinfo on an open file.
* NT does this a lot. We also need to
@@ -4839,13 +4846,18 @@ static NTSTATUS smb_set_file_time(connection_struct *conn,
* away and will set it on file close and after a write. JRA.
*/
- if (!null_timespec(ts[1])) {
- DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
- time_to_asc(convert_timespec_to_time_t(ts[1])) ));
- fsp_set_pending_modtime(fsp, ts[1]);
- }
+ DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
+ time_to_asc(convert_timespec_to_time_t(ts[1])) ));
+ if (fsp != NULL) {
+ set_write_time_fsp(fsp, ts[1], true);
+ } else {
+ set_write_time_path(conn, fname,
+ vfs_file_id_from_sbuf(conn, psbuf),
+ ts[1], true);
+ }
}
+
DEBUG(10,("smb_set_file_time: setting utimes to modified values.\n"));
if(file_ntimes(conn, fname, ts)!=0) {
@@ -5670,14 +5682,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
}
}
/* But always update the time. */
- if (null_timespec(fsp->pending_modtime)) {
- /*
- * This is equivalent to a write. Ensure it's seen immediately
- * if there are no pending writes.
- */
- set_filetime(fsp->conn, fsp->fsp_name,
- timespec_current());
- }
+ /*
+ * This is equivalent to a write. Ensure it's seen immediately
+ * if there are no pending writes.
+ */
+ trigger_write_time_update(fsp);
return NT_STATUS_OK;
}
@@ -5707,10 +5716,11 @@ static NTSTATUS smb_set_file_allocation_info(connection_struct *conn,
}
/* Changing the allocation size should set the last mod time. */
- /* Don't need to call set_filetime as this will be flushed on
- * close. */
-
- fsp_set_pending_modtime(new_fsp, timespec_current());
+ /*
+ * This is equivalent to a write. Ensure it's seen immediately
+ * if there are no pending writes.
+ */
+ trigger_write_time_update(new_fsp);
close_file(new_fsp,NORMAL_CLOSE);
return NT_STATUS_OK;
@@ -6658,11 +6668,6 @@ static void call_trans2setfilepathinfo(connection_struct *conn,
SSVAL(params,0,0);
- if (fsp && !null_timespec(fsp->pending_modtime)) {
- /* the pending modtime overrides the current modtime */
- set_mtimespec(&sbuf, fsp->pending_modtime);
- }
-
switch (info_level) {
case SMB_INFO_STANDARD: