From: Bert Hubert Date: Sat, 7 Aug 2010 19:26:40 +0000 (+0000) Subject: gratefully copied timegm replacement code from dietlibc! (GPL) X-Git-Tag: rec-3.3~38 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=49f72da134c234603abc5d270f73ea6191dceeff;p=pdns gratefully copied timegm replacement code from dietlibc! (GPL) git-svn-id: svn://svn.powerdns.com/pdns/trunk/pdns@1681 d19b8d6e-7fed-0310-83ef-9ca221ded41b --- diff --git a/pdns/rcpgenerator.cc b/pdns/rcpgenerator.cc index 6485c5e80..184fdf135 100644 --- a/pdns/rcpgenerator.cc +++ b/pdns/rcpgenerator.cc @@ -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) diff --git a/pdns/unix_utility.cc b/pdns/unix_utility.cc index ce96cb742..4e5ffdc92 100644 --- a/pdns/unix_utility.cc +++ b/pdns/unix_utility.cc @@ -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; +} + diff --git a/pdns/utility.hh b/pdns/utility.hh index 82e736522..f3a9a44e3 100644 --- a/pdns/utility.hh +++ b/pdns/utility.hh @@ -201,6 +201,8 @@ public: //! Sleeps for a number of microseconds. static void usleep( unsigned long usec ); + + static time_t timegm(struct tm *tm); };