Parcourir la source

[trac61] separated timeToText() into 32-bit and 64-bit versions.

(this is an intermediate version; the 32-bit version will be fixed to support
overflow cases)
JINMEI Tatuya il y a 14 ans
Parent
commit
8ad3c81393

+ 66 - 20
src/lib/dns/dnssectime.cc

@@ -28,30 +28,83 @@
 
 using namespace std;
 
+namespace {
+int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+inline bool
+isLeap(const int y) {
+    return ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0);
+}
+
+int
+yearSecs(const int year) {
+    return ((isLeap(year) ? 366 : 365 ) * 86400);
+}
+
+int
+monthSecs(const int month, const int year) {
+    return ((days[month] + ((month == 1 && isLeap(year)) ? 1 : 0 )) * 86400);
+}
+}
+
 namespace isc {
 namespace dns {
 
 string
-timeToText(const time_t timeval) {
-    struct tm* const t = gmtime(&timeval);
-
-    // gmtime() will keep most values within range, but it can
-    // produce a five-digit year; check for this.
-    if ((t->tm_year + 1900) > 9999) {
-        isc_throw(InvalidTime, "Time value out of range: year > 9999");
+timeToText64(uint64_t t) {
+    struct tm tm;
+    int secs;
+
+    // We cannot rely on gmtime() because time_t may not be of 64 bit
+    // integer.  The following conversion logic is borrowed from BIND 9.
+    tm.tm_year = 70;
+    while ((secs = yearSecs(tm.tm_year + 1900)) <= t) {
+        t -= secs;
+        ++tm.tm_year;
+        if (tm.tm_year + 1900 > 9999) {
+            isc_throw(InvalidTime,
+                      "Time value out of range (year > 9999): " <<
+                      tm.tm_year + 1900);
+        }
     }
+    tm.tm_mon = 0;
+    while ((secs = monthSecs(tm.tm_mon, tm.tm_year + 1900)) <= t) {
+        t -= secs;
+        tm.tm_mon++;
+    }
+    tm.tm_mday = 1;
+    while (86400 <= t) {
+        t -= 86400;
+        ++tm.tm_mday;
+    }
+    tm.tm_hour = 0;
+    while (3600 <= t) {
+        t -= 3600;
+        ++tm.tm_hour;
+    }
+    tm.tm_min = 0;
+    while (60 <= t) {
+        t -= 60;
+        ++tm.tm_min;
+    }
+    tm.tm_sec = t;              // now t < 60, so this substitution is safe.
 
     ostringstream oss;
     oss << setfill('0')
-        << setw(4) << t->tm_year + 1900
-        << setw(2) << t->tm_mon + 1
-        << setw(2) << t->tm_mday 
-        << setw(2) << t->tm_hour
-        << setw(2) << t->tm_min
-        << setw(2) << t->tm_sec;
+        << setw(4) << tm.tm_year + 1900
+        << setw(2) << tm.tm_mon + 1
+        << setw(2) << tm.tm_mday
+        << setw(2) << tm.tm_hour
+        << setw(2) << tm.tm_min
+        << setw(2) << tm.tm_sec;
     return (oss.str());
 }
 
+string
+timeToText32(const time_t timeval) {
+    return (timeToText64(timeval));
+}
+
 namespace {
 const size_t DATE_LEN = 14;      // YYYYMMDDHHmmSS
 
@@ -64,13 +117,6 @@ checkRange(const int min, const int max, const int value,
     }
     isc_throw(InvalidTime, "Invalid " << valname << "value: " << value);
 }
-
-int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-inline bool
-isLeap(const int y) {
-    return ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0);
-}
 }
 
 uint64_t

+ 4 - 1
src/lib/dns/dnssectime.h

@@ -46,7 +46,10 @@ uint64_t
 timeFromText64(const std::string& time_txt);
 
 std::string
-timeToText(const time_t timeval);
+timeToText32(const time_t timeval);
+
+std::string
+timeToText64(uint64_t t);
 }
 }
 

+ 2 - 5
src/lib/dns/rdata/generic/rrsig_46.cc

@@ -157,15 +157,12 @@ RRSIG::~RRSIG() {
 
 string
 RRSIG::toText() const {
-    string expire = timeToText(impl_->timeexpire_);
-    string inception = timeToText(impl_->timeinception_);
-
     return (impl_->covered_.toText() +
             " " + boost::lexical_cast<string>(static_cast<int>(impl_->algorithm_))
             + " " + boost::lexical_cast<string>(static_cast<int>(impl_->labels_))
             + " " + boost::lexical_cast<string>(impl_->originalttl_)
-            + " " + expire
-            + " " + inception
+            + " " + timeToText32(impl_->timeexpire_)
+            + " " + timeToText32(impl_->timeinception_)
             + " " + boost::lexical_cast<string>(impl_->tag_)
             + " " + impl_->signer_.toText()
             + " " + encodeBase64(impl_->signature_));

+ 3 - 6
src/lib/dns/tests/dnssectime_unittest.cc

@@ -75,16 +75,13 @@ TEST(DNSSECTimeTest, fromText) {
 }
 
 TEST(DNSSECTimeTest, toText) {
-    EXPECT_EQ("19700101000000", timeToText(0));
-    EXPECT_EQ("20100311233000", timeToText(1268350200));
+    EXPECT_EQ("19700101000000", timeToText32(0));
+    EXPECT_EQ("20100311233000", timeToText32(1268350200));
 }
 
 TEST(DNSSECTimeTest, overflow) {
     // Jan 1, Year 10,000.
-    if (sizeof(time_t) > 4) {
-        EXPECT_THROW(timeToText(static_cast<time_t>(253402300800LL)),
-                     InvalidTime);
-    }
+    EXPECT_THROW(timeToText64(253402300800LL), InvalidTime);
 }
 
 }