summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/proto.h12
-rw-r--r--source3/include/smb.h2
-rw-r--r--source3/modules/vfs_default.c9
-rw-r--r--source3/param/loadparm.c12
-rwxr-xr-xsource3/script/tests/selftest.sh1
-rw-r--r--source3/smbd/dosmode.c91
-rw-r--r--source3/smbd/nttrans.c8
-rw-r--r--source3/smbd/open.c9
-rw-r--r--source3/smbd/reply.c2
-rw-r--r--source3/smbd/trans2.c9
10 files changed, 140 insertions, 15 deletions
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 8b3e029d3f..963e6df0c8 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -4187,6 +4187,7 @@ bool lp_administrative_share(int );
bool lp_print_ok(int );
bool lp_map_hidden(int );
bool lp_map_archive(int );
+bool lp_store_create_time(int );
bool lp_store_dos_attributes(int );
bool lp_dmapi_support(int );
bool lp_locking(const struct share_params *p );
@@ -6266,10 +6267,17 @@ bool set_sticky_write_time_fsp(struct files_struct *fsp,
struct timespec mtime);
bool update_write_time(struct files_struct *fsp);
-struct timespec get_create_timespec(struct files_struct *fsp,
+NTSTATUS set_create_timespec_ea(connection_struct *conn,
+ struct files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ struct timespec create_time);
+
+struct timespec get_create_timespec(connection_struct *conn,
+ struct files_struct *fsp,
const struct smb_filename *smb_fname);
-struct timespec get_change_timespec(struct files_struct *fsp,
+struct timespec get_change_timespec(connection_struct *conn,
+ struct files_struct *fsp,
const struct smb_filename *smb_fname);
/* The following definitions come from smbd/error.c */
diff --git a/source3/include/smb.h b/source3/include/smb.h
index fb01a92113..28bd60a670 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -1859,6 +1859,8 @@ struct ea_list {
#define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB"
/* Prefix for DosStreams in the vfs_streams_xattr module */
#define SAMBA_XATTR_DOSSTREAM_PREFIX "user.DosStream."
+/* Prefix for DOS timestamps. */
+#define SAMBA_XATTR_DOSTIMESTAMPS "user.DosTimestamps"
#define UUID_SIZE 16
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 2ee2fd1249..a793b337a8 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -817,6 +817,15 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
errno = ENOSYS;
result = -1;
#endif
+
+ if (!null_timespec(ft->create_time) &&
+ lp_store_create_time(SNUM(handle->conn))) {
+ set_create_timespec_ea(handle->conn,
+ NULL,
+ smb_fname,
+ ft->create_time);
+ }
+
out:
END_PROFILE(syscall_ntimes);
return result;
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index dbbd6e327d..35984716a2 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -446,6 +446,7 @@ struct service {
bool bMap_system;
bool bMap_hidden;
bool bMap_archive;
+ bool bStoreCreateTime;
bool bStoreDosAttributes;
bool bDmapiSupport;
bool bLocking;
@@ -589,6 +590,7 @@ static struct service sDefault = {
False, /* bMap_system */
False, /* bMap_hidden */
True, /* bMap_archive */
+ False, /* bStoreCreateTime */
False, /* bStoreDosAttributes */
False, /* bDmapiSupport */
True, /* bLocking */
@@ -3066,6 +3068,15 @@ static struct parm_struct parm_table[] = {
.flags = FLAG_ADVANCED,
},
{
+ .label = "store create time",
+ .type = P_BOOL,
+ .p_class = P_LOCAL,
+ .ptr = &sDefault.bStoreCreateTime,
+ .special = NULL,
+ .enum_list = NULL,
+ .flags = FLAG_ADVANCED | FLAG_SHARE | FLAG_GLOBAL,
+ },
+ {
.label = "store dos attributes",
.type = P_BOOL,
.p_class = P_LOCAL,
@@ -5564,6 +5575,7 @@ FN_LOCAL_BOOL(lp_administrative_share, bAdministrative_share)
FN_LOCAL_BOOL(lp_print_ok, bPrint_ok)
FN_LOCAL_BOOL(lp_map_hidden, bMap_hidden)
FN_LOCAL_BOOL(lp_map_archive, bMap_archive)
+FN_LOCAL_BOOL(lp_store_create_time, bStoreCreateTime)
FN_LOCAL_BOOL(lp_store_dos_attributes, bStoreDosAttributes)
FN_LOCAL_BOOL(lp_dmapi_support, bDmapiSupport)
FN_LOCAL_PARM_BOOL(lp_locking, bLocking)
diff --git a/source3/script/tests/selftest.sh b/source3/script/tests/selftest.sh
index e3871132d2..3fcfa4d60d 100755
--- a/source3/script/tests/selftest.sh
+++ b/source3/script/tests/selftest.sh
@@ -243,6 +243,7 @@ cat >$SERVERCONFFILE<<EOF
map hidden = yes
map system = yes
create mask = 755
+ store create time = yes
vfs objects = $BINDIR/xattr_tdb.so $BINDIR/streams_depot.so
#Include user defined custom parameters if set
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index f4803cb68d..e9e92ada20 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -853,20 +853,103 @@ bool update_write_time(struct files_struct *fsp)
}
/******************************************************************
- Return a create time (may look at EA in future).
+ Set a create time EA.
******************************************************************/
-struct timespec get_create_timespec(struct files_struct *fsp,
+NTSTATUS set_create_timespec_ea(connection_struct *conn,
+ struct files_struct *fsp,
+ const struct smb_filename *smb_fname,
+ struct timespec create_time)
+{
+ int ret;
+ char buf[8];
+
+ if (!lp_store_create_time(SNUM(conn))) {
+ return NT_STATUS_OK;
+ }
+
+ put_long_date_timespec(buf, create_time);
+ if (fsp && fsp->fh->fd != -1) {
+ ret = SMB_VFS_FSETXATTR(fsp,
+ SAMBA_XATTR_DOSTIMESTAMPS,
+ buf,
+ sizeof(buf),
+ 0);
+ } else {
+ ret = SMB_VFS_SETXATTR(conn,
+ smb_fname->base_name,
+ SAMBA_XATTR_DOSTIMESTAMPS,
+ buf,
+ sizeof(buf),
+ 0);
+ }
+
+ if (ret == -1) {
+ map_nt_error_from_unix(errno);
+ }
+ return NT_STATUS_OK;
+}
+
+/******************************************************************
+ Returns an EA create timespec, or a zero timespec if fail.
+******************************************************************/
+
+static struct timespec get_create_timespec_ea(connection_struct *conn,
+ struct files_struct *fsp,
+ const struct smb_filename *smb_fname)
+{
+ ssize_t ret;
+ char buf[8];
+ struct timespec ts;
+
+ ZERO_STRUCT(ts);
+
+ if (!lp_store_create_time(SNUM(conn))) {
+ return ts;
+ }
+
+ if (fsp && fsp->fh->fd != -1) {
+ ret = SMB_VFS_FGETXATTR(fsp,
+ SAMBA_XATTR_DOSTIMESTAMPS,
+ buf,
+ sizeof(buf));
+ } else {
+ ret = SMB_VFS_GETXATTR(conn,
+ smb_fname->base_name,
+ SAMBA_XATTR_DOSTIMESTAMPS,
+ buf,
+ sizeof(buf));
+ }
+ if (ret == sizeof(buf)) {
+ return interpret_long_date(buf);
+ } else {
+ return ts;
+ }
+}
+
+/******************************************************************
+ Return a create time - looks at EA.
+******************************************************************/
+
+struct timespec get_create_timespec(connection_struct *conn,
+ struct files_struct *fsp,
const struct smb_filename *smb_fname)
{
- return smb_fname->st.st_ex_btime;
+ struct timespec ts = get_create_timespec_ea(conn, fsp, smb_fname);
+
+ if (!null_timespec(ts)) {
+ return ts;
+ } else {
+ return smb_fname->st.st_ex_btime;
+ }
}
/******************************************************************
Return a change time (may look at EA in future).
******************************************************************/
-struct timespec get_change_timespec(struct files_struct *fsp,
+struct timespec get_change_timespec(connection_struct *conn,
+ struct files_struct *fsp,
const struct smb_filename *smb_fname)
{
return smb_fname->st.st_ex_mtime;
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 9f4074c865..03fdff3900 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -596,10 +596,10 @@ void reply_ntcreate_and_X(struct smb_request *req)
}
/* Create time. */
- create_timespec = get_create_timespec(fsp, smb_fname);
+ create_timespec = get_create_timespec(conn, fsp, smb_fname);
a_timespec = smb_fname->st.st_ex_atime;
m_timespec = smb_fname->st.st_ex_mtime;
- c_timespec = get_change_timespec(fsp, smb_fname);
+ c_timespec = get_change_timespec(conn, fsp, smb_fname);
if (lp_dos_filetime_resolution(SNUM(conn))) {
dos_filetime_timespec(&create_timespec);
@@ -1094,10 +1094,10 @@ static void call_nt_transact_create(connection_struct *conn,
}
/* Create time. */
- create_timespec = get_create_timespec(fsp, smb_fname);
+ create_timespec = get_create_timespec(conn, fsp, smb_fname);
a_timespec = smb_fname->st.st_ex_atime;
m_timespec = smb_fname->st.st_ex_mtime;
- c_timespec = get_change_timespec(fsp, smb_fname);
+ c_timespec = get_change_timespec(conn, fsp, smb_fname);
if (lp_dos_filetime_resolution(SNUM(conn))) {
dos_filetime_timespec(&create_timespec);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 62a0fa73b7..63982341ac 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -3280,6 +3280,15 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
SMB_VFS_FSTAT(fsp, &smb_fname->st);
fsp->fsp_name->st = smb_fname->st;
}
+
+ /* Try and make a create timestamp, if required. */
+ if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
+ if (lp_store_create_time(SNUM(conn))) {
+ set_create_timespec_ea(conn, fsp,
+ smb_fname, smb_fname->st.st_ex_btime);
+ }
+ }
+
return NT_STATUS_OK;
fail:
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index de187e902b..7b290a6b0e 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -7793,7 +7793,7 @@ void reply_getattrE(struct smb_request *req)
reply_outbuf(req, 11, 0);
- create_ts = get_create_timespec(fsp, fsp->fsp_name);
+ create_ts = get_create_timespec(conn, fsp, fsp->fsp_name);
srv_put_dos_date2((char *)req->outbuf, smb_vwv0, create_ts.tv_sec);
srv_put_dos_date2((char *)req->outbuf, smb_vwv2,
convert_timespec_to_time_t(sbuf.st_ex_atime));
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 93b217558d..b14d50594c 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -72,6 +72,7 @@ static bool samba_private_attr_name(const char *unix_ea_name)
static const char * const prohibited_ea_names[] = {
SAMBA_POSIX_INHERITANCE_EA_NAME,
SAMBA_XATTR_DOS_ATTRIB,
+ SAMBA_XATTR_DOSTIMESTAMPS,
NULL
};
@@ -1490,8 +1491,8 @@ static bool smbd_marshall_dir_entry(TALLOC_CTX *ctx,
mdate_ts = smb_fname->st.st_ex_mtime;
adate_ts = smb_fname->st.st_ex_atime;
- create_date_ts = get_create_timespec(NULL, smb_fname);
- cdate_ts = get_change_timespec(NULL, smb_fname);
+ create_date_ts = get_create_timespec(conn, NULL, smb_fname);
+ cdate_ts = get_change_timespec(conn, NULL, smb_fname);
if (lp_dos_filetime_resolution(SNUM(conn))) {
dos_filetime_timespec(&create_date_ts);
@@ -4057,10 +4058,10 @@ NTSTATUS smbd_do_qfilepathinfo(connection_struct *conn,
update_stat_ex_mtime(&sbuf, write_time_ts);
}
- create_time_ts = get_create_timespec(fsp, smb_fname);
+ create_time_ts = get_create_timespec(conn, fsp, smb_fname);
mtime_ts = sbuf.st_ex_mtime;
atime_ts = sbuf.st_ex_atime;
- ctime_ts = get_change_timespec(fsp, smb_fname);
+ ctime_ts = get_change_timespec(conn, fsp, smb_fname);
if (lp_dos_filetime_resolution(SNUM(conn))) {
dos_filetime_timespec(&create_time_ts);