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