]> granicus.if.org Git - pdns/commitdiff
gratefully copied timegm replacement code from dietlibc! (GPL)
authorBert Hubert <bert.hubert@netherlabs.nl>
Sat, 7 Aug 2010 19:26:40 +0000 (19:26 +0000)
committerBert Hubert <bert.hubert@netherlabs.nl>
Sat, 7 Aug 2010 19:26:40 +0000 (19:26 +0000)
git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1681 d19b8d6e-7fed-0310-83ef-9ca221ded41b

pdns/rcpgenerator.cc
pdns/unix_utility.cc
pdns/utility.hh

index 6485c5e808cd00d8e5e2ab5e63d634c3270ce0ec..184fdf13565e4fdde131295958a9de0f39b61e06 100644 (file)
@@ -78,7 +78,7 @@ void RecordTextReader::xfrTime(uint32_t &val)
 
   tm.tm_year-=1900;
   tm.tm_mon-=1;
-  val=(uint32_t)timegm(&tm); // XXX FIXME disabled for Solaris
+  val=(uint32_t)Utility::timegm(&tm); 
 }
 
 void RecordTextReader::xfrIP(uint32_t &val)
index ce96cb742e708aeba39f7e05cf621d145c8f7d46..4e5ffdc92b71855a5e36962b83e19035c441f57c 100644 (file)
@@ -183,3 +183,75 @@ int Utility::writev(int socket, const iovec *vector, size_t count )
   return ::writev(socket,vector,count);
 }
 
+/* this is cut and pasted from dietlibc, gratefully copied! */
+static int isleap(int year) {
+  /* every fourth year is a leap year except for century years that are
+   * not divisible by 400. */
+  return (!(year%4) && ((year%100) || !(year%400)));
+}
+
+time_t Utility::timegm(struct tm *const t) 
+{
+  const static short spm[13] = /* days per month -- nonleap! */
+  { 0,
+    (31),
+    (31+28),
+    (31+28+31),
+    (31+28+31+30),
+    (31+28+31+30+31),
+    (31+28+31+30+31+30),
+    (31+28+31+30+31+30+31),
+    (31+28+31+30+31+30+31+31),
+    (31+28+31+30+31+30+31+31+30),
+    (31+28+31+30+31+30+31+31+30+31),
+    (31+28+31+30+31+30+31+31+30+31+30),
+    (31+28+31+30+31+30+31+31+30+31+30+31),
+  };
+
+  time_t  day;
+  time_t  i;
+  time_t years = t->tm_year - 70;
+
+  if (t->tm_sec>60) { t->tm_min += t->tm_sec/60; t->tm_sec%=60; }
+  if (t->tm_min>60) { t->tm_hour += t->tm_min/60; t->tm_min%=60; }
+  if (t->tm_hour>60) { t->tm_mday += t->tm_hour/60; t->tm_hour%=60; }
+  if (t->tm_mon>12) { t->tm_year += t->tm_mon/12; t->tm_mon%=12; }
+  while (t->tm_mday>spm[1+t->tm_mon]) {
+    if (t->tm_mon==1 && isleap(t->tm_year+1900)) {
+      if (t->tm_mon==31+29) break;
+      --t->tm_mday;
+    }
+    t->tm_mday-=spm[t->tm_mon];
+    ++t->tm_mon;
+    if (t->tm_mon>11) { t->tm_mon=0; ++t->tm_year; }
+  }
+
+  if (t->tm_year < 70)
+    return (time_t) -1;
+  /* Days since 1970 is 365 * number of years + number of leap years since 1970 */
+  day  = years * 365 + (years + 1) / 4;
+
+  /* After 2100 we have to substract 3 leap years for every 400 years
+     This is not intuitive. Most mktime implementations do not support
+     dates after 2059, anyway, so we might leave this out for it's
+     bloat. */
+  if ((years -= 131) >= 0) {
+    years /= 100;
+    day -= (years >> 2) * 3 + 1;
+    if ((years &= 3) == 3) years--;
+    day -= years;
+  }
+
+  day += t->tm_yday = spm [t->tm_mon] + t->tm_mday-1 + ( isleap (t->tm_year+1900)  &  (t->tm_mon > 1) );
+
+  /* day is now the number of days since 'Jan 1 1970' */
+  i = 7;
+  t->tm_wday = (day + 4) % i;                        /* Sunday=0, Monday=1, ..., Saturday=6 */
+
+  i = 24;
+  day *= i;
+  i = 60;
+  return ((day + t->tm_hour) * i + t->tm_min) * i + t->tm_sec;
+}
+
index 82e73652219e878f8e6c181d8c9b456eb69aae92..f3a9a44e3a001064b9f87fd78d0f19ad510be251 100644 (file)
@@ -201,6 +201,8 @@ public:
   
   //! Sleeps for a number of microseconds.
   static void usleep( unsigned long usec );
+
+  static time_t timegm(struct tm *tm);
   
 };