[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha8-277-gc9c3d43

Jeremy Allison jra at samba.org
Thu Jul 9 01:00:18 GMT 2009


The branch, master has been updated
       via  c9c3d4312d7281904fc4a1cc9abd4831cdf4bfb9 (commit)
      from  58daaa3d1e7075b23c8709889be9b461c6c6c174 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c9c3d4312d7281904fc4a1cc9abd4831cdf4bfb9
Author: Jeremy Allison <jra at samba.org>
Date:   Wed Jul 8 17:51:35 2009 -0700

    The migration to struct stat_ex broke the calculation of
    create time from the existing timestamps (for systems
    that need to do this). Once the write time is changed
    via a sticky write, the create time might need to be
    recalculated. To do this I needed to add a bool into
    struct stat_ex to remember if the st_ex_btime field
    was calculated, or read from the OS. Also fixed the
    returning of modified write timestamps in the return
    from NTCreateX, SMBattr and SMBattrE (which weren't
    taking into account the modified timestamp stored
    in the open file table). Attempting to fix an issue
    with Excel 2003 and offline files. Volker and Metze,
    please review.
    Jeremy

-----------------------------------------------------------------------

Summary of changes:
 source3/include/includes.h |    2 +
 source3/include/proto.h    |    1 +
 source3/lib/system.c       |   72 +++++++++++++++++++++++++++++++++++--------
 source3/smbd/nttrans.c     |   18 +++++++++++
 source3/smbd/reply.c       |   28 +++++++++++++++++
 source3/smbd/trans2.c      |   21 +++++++------
 6 files changed, 118 insertions(+), 24 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/includes.h b/source3/include/includes.h
index 2b36d18..8fb240f 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -460,6 +460,8 @@ struct stat_ex {
 	struct timespec st_ex_mtime;
 	struct timespec st_ex_ctime;
 	struct timespec st_ex_btime; /* birthtime */
+	/* Is birthtime real, or was it calculated ? */
+	bool		st_ex_calculated_birthtime;
 	blksize_t	st_ex_blksize;
 	blkcnt_t	st_ex_blocks;
 
diff --git a/source3/include/proto.h b/source3/include/proto.h
index 0315f30..25a104d 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -911,6 +911,7 @@ ssize_t sys_recv(int fd, void *buf, size_t count, int flags);
 ssize_t sys_recvfrom(int s, void *buf, size_t len, int flags, struct sockaddr *from, socklen_t *fromlen);
 int sys_fcntl_ptr(int fd, int cmd, void *arg);
 int sys_fcntl_long(int fd, int cmd, long arg);
+void update_stat_ex_writetime(struct stat_ex *dst, struct timespec write_ts);
 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);
diff --git a/source3/lib/system.c b/source3/lib/system.c
index 47bb525..b808a36 100644
--- a/source3/lib/system.c
+++ b/source3/lib/system.c
@@ -404,7 +404,7 @@ static struct timespec get_ctimespec(const struct stat *pst)
  structure.
 ****************************************************************************/
 
-static struct timespec calc_create_time(const struct stat *st)
+static struct timespec calc_create_time_stat(const struct stat *st)
 {
 	struct timespec ret, ret1;
 	struct timespec c_time = get_ctimespec(st);
@@ -426,41 +426,85 @@ static struct timespec calc_create_time(const struct stat *st)
 }
 
 /****************************************************************************
+ Return the best approximation to a 'create time' under UNIX from a stat_ex
+ structure.
+****************************************************************************/
+
+static struct timespec calc_create_time_stat_ex(const struct stat_ex *st)
+{
+	struct timespec ret, ret1;
+	struct timespec c_time = st->st_ex_ctime;
+	struct timespec m_time = st->st_ex_mtime;
+	struct timespec a_time = st->st_ex_atime;
+
+	ret = timespec_compare(&c_time, &m_time) < 0 ? c_time : m_time;
+	ret1 = timespec_compare(&ret, &a_time) < 0 ? ret : a_time;
+
+	if(!null_timespec(ret1)) {
+		return ret1;
+	}
+
+	/*
+	 * One of ctime, mtime or atime was zero (probably atime).
+	 * Just return MIN(ctime, mtime).
+	 */
+	return ret;
+}
+
+/****************************************************************************
  Return the 'create time' from a stat struct if it exists (birthtime) or else
  use the best approximation.
 ****************************************************************************/
 
-static struct timespec get_create_timespec(const struct stat *pst)
+static void get_create_timespec(const struct stat *pst, struct stat_ex *dst)
 {
 	struct timespec ret;
 
 	if (S_ISDIR(pst->st_mode) && lp_fake_dir_create_times()) {
-		ret.tv_sec = 315493200L;          /* 1/1/1980 */
-		ret.tv_nsec = 0;
-		return ret;
+		dst->st_ex_btime.tv_sec = 315493200L;          /* 1/1/1980 */
+		dst->st_ex_btime.tv_nsec = 0;
 	}
 
+	dst->st_ex_calculated_birthtime = false;
+
 #if defined(HAVE_STRUCT_STAT_ST_BIRTHTIMESPEC_TV_NSEC)
-	ret = pst->st_birthtimespec;
+	dst->st_ex_btime = pst->st_birthtimespec;
 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIMENSEC)
-	ret.tv_sec = pst->st_birthtime;
-	ret.tv_nsec = pst->st_birthtimenspec;
+	dst->st_ex_btime.tv_sec = pst->st_birthtime;
+	dst->st_ex_btime.tv_nsec = pst->st_birthtimenspec;
 #elif defined(HAVE_STRUCT_STAT_ST_BIRTHTIME)
-	ret.tv_sec = pst->st_birthtime;
-	ret.tv_nsec = 0;
+	dst->st_ex_btime.tv_sec = pst->st_birthtime;
+	dst->st_ex_btime.tv_nsec = 0;
 #else
-	ret = calc_create_time(pst);
+	dst->st_ex_btime = calc_create_time_stat(pst);
+	dst->st_ex_calculated_birthtime = true;
 #endif
 
 	/* Deal with systems that don't initialize birthtime correctly.
 	 * Pointed out by SATOH Fumiyasu <fumiyas at osstech.jp>.
 	 */
 	if (null_timespec(ret)) {
-		ret = calc_create_time(pst);
+		dst->st_ex_btime = calc_create_time_stat(pst);
+		dst->st_ex_calculated_birthtime = true;
 	}
-	return ret;
 }
 
