1 | /* |
2 | * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") |
3 | * Copyright (c) 1999 by Internet Software Consortium. |
4 | * |
5 | * Permission to use, copy, modify, and distribute this software for any |
6 | * purpose with or without fee is hereby granted, provided that the above |
7 | * copyright notice and this permission notice appear in all copies. |
8 | * |
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES |
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR |
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT |
15 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
16 | */ |
17 | |
18 | /* Import. */ |
19 | |
20 | #include <arpa/nameser.h> |
21 | |
22 | #include <ctype.h> |
23 | #include <errno.h> |
24 | #include <stdio.h> |
25 | #include <string.h> |
26 | #include <time.h> |
27 | |
28 | #define SPRINTF(x) ((size_t)sprintf x) |
29 | |
30 | /* Forward. */ |
31 | |
32 | static int datepart(const char *, int, int, int, int *); |
33 | |
34 | /* Public. */ |
35 | |
36 | /*% |
37 | * Convert a date in ASCII into the number of seconds since |
38 | * 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all |
39 | * digits required, no spaces allowed. |
40 | */ |
41 | |
42 | u_int32_t |
43 | ns_datetosecs(const char *cp, int *errp) { |
44 | struct tm time; |
45 | u_int32_t result; |
46 | int mdays, i; |
47 | static const int days_per_month[12] = |
48 | {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
49 | |
50 | if (strlen(cp) != 14U) { |
51 | *errp = 1; |
52 | return (0); |
53 | } |
54 | *errp = 0; |
55 | |
56 | memset(&time, 0, sizeof time); |
57 | time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; |
58 | time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; |
59 | time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); |
60 | time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); |
61 | time.tm_min = datepart(cp + 10, 2, 00, 59, errp); |
62 | time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); |
63 | if (*errp) /*%< Any parse errors? */ |
64 | return (0); |
65 | |
66 | /* |
67 | * OK, now because timegm() is not available in all environments, |
68 | * we will do it by hand. Roll up sleeves, curse the gods, begin! |
69 | */ |
70 | |
71 | #define SECS_PER_DAY ((u_int32_t)24*60*60) |
72 | #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) |
73 | |
74 | result = time.tm_sec; /*%< Seconds */ |
75 | result += time.tm_min * 60; /*%< Minutes */ |
76 | result += time.tm_hour * (60*60); /*%< Hours */ |
77 | result += (time.tm_mday - 1) * SECS_PER_DAY; /*%< Days */ |
78 | /* Months are trickier. Look without leaping, then leap */ |
79 | mdays = 0; |
80 | for (i = 0; i < time.tm_mon; i++) |
81 | mdays += days_per_month[i]; |
82 | result += mdays * SECS_PER_DAY; /*%< Months */ |
83 | if (time.tm_mon > 1 && isleap(1900+time.tm_year)) |
84 | result += SECS_PER_DAY; /*%< Add leapday for this year */ |
85 | /* First figure years without leapdays, then add them in. */ |
86 | /* The loop is slow, FIXME, but simple and accurate. */ |
87 | result += (time.tm_year - 70) * (SECS_PER_DAY*365); /*%< Years */ |
88 | for (i = 70; i < time.tm_year; i++) |
89 | if (isleap(1900+i)) |
90 | result += SECS_PER_DAY; /*%< Add leapday for prev year */ |
91 | return (result); |
92 | } |
93 | |
94 | /* Private. */ |
95 | |
96 | /*% |
97 | * Parse part of a date. Set error flag if any error. |
98 | * Don't reset the flag if there is no error. |
99 | */ |
100 | static int |
101 | datepart(const char *buf, int size, int min, int max, int *errp) { |
102 | int result = 0; |
103 | int i; |
104 | |
105 | for (i = 0; i < size; i++) { |
106 | if (!isdigit((unsigned char)(buf[i]))) |
107 | *errp = 1; |
108 | result = (result * 10) + buf[i] - '0'; |
109 | } |
110 | if (result < min) |
111 | *errp = 1; |
112 | if (result > max) |
113 | *errp = 1; |
114 | return (result); |
115 | } |
116 | |
117 | /*! \file */ |
118 | |