diff options
-rw-r--r-- | docs-xml/smbdotconf/filename/storecreatetime.xml | 15 | ||||
-rw-r--r-- | docs-xml/smbdotconf/filename/storedosattributes.xml | 7 | ||||
-rw-r--r-- | source3/include/proto.h | 8 | ||||
-rw-r--r-- | source3/lib/system.c | 7 | ||||
-rw-r--r-- | source3/lib/time.c | 27 | ||||
-rw-r--r-- | source3/modules/onefs_open.c | 2 | ||||
-rw-r--r-- | source3/modules/vfs_default.c | 4 | ||||
-rw-r--r-- | source3/param/loadparm.c | 12 | ||||
-rw-r--r-- | source3/printing/printfsp.c | 9 | ||||
-rw-r--r-- | source3/smbd/dosmode.c | 244 | ||||
-rw-r--r-- | source3/smbd/nttrans.c | 18 | ||||
-rw-r--r-- | source3/smbd/open.c | 20 | ||||
-rw-r--r-- | source3/smbd/reply.c | 3 | ||||
-rw-r--r-- | source3/smbd/smb2_create.c | 40 | ||||
-rw-r--r-- | source3/smbd/trans2.c | 2 |
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; |