diff options
-rw-r--r-- | source3/configure.in | 39 | ||||
-rw-r--r-- | source3/lib/time.c | 102 | ||||
-rw-r--r-- | source3/smbd/notify_hash.c | 23 |
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) { /* |