summaryrefslogtreecommitdiff
path: root/source3/lib/system.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2009-07-08 17:51:35 -0700
committerJeremy Allison <jra@samba.org>2009-07-08 17:51:35 -0700
commitc9c3d4312d7281904fc4a1cc9abd4831cdf4bfb9 (patch)
tree78a1df33a6276aea076f57424d18729604970253 /source3/lib/system.c
parent58daaa3d1e7075b23c8709889be9b461c6c6c174 (diff)
downloadsamba-c9c3d4312d7281904fc4a1cc9abd4831cdf4bfb9.tar.gz
samba-c9c3d4312d7281904fc4a1cc9abd4831cdf4bfb9.tar.bz2
samba-c9c3d4312d7281904fc4a1cc9abd4831cdf4bfb9.zip
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
Diffstat (limited to 'source3/lib/system.c')
-rw-r--r--source3/lib/system.c72
1 files changed, 58 insertions, 14 deletions
diff --git a/source3/lib/system.c b/source3/lib/system.c
index 47bb5259cc..b808a36d17 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@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;