summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/configure.in39
-rw-r--r--source3/lib/time.c102
-rw-r--r--source3/smbd/notify_hash.c23
3 files changed, 145 insertions, 19 deletions
diff --git a/source3/configure.in b/source3/configure.in
index 6dedbd3441..9774479acb 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -1395,6 +1395,45 @@ if test x"$samba_stat_hires" = x"yes" ; then
[whether struct stat has sub-second timestamps])
fi
+AC_CACHE_CHECK([whether struct stat has sub-second timestamps without struct timespec], samba_stat_hires_notimespec,
+ [
+ AC_TRY_COMPILE(
+ [
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+ ],
+ [
+ struct timespec t;
+ struct stat s = {0};
+ t.tv_sec = s.st_mtime;
+ t.tv_nsec = s.st_mtimensec;
+ t.tv_sec = s.st_ctime;
+ t.tv_nsec = s.st_ctimensec;
+ t.tv_sec = s.st_atime;
+ t.tv_nsec = s.st_atimensec;
+ ],
+ samba_stat_hires=yes, samba_stat_hires=no)
+ ])
+
+if test x"$samba_stat_hires_notimespec" = x"yes" ; then
+ AC_DEFINE(HAVE_STAT_ST_MTIMENSEC, 1, [whether struct stat contains st_mtimensec])
+ AC_DEFINE(HAVE_STAT_ST_ATIMENSEC, 1, [whether struct stat contains st_atimensec])
+ AC_DEFINE(HAVE_STAT_ST_CTIMENSEC, 1, [whether struct stat contains st_ctimensec])
+ AC_DEFINE(HAVE_STAT_HIRES_TIMESTAMPS, 1,
+ [whether struct stat has sub-second timestamps without struct timespec])
+fi
+
#####################################
# we might need the resolv library on some systems
AC_CHECK_LIB(resolv, dn_expand)
diff --git a/source3/lib/time.c b/source3/lib/time.c
index f87e53fef5..b6a22a3098 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -955,3 +955,105 @@ time_t generalized_to_unix_time(const char *str)
return timegm(&tm);
}
+
+/****************************************************************************
+ Return all the possible time fields from a stat struct as a timespec.
+****************************************************************************/
+
+struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ struct timespec ret;
+
+ /* Old system - no ns timestamp. */
+ ret.tv_sec = pst->st_atime;
+ ret.tv_nsec = 0;
+ return ret;
+#else
+#if defined(HAVE_STAT_ST_ATIM)
+ return pst->st_atim;
+#elif defined(HAVE_STAT_ST_ATIMENSEC)
+ struct timespec ret;
+ ret.tv_sec = pst->st_atime;
+ ret.tv_nsec = pst->st_atimensec;
+ return ret;
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
+}
+
+struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ struct timespec ret;
+
+ /* Old system - no ns timestamp. */
+ ret.tv_sec = pst->st_mtime;
+ ret.tv_nsec = 0;
+ return ret;
+#else
+#if defined(HAVE_STAT_ST_MTIM)
+ return pst->st_mtim;
+#elif defined(HAVE_STAT_ST_MTIMENSEC)
+ struct timespec ret;
+ ret.tv_sec = pst->st_mtime;
+ ret.tv_nsec = pst->st_mtimensec;
+ return ret;
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
+}
+
+struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ struct timespec ret;
+
+ /* Old system - no ns timestamp. */
+ ret.tv_sec = pst->ctime;
+ ret.tv_nsec = 0;
+ return ret;
+#else
+#if defined(HAVE_STAT_ST_CTIM)
+ return pst->st_ctim;
+#elif defined(HAVE_STAT_ST_CTIMENSEC)
+ struct timespec ret;
+ ret.tv_sec = pst->st_ctime;
+ ret.tv_nsec = pst->st_ctimensec;
+ return ret;
+#else
+#error CONFIGURE_ERROR_IN_DETECTING_TIMESPEC_IN_STAT
+#endif
+#endif
+}
+
+#if 0
+/****************************************************************************
+ Return the best approximation to a 'create time' under UNIX from a stat
+ structure.
+****************************************************************************/
+
+struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+{
+ time_t ret, ret1;
+
+ if(S_ISDIR(st->st_mode) && fake_dirs) {
+ return (time_t)315493200L; /* 1/1/1980 */
+ }
+
+ ret = MIN(st->st_ctime, st->st_mtime);
+ ret1 = MIN(ret, st->st_atime);
+
+ if(ret1 != (time_t)0) {
+ return ret1;
+ }
+
+ /*
+ * One of ctime, mtime or atime was zero (probably atime).
+ * Just return MIN(ctime, mtime).
+ */
+ return ret;
+}
+#endif
diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c
index ee7d4314ee..859a92a61e 100644
--- a/source3/smbd/notify_hash.c
+++ b/source3/smbd/notify_hash.c
@@ -23,13 +23,8 @@
struct change_data {
time_t last_check_time; /* time we last checked this entry */
-#ifdef HAVE_STAT_HIRES_TIMESTAMPS
- struct timespec modify_time;
- struct timespec status_time;
-#else
- time_t modify_time; /* Info from the directory we're monitoring. */
- time_t status_time; /* Info from the directory we're monitoring. */
-#endif
+ struct timespec modify_time; /* Info from the directory we're monitoring. */
+ struct timespec status_time; /* Info from the directory we're monitoring. */
time_t total_time; /* Total time of all directory entries - don't care if it wraps. */
unsigned int num_entries; /* Zero or the number of files in the directory. */
unsigned int mode_sum;
@@ -37,13 +32,8 @@ struct change_data {
};
-#ifdef HAVE_STAT_HIRES_TIMESTAMPS
/* Compare struct timespec. */
#define TIMESTAMP_NEQ(x, y) (((x).tv_sec != (y).tv_sec) || ((x).tv_nsec != (y).tv_nsec))
-#else
-/* Compare time_t . */
-#define TIMESTAMP_NEQ(x, y) ((x) != (y))
-#endif
/****************************************************************************
Create the hash we will use to determine if the contents changed.
@@ -66,13 +56,8 @@ static BOOL notify_hash(connection_struct *conn, char *path, uint32 flags,
if(SMB_VFS_STAT(conn,path, &st) == -1)
return False;
-#ifdef HAVE_STAT_HIRES_TIMESTAMPS
- data->modify_time = st.st_mtim;
- data->status_time = st.st_ctim;
-#else
- data->modify_time = st.st_mtime;
- data->status_time = st.st_ctime;
-#endif
+ data->modify_time = get_mtimespec(&st);
+ data->status_time = get_ctimespec(&st);
if (old_data) {
/*