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