+/****************************************************************************
+ If we update a timestamp in a stat_ex struct we may have to recalculate
+ the birthtime. For now only implement this for write time, but we may
+ also need to do it for mtime and ctime. JRA.
+****************************************************************************/
+
+void update_stat_ex_writetime(struct stat_ex *dst,
+				struct timespec write_ts)
+{
+	dst->st_ex_mtime = write_ts;
+
+	/* We may have to recalculate btime. */
+	if (dst->st_ex_calculated_birthtime) {
+		dst->st_ex_btime = calc_create_time_stat_ex(dst);
+	}
+}
 
 static void init_stat_ex_from_stat (struct stat_ex *dst,
 				    const struct stat *src)
@@ -476,7 +520,7 @@ static void init_stat_ex_from_stat (struct stat_ex *dst,
 	dst->st_ex_atime = get_atimespec(src);
 	dst->st_ex_mtime = get_mtimespec(src);
 	dst->st_ex_ctime = get_ctimespec(src);
-	dst->st_ex_btime = get_create_timespec(src);
+	get_create_timespec(src, dst);
 	dst->st_ex_blksize = src->st_blksize;
 	dst->st_ex_blocks = src->st_blocks;
 
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index b970ffc..4f75b9f 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -473,6 +473,7 @@ void reply_ntcreate_and_X(struct smb_request *req)
 	struct timespec c_timespec;
 	struct timespec a_timespec;
 	struct timespec m_timespec;
+	struct timespec write_time_ts;
 	NTSTATUS status;
 	int oplock_request;
 	uint8_t oplock_granted = NO_OPLOCK_RETURN;
@@ -651,6 +652,14 @@ void reply_ntcreate_and_X(struct smb_request *req)
 	}
 	p += 4;
 
+	/* Deal with other possible opens having a modified
+	   write time. JRA. */
+	ZERO_STRUCT(write_time_ts);
+	get_file_infos(fsp->file_id, NULL, &write_time_ts);
+	if (!null_timespec(write_time_ts)) {
+		update_stat_ex_writetime(&smb_fname->st, write_time_ts);
+	}
+
 	/* Create time. */
 	c_timespec = smb_fname->st.st_ex_btime;
 	a_timespec = smb_fname->st.st_ex_atime;
