summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs-xml/smbdotconf/filename/storecreatetime.xml15
-rw-r--r--docs-xml/smbdotconf/filename/storedosattributes.xml7
-rw-r--r--source3/include/proto.h8
-rw-r--r--source3/lib/system.c7
-rw-r--r--source3/lib/time.c27
-rw-r--r--source3/modules/onefs_open.c2
-rw-r--r--source3/modules/vfs_default.c4
-rw-r--r--source3/param/loadparm.c12
-rw-r--r--source3/printing/printfsp.c9
-rw-r--r--source3/smbd/dosmode.c244
-rw-r--r--source3/smbd/nttrans.c18
-rw-r--r--source3/smbd/open.c20
-rw-r--r--source3/smbd/reply.c3
-rw-r--r--source3/smbd/smb2_create.c40
-rw-r--r--source3/smbd/trans2.c2
15 files changed, 238 insertions, 180 deletions
diff --git a/docs-xml/smbdotconf/filename/storecreatetime.xml b/docs-xml/smbdotconf/filename/storecreatetime.xml
deleted file mode 100644
index 5957a5db10..0000000000
--- a/docs-xml/smbdotconf/filename/storecreatetime.xml
+++ /dev/null
@@ -1,15 +0,0 @@
-<samba:parameter name="store create time"
- context="S"
- type="boolean"
- xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
-<description>
- <para>
- If this parameter is set Samba attempts to store a create timestamp on any file or directory created by Samba
- in a filesystem extended attribute. The data is written as an 8 byte Windows timestamp in little-endian form
- in attribute named "user.DosTimestamps". This extended attribute is explicitly hidden from smbd clients requesting an
- EA list. On Linux the filesystem must have been mounted with the mount option user_xattr in order for
- extended attributes to work, also extended attributes must be compiled into the Linux kernel.
- </para>
-</description>
-<value type="default">no</value>
-</samba:parameter>
diff --git a/docs-xml/smbdotconf/filename/storedosattributes.xml b/docs-xml/smbdotconf/filename/storedosattributes.xml
index 6fcab82f9c..621b4ace74 100644
--- a/docs-xml/smbdotconf/filename/storedosattributes.xml
+++ b/docs-xml/smbdotconf/filename/storedosattributes.xml
@@ -14,6 +14,13 @@
attribute named "user.DOSATTRIB". This extended attribute is explicitly hidden from smbd clients requesting an
EA list. On Linux the filesystem must have been mounted with the mount option user_xattr in order for
extended attributes to work, also extended attributes must be compiled into the Linux kernel.
+
+ In Samba 3.5.0 and above the "user.DOSATTRIB" extended attribute has been extended to store
+ the create time for a file as well as the DOS attributes. This is done in a backwards compatible
+ way so files created by Samba 3.5.0 and above can still have the DOS attribute read from this
+ extended attribute by earlier versions of Samba, but they will not be able to read the create
+ time stored there. Storing the create time separately from the normal filesystem meta-data
+ allows Samba to faithfully reproduce NTFS semantics on top of a POSIX filesystem.
</para>
</description>
<value type="default">no</value>
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 4e347d6ddb..6f971c3a07 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -926,6 +926,7 @@ ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *f
int sys_fcntl_ptr(int fd, int cmd, void *arg);
int sys_fcntl_long(int fd, int cmd, long arg);
void update_stat_ex_mtime(struct stat_ex *dst, struct timespec write_ts);
+void update_stat_ex_create_time(struct stat_ex *dst, struct timespec create_time);
int sys_stat(const char *fname,SMB_STRUCT_STAT *sbuf);
int sys_fstat(int fd,SMB_STRUCT_STAT *sbuf);
int sys_lstat(const char *fname,SMB_STRUCT_STAT *sbuf);
@@ -4196,7 +4197,6 @@ 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 );
@@ -4927,8 +4927,7 @@ bool sysv_cache_reload(void);
NTSTATUS print_fsp_open(struct smb_request *req, connection_struct *conn,
const char *fname,
- uint16_t current_vuid, files_struct *fsp,
- SMB_STRUCT_STAT *psbuf);
+ uint16_t current_vuid, files_struct *fsp);
void print_fsp_end(files_struct *fsp, enum file_close_type close_type);
/* The following definitions come from printing/printing.c */
@@ -6252,7 +6251,7 @@ mode_t unix_mode(connection_struct *conn, int dosmode,
uint32 dos_mode_msdfs(connection_struct *conn,
const struct smb_filename *smb_fname);
int dos_attributes_to_stat_dos_flags(uint32_t dosmode);
-uint32 dos_mode(connection_struct *conn, const struct smb_filename *smb_fname);
+uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname);
int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
uint32 dosmode, const char *parent_dir, bool newfile);
int file_ntimes(connection_struct *conn, const struct smb_filename *smb_fname,
@@ -6262,7 +6261,6 @@ bool set_sticky_write_time_fsp(struct files_struct *fsp,
struct timespec mtime);
NTSTATUS set_create_timespec_ea(connection_struct *conn,
- struct files_struct *fsp,
const struct smb_filename *smb_fname,
struct timespec create_time);
diff --git a/source3/lib/system.c b/source3/lib/system.c
index 4331691746..8abcb3dc66 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -504,6 +504,13 @@ void update_stat_ex_mtime(struct stat_ex *dst,
}
}
+void update_stat_ex_create_time(struct stat_ex *dst,
+ struct timespec create_time)
+{
+ dst->st_ex_btime = create_time;
+ dst->st_ex_calculated_birthtime = false;
+}
+
static void init_stat_ex_from_stat (struct stat_ex *dst,
const struct stat *src)
{
diff --git a/source3/lib/time.c b/source3/lib/time.c
index f6ff6d3407..1d2fae3d17 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -680,6 +680,33 @@ void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
*nt = d;
}
+#if 0
+void nt_time_to_unix_timespec(struct timespec *ts, NTTIME t)
+{
+ if (ts == NULL) {
+ return;
+ }
+
+ /* t starts in 100 nsec units since 1601-01-01. */
+
+ t *= 100;
+ /* t is now in nsec units since 1601-01-01. */
+
+ t -= TIME_FIXUP_CONSTANT*1000*1000*100;
+ /* t is now in nsec units since the UNIX epoch 1970-01-01. */
+
+ ts->tv_sec = t / 1000000000LL;
+
+ if (TIME_T_MIN > ts->tv_sec || ts->tv_sec > TIME_T_MAX) {
+ ts->tv_sec = 0;
+ ts->tv_nsec = 0;
+ return;
+ }
+
+ ts->tv_nsec = t - ts->tv_sec*1000000000LL;
+}
+#endif
+
/****************************************************************************
Convert a time_t to a NTTIME structure
diff --git a/source3/modules/onefs_open.c b/source3/modules/onefs_open.c
index d90f165cd7..fd12fff58c 100644
--- a/source3/modules/onefs_open.c
+++ b/source3/modules/onefs_open.c
@@ -489,7 +489,7 @@ NTSTATUS onefs_open_file_ntcreate(connection_struct *conn,
smb_fname_str_dbg(smb_fname)));
return print_fsp_open(req, conn, smb_fname->base_name,
- req->vuid, fsp, &smb_fname->st);
+ req->vuid, fsp);
}
if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir,
diff --git a/source3/modules/vfs_default.c b/source3/modules/vfs_default.c
index 17237ac83f..8fbea0c4f3 100644
--- a/source3/modules/vfs_default.c
+++ b/source3/modules/vfs_default.c
@@ -853,10 +853,8 @@ static int vfswrap_ntimes(vfs_handle_struct *handle,
ft->mtime = smb_fname->st.st_ex_mtime;
}
- if (!null_timespec(ft->create_time) &&
- lp_store_create_time(SNUM(handle->conn))) {
+ if (!null_timespec(ft->create_time)) {
set_create_timespec_ea(handle->conn,
- NULL,
smb_fname,
ft->create_time);
}
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index c62deb5eda..c024603cb9 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -452,7 +452,6 @@ struct service {
bool bMap_system;
bool bMap_hidden;
bool bMap_archive;
- bool bStoreCreateTime;
bool bStoreDosAttributes;
bool bDmapiSupport;
bool bLocking;
@@ -596,7 +595,6 @@ static struct service sDefault = {
False, /* bMap_system */
False, /* bMap_hidden */
True, /* bMap_archive */
- False, /* bStoreCreateTime */
False, /* bStoreDosAttributes */
False, /* bDmapiSupport */
True, /* bLocking */
@@ -3083,15 +3081,6 @@ 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,
@@ -5618,7 +5607,6 @@ 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/printing/printfsp.c b/source3/printing/printfsp.c
index 9185fc84b1..b9fe49226e 100644
--- a/source3/printing/printfsp.c
+++ b/source3/printing/printfsp.c
@@ -27,8 +27,7 @@ print_job_start().
NTSTATUS print_fsp_open(struct smb_request *req, connection_struct *conn,
const char *fname,
- uint16_t current_vuid, files_struct *fsp,
- SMB_STRUCT_STAT *psbuf)
+ uint16_t current_vuid, files_struct *fsp)
{
int jobid;
fstring name;
@@ -80,9 +79,9 @@ NTSTATUS print_fsp_open(struct smb_request *req, connection_struct *conn,
fsp->sent_oplock_break = NO_BREAK_SENT;
fsp->is_directory = False;
fsp->wcp = NULL;
- SMB_VFS_FSTAT(fsp, psbuf);
- fsp->mode = psbuf->st_ex_mode;
- fsp->file_id = vfs_file_id_from_sbuf(conn, psbuf);
+ SMB_VFS_FSTAT(fsp, &fsp->fsp_name->st);
+ fsp->mode = fsp->fsp_name->st.st_ex_mode;
+ fsp->file_id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);
return NT_STATUS_OK;
}
diff --git a/source3/smbd/dosmode.c b/source3/smbd/dosmode.c
index e10f23918d..0f31973675 100644
--- a/source3/smbd/dosmode.c
+++ b/source3/smbd/dosmode.c
@@ -19,6 +19,7 @@
*/
#include "includes.h"
+#include "librpc/gen_ndr/ndr_xattr.h"
static int set_sparse_flag(const SMB_STRUCT_STAT * const sbuf)
{
@@ -205,15 +206,19 @@ static uint32 dos_mode_from_sbuf(connection_struct *conn,
/****************************************************************************
Get DOS attributes from an EA.
+ This can also pull the create time into the stat struct inside smb_fname.
****************************************************************************/
static bool get_ea_dos_attribute(connection_struct *conn,
- const struct smb_filename *smb_fname,
+ struct smb_filename *smb_fname,
uint32 *pattr)
{
+ struct xattr_DOSATTRIB dosattrib;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
ssize_t sizeret;
fstring attrstr;
- unsigned int dosattr;
+ uint32_t dosattr;
if (!lp_store_dos_attributes(SNUM(conn))) {
return False;
@@ -240,18 +245,65 @@ static bool get_ea_dos_attribute(connection_struct *conn,
}
return False;
}
- /* Null terminate string. */
- attrstr[sizeret] = 0;
- DEBUG(10,("get_ea_dos_attribute: %s attrstr = %s\n",
- smb_fname_str_dbg(smb_fname), attrstr));
- if (sizeret < 2 || attrstr[0] != '0' || attrstr[1] != 'x' ||
- sscanf(attrstr, "%x", &dosattr) != 1) {
- DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on "
- "file %s - %s\n", smb_fname_str_dbg(smb_fname),
- attrstr));
- return False;
- }
+ blob.data = (uint8_t *)attrstr;
+ blob.length = sizeret;
+
+ ndr_err = ndr_pull_struct_blob(&blob, talloc_tos(), NULL, &dosattrib,
+ (ndr_pull_flags_fn_t)ndr_pull_xattr_DOSATTRIB);
+
+ DEBUG(10,("get_ea_dos_attribute: %s attr = %s\n",
+ smb_fname_str_dbg(smb_fname), dosattrib.attrib_hex));
+
+ switch (dosattrib.version) {
+ case 0xFFFF:
+ dosattr = dosattrib.info.compatinfoFFFF.attrib;
+ break;
+ case 1:
+ dosattr = dosattrib.info.info1.attrib;
+ if (!null_nttime(dosattrib.info.info1.create_time)) {
+ struct timespec create_time =
+ nt_time_to_unix_timespec(
+ &dosattrib.info.info1.create_time);
+
+ update_stat_ex_create_time(&smb_fname->st,
+ create_time);
+
+ DEBUG(10,("get_ea_dos_attributes: file %s case 1 "
+ "set btime %s\n",
+ smb_fname_str_dbg(smb_fname),
+ time_to_asc(convert_timespec_to_time_t(
+ create_time)) ));
+ }
+ break;
+ case 2:
+ dosattr = dosattrib.info.oldinfo2.attrib;
+ /* Don't know what flags to check for this case. */
+ break;
+ case 3:
+ dosattr = dosattrib.info.info3.attrib;
+ 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(
+ &dosattrib.info.info3.create_time);
+
+ update_stat_ex_create_time(&smb_fname->st,
+ create_time);
+
+ DEBUG(10,("get_ea_dos_attributes: file %s case 3 "
+ "set btime %s\n",
+ smb_fname_str_dbg(smb_fname),
+ time_to_asc(convert_timespec_to_time_t(
+ create_time)) ));
+ }
+ break;
+ default:
+ DEBUG(1,("get_ea_dos_attributes: Badly formed DOSATTRIB on "
+ "file %s - %s\n", smb_fname_str_dbg(smb_fname),
+ attrstr));
+ return false;
+ }
if (S_ISDIR(smb_fname->st.st_ex_mode)) {
dosattr |= aDIR;
@@ -273,23 +325,49 @@ static bool get_ea_dos_attribute(connection_struct *conn,
/****************************************************************************
Set DOS attributes in an EA.
+ Also sets the create time.
****************************************************************************/
static bool set_ea_dos_attribute(connection_struct *conn,
struct smb_filename *smb_fname,
uint32 dosmode)
{
- fstring attrstr;
+ struct xattr_DOSATTRIB dosattrib;
+ enum ndr_err_code ndr_err;
+ DATA_BLOB blob;
files_struct *fsp = NULL;
- bool ret = False;
+ bool ret = false;
if (!lp_store_dos_attributes(SNUM(conn))) {
return False;
}
- snprintf(attrstr, sizeof(attrstr)-1, "0x%x", dosmode & SAMBA_ATTRIBUTES_MASK);
+ ZERO_STRUCT(dosattrib);
+ ZERO_STRUCT(blob);
+
+ dosattrib.version = 3;
+ dosattrib.info.info3.valid_flags = XATTR_DOSINFO_ATTRIB|
+ XATTR_DOSINFO_CREATE_TIME;
+ dosattrib.info.info3.attrib = dosmode;
+ unix_timespec_to_nt_time(&dosattrib.info.info3.create_time,
+ smb_fname->st.st_ex_btime);
+
+ ndr_err = ndr_push_struct_blob(
+ &blob, talloc_tos(), NULL, &dosattrib,
+ (ndr_push_flags_fn_t)ndr_push_xattr_DOSATTRIB);
+
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(5, ("create_acl_blob: ndr_push_xattr_DOSATTRIB failed: %s\n",
+ ndr_errstr(ndr_err)));
+ return false;
+ }
+
+ if (blob.data == NULL || blob.length == 0) {
+ return false;
+ }
+
if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
- SAMBA_XATTR_DOS_ATTRIB, attrstr, strlen(attrstr),
+ SAMBA_XATTR_DOS_ATTRIB, blob.data, blob.length,
0) == -1) {
if((errno != EPERM) && (errno != EACCES)) {
if (errno == ENOSYS
@@ -304,7 +382,7 @@ static bool set_ea_dos_attribute(connection_struct *conn,
strerror(errno) ));
set_store_dos_attributes(SNUM(conn), False);
}
- return False;
+ return false;
}
/* We want DOS semantics, ie allow non owner with write permission to change the
@@ -313,7 +391,7 @@ static bool set_ea_dos_attribute(connection_struct *conn,
/* Check if we have write access. */
if(!CAN_WRITE(conn) || !lp_dos_filemode(SNUM(conn)))
- return False;
+ return false;
/*
* We need to open the file with write access whilst
@@ -326,17 +404,18 @@ static bool set_ea_dos_attribute(connection_struct *conn,
return ret;
become_root();
if (SMB_VFS_SETXATTR(conn, smb_fname->base_name,
- SAMBA_XATTR_DOS_ATTRIB, attrstr,
- strlen(attrstr), 0) == 0) {
- ret = True;
+ SAMBA_XATTR_DOS_ATTRIB, blob.data,
+ blob.length, 0) == 0) {
+ ret = true;
}
unbecome_root();
close_file_fchmod(NULL, fsp);
return ret;
}
- DEBUG(10,("set_ea_dos_attribute: set EA %s on file %s\n", attrstr,
- smb_fname_str_dbg(smb_fname)));
- return True;
+ DEBUG(10,("set_ea_dos_attribute: set EA 0x%x on file %s\n",
+ (unsigned int)dosmode,
+ smb_fname_str_dbg(smb_fname)));
+ return true;
}
/****************************************************************************
@@ -510,11 +589,12 @@ static bool set_stat_dos_flags(connection_struct *conn,
/****************************************************************************
Change a unix mode to a dos mode.
+ May also read the create timespec into the stat struct in smb_fname
+ if "store dos attributes" is true.
****************************************************************************/
-uint32 dos_mode(connection_struct *conn, const struct smb_filename *smb_fname)
+uint32 dos_mode(connection_struct *conn, struct smb_filename *smb_fname)
{
- SMB_STRUCT_STAT sbuf;
uint32 result = 0;
bool offline, used_stat_dos_flags = false;
@@ -553,9 +633,8 @@ uint32 dos_mode(connection_struct *conn, const struct smb_filename *smb_fname)
}
}
- sbuf = smb_fname->st;
- offline = SMB_VFS_IS_OFFLINE(conn, smb_fname->base_name, &sbuf);
- if (S_ISREG(sbuf.st_ex_mode) && offline) {
+ offline = SMB_VFS_IS_OFFLINE(conn, smb_fname->base_name, &smb_fname->st);
+ if (S_ISREG(smb_fname->st.st_ex_mode) && offline) {
result |= FILE_ATTRIBUTE_OFFLINE;
}
@@ -588,6 +667,9 @@ uint32 dos_mode(connection_struct *conn, const struct smb_filename *smb_fname)
/*******************************************************************
chmod a file - but preserve some bits.
+ If "store dos attributes" is also set it will store the create time
+ from the stat struct in smb_fname (in NTTIME format) in the EA
+ attribute also.
********************************************************************/
int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
@@ -598,6 +680,7 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
mode_t unixmode;
int ret = -1, lret = -1;
uint32_t old_mode;
+ struct timespec new_create_timespec;
/* We only allow READONLY|HIDDEN|SYSTEM|DIRECTORY|ARCHIVE here. */
dosmode &= (SAMBA_ATTRIBUTES_MASK | FILE_ATTRIBUTE_OFFLINE);
@@ -605,11 +688,6 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
DEBUG(10,("file_set_dosmode: setting dos mode 0x%x on file %s\n",
dosmode, smb_fname_str_dbg(smb_fname)));
- if (!VALID_STAT(smb_fname->st)) {
- if (SMB_VFS_STAT(conn, smb_fname))
- return(-1);
- }
-
unixmode = smb_fname->st.st_ex_mode;
get_acl_group_bits(conn, smb_fname->base_name,
@@ -620,6 +698,8 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
else
dosmode &= ~aDIR;
+ new_create_timespec = smb_fname->st.st_ex_btime;
+
old_mode = dos_mode(conn, smb_fname);
if (dosmode & FILE_ATTRIBUTE_OFFLINE) {
@@ -639,11 +719,15 @@ int file_set_dosmode(connection_struct *conn, struct smb_filename *smb_fname,
dosmode &= ~FILE_ATTRIBUTE_OFFLINE;
old_mode &= ~FILE_ATTRIBUTE_OFFLINE;
- if (old_mode == dosmode) {
+ if (old_mode == dosmode &&
+ (timespec_compare(&new_create_timespec,
+ &smb_fname->st.st_ex_btime) == 0)) {
smb_fname->st.st_ex_mode = unixmode;
return(0);
}
+ smb_fname->st.st_ex_btime = new_create_timespec;
+
#ifdef HAVE_STAT_DOS_FLAGS
{
bool attributes_changed;
@@ -842,6 +926,10 @@ 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)) {
+ return true;
+ }
+
fsp->write_time_forced = true;
TALLOC_FREE(fsp->update_write_time_event);
@@ -853,93 +941,51 @@ bool set_sticky_write_time_fsp(struct files_struct *fsp, struct timespec mtime)
******************************************************************/
NTSTATUS set_create_timespec_ea(connection_struct *conn,
- struct files_struct *fsp,
- const struct smb_filename *smb_fname,
+ const struct smb_filename *psmb_fname,
struct timespec create_time)
{
+ NTSTATUS status;
+ struct smb_filename *smb_fname = NULL;
+ uint32_t dosmode;
int ret;
- char buf[8];
- if (!lp_store_create_time(SNUM(conn))) {
+ if (!lp_store_dos_attributes(SNUM(conn))) {
return NT_STATUS_OK;
}
- put_long_date_timespec(conn->ts_res, 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);
+ status = create_synthetic_smb_fname(talloc_tos(),
+ psmb_fname->base_name,
+ NULL, &psmb_fname->st,
+ &smb_fname);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
}
+ dosmode = dos_mode(conn, smb_fname);
+
+ smb_fname->st.st_ex_btime = create_time;
+
+ ret = file_set_dosmode(conn, smb_fname, dosmode, NULL, false);
if (ret == -1) {
map_nt_error_from_unix(errno);
}
+
DEBUG(10,("set_create_timespec_ea: wrote create time EA for file %s\n",
smb_fname_str_dbg(smb_fname)));
- 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 NT_STATUS_OK;
}
/******************************************************************
- Return a create time - looks at EA.
+ Return a create time.
******************************************************************/
struct timespec get_create_timespec(connection_struct *conn,
struct files_struct *fsp,
const struct smb_filename *smb_fname)
{
- 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 smb_fname->st.st_ex_btime;
}
/******************************************************************
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index 66102fa96c..bacb9cb0b2 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -554,10 +554,6 @@ void reply_ntcreate_and_X(struct smb_request *req)
}
file_len = smb_fname->st.st_ex_size;
- fattr = dos_mode(conn, smb_fname);
- if (fattr == 0) {
- fattr = FILE_ATTRIBUTE_NORMAL;
- }
if (flags & EXTENDED_RESPONSE_REQUIRED) {
/* This is very strange. We
@@ -586,6 +582,11 @@ void reply_ntcreate_and_X(struct smb_request *req)
}
p += 4;
+ fattr = dos_mode(conn, smb_fname);
+ if (fattr == 0) {
+ fattr = FILE_ATTRIBUTE_NORMAL;
+ }
+
/* Deal with other possible opens having a modified
write time. JRA. */
ZERO_STRUCT(write_time_ts);
@@ -1070,10 +1071,6 @@ static void call_nt_transact_create(connection_struct *conn,
}
file_len = smb_fname->st.st_ex_size;
- fattr = dos_mode(conn, smb_fname);
- if (fattr == 0) {
- fattr = FILE_ATTRIBUTE_NORMAL;
- }
/* Realloc the size of parameters and data we will return */
if (flags & EXTENDED_RESPONSE_REQUIRED) {
@@ -1102,6 +1099,11 @@ static void call_nt_transact_create(connection_struct *conn,
}
p += 8;
+ fattr = dos_mode(conn, smb_fname);
+ if (fattr == 0) {
+ fattr = FILE_ATTRIBUTE_NORMAL;
+ }
+
/* Deal with other possible opens having a modified
write time. JRA. */
ZERO_STRUCT(write_time_ts);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 85b7d9106d..1f48daf904 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -1495,7 +1495,7 @@ static NTSTATUS open_file_ntcreate(connection_struct *conn,
}
return print_fsp_open(req, conn, smb_fname->base_name,
- req->vuid, fsp, &smb_fname->st);
+ req->vuid, fsp);
}
if (!parent_dirname(talloc_tos(), smb_fname->base_name, &parent_dir,
@@ -3243,7 +3243,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
}
}
- if (!fsp->is_directory && S_ISDIR(smb_fname->st.st_ex_mode)) {
+ if (!fsp->is_directory && S_ISDIR(fsp->fsp_name->st.st_ex_mode)) {
status = NT_STATUS_ACCESS_DENIED;
goto fail;
}
@@ -3251,7 +3251,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
/* Save the requested allocation size. */
if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
if (allocation_size
- && (allocation_size > smb_fname->st.st_ex_size)) {
+ && (allocation_size > fsp->fsp_name->st.st_ex_size)) {
fsp->initial_allocation_size = smb_roundup(
fsp->conn, allocation_size);
if (fsp->is_directory) {
@@ -3266,7 +3266,7 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
}
} else {
fsp->initial_allocation_size = smb_roundup(
- fsp->conn, (uint64_t)smb_fname->st.st_ex_size);
+ fsp->conn, (uint64_t)fsp->fsp_name->st.st_ex_size);
}
}
@@ -3276,18 +3276,8 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
if (pinfo != NULL) {
*pinfo = info;
}
- if ((fsp->fh != NULL) && (fsp->fh->fd != -1)) {
- 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);
- }
- }
+ smb_fname->st = fsp->fsp_name->st;
return NT_STATUS_OK;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index d39edc56db..caa80f9ade 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -4980,7 +4980,6 @@ void reply_printopen(struct smb_request *req)
{
connection_struct *conn = req->conn;
files_struct *fsp;
- SMB_STRUCT_STAT sbuf;
NTSTATUS status;
START_PROFILE(SMBsplopen);
@@ -5005,7 +5004,7 @@ void reply_printopen(struct smb_request *req)
}
/* Open for exclusive use, write only. */
- status = print_fsp_open(req, conn, NULL, req->vuid, fsp, &sbuf);
+ status = print_fsp_open(req, conn, NULL, req->vuid, fsp);
if (!NT_STATUS_IS_OK(status)) {
file_free(req, fsp);
diff --git a/source3/smbd/smb2_create.c b/source3/smbd/smb2_create.c
index e0815049a4..3cf8b185b0 100644
--- a/source3/smbd/smb2_create.c
+++ b/source3/smbd/smb2_create.c
@@ -347,7 +347,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
struct smb_request *smbreq;
files_struct *result;
int info;
- SMB_STRUCT_STAT sbuf;
+ struct timespec write_time_ts;
struct smb2_create_blobs out_context_blobs;
ZERO_STRUCT(out_context_blobs);
@@ -386,7 +386,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
info = FILE_WAS_OPENED;
- ZERO_STRUCT(sbuf);
} else if (CAN_PRINT(smbreq->conn)) {
status = file_new(smbreq, smbreq->conn, &result);
if(!NT_STATUS_IS_OK(status)) {
@@ -398,8 +397,7 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
smbreq->conn,
in_name,
smbreq->vuid,
- result,
- &sbuf);
+ result);
if (!NT_STATUS_IS_OK(status)) {
file_free(smbreq, result);
tevent_req_nterror(req, status);
@@ -669,8 +667,6 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
return tevent_req_post(req, ev);
}
}
-
- sbuf = result->fsp_name->st;
}
smb2req->compat_chain_fsp = smbreq->chain_fsp;
@@ -682,14 +678,30 @@ static struct tevent_req *smbd_smb2_create_send(TALLOC_CTX *mem_ctx,
} else {
state->out_create_action = info;
}
- unix_timespec_to_nt_time(&state->out_creation_time, sbuf.st_ex_btime);
- unix_timespec_to_nt_time(&state->out_last_access_time, sbuf.st_ex_atime);
- unix_timespec_to_nt_time(&state->out_last_write_time,sbuf.st_ex_mtime);
- unix_timespec_to_nt_time(&state->out_change_time, sbuf.st_ex_ctime);
- state->out_allocation_size = sbuf.st_ex_blksize * sbuf.st_ex_blocks;
- state->out_end_of_file = sbuf.st_ex_size;
- state->out_file_attributes = dos_mode(result->conn,
- result->fsp_name);
+ state->out_file_attributes = dos_mode(result->conn,
+ result->fsp_name);
+ /* Deal with other possible opens having a modified
+ write time. JRA. */
+ ZERO_STRUCT(write_time_ts);
+ get_file_infos(result->file_id, NULL, &write_time_ts);
+ if (!null_timespec(write_time_ts)) {
+ update_stat_ex_mtime(&result->fsp_name->st, write_time_ts);
+ }
+
+ unix_timespec_to_nt_time(&state->out_creation_time,
+ get_create_timespec(smbreq->conn, result,
+ result->fsp_name));
+ unix_timespec_to_nt_time(&state->out_last_access_time,
+ result->fsp_name->st.st_ex_atime);
+ unix_timespec_to_nt_time(&state->out_last_write_time,
+ result->fsp_name->st.st_ex_mtime);
+ unix_timespec_to_nt_time(&state->out_change_time,
+ get_change_timespec(smbreq->conn, result,
+ result->fsp_name));
+ state->out_allocation_size =
+ result->fsp_name->st.st_ex_blksize *
+ result->fsp_name->st.st_ex_blocks;
+ state->out_end_of_file = result->fsp_name->st.st_ex_size;
if (state->out_file_attributes == 0) {
state->out_file_attributes = FILE_ATTRIBUTE_NORMAL;
}
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 74dd173f4f..dacf5f34e0 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5720,7 +5720,7 @@ static NTSTATUS smb_set_file_disposition_info(connection_struct *conn,
const char *pdata,
int total_data,
files_struct *fsp,
- const struct smb_filename *smb_fname)
+ struct smb_filename *smb_fname)
{
NTSTATUS status = NT_STATUS_OK;
bool delete_on_close;