Remove "store create time" code, cause create time to be stored
authorJeremy Allison <jra@samba.org>
Tue, 17 Nov 2009 22:55:02 +0000 (14:55 -0800)
committerJeremy Allison <jra@samba.org>
Tue, 17 Nov 2009 22:55:02 +0000 (14:55 -0800)
in the "user.DOSATTRIB" EA. From the docs:
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.
Passes make test but will need more testing.
Jeremy.

15 files changed:
docs-xml/smbdotconf/filename/storecreatetime.xml [deleted file]
docs-xml/smbdotconf/filename/storedosattributes.xml
source3/include/proto.h
source3/lib/system.c
source3/lib/time.c
source3/modules/onefs_open.c
source3/modules/vfs_default.c
source3/param/loadparm.c
source3/printing/printfsp.c
source3/smbd/dosmode.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/reply.c
source3/smbd/smb2_create.c
source3/smbd/trans2.c

diff --git a/docs-xml/smbdotconf/filename/storecreatetime.xml b/docs-xml/smbdotconf/filename/storecreatetime.xml
deleted file mode 100644 (file)
index 5957a5d..0000000
+++ /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>
index 6fcab82f9c72ac507f56f465440fb498b355b471..621b4ace742f1444c631a49ecb2e30b00b82623b 100644 (file)
        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>
index 4e347d6ddb6af357d190e6c7420fd5e296b471ea..6f971c3a07efe841ff35548efa7986c50eed8490 100644 (file)
@@ -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);
 
index 433169174661f8d2508ee39c5f3ffe7ccbf4397f..8abcb3dc666d0c6cceb89741e6c33842940c9c4b 100644 (file)
@@ -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)
 {
index f6ff6d3407480020389dd1911c5e7157e51e63ec..1d2fae3d171eed846a1905869461cb3ab36d3844 100644 (file)
@@ -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
 
index d90f165cd7627ccc5805936f9e46d8934059e9aa..fd12fff58ca484d6adf1c66a0cf074827bf2276e 100644 (file)
@@ -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,
index 17237ac83fc516b7f7baca065a42277abaa63536..8fbea0c4f333623430dad759afc2e8d1b4455e21 100644 (file)
@@ -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);
        }
index c62deb5eda5948e59ef214293423968114ea2310..c024603cb96ccc504fa11bd8ee672a98251a9ba9 100644 (file)
@@ -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 */
@@ -3082,15 +3080,6 @@ static struct parm_struct parm_table[] = {
                .enum_list      = NULL,
                .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,
@@ -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)
index 9185fc84b1ba43c62e0423a39d8c436da736dd80..b9fe49226eaba5774c7f9b716a5069448bc2d28f 100644 (file)
@@ -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;
 }
index e10f23918d1e781f7fe729423c7077caee408407..0f319736758d8662a8d9d16cd9427a5a4a68ad71 100644 (file)
@@ -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;
 }
 
 /******************************************************************
index 66102fa96ccdbf90393d260dc4d6de988d5a28a1..bacb9cb0b2fdaa620ea3fa9f7cb2bd8bffe1f02f 100644 (file)
@@ -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);
index 85b7d9106ddd37ad8c067aa6d0d1aa9ec230b49b..1f48daf9048cd2a257657822735f1358dc27f1ad 100644 (file)
@@ -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;
 
index d39edc56db479e88752d70d22218476dad91a4c9..caa80f9ade727b18206378ef3158a8ef9609f5c4 100644 (file)
@@ -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);
index e0815049a429d18ff39c56653ae1ca0fb94f5f0a..3cf8b185b08caba28deb622d369ef32fdd091a48 100644 (file)
@@ -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;
        }
index 74dd173f4f9c2b9d3094d4a406df42aa0c02ca24..dacf5f34e0e16aedd684952c7e9798acbdd04391 100644 (file)
@@ -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;