summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalph Boehme <slow@samba.org>2019-12-02 16:30:50 +0100
committerJeremy Allison <jra@samba.org>2019-12-06 00:17:36 +0000
commit69691dd0cd5fac292bfb1c1dc28136ae253bbc76 (patch)
tree89c86e4ee8bd9d7a9e390bdb7c3e87460ba92212
parent6e58cfab98d958c8008c77b0d909a3384de28d7b (diff)
downloadsamba-69691dd0cd5fac292bfb1c1dc28136ae253bbc76.tar.gz
smbd: fix handling of sentinel timestamp values
This implements two core changes: * use NTTIME instead of struct timespec at the database layer * use struct timespec { .tv_nsec = SAMBA_UTIME_OMIT } as special sentinel value in smbd when processing timestamps Using NTTIME at the database layer is only done to avoid storing the special struct timespec sentinel values on disk. Instead, with NTTIME the sentinel value for an "unset" timestamp is just 0 on-disk. The NTTIME value of 0 gets translated by nt_time_to_full_timespec() to the struct timespec sentinel value { .tv_nsec = SAMBA_UTIME_OMIT }. The function is_omit_timespec() can be used to check this. Beside nt_time_to_full_timespec(), there are various other new time conversion functions with *full* in their name that can be used to safely convert between different types with the changed sentinel value. BUG: https://bugzilla.samba.org/show_bug.cgi?id=7771 Signed-off-by: Ralph Boehme <slow@samba.org> Reviewed-by: Jeremy Allison <jra@samba.org>
-rw-r--r--selftest/knownfail.d/samba3.smb210
-rw-r--r--source3/include/vfs.h1
-rw-r--r--source3/librpc/idl/open_files.idl6
-rw-r--r--source3/locking/locking.c27
-rw-r--r--source3/locking/share_mode_lock.c2
-rw-r--r--source3/modules/vfs_ceph.c12
-rw-r--r--source3/modules/vfs_default.c6
-rw-r--r--source3/modules/vfs_fruit.c2
-rw-r--r--source3/modules/vfs_glusterfs.c4
-rw-r--r--source3/modules/vfs_gpfs.c4
-rw-r--r--source3/modules/vfs_recycle.c2
-rw-r--r--source3/smbd/close.c15
-rw-r--r--source3/smbd/dir.c2
-rw-r--r--source3/smbd/dosmode.c16
-rw-r--r--source3/smbd/durable.c18
-rw-r--r--source3/smbd/fileio.c4
-rw-r--r--source3/smbd/files.c1
-rw-r--r--source3/smbd/open.c6
-rw-r--r--source3/smbd/reply.c23
-rw-r--r--source3/smbd/smb2_create.c4
-rw-r--r--source3/smbd/smb2_query_directory.c2
-rw-r--r--source3/smbd/trans2.c48
-rw-r--r--source3/torture/cmd_vfs.c6
23 files changed, 114 insertions, 107 deletions
diff --git a/selftest/knownfail.d/samba3.smb2 b/selftest/knownfail.d/samba3.smb2
deleted file mode 100644
index 8346ce95658..00000000000
--- a/selftest/knownfail.d/samba3.smb2
+++ /dev/null
@@ -1,10 +0,0 @@
-^samba3.smb2.timestamps.time_t_4294967295\(ad_dc\)
-^samba3.smb2.timestamps.time_t_4294967295\(nt4_dc\)
-^samba3.smb2.timestamps.time_t_0\(nt4_dc\)
-^samba3.smb2.timestamps.time_t_0\(ad_dc\)
-^samba3.smb2.timestamps.time_t_-1\(nt4_dc\)
-^samba3.smb2.timestamps.time_t_-1\(ad_dc\)
-^samba3.smb2.timestamps.time_t_-2\(nt4_dc\)
-^samba3.smb2.timestamps.time_t_-2\(ad_dc\)
-^samba3.smb2.timestamps.time_t_1968\(nt4_dc\)
-^samba3.smb2.timestamps.time_t_1968\(ad_dc\)
diff --git a/source3/include/vfs.h b/source3/include/vfs.h
index a6c57c6bcbc..28a3ce60543 100644
--- a/source3/include/vfs.h
+++ b/source3/include/vfs.h
@@ -287,6 +287,7 @@
Use SMB_VFS_UNLINKAT(.., AT_REMOVEDIR) instead. */
/* Version 42 - Remove SMB_VFS_CHOWN */
/* Version 42 - Remove struct write_cache *wcp from files_struct */
+/* Version 42 - SMB_VFS_NTIMES() receives null times based on UTIMES_OMIT */
#define SMB_VFS_INTERFACE_VERSION 42
diff --git a/source3/librpc/idl/open_files.idl b/source3/librpc/idl/open_files.idl
index 8742a38dfa6..4bfadb5656a 100644
--- a/source3/librpc/idl/open_files.idl
+++ b/source3/librpc/idl/open_files.idl
@@ -61,8 +61,8 @@ interface open_files
uint32 num_share_modes;
uint32 num_delete_tokens;
[size_is(num_delete_tokens)] delete_token delete_tokens[];
- timespec old_write_time;
- timespec changed_write_time;
+ NTTIME old_write_time;
+ NTTIME changed_write_time;
[skip] boolean8 fresh;
[skip] boolean8 modified;
[ignore] file_id id; /* In memory key used to lookup cache. */
@@ -105,7 +105,7 @@ interface open_files
boolean8 update_write_time_triggered;
boolean8 update_write_time_on_close;
boolean8 write_time_forced;
- timespec close_write_time;
+ NTTIME close_write_time;
vfs_default_durable_stat stat_info;
} vfs_default_durable_cookie;
diff --git a/source3/locking/locking.c b/source3/locking/locking.c
index 7822c2b3665..1220cb3a2be 100644
--- a/source3/locking/locking.c
+++ b/source3/locking/locking.c
@@ -36,6 +36,7 @@
*/
#include "includes.h"
+#include "lib/util/time_basic.h"
#include "system/filesys.h"
#include "lib/util/server_id.h"
#include "locking/proto.h"
@@ -637,7 +638,7 @@ void get_file_infos(struct file_id id,
}
if (write_time) {
- ZERO_STRUCTP(write_time);
+ *write_time = make_omit_timespec();
}
if (!(lck = fetch_share_mode_unlocked(talloc_tos(), id))) {
@@ -990,10 +991,11 @@ bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
{
struct share_mode_lock *lck;
struct file_id_buf ftmp;
+ struct timeval_buf tbuf;
+ NTTIME nt = full_timespec_to_nt_time(&write_time);
DBG_INFO("%s id=%s\n",
- timestring(talloc_tos(),
- convert_timespec_to_time_t(write_time)),
+ timespec_string_buf(&write_time, true, &tbuf),
file_id_str_buf(fileid, &ftmp));
lck = get_existing_share_mode_lock(talloc_tos(), fileid);
@@ -1001,9 +1003,9 @@ bool set_sticky_write_time(struct file_id fileid, struct timespec write_time)
return False;
}
- if (timespec_compare(&lck->data->changed_write_time, &write_time) != 0) {
+ if (lck->data->changed_write_time != nt) {
lck->data->modified = True;
- lck->data->changed_write_time = write_time;
+ lck->data->changed_write_time = nt;
}
TALLOC_FREE(lck);
@@ -1014,10 +1016,11 @@ bool set_write_time(struct file_id fileid, struct timespec write_time)
{
struct share_mode_lock *lck;
struct file_id_buf idbuf;
+ struct timeval_buf tbuf;
+ NTTIME nt = full_timespec_to_nt_time(&write_time);
DBG_INFO("%s id=%s\n",
- timestring(talloc_tos(),
- convert_timespec_to_time_t(write_time)),
+ timespec_string_buf(&write_time, true, &tbuf),
file_id_str_buf(fileid, &idbuf));
lck = get_existing_share_mode_lock(talloc_tos(), fileid);
@@ -1025,9 +1028,9 @@ bool set_write_time(struct file_id fileid, struct timespec write_time)
return False;
}
- if (timespec_compare(&lck->data->old_write_time, &write_time) != 0) {
+ if (lck->data->old_write_time != nt) {
lck->data->modified = True;
- lck->data->old_write_time = write_time;
+ lck->data->old_write_time = nt;
}
TALLOC_FREE(lck);
@@ -1038,10 +1041,10 @@ struct timespec get_share_mode_write_time(struct share_mode_lock *lck)
{
struct share_mode_data *d = lck->data;
- if (!null_timespec(d->changed_write_time)) {
- return d->changed_write_time;
+ if (!null_nttime(d->changed_write_time)) {
+ return nt_time_to_full_timespec(d->changed_write_time);
}
- return d->old_write_time;
+ return nt_time_to_full_timespec(d->old_write_time);
}
struct file_has_open_streams_state {
diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c
index edf47274d29..4697b6d9eee 100644
--- a/source3/locking/share_mode_lock.c
+++ b/source3/locking/share_mode_lock.c
@@ -505,7 +505,7 @@ static struct share_mode_data *fresh_share_mode_lock(
if (d->servicepath == NULL) {
goto fail;
}
- d->old_write_time = *old_write_time;
+ d->old_write_time = full_timespec_to_nt_time(old_write_time);
d->modified = false;
d->fresh = true;
return d;
diff --git a/source3/modules/vfs_ceph.c b/source3/modules/vfs_ceph.c
index 8864b424008..82bcb154f77 100644
--- a/source3/modules/vfs_ceph.c
+++ b/source3/modules/vfs_ceph.c
@@ -782,15 +782,15 @@ static int cephwrap_ntimes(struct vfs_handle_struct *handle,
int result;
int mask = 0;
- if (!null_timespec(ft->atime)) {
+ if (!is_omit_timespec(&ft->atime)) {
stx.stx_atime = ft->atime;
mask |= CEPH_SETATTR_ATIME;
}
- if (!null_timespec(ft->mtime)) {
+ if (!is_omit_timespec(&ft->mtime)) {
stx.stx_mtime = ft->mtime;
mask |= CEPH_SETATTR_MTIME;
}
- if (!null_timespec(ft->create_time)) {
+ if (!is_omit_timespec(&ft->create_time)) {
stx.stx_btime = ft->create_time;
mask |= CEPH_SETATTR_BTIME;
}
@@ -899,17 +899,17 @@ static int cephwrap_ntimes(struct vfs_handle_struct *handle,
struct utimbuf buf;
int result;
- if (null_timespec(ft->atime)) {
+ if (is_omit_timespec(&ft->atime)) {
buf.actime = smb_fname->st.st_ex_atime.tv_sec;
} else {
buf.actime = ft->atime.tv_sec;
}
- if (null_timespec(ft->mtime)) {
+ if (is_omit_timespec(&ft->mtime)) {
buf.modtime = smb_fname->st.st_ex_mtime.tv_sec;
} else {
buf.modtime = ft->mtime.tv_sec;
}
- if (!null_timespec(ft->create_time)) {
+ if (!is_omit_timespec(&ft->create_time)) {
set_create_timespec_ea(handle->conn, smb_fname,
ft->create_time);
}
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 368f1e25566..5666e09f60b 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -2332,15 +2332,15 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
}
if (ft != NULL) {
- if (null_timespec(ft->atime)) {
+ if (is_omit_timespec(&ft->atime)) {
ft->atime= smb_fname->st.st_ex_atime;
}
- if (null_timespec(ft->mtime)) {
+ if (is_omit_timespec(&ft->mtime)) {
ft->mtime = smb_fname->st.st_ex_mtime;
}
- if (!null_timespec(ft->create_time)) {
+ if (!is_omit_timespec(&ft->create_time)) {
set_create_timespec_ea(handle->conn,
smb_fname,
ft->create_time);
diff --git a/source3/modules/vfs_fruit.c b/source3/modules/vfs_fruit.c
index 265abdcb304..ebf3e18af2f 100644
--- a/source3/modules/vfs_fruit.c
+++ b/source3/modules/vfs_fruit.c
@@ -3801,7 +3801,7 @@ static int fruit_ntimes(vfs_handle_struct *handle,
return -1);
if ((config->meta != FRUIT_META_NETATALK) ||
- null_timespec(ft->create_time))
+ is_omit_timespec(&ft->create_time))
{
return SMB_VFS_NEXT_NTIMES(handle, smb_fname, ft);
}
diff --git a/source3/modules/vfs_glusterfs.c b/source3/modules/vfs_glusterfs.c
index d67ba89391c..6c3995b7168 100644
--- a/source3/modules/vfs_glusterfs.c
+++ b/source3/modules/vfs_glusterfs.c
@@ -1418,7 +1418,7 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
START_PROFILE(syscall_ntimes);
- if (null_timespec(ft->atime)) {
+ if (is_omit_timespec(&ft->atime)) {
times[0].tv_sec = smb_fname->st.st_ex_atime.tv_sec;
times[0].tv_nsec = smb_fname->st.st_ex_atime.tv_nsec;
} else {
@@ -1426,7 +1426,7 @@ static int vfs_gluster_ntimes(struct vfs_handle_struct *handle,
times[0].tv_nsec = ft->atime.tv_nsec;
}
- if (null_timespec(ft->mtime)) {
+ if (is_omit_timespec(&ft->mtime)) {
times[1].tv_sec = smb_fname->st.st_ex_mtime.tv_sec;
times[1].tv_nsec = smb_fname->st.st_ex_mtime.tv_nsec;
} else {
diff --git a/source3/modules/vfs_gpfs.c b/source3/modules/vfs_gpfs.c
index 558f57c2417..25df3266902 100644
--- a/source3/modules/vfs_gpfs.c
+++ b/source3/modules/vfs_gpfs.c
@@ -1934,7 +1934,7 @@ static int vfs_gpfs_lstat(struct vfs_handle_struct *handle,
static void timespec_to_gpfs_time(struct timespec ts, gpfs_timestruc_t *gt,
int idx, int *flags)
{
- if (!null_timespec(ts)) {
+ if (!is_omit_timespec(&ts)) {
*flags |= 1 << idx;
gt[idx].tv_sec = ts.tv_sec;
gt[idx].tv_nsec = ts.tv_nsec;
@@ -2004,7 +2004,7 @@ static int vfs_gpfs_ntimes(struct vfs_handle_struct *handle,
return -1;
}
- if(null_timespec(ft->create_time)){
+ if (is_omit_timespec(&ft->create_time)){
DEBUG(10,("vfs_gpfs_ntimes:Create Time is NULL\n"));
return 0;
}
diff --git a/source3/modules/vfs_recycle.c b/source3/modules/vfs_recycle.c
index 6c8c6a76f30..a1d32bf10cb 100644
--- a/source3/modules/vfs_recycle.c
+++ b/source3/modules/vfs_recycle.c
@@ -417,7 +417,7 @@ static void recycle_do_touch(vfs_handle_struct *handle,
struct smb_file_time ft;
int ret, err;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
smb_fname_tmp = cp_smb_filename(talloc_tos(), smb_fname);
if (smb_fname_tmp == NULL) {
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 6b63ea2c64e..f45371e656c 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -313,13 +313,16 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp,
}
if (fsp->write_time_forced) {
+ struct timespec ts;
+
DEBUG(10,("close_remove_share_mode: write time forced "
"for file %s\n",
fsp_str_dbg(fsp)));
- set_close_write_time(fsp, lck->data->changed_write_time);
+ ts = nt_time_to_full_timespec(lck->data->changed_write_time);
+ set_close_write_time(fsp, ts);
} else if (fsp->update_write_time_on_close) {
/* Someone had a pending write. */
- if (null_timespec(fsp->close_write_time)) {
+ if (is_omit_timespec(&fsp->close_write_time)) {
DEBUG(10,("close_remove_share_mode: update to current time "
"for file %s\n",
fsp_str_dbg(fsp)));
@@ -548,7 +551,7 @@ 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)) {
+ if (is_omit_timespec(&ts)) {
return;
}
fsp->write_time_forced = false;
@@ -562,13 +565,13 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
NTSTATUS status;
struct share_mode_lock *lck = NULL;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (!fsp->update_write_time_on_close) {
return NT_STATUS_OK;
}
- if (null_timespec(fsp->close_write_time)) {
+ if (is_omit_timespec(&fsp->close_write_time)) {
fsp->close_write_time = timespec_current();
}
@@ -603,7 +606,7 @@ static NTSTATUS update_write_time_on_close(struct files_struct *fsp)
/* Close write times overwrite sticky write times
so we must replace any sticky write time here. */
- if (!null_timespec(lck->data->changed_write_time)) {
+ if (!null_nttime(lck->data->changed_write_time)) {
(void)set_sticky_write_time(fsp->file_id, fsp->close_write_time);
}
TALLOC_FREE(lck);
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c
index 49e8dd17451..8314f4084c0 100644
--- a/source3/smbd/dir.c
+++ b/source3/smbd/dir.c
@@ -899,7 +899,7 @@ bool smbd_dirptr_get_entry(TALLOC_CTX *ctx,
fileid = vfs_file_id_from_sbuf(conn,
&smb_fname.st);
get_file_infos(fileid, 0, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
+ if (!is_omit_timespec(&write_time_ts)) {
update_stat_ex_mtime(&smb_fname.st,
write_time_ts);
}
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index b4ca2374118..322bf4476d6 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -313,7 +313,7 @@ NTSTATUS parse_dos_attribute_blob(struct smb_filename *smb_fname,
if ((dosattrib.info.info3.valid_flags & XATTR_DOSINFO_CREATE_TIME) &&
!null_nttime(dosattrib.info.info3.create_time)) {
struct timespec create_time =
- nt_time_to_unix_timespec(
+ nt_time_to_full_timespec(
dosattrib.info.info3.create_time);
update_stat_ex_create_time(&smb_fname->st,
@@ -336,7 +336,7 @@ NTSTATUS parse_dos_attribute_blob(struct smb_filename *smb_fname,
{
struct timespec creat_time;
- creat_time = nt_time_to_unix_timespec(info->create_time);
+ creat_time = nt_time_to_full_timespec(info->create_time);
update_stat_ex_create_time(&smb_fname->st, creat_time);
DBG_DEBUG("file [%s] creation time [%s]\n",
@@ -492,13 +492,13 @@ NTSTATUS set_ea_dos_attribute(connection_struct *conn,
dosattrib.info.info4.valid_flags = XATTR_DOSINFO_ATTRIB |
XATTR_DOSINFO_CREATE_TIME;
dosattrib.info.info4.attrib = dosmode;
- dosattrib.info.info4.create_time = unix_timespec_to_nt_time(
- smb_fname->st.st_ex_btime);
+ dosattrib.info.info4.create_time = full_timespec_to_nt_time(
+ &smb_fname->st.st_ex_btime);
if (!(smb_fname->st.st_ex_iflags & ST_EX_IFLAG_CALCULATED_ITIME)) {
dosattrib.info.info4.valid_flags |= XATTR_DOSINFO_ITIME;
- dosattrib.info.info4.itime = unix_timespec_to_nt_time(
- smb_fname->st.st_ex_itime);
+ dosattrib.info.info4.itime = full_timespec_to_nt_time(
+ &smb_fname->st.st_ex_itime);
}
DEBUG(10,("set_ea_dos_attributes: set attribute 0x%x, btime = %s on file %s\n",
@@ -1270,7 +1270,7 @@ int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime)
{
- if (null_timespec(mtime)) {
+ if (is_omit_timespec(&mtime)) {
return true;
}
@@ -1288,7 +1288,7 @@ bool set_sticky_write_time_path(struct file_id fileid, struct timespec mtime)
bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime)
{
- if (null_timespec(mtime)) {
+ if (is_omit_timespec(&mtime)) {
return true;
}
diff --git a/source3/smbd/durable.c b/source3/smbd/durable.c
index 9a2e639bdcd..9a4ebfb12d2 100644
--- a/source3/smbd/durable.c
+++ b/source3/smbd/durable.c
@@ -104,7 +104,8 @@ NTSTATUS vfs_default_durable_cookie(struct files_struct *fsp,
cookie.update_write_time_triggered = fsp->update_write_time_triggered;
cookie.update_write_time_on_close = fsp->update_write_time_on_close;
cookie.write_time_forced = fsp->write_time_forced;
- cookie.close_write_time = fsp->close_write_time;
+ cookie.close_write_time = full_timespec_to_nt_time(
+ &fsp->close_write_time);
cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev;
cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino;
@@ -205,19 +206,20 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
if (lck != NULL) {
struct smb_file_time ft;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (fsp->write_time_forced) {
- ft.mtime = lck->data->changed_write_time;
+ ft.mtime = nt_time_to_full_timespec(
+ lck->data->changed_write_time);
} else if (fsp->update_write_time_on_close) {
- if (null_timespec(fsp->close_write_time)) {
+ if (is_omit_timespec(&fsp->close_write_time)) {
ft.mtime = timespec_current();
} else {
ft.mtime = fsp->close_write_time;
}
}
- if (!null_timespec(ft.mtime)) {
+ if (!is_omit_timespec(&ft.mtime)) {
round_timespec(conn->ts_res, &ft.mtime);
file_ntimes(conn, fsp->fsp_name, &ft);
}
@@ -253,7 +255,8 @@ NTSTATUS vfs_default_durable_disconnect(struct files_struct *fsp,
cookie.update_write_time_triggered = fsp->update_write_time_triggered;
cookie.update_write_time_on_close = fsp->update_write_time_on_close;
cookie.write_time_forced = fsp->write_time_forced;
- cookie.close_write_time = fsp->close_write_time;
+ cookie.close_write_time = full_timespec_to_nt_time(
+ &fsp->close_write_time);
cookie.stat_info.st_ex_dev = fsp->fsp_name->st.st_ex_dev;
cookie.stat_info.st_ex_ino = fsp->fsp_name->st.st_ex_ino;
@@ -748,7 +751,8 @@ NTSTATUS vfs_default_durable_reconnect(struct connection_struct *conn,
fsp->update_write_time_triggered = cookie.update_write_time_triggered;
fsp->update_write_time_on_close = cookie.update_write_time_on_close;
fsp->write_time_forced = cookie.write_time_forced;
- fsp->close_write_time = cookie.close_write_time;
+ fsp->close_write_time = nt_time_to_full_timespec(
+ cookie.close_write_time);
status = fsp_set_smb_fname(fsp, smb_fname);
if (!NT_STATUS_IS_OK(status)) {
diff --git a/source3/smbd/fileio.c b/source3/smbd/fileio.c
index b03f86d49d6..029965282f1 100644
--- a/source3/smbd/fileio.c
+++ b/source3/smbd/fileio.c
@@ -178,6 +178,8 @@ void trigger_write_time_update_immediate(struct files_struct *fsp)
{
struct smb_file_time ft;
+ init_smb_file_time(&ft);
+
if (fsp->posix_flags & FSP_POSIX_FLAGS_OPEN) {
/* Don't use delayed writes on POSIX files. */
return;
@@ -199,7 +201,7 @@ void trigger_write_time_update_immediate(struct files_struct *fsp)
fsp->update_write_time_triggered = true;
fsp->update_write_time_on_close = false;
- ft = (struct smb_file_time) { .mtime = timespec_current() };
+ ft.mtime = timespec_current();
/* Update the time in the open file db. */
(void)set_write_time(fsp->file_id, ft.mtime);
diff --git a/source3/smbd/files.c b/source3/smbd/files.c
index 077610cad75..97947753170 100644
--- a/source3/smbd/files.c
+++ b/source3/smbd/files.c
@@ -65,6 +65,7 @@ NTSTATUS fsp_new(struct connection_struct *conn, TALLOC_CTX *mem_ctx,
fsp->fnum = FNUM_FIELD_INVALID;
fsp->conn = conn;
+ fsp->close_write_time = make_omit_timespec();
DLIST_ADD(sconn->files, fsp);
sconn->num_files += 1;
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index d7202d015cb..d3d77cee631 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -4035,7 +4035,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
*/
struct timespec write_time = get_share_mode_write_time(lck);
- if (!null_timespec(write_time)) {
+ if (!is_omit_timespec(&write_time)) {
update_stat_ex_mtime(&fsp->fsp_name->st, write_time);
}
}
@@ -4398,7 +4398,7 @@ static NTSTATUS open_directory(connection_struct *conn,
we only update timestamps on file writes.
See bug #9870.
*/
- ZERO_STRUCT(mtimespec);
+ mtimespec = make_omit_timespec();
#ifdef O_DIRECTORY
status = fd_open(conn, fsp, O_RDONLY|O_DIRECTORY, 0);
@@ -4523,7 +4523,7 @@ static NTSTATUS open_directory(connection_struct *conn,
*/
struct timespec write_time = get_share_mode_write_time(lck);
- if (!null_timespec(write_time)) {
+ if (!is_omit_timespec(&write_time)) {
update_stat_ex_mtime(&fsp->fsp_name->st, write_time);
}
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 5c173539aad..f2d0b878e20 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1449,7 +1449,7 @@ void reply_getatr(struct smb_request *req)
ZERO_STRUCT(write_time_ts);
fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
get_file_infos(fileid, 0, NULL, &write_time_ts);
- if (!null_timespec(write_time_ts)) {
+ if (!is_omit_timespec(&write_time_ts)) {
update_stat_ex_mtime(&smb_fname->st, write_time_ts);
}
}
@@ -1503,6 +1503,7 @@ void reply_setatr(struct smb_request *req)
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBsetatr);
+ init_smb_file_time(&ft);
if (req->wct < 2) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -1565,9 +1566,7 @@ void reply_setatr(struct smb_request *req)
}
}
- ft = (struct smb_file_time) {
- .mtime = convert_time_t_to_timespec(mtime)
- };
+ ft.mtime = time_t_to_full_timespec(mtime);
status = smb_set_file_time(conn, NULL, smb_fname, &ft, true);
if (!NT_STATUS_IS_OK(status)) {
@@ -2688,7 +2687,7 @@ void reply_mknew(struct smb_request *req)
TALLOC_CTX *ctx = talloc_tos();
START_PROFILE(SMBcreate);
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (req->wct < 3) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -2707,7 +2706,7 @@ void reply_mknew(struct smb_request *req)
}
/* mtime. */
- ft.mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+1));
+ ft.mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+1));
srvstr_get_path_req(ctx, req, &fname, (const char *)req->buf + 1,
STR_TERMINATE, &status);
@@ -5633,7 +5632,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(fsp, time_t_to_full_timespec(t));
}
if (fsp->num_aio_requests != 0) {
@@ -5770,7 +5769,7 @@ void reply_writeclose(struct smb_request *req)
numtowrite = SVAL(req->vwv+1, 0);
startpos = IVAL_TO_SMB_OFF_T(req->vwv+2, 0);
- mtime = convert_time_t_to_timespec(srv_make_unix_date3(req->vwv+4));
+ mtime = time_t_to_full_timespec(srv_make_unix_date3(req->vwv+4));
data = (const char *)req->buf + 1;
/*
@@ -8791,7 +8790,7 @@ void reply_setattrE(struct smb_request *req)
NTSTATUS status;
START_PROFILE(SMBsetattrE);
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (req->wct < 7) {
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
@@ -8809,11 +8808,11 @@ void reply_setattrE(struct smb_request *req)
* Convert the DOS times into unix times.
*/
- ft.atime = convert_time_t_to_timespec(
+ ft.atime = time_t_to_full_timespec(
srv_make_unix_date2(req->vwv+3));
- ft.mtime = convert_time_t_to_timespec(
+ ft.mtime = time_t_to_full_timespec(
srv_make_unix_date2(req->vwv+5));
- ft.create_time = convert_time_t_to_timespec(
+ ft.create_time = time_t_to_full_timespec(
srv_make_unix_date2(req->vwv+1));
reply_outbuf(req, 0, 0);
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index 1a3af78acf2..bf0c3912c07 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -1325,8 +1325,8 @@ static void smbd_smb2_create_after_exec(struct tevent_req *req)
if (state->mxac != NULL) {
NTTIME last_write_time;
- last_write_time = unix_timespec_to_nt_time(
- state->result->fsp_name->st.st_ex_mtime);
+ last_write_time = full_timespec_to_nt_time(
+ &state->result->fsp_name->st.st_ex_mtime);
if (last_write_time != state->max_access_time) {
uint8_t p[8];
uint32_t max_access_granted;
diff --git a/source3/smbd/smb2_query_directory.c b/source3/smbd/smb2_query_directory.c
index 94d2144ad26..79a46e005cf 100644
--- a/source3/smbd/smb2_query_directory.c
+++ b/source3/smbd/smb2_query_directory.c
@@ -930,7 +930,7 @@ static void fetch_write_time_done(struct tevent_req *subreq)
write_time = get_share_mode_write_time(lck);
TALLOC_FREE(lck);
- if (null_timespec(write_time)) {
+ if (is_omit_timespec(&write_time)) {
tevent_req_done(req);
return;
}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index ed5a52beb86..9c77b32ee68 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -26,6 +26,7 @@
#include "includes.h"
#include "ntioctl.h"
#include "system/filesys.h"
+#include "lib/util/time_basic.h"
#include "version.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
@@ -5220,7 +5221,9 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
dstart = pdata;
dend = dstart + data_size - 1;
- if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
+ if (!is_omit_timespec(&write_time_ts) &&
+ !INFO_LEVEL_IS_UNIX(info_level))
+ {
update_stat_ex_mtime(psbuf, write_time_ts);
}
@@ -6500,6 +6503,7 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
bool setting_write_time)
{
struct smb_filename smb_fname_base;
+ struct timeval_buf tbuf[4];
uint32_t action =
FILE_NOTIFY_CHANGE_LAST_ACCESS
|FILE_NOTIFY_CHANGE_LAST_WRITE
@@ -6510,15 +6514,15 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
}
/* get some defaults (no modifications) if any info is zero or -1. */
- if (null_timespec(ft->create_time)) {
+ if (is_omit_timespec(&ft->create_time)) {
action &= ~FILE_NOTIFY_CHANGE_CREATION;
}
- if (null_timespec(ft->atime)) {
+ if (is_omit_timespec(&ft->atime)) {
action &= ~FILE_NOTIFY_CHANGE_LAST_ACCESS;
}
- if (null_timespec(ft->mtime)) {
+ if (is_omit_timespec(&ft->mtime)) {
action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
}
@@ -6535,14 +6539,14 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
round_timespec(conn->ts_res, &ft->atime);
round_timespec(conn->ts_res, &ft->mtime);
- DEBUG(5,("smb_set_filetime: actime: %s\n ",
- time_to_asc(convert_timespec_to_time_t(ft->atime))));
- DEBUG(5,("smb_set_filetime: modtime: %s\n ",
- time_to_asc(convert_timespec_to_time_t(ft->mtime))));
- DEBUG(5,("smb_set_filetime: ctime: %s\n ",
- time_to_asc(convert_timespec_to_time_t(ft->ctime))));
- DEBUG(5,("smb_set_file_time: createtime: %s\n ",
- time_to_asc(convert_timespec_to_time_t(ft->create_time))));
+ DBG_DEBUG("smb_set_filetime: actime: %s\n ",
+ timespec_string_buf(&ft->atime, true, &tbuf[0]));
+ DBG_DEBUG("smb_set_filetime: modtime: %s\n ",
+ timespec_string_buf(&ft->mtime, true, &tbuf[1]));
+ DBG_DEBUG("smb_set_filetime: ctime: %s\n ",
+ timespec_string_buf(&ft->ctime, true, &tbuf[2]));
+ DBG_DEBUG("smb_set_file_time: createtime: %s\n ",
+ timespec_string_buf(&ft->create_time, true, &tbuf[3]));
if (setting_write_time) {
/*
@@ -6555,8 +6559,8 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
* away and will set it on file close and after a write. JRA.
*/
- DEBUG(10,("smb_set_file_time: setting pending modtime to %s\n",
- time_to_asc(convert_timespec_to_time_t(ft->mtime))));
+ DBG_DEBUG("setting pending modtime to %s\n",
+ timespec_string_buf(&ft->mtime, true, &tbuf[0]));
if (fsp != NULL) {
if (fsp->base_fsp) {
@@ -7780,7 +7784,7 @@ static NTSTATUS smb_set_file_basic_info(connection_struct *conn,
uint32_t dosmode = 0;
NTSTATUS status = NT_STATUS_OK;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (total_data < 36) {
return NT_STATUS_INVALID_PARAMETER;
@@ -7830,18 +7834,18 @@ static NTSTATUS smb_set_info_standard(connection_struct *conn,
NTSTATUS status;
struct smb_file_time ft;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (total_data < 12) {
return NT_STATUS_INVALID_PARAMETER;
}
/* create time */
- ft.create_time = convert_time_t_to_timespec(srv_make_unix_date2(pdata));
+ ft.create_time = time_t_to_full_timespec(srv_make_unix_date2(pdata));
/* access time */
- ft.atime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+4));
+ ft.atime = time_t_to_full_timespec(srv_make_unix_date2(pdata+4));
/* write time */
- ft.mtime = convert_time_t_to_timespec(srv_make_unix_date2(pdata+8));
+ ft.mtime = time_t_to_full_timespec(srv_make_unix_date2(pdata+8));
DEBUG(10,("smb_set_info_standard: file %s\n",
smb_fname_str_dbg(smb_fname)));
@@ -8122,7 +8126,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
struct file_id id;
SMB_STRUCT_STAT sbuf;
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
if (total_data < 100) {
return NT_STATUS_INVALID_PARAMETER;
@@ -8281,7 +8285,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
}
/* Deal with any time changes. */
- if (null_timespec(ft.mtime) && null_timespec(ft.atime)) {
+ if (is_omit_timespec(&ft.mtime) && is_omit_timespec(&ft.atime)) {
/* No change, don't cancel anything. */
return status;
}
@@ -8303,7 +8307,7 @@ static NTSTATUS smb_set_file_unix_basic(connection_struct *conn,
* we need. Just remember if we modified
* mtime and send the notify ourselves.
*/
- if (null_timespec(ft.mtime)) {
+ if (is_omit_timespec(&ft.mtime)) {
modify_mtime = false;
}
diff --git a/source3/torture/cmd_vfs.c b/source3/torture/cmd_vfs.c
index fb9615e26a3..81068fb84a0 100644
--- a/source3/torture/cmd_vfs.c
+++ b/source3/torture/cmd_vfs.c
@@ -1003,10 +1003,10 @@ static NTSTATUS cmd_utime(struct vfs_state *vfs, TALLOC_CTX *mem_ctx, int argc,
return NT_STATUS_OK;
}
- ZERO_STRUCT(ft);
+ init_smb_file_time(&ft);
- ft.atime = convert_time_t_to_timespec(atoi(argv[2]));
- ft.mtime = convert_time_t_to_timespec(atoi(argv[3]));
+ ft.atime = time_t_to_full_timespec(atoi(argv[2]));
+ ft.mtime = time_t_to_full_timespec(atoi(argv[3]));
smb_fname = synthetic_smb_fname_split(mem_ctx,
argv[1],