[SCM] Samba Shared Repository - branch master updated - release-4-0-0alpha8-1114-g1af0aa9

Jeremy Allison jra at samba.org
Fri Aug 21 22:46:41 MDT 2009


The branch, master has been updated
       via  1af0aa92b3f3467715f6ffbfedf66df1acc0a83c (commit)
      from  47c7063dc62dc06d0cdd50e1946c088f8bf1ee1d (commit)

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


- Log -----------------------------------------------------------------
commit 1af0aa92b3f3467715f6ffbfedf66df1acc0a83c
Author: Jeremy Allison <jra at samba.org>
Date:   Fri Aug 21 21:44:21 2009 -0700

    Fix bug 6529 - Offline files conflict with Vista and Office 2003
    On filesystems that can't store less than one second timestamps,
    round the incoming timestamp set requests so the client can't discover
    that a time set request has been truncated by the filesystem.
    Needs backporting to 3.4, 3.3, 3.2 and (even) 3.0.
    Jeremy

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

Summary of changes:
 source3/include/proto.h |    1 +
 source3/include/smb.h   |    3 +++
 source3/lib/time.c      |   11 +++++++++++
 source3/smbd/open.c     |    6 +++++-
 source3/smbd/service.c  |   13 +++++++++++++
 source3/smbd/trans2.c   |    9 +++++++++
 6 files changed, 42 insertions(+), 1 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source3/include/proto.h b/source3/include/proto.h
index 963e6df..1b09732 100644
--- a/source3/include/proto.h
+++ b/source3/include/proto.h
@@ -1044,6 +1044,7 @@ struct timespec timespec_current(void);
 struct timespec timespec_min(const struct timespec *ts1,
 			   const struct timespec *ts2);
 int timespec_compare(const struct timespec *ts1, const struct timespec *ts2);
+void round_timespec(struct timespec *ts);
 struct timespec interpret_long_date(const char *p);
 void cli_put_dos_date(struct cli_state *cli, char *buf, int offset, time_t unixdate);
 void cli_put_dos_date2(struct cli_state *cli, char *buf, int offset, time_t unixdate);
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 9d1e22b..1347ab2 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -557,6 +557,9 @@ typedef struct connection_struct {
 	bool ipc;
 	bool read_only; /* Attributes for the current user of the share. */
 	bool admin_user; /* Attributes for the current user of the share. */
+	bool hires_timestamps_avail; /* Does this filesystem honor
+					sub second timestamps on files
+					and directories ? */
 	char *connectpath;
 	char *origpath;
 
diff --git a/source3/lib/time.c b/source3/lib/time.c
index a2e615a..06605cd 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -468,6 +468,17 @@ int timespec_compare(const struct timespec *ts1, const struct timespec *ts2)
 }
 
 /****************************************************************************
+ Round up a timespec if nsec > 500000000, round down if lower,
+ then zero nsec.
+****************************************************************************/
+
+void round_timespec(struct timespec *ts)
+{
+	ts->tv_sec += ts->tv_nsec >= 500000000 ? 1 : 0;
+	ts->tv_nsec = 0;
+}
+
+/****************************************************************************
  Interprets an nt time into a unix struct timespec.
  Differs from nt_time_to_unix in that an 8 byte value of 0xffffffffffffffff
  will be returned as (time_t)-1, whereas nt_time_to_unix returns 0 in this case.
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 0456355..9b4eedf 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -3284,8 +3284,12 @@ static NTSTATUS create_file_unixpath(connection_struct *conn,
 	/* Try and make a create timestamp, if required. */
 	if ((info == FILE_WAS_CREATED) || (info == FILE_WAS_OVERWRITTEN)) {
 		if (lp_store_create_time(SNUM(conn))) {
+			struct timespec ts = smb_fname->st.st_ex_btime;
+			if (!conn->hires_timestamps_avail) {
+				round_timespec(&ts);
+			}
 			set_create_timespec_ea(conn, fsp,
-				smb_fname, smb_fname->st.st_ex_btime);
+				smb_fname, ts);
 		}
 	}
 
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index fc56105..6254d75 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -1015,6 +1015,19 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
 		goto err_root_exit;
 	}
 
+	if (smb_fname_cpath->st.st_ex_mtime.tv_nsec ||
+			smb_fname_cpath->st.st_ex_atime.tv_nsec ||
+			smb_fname_cpath->st.st_ex_ctime.tv_nsec) {
+		/* If any of the normal UNIX directory timestamps
+		 * have a non-zero tv_nsec component assume
+		 * we can fully store hires timestamps. We need
+		 * to make a runtime/share level distinction
+		 * as on Linux ext3 doesn't have hires timestamps, but
+		 * ext4 does, so a compile time test won't work. JRA.
+		 */
+		conn->hires_timestamps_avail = true;
+	}
+
 	string_set(&conn->origpath,conn->connectpath);
 
 #if SOFTLINK_OPTIMISATION
diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c
index 56651b4..2900e76 100644
--- a/source3/smbd/trans2.c
+++ b/source3/smbd/trans2.c
@@ -5402,6 +5402,15 @@ NTSTATUS smb_set_file_time(connection_struct *conn,
 		action &= ~FILE_NOTIFY_CHANGE_LAST_WRITE;
 	}
 
+	if (!conn->hires_timestamps_avail) {
+		/* We can't store sub second timestamps
+		 * on this share. Round to seconds. */
+		round_timespec(&ft->create_time);
+		round_timespec(&ft->ctime);
+		round_timespec(&ft->atime);
+		round_timespec(&ft->mtime);
+	}
+
 	DEBUG(5,("smb_set_filetime: actime: %s\n ",
 		time_to_asc(convert_timespec_to_time_t(ft->atime))));
 	DEBUG(5,("smb_set_filetime: modtime: %s\n ",


-- 
Samba Shared Repository


More information about the samba-cvs mailing list