Author: jra
Date: 2006-08-24 20:51:57 +0000 (Thu, 24 Aug 2006)
New Revision: 17809

WebSVN: 
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17809

Log:
Add in 64-bit integer time calculations (taken from
Samba4) for machines that have 64-bit integers. Leave
the (double) code for machines that don't. Needs
testing.... :-).
Jeremy.

Modified:
   branches/SAMBA_3_0/source/lib/time.c


Changeset:
Modified: branches/SAMBA_3_0/source/lib/time.c
===================================================================
--- branches/SAMBA_3_0/source/lib/time.c        2006-08-24 20:49:26 UTC (rev 
17808)
+++ branches/SAMBA_3_0/source/lib/time.c        2006-08-24 20:51:57 UTC (rev 
17809)
@@ -190,8 +190,14 @@
        return ts;
 }
 
-#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
+#ifdef uint64
 
+#if (SIZEOF_LONG == 8)
+#define TIME_FIXUP_CONSTANT_INT 11644473600L
+#elif (SIZEOF_LONG_LONG == 8)
+#define TIME_FIXUP_CONSTANT_INT 11644473600LL
+#endif
+
 /****************************************************************************
  Interpret an 8 byte "filetime" structure to a time_t
  It's originally in "100ns units since jan 1st 1601"
@@ -204,14 +210,130 @@
  Returns GMT.
 ****************************************************************************/
 