@@ -908,6 +917,7 @@ static void call_nt_transact_create(connection_struct *conn,
 	struct timespec c_timespec;
 	struct timespec a_timespec;
 	struct timespec m_timespec;
+	struct timespec write_time_ts;
 	struct ea_list *ea_list = NULL;
 	NTSTATUS status;
 	size_t param_len;
@@ -1133,6 +1143,14 @@ static void call_nt_transact_create(connection_struct *conn,
 	}
 	p += 8;
 
+	/* Deal with other possible opens having a modified
+	   write time. JRA. */
+	ZERO_STRUCT(write_time_ts);
+	get_file_infos(fsp->file_id, NULL, &write_time_ts);
+	if (!null_timespec(write_time_ts)) {
+		update_stat_ex_writetime(&smb_fname->st, write_time_ts);
+	}
+
 	/* Create time. */
 	c_timespec = smb_fname->st.st_ex_btime;
 	a_timespec = smb_fname->st.st_ex_atime;
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index c07ac33..e02482e 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -1065,6 +1065,7 @@ void reply_getatr(struct smb_request *req)
 	const char *p;
 	NTSTATUS status;
 	TALLOC_CTX *ctx = talloc_tos();
+	bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
 
 	START_PROFILE(SMBgetatr);
 
@@ -1111,6 +1112,19 @@ void reply_getatr(struct smb_request *req)
 
 		mode = dos_mode(conn, fname, &smb_fname->st);
 		size = smb_fname->st.st_ex_size;
+
+		if (ask_sharemode) {
+			struct timespec write_time_ts;
+			struct file_id fileid;
+
+			ZERO_STRUCT(write_time_ts);
+			fileid = vfs_file_id_from_sbuf(conn, &smb_fname->st);
+			get_file_infos(fileid, NULL, &write_time_ts);
+			if (!null_timespec(write_time_ts)) {
+				update_stat_ex_writetime(&smb_fname->st, write_time_ts);
+			}
+		}
+
 		mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
 		if (mode & aDIR) {
 			size = 0;
@@ -1707,6 +1721,7 @@ void reply_open(struct smb_request *req)
 	uint32 create_disposition;
 	uint32 create_options = 0;
 	NTSTATUS status;
+	bool ask_sharemode = lp_parm_bool(SNUM(conn), "smbd", "search ask sharemode", true);
 	TALLOC_CTX *ctx = talloc_tos();
 
 	START_PROFILE(SMBopen);
@@ -1779,6 +1794,19 @@ void reply_open(struct smb_request *req)
 
 	size = smb_fname->st.st_ex_size;
 	fattr = dos_mode(conn,fsp->fsp_name,&smb_fname->st);
+
+	/* Deal with other possible opens having a modified
+	   write time. JRA. */
+	if (ask_sharemode) {
+		struct timespec write_time_ts;
+
+		ZERO_STRUCT(write_time_ts);
+		get_file_infos(fsp->file_id, NULL, &write_time_ts);
+		if (!null_timespec(write_time_ts)) {
+			update_stat_ex_writetime(&smb_fname->st, write_time_ts);
+		}
+	}
+
 	mtime = convert_timespec_to_time_t(smb_fname->st.st_ex_mtime);
 
 	if (fattr & aDIR) {
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index e5f8039..cb4f10f 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -1455,21 +1455,22 @@ static bool get_lanman2_dir_entry(TALLOC_CTX *ctx,
 			}
 			allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,NULL,&sbuf);
 
-			mdate_ts = sbuf.st_ex_mtime;
-			adate_ts = sbuf.st_ex_atime;
-			create_date_ts = sbuf.st_ex_btime;
-
 			if (ask_sharemode) {
 				struct timespec write_time_ts;
 				struct file_id fileid;
 
+				ZERO_STRUCT(write_time_ts);
 				fileid = vfs_file_id_from_sbuf(conn, &sbuf);
 				get_file_infos(fileid, NULL, &write_time_ts);
 				if (!null_timespec(write_time_ts)) {
-					mdate_ts = write_time_ts;
+					update_stat_ex_writetime(&sbuf, write_time_ts);
 				}
 			}
 
+			mdate_ts = sbuf.st_ex_mtime;
+			adate_ts = sbuf.st_ex_atime;
+			create_date_ts = sbuf.st_ex_btime;
+
 			if (lp_dos_filetime_resolution(SNUM(conn))) {
 				dos_filetime_timespec(&create_date_ts);
 				dos_filetime_timespec(&mdate_ts);
@@ -4244,10 +4245,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 	dstart = pdata;
 	dend = dstart + data_size - 1;
 
-	create_time_ts = sbuf.st_ex_btime;
-	mtime_ts = sbuf.st_ex_mtime;
-	atime_ts = sbuf.st_ex_atime;
-
 	allocation_size = SMB_VFS_GET_ALLOC_SIZE(conn,fsp,&sbuf);
 
 	if (!fsp) {
@@ -4261,9 +4258,13 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd
 	}
 
 	if (!null_timespec(write_time_ts) && !INFO_LEVEL_IS_UNIX(info_level)) {
-		mtime_ts = write_time_ts;
+		update_stat_ex_writetime(&sbuf, write_time_ts);
 	}
 
+	create_time_ts = sbuf.st_ex_btime;
+	mtime_ts = sbuf.st_ex_mtime;
+	atime_ts = sbuf.st_ex_atime;
+
 	if (lp_dos_filetime_resolution(SNUM(conn))) {
 		dos_filetime_timespec(&create_time_ts);
 		dos_filetime_timespec(&mtime_ts);


-- 
Samba Shared Repository


More information about the samba-cvs mailing list