summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/close.c78
-rw-r--r--source3/smbd/dir.c8
-rw-r--r--source3/smbd/dosmode.c42
-rw-r--r--source3/smbd/fileio.c60
-rw-r--r--source3/smbd/files.c29
-rw-r--r--source3/smbd/nttrans.c2
-rw-r--r--source3/smbd/reply.c61
-rw-r--r--source3/smbd/trans2.c85
8 files changed, 235 insertions, 130 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;
}
}
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index ca6f8bfd8d..8531d6250d 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -841,6 +841,8 @@ bool get_dir_entry(TALLOC_CTX *ctx,
mask_match_search(filename,mask,False) ||
mangle_mask_match(conn,filename,mask)) {
char mname[13];
+ struct timespec write_time_ts;
+ struct file_id fileid;
if (!mangle_is_8_3(filename, False, conn->params)) {
if (!name_to_8_3(filename,mname,False,
@@ -883,6 +885,12 @@ bool get_dir_entry(TALLOC_CTX *ctx,
*size = sbuf.st_size;
*date = sbuf.st_mtime;
+ fileid = vfs_file_id_from_sbuf(conn, &sbuf);
+ write_time_ts = get_write_time(fileid);
+ if (!null_timespec(write_time_ts)) {
+ *date = convert_timespec_to_time_t(write_time_ts);
+ }
+
DEBUG(3,("get_dir_entry mask=[%s] found %s "
"fname=%s (%s)\n",
mask,
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index a2e617c117..0ac3873275 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -571,6 +571,11 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
errno = 0;
ZERO_STRUCT(sbuf);
+ DEBUG(6, ("file_ntime: actime: %s",
+ time_to_asc(convert_timespec_to_time_t(ts[0]))));
+ DEBUG(6, ("file_ntime: modtime: %s",
+ time_to_asc(convert_timespec_to_time_t(ts[1]))));
+
/* Don't update the time on read-only shares */
/* We need this as set_filetime (which can be called on
close and other paths) can end up calling this function
@@ -615,26 +620,35 @@ int file_ntimes(connection_struct *conn, const char *fname, const struct timespe
Change a filetime - possibly allowing DOS semantics.
*******************************************************************/
-bool set_filetime(connection_struct *conn, const char *fname,
- const struct timespec mtime)
+bool set_write_time_path(connection_struct *conn, const char *fname,
+ struct file_id fileid, const struct timespec mtime,
+ bool overwrite)
{
- struct timespec ts[2];
-
if (null_timespec(mtime)) {
- return(True);
+ return true;
}
- ts[1] = mtime; /* mtime. */
- ts[0] = ts[1]; /* atime. */
-
- if (file_ntimes(conn, fname, ts)) {
- DEBUG(4,("set_filetime(%s) failed: %s\n",
- fname,strerror(errno)));
- return False;
+ if (!set_write_time(fileid, mtime, overwrite)) {
+ return false;
}
- notify_fname(conn, NOTIFY_ACTION_MODIFIED,
- FILE_NOTIFY_CHANGE_LAST_WRITE, fname);
+ /* 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)
+{
+ if (overwrite) {
+ fsp->write_time_forced = true;
+ TALLOC_FREE(fsp->update_write_time_event);
+ }
+
+ return set_write_time_path(fsp->conn, fsp->fsp_name, fsp->file_id,
+ mtime, overwrite);
+}
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index 8cea4989f5..93a303f6c8 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -142,27 +142,6 @@ static ssize_t real_write_file(struct smb_request *req,
if (ret != -1) {
fsp->fh->pos += ret;
- /*
- * It turns out that setting the last write time from a Windows
- * client stops any subsequent writes from updating the write time.
- * Doing this after the write gives a race condition here where
- * a stat may see the changed write time before we reset it here,
- * but it's cheaper than having to store the write time in shared
- * memory and look it up using dev/inode across all running smbd's.
- * The 99% solution will hopefully be good enough in this case. JRA.
- */
-
- if (!null_timespec(fsp->pending_modtime)) {
- set_filetime(fsp->conn, fsp->fsp_name,
- fsp->pending_modtime);
-
- /* If we didn't get the "set modtime" call ourselves, we must
- store the last write time to restore on close. JRA. */
- if (!fsp->pending_modtime_owner) {
- fsp->last_write_time = timespec_current();
- }
- }
-
/* Yes - this is correct - writes don't update this. JRA. */
/* Found by Samba4 tests. */
#if 0
@@ -192,6 +171,41 @@ static int wcp_file_size_change(files_struct *fsp)
return ret;
}
+static void update_write_time_handler(struct event_context *ctx,
+ struct timed_event *te,
+ const 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->fsp_name));
+
+ /* change the write time if not already changed by someoneelse */
+ set_write_time_fsp(fsp, timespec_current(), false);
+}
+
+void trigger_write_time_update(struct files_struct *fsp)
+{
+ if (fsp->write_time_forced) {
+ return;
+ }
+
+ if (fsp->update_write_time_triggered) {
+ return;
+ }
+ fsp->update_write_time_triggered = true;
+
+ /* 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(2, 0),
+ "update_write_time_handler",
+ update_write_time_handler, fsp);
+}
+
/****************************************************************************
Write to a file.
****************************************************************************/
@@ -230,7 +244,9 @@ ssize_t write_file(struct smb_request *req,
fsp->modified = True;
if (SMB_VFS_FSTAT(fsp, &st) == 0) {
- int dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
+ int dosmode;
+ trigger_write_time_update(fsp);
+ dosmode = dos_mode(fsp->conn,fsp->fsp_name,&st);
if ((lp_store_dos_attributes(SNUM(fsp->conn)) ||
MAP_ARCHIVE(fsp->conn)) &&
!IS_DOS_ARCHIVE(dosmode)) {
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 95f01b88ce..d6e91c67be 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -375,29 +375,6 @@ files_struct *file_find_print(void)
}
/****************************************************************************
- Set a pending modtime across all files with a given dev/ino pair.
- Record the owner of that modtime.
-****************************************************************************/
-
-void fsp_set_pending_modtime(files_struct *tfsp, const struct timespec mod)
-{
- files_struct *fsp;
-
- if (null_timespec(mod)) {
- return;
- }
-
- for (fsp = Files;fsp;fsp=fsp->next) {
- if ( fsp->fh->fd != -1 && file_id_equal(&fsp->file_id, &tfsp->file_id)) {
- fsp->pending_modtime = mod;
- fsp->pending_modtime_owner = False;
- }
- }
-
- tfsp->pending_modtime_owner = True;
-}
-
-/****************************************************************************
Sync open files on a connection.
****************************************************************************/
@@ -441,6 +418,9 @@ void file_free(files_struct *fsp)
/* Ensure this event will never fire. */
TALLOC_FREE(fsp->oplock_timeout);
+ /* Ensure this event will never fire. */
+ TALLOC_FREE(fsp->update_write_time_event);
+
bitmap_clear(file_bmap, fsp->fnum - FILE_HANDLE_OFFSET);
files_used--;
@@ -548,9 +528,6 @@ NTSTATUS dup_file_fsp(files_struct *fsp,
dup_fsp->open_time = fsp->open_time;
dup_fsp->access_mask = access_mask;
dup_fsp->share_access = share_access;
- dup_fsp->pending_modtime_owner = fsp->pending_modtime_owner;
- dup_fsp->pending_modtime = fsp->pending_modtime;
- dup_fsp->last_write_time = fsp->last_write_time;
dup_fsp->oplock_type = fsp->oplock_type;
dup_fsp->can_lock = fsp->can_lock;
dup_fsp->can_read = (access_mask & (FILE_READ_DATA)) ? True : False;
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 60e546450b..05c0957e4f 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -1233,7 +1233,7 @@ static NTSTATUS copy_internals(TALLOC_CTX *ctx,
close_file(fsp1,NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- fsp_set_pending_modtime(fsp2, get_mtimespec(&sbuf1));
+ set_close_write_time(fsp2, get_mtimespec(&sbuf1));
status = close_file(fsp2,NORMAL_CLOSE);
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index b300c09f4f..411eb98ac5 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1042,6 +1042,7 @@ void reply_getatr(struct smb_request *req)
void reply_setatr(struct smb_request *req)
{
+ struct timespec ts[2];
connection_struct *conn = req->conn;
char *fname = NULL;
int mode;
@@ -1053,6 +1054,8 @@ void reply_setatr(struct smb_request *req)
START_PROFILE(SMBsetatr);
+ ZERO_STRUCT(ts);
+
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
return;
@@ -1110,7 +1113,10 @@ void reply_setatr(struct smb_request *req)
mode = SVAL(req->inbuf,smb_vwv0);
mtime = srv_make_unix_date3(req->inbuf+smb_vwv1);
- if (!set_filetime(conn,fname,convert_time_t_to_timespec(mtime))) {
+ ts[1] = convert_time_t_to_timespec(mtime);
+ status = smb_set_file_time(conn, NULL, fname,
+ &sbuf, ts, true);
+ if (!NT_STATUS_IS_OK(status)) {
reply_unixerror(req, ERRDOS, ERRnoaccess);
END_PROFILE(SMBsetatr);
return;
@@ -1985,7 +1991,12 @@ void reply_mknew(struct smb_request *req)
}
ts[0] = get_atimespec(&sbuf); /* atime. */
- file_ntimes(conn, fsp->fsp_name, ts);
+ status = smb_set_file_time(conn, fsp, fname, &sbuf, ts, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ END_PROFILE(SMBcreate);
+ reply_openerror(req, status);
+ return;
+ }
reply_outbuf(req, 1, 0);
SSVAL(req->outbuf,smb_vwv0,fsp->fnum);
@@ -4239,6 +4250,7 @@ void reply_close(struct smb_request *req)
DEBUG(3,("close directory fnum=%d\n", fsp->fnum));
status = close_file(fsp,NORMAL_CLOSE);
} else {
+ time_t t;
/*
* Close ordinary file.
*/
@@ -4251,9 +4263,8 @@ void reply_close(struct smb_request *req)
* Take care of any time sent in the close.
*/
- fsp_set_pending_modtime(fsp, convert_time_t_to_timespec(
- srv_make_unix_date3(
- req->inbuf+smb_vwv1)));
+ t = srv_make_unix_date3(req->inbuf+smb_vwv1);
+ set_close_write_time(fsp, convert_time_t_to_timespec(t));
/*
* close_file() returns the unix errno if an error
@@ -4326,8 +4337,8 @@ void reply_writeclose(struct smb_request *req)
nwritten = write_file(req,fsp,data,startpos,numtowrite);
- set_filetime(conn, fsp->fsp_name, mtime);
-
+ set_close_write_time(fsp, mtime);
+
/*
* More insanity. W2K only closes the file if writelen > 0.
* JRA.
@@ -6078,7 +6089,7 @@ NTSTATUS copy_file(TALLOC_CTX *ctx,
close_file(fsp1,NORMAL_CLOSE);
/* Ensure the modtime is set correctly on the destination file. */
- fsp_set_pending_modtime( fsp2, get_mtimespec(&src_sbuf));
+ set_close_write_time(fsp2, get_mtimespec(&src_sbuf));
/*
* As we are opening fsp1 read-only we only expect
@@ -6961,6 +6972,8 @@ void reply_setattrE(struct smb_request *req)
connection_struct *conn = req->conn;
struct timespec ts[2];
files_struct *fsp;
+ SMB_STRUCT_STAT sbuf;
+ NTSTATUS status;
START_PROFILE(SMBsetattrE);
@@ -6996,23 +7009,27 @@ void reply_setattrE(struct smb_request *req)
* Sometimes times are sent as zero - ignore them.
*/
- if (null_timespec(ts[0]) && null_timespec(ts[1])) {
- /* Ignore request */
- if( DEBUGLVL( 3 ) ) {
- dbgtext( "reply_setattrE fnum=%d ", fsp->fnum);
- dbgtext( "ignoring zero request - not setting timestamps of 0\n" );
+ /* Ensure we have a valid stat struct for the source. */
+ if (fsp->fh->fd != -1) {
+ if (SMB_VFS_FSTAT(fsp, &sbuf) == -1) {
+ status = map_nt_error_from_unix(errno);
+ reply_nterror(req, status);
+ END_PROFILE(SMBsetattrE);
+ return;
+ }
+ } else {
+ if (SMB_VFS_STAT(conn, fsp->fsp_name, &sbuf) == -1) {
+ status = map_nt_error_from_unix(errno);
+ reply_nterror(req, status)
+ END_PROFILE(SMBsetattrE);
+ return;
}
- END_PROFILE(SMBsetattrE);
- return;
- } else if (!null_timespec(ts[0]) && null_timespec(ts[1])) {
- /* set modify time = to access time if modify time was unset */
- ts[1] = ts[0];
}
- /* Set the date on this file */
- /* Should we set pending modtime here ? JRA */
- if(file_ntimes(conn, fsp->fsp_name, ts)) {
- reply_doserror(req, ERRDOS, ERRnoaccess);
+ status = smb_set_file_time(conn, fsp, fsp->fsp_name,
+ &sbuf, ts, true);
+ if (!NT_STATUS_IS_OK(status)) {
+ reply_doserror(req, ERRDOS, ERRnoaccess)
END_PROFILE(SMBsetattrE);
return;
}
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: