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