xref: /illumos-gate/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gmt_mktime.c (revision 4bc0a2ef2b7ba50a7a717e7ddbf31472ad28e358)
1 /*
2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
3  * Use is subject to license terms.
4  */
5 
6 #pragma ident	"%Z%%M%	%I%	%E% SMI"
7 
8 /* This code placed in the public domain by Mark W. Eichin */
9 
10 #include <stdio.h>
11 #include <k5-int.h>
12 
13 #ifdef HAVE_SYS_TYPES_H
14 #include <sys/types.h>
15 #endif
16 #ifdef HAVE_SYS_TIME_H
17 #include <sys/time.h>
18 #ifdef TIME_WITH_SYS_TIME
19 #include <time.h>
20 #endif
21 #else
22 #include <time.h>
23 #endif
24 
25 /* take a struct tm, return seconds from GMT epoch */
26 /* like mktime, this ignores tm_wday and tm_yday. */
27 /* unlike mktime, this does not set them... it only passes a return value. */
28 
29 static const int days_in_month[12] = {
30 0,				/* jan 31 */
31 31,				/* feb 28 */
32 59,				/* mar 31 */
33 90,				/* apr 30 */
34 120,				/* may 31 */
35 151,				/* jun 30 */
36 181,				/* jul 31 */
37 212,				/* aug 31 */
38 243,				/* sep 30 */
39 273,				/* oct 31 */
40 304,				/* nov 30 */
41 334				/* dec 31 */
42 };
43 
44 #define hasleapday(year) (year%400?(year%100?(year%4?0:1):0):1)
45 
46 time_t gmt_mktime(struct tm *t)
47 {
48   time_t accum;
49 
50 #define assert_time(cnd) if(!(cnd)) return (time_t) -1
51 
52   /*
53    * For 32-bit signed time_t centered on 1/1/1970, the range is:
54    * time 0x80000000 -> Fri Dec 13 16:45:52 1901
55    * time 0x7fffffff -> Mon Jan 18 22:14:07 2038
56    *
57    * So years 1901 and 2038 are allowable, but we can't encode all
58    * dates in those years, and we're not doing overflow/underflow
59    * checking for such cases.
60    */
61   assert_time(t->tm_year>=1);
62   assert_time(t->tm_year<=138);
63   assert_time(t->tm_mon>=0);
64   assert_time(t->tm_mon<=11);
65   assert_time(t->tm_mday>=1);
66   assert_time(t->tm_mday<=31);
67   assert_time(t->tm_hour>=0);
68   assert_time(t->tm_hour<=23);
69   assert_time(t->tm_min>=0);
70   assert_time(t->tm_min<=59);
71   assert_time(t->tm_sec>=0);
72   assert_time(t->tm_sec<=62);
73 
74 #undef assert_time
75 
76 
77   accum = t->tm_year - 70;
78   accum *= 365;			/* 365 days/normal year */
79 
80   /* add in leap day for all previous years */
81   if (t->tm_year >= 70)
82     accum += (t->tm_year - 69) / 4;
83   else
84     accum -= (72 - t->tm_year) / 4;
85   /* add in leap day for this year */
86   if(t->tm_mon >= 2)		/* march or later */
87     if(hasleapday((t->tm_year + 1900))) accum += 1;
88 
89   accum += days_in_month[t->tm_mon];
90   accum += t->tm_mday-1;	/* days of month are the only 1-based field */
91   accum *= 24;			/* 24 hour/day */
92   accum += t->tm_hour;
93   accum *= 60;			/* 60 minute/hour */
94   accum += t->tm_min;
95   accum *= 60;			/* 60 seconds/minute */
96   accum += t->tm_sec;
97 
98   return accum;
99 }
100