]> git.ipfire.org Git - thirdparty/unbound.git/commitdiff
gmtime_r threadsafe.
authorWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 23 May 2008 15:43:55 +0000 (15:43 +0000)
committerWouter Wijngaards <wouter@nlnetlabs.nl>
Fri, 23 May 2008 15:43:55 +0000 (15:43 +0000)
git-svn-id: file:///svn/unbound/trunk@1099 be551aaa-1e26-0410-a405-d3ace91eadb9

compat/gmtime_r.c

index 2588ad85cd34807ac9694919ff82008f7226ca6a..231d37e937cc502677a4af4f1e42809b3595f826 100644 (file)
+/*
+ * Taken from FreeBSD src / lib / libc / stdtime / localtime.c 1.43 revision.
+ * localtime.c 7.78.
+ * tzfile.h 1.8
+ * adapted to be replacement gmtime_r.
+ */
 #include "config.h"
 
 #ifdef HAVE_TIME_H
 #include <time.h>
 #endif
 
-struct tm *gmtime_r(const time_t *timep, struct tm *result)
+#define MONSPERYEAR 12
+#define DAYSPERNYEAR 365
+#define DAYSPERLYEAR 366
+#define SECSPERMIN 60
+#define SECSPERHOUR (60*60)
+#define SECSPERDAY (24*60*60)
+#define DAYSPERWEEK 7
+#define TM_SUNDAY      0
+#define TM_MONDAY      1
+#define TM_TUESDAY     2
+#define TM_WEDNESDAY   3
+#define TM_THURSDAY    4
+#define TM_FRIDAY      5
+#define TM_SATURDAY    6
+
+#define TM_JANUARY     0
+#define TM_FEBRUARY    1
+#define TM_MARCH       2
+#define TM_APRIL       3
+#define TM_MAY         4
+#define TM_JUNE                5
+#define TM_JULY                6
+#define TM_AUGUST      7
+#define TM_SEPTEMBER   8
+#define TM_OCTOBER     9
+#define TM_NOVEMBER    10
+#define TM_DECEMBER    11
+
+#define TM_YEAR_BASE   1900
+
+#define EPOCH_YEAR     1970
+#define EPOCH_WDAY     TM_THURSDAY
+
+#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
+
+static const int       mon_lengths[2][MONSPERYEAR] = {
+       { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
+       { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
+};
+
+static const int       year_lengths[2] = {
+       DAYSPERNYEAR, DAYSPERLYEAR
+};
+
+static void
+timesub(timep, offset, tmp)
+const time_t * const                   timep;
+const long                             offset;
+struct tm * const              tmp;
+{
+       long                    days;
+       long                    rem;
+       long                    y;
+       int                     yleap;
+       const int *             ip;
+
+       days = *timep / SECSPERDAY;
+       rem = *timep % SECSPERDAY;
+       rem += (offset);
+       while (rem < 0) {
+               rem += SECSPERDAY;
+               --days;
+       }
+       while (rem >= SECSPERDAY) {
+               rem -= SECSPERDAY;
+               ++days;
+       }
+       tmp->tm_hour = (int) (rem / SECSPERHOUR);
+       rem = rem % SECSPERHOUR;
+       tmp->tm_min = (int) (rem / SECSPERMIN);
+       /*
+       ** A positive leap second requires a special
+       ** representation.  This uses "... ??:59:60" et seq.
+       */
+       tmp->tm_sec = (int) (rem % SECSPERMIN) ;
+       tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
+       if (tmp->tm_wday < 0)
+               tmp->tm_wday += DAYSPERWEEK;
+       y = EPOCH_YEAR;
+#define LEAPS_THRU_END_OF(y)   ((y) / 4 - (y) / 100 + (y) / 400)
+       while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
+               long    newy;
+
+               newy = y + days / DAYSPERNYEAR;
+               if (days < 0)
+                       --newy;
+               days -= (newy - y) * DAYSPERNYEAR +
+                       LEAPS_THRU_END_OF(newy - 1) -
+                       LEAPS_THRU_END_OF(y - 1);
+               y = newy;
+       }
+       tmp->tm_year = y - TM_YEAR_BASE;
+       tmp->tm_yday = (int) days;
+       ip = mon_lengths[yleap];
+       for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
+               days = days - (long) ip[tmp->tm_mon];
+       tmp->tm_mday = (int) (days + 1);
+       tmp->tm_isdst = 0;
+}
+
+/*
+* Re-entrant version of gmtime.
+*/
+struct tm * gmtime_r(const time_t* timep, struct tm *tm)
 {
-       /* no thread safety. */
-       *result = *gmtime(timep);
-       return result;
+       timesub(timep, 0L, tm);
+       return tm;
 }