]>
Commit | Line | Data |
---|---|---|
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 | #if !defined(_LIBC) && !defined(lint) | |
19 | static const char rcsid[] = "$Id$"; | |
20 | #endif | |
21 | ||
22 | /* Import. */ | |
23 | ||
24 | #include <arpa/nameser.h> | |
25 | ||
26 | #include <ctype.h> | |
27 | #include <errno.h> | |
28 | #include <stdio.h> | |
29 | #include <string.h> | |
30 | #include <time.h> | |
31 | ||
32 | #define SPRINTF(x) ((size_t)sprintf x) | |
33 | ||
34 | /* Forward. */ | |
35 | ||
36 | static int datepart(const char *, int, int, int, int *); | |
37 | ||
38 | /* Public. */ | |
39 | ||
40 | /*% | |
41 | * Convert a date in ASCII into the number of seconds since | |
42 | * 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all | |
43 | * digits required, no spaces allowed. | |
44 | */ | |
45 | ||
46 | u_int32_t | |
47 | ns_datetosecs(const char *cp, int *errp) { | |
48 | struct tm time; | |
49 | u_int32_t result; | |
50 | int mdays, i; | |
51 | static const int days_per_month[12] = | |
52 | {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; | |
53 | ||
54 | if (strlen(cp) != 14U) { | |
55 | *errp = 1; | |
56 | return (0); | |
57 | } | |
58 | *errp = 0; | |
59 | ||
60 | memset(&time, 0, sizeof time); | |
61 | time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; | |
62 | time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; | |
63 | time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); | |
64 | time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); | |
65 | time.tm_min = datepart(cp + 10, 2, 00, 59, errp); | |
66 | time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); | |
67 | if (*errp) /*%< Any parse errors? */ | |
68 | return (0); | |
69 | ||
70 | /* | |
71 | * OK, now because timegm() is not available in all environments, | |
72 | * we will do it by hand. Roll up sleeves, curse the gods, begin! | |
73 | */ | |
74 | ||
75 | #define SECS_PER_DAY ((u_int32_t)24*60*60) | |
76 | #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) | |
77 | ||
78 | result = time.tm_sec; /*%< Seconds */ | |
79 | result += time.tm_min * 60; /*%< Minutes */ | |
80 | result += time.tm_hour * (60*60); /*%< Hours */ | |
81 | result += (time.tm_mday - 1) * SECS_PER_DAY; /*%< Days */ | |
82 | /* Months are trickier. Look without leaping, then leap */ | |
83 | mdays = 0; | |
84 | for (i = 0; i < time.tm_mon; i++) | |
85 | mdays += days_per_month[i]; | |
86 | result += mdays * SECS_PER_DAY; /*%< Months */ | |
87 | if (time.tm_mon > 1 && isleap(1900+time.tm_year)) | |
88 | result += SECS_PER_DAY; /*%< Add leapday for this year */ | |
89 | /* First figure years without leapdays, then add them in. */ | |
90 | /* The loop is slow, FIXME, but simple and accurate. */ | |
91 | result += (time.tm_year - 70) * (SECS_PER_DAY*365); /*%< Years */ | |
92 | for (i = 70; i < time.tm_year; i++) | |
93 | if (isleap(1900+i)) | |
94 | result += SECS_PER_DAY; /*%< Add leapday for prev year */ | |
95 | return (result); | |
96 | } | |
97 | ||
98 | /* Private. */ | |
99 | ||
100 | /*% | |
101 | * Parse part of a date. Set error flag if any error. | |
102 | * Don't reset the flag if there is no error. | |
103 | */ | |
104 | static int | |
105 | datepart(const char *buf, int size, int min, int max, int *errp) { | |
106 | int result = 0; | |
107 | int i; | |
108 | ||
109 | for (i = 0; i < size; i++) { | |
110 | if (!isdigit((unsigned char)(buf[i]))) | |
111 | *errp = 1; | |
112 | result = (result * 10) + buf[i] - '0'; | |
113 | } | |
114 | if (result < min) | |
115 | *errp = 1; | |
116 | if (result > max) | |
117 | *errp = 1; | |
118 | return (result); | |
119 | } | |
120 | ||
121 | /*! \file */ |