summaryrefslogtreecommitdiff
path: root/source3/lib/time.c
diff options
context:
space:
mode:
authorJeremy Allison <jra@samba.org>2006-08-24 16:44:00 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 11:38:48 -0500
commita64925ddff467a47f7adfac4b1b977ddc0c7f4ef (patch)
tree0c228a2046097065d34dc62a744747509689e09c /source3/lib/time.c
parent26f55cb40de4556774ac3a4ef0e46003d85477a4 (diff)
downloadsamba-a64925ddff467a47f7adfac4b1b977ddc0c7f4ef.tar.gz
samba-a64925ddff467a47f7adfac4b1b977ddc0c7f4ef.tar.bz2
samba-a64925ddff467a47f7adfac4b1b977ddc0c7f4ef.zip
r17800: Start using struct timespec internally for file times
on the wire. This allows us to go to nsec resolution for systems that support it. It should also now be easy to add a correct "create time" (birth time) for systems that support it (*BSD). I'll be watching the build farm closely after this one for breakage :-). Jeremy. (This used to be commit 425280a1d23f97ef0b0be77462386d619f47b21d)
Diffstat (limited to 'source3/lib/time.c')
-rw-r--r--source3/lib/time.c173
1 files changed, 147 insertions, 26 deletions
diff --git a/source3/lib/time.c b/source3/lib/time.c
index 0bfdfac856..fa4ef398f2 100644
--- a/source3/lib/time.c
+++ b/source3/lib/time.c
@@ -172,28 +172,52 @@ int TimeDiff(time_t t)
}
#endif
+time_t convert_timespec_to_time_t(struct timespec ts)
+{
+ /* 1 ns == 1,000,000,000 - one thousand millionths of a second.
+ increment if it's greater than 500 millionth of a second. */
+ if (ts.tv_nsec > 500000000) {
+ return ts.tv_sec + 1;
+ }
+ return ts.tv_sec;
+}
+
+struct timespec convert_time_t_to_timespec(time_t t)
+{
+ struct timespec ts;
+ ts.tv_sec = t;
+ ts.tv_nsec = 0;
+ return ts;
+}
+
#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
/****************************************************************************
Interpret an 8 byte "filetime" structure to a time_t
It's originally in "100ns units since jan 1st 1601"
- An 8 byte value of 0xffffffffffffffff will be returned as (time_t)0.
+ An 8 byte value of 0xffffffffffffffff will be returned as a timespec of
+
+ tv_sec = 0
+ tv_nsec = 0;
Returns GMT.
****************************************************************************/
-time_t nt_time_to_unix(NTTIME *nt)
+static struct timespec nt_time_to_unix_timespec(NTTIME *nt)
{
double d;
- time_t ret;
+ struct timespec ret;
/* The next two lines are a fix needed for the
broken SCO compiler. JRA. */
time_t l_time_min = TIME_T_MIN;
time_t l_time_max = TIME_T_MAX;
- if (nt->high == 0 || (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
- return(0);
+ if ((nt->high == 0 && nt->low == 0 )||
+ (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
+ ret.tv_sec = 0;
+ ret.tv_nsec = 0;
+ return ret;
}
d = ((double)nt->high)*4.0*(double)(1<<30);
@@ -204,15 +228,25 @@ time_t nt_time_to_unix(NTTIME *nt)
d -= TIME_FIXUP_CONSTANT;
if (d <= l_time_min) {
- return (l_time_min);
+ ret.tv_sec = l_time_min;
+ ret.tv_nsec = 0;
+ return ret;
}
if (d >= l_time_max) {
- return (l_time_max);
+ ret.tv_sec = l_time_max;
+ ret.tv_nsec = 0;
+ return ret;
}
- ret = (time_t)(d+0.5);
- return(ret);
+ ret.tv_sec = (time_t)d;
+ ret.tv_nsec = (long) ((d - (double)ret.tv_sec)*1.0e9);
+ return ret;
+}
+
+time_t nt_time_to_unix(NTTIME *nt)
+{
+ return convert_timespec_to_time_t(nt_time_to_unix_timespec(nt));
}
/****************************************************************************
@@ -235,7 +269,7 @@ time_t nt_time_to_unix_abs(const NTTIME *nt)
NTTIME neg_nt;
if (nt->high == 0) {
- return(0);
+ return (time_t)0;
}
if (nt->high==0x80000000 && nt->low==0) {
@@ -252,64 +286,79 @@ time_t nt_time_to_unix_abs(const NTTIME *nt)
d *= 1.0e-7;
if (!(l_time_min <= d && d <= l_time_max)) {
- return(0);
+ return (time_t)0;
}
ret = (time_t)(d+0.5);
-
- return(ret);
+ return ret;
}
/****************************************************************************
- Interprets an nt time into a unix time_t.
+ 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.
****************************************************************************/
-time_t interpret_long_date(char *p)
+struct timespec interpret_long_date(char *p)
{
NTTIME nt;
nt.low = IVAL(p,0);
nt.high = IVAL(p,4);
if (nt.low == 0xFFFFFFFF && nt.high == 0xFFFFFFFF) {
- return (time_t)-1;
+ struct timespec ret;
+ ret.tv_sec = (time_t)-1;
+ ret.tv_nsec = 0;
+ return ret;
}
- return nt_time_to_unix(&nt);
+ return nt_time_to_unix_timespec(&nt);
}
/****************************************************************************
- Put a 8 byte filetime from a time_t. Uses GMT.
+ Put a 8 byte filetime from a struct timespec. Uses GMT.
****************************************************************************/
-void unix_to_nt_time(NTTIME *nt, time_t t)
+void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
{
double d;
- if (t==0) {
+ if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
nt->low = 0;
nt->high = 0;
return;
}
- if (t == TIME_T_MAX) {
+ if (ts.tv_sec == TIME_T_MAX) {
nt->low = 0xffffffff;
nt->high = 0x7fffffff;
return;
}
- if (t == (time_t)-1) {
+ if (ts.tv_sec == (time_t)-1) {
nt->low = 0xffffffff;
nt->high = 0xffffffff;
return;
}
- d = (double)(t);
+ d = (double)(ts.tv_sec);
d += TIME_FIXUP_CONSTANT;
d *= 1.0e7;
+ d += ((double)ts.tv_nsec / 100.0);
nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
nt->low = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
}
/****************************************************************************
+ Put a 8 byte filetime from a time_t. Uses GMT.
+****************************************************************************/
+
+void unix_to_nt_time(NTTIME *nt, time_t t)
+{
+ struct timespec ts;
+ ts.tv_sec = t;
+ ts.tv_nsec = 0;
+ unix_timespec_to_nt_time(nt, ts);
+}
+
+/****************************************************************************
Convert a time_t to a NTTIME structure
This is an absolute version of the one above.
@@ -356,14 +405,22 @@ void unix_to_nt_time_abs(NTTIME *nt, time_t t)
pointed to by p.
****************************************************************************/
-void put_long_date(char *p, time_t t)
+void put_long_date_timespec(char *p, struct timespec ts)
{
NTTIME nt;
- unix_to_nt_time(&nt, t);
+ unix_timespec_to_nt_time(&nt, ts);
SIVAL(p, 0, nt.low);
SIVAL(p, 4, nt.high);
}
+void put_long_date(char *p, time_t t)
+{
+ struct timespec ts;
+ ts.tv_sec = t;
+ ts.tv_nsec = 0;
+ put_long_date_timespec(p, ts);
+}
+
/****************************************************************************
Check if it's a null mtime.
****************************************************************************/
@@ -717,6 +774,14 @@ time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
return ret;
}
+struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
+{
+ struct timespec ts;
+ ts.tv_sec = get_create_time(st, fake_dirs);
+ ts.tv_nsec = 0;
+ return ts;
+}
+
/****************************************************************************
Initialise an NTTIME to -1, which means "unknown" or "don't expire".
****************************************************************************/
@@ -955,7 +1020,7 @@ time_t generalized_to_unix_time(const char *str)
}
/****************************************************************************
- Return all the possible time fields from a stat struct as a timespec.
+ Get/Set all the possible time fields from a stat struct as a timespec.
****************************************************************************/
struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
@@ -981,6 +1046,23 @@ struct timespec get_atimespec(SMB_STRUCT_STAT *pst)
#endif
}
+void set_atimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ /* Old system - no ns timestamp. */
+ pst->st_atime = ts.tv_sec;
+#else
+#if defined(HAVE_STAT_ST_ATIM)
+ pst->st_atim = ts;
+#elif defined(HAVE_STAT_ST_ATIMENSEC)
+ pst->st_atime = ts.tv_sec;
+ pst->st_atimensec = ts.tv_nsec
+#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)
@@ -1004,6 +1086,23 @@ struct timespec get_mtimespec(SMB_STRUCT_STAT *pst)
#endif
}
+void set_mtimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ /* Old system - no ns timestamp. */
+ pst->st_mtime = ts.tv_sec;
+#else
+#if defined(HAVE_STAT_ST_MTIM)
+ pst->st_mtim = ts;
+#elif defined(HAVE_STAT_ST_MTIMENSEC)
+ pst->st_mtime = ts.tv_sec;
+ pst->st_mtimensec = ts.tv_nsec
+#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)
@@ -1027,6 +1126,23 @@ struct timespec get_ctimespec(SMB_STRUCT_STAT *pst)
#endif
}
+void set_ctimespec(SMB_STRUCT_STAT *pst, struct timespec ts)
+{
+#if !defined(HAVE_STAT_HIRES_TIMESTAMPS)
+ /* Old system - no ns timestamp. */
+ pst->st_ctime = ts.tv_sec;
+#else
+#if defined(HAVE_STAT_ST_CTIM)
+ pst->st_atim = ts;
+#elif defined(HAVE_STAT_ST_CTIMENSEC)
+ pst->st_ctime = ts.tv_sec;
+ pst->st_ctimensec = ts.tv_nsec
+#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
@@ -1056,6 +1172,11 @@ struct timespec get_create_timespec(SMB_STRUCT_STAT *st,BOOL fake_dirs)
}
#endif
+void dos_filetime_timespec(struct timespec *tsp)
+{
+ tsp->tv_sec &= ~1;
+ tsp->tv_nsec = 0;
+}
/**
Return the date and time as a string