Round and round we go....
[ira/wip.git] / source3 / lib / time.c
index 3cea1a3e14a08367f09f1ea314850a30e945a44c..c39753403d707dc9d1a7614bce35a24931323941 100644 (file)
   */
 
 
-int serverzone=0;
 int extra_time_offset = 0;
 
-extern int DEBUGLEVEL;
-
 #ifndef CHAR_BIT
 #define CHAR_BIT 8
 #endif
@@ -44,7 +41,19 @@ extern int DEBUGLEVEL;
 #define TIME_T_MAX (~ (time_t) 0 - TIME_T_MIN)
 #endif
 
+/*******************************************************************
+ External access to time_t_min and time_t_max.
+********************************************************************/
+
+time_t get_time_t_min(void)
+{
+       return TIME_T_MIN;
+}
 
+time_t get_time_t_max(void)
+{
+       return TIME_T_MAX;
+}
 
 /*******************************************************************
 a gettimeofday wrapper
@@ -95,21 +104,61 @@ static int TimeZone(time_t t)
 
 }
 
+static BOOL done_serverzone_init;
 
-/*******************************************************************
-init the time differences
-********************************************************************/
-void TimeInit(void)
+/* Return the smb serverzone value */
+
+static int get_serverzone(void)
 {
-  serverzone = TimeZone(time(NULL));
+        static int serverzone;
 
-  if ((serverzone % 60) != 0) {
-         DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n"));
-  }
+        if (!done_serverzone_init) {
+                serverzone = TimeZone(time(NULL));
+
+                if ((serverzone % 60) != 0) {
+                        DEBUG(1,("WARNING: Your timezone is not a multiple of 1 minute.\n"));
+                }
+
+                DEBUG(4,("Serverzone is %d\n",serverzone));
 
-  DEBUG(4,("Serverzone is %d\n",serverzone));
+                done_serverzone_init = True;
+        }
+
+        return serverzone;
 }
 