+/* Large integer version. */
 static struct timespec nt_time_to_unix_timespec(NTTIME *nt)
 {
+       uint64 d;
+       struct timespec ret;
+
+       if ((nt->high == 0 && nt->low == 0 )||
+                       (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
+               ret.tv_sec = 0;
+               ret.tv_nsec = 0;
+               return ret;
+       }
+
+       d = (((uint64)nt->high) << 32 ) + ((uint64)nt->low);
+       /* d is now in 100ns units, since jan 1st 1601".
+          Save off the ns fraction. */
+       
+       ret.tv_nsec = (long) ((d % 100) * 100);
+
+       /* Convert to seconds */
+       d /= 1000*1000*10;
+
+       /* Now adjust by 369 years to make the secs since 1970 */
+       d -= TIME_FIXUP_CONSTANT_INT;
+
+       if (d <= TIME_T_MIN) {
+               ret.tv_sec = TIME_T_MIN;
+               ret.tv_nsec = 0;
+               return ret;
+       }
+
+       if (d >= TIME_T_MAX) {
+               ret.tv_sec = TIME_T_MAX;
+               ret.tv_nsec = 0;
+               return ret;
+       }
+
+       ret.tv_sec = (time_t)d;
+        return ret;
+}
+
+/****************************************************************************
+ Convert a NTTIME structure to a time_t.
+ It's originally in "100ns units".
+
+ This is an absolute version of the one above.
+ By absolute I mean, it doesn't adjust from 1/1/1601 to 1/1/1970
+ if the NTTIME was 5 seconds, the time_t is 5 seconds. JFM
+****************************************************************************/
+
+time_t nt_time_to_unix_abs(const NTTIME *nt)
+{
+       uint64 d;
+       NTTIME neg_nt;
+
+       if (nt->high == 0) {
+               return (time_t)0;
+       }
+
+       if (nt->high==0x80000000 && nt->low==0) {
+               return (time_t)-1;
+       }
+
+       /* reverse the time */
+       /* it's a negative value, turn it to positive */
+       neg_nt.high=~nt->high;
+       neg_nt.low=~nt->low;
+
+       d = (((uint64)neg_nt.high) << 32 ) + ((uint64)neg_nt.low);
+
+       d += 1000*1000*10/2;
+       d /= 1000*1000*10;
+
+       if (!(TIME_T_MIN <= d && d <= TIME_T_MAX)) {
+               return (time_t)0;
+       }
+
+       return (time_t)d;
+}
+
+/****************************************************************************
+ Put a 8 byte filetime from a struct timespec. Uses GMT.
+****************************************************************************/
+
+void unix_timespec_to_nt_time(NTTIME *nt, struct timespec ts)
+{
+       uint64 d;
+
+       if (ts.tv_sec ==0 && ts.tv_nsec == 0) {
+               nt->low = 0;
+               nt->high = 0;
+               return;
+       }
+       if (ts.tv_sec == TIME_T_MAX) {
+               nt->low = 0xffffffff;
+               nt->high = 0x7fffffff;
+               return;
+       }               
+       if (ts.tv_sec == (time_t)-1) {
+               nt->low = 0xffffffff;
+               nt->high = 0xffffffff;
+               return;
+       }               
+
+       d = ts.tv_sec;
+       d += TIME_FIXUP_CONSTANT_INT;
+       d = ts.tv_sec * 1000*1000*10;
+       /* d is now in 100ns units. */
+       d += (ts.tv_nsec / 100);
+
+       nt->high = (uint32)(d / 1000*1000*10);
+       nt->low  = (uint32)(d % 1000*1000*10);
+}
+
+#else
+
+/* No 64-bit datatype. Use double float. */
+#define TIME_FIXUP_CONSTANT_DOUBLE 
(369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
+
+/* Floating point double versions. */
+static struct timespec nt_time_to_unix_timespec(NTTIME *nt)
+{
        double d;
        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->low == 0 )||
                        (nt->high == 0xffffffff && nt->low == 0xffffffff)) {
@@ -225,16 +347,16 @@
        d *= 1.0e-7;
  
        /* now adjust by 369 years to make the secs since 1970 */
-       d -= TIME_FIXUP_CONSTANT;
+       d -= TIME_FIXUP_CONSTANT_DOUBLE;
 
-       if (d <= l_time_min) {
-               ret.tv_sec = l_time_min;
+       if (d <= TIME_T_MIN) {
+               ret.tv_sec = TIME_T_MIN;
                ret.tv_nsec = 0;
                return ret;
        }
 
-       if (d >= l_time_max) {
-               ret.tv_sec = l_time_max;
+       if (d >= TIME_T_MAX) {
+               ret.tv_sec = TIME_T_MAX;
                ret.tv_nsec = 0;
                return ret;
        }
@@ -244,11 +366,6 @@
        return ret;
 }
 
-time_t nt_time_to_unix(NTTIME *nt)
-{
-       return convert_timespec_to_time_t(nt_time_to_unix_timespec(nt));
-}
-
 /****************************************************************************
  Convert a NTTIME structure to a time_t.
  It's originally in "100ns units".
@@ -262,10 +379,6 @@
 {
        double d;
        time_t 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;
        NTTIME neg_nt;
 
        if (nt->high == 0) {
@@ -285,7 +398,7 @@
        d += (neg_nt.low&0xFFF00000);
        d *= 1.0e-7;
   
-       if (!(l_time_min <= d && d <= l_time_max)) {
+       if (!(TIME_T_MIN <= d && d <= TIME_T_MAX)) {
                return (time_t)0;
        }
 
@@ -294,26 +407,6 @@
 }
 
 /****************************************************************************
- 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.
-****************************************************************************/
-
-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) {
-               struct timespec ret;
-               ret.tv_sec = (time_t)-1;
-               ret.tv_nsec = 0;
-               return ret;
-       }
-       return nt_time_to_unix_timespec(&nt);
-}
-
-/****************************************************************************
  Put a 8 byte filetime from a struct timespec. Uses GMT.
 ****************************************************************************/
 
@@ -338,15 +431,41 @@
        }               
 
        d = (double)(ts.tv_sec);
-       d += TIME_FIXUP_CONSTANT;
+       d += TIME_FIXUP_CONSTANT_DOUBLE;
        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));
 }
+#endif
 
+time_t nt_time_to_unix(NTTIME *nt)
+{
+       return convert_timespec_to_time_t(nt_time_to_unix_timespec(nt));
+}
+
 /****************************************************************************
+ 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.
+****************************************************************************/
+
+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) {
+               struct timespec ret;
+               ret.tv_sec = (time_t)-1;
+               ret.tv_nsec = 0;
+               return ret;
+       }
+       return nt_time_to_unix_timespec(&nt);
+}
+
+/****************************************************************************
  Put a 8 byte filetime from a time_t. Uses GMT.
 ****************************************************************************/
 

Reply via email to