add _der_gmtime, use and test it
authorLove Hornquist Astrand <lha@h5l.org>
Wed, 29 Sep 2010 20:32:39 +0000 (13:32 -0700)
committerLove Hornquist Astrand <lha@h5l.org>
Wed, 29 Sep 2010 20:32:39 +0000 (13:32 -0700)
lib/asn1/check-timegm.c
lib/asn1/der_locl.h
lib/asn1/der_put.c
lib/asn1/libasn1-exports.def
lib/asn1/timegm.c

index 449ef52567ec6cf2380c80936b9766a6e2e402d6..13d3abcf1fa57e2fc4b18d4af1b6179c57268109 100644 (file)
@@ -58,6 +58,15 @@ test_timegm(void)
     if (t != -1)
        ret += 1;
 
+    _der_gmtime(1159696980, &tm);
+    if (tm.tm_year != 106 ||
+       tm.tm_mon != 9 ||
+       tm.tm_mday != 1 ||
+       tm.tm_hour != 10 ||
+       tm.tm_min != 3 ||
+       tm.tm_sec != 0)
+      errx(1, "tmtime failes");
+
     return ret;
 }
 
index 0f65c50a2234449227e7d1551ab7df4a09575049..a086e18fa4a4ff9572eb912c7339959106739bfd 100644 (file)
@@ -56,6 +56,7 @@
 #include "asn1-template.h"
 
 time_t _der_timegm (struct tm *);
+struct tm * _der_gmtime(time_t t, struct tm *);
 size_t _heim_len_unsigned (unsigned);
 size_t _heim_len_int (int);
 
index c8192f25fe5ca1e5b87f183bf87ef0f2f3ee9f72..b8101458ad4be9866f3e43dd9e4c08606855a67d 100644 (file)
@@ -426,22 +426,22 @@ der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val,
 int
 _heim_time2generalizedtime (time_t t, heim_octet_string *s, int gtimep)
 {
-     struct tm *tm;
+     struct tm tm;
      const size_t len = gtimep ? 15 : 13;
 
      s->data = malloc(len + 1);
      if (s->data == NULL)
         return ENOMEM;
      s->length = len;
-     tm = gmtime (&t);
+     _der_gmtime(t, &tm);
      if (gtimep)
         snprintf (s->data, len + 1, "%04d%02d%02d%02d%02d%02dZ",
-                  tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
-                  tm->tm_hour, tm->tm_min, tm->tm_sec);
+                  tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
+                  tm.tm_hour, tm.tm_min, tm.tm_sec);
      else
         snprintf (s->data, len + 1, "%02d%02d%02d%02d%02d%02dZ",
-                  tm->tm_year % 100, tm->tm_mon + 1, tm->tm_mday,
-                  tm->tm_hour, tm->tm_min, tm->tm_sec);
+                  tm.tm_year % 100, tm.tm_mon + 1, tm.tm_mday,
+                  tm.tm_hour, tm.tm_min, tm.tm_sec);
 
      return 0;
 }
index 3815917dc4dd714a047326bd633c716f7e9b2b52..6dfb93ea054ca701d9347a060f930b6aa5aff747 100644 (file)
@@ -8,6 +8,7 @@ EXPORTS
        SAMFlags2int
        TicketFlags2int
        _der_timegm
+       _der_gmtime
        _heim_der_set_sort
        _heim_fix_dce
        _heim_len_int
index c72968dc049bd661fd8ae3a37ebb24e0d2b68980..b5694784138ce12b76833c5d6a069d47d1cfde6a 100644 (file)
@@ -42,6 +42,10 @@ is_leap(unsigned y)
     return (y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0);
 }
 
+static const unsigned ndays[2][12] ={
+    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
+    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
+
 /*
  * This is a simplifed version of timegm(3) that doesn't accept out of
  * bound values that timegm(3) normally accepts but those are not
@@ -51,9 +55,6 @@ is_leap(unsigned y)
 time_t
 _der_timegm (struct tm *tm)
 {
-  static const unsigned ndays[2][12] ={
-    {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
-    {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}};
   time_t res = 0;
   unsigned i;
 
@@ -84,3 +85,37 @@ _der_timegm (struct tm *tm)
   res += tm->tm_sec;
   return res;
 }
+
+struct tm *
+_der_gmtime(time_t t, struct tm *tm)
+{
+    time_t secday = t % (3600 * 24);
+    time_t days = t / (3600 * 24);
+
+    memset(tm, 0, sizeof(*tm));
+
+    tm->tm_sec = secday % 60;
+    tm->tm_min = (secday % 3600) / 60;
+    tm->tm_hour = secday / 3600;
+
+    tm->tm_year = 70;
+    while(1) {
+       unsigned dayinyear = (is_leap(tm->tm_year) ? 366 : 365);
+       if (days < dayinyear)
+           break;
+       tm->tm_year += 1;
+       days -= dayinyear;
+    }
+    tm->tm_mon = 0;
+
+    while (1) {
+       unsigned daysinmonth = ndays[is_leap(tm->tm_year)][tm->tm_mon];
+       if (days < daysinmonth)
+           break;
+       days -= daysinmonth;
+       tm->tm_mon++;
+    }
+    tm->tm_mday = days + 1;
+
+    return tm;
+}