+/* Re-read the smb serverzone value */
+
+static struct timeval start_time_hires;
+
+void TimeInit(void)
+{
+       done_serverzone_init = False;
+       get_serverzone();
+       /* Save the start time of this process. */
+       if (start_time_hires.tv_sec == 0 && start_time_hires.tv_usec == 0)
+               GetTimeOfDay(&start_time_hires);
+}
+
+/**********************************************************************
+ Return a timeval struct of the uptime of this process. As TimeInit is
+ done before a daemon fork then this is the start time from the parent
+ daemon start. JRA.
+***********************************************************************/
+
+void get_process_uptime(struct timeval *ret_time)
+{
+       struct timeval time_now_hires;
+
+       GetTimeOfDay(&time_now_hires);
+       ret_time->tv_sec = time_now_hires.tv_sec - start_time_hires.tv_sec;
+       ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
+       if (time_now_hires.tv_usec < start_time_hires.tv_usec) {
+               ret_time->tv_sec -= 1;
+               ret_time->tv_usec = 1000000 + (time_now_hires.tv_usec - start_time_hires.tv_usec);
+       } else
+               ret_time->tv_usec = time_now_hires.tv_usec - start_time_hires.tv_usec;
+}
 
 /*******************************************************************
 return the same value as TimeZone, but it should be more efficient.
@@ -121,7 +170,7 @@ Updated by Paul Eggert <eggert@twinsun.com>
 ********************************************************************/
 static int TimeZoneFaster(time_t t)
 {
-  static struct dst_table {time_t start,end; int zone;} *dst_table = NULL;
+  static struct dst_table {time_t start,end; int zone;} *tdt, *dst_table = NULL;
   static int table_size = 0;
   int i;
   int zone = 0;
@@ -141,11 +190,14 @@ static int TimeZoneFaster(time_t t)
     time_t low,high;
 
     zone = TimeZone(t);
-    dst_table = (struct dst_table *)Realloc(dst_table,
+    tdt = (struct dst_table *)Realloc(dst_table,
                                              sizeof(dst_table[0])*(i+1));
-    if (!dst_table) {
+    if (!tdt) {
+      DEBUG(0,("TimeZoneFaster: out of memory!\n"));
+      SAFE_FREE(dst_table);
       table_size = 0;
     } else {
+      dst_table = tdt;
       table_size++;
 
       dst_table[i].zone = zone; 
@@ -271,12 +323,56 @@ time_t nt_time_to_unix(NTTIME *nt)
   ret = (time_t)(d+0.5);
 
   /* this takes us from kludge-GMT to real GMT */
-  ret -= serverzone;
+  ret -= get_serverzone();
   ret += LocTimeDiff(ret);
 
   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(NTTIME *nt)
+{
+       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;
+
+       if (nt->high == 0)
+               return(0);
+
+       if (nt->high==0x80000000 && nt->low==0)
+               return -1;
+
+       /* reverse the time */
+       /* it's a negative value, turn it to positive */
+       nt->high=~nt->high;
+       nt->low=~nt->low;
+
+       d = ((double)nt->high)*4.0*(double)(1<<30);
+       d += (nt->low&0xFFF00000);
+       d *= 1.0e-7;
+  
+       if (!(l_time_min <= d && d <= l_time_max))
+               return(0);
+
+       ret = (time_t)(d+0.5);
+
+       /* this takes us from kludge-GMT to real GMT */
+       ret -= get_serverzone();
+       ret += LocTimeDiff(ret);
+
+       return(ret);
+}
+
 
 
 /****************************************************************************
@@ -304,9 +400,21 @@ void unix_to_nt_time(NTTIME *nt, time_t t)
                nt->high = 0;
                return;
        }
+       if (t == TIME_T_MAX)
+       {
+               nt->low = 0xffffffff;
+               nt->high = 0x7fffffff;
+               return;
+       }               
+       if (t == -1)
+       {
+               nt->low = 0xffffffff;
+               nt->high = 0xffffffff;
+               return;
+       }               
 
        /* this converts GMT to kludge-GMT */
-       t -= LocTimeDiff(t) - serverzone
+       t -= LocTimeDiff(t) - get_serverzone()
 
        d = (double)(t);
        d += TIME_FIXUP_CONSTANT;
@@ -316,6 +424,50 @@ void unix_to_nt_time(NTTIME *nt, time_t t)
        nt->low  = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
 }
 
+/****************************************************************************
+convert a time_t to a NTTIME structure
+
+this is an absolute version of the one above.
+By absolute I mean, it doesn't adjust from 1/1/1970 to 1/1/1601
+if the nttime_t was 5 seconds, the NTTIME is 5 seconds. JFM
+****************************************************************************/
+void unix_to_nt_time_abs(NTTIME *nt, time_t t)
+{
+       double d;
+
+       if (t==0) {
+               nt->low = 0;
+               nt->high = 0;
+               return;
+       }
+
+       if (t == TIME_T_MAX) {
+               nt->low = 0xffffffff;
+               nt->high = 0x7fffffff;
+               return;
+       }
+               
+       if (t == -1) {
+               /* that's what NT uses for infinite */
+               nt->low = 0x0;
+               nt->high = 0x80000000;
+               return;
+       }               
+
+       /* this converts GMT to kludge-GMT */
+       t -= LocTimeDiff(t) - get_serverzone(); 
+
+       d = (double)(t);
+       d *= 1.0e7;
+
+       nt->high = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
+       nt->low  = (uint32)(d - ((double)nt->high)*4.0*(double)(1<<30));
+
+       /* convert to a negative value */
+       nt->high=~nt->high;
+       nt->low=~nt->low;
+}
+
 
 /****************************************************************************
 take an NTTIME structure, containing high / low time.  convert to unix time.
@@ -495,6 +647,8 @@ char *http_timestring(time_t t)
   else
 #ifndef HAVE_STRFTIME
   fstrcpy(buf, asctime(tm));
+  if(buf[strlen(buf)-1] == '\n')
+    buf[strlen(buf)-1] = 0;
 #else /* !HAVE_STRFTIME */
   strftime(buf, sizeof(buf)-1, "%a, %d %b %Y %H:%M:%S %Z", tm);
 #endif /* !HAVE_STRFTIME */
@@ -504,21 +658,57 @@ char *http_timestring(time_t t)
 
 
 /****************************************************************************
 return the date and time as a string
Return the date and time as a string
 ****************************************************************************/
-char *timestring(void )
+
+char *timestring(BOOL hires)
 {
        static fstring TimeBuf;
-       time_t t = time(NULL);
-       struct tm *tm = LocalTime(&t);
+       struct timeval tp;
+       time_t t;
+       struct tm *tm;
 
+       if (hires) {
+               GetTimeOfDay(&tp);
+               t = (time_t)tp.tv_sec;
+       } else {
+               t = time(NULL);
+       }
+       tm = LocalTime(&t);
        if (!tm) {
-               slprintf(TimeBuf,sizeof(TimeBuf)-1,"%ld seconds since the Epoch",(long)t);
+               if (hires) {
+                       slprintf(TimeBuf,
+                                sizeof(TimeBuf)-1,
+                                "%ld.%06ld seconds since the Epoch",
+                                (long)tp.tv_sec, 
+                                (long)tp.tv_usec);
+               } else {
+                       slprintf(TimeBuf,
+                                sizeof(TimeBuf)-1,
+                                "%ld seconds since the Epoch",
+                                (long)t);
+               }
        } else {
 #ifdef HAVE_STRFTIME
-               strftime(TimeBuf,100,"%Y/%m/%d %T",tm);
+               if (hires) {
+                       strftime(TimeBuf,sizeof(TimeBuf)-1,"%Y/%m/%d %H:%M:%S",tm);
+                       slprintf(TimeBuf+strlen(TimeBuf),
+                                sizeof(TimeBuf)-1 - strlen(TimeBuf), 
+                                ".%06ld", 
+                                (long)tp.tv_usec);
+               } else {
+                       strftime(TimeBuf,100,"%Y/%m/%d %H:%M:%S",tm);
+               }
 #else
-               fstrcpy(TimeBuf, asctime(tm));
+               if (hires) {
+                       slprintf(TimeBuf, 
+                                sizeof(TimeBuf)-1, 
+                                "%s.%06ld", 
+                                asctime(tm), 
+                                (long)tp.tv_usec);
+               } else {
+                       fstrcpy(TimeBuf, asctime(tm));
+               }
 #endif
        }
        return(TimeBuf);
@@ -549,3 +739,12 @@ time_t get_create_time(SMB_STRUCT_STAT *st,BOOL fake_dirs)
   return ret;
 }
 
+/****************************************************************************
+initialise an NTTIME to -1, which means "unknown" or "don't expire"
+****************************************************************************/
+
+void init_nt_time(NTTIME *nt)
+{
+       nt->high = 0x7FFFFFFF;
+       nt->low = 0xFFFFFFFF;
+}