localtime.c revision 1.127 1 1.127 christos /* $NetBSD: localtime.c,v 1.127 2022/03/22 17:48:39 christos Exp $ */
2 1.113 christos
3 1.113 christos /* Convert timestamp from time_t to struct tm. */
4 1.7 jtc
5 1.7 jtc /*
6 1.7 jtc ** This file is in the public domain, so clarified as of
7 1.45 mlelstv ** 1996-06-05 by Arthur David Olson.
8 1.7 jtc */
9 1.2 jtc
10 1.11 christos #include <sys/cdefs.h>
11 1.24 msaitoh #if defined(LIBC_SCCS) && !defined(lint)
12 1.11 christos #if 0
13 1.58 christos static char elsieid[] = "@(#)localtime.c 8.17";
14 1.11 christos #else
15 1.127 christos __RCSID("$NetBSD: localtime.c,v 1.127 2022/03/22 17:48:39 christos Exp $");
16 1.11 christos #endif
17 1.24 msaitoh #endif /* LIBC_SCCS and not lint */
18 1.1 jtc
19 1.1 jtc /*
20 1.45 mlelstv ** Leap second handling from Bradley White.
21 1.45 mlelstv ** POSIX-style TZ environment variable handling from Guy Harris.
22 1.1 jtc */
23 1.1 jtc
24 1.1 jtc /*LINTLIBRARY*/
25 1.1 jtc
26 1.12 jtc #include "namespace.h"
27 1.78 christos #include <assert.h>
28 1.87 christos #define LOCALTIME_IMPLEMENTATION
29 1.1 jtc #include "private.h"
30 1.87 christos
31 1.1 jtc #include "tzfile.h"
32 1.106 christos #include <fcntl.h>
33 1.12 jtc
34 1.42 christos #if defined(__weak_alias)
35 1.25 kleink __weak_alias(daylight,_daylight)
36 1.23 mycroft __weak_alias(tzname,_tzname)
37 1.12 jtc #endif
38 1.1 jtc
39 1.45 mlelstv #ifndef TZ_ABBR_MAX_LEN
40 1.45 mlelstv #define TZ_ABBR_MAX_LEN 16
41 1.45 mlelstv #endif /* !defined TZ_ABBR_MAX_LEN */
42 1.45 mlelstv
43 1.45 mlelstv #ifndef TZ_ABBR_CHAR_SET
44 1.45 mlelstv #define TZ_ABBR_CHAR_SET \
45 1.45 mlelstv "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
46 1.45 mlelstv #endif /* !defined TZ_ABBR_CHAR_SET */
47 1.45 mlelstv
48 1.45 mlelstv #ifndef TZ_ABBR_ERR_CHAR
49 1.45 mlelstv #define TZ_ABBR_ERR_CHAR '_'
50 1.45 mlelstv #endif /* !defined TZ_ABBR_ERR_CHAR */
51 1.45 mlelstv
52 1.1 jtc /*
53 1.1 jtc ** SunOS 4.1.1 headers lack O_BINARY.
54 1.1 jtc */
55 1.1 jtc
56 1.1 jtc #ifdef O_BINARY
57 1.86 christos #define OPEN_MODE (O_RDONLY | O_BINARY | O_CLOEXEC)
58 1.1 jtc #endif /* defined O_BINARY */
59 1.1 jtc #ifndef O_BINARY
60 1.86 christos #define OPEN_MODE (O_RDONLY | O_CLOEXEC)
61 1.1 jtc #endif /* !defined O_BINARY */
62 1.1 jtc
63 1.1 jtc #ifndef WILDABBR
64 1.1 jtc /*
65 1.1 jtc ** Someone might make incorrect use of a time zone abbreviation:
66 1.1 jtc ** 1. They might reference tzname[0] before calling tzset (explicitly
67 1.1 jtc ** or implicitly).
68 1.1 jtc ** 2. They might reference tzname[1] before calling tzset (explicitly
69 1.1 jtc ** or implicitly).
70 1.1 jtc ** 3. They might reference tzname[1] after setting to a time zone
71 1.1 jtc ** in which Daylight Saving Time is never observed.
72 1.1 jtc ** 4. They might reference tzname[0] after setting to a time zone
73 1.1 jtc ** in which Standard Time is never observed.
74 1.1 jtc ** 5. They might reference tm.TM_ZONE after calling offtime.
75 1.1 jtc ** What's best to do in the above cases is open to debate;
76 1.1 jtc ** for now, we just set things up so that in any of the five cases
77 1.45 mlelstv ** WILDABBR is used. Another possibility: initialize tzname[0] to the
78 1.1 jtc ** string "tzname[0] used before set", and similarly for the other cases.
79 1.45 mlelstv ** And another: initialize tzname[0] to "ERA", with an explanation in the
80 1.1 jtc ** manual page of what this "time zone abbreviation" means (doing this so
81 1.1 jtc ** that tzname[0] has the "normal" length of three characters).
82 1.1 jtc */
83 1.1 jtc #define WILDABBR " "
84 1.1 jtc #endif /* !defined WILDABBR */
85 1.1 jtc
86 1.45 mlelstv static const char wildabbr[] = WILDABBR;
87 1.1 jtc
88 1.71 christos static const char gmt[] = "GMT";
89 1.1 jtc
90 1.22 kleink /*
91 1.22 kleink ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
92 1.109 christos ** Default to US rules as of 2017-05-07.
93 1.112 christos ** POSIX does not specify the default DST rules;
94 1.112 christos ** for historical reasons, US rules are a common default.
95 1.22 kleink */
96 1.22 kleink #ifndef TZDEFRULESTRING
97 1.109 christos #define TZDEFRULESTRING ",M3.2.0,M11.1.0"
98 1.109 christos #endif
99 1.22 kleink
100 1.126 christos typedef int_fast64_t __time_t;
101 1.126 christos
102 1.1 jtc struct ttinfo { /* time type information */
103 1.122 christos int_fast32_t tt_utoff; /* UT offset in seconds */
104 1.87 christos bool tt_isdst; /* used to set tm_isdst */
105 1.122 christos int tt_desigidx; /* abbreviation list index */
106 1.87 christos bool tt_ttisstd; /* transition is std time */
107 1.122 christos bool tt_ttisut; /* transition is UT */
108 1.1 jtc };
109 1.1 jtc
110 1.1 jtc struct lsinfo { /* leap second information */
111 1.126 christos __time_t ls_trans; /* transition time */
112 1.124 christos int_fast32_t ls_corr; /* correction to apply */
113 1.1 jtc };
114 1.1 jtc
115 1.87 christos #define SMALLEST(a, b) (((a) < (b)) ? (a) : (b))
116 1.1 jtc #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
117 1.1 jtc
118 1.127 christos /* This abbreviation means local time is unspecified. */
119 1.127 christos static char const UNSPEC[] = "-00";
120 1.127 christos
121 1.127 christos /* How many extra bytes are needed at the end of struct state's chars array.
122 1.127 christos This needs to be at least 1 for null termination in case the input
123 1.127 christos data isn't properly terminated, and it also needs to be big enough
124 1.127 christos for ttunspecified to work without crashing. */
125 1.127 christos enum { CHARS_EXTRA = BIGGEST(sizeof UNSPEC, 2) - 1 };
126 1.127 christos
127 1.1 jtc #ifdef TZNAME_MAX
128 1.1 jtc #define MY_TZNAME_MAX TZNAME_MAX
129 1.1 jtc #endif /* defined TZNAME_MAX */
130 1.1 jtc #ifndef TZNAME_MAX
131 1.1 jtc #define MY_TZNAME_MAX 255
132 1.1 jtc #endif /* !defined TZNAME_MAX */
133 1.1 jtc
134 1.87 christos #define state __state
135 1.87 christos struct state {
136 1.1 jtc int leapcnt;
137 1.1 jtc int timecnt;
138 1.1 jtc int typecnt;
139 1.1 jtc int charcnt;
140 1.87 christos bool goback;
141 1.87 christos bool goahead;
142 1.126 christos __time_t ats[TZ_MAX_TIMES];
143 1.1 jtc unsigned char types[TZ_MAX_TIMES];
144 1.1 jtc struct ttinfo ttis[TZ_MAX_TYPES];
145 1.127 christos char chars[/*CONSTCOND*/
146 1.127 christos BIGGEST(BIGGEST(TZ_MAX_CHARS + CHARS_EXTRA,
147 1.127 christos sizeof gmt), (2 * (MY_TZNAME_MAX + 1)))];
148 1.1 jtc struct lsinfo lsis[TZ_MAX_LEAPS];
149 1.113 christos
150 1.113 christos /* The time type to use for early times or if no transitions.
151 1.113 christos It is always zero for recent tzdb releases.
152 1.113 christos It might be nonzero for data from tzdb 2018e or earlier. */
153 1.113 christos int defaulttype;
154 1.1 jtc };
155 1.1 jtc
156 1.96 christos enum r_type {
157 1.96 christos JULIAN_DAY, /* Jn = Julian day */
158 1.96 christos DAY_OF_YEAR, /* n = day of year */
159 1.96 christos MONTH_NTH_DAY_OF_WEEK /* Mm.n.d = month, week, day of week */
160 1.96 christos };
161 1.96 christos
162 1.1 jtc struct rule {
163 1.96 christos enum r_type r_type; /* type of rule */
164 1.1 jtc int r_day; /* day number of rule */
165 1.1 jtc int r_week; /* week number of rule */
166 1.1 jtc int r_mon; /* month number of rule */
167 1.74 christos int_fast32_t r_time; /* transition time of rule */
168 1.1 jtc };
169 1.1 jtc
170 1.87 christos static struct tm *gmtsub(struct state const *, time_t const *, int_fast32_t,
171 1.87 christos struct tm *);
172 1.87 christos static bool increment_overflow(int *, int);
173 1.126 christos static bool increment_overflow_time(__time_t *, int_fast32_t);
174 1.124 christos static int_fast32_t leapcorr(struct state const *, time_t);
175 1.87 christos static bool normalize_overflow32(int_fast32_t *, int *, int);
176 1.87 christos static struct tm *timesub(time_t const *, int_fast32_t, struct state const *,
177 1.87 christos struct tm *);
178 1.87 christos static bool typesequiv(struct state const *, int, int);
179 1.124 christos static bool tzparse(char const *, struct state *, struct state *);
180 1.1 jtc
181 1.49 christos static timezone_t gmtptr;
182 1.1 jtc
183 1.1 jtc #ifndef TZ_STRLEN_MAX
184 1.1 jtc #define TZ_STRLEN_MAX 255
185 1.1 jtc #endif /* !defined TZ_STRLEN_MAX */
186 1.1 jtc
187 1.45 mlelstv static char lcl_TZname[TZ_STRLEN_MAX + 1];
188 1.45 mlelstv static int lcl_is_set;
189 1.42 christos
190 1.42 christos
191 1.117 christos #if !defined(__LIBC12_SOURCE__)
192 1.117 christos timezone_t __lclptr;
193 1.33 christos #ifdef _REENTRANT
194 1.117 christos rwlock_t __lcl_lock = RWLOCK_INITIALIZER;
195 1.117 christos #endif
196 1.19 kleink #endif
197 1.19 kleink
198 1.1 jtc /*
199 1.1 jtc ** Section 4.12.3 of X3.159-1989 requires that
200 1.1 jtc ** Except for the strftime function, these functions [asctime,
201 1.1 jtc ** ctime, gmtime, localtime] return values in one of two static
202 1.1 jtc ** objects: a broken-down time structure and an array of char.
203 1.45 mlelstv ** Thanks to Paul Eggert for noting this.
204 1.1 jtc */
205 1.1 jtc
206 1.1 jtc static struct tm tm;
207 1.1 jtc
208 1.123 christos #if 2 <= HAVE_TZNAME + TZ_TIME_T || defined(__NetBSD__)
209 1.102 christos # if !defined(__LIBC12_SOURCE__)
210 1.102 christos
211 1.102 christos __aconst char * tzname[2] = {
212 1.102 christos (__aconst char *)__UNCONST(wildabbr),
213 1.102 christos (__aconst char *)__UNCONST(wildabbr)
214 1.102 christos };
215 1.102 christos
216 1.102 christos # else
217 1.102 christos
218 1.102 christos extern __aconst char * tzname[2];
219 1.102 christos
220 1.102 christos # endif /* __LIBC12_SOURCE__ */
221 1.123 christos #endif
222 1.102 christos
223 1.123 christos #if 2 <= USG_COMPAT + TZ_TIME_T || defined(__NetBSD__)
224 1.123 christos # if !defined(__LIBC12_SOURCE__)
225 1.42 christos long timezone = 0;
226 1.1 jtc int daylight = 0;
227 1.123 christos # else
228 1.42 christos extern int daylight;
229 1.42 christos extern long timezone __RENAME(__timezone13);
230 1.123 christos # endif /* __LIBC12_SOURCE__ */
231 1.123 christos #endif /* 2<= USG_COMPAT + TZ_TIME_T */
232 1.1 jtc
233 1.123 christos #if 2 <= ALTZONE + TZ_TIME_T
234 1.81 christos long altzone = 0;
235 1.123 christos #endif /* 2 <= ALTZONE + TZ_TIME_T */
236 1.1 jtc
237 1.122 christos /* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX. */
238 1.91 christos static void
239 1.122 christos init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
240 1.91 christos {
241 1.122 christos s->tt_utoff = utoff;
242 1.91 christos s->tt_isdst = isdst;
243 1.122 christos s->tt_desigidx = desigidx;
244 1.91 christos s->tt_ttisstd = false;
245 1.122 christos s->tt_ttisut = false;
246 1.91 christos }
247 1.91 christos
248 1.127 christos /* Return true if SP's time type I does not specify local time. */
249 1.127 christos static bool
250 1.127 christos ttunspecified(struct state const *sp, int i)
251 1.127 christos {
252 1.127 christos char const *abbr = &sp->chars[sp->ttis[i].tt_desigidx];
253 1.127 christos /* memcmp is likely faster than strcmp, and is safe due to CHARS_EXTRA. */
254 1.127 christos return memcmp(abbr, UNSPEC, sizeof UNSPEC) == 0;
255 1.127 christos }
256 1.127 christos
257 1.74 christos static int_fast32_t
258 1.49 christos detzcode(const char *const codep)
259 1.1 jtc {
260 1.95 christos int_fast32_t result;
261 1.95 christos int i;
262 1.95 christos int_fast32_t one = 1;
263 1.95 christos int_fast32_t halfmaxval = one << (32 - 2);
264 1.95 christos int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
265 1.95 christos int_fast32_t minval = -1 - maxval;
266 1.45 mlelstv
267 1.95 christos result = codep[0] & 0x7f;
268 1.95 christos for (i = 1; i < 4; ++i)
269 1.45 mlelstv result = (result << 8) | (codep[i] & 0xff);
270 1.95 christos
271 1.95 christos if (codep[0] & 0x80) {
272 1.95 christos /* Do two's-complement negation even on non-two's-complement machines.
273 1.95 christos If the result would be minval - 1, return minval. */
274 1.95 christos result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
275 1.95 christos result += minval;
276 1.95 christos }
277 1.95 christos return result;
278 1.45 mlelstv }
279 1.45 mlelstv
280 1.81 christos static int_fast64_t
281 1.49 christos detzcode64(const char *const codep)
282 1.45 mlelstv {
283 1.87 christos int_fast64_t result;
284 1.49 christos int i;
285 1.95 christos int_fast64_t one = 1;
286 1.95 christos int_fast64_t halfmaxval = one << (64 - 2);
287 1.95 christos int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
288 1.95 christos int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
289 1.1 jtc
290 1.95 christos result = codep[0] & 0x7f;
291 1.95 christos for (i = 1; i < 8; ++i)
292 1.81 christos result = (result << 8) | (codep[i] & 0xff);
293 1.95 christos
294 1.95 christos if (codep[0] & 0x80) {
295 1.95 christos /* Do two's-complement negation even on non-two's-complement machines.
296 1.95 christos If the result would be minval - 1, return minval. */
297 1.95 christos result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
298 1.95 christos result += minval;
299 1.95 christos }
300 1.95 christos return result;
301 1.1 jtc }
302 1.1 jtc
303 1.121 christos #include <stdio.h>
304 1.121 christos
305 1.49 christos const char *
306 1.49 christos tzgetname(const timezone_t sp, int isdst)
307 1.49 christos {
308 1.49 christos int i;
309 1.121 christos const char *name = NULL;
310 1.103 ginsbach for (i = 0; i < sp->typecnt; ++i) {
311 1.120 christos const struct ttinfo *const ttisp = &sp->ttis[i];
312 1.49 christos if (ttisp->tt_isdst == isdst)
313 1.122 christos name = &sp->chars[ttisp->tt_desigidx];
314 1.49 christos }
315 1.121 christos if (name != NULL)
316 1.121 christos return name;
317 1.88 christos errno = ESRCH;
318 1.49 christos return NULL;
319 1.49 christos }
320 1.49 christos
321 1.99 christos long
322 1.99 christos tzgetgmtoff(const timezone_t sp, int isdst)
323 1.99 christos {
324 1.99 christos int i;
325 1.99 christos long l = -1;
326 1.103 ginsbach for (i = 0; i < sp->typecnt; ++i) {
327 1.120 christos const struct ttinfo *const ttisp = &sp->ttis[i];
328 1.99 christos
329 1.99 christos if (ttisp->tt_isdst == isdst) {
330 1.122 christos l = ttisp->tt_utoff;
331 1.99 christos }
332 1.99 christos }
333 1.99 christos if (l == -1)
334 1.99 christos errno = ESRCH;
335 1.99 christos return l;
336 1.99 christos }
337 1.99 christos
338 1.49 christos static void
339 1.93 christos update_tzname_etc(const struct state *sp, const struct ttinfo *ttisp)
340 1.92 christos {
341 1.109 christos #if HAVE_TZNAME
342 1.122 christos tzname[ttisp->tt_isdst] = __UNCONST(&sp->chars[ttisp->tt_desigidx]);
343 1.109 christos #endif
344 1.109 christos #if USG_COMPAT
345 1.93 christos if (!ttisp->tt_isdst)
346 1.122 christos timezone = - ttisp->tt_utoff;
347 1.93 christos #endif
348 1.123 christos #if ALTZONE
349 1.93 christos if (ttisp->tt_isdst)
350 1.122 christos altzone = - ttisp->tt_utoff;
351 1.123 christos #endif /* ALTZONE */
352 1.92 christos }
353 1.92 christos
354 1.45 mlelstv static void
355 1.45 mlelstv settzname(void)
356 1.1 jtc {
357 1.117 christos timezone_t const sp = __lclptr;
358 1.49 christos int i;
359 1.1 jtc
360 1.109 christos #if HAVE_TZNAME
361 1.109 christos tzname[0] = tzname[1] =
362 1.109 christos (__aconst char *) __UNCONST(sp ? wildabbr : gmt);
363 1.109 christos #endif
364 1.109 christos #if USG_COMPAT
365 1.1 jtc daylight = 0;
366 1.1 jtc timezone = 0;
367 1.109 christos #endif
368 1.123 christos #if ALTZONE
369 1.1 jtc altzone = 0;
370 1.123 christos #endif
371 1.1 jtc if (sp == NULL) {
372 1.1 jtc return;
373 1.1 jtc }
374 1.58 christos /*
375 1.113 christos ** And to get the latest time zone abbreviations into tzname. . .
376 1.58 christos */
377 1.92 christos for (i = 0; i < sp->typecnt; ++i)
378 1.93 christos update_tzname_etc(sp, &sp->ttis[i]);
379 1.1 jtc
380 1.93 christos for (i = 0; i < sp->timecnt; ++i) {
381 1.93 christos const struct ttinfo * const ttisp = &sp->ttis[sp->types[i]];
382 1.93 christos update_tzname_etc(sp, ttisp);
383 1.109 christos #if USG_COMPAT
384 1.93 christos if (ttisp->tt_isdst)
385 1.93 christos daylight = 1;
386 1.109 christos #endif
387 1.93 christos }
388 1.1 jtc }
389 1.1 jtc
390 1.124 christos static void
391 1.124 christos scrub_abbrs(struct state *sp)
392 1.45 mlelstv {
393 1.124 christos int i;
394 1.124 christos /*
395 1.124 christos ** First, replace bogus characters.
396 1.124 christos */
397 1.124 christos for (i = 0; i < sp->charcnt; ++i)
398 1.124 christos if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
399 1.124 christos sp->chars[i] = TZ_ABBR_ERR_CHAR;
400 1.124 christos /*
401 1.124 christos ** Second, truncate long abbreviations.
402 1.124 christos */
403 1.124 christos for (i = 0; i < sp->typecnt; ++i) {
404 1.124 christos const struct ttinfo * const ttisp = &sp->ttis[i];
405 1.124 christos char *cp = &sp->chars[ttisp->tt_desigidx];
406 1.124 christos
407 1.124 christos if (strlen(cp) > TZ_ABBR_MAX_LEN &&
408 1.124 christos strcmp(cp, GRANDPARENTED) != 0)
409 1.124 christos *(cp + TZ_ABBR_MAX_LEN) = '\0';
410 1.124 christos }
411 1.45 mlelstv }
412 1.45 mlelstv
413 1.124 christos /* Input buffer for data read from a compiled tz file. */
414 1.91 christos union input_buffer {
415 1.91 christos /* The first part of the buffer, interpreted as a header. */
416 1.91 christos struct tzhead tzhead;
417 1.91 christos
418 1.91 christos /* The entire buffer. */
419 1.124 christos char buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
420 1.91 christos + 4 * TZ_MAX_TIMES];
421 1.91 christos };
422 1.91 christos
423 1.109 christos /* TZDIR with a trailing '/' rather than a trailing '\0'. */
424 1.109 christos static char const tzdirslash[sizeof TZDIR] = TZDIR "/";
425 1.109 christos
426 1.91 christos /* Local storage needed for 'tzloadbody'. */
427 1.91 christos union local_storage {
428 1.91 christos /* The results of analyzing the file's contents after it is opened. */
429 1.109 christos struct file_analysis {
430 1.91 christos /* The input buffer. */
431 1.91 christos union input_buffer u;
432 1.91 christos
433 1.91 christos /* A temporary state used for parsing a TZ string in the file. */
434 1.91 christos struct state st;
435 1.91 christos } u;
436 1.109 christos
437 1.109 christos /* The file name to be opened. */
438 1.124 christos char fullname[/*CONSTCOND*/BIGGEST(sizeof(struct file_analysis),
439 1.109 christos sizeof tzdirslash + 1024)];
440 1.91 christos };
441 1.91 christos
442 1.91 christos /* Load tz data from the file named NAME into *SP. Read extended
443 1.91 christos format if DOEXTEND. Use *LSP for temporary storage. Return 0 on
444 1.91 christos success, an errno value on failure. */
445 1.91 christos static int
446 1.91 christos tzloadbody(char const *name, struct state *sp, bool doextend,
447 1.91 christos union local_storage *lsp)
448 1.49 christos {
449 1.49 christos int i;
450 1.49 christos int fid;
451 1.49 christos int stored;
452 1.66 christos ssize_t nread;
453 1.91 christos bool doaccess;
454 1.91 christos union input_buffer *up = &lsp->u.u;
455 1.91 christos size_t tzheadsize = sizeof(struct tzhead);
456 1.83 christos
457 1.87 christos sp->goback = sp->goahead = false;
458 1.83 christos
459 1.83 christos if (! name) {
460 1.83 christos name = TZDEFAULT;
461 1.83 christos if (! name)
462 1.91 christos return EINVAL;
463 1.83 christos }
464 1.83 christos
465 1.83 christos if (name[0] == ':')
466 1.83 christos ++name;
467 1.112 christos #ifdef SUPPRESS_TZDIR
468 1.112 christos /* Do not prepend TZDIR. This is intended for specialized
469 1.112 christos applications only, due to its security implications. */
470 1.112 christos doaccess = true;
471 1.112 christos #else
472 1.83 christos doaccess = name[0] == '/';
473 1.112 christos #endif
474 1.83 christos if (!doaccess) {
475 1.114 christos char const *dot;
476 1.109 christos size_t namelen = strlen(name);
477 1.109 christos if (sizeof lsp->fullname - sizeof tzdirslash <= namelen)
478 1.91 christos return ENAMETOOLONG;
479 1.109 christos
480 1.109 christos /* Create a string "TZDIR/NAME". Using sprintf here
481 1.109 christos would pull in stdio (and would fail if the
482 1.109 christos resulting string length exceeded INT_MAX!). */
483 1.109 christos memcpy(lsp->fullname, tzdirslash, sizeof tzdirslash);
484 1.109 christos strcpy(lsp->fullname + sizeof tzdirslash, name);
485 1.109 christos
486 1.114 christos /* Set doaccess if NAME contains a ".." file name
487 1.114 christos component, as such a name could read a file outside
488 1.114 christos the TZDIR virtual subtree. */
489 1.117 christos for (dot = name; (dot = strchr(dot, '.')) != NULL; dot++)
490 1.114 christos if ((dot == name || dot[-1] == '/') && dot[1] == '.'
491 1.114 christos && (dot[2] == '/' || !dot[2])) {
492 1.114 christos doaccess = true;
493 1.114 christos break;
494 1.114 christos }
495 1.114 christos
496 1.110 kre name = lsp->fullname;
497 1.1 jtc }
498 1.83 christos if (doaccess && access(name, R_OK) != 0)
499 1.91 christos return errno;
500 1.83 christos fid = open(name, OPEN_MODE);
501 1.83 christos if (fid < 0)
502 1.91 christos return errno;
503 1.124 christos
504 1.58 christos nread = read(fid, up->buf, sizeof up->buf);
505 1.91 christos if (nread < (ssize_t)tzheadsize) {
506 1.91 christos int err = nread < 0 ? errno : EINVAL;
507 1.91 christos close(fid);
508 1.91 christos return err;
509 1.91 christos }
510 1.91 christos if (close(fid) < 0)
511 1.91 christos return errno;
512 1.45 mlelstv for (stored = 4; stored <= 8; stored *= 2) {
513 1.127 christos char version = up->tzhead.tzh_version[0];
514 1.127 christos bool skip_datablock = stored == 4 && version;
515 1.127 christos int_fast32_t datablock_size;
516 1.127 christos int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
517 1.127 christos int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
518 1.127 christos int_fast64_t prevtr = -1;
519 1.127 christos int_fast32_t prevcorr = 0;
520 1.127 christos int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
521 1.127 christos int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
522 1.127 christos int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
523 1.127 christos int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
524 1.127 christos char const *p = up->buf + tzheadsize;
525 1.127 christos /* Although tzfile(5) currently requires typecnt to be nonzero,
526 1.127 christos support future formats that may allow zero typecnt
527 1.127 christos in files that have a TZ string and no transitions. */
528 1.127 christos if (! (0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
529 1.127 christos && 0 <= typecnt && typecnt < TZ_MAX_TYPES
530 1.127 christos && 0 <= timecnt && timecnt < TZ_MAX_TIMES
531 1.127 christos && 0 <= charcnt && charcnt < TZ_MAX_CHARS
532 1.127 christos && 0 <= ttisstdcnt && ttisstdcnt < TZ_MAX_TYPES
533 1.127 christos && 0 <= ttisutcnt && ttisutcnt < TZ_MAX_TYPES))
534 1.127 christos return EINVAL;
535 1.127 christos datablock_size
536 1.127 christos = (timecnt * stored /* ats */
537 1.87 christos + timecnt /* types */
538 1.87 christos + typecnt * 6 /* ttinfos */
539 1.87 christos + charcnt /* chars */
540 1.87 christos + leapcnt * (stored + 4) /* lsinfos */
541 1.87 christos + ttisstdcnt /* ttisstds */
542 1.127 christos + ttisutcnt); /* ttisuts */
543 1.127 christos if (nread < (ssize_t)(tzheadsize + datablock_size))
544 1.127 christos return EINVAL;
545 1.127 christos if (skip_datablock)
546 1.127 christos p += datablock_size;
547 1.127 christos else {
548 1.127 christos if (! ((ttisstdcnt == typecnt || ttisstdcnt == 0)
549 1.127 christos && (ttisutcnt == typecnt || ttisutcnt == 0)))
550 1.91 christos return EINVAL;
551 1.127 christos
552 1.87 christos sp->leapcnt = leapcnt;
553 1.87 christos sp->timecnt = timecnt;
554 1.87 christos sp->typecnt = typecnt;
555 1.87 christos sp->charcnt = charcnt;
556 1.87 christos
557 1.87 christos /* Read transitions, discarding those out of time_t range.
558 1.109 christos But pretend the last transition before TIME_T_MIN
559 1.109 christos occurred at TIME_T_MIN. */
560 1.81 christos timecnt = 0;
561 1.1 jtc for (i = 0; i < sp->timecnt; ++i) {
562 1.81 christos int_fast64_t at
563 1.81 christos = stored == 4 ? detzcode(p) : detzcode64(p);
564 1.109 christos sp->types[i] = at <= TIME_T_MAX;
565 1.81 christos if (sp->types[i]) {
566 1.87 christos time_t attime
567 1.87 christos = ((TYPE_SIGNED(time_t) ?
568 1.109 christos at < TIME_T_MIN : at < 0)
569 1.109 christos ? TIME_T_MIN : (time_t)at);
570 1.87 christos if (timecnt && attime <= sp->ats[timecnt - 1]) {
571 1.87 christos if (attime < sp->ats[timecnt - 1])
572 1.91 christos return EINVAL;
573 1.87 christos sp->types[i - 1] = 0;
574 1.87 christos timecnt--;
575 1.81 christos }
576 1.87 christos sp->ats[timecnt++] = attime;
577 1.81 christos }
578 1.45 mlelstv p += stored;
579 1.1 jtc }
580 1.87 christos
581 1.81 christos timecnt = 0;
582 1.1 jtc for (i = 0; i < sp->timecnt; ++i) {
583 1.81 christos unsigned char typ = *p++;
584 1.81 christos if (sp->typecnt <= typ)
585 1.91 christos return EINVAL;
586 1.81 christos if (sp->types[i])
587 1.81 christos sp->types[timecnt++] = typ;
588 1.1 jtc }
589 1.87 christos sp->timecnt = timecnt;
590 1.1 jtc for (i = 0; i < sp->typecnt; ++i) {
591 1.49 christos struct ttinfo * ttisp;
592 1.122 christos unsigned char isdst, desigidx;
593 1.1 jtc
594 1.1 jtc ttisp = &sp->ttis[i];
595 1.122 christos ttisp->tt_utoff = detzcode(p);
596 1.1 jtc p += 4;
597 1.87 christos isdst = *p++;
598 1.87 christos if (! (isdst < 2))
599 1.91 christos return EINVAL;
600 1.87 christos ttisp->tt_isdst = isdst;
601 1.122 christos desigidx = *p++;
602 1.122 christos if (! (desigidx < sp->charcnt))
603 1.91 christos return EINVAL;
604 1.122 christos ttisp->tt_desigidx = desigidx;
605 1.1 jtc }
606 1.1 jtc for (i = 0; i < sp->charcnt; ++i)
607 1.1 jtc sp->chars[i] = *p++;
608 1.127 christos /* Ensure '\0'-terminated, and make it safe to call
609 1.127 christos ttunspecified later. */
610 1.127 christos memset(&sp->chars[i], 0, CHARS_EXTRA);
611 1.87 christos
612 1.87 christos /* Read leap seconds, discarding those out of time_t range. */
613 1.87 christos leapcnt = 0;
614 1.1 jtc for (i = 0; i < sp->leapcnt; ++i) {
615 1.87 christos int_fast64_t tr = stored == 4 ? detzcode(p) :
616 1.87 christos detzcode64(p);
617 1.87 christos int_fast32_t corr = detzcode(p + stored);
618 1.87 christos p += stored + 4;
619 1.125 christos
620 1.124 christos /* Leap seconds cannot occur before the Epoch,
621 1.124 christos or out of order. */
622 1.124 christos if (tr <= prevtr)
623 1.109 christos return EINVAL;
624 1.127 christos
625 1.125 christos /* To avoid other botches in this code, each leap second's
626 1.125 christos correction must differ from the previous one's by 1
627 1.125 christos second or less, except that the first correction can be
628 1.125 christos any value; these requirements are more generous than
629 1.125 christos RFC 8536, to allow future RFC extensions. */
630 1.124 christos if (! (i == 0
631 1.124 christos || (prevcorr < corr
632 1.124 christos ? corr == prevcorr + 1
633 1.124 christos : (corr == prevcorr
634 1.124 christos || corr == prevcorr - 1))))
635 1.125 christos return EINVAL;
636 1.125 christos prevtr = tr;
637 1.125 christos prevcorr = corr;
638 1.127 christos
639 1.125 christos if (tr <= TIME_T_MAX) {
640 1.125 christos sp->lsis[leapcnt].ls_trans = (time_t)tr;
641 1.125 christos sp->lsis[leapcnt].ls_corr = corr;
642 1.87 christos leapcnt++;
643 1.87 christos }
644 1.87 christos }
645 1.87 christos sp->leapcnt = leapcnt;
646 1.1 jtc
647 1.1 jtc for (i = 0; i < sp->typecnt; ++i) {
648 1.49 christos struct ttinfo * ttisp;
649 1.1 jtc
650 1.1 jtc ttisp = &sp->ttis[i];
651 1.1 jtc if (ttisstdcnt == 0)
652 1.87 christos ttisp->tt_ttisstd = false;
653 1.1 jtc else {
654 1.87 christos if (*p != true && *p != false)
655 1.91 christos return EINVAL;
656 1.1 jtc ttisp->tt_ttisstd = *p++;
657 1.1 jtc }
658 1.1 jtc }
659 1.1 jtc for (i = 0; i < sp->typecnt; ++i) {
660 1.49 christos struct ttinfo * ttisp;
661 1.1 jtc
662 1.1 jtc ttisp = &sp->ttis[i];
663 1.122 christos if (ttisutcnt == 0)
664 1.122 christos ttisp->tt_ttisut = false;
665 1.1 jtc else {
666 1.87 christos if (*p != true && *p != false)
667 1.91 christos return EINVAL;
668 1.122 christos ttisp->tt_ttisut = *p++;
669 1.1 jtc }
670 1.1 jtc }
671 1.58 christos nread -= p - up->buf;
672 1.91 christos memmove(up->buf, p, (size_t)nread);
673 1.127 christos }
674 1.127 christos
675 1.127 christos /* If this is an old file, we're done. */
676 1.127 christos if (!version)
677 1.127 christos break;
678 1.45 mlelstv }
679 1.45 mlelstv if (doextend && nread > 2 &&
680 1.58 christos up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
681 1.45 mlelstv sp->typecnt + 2 <= TZ_MAX_TYPES) {
682 1.87 christos struct state *ts = &lsp->u.st;
683 1.45 mlelstv
684 1.58 christos up->buf[nread - 1] = '\0';
685 1.124 christos if (tzparse(&up->buf[1], ts, sp)) {
686 1.98 christos
687 1.98 christos /* Attempt to reuse existing abbreviations.
688 1.106 christos Without this, America/Anchorage would be right on
689 1.106 christos the edge after 2037 when TZ_MAX_CHARS is 50, as
690 1.106 christos sp->charcnt equals 40 (for LMT AST AWT APT AHST
691 1.98 christos AHDT YST AKDT AKST) and ts->charcnt equals 10
692 1.98 christos (for AKST AKDT). Reusing means sp->charcnt can
693 1.106 christos stay 40 in this example. */
694 1.98 christos int gotabbr = 0;
695 1.98 christos int charcnt = sp->charcnt;
696 1.113 christos for (i = 0; i < ts->typecnt; i++) {
697 1.122 christos char *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
698 1.98 christos int j;
699 1.98 christos for (j = 0; j < charcnt; j++)
700 1.98 christos if (strcmp(sp->chars + j, tsabbr) == 0) {
701 1.122 christos ts->ttis[i].tt_desigidx = j;
702 1.98 christos gotabbr++;
703 1.98 christos break;
704 1.98 christos }
705 1.98 christos if (! (j < charcnt)) {
706 1.99 christos size_t tsabbrlen = strlen(tsabbr);
707 1.98 christos if (j + tsabbrlen < TZ_MAX_CHARS) {
708 1.98 christos strcpy(sp->chars + j, tsabbr);
709 1.100 christos charcnt = (int_fast32_t)(j + tsabbrlen + 1);
710 1.122 christos ts->ttis[i].tt_desigidx = j;
711 1.98 christos gotabbr++;
712 1.98 christos }
713 1.98 christos }
714 1.98 christos }
715 1.113 christos if (gotabbr == ts->typecnt) {
716 1.98 christos sp->charcnt = charcnt;
717 1.106 christos
718 1.106 christos /* Ignore any trailing, no-op transitions generated
719 1.106 christos by zic as they don't help here and can run afoul
720 1.106 christos of bugs in zic 2016j or earlier. */
721 1.106 christos while (1 < sp->timecnt
722 1.106 christos && (sp->types[sp->timecnt - 1]
723 1.106 christos == sp->types[sp->timecnt - 2]))
724 1.106 christos sp->timecnt--;
725 1.106 christos
726 1.124 christos for (i = 0;
727 1.124 christos i < ts->timecnt && sp->timecnt < TZ_MAX_TIMES;
728 1.124 christos i++) {
729 1.126 christos __time_t t = ts->ats[i];
730 1.124 christos if (increment_overflow_time(&t, leapcorr(sp, t))
731 1.124 christos || (0 < sp->timecnt
732 1.124 christos && t <= sp->ats[sp->timecnt - 1]))
733 1.124 christos continue;
734 1.124 christos sp->ats[sp->timecnt] = t;
735 1.98 christos sp->types[sp->timecnt] = (sp->typecnt
736 1.98 christos + ts->types[i]);
737 1.98 christos sp->timecnt++;
738 1.98 christos }
739 1.113 christos for (i = 0; i < ts->typecnt; i++)
740 1.113 christos sp->ttis[sp->typecnt++] = ts->ttis[i];
741 1.98 christos }
742 1.45 mlelstv }
743 1.45 mlelstv }
744 1.113 christos if (sp->typecnt == 0)
745 1.113 christos return EINVAL;
746 1.45 mlelstv if (sp->timecnt > 1) {
747 1.124 christos if (sp->ats[0] <= (time_t)(TIME_T_MAX - SECSPERREPEAT)) {
748 1.124 christos time_t repeatat = (time_t)(sp->ats[0] + SECSPERREPEAT);
749 1.124 christos int repeattype = sp->types[0];
750 1.45 mlelstv for (i = 1; i < sp->timecnt; ++i)
751 1.124 christos if (sp->ats[i] == repeatat
752 1.124 christos && typesequiv(sp, sp->types[i], repeattype)) {
753 1.87 christos sp->goback = true;
754 1.45 mlelstv break;
755 1.124 christos }
756 1.124 christos }
757 1.124 christos if ((time_t)(TIME_T_MIN + SECSPERREPEAT) <= sp->ats[sp->timecnt - 1]) {
758 1.124 christos time_t repeatat =
759 1.124 christos (time_t)(sp->ats[sp->timecnt - 1] - SECSPERREPEAT);
760 1.124 christos int repeattype = sp->types[sp->timecnt - 1];
761 1.45 mlelstv for (i = sp->timecnt - 2; i >= 0; --i)
762 1.124 christos if (sp->ats[i] == repeatat
763 1.124 christos && typesequiv(sp, sp->types[i], repeattype)) {
764 1.87 christos sp->goahead = true;
765 1.45 mlelstv break;
766 1.124 christos }
767 1.124 christos }
768 1.1 jtc }
769 1.113 christos
770 1.113 christos /* Infer sp->defaulttype from the data. Although this default
771 1.113 christos type is always zero for data from recent tzdb releases,
772 1.113 christos things are trickier for data from tzdb 2018e or earlier.
773 1.113 christos
774 1.113 christos The first set of heuristics work around bugs in 32-bit data
775 1.113 christos generated by tzdb 2013c or earlier. The workaround is for
776 1.113 christos zones like Australia/Macquarie where timestamps before the
777 1.113 christos first transition have a time type that is not the earliest
778 1.113 christos standard-time type. See:
779 1.113 christos https://mm.icann.org/pipermail/tz/2013-May/019368.html */
780 1.74 christos /*
781 1.127 christos ** If type 0 does not specify local time, or is unused in transitions,
782 1.74 christos ** it's the type to use for early times.
783 1.74 christos */
784 1.87 christos for (i = 0; i < sp->timecnt; ++i)
785 1.74 christos if (sp->types[i] == 0)
786 1.74 christos break;
787 1.127 christos i = i < sp->timecnt && ! ttunspecified(sp, 0) ? -1 : 0;
788 1.74 christos /*
789 1.74 christos ** Absent the above,
790 1.74 christos ** if there are transition times
791 1.74 christos ** and the first transition is to a daylight time
792 1.74 christos ** find the standard type less than and closest to
793 1.74 christos ** the type of the first transition.
794 1.74 christos */
795 1.74 christos if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst) {
796 1.74 christos i = sp->types[0];
797 1.74 christos while (--i >= 0)
798 1.74 christos if (!sp->ttis[i].tt_isdst)
799 1.74 christos break;
800 1.74 christos }
801 1.113 christos /* The next heuristics are for data generated by tzdb 2018e or
802 1.113 christos earlier, for zones like EST5EDT where the first transition
803 1.113 christos is to DST. */
804 1.74 christos /*
805 1.74 christos ** If no result yet, find the first standard type.
806 1.74 christos ** If there is none, punt to type zero.
807 1.74 christos */
808 1.74 christos if (i < 0) {
809 1.74 christos i = 0;
810 1.74 christos while (sp->ttis[i].tt_isdst)
811 1.74 christos if (++i >= sp->typecnt) {
812 1.74 christos i = 0;
813 1.74 christos break;
814 1.74 christos }
815 1.74 christos }
816 1.113 christos /* A simple 'sp->defaulttype = 0;' would suffice here if we
817 1.113 christos didn't have to worry about 2018e-or-earlier data. Even
818 1.113 christos simpler would be to remove the defaulttype member and just
819 1.113 christos use 0 in its place. */
820 1.74 christos sp->defaulttype = i;
821 1.113 christos
822 1.91 christos return 0;
823 1.91 christos }
824 1.91 christos
825 1.91 christos /* Load tz data from the file named NAME into *SP. Read extended
826 1.91 christos format if DOEXTEND. Return 0 on success, an errno value on failure. */
827 1.91 christos static int
828 1.91 christos tzload(char const *name, struct state *sp, bool doextend)
829 1.91 christos {
830 1.91 christos union local_storage *lsp = malloc(sizeof *lsp);
831 1.124 christos if (!lsp) {
832 1.124 christos return /*CONSTCOND*/HAVE_MALLOC_ERRNO ? errno : ENOMEM;
833 1.124 christos } else {
834 1.91 christos int err = tzloadbody(name, sp, doextend, lsp);
835 1.91 christos free(lsp);
836 1.91 christos return err;
837 1.91 christos }
838 1.1 jtc }
839 1.1 jtc
840 1.87 christos static bool
841 1.96 christos typesequiv(const struct state *sp, int a, int b)
842 1.45 mlelstv {
843 1.87 christos bool result;
844 1.45 mlelstv
845 1.45 mlelstv if (sp == NULL ||
846 1.45 mlelstv a < 0 || a >= sp->typecnt ||
847 1.45 mlelstv b < 0 || b >= sp->typecnt)
848 1.87 christos result = false;
849 1.45 mlelstv else {
850 1.49 christos const struct ttinfo * ap = &sp->ttis[a];
851 1.49 christos const struct ttinfo * bp = &sp->ttis[b];
852 1.122 christos result = (ap->tt_utoff == bp->tt_utoff
853 1.122 christos && ap->tt_isdst == bp->tt_isdst
854 1.122 christos && ap->tt_ttisstd == bp->tt_ttisstd
855 1.122 christos && ap->tt_ttisut == bp->tt_ttisut
856 1.122 christos && (strcmp(&sp->chars[ap->tt_desigidx],
857 1.122 christos &sp->chars[bp->tt_desigidx])
858 1.122 christos == 0));
859 1.45 mlelstv }
860 1.45 mlelstv return result;
861 1.45 mlelstv }
862 1.45 mlelstv
863 1.1 jtc static const int mon_lengths[2][MONSPERYEAR] = {
864 1.1 jtc { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
865 1.1 jtc { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
866 1.1 jtc };
867 1.1 jtc
868 1.1 jtc static const int year_lengths[2] = {
869 1.1 jtc DAYSPERNYEAR, DAYSPERLYEAR
870 1.1 jtc };
871 1.1 jtc
872 1.124 christos /* Is C an ASCII digit? */
873 1.124 christos static bool
874 1.124 christos is_digit(char c)
875 1.124 christos {
876 1.124 christos return '0' <= c && c <= '9';
877 1.124 christos }
878 1.124 christos
879 1.1 jtc /*
880 1.113 christos ** Given a pointer into a timezone string, scan until a character that is not
881 1.113 christos ** a valid character in a time zone abbreviation is found.
882 1.113 christos ** Return a pointer to that character.
883 1.1 jtc */
884 1.1 jtc
885 1.114 christos static ATTRIBUTE_PURE const char *
886 1.67 matt getzname(const char *strp)
887 1.1 jtc {
888 1.49 christos char c;
889 1.1 jtc
890 1.5 jtc while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
891 1.1 jtc c != '+')
892 1.1 jtc ++strp;
893 1.1 jtc return strp;
894 1.1 jtc }
895 1.1 jtc
896 1.1 jtc /*
897 1.113 christos ** Given a pointer into an extended timezone string, scan until the ending
898 1.113 christos ** delimiter of the time zone abbreviation is located.
899 1.113 christos ** Return a pointer to the delimiter.
900 1.45 mlelstv **
901 1.45 mlelstv ** As with getzname above, the legal character set is actually quite
902 1.45 mlelstv ** restricted, with other characters producing undefined results.
903 1.45 mlelstv ** We don't do any checking here; checking is done later in common-case code.
904 1.45 mlelstv */
905 1.45 mlelstv
906 1.114 christos static ATTRIBUTE_PURE const char *
907 1.49 christos getqzname(const char *strp, const int delim)
908 1.45 mlelstv {
909 1.49 christos int c;
910 1.45 mlelstv
911 1.45 mlelstv while ((c = *strp) != '\0' && c != delim)
912 1.45 mlelstv ++strp;
913 1.45 mlelstv return strp;
914 1.45 mlelstv }
915 1.45 mlelstv
916 1.45 mlelstv /*
917 1.113 christos ** Given a pointer into a timezone string, extract a number from that string.
918 1.1 jtc ** Check that the number is within a specified range; if it is not, return
919 1.1 jtc ** NULL.
920 1.1 jtc ** Otherwise, return a pointer to the first character not part of the number.
921 1.1 jtc */
922 1.1 jtc
923 1.1 jtc static const char *
924 1.68 christos getnum(const char *strp, int *const nump, const int min, const int max)
925 1.1 jtc {
926 1.49 christos char c;
927 1.49 christos int num;
928 1.1 jtc
929 1.46 christos if (strp == NULL || !is_digit(c = *strp)) {
930 1.46 christos errno = EINVAL;
931 1.1 jtc return NULL;
932 1.46 christos }
933 1.1 jtc num = 0;
934 1.5 jtc do {
935 1.1 jtc num = num * 10 + (c - '0');
936 1.46 christos if (num > max) {
937 1.46 christos errno = EOVERFLOW;
938 1.1 jtc return NULL; /* illegal value */
939 1.46 christos }
940 1.5 jtc c = *++strp;
941 1.5 jtc } while (is_digit(c));
942 1.46 christos if (num < min) {
943 1.46 christos errno = EINVAL;
944 1.1 jtc return NULL; /* illegal value */
945 1.46 christos }
946 1.1 jtc *nump = num;
947 1.1 jtc return strp;
948 1.1 jtc }
949 1.1 jtc
950 1.1 jtc /*
951 1.113 christos ** Given a pointer into a timezone string, extract a number of seconds,
952 1.1 jtc ** in hh[:mm[:ss]] form, from the string.
953 1.1 jtc ** If any error occurs, return NULL.
954 1.1 jtc ** Otherwise, return a pointer to the first character not part of the number
955 1.1 jtc ** of seconds.
956 1.1 jtc */
957 1.1 jtc
958 1.1 jtc static const char *
959 1.74 christos getsecs(const char *strp, int_fast32_t *const secsp)
960 1.1 jtc {
961 1.1 jtc int num;
962 1.124 christos int_fast32_t secsperhour = SECSPERHOUR;
963 1.1 jtc
964 1.1 jtc /*
965 1.83 christos ** 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
966 1.1 jtc ** "M10.4.6/26", which does not conform to Posix,
967 1.1 jtc ** but which specifies the equivalent of
968 1.83 christos ** "02:00 on the first Sunday on or after 23 Oct".
969 1.1 jtc */
970 1.1 jtc strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
971 1.1 jtc if (strp == NULL)
972 1.1 jtc return NULL;
973 1.124 christos *secsp = num * secsperhour;
974 1.1 jtc if (*strp == ':') {
975 1.1 jtc ++strp;
976 1.1 jtc strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
977 1.1 jtc if (strp == NULL)
978 1.1 jtc return NULL;
979 1.1 jtc *secsp += num * SECSPERMIN;
980 1.1 jtc if (*strp == ':') {
981 1.1 jtc ++strp;
982 1.83 christos /* 'SECSPERMIN' allows for leap seconds. */
983 1.1 jtc strp = getnum(strp, &num, 0, SECSPERMIN);
984 1.1 jtc if (strp == NULL)
985 1.1 jtc return NULL;
986 1.1 jtc *secsp += num;
987 1.1 jtc }
988 1.1 jtc }
989 1.1 jtc return strp;
990 1.1 jtc }
991 1.1 jtc
992 1.1 jtc /*
993 1.113 christos ** Given a pointer into a timezone string, extract an offset, in
994 1.1 jtc ** [+-]hh[:mm[:ss]] form, from the string.
995 1.1 jtc ** If any error occurs, return NULL.
996 1.1 jtc ** Otherwise, return a pointer to the first character not part of the time.
997 1.1 jtc */
998 1.1 jtc
999 1.1 jtc static const char *
1000 1.74 christos getoffset(const char *strp, int_fast32_t *const offsetp)
1001 1.1 jtc {
1002 1.87 christos bool neg = false;
1003 1.1 jtc
1004 1.1 jtc if (*strp == '-') {
1005 1.87 christos neg = true;
1006 1.1 jtc ++strp;
1007 1.5 jtc } else if (*strp == '+')
1008 1.5 jtc ++strp;
1009 1.1 jtc strp = getsecs(strp, offsetp);
1010 1.1 jtc if (strp == NULL)
1011 1.1 jtc return NULL; /* illegal time */
1012 1.1 jtc if (neg)
1013 1.1 jtc *offsetp = -*offsetp;
1014 1.1 jtc return strp;
1015 1.1 jtc }
1016 1.1 jtc
1017 1.1 jtc /*
1018 1.113 christos ** Given a pointer into a timezone string, extract a rule in the form
1019 1.45 mlelstv ** date[/time]. See POSIX section 8 for the format of "date" and "time".
1020 1.1 jtc ** If a valid rule is not found, return NULL.
1021 1.1 jtc ** Otherwise, return a pointer to the first character not part of the rule.
1022 1.1 jtc */
1023 1.1 jtc
1024 1.1 jtc static const char *
1025 1.49 christos getrule(const char *strp, struct rule *const rulep)
1026 1.1 jtc {
1027 1.1 jtc if (*strp == 'J') {
1028 1.1 jtc /*
1029 1.1 jtc ** Julian day.
1030 1.1 jtc */
1031 1.1 jtc rulep->r_type = JULIAN_DAY;
1032 1.1 jtc ++strp;
1033 1.1 jtc strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1034 1.1 jtc } else if (*strp == 'M') {
1035 1.1 jtc /*
1036 1.1 jtc ** Month, week, day.
1037 1.1 jtc */
1038 1.1 jtc rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1039 1.1 jtc ++strp;
1040 1.1 jtc strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1041 1.1 jtc if (strp == NULL)
1042 1.1 jtc return NULL;
1043 1.1 jtc if (*strp++ != '.')
1044 1.1 jtc return NULL;
1045 1.1 jtc strp = getnum(strp, &rulep->r_week, 1, 5);
1046 1.1 jtc if (strp == NULL)
1047 1.1 jtc return NULL;
1048 1.1 jtc if (*strp++ != '.')
1049 1.1 jtc return NULL;
1050 1.1 jtc strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1051 1.5 jtc } else if (is_digit(*strp)) {
1052 1.1 jtc /*
1053 1.1 jtc ** Day of year.
1054 1.1 jtc */
1055 1.1 jtc rulep->r_type = DAY_OF_YEAR;
1056 1.1 jtc strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1057 1.1 jtc } else return NULL; /* invalid format */
1058 1.1 jtc if (strp == NULL)
1059 1.1 jtc return NULL;
1060 1.1 jtc if (*strp == '/') {
1061 1.1 jtc /*
1062 1.1 jtc ** Time specified.
1063 1.1 jtc */
1064 1.1 jtc ++strp;
1065 1.78 christos strp = getoffset(strp, &rulep->r_time);
1066 1.1 jtc } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
1067 1.1 jtc return strp;
1068 1.1 jtc }
1069 1.1 jtc
1070 1.1 jtc /*
1071 1.81 christos ** Given a year, a rule, and the offset from UT at the time that rule takes
1072 1.81 christos ** effect, calculate the year-relative time that rule takes effect.
1073 1.1 jtc */
1074 1.1 jtc
1075 1.109 christos static int_fast32_t
1076 1.81 christos transtime(const int year, const struct rule *const rulep,
1077 1.81 christos const int_fast32_t offset)
1078 1.49 christos {
1079 1.87 christos bool leapyear;
1080 1.87 christos int_fast32_t value;
1081 1.49 christos int i;
1082 1.1 jtc int d, m1, yy0, yy1, yy2, dow;
1083 1.1 jtc
1084 1.1 jtc leapyear = isleap(year);
1085 1.1 jtc switch (rulep->r_type) {
1086 1.1 jtc
1087 1.1 jtc case JULIAN_DAY:
1088 1.1 jtc /*
1089 1.1 jtc ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1090 1.1 jtc ** years.
1091 1.1 jtc ** In non-leap years, or if the day number is 59 or less, just
1092 1.1 jtc ** add SECSPERDAY times the day number-1 to the time of
1093 1.1 jtc ** January 1, midnight, to get the day.
1094 1.1 jtc */
1095 1.81 christos value = (rulep->r_day - 1) * SECSPERDAY;
1096 1.1 jtc if (leapyear && rulep->r_day >= 60)
1097 1.1 jtc value += SECSPERDAY;
1098 1.1 jtc break;
1099 1.1 jtc
1100 1.1 jtc case DAY_OF_YEAR:
1101 1.1 jtc /*
1102 1.1 jtc ** n - day of year.
1103 1.1 jtc ** Just add SECSPERDAY times the day number to the time of
1104 1.1 jtc ** January 1, midnight, to get the day.
1105 1.1 jtc */
1106 1.81 christos value = rulep->r_day * SECSPERDAY;
1107 1.1 jtc break;
1108 1.1 jtc
1109 1.1 jtc case MONTH_NTH_DAY_OF_WEEK:
1110 1.1 jtc /*
1111 1.1 jtc ** Mm.n.d - nth "dth day" of month m.
1112 1.1 jtc */
1113 1.1 jtc
1114 1.1 jtc /*
1115 1.1 jtc ** Use Zeller's Congruence to get day-of-week of first day of
1116 1.1 jtc ** month.
1117 1.1 jtc */
1118 1.1 jtc m1 = (rulep->r_mon + 9) % 12 + 1;
1119 1.1 jtc yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1120 1.1 jtc yy1 = yy0 / 100;
1121 1.1 jtc yy2 = yy0 % 100;
1122 1.1 jtc dow = ((26 * m1 - 2) / 10 +
1123 1.1 jtc 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1124 1.1 jtc if (dow < 0)
1125 1.1 jtc dow += DAYSPERWEEK;
1126 1.1 jtc
1127 1.1 jtc /*
1128 1.45 mlelstv ** "dow" is the day-of-week of the first day of the month. Get
1129 1.1 jtc ** the day-of-month (zero-origin) of the first "dow" day of the
1130 1.1 jtc ** month.
1131 1.1 jtc */
1132 1.1 jtc d = rulep->r_day - dow;
1133 1.1 jtc if (d < 0)
1134 1.1 jtc d += DAYSPERWEEK;
1135 1.1 jtc for (i = 1; i < rulep->r_week; ++i) {
1136 1.1 jtc if (d + DAYSPERWEEK >=
1137 1.1 jtc mon_lengths[leapyear][rulep->r_mon - 1])
1138 1.1 jtc break;
1139 1.1 jtc d += DAYSPERWEEK;
1140 1.1 jtc }
1141 1.1 jtc
1142 1.1 jtc /*
1143 1.1 jtc ** "d" is the day-of-month (zero-origin) of the day we want.
1144 1.1 jtc */
1145 1.81 christos value = d * SECSPERDAY;
1146 1.81 christos for (i = 0; i < rulep->r_mon - 1; ++i)
1147 1.81 christos value += mon_lengths[leapyear][i] * SECSPERDAY;
1148 1.1 jtc break;
1149 1.124 christos
1150 1.124 christos default: UNREACHABLE();
1151 1.1 jtc }
1152 1.1 jtc
1153 1.1 jtc /*
1154 1.81 christos ** "value" is the year-relative time of 00:00:00 UT on the day in
1155 1.81 christos ** question. To get the year-relative time of the specified local
1156 1.1 jtc ** time on that day, add the transition time and the current offset
1157 1.78 christos ** from UT.
1158 1.1 jtc */
1159 1.81 christos return value + rulep->r_time + offset;
1160 1.1 jtc }
1161 1.1 jtc
1162 1.1 jtc /*
1163 1.1 jtc ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1164 1.1 jtc ** appropriate.
1165 1.1 jtc */
1166 1.1 jtc
1167 1.87 christos static bool
1168 1.124 christos tzparse(const char *name, struct state *sp, struct state *basep)
1169 1.87 christos {
1170 1.87 christos const char * stdname;
1171 1.87 christos const char * dstname;
1172 1.87 christos size_t stdlen;
1173 1.87 christos size_t dstlen;
1174 1.96 christos size_t charcnt;
1175 1.87 christos int_fast32_t stdoffset;
1176 1.87 christos int_fast32_t dstoffset;
1177 1.87 christos char * cp;
1178 1.87 christos bool load_ok;
1179 1.124 christos time_t atlo = TIME_T_MIN, leaplo = TIME_T_MIN;
1180 1.1 jtc
1181 1.84 martin dstname = NULL; /* XXX gcc */
1182 1.1 jtc stdname = name;
1183 1.124 christos if (*name == '<') {
1184 1.124 christos name++;
1185 1.124 christos stdname = name;
1186 1.124 christos name = getqzname(name, '>');
1187 1.124 christos if (*name != '>')
1188 1.124 christos return false;
1189 1.124 christos stdlen = name - stdname;
1190 1.124 christos name++;
1191 1.1 jtc } else {
1192 1.124 christos name = getzname(name);
1193 1.124 christos stdlen = name - stdname;
1194 1.1 jtc }
1195 1.124 christos if (!stdlen)
1196 1.124 christos return false;
1197 1.124 christos name = getoffset(name, &stdoffset);
1198 1.124 christos if (name == NULL)
1199 1.124 christos return false;
1200 1.96 christos charcnt = stdlen + 1;
1201 1.96 christos if (sizeof sp->chars < charcnt)
1202 1.96 christos return false;
1203 1.124 christos if (basep) {
1204 1.124 christos if (0 < basep->timecnt)
1205 1.124 christos atlo = basep->ats[basep->timecnt - 1];
1206 1.124 christos load_ok = false;
1207 1.124 christos sp->leapcnt = basep->leapcnt;
1208 1.124 christos memcpy(sp->lsis, basep->lsis, sp->leapcnt * sizeof *sp->lsis);
1209 1.124 christos } else {
1210 1.124 christos load_ok = tzload(TZDEFRULES, sp, false) == 0;
1211 1.124 christos if (!load_ok)
1212 1.124 christos sp->leapcnt = 0; /* So, we're off a little. */
1213 1.124 christos }
1214 1.124 christos if (0 < sp->leapcnt)
1215 1.124 christos leaplo = sp->lsis[sp->leapcnt - 1].ls_trans;
1216 1.1 jtc if (*name != '\0') {
1217 1.45 mlelstv if (*name == '<') {
1218 1.45 mlelstv dstname = ++name;
1219 1.45 mlelstv name = getqzname(name, '>');
1220 1.45 mlelstv if (*name != '>')
1221 1.87 christos return false;
1222 1.45 mlelstv dstlen = name - dstname;
1223 1.45 mlelstv name++;
1224 1.45 mlelstv } else {
1225 1.45 mlelstv dstname = name;
1226 1.45 mlelstv name = getzname(name);
1227 1.113 christos dstlen = name - dstname; /* length of DST abbr. */
1228 1.45 mlelstv }
1229 1.96 christos if (!dstlen)
1230 1.96 christos return false;
1231 1.96 christos charcnt += dstlen + 1;
1232 1.96 christos if (sizeof sp->chars < charcnt)
1233 1.96 christos return false;
1234 1.1 jtc if (*name != '\0' && *name != ',' && *name != ';') {
1235 1.45 mlelstv name = getoffset(name, &dstoffset);
1236 1.1 jtc if (name == NULL)
1237 1.87 christos return false;
1238 1.1 jtc } else dstoffset = stdoffset - SECSPERHOUR;
1239 1.87 christos if (*name == '\0' && !load_ok)
1240 1.22 kleink name = TZDEFRULESTRING;
1241 1.1 jtc if (*name == ',' || *name == ';') {
1242 1.1 jtc struct rule start;
1243 1.1 jtc struct rule end;
1244 1.78 christos int year;
1245 1.81 christos int timecnt;
1246 1.126 christos __time_t janfirst;
1247 1.106 christos int_fast32_t janoffset = 0;
1248 1.124 christos int yearbeg, yearlim;
1249 1.1 jtc
1250 1.1 jtc ++name;
1251 1.45 mlelstv if ((name = getrule(name, &start)) == NULL)
1252 1.87 christos return false;
1253 1.1 jtc if (*name++ != ',')
1254 1.87 christos return false;
1255 1.45 mlelstv if ((name = getrule(name, &end)) == NULL)
1256 1.87 christos return false;
1257 1.1 jtc if (*name != '\0')
1258 1.87 christos return false;
1259 1.1 jtc sp->typecnt = 2; /* standard time and DST */
1260 1.1 jtc /*
1261 1.45 mlelstv ** Two transitions per year, from EPOCH_YEAR forward.
1262 1.1 jtc */
1263 1.113 christos init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1264 1.113 christos init_ttinfo(&sp->ttis[1], -dstoffset, true,
1265 1.91 christos (int)(stdlen + 1));
1266 1.82 christos sp->defaulttype = 0;
1267 1.81 christos timecnt = 0;
1268 1.1 jtc janfirst = 0;
1269 1.106 christos yearbeg = EPOCH_YEAR;
1270 1.106 christos
1271 1.106 christos do {
1272 1.106 christos int_fast32_t yearsecs
1273 1.106 christos = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1274 1.106 christos yearbeg--;
1275 1.106 christos if (increment_overflow_time(&janfirst, -yearsecs)) {
1276 1.106 christos janoffset = -yearsecs;
1277 1.106 christos break;
1278 1.106 christos }
1279 1.124 christos } while (atlo < janfirst
1280 1.124 christos && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1281 1.124 christos
1282 1.124 christos for (;;) {
1283 1.124 christos int_fast32_t yearsecs
1284 1.124 christos = year_lengths[isleap(yearbeg)] * SECSPERDAY;
1285 1.124 christos int yearbeg1 = yearbeg;
1286 1.126 christos __time_t janfirst1 = janfirst;
1287 1.124 christos if (increment_overflow_time(&janfirst1, yearsecs)
1288 1.124 christos || increment_overflow(&yearbeg1, 1)
1289 1.124 christos || atlo <= janfirst1)
1290 1.124 christos break;
1291 1.124 christos yearbeg = yearbeg1;
1292 1.124 christos janfirst = janfirst1;
1293 1.124 christos }
1294 1.106 christos
1295 1.124 christos yearlim = yearbeg;
1296 1.124 christos if (increment_overflow(&yearlim, YEARSPERREPEAT + 1))
1297 1.124 christos yearlim = INT_MAX;
1298 1.106 christos for (year = yearbeg; year < yearlim; year++) {
1299 1.81 christos int_fast32_t
1300 1.81 christos starttime = transtime(year, &start, stdoffset),
1301 1.81 christos endtime = transtime(year, &end, dstoffset);
1302 1.81 christos int_fast32_t
1303 1.81 christos yearsecs = (year_lengths[isleap(year)]
1304 1.81 christos * SECSPERDAY);
1305 1.87 christos bool reversed = endtime < starttime;
1306 1.81 christos if (reversed) {
1307 1.81 christos int_fast32_t swap = starttime;
1308 1.81 christos starttime = endtime;
1309 1.81 christos endtime = swap;
1310 1.81 christos }
1311 1.81 christos if (reversed
1312 1.78 christos || (starttime < endtime
1313 1.124 christos && endtime - starttime < yearsecs)) {
1314 1.81 christos if (TZ_MAX_TIMES - 2 < timecnt)
1315 1.78 christos break;
1316 1.81 christos sp->ats[timecnt] = janfirst;
1317 1.106 christos if (! increment_overflow_time
1318 1.106 christos (&sp->ats[timecnt],
1319 1.124 christos janoffset + starttime)
1320 1.124 christos && atlo <= sp->ats[timecnt])
1321 1.113 christos sp->types[timecnt++] = !reversed;
1322 1.81 christos sp->ats[timecnt] = janfirst;
1323 1.106 christos if (! increment_overflow_time
1324 1.106 christos (&sp->ats[timecnt],
1325 1.124 christos janoffset + endtime)
1326 1.124 christos && atlo <= sp->ats[timecnt]) {
1327 1.113 christos sp->types[timecnt++] = reversed;
1328 1.113 christos }
1329 1.1 jtc }
1330 1.124 christos if (endtime < leaplo) {
1331 1.124 christos yearlim = year;
1332 1.124 christos if (increment_overflow(&yearlim,
1333 1.124 christos YEARSPERREPEAT + 1))
1334 1.124 christos yearlim = INT_MAX;
1335 1.124 christos }
1336 1.106 christos if (increment_overflow_time
1337 1.106 christos (&janfirst, janoffset + yearsecs))
1338 1.45 mlelstv break;
1339 1.106 christos janoffset = 0;
1340 1.1 jtc }
1341 1.81 christos sp->timecnt = timecnt;
1342 1.113 christos if (! timecnt) {
1343 1.113 christos sp->ttis[0] = sp->ttis[1];
1344 1.78 christos sp->typecnt = 1; /* Perpetual DST. */
1345 1.113 christos } else if (YEARSPERREPEAT < year - yearbeg)
1346 1.106 christos sp->goback = sp->goahead = true;
1347 1.1 jtc } else {
1348 1.74 christos int_fast32_t theirstdoffset;
1349 1.74 christos int_fast32_t theirdstoffset;
1350 1.74 christos int_fast32_t theiroffset;
1351 1.87 christos bool isdst;
1352 1.74 christos int i;
1353 1.74 christos int j;
1354 1.1 jtc
1355 1.1 jtc if (*name != '\0')
1356 1.87 christos return false;
1357 1.1 jtc /*
1358 1.69 christos ** Initial values of theirstdoffset and theirdstoffset.
1359 1.1 jtc */
1360 1.1 jtc theirstdoffset = 0;
1361 1.1 jtc for (i = 0; i < sp->timecnt; ++i) {
1362 1.1 jtc j = sp->types[i];
1363 1.1 jtc if (!sp->ttis[j].tt_isdst) {
1364 1.5 jtc theirstdoffset =
1365 1.122 christos - sp->ttis[j].tt_utoff;
1366 1.1 jtc break;
1367 1.1 jtc }
1368 1.1 jtc }
1369 1.45 mlelstv theirdstoffset = 0;
1370 1.45 mlelstv for (i = 0; i < sp->timecnt; ++i) {
1371 1.45 mlelstv j = sp->types[i];
1372 1.45 mlelstv if (sp->ttis[j].tt_isdst) {
1373 1.45 mlelstv theirdstoffset =
1374 1.122 christos - sp->ttis[j].tt_utoff;
1375 1.45 mlelstv break;
1376 1.45 mlelstv }
1377 1.45 mlelstv }
1378 1.1 jtc /*
1379 1.1 jtc ** Initially we're assumed to be in standard time.
1380 1.1 jtc */
1381 1.87 christos isdst = false;
1382 1.1 jtc /*
1383 1.1 jtc ** Now juggle transition times and types
1384 1.1 jtc ** tracking offsets as you do.
1385 1.1 jtc */
1386 1.1 jtc for (i = 0; i < sp->timecnt; ++i) {
1387 1.1 jtc j = sp->types[i];
1388 1.1 jtc sp->types[i] = sp->ttis[j].tt_isdst;
1389 1.122 christos if (sp->ttis[j].tt_ttisut) {
1390 1.1 jtc /* No adjustment to transition time */
1391 1.1 jtc } else {
1392 1.1 jtc /*
1393 1.112 christos ** If daylight saving time is in
1394 1.112 christos ** effect, and the transition time was
1395 1.112 christos ** not specified as standard time, add
1396 1.112 christos ** the daylight saving time offset to
1397 1.112 christos ** the transition time; otherwise, add
1398 1.112 christos ** the standard time offset to the
1399 1.112 christos ** transition time.
1400 1.1 jtc */
1401 1.1 jtc /*
1402 1.1 jtc ** Transitions from DST to DDST
1403 1.1 jtc ** will effectively disappear since
1404 1.1 jtc ** POSIX provides for only one DST
1405 1.1 jtc ** offset.
1406 1.1 jtc */
1407 1.45 mlelstv if (isdst && !sp->ttis[j].tt_ttisstd) {
1408 1.66 christos sp->ats[i] += (time_t)
1409 1.66 christos (dstoffset - theirdstoffset);
1410 1.45 mlelstv } else {
1411 1.66 christos sp->ats[i] += (time_t)
1412 1.66 christos (stdoffset - theirstdoffset);
1413 1.45 mlelstv }
1414 1.1 jtc }
1415 1.122 christos theiroffset = -sp->ttis[j].tt_utoff;
1416 1.87 christos if (sp->ttis[j].tt_isdst)
1417 1.39 christos theirstdoffset = theiroffset;
1418 1.45 mlelstv else theirdstoffset = theiroffset;
1419 1.1 jtc }
1420 1.1 jtc /*
1421 1.1 jtc ** Finally, fill in ttis.
1422 1.1 jtc */
1423 1.91 christos init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1424 1.91 christos init_ttinfo(&sp->ttis[1], -dstoffset, true,
1425 1.91 christos (int)(stdlen + 1));
1426 1.7 jtc sp->typecnt = 2;
1427 1.82 christos sp->defaulttype = 0;
1428 1.1 jtc }
1429 1.1 jtc } else {
1430 1.1 jtc dstlen = 0;
1431 1.1 jtc sp->typecnt = 1; /* only standard time */
1432 1.1 jtc sp->timecnt = 0;
1433 1.91 christos init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1434 1.91 christos init_ttinfo(&sp->ttis[1], 0, false, 0);
1435 1.82 christos sp->defaulttype = 0;
1436 1.1 jtc }
1437 1.99 christos sp->charcnt = (int)charcnt;
1438 1.1 jtc cp = sp->chars;
1439 1.124 christos memcpy(cp, stdname, stdlen);
1440 1.1 jtc cp += stdlen;
1441 1.1 jtc *cp++ = '\0';
1442 1.1 jtc if (dstlen != 0) {
1443 1.87 christos (void) memcpy(cp, dstname, dstlen);
1444 1.1 jtc *(cp + dstlen) = '\0';
1445 1.1 jtc }
1446 1.87 christos return true;
1447 1.1 jtc }
1448 1.1 jtc
1449 1.1 jtc static void
1450 1.87 christos gmtload(struct state *const sp)
1451 1.49 christos {
1452 1.91 christos if (tzload(gmt, sp, true) != 0)
1453 1.124 christos (void) tzparse("GMT0", sp, NULL);
1454 1.49 christos }
1455 1.49 christos
1456 1.124 christos /* Initialize *SP to a value appropriate for the TZ setting NAME.
1457 1.124 christos Return 0 on success, an errno value on failure. */
1458 1.91 christos static int
1459 1.87 christos zoneinit(struct state *sp, char const *name)
1460 1.49 christos {
1461 1.87 christos if (name && ! name[0]) {
1462 1.91 christos /*
1463 1.91 christos ** User wants it fast rather than right.
1464 1.91 christos */
1465 1.91 christos sp->leapcnt = 0; /* so, we're off a little */
1466 1.87 christos sp->timecnt = 0;
1467 1.118 christos sp->typecnt = 1;
1468 1.91 christos sp->charcnt = 0;
1469 1.91 christos sp->goback = sp->goahead = false;
1470 1.91 christos init_ttinfo(&sp->ttis[0], 0, false, 0);
1471 1.87 christos strcpy(sp->chars, gmt);
1472 1.91 christos sp->defaulttype = 0;
1473 1.91 christos return 0;
1474 1.91 christos } else {
1475 1.91 christos int err = tzload(name, sp, true);
1476 1.91 christos if (err != 0 && name && name[0] != ':' &&
1477 1.124 christos tzparse(name, sp, NULL))
1478 1.93 christos err = 0;
1479 1.93 christos if (err == 0)
1480 1.93 christos scrub_abbrs(sp);
1481 1.91 christos return err;
1482 1.87 christos }
1483 1.49 christos }
1484 1.87 christos
1485 1.19 kleink static void
1486 1.87 christos tzsetlcl(char const *name)
1487 1.1 jtc {
1488 1.117 christos struct state *sp = __lclptr;
1489 1.87 christos int lcl = name ? strlen(name) < sizeof lcl_TZname : -1;
1490 1.87 christos if (lcl < 0 ? lcl_is_set < 0
1491 1.87 christos : 0 < lcl_is_set && strcmp(lcl_TZname, name) == 0)
1492 1.1 jtc return;
1493 1.1 jtc
1494 1.91 christos if (! sp)
1495 1.117 christos __lclptr = sp = malloc(sizeof *__lclptr);
1496 1.91 christos if (sp) {
1497 1.91 christos if (zoneinit(sp, name) != 0)
1498 1.91 christos zoneinit(sp, "");
1499 1.91 christos if (0 < lcl)
1500 1.91 christos strcpy(lcl_TZname, name);
1501 1.89 christos }
1502 1.45 mlelstv settzname();
1503 1.87 christos lcl_is_set = lcl;
1504 1.1 jtc }
1505 1.1 jtc
1506 1.87 christos #ifdef STD_INSPIRED
1507 1.1 jtc void
1508 1.45 mlelstv tzsetwall(void)
1509 1.19 kleink {
1510 1.117 christos rwlock_wrlock(&__lcl_lock);
1511 1.87 christos tzsetlcl(NULL);
1512 1.117 christos rwlock_unlock(&__lcl_lock);
1513 1.19 kleink }
1514 1.87 christos #endif
1515 1.87 christos
1516 1.117 christos void
1517 1.87 christos tzset_unlocked(void)
1518 1.87 christos {
1519 1.87 christos tzsetlcl(getenv("TZ"));
1520 1.87 christos }
1521 1.19 kleink
1522 1.45 mlelstv void
1523 1.87 christos tzset(void)
1524 1.1 jtc {
1525 1.117 christos rwlock_wrlock(&__lcl_lock);
1526 1.87 christos tzset_unlocked();
1527 1.117 christos rwlock_unlock(&__lcl_lock);
1528 1.87 christos }
1529 1.1 jtc
1530 1.87 christos static void
1531 1.87 christos gmtcheck(void)
1532 1.87 christos {
1533 1.87 christos static bool gmt_is_set;
1534 1.117 christos rwlock_wrlock(&__lcl_lock);
1535 1.87 christos if (! gmt_is_set) {
1536 1.87 christos gmtptr = malloc(sizeof *gmtptr);
1537 1.87 christos if (gmtptr)
1538 1.87 christos gmtload(gmtptr);
1539 1.87 christos gmt_is_set = true;
1540 1.1 jtc }
1541 1.117 christos rwlock_unlock(&__lcl_lock);
1542 1.87 christos }
1543 1.1 jtc
1544 1.87 christos #if NETBSD_INSPIRED
1545 1.1 jtc
1546 1.87 christos timezone_t
1547 1.87 christos tzalloc(const char *name)
1548 1.87 christos {
1549 1.87 christos timezone_t sp = malloc(sizeof *sp);
1550 1.91 christos if (sp) {
1551 1.91 christos int err = zoneinit(sp, name);
1552 1.91 christos if (err != 0) {
1553 1.91 christos free(sp);
1554 1.91 christos errno = err;
1555 1.91 christos return NULL;
1556 1.91 christos }
1557 1.91 christos }
1558 1.124 christos #if !HAVE_MALLOC_ERRNO
1559 1.124 christos } else
1560 1.124 christos errno = ENOMEM;
1561 1.124 christos #endif
1562 1.91 christos return sp;
1563 1.1 jtc }
1564 1.1 jtc
1565 1.19 kleink void
1566 1.87 christos tzfree(timezone_t sp)
1567 1.19 kleink {
1568 1.87 christos free(sp);
1569 1.19 kleink }
1570 1.19 kleink
1571 1.1 jtc /*
1572 1.87 christos ** NetBSD 6.1.4 has ctime_rz, but omit it because POSIX says ctime and
1573 1.87 christos ** ctime_r are obsolescent and have potential security problems that
1574 1.87 christos ** ctime_rz would share. Callers can instead use localtime_rz + strftime.
1575 1.87 christos **
1576 1.87 christos ** NetBSD 6.1.4 has tzgetname, but omit it because it doesn't work
1577 1.87 christos ** in zones with three or more time zone abbreviations.
1578 1.87 christos ** Callers can instead use localtime_rz + strftime.
1579 1.87 christos */
1580 1.87 christos
1581 1.87 christos #endif
1582 1.87 christos
1583 1.87 christos /*
1584 1.1 jtc ** The easy way to behave "as if no library function calls" localtime
1585 1.83 christos ** is to not call it, so we drop its guts into "localsub", which can be
1586 1.83 christos ** freely called. (And no, the PANS doesn't require the above behavior,
1587 1.1 jtc ** but it *is* desirable.)
1588 1.1 jtc **
1589 1.93 christos ** If successful and SETNAME is nonzero,
1590 1.91 christos ** set the applicable parts of tzname, timezone and altzone;
1591 1.113 christos ** however, it's OK to omit this step if the timezone is POSIX-compatible,
1592 1.91 christos ** since in that case tzset should have already done this step correctly.
1593 1.93 christos ** SETNAME's type is intfast32_t for compatibility with gmtsub,
1594 1.93 christos ** but it is actually a boolean and its value should be 0 or 1.
1595 1.1 jtc */
1596 1.1 jtc
1597 1.1 jtc /*ARGSUSED*/
1598 1.45 mlelstv static struct tm *
1599 1.93 christos localsub(struct state const *sp, time_t const *timep, int_fast32_t setname,
1600 1.87 christos struct tm *const tmp)
1601 1.49 christos {
1602 1.49 christos const struct ttinfo * ttisp;
1603 1.49 christos int i;
1604 1.49 christos struct tm * result;
1605 1.1 jtc const time_t t = *timep;
1606 1.1 jtc
1607 1.87 christos if (sp == NULL) {
1608 1.91 christos /* Don't bother to set tzname etc.; tzset has already done it. */
1609 1.91 christos return gmtsub(gmtptr, timep, 0, tmp);
1610 1.87 christos }
1611 1.45 mlelstv if ((sp->goback && t < sp->ats[0]) ||
1612 1.45 mlelstv (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1613 1.124 christos time_t newt;
1614 1.49 christos time_t seconds;
1615 1.78 christos time_t years;
1616 1.45 mlelstv
1617 1.45 mlelstv if (t < sp->ats[0])
1618 1.45 mlelstv seconds = sp->ats[0] - t;
1619 1.45 mlelstv else seconds = t - sp->ats[sp->timecnt - 1];
1620 1.45 mlelstv --seconds;
1621 1.124 christos
1622 1.124 christos /* Beware integer overflow, as SECONDS might
1623 1.124 christos be close to the maximum time_t. */
1624 1.124 christos years = (time_t)(seconds / SECSPERREPEAT
1625 1.124 christos * YEARSPERREPEAT);
1626 1.78 christos seconds = (time_t)(years * AVGSECSPERYEAR);
1627 1.124 christos years += YEARSPERREPEAT;
1628 1.45 mlelstv if (t < sp->ats[0])
1629 1.124 christos newt = (time_t)(t + seconds + SECSPERREPEAT);
1630 1.124 christos else
1631 1.124 christos newt = (time_t)(t - seconds - SECSPERREPEAT);
1632 1.124 christos
1633 1.45 mlelstv if (newt < sp->ats[0] ||
1634 1.88 christos newt > sp->ats[sp->timecnt - 1]) {
1635 1.88 christos errno = EINVAL;
1636 1.88 christos return NULL; /* "cannot happen" */
1637 1.88 christos }
1638 1.93 christos result = localsub(sp, &newt, setname, tmp);
1639 1.87 christos if (result) {
1640 1.87 christos int_fast64_t newy;
1641 1.45 mlelstv
1642 1.87 christos newy = result->tm_year;
1643 1.45 mlelstv if (t < sp->ats[0])
1644 1.78 christos newy -= years;
1645 1.78 christos else newy += years;
1646 1.88 christos if (! (INT_MIN <= newy && newy <= INT_MAX)) {
1647 1.88 christos errno = EOVERFLOW;
1648 1.45 mlelstv return NULL;
1649 1.88 christos }
1650 1.87 christos result->tm_year = (int)newy;
1651 1.45 mlelstv }
1652 1.45 mlelstv return result;
1653 1.1 jtc }
1654 1.1 jtc if (sp->timecnt == 0 || t < sp->ats[0]) {
1655 1.74 christos i = sp->defaulttype;
1656 1.1 jtc } else {
1657 1.49 christos int lo = 1;
1658 1.49 christos int hi = sp->timecnt;
1659 1.45 mlelstv
1660 1.45 mlelstv while (lo < hi) {
1661 1.49 christos int mid = (lo + hi) / 2;
1662 1.45 mlelstv
1663 1.45 mlelstv if (t < sp->ats[mid])
1664 1.45 mlelstv hi = mid;
1665 1.45 mlelstv else lo = mid + 1;
1666 1.45 mlelstv }
1667 1.124 christos i = sp->types[lo - 1];
1668 1.1 jtc }
1669 1.1 jtc ttisp = &sp->ttis[i];
1670 1.1 jtc /*
1671 1.1 jtc ** To get (wrong) behavior that's compatible with System V Release 2.0
1672 1.1 jtc ** you'd replace the statement below with
1673 1.122 christos ** t += ttisp->tt_utoff;
1674 1.1 jtc ** timesub(&t, 0L, sp, tmp);
1675 1.1 jtc */
1676 1.122 christos result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1677 1.87 christos if (result) {
1678 1.92 christos result->tm_isdst = ttisp->tt_isdst;
1679 1.92 christos #ifdef TM_ZONE
1680 1.122 christos result->TM_ZONE = __UNCONST(&sp->chars[ttisp->tt_desigidx]);
1681 1.92 christos #endif /* defined TM_ZONE */
1682 1.93 christos if (setname)
1683 1.93 christos update_tzname_etc(sp, ttisp);
1684 1.87 christos }
1685 1.45 mlelstv return result;
1686 1.1 jtc }
1687 1.1 jtc
1688 1.87 christos #if NETBSD_INSPIRED
1689 1.49 christos
1690 1.1 jtc struct tm *
1691 1.87 christos localtime_rz(timezone_t sp, time_t const *timep, struct tm *tmp)
1692 1.87 christos {
1693 1.87 christos return localsub(sp, timep, 0, tmp);
1694 1.87 christos }
1695 1.87 christos
1696 1.87 christos #endif
1697 1.87 christos
1698 1.87 christos static struct tm *
1699 1.87 christos localtime_tzset(time_t const *timep, struct tm *tmp, bool setname)
1700 1.1 jtc {
1701 1.117 christos rwlock_wrlock(&__lcl_lock);
1702 1.87 christos if (setname || !lcl_is_set)
1703 1.87 christos tzset_unlocked();
1704 1.117 christos tmp = localsub(__lclptr, timep, setname, tmp);
1705 1.117 christos rwlock_unlock(&__lcl_lock);
1706 1.49 christos return tmp;
1707 1.1 jtc }
1708 1.1 jtc
1709 1.49 christos struct tm *
1710 1.96 christos localtime(const time_t *timep)
1711 1.49 christos {
1712 1.87 christos return localtime_tzset(timep, &tm, true);
1713 1.49 christos }
1714 1.35 kleink
1715 1.18 kleink struct tm *
1716 1.87 christos localtime_r(const time_t * __restrict timep, struct tm *tmp)
1717 1.18 kleink {
1718 1.101 christos return localtime_tzset(timep, tmp, true);
1719 1.18 kleink }
1720 1.18 kleink
1721 1.18 kleink /*
1722 1.1 jtc ** gmtsub is to gmtime as localsub is to localtime.
1723 1.1 jtc */
1724 1.1 jtc
1725 1.45 mlelstv static struct tm *
1726 1.87 christos gmtsub(struct state const *sp, const time_t *timep, int_fast32_t offset,
1727 1.87 christos struct tm *tmp)
1728 1.1 jtc {
1729 1.49 christos struct tm * result;
1730 1.19 kleink
1731 1.87 christos result = timesub(timep, offset, gmtptr, tmp);
1732 1.1 jtc #ifdef TM_ZONE
1733 1.1 jtc /*
1734 1.1 jtc ** Could get fancy here and deliver something such as
1735 1.104 christos ** "+xx" or "-xx" if offset is non-zero,
1736 1.1 jtc ** but this is no time for a treasure hunt.
1737 1.1 jtc */
1738 1.88 christos if (result)
1739 1.88 christos result->TM_ZONE = offset ? __UNCONST(wildabbr) : gmtptr ?
1740 1.88 christos gmtptr->chars : __UNCONST(gmt);
1741 1.1 jtc #endif /* defined TM_ZONE */
1742 1.45 mlelstv return result;
1743 1.1 jtc }
1744 1.1 jtc
1745 1.1 jtc
1746 1.18 kleink /*
1747 1.35 kleink ** Re-entrant version of gmtime.
1748 1.35 kleink */
1749 1.35 kleink
1750 1.18 kleink struct tm *
1751 1.96 christos gmtime_r(const time_t *timep, struct tm *tmp)
1752 1.18 kleink {
1753 1.87 christos gmtcheck();
1754 1.90 christos return gmtsub(NULL, timep, 0, tmp);
1755 1.18 kleink }
1756 1.18 kleink
1757 1.96 christos struct tm *
1758 1.96 christos gmtime(const time_t *timep)
1759 1.96 christos {
1760 1.96 christos return gmtime_r(timep, &tm);
1761 1.96 christos }
1762 1.124 christos
1763 1.1 jtc #ifdef STD_INSPIRED
1764 1.1 jtc
1765 1.1 jtc struct tm *
1766 1.96 christos offtime(const time_t *timep, long offset)
1767 1.1 jtc {
1768 1.87 christos gmtcheck();
1769 1.90 christos return gmtsub(gmtptr, timep, (int_fast32_t)offset, &tm);
1770 1.49 christos }
1771 1.49 christos
1772 1.49 christos struct tm *
1773 1.49 christos offtime_r(const time_t *timep, long offset, struct tm *tmp)
1774 1.49 christos {
1775 1.87 christos gmtcheck();
1776 1.90 christos return gmtsub(NULL, timep, (int_fast32_t)offset, tmp);
1777 1.1 jtc }
1778 1.1 jtc
1779 1.1 jtc #endif /* defined STD_INSPIRED */
1780 1.1 jtc
1781 1.109 christos #if TZ_TIME_T
1782 1.105 christos
1783 1.109 christos # if USG_COMPAT
1784 1.105 christos # define daylight 0
1785 1.105 christos # define timezone 0
1786 1.105 christos # endif
1787 1.123 christos # if !ALTZONE
1788 1.105 christos # define altzone 0
1789 1.105 christos # endif
1790 1.105 christos
1791 1.105 christos /* Convert from the underlying system's time_t to the ersatz time_tz,
1792 1.105 christos which is called 'time_t' in this file. Typically, this merely
1793 1.105 christos converts the time's integer width. On some platforms, the system
1794 1.105 christos time is local time not UT, or uses some epoch other than the POSIX
1795 1.105 christos epoch.
1796 1.105 christos
1797 1.105 christos Although this code appears to define a function named 'time' that
1798 1.105 christos returns time_t, the macros in private.h cause this code to actually
1799 1.105 christos define a function named 'tz_time' that returns tz_time_t. The call
1800 1.105 christos to sys_time invokes the underlying system's 'time' function. */
1801 1.105 christos
1802 1.105 christos time_t
1803 1.105 christos time(time_t *p)
1804 1.105 christos {
1805 1.126 christos __time_t r = sys_time(0);
1806 1.105 christos if (r != (time_t) -1) {
1807 1.105 christos int_fast32_t offset = EPOCH_LOCAL ? (daylight ? timezone : altzone) : 0;
1808 1.105 christos if (increment_overflow32(&offset, -EPOCH_OFFSET)
1809 1.124 christos || increment_overflow_time(&r, offset)) {
1810 1.105 christos errno = EOVERFLOW;
1811 1.105 christos r = -1;
1812 1.105 christos }
1813 1.105 christos }
1814 1.105 christos if (p)
1815 1.126 christos *p = (time_t)r;
1816 1.126 christos return (time_t)r;
1817 1.105 christos }
1818 1.105 christos #endif
1819 1.105 christos
1820 1.45 mlelstv /*
1821 1.45 mlelstv ** Return the number of leap years through the end of the given year
1822 1.45 mlelstv ** where, to make the math easy, the answer for year zero is defined as zero.
1823 1.45 mlelstv */
1824 1.124 christos static time_t
1825 1.124 christos leaps_thru_end_of_nonneg(time_t y)
1826 1.109 christos {
1827 1.109 christos return y / 4 - y / 100 + y / 400;
1828 1.109 christos }
1829 1.45 mlelstv
1830 1.124 christos static time_t
1831 1.124 christos leaps_thru_end_of(const time_t y)
1832 1.45 mlelstv {
1833 1.109 christos return (y < 0
1834 1.109 christos ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1835 1.109 christos : leaps_thru_end_of_nonneg(y));
1836 1.45 mlelstv }
1837 1.45 mlelstv
1838 1.45 mlelstv static struct tm *
1839 1.96 christos timesub(const time_t *timep, int_fast32_t offset,
1840 1.97 riz const struct state *sp, struct tm *tmp)
1841 1.49 christos {
1842 1.49 christos const struct lsinfo * lp;
1843 1.49 christos time_t tdays;
1844 1.49 christos const int * ip;
1845 1.124 christos int_fast32_t corr;
1846 1.49 christos int i;
1847 1.124 christos int_fast32_t idays, rem, dayoff, dayrem;
1848 1.124 christos time_t y;
1849 1.124 christos
1850 1.124 christos /* If less than SECSPERMIN, the number of seconds since the
1851 1.124 christos most recent positive leap second; otherwise, do not add 1
1852 1.124 christos to localtime tm_sec because of leap seconds. */
1853 1.124 christos time_t secs_since_posleap = SECSPERMIN;
1854 1.1 jtc
1855 1.1 jtc corr = 0;
1856 1.1 jtc i = (sp == NULL) ? 0 : sp->leapcnt;
1857 1.1 jtc while (--i >= 0) {
1858 1.1 jtc lp = &sp->lsis[i];
1859 1.1 jtc if (*timep >= lp->ls_trans) {
1860 1.1 jtc corr = lp->ls_corr;
1861 1.124 christos if ((i == 0 ? 0 : lp[-1].ls_corr) < corr)
1862 1.124 christos secs_since_posleap = *timep - lp->ls_trans;
1863 1.1 jtc break;
1864 1.1 jtc }
1865 1.1 jtc }
1866 1.124 christos
1867 1.124 christos /* Calculate the year, avoiding integer overflow even if
1868 1.124 christos time_t is unsigned. */
1869 1.66 christos tdays = (time_t)(*timep / SECSPERDAY);
1870 1.124 christos rem = (int)(*timep % SECSPERDAY);
1871 1.124 christos rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
1872 1.124 christos dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
1873 1.124 christos rem %= SECSPERDAY;
1874 1.124 christos /* y = (EPOCH_YEAR
1875 1.124 christos + floor((tdays + dayoff) / DAYSPERREPEAT) * YEARSPERREPEAT),
1876 1.124 christos sans overflow. But calculate against 1570 (EPOCH_YEAR -
1877 1.124 christos YEARSPERREPEAT) instead of against 1970 so that things work
1878 1.124 christos for localtime values before 1970 when time_t is unsigned. */
1879 1.124 christos dayrem = (int)(tdays % DAYSPERREPEAT);
1880 1.124 christos dayrem += dayoff % DAYSPERREPEAT;
1881 1.124 christos y = (EPOCH_YEAR - YEARSPERREPEAT
1882 1.124 christos + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
1883 1.124 christos - ((dayrem % DAYSPERREPEAT) < 0)
1884 1.124 christos + tdays / DAYSPERREPEAT)
1885 1.124 christos * YEARSPERREPEAT));
1886 1.124 christos /* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow. */
1887 1.124 christos idays = (int)(tdays % DAYSPERREPEAT);
1888 1.124 christos idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
1889 1.124 christos idays %= DAYSPERREPEAT;
1890 1.124 christos /* Increase Y and decrease IDAYS until IDAYS is in range for Y. */
1891 1.124 christos while (year_lengths[isleap(y)] <= idays) {
1892 1.124 christos int tdelta = idays / DAYSPERLYEAR;
1893 1.124 christos int_fast32_t ydelta = tdelta + !tdelta;
1894 1.124 christos time_t newy = y + ydelta;
1895 1.49 christos int leapdays;
1896 1.124 christos leapdays = (int)(leaps_thru_end_of(newy - 1) -
1897 1.124 christos leaps_thru_end_of(y - 1));
1898 1.124 christos idays -= ydelta * DAYSPERNYEAR;
1899 1.124 christos idays -= leapdays;
1900 1.45 mlelstv y = newy;
1901 1.45 mlelstv }
1902 1.124 christos
1903 1.124 christos if (!TYPE_SIGNED(time_t) && y < TM_YEAR_BASE) {
1904 1.124 christos int signed_y = (int)y;
1905 1.124 christos tmp->tm_year = signed_y - TM_YEAR_BASE;
1906 1.124 christos } else if ((!TYPE_SIGNED(time_t) || INT_MIN + TM_YEAR_BASE <= y)
1907 1.124 christos && y - TM_YEAR_BASE <= INT_MAX)
1908 1.124 christos tmp->tm_year = (int)(y - TM_YEAR_BASE);
1909 1.124 christos else {
1910 1.124 christos errno = EOVERFLOW;
1911 1.124 christos return NULL;
1912 1.45 mlelstv }
1913 1.45 mlelstv tmp->tm_yday = idays;
1914 1.45 mlelstv /*
1915 1.45 mlelstv ** The "extra" mods below avoid overflow problems.
1916 1.45 mlelstv */
1917 1.124 christos tmp->tm_wday = (int)(TM_WDAY_BASE
1918 1.124 christos + ((tmp->tm_year % DAYSPERWEEK)
1919 1.124 christos * (DAYSPERNYEAR % DAYSPERWEEK))
1920 1.124 christos + leaps_thru_end_of(y - 1)
1921 1.124 christos - leaps_thru_end_of(TM_YEAR_BASE - 1)
1922 1.124 christos + idays);
1923 1.45 mlelstv tmp->tm_wday %= DAYSPERWEEK;
1924 1.45 mlelstv if (tmp->tm_wday < 0)
1925 1.45 mlelstv tmp->tm_wday += DAYSPERWEEK;
1926 1.1 jtc tmp->tm_hour = (int) (rem / SECSPERHOUR);
1927 1.45 mlelstv rem %= SECSPERHOUR;
1928 1.124 christos tmp->tm_min = rem / SECSPERMIN;
1929 1.124 christos tmp->tm_sec = rem % SECSPERMIN;
1930 1.124 christos
1931 1.124 christos /* Use "... ??:??:60" at the end of the localtime minute containing
1932 1.124 christos the second just before the positive leap second. */
1933 1.124 christos tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
1934 1.124 christos
1935 1.45 mlelstv ip = mon_lengths[isleap(y)];
1936 1.45 mlelstv for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1937 1.45 mlelstv idays -= ip[tmp->tm_mon];
1938 1.124 christos tmp->tm_mday = idays + 1;
1939 1.1 jtc tmp->tm_isdst = 0;
1940 1.1 jtc #ifdef TM_GMTOFF
1941 1.1 jtc tmp->TM_GMTOFF = offset;
1942 1.1 jtc #endif /* defined TM_GMTOFF */
1943 1.45 mlelstv return tmp;
1944 1.1 jtc }
1945 1.1 jtc
1946 1.1 jtc char *
1947 1.96 christos ctime(const time_t *timep)
1948 1.1 jtc {
1949 1.1 jtc /*
1950 1.1 jtc ** Section 4.12.3.2 of X3.159-1989 requires that
1951 1.18 kleink ** The ctime function converts the calendar time pointed to by timer
1952 1.45 mlelstv ** to local time in the form of a string. It is equivalent to
1953 1.1 jtc ** asctime(localtime(timer))
1954 1.1 jtc */
1955 1.91 christos struct tm *tmp = localtime(timep);
1956 1.91 christos return tmp ? asctime(tmp) : NULL;
1957 1.18 kleink }
1958 1.18 kleink
1959 1.18 kleink char *
1960 1.96 christos ctime_r(const time_t *timep, char *buf)
1961 1.18 kleink {
1962 1.91 christos struct tm mytm;
1963 1.91 christos struct tm *tmp = localtime_r(timep, &mytm);
1964 1.91 christos return tmp ? asctime_r(tmp, buf) : NULL;
1965 1.1 jtc }
1966 1.1 jtc
1967 1.49 christos char *
1968 1.49 christos ctime_rz(const timezone_t sp, const time_t * timep, char *buf)
1969 1.49 christos {
1970 1.49 christos struct tm mytm, *rtm;
1971 1.49 christos
1972 1.49 christos rtm = localtime_rz(sp, timep, &mytm);
1973 1.49 christos if (rtm == NULL)
1974 1.49 christos return NULL;
1975 1.49 christos return asctime_r(rtm, buf);
1976 1.49 christos }
1977 1.49 christos
1978 1.1 jtc /*
1979 1.1 jtc ** Adapted from code provided by Robert Elz, who writes:
1980 1.1 jtc ** The "best" way to do mktime I think is based on an idea of Bob
1981 1.7 jtc ** Kridle's (so its said...) from a long time ago.
1982 1.45 mlelstv ** It does a binary search of the time_t space. Since time_t's are
1983 1.1 jtc ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1984 1.1 jtc ** would still be very reasonable).
1985 1.1 jtc */
1986 1.1 jtc
1987 1.1 jtc #ifndef WRONG
1988 1.51 christos #define WRONG ((time_t)-1)
1989 1.1 jtc #endif /* !defined WRONG */
1990 1.1 jtc
1991 1.1 jtc /*
1992 1.87 christos ** Normalize logic courtesy Paul Eggert.
1993 1.1 jtc */
1994 1.1 jtc
1995 1.87 christos static bool
1996 1.96 christos increment_overflow(int *ip, int j)
1997 1.1 jtc {
1998 1.87 christos int const i = *ip;
1999 1.1 jtc
2000 1.58 christos /*
2001 1.58 christos ** If i >= 0 there can only be overflow if i + j > INT_MAX
2002 1.58 christos ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
2003 1.58 christos ** If i < 0 there can only be overflow if i + j < INT_MIN
2004 1.58 christos ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
2005 1.58 christos */
2006 1.58 christos if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
2007 1.87 christos return true;
2008 1.58 christos *ip += j;
2009 1.87 christos return false;
2010 1.1 jtc }
2011 1.1 jtc
2012 1.87 christos static bool
2013 1.74 christos increment_overflow32(int_fast32_t *const lp, int const m)
2014 1.45 mlelstv {
2015 1.87 christos int_fast32_t const l = *lp;
2016 1.45 mlelstv
2017 1.74 christos if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
2018 1.87 christos return true;
2019 1.58 christos *lp += m;
2020 1.87 christos return false;
2021 1.45 mlelstv }
2022 1.45 mlelstv
2023 1.87 christos static bool
2024 1.126 christos increment_overflow_time(__time_t *tp, int_fast32_t j)
2025 1.81 christos {
2026 1.81 christos /*
2027 1.81 christos ** This is like
2028 1.109 christos ** 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
2029 1.81 christos ** except that it does the right thing even if *tp + j would overflow.
2030 1.81 christos */
2031 1.81 christos if (! (j < 0
2032 1.109 christos ? (TYPE_SIGNED(time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
2033 1.109 christos : *tp <= TIME_T_MAX - j))
2034 1.87 christos return true;
2035 1.81 christos *tp += j;
2036 1.87 christos return false;
2037 1.81 christos }
2038 1.81 christos
2039 1.87 christos static bool
2040 1.49 christos normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
2041 1.1 jtc {
2042 1.49 christos int tensdelta;
2043 1.1 jtc
2044 1.1 jtc tensdelta = (*unitsptr >= 0) ?
2045 1.1 jtc (*unitsptr / base) :
2046 1.1 jtc (-1 - (-1 - *unitsptr) / base);
2047 1.1 jtc *unitsptr -= tensdelta * base;
2048 1.1 jtc return increment_overflow(tensptr, tensdelta);
2049 1.1 jtc }
2050 1.1 jtc
2051 1.87 christos static bool
2052 1.96 christos normalize_overflow32(int_fast32_t *tensptr, int *unitsptr, int base)
2053 1.45 mlelstv {
2054 1.49 christos int tensdelta;
2055 1.45 mlelstv
2056 1.45 mlelstv tensdelta = (*unitsptr >= 0) ?
2057 1.45 mlelstv (*unitsptr / base) :
2058 1.45 mlelstv (-1 - (-1 - *unitsptr) / base);
2059 1.45 mlelstv *unitsptr -= tensdelta * base;
2060 1.74 christos return increment_overflow32(tensptr, tensdelta);
2061 1.45 mlelstv }
2062 1.45 mlelstv
2063 1.45 mlelstv static int
2064 1.87 christos tmcomp(const struct tm *const atmp,
2065 1.87 christos const struct tm *const btmp)
2066 1.1 jtc {
2067 1.49 christos int result;
2068 1.1 jtc
2069 1.78 christos if (atmp->tm_year != btmp->tm_year)
2070 1.78 christos return atmp->tm_year < btmp->tm_year ? -1 : 1;
2071 1.78 christos if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
2072 1.1 jtc (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
2073 1.1 jtc (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
2074 1.1 jtc (result = (atmp->tm_min - btmp->tm_min)) == 0)
2075 1.1 jtc result = atmp->tm_sec - btmp->tm_sec;
2076 1.1 jtc return result;
2077 1.1 jtc }
2078 1.1 jtc
2079 1.1 jtc static time_t
2080 1.87 christos time2sub(struct tm *const tmp,
2081 1.87 christos struct tm *(*funcp)(struct state const *, time_t const *,
2082 1.87 christos int_fast32_t, struct tm *),
2083 1.87 christos struct state const *sp,
2084 1.87 christos const int_fast32_t offset,
2085 1.87 christos bool *okayp,
2086 1.87 christos bool do_norm_secs)
2087 1.49 christos {
2088 1.49 christos int dir;
2089 1.49 christos int i, j;
2090 1.49 christos int saved_seconds;
2091 1.74 christos int_fast32_t li;
2092 1.49 christos time_t lo;
2093 1.49 christos time_t hi;
2094 1.61 christos #ifdef NO_ERROR_IN_DST_GAP
2095 1.61 christos time_t ilo;
2096 1.61 christos #endif
2097 1.74 christos int_fast32_t y;
2098 1.74 christos time_t newt;
2099 1.74 christos time_t t;
2100 1.74 christos struct tm yourtm, mytm;
2101 1.1 jtc
2102 1.87 christos *okayp = false;
2103 1.1 jtc yourtm = *tmp;
2104 1.64 christos #ifdef NO_ERROR_IN_DST_GAP
2105 1.64 christos again:
2106 1.64 christos #endif
2107 1.13 jtc if (do_norm_secs) {
2108 1.13 jtc if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
2109 1.60 christos SECSPERMIN))
2110 1.91 christos goto out_of_range;
2111 1.13 jtc }
2112 1.1 jtc if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
2113 1.91 christos goto out_of_range;
2114 1.1 jtc if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
2115 1.91 christos goto out_of_range;
2116 1.45 mlelstv y = yourtm.tm_year;
2117 1.74 christos if (normalize_overflow32(&y, &yourtm.tm_mon, MONSPERYEAR))
2118 1.91 christos goto out_of_range;
2119 1.1 jtc /*
2120 1.45 mlelstv ** Turn y into an actual year number for now.
2121 1.1 jtc ** It is converted back to an offset from TM_YEAR_BASE later.
2122 1.1 jtc */
2123 1.74 christos if (increment_overflow32(&y, TM_YEAR_BASE))
2124 1.91 christos goto out_of_range;
2125 1.1 jtc while (yourtm.tm_mday <= 0) {
2126 1.74 christos if (increment_overflow32(&y, -1))
2127 1.91 christos goto out_of_range;
2128 1.45 mlelstv li = y + (1 < yourtm.tm_mon);
2129 1.45 mlelstv yourtm.tm_mday += year_lengths[isleap(li)];
2130 1.1 jtc }
2131 1.1 jtc while (yourtm.tm_mday > DAYSPERLYEAR) {
2132 1.45 mlelstv li = y + (1 < yourtm.tm_mon);
2133 1.45 mlelstv yourtm.tm_mday -= year_lengths[isleap(li)];
2134 1.74 christos if (increment_overflow32(&y, 1))
2135 1.91 christos goto out_of_range;
2136 1.1 jtc }
2137 1.1 jtc for ( ; ; ) {
2138 1.45 mlelstv i = mon_lengths[isleap(y)][yourtm.tm_mon];
2139 1.1 jtc if (yourtm.tm_mday <= i)
2140 1.1 jtc break;
2141 1.1 jtc yourtm.tm_mday -= i;
2142 1.1 jtc if (++yourtm.tm_mon >= MONSPERYEAR) {
2143 1.1 jtc yourtm.tm_mon = 0;
2144 1.74 christos if (increment_overflow32(&y, 1))
2145 1.91 christos goto out_of_range;
2146 1.1 jtc }
2147 1.1 jtc }
2148 1.74 christos if (increment_overflow32(&y, -TM_YEAR_BASE))
2149 1.91 christos goto out_of_range;
2150 1.87 christos if (! (INT_MIN <= y && y <= INT_MAX))
2151 1.91 christos goto out_of_range;
2152 1.66 christos yourtm.tm_year = (int)y;
2153 1.29 kleink if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
2154 1.29 kleink saved_seconds = 0;
2155 1.45 mlelstv else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
2156 1.1 jtc /*
2157 1.1 jtc ** We can't set tm_sec to 0, because that might push the
2158 1.1 jtc ** time below the minimum representable time.
2159 1.1 jtc ** Set tm_sec to 59 instead.
2160 1.1 jtc ** This assumes that the minimum representable time is
2161 1.1 jtc ** not in the same minute that a leap second was deleted from,
2162 1.1 jtc ** which is a safer assumption than using 58 would be.
2163 1.1 jtc */
2164 1.1 jtc if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
2165 1.91 christos goto out_of_range;
2166 1.1 jtc saved_seconds = yourtm.tm_sec;
2167 1.1 jtc yourtm.tm_sec = SECSPERMIN - 1;
2168 1.1 jtc } else {
2169 1.1 jtc saved_seconds = yourtm.tm_sec;
2170 1.1 jtc yourtm.tm_sec = 0;
2171 1.1 jtc }
2172 1.1 jtc /*
2173 1.45 mlelstv ** Do a binary search (this works whatever time_t's type is).
2174 1.1 jtc */
2175 1.109 christos lo = TIME_T_MIN;
2176 1.109 christos hi = TIME_T_MAX;
2177 1.61 christos #ifdef NO_ERROR_IN_DST_GAP
2178 1.61 christos ilo = lo;
2179 1.61 christos #endif
2180 1.1 jtc for ( ; ; ) {
2181 1.45 mlelstv t = lo / 2 + hi / 2;
2182 1.45 mlelstv if (t < lo)
2183 1.45 mlelstv t = lo;
2184 1.45 mlelstv else if (t > hi)
2185 1.45 mlelstv t = hi;
2186 1.87 christos if (! funcp(sp, &t, offset, &mytm)) {
2187 1.45 mlelstv /*
2188 1.45 mlelstv ** Assume that t is too extreme to be represented in
2189 1.45 mlelstv ** a struct tm; arrange things so that it is less
2190 1.45 mlelstv ** extreme on the next pass.
2191 1.45 mlelstv */
2192 1.45 mlelstv dir = (t > 0) ? 1 : -1;
2193 1.45 mlelstv } else dir = tmcomp(&mytm, &yourtm);
2194 1.1 jtc if (dir != 0) {
2195 1.45 mlelstv if (t == lo) {
2196 1.109 christos if (t == TIME_T_MAX)
2197 1.91 christos goto out_of_range;
2198 1.45 mlelstv ++t;
2199 1.45 mlelstv ++lo;
2200 1.45 mlelstv } else if (t == hi) {
2201 1.109 christos if (t == TIME_T_MIN)
2202 1.91 christos goto out_of_range;
2203 1.45 mlelstv --t;
2204 1.45 mlelstv --hi;
2205 1.45 mlelstv }
2206 1.59 christos #ifdef NO_ERROR_IN_DST_GAP
2207 1.64 christos if (ilo != lo && lo - 1 == hi && yourtm.tm_isdst < 0 &&
2208 1.64 christos do_norm_secs) {
2209 1.59 christos for (i = sp->typecnt - 1; i >= 0; --i) {
2210 1.59 christos for (j = sp->typecnt - 1; j >= 0; --j) {
2211 1.64 christos time_t off;
2212 1.59 christos if (sp->ttis[j].tt_isdst ==
2213 1.59 christos sp->ttis[i].tt_isdst)
2214 1.59 christos continue;
2215 1.127 christos if (ttunspecified(sp, j))
2216 1.127 christos continue;
2217 1.122 christos off = sp->ttis[j].tt_utoff -
2218 1.122 christos sp->ttis[i].tt_utoff;
2219 1.64 christos yourtm.tm_sec += off < 0 ?
2220 1.64 christos -off : off;
2221 1.64 christos goto again;
2222 1.59 christos }
2223 1.59 christos }
2224 1.59 christos }
2225 1.59 christos #endif
2226 1.45 mlelstv if (lo > hi)
2227 1.60 christos goto invalid;
2228 1.45 mlelstv if (dir > 0)
2229 1.45 mlelstv hi = t;
2230 1.45 mlelstv else lo = t;
2231 1.1 jtc continue;
2232 1.1 jtc }
2233 1.87 christos #if defined TM_GMTOFF && ! UNINIT_TRAP
2234 1.87 christos if (mytm.TM_GMTOFF != yourtm.TM_GMTOFF
2235 1.87 christos && (yourtm.TM_GMTOFF < 0
2236 1.87 christos ? (-SECSPERDAY <= yourtm.TM_GMTOFF
2237 1.87 christos && (mytm.TM_GMTOFF <=
2238 1.124 christos (/*CONSTCOND*/SMALLEST(INT_FAST32_MAX, LONG_MAX)
2239 1.87 christos + yourtm.TM_GMTOFF)))
2240 1.87 christos : (yourtm.TM_GMTOFF <= SECSPERDAY
2241 1.124 christos && ((/*CONSTCOND*/BIGGEST(INT_FAST32_MIN, LONG_MIN)
2242 1.87 christos + yourtm.TM_GMTOFF)
2243 1.87 christos <= mytm.TM_GMTOFF)))) {
2244 1.111 christos /* MYTM matches YOURTM except with the wrong UT offset.
2245 1.87 christos YOURTM.TM_GMTOFF is plausible, so try it instead.
2246 1.87 christos It's OK if YOURTM.TM_GMTOFF contains uninitialized data,
2247 1.87 christos since the guess gets checked. */
2248 1.126 christos __time_t altt = t;
2249 1.87 christos int_fast32_t diff = (int_fast32_t)
2250 1.87 christos (mytm.TM_GMTOFF - yourtm.TM_GMTOFF);
2251 1.87 christos if (!increment_overflow_time(&altt, diff)) {
2252 1.87 christos struct tm alttm;
2253 1.126 christos time_t xaltt = (time_t)altt;
2254 1.126 christos if (funcp(sp, &xaltt, offset, &alttm)
2255 1.87 christos && alttm.tm_isdst == mytm.tm_isdst
2256 1.87 christos && alttm.TM_GMTOFF == yourtm.TM_GMTOFF
2257 1.124 christos && tmcomp(&alttm, &yourtm) == 0) {
2258 1.126 christos t = xaltt;
2259 1.87 christos mytm = alttm;
2260 1.87 christos }
2261 1.87 christos }
2262 1.87 christos }
2263 1.87 christos #endif
2264 1.1 jtc if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2265 1.1 jtc break;
2266 1.1 jtc /*
2267 1.1 jtc ** Right time, wrong type.
2268 1.1 jtc ** Hunt for right time, right type.
2269 1.1 jtc ** It's okay to guess wrong since the guess
2270 1.1 jtc ** gets checked.
2271 1.1 jtc */
2272 1.1 jtc if (sp == NULL)
2273 1.60 christos goto invalid;
2274 1.5 jtc for (i = sp->typecnt - 1; i >= 0; --i) {
2275 1.1 jtc if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2276 1.1 jtc continue;
2277 1.5 jtc for (j = sp->typecnt - 1; j >= 0; --j) {
2278 1.1 jtc if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2279 1.1 jtc continue;
2280 1.122 christos newt = (time_t)(t + sp->ttis[j].tt_utoff -
2281 1.122 christos sp->ttis[i].tt_utoff);
2282 1.87 christos if (! funcp(sp, &newt, offset, &mytm))
2283 1.45 mlelstv continue;
2284 1.1 jtc if (tmcomp(&mytm, &yourtm) != 0)
2285 1.1 jtc continue;
2286 1.1 jtc if (mytm.tm_isdst != yourtm.tm_isdst)
2287 1.1 jtc continue;
2288 1.1 jtc /*
2289 1.1 jtc ** We have a match.
2290 1.1 jtc */
2291 1.1 jtc t = newt;
2292 1.1 jtc goto label;
2293 1.1 jtc }
2294 1.1 jtc }
2295 1.60 christos goto invalid;
2296 1.1 jtc }
2297 1.1 jtc label:
2298 1.1 jtc newt = t + saved_seconds;
2299 1.1 jtc if ((newt < t) != (saved_seconds < 0))
2300 1.91 christos goto out_of_range;
2301 1.1 jtc t = newt;
2302 1.87 christos if (funcp(sp, &t, offset, tmp)) {
2303 1.87 christos *okayp = true;
2304 1.51 christos return t;
2305 1.60 christos }
2306 1.91 christos out_of_range:
2307 1.60 christos errno = EOVERFLOW;
2308 1.60 christos return WRONG;
2309 1.60 christos invalid:
2310 1.60 christos errno = EINVAL;
2311 1.60 christos return WRONG;
2312 1.13 jtc }
2313 1.13 jtc
2314 1.13 jtc static time_t
2315 1.87 christos time2(struct tm * const tmp,
2316 1.87 christos struct tm *(*funcp)(struct state const *, time_t const *,
2317 1.87 christos int_fast32_t, struct tm *),
2318 1.87 christos struct state const *sp,
2319 1.87 christos const int_fast32_t offset,
2320 1.87 christos bool *okayp)
2321 1.13 jtc {
2322 1.13 jtc time_t t;
2323 1.13 jtc
2324 1.13 jtc /*
2325 1.13 jtc ** First try without normalization of seconds
2326 1.13 jtc ** (in case tm_sec contains a value associated with a leap second).
2327 1.13 jtc ** If that fails, try with normalization of seconds.
2328 1.13 jtc */
2329 1.87 christos t = time2sub(tmp, funcp, sp, offset, okayp, false);
2330 1.87 christos return *okayp ? t : time2sub(tmp, funcp, sp, offset, okayp, true);
2331 1.1 jtc }
2332 1.1 jtc
2333 1.1 jtc static time_t
2334 1.87 christos time1(struct tm *const tmp,
2335 1.124 christos struct tm *(*funcp)(struct state const *, time_t const *,
2336 1.124 christos int_fast32_t, struct tm *),
2337 1.87 christos struct state const *sp,
2338 1.87 christos const int_fast32_t offset)
2339 1.49 christos {
2340 1.49 christos time_t t;
2341 1.49 christos int samei, otheri;
2342 1.49 christos int sameind, otherind;
2343 1.49 christos int i;
2344 1.49 christos int nseen;
2345 1.90 christos int save_errno;
2346 1.83 christos char seen[TZ_MAX_TYPES];
2347 1.83 christos unsigned char types[TZ_MAX_TYPES];
2348 1.87 christos bool okay;
2349 1.1 jtc
2350 1.58 christos if (tmp == NULL) {
2351 1.58 christos errno = EINVAL;
2352 1.58 christos return WRONG;
2353 1.58 christos }
2354 1.1 jtc if (tmp->tm_isdst > 1)
2355 1.1 jtc tmp->tm_isdst = 1;
2356 1.90 christos save_errno = errno;
2357 1.87 christos t = time2(tmp, funcp, sp, offset, &okay);
2358 1.90 christos if (okay) {
2359 1.90 christos errno = save_errno;
2360 1.1 jtc return t;
2361 1.90 christos }
2362 1.1 jtc if (tmp->tm_isdst < 0)
2363 1.82 christos #ifdef PCTS
2364 1.82 christos /*
2365 1.82 christos ** POSIX Conformance Test Suite code courtesy Grant Sullivan.
2366 1.82 christos */
2367 1.1 jtc tmp->tm_isdst = 0; /* reset to std and try again */
2368 1.82 christos #else
2369 1.1 jtc return t;
2370 1.1 jtc #endif /* !defined PCTS */
2371 1.1 jtc /*
2372 1.1 jtc ** We're supposed to assume that somebody took a time of one type
2373 1.1 jtc ** and did some math on it that yielded a "struct tm" that's bad.
2374 1.1 jtc ** We try to divine the type they started from and adjust to the
2375 1.1 jtc ** type they need.
2376 1.1 jtc */
2377 1.60 christos if (sp == NULL) {
2378 1.60 christos errno = EINVAL;
2379 1.1 jtc return WRONG;
2380 1.60 christos }
2381 1.35 kleink for (i = 0; i < sp->typecnt; ++i)
2382 1.87 christos seen[i] = false;
2383 1.35 kleink nseen = 0;
2384 1.35 kleink for (i = sp->timecnt - 1; i >= 0; --i)
2385 1.127 christos if (!seen[sp->types[i]] && !ttunspecified(sp, sp->types[i])) {
2386 1.87 christos seen[sp->types[i]] = true;
2387 1.35 kleink types[nseen++] = sp->types[i];
2388 1.35 kleink }
2389 1.35 kleink for (sameind = 0; sameind < nseen; ++sameind) {
2390 1.35 kleink samei = types[sameind];
2391 1.1 jtc if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2392 1.1 jtc continue;
2393 1.35 kleink for (otherind = 0; otherind < nseen; ++otherind) {
2394 1.35 kleink otheri = types[otherind];
2395 1.1 jtc if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2396 1.1 jtc continue;
2397 1.122 christos tmp->tm_sec += (int)(sp->ttis[otheri].tt_utoff -
2398 1.122 christos sp->ttis[samei].tt_utoff);
2399 1.1 jtc tmp->tm_isdst = !tmp->tm_isdst;
2400 1.87 christos t = time2(tmp, funcp, sp, offset, &okay);
2401 1.90 christos if (okay) {
2402 1.90 christos errno = save_errno;
2403 1.1 jtc return t;
2404 1.90 christos }
2405 1.122 christos tmp->tm_sec -= (int)(sp->ttis[otheri].tt_utoff -
2406 1.122 christos sp->ttis[samei].tt_utoff);
2407 1.1 jtc tmp->tm_isdst = !tmp->tm_isdst;
2408 1.1 jtc }
2409 1.1 jtc }
2410 1.60 christos errno = EOVERFLOW;
2411 1.1 jtc return WRONG;
2412 1.1 jtc }
2413 1.1 jtc
2414 1.87 christos static time_t
2415 1.87 christos mktime_tzname(timezone_t sp, struct tm *tmp, bool setname)
2416 1.87 christos {
2417 1.87 christos if (sp)
2418 1.87 christos return time1(tmp, localsub, sp, setname);
2419 1.87 christos else {
2420 1.87 christos gmtcheck();
2421 1.87 christos return time1(tmp, gmtsub, gmtptr, 0);
2422 1.87 christos }
2423 1.87 christos }
2424 1.87 christos
2425 1.87 christos #if NETBSD_INSPIRED
2426 1.87 christos
2427 1.1 jtc time_t
2428 1.87 christos mktime_z(timezone_t sp, struct tm *const tmp)
2429 1.49 christos {
2430 1.87 christos return mktime_tzname(sp, tmp, false);
2431 1.49 christos }
2432 1.49 christos
2433 1.87 christos #endif
2434 1.87 christos
2435 1.49 christos time_t
2436 1.96 christos mktime(struct tm *tmp)
2437 1.1 jtc {
2438 1.87 christos time_t t;
2439 1.19 kleink
2440 1.117 christos rwlock_wrlock(&__lcl_lock);
2441 1.45 mlelstv tzset_unlocked();
2442 1.117 christos t = mktime_tzname(__lclptr, tmp, true);
2443 1.117 christos rwlock_unlock(&__lcl_lock);
2444 1.87 christos return t;
2445 1.1 jtc }
2446 1.1 jtc
2447 1.1 jtc #ifdef STD_INSPIRED
2448 1.1 jtc
2449 1.1 jtc time_t
2450 1.68 christos timelocal_z(const timezone_t sp, struct tm *const tmp)
2451 1.49 christos {
2452 1.49 christos if (tmp != NULL)
2453 1.49 christos tmp->tm_isdst = -1; /* in case it wasn't initialized */
2454 1.49 christos return mktime_z(sp, tmp);
2455 1.49 christos }
2456 1.49 christos
2457 1.49 christos time_t
2458 1.96 christos timelocal(struct tm *tmp)
2459 1.1 jtc {
2460 1.58 christos if (tmp != NULL)
2461 1.58 christos tmp->tm_isdst = -1; /* in case it wasn't initialized */
2462 1.1 jtc return mktime(tmp);
2463 1.1 jtc }
2464 1.1 jtc
2465 1.1 jtc time_t
2466 1.96 christos timegm(struct tm *tmp)
2467 1.1 jtc {
2468 1.51 christos
2469 1.87 christos return timeoff(tmp, 0);
2470 1.1 jtc }
2471 1.1 jtc
2472 1.1 jtc time_t
2473 1.96 christos timeoff(struct tm *tmp, long offset)
2474 1.1 jtc {
2475 1.87 christos if (tmp)
2476 1.58 christos tmp->tm_isdst = 0;
2477 1.87 christos gmtcheck();
2478 1.87 christos return time1(tmp, gmtsub, gmtptr, (int_fast32_t)offset);
2479 1.1 jtc }
2480 1.1 jtc
2481 1.1 jtc #endif /* defined STD_INSPIRED */
2482 1.1 jtc
2483 1.124 christos static int_fast32_t
2484 1.123 christos leapcorr(struct state const *sp, time_t t)
2485 1.1 jtc {
2486 1.87 christos struct lsinfo const * lp;
2487 1.49 christos int i;
2488 1.1 jtc
2489 1.1 jtc i = sp->leapcnt;
2490 1.1 jtc while (--i >= 0) {
2491 1.1 jtc lp = &sp->lsis[i];
2492 1.87 christos if (t >= lp->ls_trans)
2493 1.1 jtc return lp->ls_corr;
2494 1.1 jtc }
2495 1.1 jtc return 0;
2496 1.1 jtc }
2497 1.1 jtc
2498 1.124 christos /* NETBSD_INSPIRED_EXTERN functions are exported to callers if
2499 1.124 christos NETBSD_INSPIRED is defined, and are private otherwise. */
2500 1.124 christos #if NETBSD_INSPIRED
2501 1.124 christos # define NETBSD_INSPIRED_EXTERN
2502 1.124 christos #else
2503 1.124 christos # define NETBSD_INSPIRED_EXTERN static
2504 1.124 christos #endif
2505 1.124 christos
2506 1.124 christos
2507 1.109 christos NETBSD_INSPIRED_EXTERN time_t
2508 1.87 christos time2posix_z(timezone_t sp, time_t t)
2509 1.49 christos {
2510 1.87 christos return (time_t)(t - leapcorr(sp, t));
2511 1.49 christos }
2512 1.49 christos
2513 1.49 christos time_t
2514 1.49 christos time2posix(time_t t)
2515 1.1 jtc {
2516 1.117 christos rwlock_wrlock(&__lcl_lock);
2517 1.87 christos if (!lcl_is_set)
2518 1.87 christos tzset_unlocked();
2519 1.117 christos if (__lclptr)
2520 1.117 christos t = (time_t)(t - leapcorr(__lclptr, t));
2521 1.117 christos rwlock_unlock(&__lcl_lock);
2522 1.87 christos return t;
2523 1.1 jtc }
2524 1.1 jtc
2525 1.123 christos /*
2526 1.123 christos ** XXX--is the below the right way to conditionalize??
2527 1.123 christos */
2528 1.123 christos
2529 1.123 christos #ifdef STD_INSPIRED
2530 1.123 christos
2531 1.123 christos /*
2532 1.123 christos ** IEEE Std 1003.1 (POSIX) says that 536457599
2533 1.123 christos ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2534 1.123 christos ** is not the case if we are accounting for leap seconds.
2535 1.123 christos ** So, we provide the following conversion routines for use
2536 1.123 christos ** when exchanging timestamps with POSIX conforming systems.
2537 1.123 christos */
2538 1.123 christos
2539 1.109 christos NETBSD_INSPIRED_EXTERN time_t
2540 1.87 christos posix2time_z(timezone_t sp, time_t t)
2541 1.1 jtc {
2542 1.1 jtc time_t x;
2543 1.1 jtc time_t y;
2544 1.1 jtc /*
2545 1.1 jtc ** For a positive leap second hit, the result
2546 1.45 mlelstv ** is not unique. For a negative leap second
2547 1.1 jtc ** hit, the corresponding time doesn't exist,
2548 1.1 jtc ** so we return an adjacent second.
2549 1.1 jtc */
2550 1.87 christos x = (time_t)(t + leapcorr(sp, t));
2551 1.87 christos y = (time_t)(x - leapcorr(sp, x));
2552 1.1 jtc if (y < t) {
2553 1.1 jtc do {
2554 1.1 jtc x++;
2555 1.87 christos y = (time_t)(x - leapcorr(sp, x));
2556 1.1 jtc } while (y < t);
2557 1.87 christos x -= y != t;
2558 1.1 jtc } else if (y > t) {
2559 1.1 jtc do {
2560 1.1 jtc --x;
2561 1.87 christos y = (time_t)(x - leapcorr(sp, x));
2562 1.1 jtc } while (y > t);
2563 1.87 christos x += y != t;
2564 1.1 jtc }
2565 1.49 christos return x;
2566 1.49 christos }
2567 1.49 christos
2568 1.49 christos time_t
2569 1.49 christos posix2time(time_t t)
2570 1.49 christos {
2571 1.117 christos rwlock_wrlock(&__lcl_lock);
2572 1.87 christos if (!lcl_is_set)
2573 1.87 christos tzset_unlocked();
2574 1.117 christos if (__lclptr)
2575 1.117 christos t = posix2time_z(__lclptr, t);
2576 1.117 christos rwlock_unlock(&__lcl_lock);
2577 1.87 christos return t;
2578 1.1 jtc }
2579 1.1 jtc
2580 1.1 jtc #endif /* defined STD_INSPIRED */
2581