1 /*-
2 * Copyright (c) 2004, 2005, 2007, 2011
3 * Thorsten Glaser <tg@mirbsd.org>
4 * Based upon work placed in the public domain 1996-06-05 by
5 * Arthur David Olson (arthur_david_olson@nih.gov)
6 *
7 * Provided that these terms and disclaimer and all copyright notices
8 * are retained or reproduced in an accompanying document, permission
9 * is granted to deal in this work without restriction, including un-
10 * limited rights to use, publicly perform, distribute, sell, modify,
11 * merge, give away, or sublicence.
12 *
13 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
14 * the utmost extent permitted by applicable law, neither express nor
15 * implied; without malicious intent or gross negligence. In no event
16 * may a licensor, author or contributor be held liable for indirect,
17 * direct, other damage, loss, or other issues arising in any way out
18 * of dealing in the work, even if advised of the possibility of such
19 * damage or existence of a defect, except proven that it results out
20 * of said person's immediate fault when using the work as intended.
21 */
22
23 #include <sys/param.h>
24
25 __SCCSID("@(#)localtime.c 7.80");
26 __RCSID("$MirOS: src/lib/libc/time/localtime.c,v 1.18 2011/11/20 21:30:56 tg Exp $");
27
28 struct tm *offtime(const time_t * const, const long);
29
30 /*
31 ** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
32 ** POSIX-style TZ environment variable handling from Guy Harris
33 ** (guy@auspex.com).
34 */
35
36 /* LINTLIBRARY */
37
38 #include <syskern/mirtime.h>
39 #include "private.h"
40 #include "tzfile.h"
41 #include "fcntl.h"
42 #include "float.h" /* for FLT_MAX and DBL_MAX */
43 #include "thread_private.h"
44
45 #ifndef TZ_ABBR_MAX_LEN
46 #define TZ_ABBR_MAX_LEN 16
47 #endif /* !defined TZ_ABBR_MAX_LEN */
48
49 #ifndef TZ_ABBR_CHAR_SET
50 #define TZ_ABBR_CHAR_SET \
51 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
52 #endif /* !defined TZ_ABBR_CHAR_SET */
53
54 #ifndef TZ_ABBR_ERR_CHAR
55 #define TZ_ABBR_ERR_CHAR '_'
56 #endif /* !defined TZ_ABBR_ERR_CHAR */
57
58 /*
59 ** SunOS 4.1.1 headers lack O_BINARY.
60 */
61
62 #ifdef O_BINARY
63 #define OPEN_MODE (O_RDONLY | O_BINARY)
64 #else
65 #define OPEN_MODE O_RDONLY
66 #endif
67
68 #ifndef WILDABBR
69 /*
70 ** Someone might make incorrect use of a time zone abbreviation:
71 ** 1. They might reference tzname[0] before calling tzset (explicitly
72 ** or implicitly).
73 ** 2. They might reference tzname[1] before calling tzset (explicitly
74 ** or implicitly).
75 ** 3. They might reference tzname[1] after setting to a time zone
76 ** in which Daylight Saving Time is never observed.
77 ** 4. They might reference tzname[0] after setting to a time zone
78 ** in which Standard Time is never observed.
79 ** 5. They might reference tm.TM_ZONE after calling offtime.
80 ** What's best to do in the above cases is open to debate;
81 ** for now, we just set things up so that in any of the five cases
82 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
83 ** string "tzname[0] used before set", and similarly for the other cases.
84 ** And another: initialize tzname[0] to "ERA", with an explanation in the
85 ** manual page of what this "time zone abbreviation" means (doing this so
86 ** that tzname[0] has the "normal" length of three characters).
87 */
88 #define WILDABBR " "
89 #endif
90
91 static char wildabbr[] = WILDABBR;
92 static const char gmt[] = "UTC";
93
94 /*
95 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
96 ** We default to US rules as of 1999-08-17.
97 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
98 ** implementation dependent; for historical reasons, US rules are a
99 ** common default.
100 */
101 #ifndef TZDEFRULESTRING
102 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
103 #endif
104
105 struct ttinfo { /* time type information */
106 long tt_gmtoff; /* UTC offset in seconds */
107 int tt_isdst; /* used to set tm_isdst */
108 int tt_abbrind; /* abbreviation list index */
109 int tt_ttisstd; /* TRUE if transition is std time */
110 int tt_ttisgmt; /* TRUE if transition is UTC */
111 };
112
113 struct lsinfo { /* leap second information */
114 time_t ls_trans; /* transition time */
115 long ls_corr; /* correction to apply */
116 };
117
118 #ifdef TZNAME_MAX
119 #define MY_TZNAME_MAX TZNAME_MAX
120 #else
121 #define MY_TZNAME_MAX 255
122 #endif
123
124 struct state {
125 int leapcnt;
126 int timecnt;
127 int typecnt;
128 int charcnt;
129 time_t ats[TZ_MAX_TIMES];
130 unsigned char types[TZ_MAX_TIMES];
131 struct ttinfo ttis[TZ_MAX_TYPES];
132 /* CONSTCOND */
133 char chars[MAX(MAX(TZ_MAX_CHARS + 1, sizeof gmt),
134 (2 * (MY_TZNAME_MAX + 1)))];
135 struct lsinfo lsis[TZ_MAX_LEAPS];
136 };
137
138 struct rule {
139 int r_type; /* type of rule--see below */
140 int r_day; /* day number of rule */
141 int r_week; /* week number of rule */
142 int r_mon; /* month number of rule */
143 long r_time; /* transition time of rule */
144 };
145
146 #define JULIAN_DAY 0 /* Jn - Julian day */
147 #define DAY_OF_YEAR 1 /* n - day of year */
148 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
149
150 /*
151 ** Prototypes for static functions.
152 */
153
154 static long detzcode(const char *codep);
155 static const char *getzname(const char *strp);
156 static const char *getqzname(const char * strp, const char delim);
157 static const char *getnum(const char *strp, int *nump, int min, int max);
158 static const char *getsecs(const char *strp, long *secsp);
159 static const char *getoffset(const char *strp, long *offsetp);
160 static const char *getrule(const char *strp, struct rule *rulep);
161 static void gmtload(struct state *sp);
162 static struct tm *gmtsub(const time_t *timep, long offset, struct tm *tmp);
163 static struct tm *localsub(const time_t *timep, long offset, struct tm *tmp);
164 static int increment_overflow(int *number, int delta);
165 static int leaps_thru_end_of(int y);
166 static int long_increment_overflow(time_t *number, time_t delta);
167 static int long_normalize_overflow(time_t *tensptr, int *unitsptr, int base);
168 static int normalize_overflow(int *tensptr, int *unitsptr, int base);
169 static void settzname(void);
170 static time_t time1(struct tm *tmp, struct tm *(*funcp) (const time_t *, long, struct tm *), long offset);
171 static time_t time2(struct tm *tmp, struct tm *(*funcp) (const time_t *, long, struct tm *), long offset, int *okayp);
172 static time_t time2sub(struct tm *tmp, struct tm *(*funcp) (const time_t *, long, struct tm *), long offset, int *okayp, int do_norm_secs);
173 static struct tm *timesub(const time_t *timep, long offset, const struct state *sp, struct tm *tmp);
174 static int tmcomp(const struct tm *atmp, const struct tm *btmp);
175 static time_t transtime(time_t janfirst, int year, const struct rule *rulep, long offset);
176 static int tzload(const char *name, struct state *sp);
177 static int tzparse(const char *name, struct state *sp, int lastditch);
178
179 static struct state lclmem;
180 static struct state gmtmem;
181 #define lclptr (&lclmem)
182 #define gmtptr (&gmtmem)
183
184 #ifndef TZ_STRLEN_MAX
185 #define TZ_STRLEN_MAX 255
186 #endif
187
188 static char lcl_TZname[TZ_STRLEN_MAX + 1];
189 static int lcl_is_set;
190 static int gmt_is_set;
191 _THREAD_PRIVATE_MUTEX(lcl);
192 _THREAD_PRIVATE_MUTEX(gmt);
193
194 char *tzname[2] = {
195 wildabbr,
196 wildabbr
197 };
198
199 /*
200 ** Section 4.12.3 of X3.159-1989 requires that
201 ** Except for the strftime function, these functions [asctime,
202 ** ctime, gmtime, localtime] return values in one of two static
203 ** objects: a broken-down time structure and an array of char.
204 ** Thanks to Paul Eggert (eggert@twinsun.com) for noting this.
205 */
206
207 static struct tm tm;
208
209 static long
detzcode(codep)210 detzcode(codep)
211 const char *const codep;
212 {
213 long result;
214 int i;
215
216 result = (codep[0] & 0x80) ? ~0L : 0L;
217 for (i = 0; i < 4; ++i)
218 result = (result << 8) | (codep[i] & 0xff);
219 return result;
220 }
221
222 static void
settzname(void)223 settzname(void)
224 {
225 struct state *const sp = lclptr;
226 int i;
227
228 tzname[0] = wildabbr;
229 tzname[1] = wildabbr;
230 for (i = 0; i < sp->typecnt; ++i) {
231 const struct ttinfo *const ttisp = &sp->ttis[i];
232
233 tzname[ttisp->tt_isdst] =
234 &sp->chars[ttisp->tt_abbrind];
235 }
236 /*
237 ** And to get the latest zone names into tzname. . .
238 */
239 for (i = 0; i < sp->timecnt; ++i) {
240 const struct ttinfo *const ttisp =
241 &sp->ttis[
242 sp->types[i]];
243
244 tzname[ttisp->tt_isdst] =
245 &sp->chars[ttisp->tt_abbrind];
246 }
247 /*
248 ** Finally, scrub the abbreviations.
249 ** First, replace bogus characters.
250 */
251 for (i = 0; i < sp->charcnt; ++i)
252 if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
253 sp->chars[i] = TZ_ABBR_ERR_CHAR;
254 /*
255 ** Second, truncate long abbreviations.
256 */
257 for (i = 0; i < sp->typecnt; ++i) {
258 register const struct ttinfo * const ttisp = &sp->ttis[i];
259 register char * cp = &sp->chars[ttisp->tt_abbrind];
260
261 if (strlen(cp) > TZ_ABBR_MAX_LEN &&
262 strcmp(cp, GRANDPARENTED) != 0)
263 *(cp + TZ_ABBR_MAX_LEN) = '\0';
264 }
265 }
266
267 static int
tzload(name,sp)268 tzload(name, sp)
269 const char *name;
270 struct state *const sp;
271 {
272 const char *p;
273 int i;
274 int fid;
275
276 if (name != NULL && issetugid() != 0)
277 if ((name[0] == ':' && (strchr(name, '/') || strstr(name, ".."))) ||
278 name[0] == '/' || strchr(name, '.'))
279 name = NULL;
280 if (name == NULL && (name = TZDEFAULT) == NULL)
281 return -1;
282 {
283 int doaccess;
284 /*
285 ** Section 4.9.1 of the C standard says that
286 ** "FILENAME_MAX expands to an integral constant expression
287 ** that is the size needed for an array of char large enough
288 ** to hold the longest file name string that the implementation
289 ** guarantees can be opened."
290 */
291 char fullname[FILENAME_MAX];
292
293 if (name[0] == ':')
294 ++name;
295 doaccess = name[0] == '/';
296 if (!doaccess) {
297 if ((p = TZDIR) == NULL)
298 return -1;
299 if ((strlen(p) + strlen(name) + 1) >= sizeof fullname)
300 return -1;
301 (void)strlcpy(fullname, p, sizeof fullname);
302 (void)strlcat(fullname, "/", sizeof fullname);
303 (void)strlcat(fullname, name, sizeof fullname);
304 /*
305 ** Set doaccess if '.' (as in "../") shows up in name.
306 */
307 if (strchr(name, '.') != NULL)
308 doaccess = TRUE;
309 name = fullname;
310 }
311 if (doaccess && access(name, R_OK) != 0)
312 return -1;
313 if ((fid = open(name, OPEN_MODE)) == -1)
314 return -1;
315 }
316 {
317 struct tzhead *tzhp;
318 union {
319 struct tzhead tzhead;
320 char buf[sizeof *sp + sizeof *tzhp];
321 } u;
322 int ttisstdcnt;
323 int ttisgmtcnt;
324
325 i = read(fid, u.buf, sizeof u.buf);
326 if (close(fid) != 0)
327 return -1;
328 ttisstdcnt = (int)detzcode(u.tzhead.tzh_ttisstdcnt);
329 ttisgmtcnt = (int)detzcode(u.tzhead.tzh_ttisgmtcnt);
330 sp->leapcnt = (int)detzcode(u.tzhead.tzh_leapcnt);
331 sp->timecnt = (int)detzcode(u.tzhead.tzh_timecnt);
332 sp->typecnt = (int)detzcode(u.tzhead.tzh_typecnt);
333 sp->charcnt = (int)detzcode(u.tzhead.tzh_charcnt);
334 p = u.tzhead.tzh_charcnt + sizeof u.tzhead.tzh_charcnt;
335 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
336 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
337 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
338 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
339 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
340 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
341 return -1;
342 if (i - (p - u.buf)<sp->timecnt * 4 + /* ats */
343 sp->timecnt + /* types */
344 sp->typecnt * (4 + 2) + /* ttinfos */
345 sp->charcnt + /* chars */
346 sp->leapcnt * (4 + 4) + /* lsinfos */
347 ttisstdcnt + /* ttisstds */
348 ttisgmtcnt) /* ttisgmts */
349 return -1;
350 for (i = 0; i < sp->timecnt; ++i) {
351 sp->ats[i] = detzcode(p);
352 p += 4;
353 }
354 for (i = 0; i < sp->timecnt; ++i) {
355 sp->types[i] = (unsigned char)*p++;
356 if (sp->types[i] >= sp->typecnt)
357 return -1;
358 }
359 for (i = 0; i < sp->typecnt; ++i) {
360 struct ttinfo *ttisp;
361
362 ttisp = &sp->ttis[i];
363 ttisp->tt_gmtoff = detzcode(p);
364 p += 4;
365 ttisp->tt_isdst = (unsigned char)*p++;
366 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
367 return -1;
368 ttisp->tt_abbrind = (unsigned char)*p++;
369 if (ttisp->tt_abbrind < 0 ||
370 ttisp->tt_abbrind > sp->charcnt)
371 return -1;
372 }
373 for (i = 0; i < sp->charcnt; ++i)
374 sp->chars[i] = *p++;
375 sp->chars[i] = '\0'; /* ensure '\0' at end */
376 for (i = 0; i < sp->leapcnt; ++i) {
377 struct lsinfo *lsisp;
378
379 lsisp = &sp->lsis[i];
380 lsisp->ls_trans = detzcode(p);
381 p += 4;
382 lsisp->ls_corr = detzcode(p);
383 p += 4;
384 }
385 for (i = 0; i < sp->typecnt; ++i) {
386 struct ttinfo *ttisp;
387
388 ttisp = &sp->ttis[i];
389 if (ttisstdcnt == 0)
390 ttisp->tt_ttisstd = FALSE;
391 else {
392 ttisp->tt_ttisstd = *p++;
393 if (ttisp->tt_ttisstd != TRUE &&
394 ttisp->tt_ttisstd != FALSE)
395 return -1;
396 }
397 }
398 for (i = 0; i < sp->typecnt; ++i) {
399 struct ttinfo *ttisp;
400
401 ttisp = &sp->ttis[i];
402 if (ttisgmtcnt == 0)
403 ttisp->tt_ttisgmt = FALSE;
404 else {
405 ttisp->tt_ttisgmt = *p++;
406 if (ttisp->tt_ttisgmt != TRUE &&
407 ttisp->tt_ttisgmt != FALSE)
408 return -1;
409 }
410 }
411 /*
412 ** Out-of-sort ats should mean we're running on a
413 ** signed time_t system but using a data file with
414 ** unsigned values (or vice versa).
415 */
416 for (i = 0; i < sp->timecnt - 2; ++i)
417 if (sp->ats[i] > sp->ats[i + 1]) {
418 ++i;
419 if (TYPE_SIGNED(time_t)) {
420 /*
421 ** Ignore the end (easy).
422 */
423 sp->timecnt = i;
424 } else {
425 /*
426 ** Ignore the beginning (harder).
427 */
428 register int j;
429
430 for (j = 0; j + i < sp->timecnt; ++j) {
431 sp->ats[j] = sp->ats[j + i];
432 sp->types[j] = sp->types[j + i];
433 }
434 sp->timecnt = j;
435 }
436 break;
437 }
438 }
439 #ifdef SKIP_LEAPSECS
440 for (i = 0; i < sp->leapcnt; ++i) {
441 struct lsinfo *lsisp;
442
443 lsisp = &sp->lsis[i];
444 lsisp->ls_trans = 0;
445 lsisp->ls_corr = 0;
446 }
447 sp->leapcnt = 0;
448 #undef SKIPPED_LEAPSECS
449 #define SKIPPED_LEAPSECS 1
450 #endif
451 return 0;
452 }
453
454 static const int mon_lengths[2][MONSPERYEAR] = {
455 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
456 {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
457 };
458
459 static const int year_lengths[2] = {
460 DAYSPERNYEAR, DAYSPERLYEAR
461 };
462
463 /*
464 ** Given a pointer into a time zone string, scan until a character that is not
465 ** a valid character in a zone name is found. Return a pointer to that
466 ** character.
467 */
468
469 static const char *
getzname(strp)470 getzname(strp)
471 const char *strp;
472 {
473 char c;
474
475 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
476 c != '+')
477 ++strp;
478 return strp;
479 }
480
481 /*
482 ** Given a pointer into an extended time zone string, scan until the ending
483 ** delimiter of the zone name is located. Return a pointer to the delimiter.
484 **
485 ** As with getzname above, the legal character set is actually quite
486 ** restricted, with other characters producing undefined results.
487 ** We choose not to care - allowing almost anything to be in the zone abbrev.
488 */
489
490 static const char *
getqzname(strp,delim)491 getqzname(strp, delim)
492 register const char * strp;
493 const char delim;
494 {
495 register char c;
496
497 while ((c = *strp) != '\0' && c != delim)
498 ++strp;
499 return strp;
500 }
501
502 /*
503 ** Given a pointer into a time zone string, extract a number from that string.
504 ** Check that the number is within a specified range; if it is not, return
505 ** NULL.
506 ** Otherwise, return a pointer to the first character not part of the number.
507 */
508
509 static const char *
getnum(strp,nump,min,max)510 getnum(strp, nump, min, max)
511 const char *strp;
512 int *const nump;
513 const int min;
514 const int max;
515 {
516 char c;
517 int num;
518
519 if (strp == NULL || !is_digit(c = *strp))
520 return NULL;
521 num = 0;
522 do {
523 num = num * 10 + (c - '0');
524 if (num > max)
525 return NULL; /* illegal value */
526 c = *++strp;
527 } while (is_digit(c));
528 if (num < min)
529 return NULL; /* illegal value */
530 *nump = num;
531 return strp;
532 }
533
534 /*
535 ** Given a pointer into a time zone string, extract a number of seconds,
536 ** in hh[:mm[:ss]] form, from the string.
537 ** If any error occurs, return NULL.
538 ** Otherwise, return a pointer to the first character not part of the number
539 ** of seconds.
540 */
541
542 static const char *
getsecs(strp,secsp)543 getsecs(strp, secsp)
544 const char *strp;
545 long *const secsp;
546 {
547 int num;
548
549 /*
550 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
551 ** "M10.4.6/26", which does not conform to Posix,
552 ** but which specifies the equivalent of
553 ** ``02:00 on the first Sunday on or after 23 Oct''.
554 */
555 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
556 if (strp == NULL)
557 return NULL;
558 *secsp = num * (long)SECSPERHOUR;
559 if (*strp == ':') {
560 ++strp;
561 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
562 if (strp == NULL)
563 return NULL;
564 *secsp += num * SECSPERMIN;
565 if (*strp == ':') {
566 ++strp;
567 /* `SECSPERMIN' allows for leap seconds. */
568 strp = getnum(strp, &num, 0, SECSPERMIN);
569 if (strp == NULL)
570 return NULL;
571 *secsp += num;
572 }
573 }
574 return strp;
575 }
576
577 /*
578 ** Given a pointer into a time zone string, extract an offset, in
579 ** [+-]hh[:mm[:ss]] form, from the string.
580 ** If any error occurs, return NULL.
581 ** Otherwise, return a pointer to the first character not part of the time.
582 */
583
584 static const char *
getoffset(strp,offsetp)585 getoffset(strp, offsetp)
586 const char *strp;
587 long *const offsetp;
588 {
589 int neg = 0;
590
591 if (*strp == '-') {
592 neg = 1;
593 ++strp;
594 } else if (*strp == '+')
595 ++strp;
596 strp = getsecs(strp, offsetp);
597 if (strp == NULL)
598 return NULL; /* illegal time */
599 if (neg)
600 *offsetp = -*offsetp;
601 return strp;
602 }
603
604 /*
605 ** Given a pointer into a time zone string, extract a rule in the form
606 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
607 ** If a valid rule is not found, return NULL.
608 ** Otherwise, return a pointer to the first character not part of the rule.
609 */
610
611 static const char *
getrule(strp,rulep)612 getrule(strp, rulep)
613 const char *strp;
614 struct rule *const rulep;
615 {
616 if (*strp == 'J') {
617 /*
618 ** Julian day.
619 */
620 rulep->r_type = JULIAN_DAY;
621 ++strp;
622 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
623 } else if (*strp == 'M') {
624 /*
625 ** Month, week, day.
626 */
627 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
628 ++strp;
629 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
630 if (strp == NULL)
631 return NULL;
632 if (*strp++ != '.')
633 return NULL;
634 strp = getnum(strp, &rulep->r_week, 1, 5);
635 if (strp == NULL)
636 return NULL;
637 if (*strp++ != '.')
638 return NULL;
639 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
640 } else if (is_digit(*strp)) {
641 /*
642 ** Day of year.
643 */
644 rulep->r_type = DAY_OF_YEAR;
645 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
646 } else
647 return NULL; /* invalid format */
648 if (strp == NULL)
649 return NULL;
650 if (*strp == '/') {
651 /*
652 ** Time specified.
653 */
654 ++strp;
655 strp = getsecs(strp, &rulep->r_time);
656 } else
657 rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
658 return strp;
659 }
660
661 /*
662 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
663 ** year, a rule, and the offset from UTC at the time that rule takes effect,
664 ** calculate the Epoch-relative time that rule takes effect.
665 */
666
667 static time_t
transtime(janfirst,year,rulep,offset)668 transtime(janfirst, year, rulep, offset)
669 const time_t janfirst;
670 const int year;
671 const struct rule *const rulep;
672 const long offset;
673 {
674 int leapyear;
675 time_t value;
676 int i;
677 int d, m1, yy0, yy1, yy2, dow;
678
679 INITIALIZE(value);
680 leapyear = isleap(year);
681 switch (rulep->r_type) {
682
683 case JULIAN_DAY:
684 /*
685 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
686 ** years.
687 ** In non-leap years, or if the day number is 59 or less, just
688 ** add SECSPERDAY times the day number-1 to the time of
689 ** January 1, midnight, to get the day.
690 */
691 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
692 if (leapyear && rulep->r_day >= 60)
693 value += SECSPERDAY;
694 break;
695
696 case DAY_OF_YEAR:
697 /*
698 ** n - day of year.
699 ** Just add SECSPERDAY times the day number to the time of
700 ** January 1, midnight, to get the day.
701 */
702 value = janfirst + rulep->r_day * SECSPERDAY;
703 break;
704
705 case MONTH_NTH_DAY_OF_WEEK:
706 /*
707 ** Mm.n.d - nth "dth day" of month m.
708 */
709 value = janfirst;
710 for (i = 0; i < rulep->r_mon - 1; ++i)
711 value += mon_lengths[leapyear][i] * SECSPERDAY;
712
713 /*
714 ** Use Zeller's Congruence to get day-of-week of first day of
715 ** month.
716 */
717 m1 = (rulep->r_mon + 9) % 12 + 1;
718 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
719 yy1 = yy0 / 100;
720 yy2 = yy0 % 100;
721 dow = ((26 * m1 - 2) / 10 +
722 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
723 if (dow < 0)
724 dow += DAYSPERWEEK;
725
726 /*
727 ** "dow" is the day-of-week of the first day of the month. Get
728 ** the day-of-month (zero-origin) of the first "dow" day of the
729 ** month.
730 */
731 d = rulep->r_day - dow;
732 if (d < 0)
733 d += DAYSPERWEEK;
734 for (i = 1; i < rulep->r_week; ++i) {
735 if (d + DAYSPERWEEK >=
736 mon_lengths[leapyear][rulep->r_mon - 1])
737 break;
738 d += DAYSPERWEEK;
739 }
740
741 /*
742 ** "d" is the day-of-month (zero-origin) of the day we want.
743 */
744 value += d * SECSPERDAY;
745 break;
746 }
747
748 /*
749 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
750 ** question. To get the Epoch-relative time of the specified local
751 ** time on that day, add the transition time and the current offset
752 ** from UTC.
753 */
754 return value + rulep->r_time + offset;
755 }
756
757 /*
758 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
759 ** appropriate.
760 */
761
762 static int
tzparse(name,sp,lastditch)763 tzparse(name, sp, lastditch)
764 const char *name;
765 struct state *const sp;
766 const int lastditch;
767 {
768 const char *stdname;
769 const char *dstname;
770 size_t stdlen;
771 size_t dstlen;
772 long stdoffset;
773 long dstoffset;
774 time_t *atp;
775 unsigned char *typep;
776 char *cp;
777 int load_result;
778
779 INITIALIZE(dstname);
780 stdname = name;
781 if (lastditch) {
782 stdlen = strlen(name); /* length of standard zone name */
783 name += stdlen;
784 if (stdlen >= sizeof sp->chars)
785 stdlen = (sizeof sp->chars) - 1;
786 stdoffset = 0;
787 } else {
788 if (*name == '<') {
789 name++;
790 stdname = name;
791 name = getqzname(name, '>');
792 if (*name != '>')
793 return (-1);
794 stdlen = name - stdname;
795 name++;
796 } else {
797 name = getzname(name);
798 stdlen = name - stdname;
799 }
800 if (*name == '\0')
801 return -1;
802 name = getoffset(name, &stdoffset);
803 if (name == NULL)
804 return -1;
805 }
806 load_result = tzload(TZDEFRULES, sp);
807 if (load_result != 0)
808 sp->leapcnt = 0; /* so, we're off a little */
809 if (*name != '\0') {
810 if (*name == '<') {
811 dstname = ++name;
812 name = getqzname(name, '>');
813 if (*name != '>')
814 return -1;
815 dstlen = name - dstname;
816 name++;
817 } else {
818 dstname = name;
819 name = getzname(name);
820 dstlen = name - dstname; /* length of DST zone name */
821 }
822 if (*name != '\0' && *name != ',' && *name != ';') {
823 name = getoffset(name, &dstoffset);
824 if (name == NULL)
825 return -1;
826 } else
827 dstoffset = stdoffset - SECSPERHOUR;
828 if (*name == '\0' && load_result != 0)
829 name = TZDEFRULESTRING;
830 if (*name == ',' || *name == ';') {
831 struct rule start;
832 struct rule end;
833 int year;
834 time_t janfirst;
835 time_t starttime;
836 time_t endtime;
837
838 ++name;
839 if ((name = getrule(name, &start)) == NULL)
840 return -1;
841 if (*name++ != ',')
842 return -1;
843 if ((name = getrule(name, &end)) == NULL)
844 return -1;
845 if (*name != '\0')
846 return -1;
847 sp->typecnt = 2;/* standard time and DST */
848 /*
849 ** Two transitions per year, from EPOCH_YEAR to 2037.
850 */
851 sp->timecnt = 2 * (2037 - EPOCH_YEAR + 1);
852 if (sp->timecnt > TZ_MAX_TIMES)
853 return -1;
854 sp->ttis[0].tt_gmtoff = -dstoffset;
855 sp->ttis[0].tt_isdst = 1;
856 sp->ttis[0].tt_abbrind = stdlen + 1;
857 sp->ttis[1].tt_gmtoff = -stdoffset;
858 sp->ttis[1].tt_isdst = 0;
859 sp->ttis[1].tt_abbrind = 0;
860 atp = sp->ats;
861 typep = sp->types;
862 janfirst = 0;
863 for (year = EPOCH_YEAR; year <= 2037; ++year) {
864 starttime = transtime(janfirst, year, &start,
865 stdoffset);
866 endtime = transtime(janfirst, year, &end,
867 dstoffset);
868 if (starttime > endtime) {
869 *atp++ = endtime;
870 *typep++ = 1; /* DST ends */
871 *atp++ = starttime;
872 *typep++ = 0; /* DST begins */
873 } else {
874 *atp++ = starttime;
875 *typep++ = 0; /* DST begins */
876 *atp++ = endtime;
877 *typep++ = 1; /* DST ends */
878 }
879 janfirst += year_lengths[isleap(year)] *
880 SECSPERDAY;
881 }
882 } else {
883 long theirstdoffset;
884 long theirdstoffset;
885 long theiroffset;
886 int isdst;
887 int i;
888 int j;
889
890 if (*name != '\0')
891 return -1;
892 /*
893 ** Initial values of theirstdoffset and theirdstoffset.
894 */
895 theirstdoffset = 0;
896 for (i = 0; i < sp->timecnt; ++i) {
897 j = sp->types[i];
898 if (!sp->ttis[j].tt_isdst) {
899 theirstdoffset =
900 -sp->ttis[j].tt_gmtoff;
901 break;
902 }
903 }
904 theirdstoffset = 0;
905 for (i = 0; i < sp->timecnt; ++i) {
906 j = sp->types[i];
907 if (sp->ttis[j].tt_isdst) {
908 theirdstoffset =
909 -sp->ttis[j].tt_gmtoff;
910 break;
911 }
912 }
913 /*
914 ** Initially we're assumed to be in standard time.
915 */
916 isdst = FALSE;
917 theiroffset = theirstdoffset;
918 /*
919 ** Now juggle transition times and types
920 ** tracking offsets as you do.
921 */
922 for (i = 0; i < sp->timecnt; ++i) {
923 j = sp->types[i];
924 sp->types[i] = sp->ttis[j].tt_isdst;
925 if (sp->ttis[j].tt_ttisgmt) {
926 /* No adjustment to transition time */
927 } else {
928 /*
929 ** If summer time is in effect, and the
930 ** transition time was not specified as
931 ** standard time, add the summer time
932 ** offset to the transition time;
933 ** otherwise, add the standard time
934 ** offset to the transition time.
935 */
936 /*
937 ** Transitions from DST to DDST
938 ** will effectively disappear since
939 ** POSIX provides for only one DST
940 ** offset.
941 */
942 if (isdst && !sp->ttis[j].tt_ttisstd) {
943 sp->ats[i] += dstoffset -
944 theirdstoffset;
945 } else {
946 sp->ats[i] += stdoffset -
947 theirstdoffset;
948 }
949 }
950 theiroffset = -sp->ttis[j].tt_gmtoff;
951 if (sp->ttis[j].tt_isdst)
952 theirdstoffset = theiroffset;
953 else
954 theirstdoffset = theiroffset;
955 }
956 /*
957 ** Finally, fill in ttis.
958 ** ttisstd and ttisgmt need not be handled.
959 */
960 sp->ttis[0].tt_gmtoff = -stdoffset;
961 sp->ttis[0].tt_isdst = FALSE;
962 sp->ttis[0].tt_abbrind = 0;
963 sp->ttis[1].tt_gmtoff = -dstoffset;
964 sp->ttis[1].tt_isdst = TRUE;
965 sp->ttis[1].tt_abbrind = stdlen + 1;
966 sp->typecnt = 2;
967 }
968 } else {
969 dstlen = 0;
970 sp->typecnt = 1; /* only standard time */
971 sp->timecnt = 0;
972 sp->ttis[0].tt_gmtoff = -stdoffset;
973 sp->ttis[0].tt_isdst = 0;
974 sp->ttis[0].tt_abbrind = 0;
975 }
976 sp->charcnt = stdlen + 1;
977 if (dstlen != 0)
978 sp->charcnt += dstlen + 1;
979 if ((size_t)sp->charcnt > sizeof sp->chars)
980 return -1;
981 cp = sp->chars;
982 strlcpy(cp, stdname, stdlen + 1);
983 cp += stdlen + 1;
984 if (dstlen != 0) {
985 strlcpy(cp, dstname, dstlen + 1);
986 }
987 return 0;
988 }
989
990 static void
gmtload(sp)991 gmtload(sp)
992 struct state *const sp;
993 {
994 if (tzload(gmt, sp) != 0)
995 (void)tzparse(gmt, sp, TRUE);
996 }
997 static
998 void
tzsetwall_basic(void)999 tzsetwall_basic(void)
1000 {
1001 if (lcl_is_set < 0)
1002 return;
1003 lcl_is_set = -1;
1004
1005 if (tzload((char *)NULL, lclptr) != 0)
1006 gmtload(lclptr);
1007 settzname();
1008 }
1009
1010 void
tzsetwall(void)1011 tzsetwall(void)
1012 {
1013 _THREAD_PRIVATE_MUTEX_LOCK(lcl);
1014 tzsetwall_basic();
1015 _THREAD_PRIVATE_MUTEX_UNLOCK(lcl);
1016 }
1017
1018 static
1019 void
tzset_basic(void)1020 tzset_basic(void)
1021 {
1022 const char *name;
1023
1024 name = getenv("TZ");
1025 if (name == NULL) {
1026 tzsetwall_basic();
1027 return;
1028 }
1029 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
1030 return;
1031 lcl_is_set = strlen(name) < sizeof lcl_TZname;
1032 if (lcl_is_set)
1033 (void)strlcpy(lcl_TZname, name, sizeof lcl_TZname);
1034
1035 if (*name == '\0') {
1036 /*
1037 ** User wants it fast rather than right.
1038 */
1039 lclptr->leapcnt = 0; /* so, we're off a little */
1040 lclptr->timecnt = 0;
1041 lclptr->typecnt = 0;
1042 lclptr->ttis[0].tt_isdst = 0;
1043 lclptr->ttis[0].tt_gmtoff = 0;
1044 lclptr->ttis[0].tt_abbrind = 0;
1045 (void)strlcpy(lclptr->chars, gmt, sizeof lclptr->chars);
1046 } else if (tzload(name, lclptr) != 0)
1047 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
1048 (void)gmtload(lclptr);
1049 settzname();
1050 }
1051
1052 void
tzset(void)1053 tzset(void)
1054 {
1055 _THREAD_PRIVATE_MUTEX_LOCK(lcl);
1056 tzset_basic();
1057 _THREAD_PRIVATE_MUTEX_UNLOCK(lcl);
1058 mirtime_getleaps();
1059 }
1060
1061 /*
1062 ** The easy way to behave "as if no library function calls" localtime
1063 ** is to not call it--so we drop its guts into "localsub", which can be
1064 ** freely called. (And no, the PANS doesn't require the above behavior--
1065 ** but it *is* desirable.)
1066 **
1067 ** The unused offset argument is for the benefit of mktime variants.
1068 */
1069
1070 /*ARGSUSED*/
1071 static struct tm *
localsub(const time_t * const timep,const long offset __unused,struct tm * const tmp)1072 localsub(const time_t * const timep, const long offset __unused,
1073 struct tm * const tmp)
1074 {
1075 register struct state * sp;
1076 register const struct ttinfo * ttisp;
1077 register int i;
1078 register struct tm * result;
1079 const time_t t = *timep;
1080
1081 sp = lclptr;
1082 if (sp->timecnt == 0 || t < sp->ats[0]) {
1083 i = 0;
1084 while (sp->ttis[i].tt_isdst)
1085 if (++i >= sp->typecnt) {
1086 i = 0;
1087 break;
1088 }
1089 } else {
1090 for (i = 1; i < sp->timecnt; ++i)
1091 if (t < sp->ats[i])
1092 break;
1093 i = (int) sp->types[i - 1];
1094 }
1095 ttisp = &sp->ttis[i];
1096 /*
1097 ** To get (wrong) behavior that's compatible with System V Release 2.0
1098 ** you'd replace the statement below with
1099 ** t += ttisp->tt_gmtoff;
1100 ** timesub(&t, 0L, sp, tmp);
1101 */
1102 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1103 tmp->tm_isdst = ttisp->tt_isdst;
1104 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
1105 #ifdef TM_ZONE
1106 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1107 #endif /* defined TM_ZONE */
1108 return result;
1109 }
1110
1111 /*
1112 ** Re-entrant version of localtime.
1113 */
1114
1115 struct tm *
localtime_r(timep,p_tm)1116 localtime_r(timep, p_tm)
1117 const time_t *const timep;
1118 struct tm *p_tm;
1119 {
1120 _THREAD_PRIVATE_MUTEX_LOCK(lcl);
1121 tzset_basic();
1122 p_tm = localsub(timep, 0L, p_tm);
1123 _THREAD_PRIVATE_MUTEX_UNLOCK(lcl);
1124 return p_tm;
1125 }
1126
1127 struct tm *
localtime(timep)1128 localtime(timep)
1129 const time_t *const timep;
1130 {
1131 _THREAD_PRIVATE_KEY(localtime);
1132 struct tm *p_tm = (struct tm *)_THREAD_PRIVATE(localtime, tm, NULL);
1133
1134 if (p_tm == NULL)
1135 return NULL;
1136 return localtime_r(timep, p_tm);
1137 }
1138
1139 /*
1140 ** gmtsub is to gmtime as localsub is to localtime.
1141 */
1142
1143 static struct tm *
gmtsub(timep,offset,tmp)1144 gmtsub(timep, offset, tmp)
1145 const time_t *const timep;
1146 const long offset;
1147 struct tm *const tmp;
1148 {
1149 register struct tm * result;
1150
1151 _THREAD_PRIVATE_MUTEX_LOCK(gmt);
1152 if (!gmt_is_set) {
1153 gmt_is_set = TRUE;
1154 gmtload(gmtptr);
1155 }
1156 _THREAD_PRIVATE_MUTEX_UNLOCK(gmt);
1157 result = timesub(timep, offset, gmtptr, tmp);
1158 #ifdef TM_ZONE
1159 /*
1160 ** Could get fancy here and deliver something such as
1161 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1162 ** but this is no time for a treasure hunt.
1163 */
1164 if (offset != 0)
1165 tmp->TM_ZONE = wildabbr;
1166 else {
1167 tmp->TM_ZONE = gmtptr->chars;
1168 }
1169 #endif /* defined TM_ZONE */
1170 return result;
1171 }
1172
1173 /*
1174 ** Re-entrant version of gmtime.
1175 */
1176
1177 struct tm *
gmtime_r(timep,p_tm)1178 gmtime_r(timep, p_tm)
1179 const time_t *timep;
1180 struct tm *p_tm;
1181 {
1182 gmtsub(timep, 0L, p_tm);
1183 return p_tm;
1184 }
1185
1186 struct tm *
gmtime(timep)1187 gmtime(timep)
1188 const time_t *const timep;
1189 {
1190 _THREAD_PRIVATE_KEY(gmtime);
1191 struct tm *p_tm = (struct tm *)_THREAD_PRIVATE(gmtime, tm, NULL);
1192
1193 if (p_tm == NULL)
1194 return NULL;
1195 return gmtime_r(timep, p_tm);
1196
1197 }
1198
1199 struct tm *
offtime(const time_t * const timep,const long offset)1200 offtime(const time_t * const timep, const long offset)
1201 {
1202 return gmtsub(timep, offset, &tm);
1203 }
1204
1205 /*
1206 ** Return the number of leap years through the end of the given year
1207 ** where, to make the math easy, the answer for year zero is defined as zero.
1208 */
1209 static int
leaps_thru_end_of(y)1210 leaps_thru_end_of(y)
1211 register const int y;
1212 {
1213 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
1214 -(leaps_thru_end_of(-(y + 1)) + 1);
1215 }
1216
1217 static struct tm *
timesub(timep,offset,sp,tmp)1218 timesub(timep, offset, sp, tmp)
1219 const time_t *const timep;
1220 const long offset;
1221 const struct state *const sp;
1222 struct tm *const tmp;
1223 {
1224 const struct lsinfo *lp;
1225 time_t days;
1226 long rem, corr;
1227 int i, hit; /* hit: leap second bit */
1228 mirtime_mjd tmjd;
1229
1230 corr = 0;
1231 hit = 0;
1232 i = sp->leapcnt;
1233 while (--i >= 0) {
1234 lp = &sp->lsis[i];
1235 if (*timep >= lp->ls_trans) {
1236 if (*timep == lp->ls_trans) {
1237 hit = ((i == 0 && lp->ls_corr > 0) ||
1238 lp->ls_corr > sp->lsis[i - 1].ls_corr);
1239 if (hit)
1240 while (i > 0 &&
1241 sp->lsis[i].ls_trans ==
1242 sp->lsis[i - 1].ls_trans + 1 &&
1243 sp->lsis[i].ls_corr ==
1244 sp->lsis[i - 1].ls_corr + 1) {
1245 ++hit;
1246 --i;
1247 }
1248 }
1249 corr = lp->ls_corr;
1250 break;
1251 }
1252 }
1253 days = *timep / SECSPERDAY;
1254 rem = (int32_t)(*timep % SECSPERDAY);
1255 #ifdef mc68k
1256 if (*timep == 0x80000000) {
1257 /*
1258 ** A 3B1 muffs the division on the most negative number.
1259 */
1260 days = -24855;
1261 rem = -11648;
1262 }
1263 #endif /* defined mc68k */
1264 rem += (offset - corr);
1265 while (rem < 0) {
1266 rem += SECSPERDAY;
1267 --days;
1268 }
1269 while (rem >= SECSPERDAY) {
1270 rem -= SECSPERDAY;
1271 ++days;
1272 }
1273
1274 tmjd.mjd = days + 40587;
1275 tmjd.sec = (int32_t)rem;
1276 mjd_explode(tmp, &tmjd);
1277 tmp->tm_gmtoff = offset;
1278 tmp->tm_sec += hit;
1279 return (tmp);
1280 }
1281
1282 char *
ctime(timep)1283 ctime(timep)
1284 const time_t *const timep;
1285 {
1286 /*
1287 ** Section 4.12.3.2 of X3.159-1989 requires that
1288 ** The ctime function converts the calendar time pointed to by timer
1289 ** to local time in the form of a string. It is equivalent to
1290 ** asctime(localtime(timer))
1291 */
1292 return asctime(localtime(timep));
1293 }
1294
1295 char *
ctime_r(timep,buf)1296 ctime_r(timep, buf)
1297 const time_t *const timep;
1298 char *buf;
1299 {
1300 struct tm mytm;
1301
1302 return asctime_r(localtime_r(timep, &mytm), buf);
1303 }
1304
1305 /*
1306 ** Adapted from code provided by Robert Elz, who writes:
1307 ** The "best" way to do mktime I think is based on an idea of Bob
1308 ** Kridle's (so its said...) from a long time ago.
1309 ** [kridle@xinet.com as of 1996-01-16.]
1310 ** It does a binary search of the time_t space. Since time_t's are
1311 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
1312 ** would still be very reasonable).
1313 */
1314
1315 #ifndef WRONG
1316 #define WRONG (-1)
1317 #endif /* !defined WRONG */
1318
1319 /*
1320 ** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1321 */
1322
1323 static int
increment_overflow(number,delta)1324 increment_overflow(number, delta)
1325 int *number;
1326 int delta;
1327 {
1328 int number0;
1329
1330 number0 = *number;
1331 *number += delta;
1332 return (*number < number0) != (delta < 0);
1333 }
1334
1335 static int
long_increment_overflow(number,delta)1336 long_increment_overflow(number, delta)
1337 time_t *number;
1338 time_t delta;
1339 {
1340 time_t number0;
1341
1342 number0 = *number;
1343 *number += delta;
1344 return (*number < number0) != (delta < 0);
1345 }
1346
1347 static int
normalize_overflow(tensptr,unitsptr,base)1348 normalize_overflow(tensptr, unitsptr, base)
1349 int *const tensptr;
1350 int *const unitsptr;
1351 const int base;
1352 {
1353 int tensdelta;
1354
1355 tensdelta = (*unitsptr >= 0) ?
1356 (*unitsptr / base) :
1357 (-1 - (-1 - *unitsptr) / base);
1358 *unitsptr -= tensdelta * base;
1359 return increment_overflow(tensptr, tensdelta);
1360 }
1361
1362 static int
long_normalize_overflow(tensptr,unitsptr,base)1363 long_normalize_overflow(tensptr, unitsptr, base)
1364 time_t *const tensptr;
1365 int *const unitsptr;
1366 const int base;
1367 {
1368 time_t tensdelta;
1369
1370 tensdelta = (*unitsptr >= 0) ?
1371 (*unitsptr / base) :
1372 (-1 - (-1 - *unitsptr) / base);
1373 *unitsptr -= (int)(tensdelta) * base;
1374 return long_increment_overflow(tensptr, tensdelta);
1375 }
1376
1377 static int
tmcomp(atmp,btmp)1378 tmcomp(atmp, btmp)
1379 const struct tm *const atmp;
1380 const struct tm *const btmp;
1381 {
1382 int result;
1383 time_t resyr = atmp->tm_year - btmp->tm_year;
1384
1385 if (resyr > 0)
1386 return 1;
1387 else if (resyr < 0)
1388 return -1;
1389
1390 if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
1391 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
1392 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
1393 (result = (atmp->tm_min - btmp->tm_min)) == 0)
1394 result = atmp->tm_sec - btmp->tm_sec;
1395 return result;
1396 }
1397
1398 static time_t
time2sub(tmp,funcp,offset,okayp,do_norm_secs)1399 time2sub(tmp, funcp, offset, okayp, do_norm_secs)
1400 struct tm * const tmp;
1401 struct tm * (* const funcp) P((const time_t*, long, struct tm*));
1402 const long offset;
1403 int * const okayp;
1404 const int do_norm_secs;
1405 {
1406 register const struct state * sp;
1407 register int dir;
1408 register int i, j;
1409 register int saved_seconds;
1410 register long li;
1411 register time_t lo;
1412 register time_t hi;
1413 time_t y;
1414 time_t newt;
1415 time_t t;
1416 struct tm yourtm, mytm;
1417
1418 *okayp = FALSE;
1419 yourtm = *tmp;
1420 if (do_norm_secs) {
1421 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
1422 SECSPERMIN))
1423 return WRONG;
1424 }
1425 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
1426 return WRONG;
1427 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
1428 return WRONG;
1429 y = yourtm.tm_year;
1430 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
1431 return WRONG;
1432 /*
1433 ** Turn y into an actual year number for now.
1434 ** It is converted back to an offset from TM_YEAR_BASE later.
1435 */
1436 if (long_increment_overflow(&y, (time_t)TM_YEAR_BASE))
1437 return WRONG;
1438 while (yourtm.tm_mday <= 0) {
1439 if (long_increment_overflow(&y, (time_t)-1))
1440 return WRONG;
1441 li = y + (1 < yourtm.tm_mon);
1442 yourtm.tm_mday += year_lengths[isleap(li)];
1443 }
1444 while (yourtm.tm_mday > DAYSPERLYEAR) {
1445 if (long_increment_overflow(&y, (time_t)1))
1446 return WRONG;
1447 li = y + (1 < yourtm.tm_mon);
1448 yourtm.tm_mday -= year_lengths[isleap(li)];
1449 }
1450 for ( ; ; ) {
1451 i = mon_lengths[isleap((y < 0) ? y+1 : y)][yourtm.tm_mon];
1452 if (yourtm.tm_mday <= i)
1453 break;
1454 yourtm.tm_mday -= i;
1455 if (++yourtm.tm_mon >= MONSPERYEAR) {
1456 yourtm.tm_mon = 0;
1457 if (long_increment_overflow(&y, (time_t)1))
1458 return WRONG;
1459 }
1460 }
1461 if (long_increment_overflow(&y, (time_t)-TM_YEAR_BASE))
1462 return WRONG;
1463 yourtm.tm_year = y;
1464 if (yourtm.tm_year != y)
1465 return WRONG;
1466 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
1467 saved_seconds = 0;
1468 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
1469 /*
1470 ** We can't set tm_sec to 0, because that might push the
1471 ** time below the minimum representable time.
1472 ** Set tm_sec to 59 instead.
1473 ** This assumes that the minimum representable time is
1474 ** not in the same minute that a leap second was deleted from,
1475 ** which is a safer assumption than using 58 would be.
1476 */
1477 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
1478 return WRONG;
1479 saved_seconds = yourtm.tm_sec;
1480 yourtm.tm_sec = SECSPERMIN - 1;
1481 } else {
1482 saved_seconds = yourtm.tm_sec;
1483 yourtm.tm_sec = 0;
1484 }
1485 /*
1486 ** Do a binary search (this works whatever time_t's type is).
1487 */
1488 if (!TYPE_SIGNED(time_t)) {
1489 lo = 0;
1490 hi = lo - 1;
1491 } else if (!TYPE_INTEGRAL(time_t)) {
1492 if (sizeof(time_t) > sizeof(float))
1493 hi = (time_t) DBL_MAX;
1494 else hi = (time_t) FLT_MAX;
1495 lo = -hi;
1496 } else {
1497 lo = 1;
1498 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
1499 lo *= 2;
1500 hi = -(lo + 1);
1501 }
1502 for ( ; ; ) {
1503 t = lo / 2 + hi / 2;
1504 if (t < lo)
1505 t = lo;
1506 else if (t > hi)
1507 t = hi;
1508 if ((*funcp)(&t, offset, &mytm) == NULL) {
1509 /*
1510 ** Assume that t is too extreme to be represented in
1511 ** a struct tm; arrange things so that it is less
1512 ** extreme on the next pass.
1513 */
1514 dir = (t > 0) ? 1 : -1;
1515 } else dir = tmcomp(&mytm, &yourtm);
1516 if (dir != 0) {
1517 if (t == lo) {
1518 ++t;
1519 ++lo;
1520 } else if (t == hi) {
1521 --t;
1522 --hi;
1523 }
1524 if (lo > hi)
1525 return WRONG;
1526 if (dir > 0)
1527 hi = t;
1528 else lo = t;
1529 continue;
1530 }
1531 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1532 break;
1533 /*
1534 ** Right time, wrong type.
1535 ** Hunt for right time, right type.
1536 ** It's okay to guess wrong since the guess
1537 ** gets checked.
1538 */
1539 /*
1540 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1541 */
1542 sp = (const struct state *)
1543 (((void *) funcp == (void *) localsub) ?
1544 lclptr : gmtptr);
1545 for (i = sp->typecnt - 1; i >= 0; --i) {
1546 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
1547 continue;
1548 for (j = sp->typecnt - 1; j >= 0; --j) {
1549 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
1550 continue;
1551 newt = t + sp->ttis[j].tt_gmtoff -
1552 sp->ttis[i].tt_gmtoff;
1553 if ((*funcp)(&newt, offset, &mytm) == NULL)
1554 continue;
1555 if (tmcomp(&mytm, &yourtm) != 0)
1556 continue;
1557 if (mytm.tm_isdst != yourtm.tm_isdst)
1558 continue;
1559 /*
1560 ** We have a match.
1561 */
1562 t = newt;
1563 goto label;
1564 }
1565 }
1566 return WRONG;
1567 }
1568 label:
1569 newt = t + saved_seconds;
1570 if ((newt < t) != (saved_seconds < 0))
1571 return WRONG;
1572 t = newt;
1573 if ((*funcp)(&t, offset, tmp))
1574 *okayp = TRUE;
1575 return t;
1576 }
1577
1578 static time_t
time2(tmp,funcp,offset,okayp)1579 time2(tmp, funcp, offset, okayp)
1580 struct tm *const tmp;
1581 struct tm *(*const funcp) (const time_t *, long, struct tm *);
1582 const long offset;
1583 int *const okayp;
1584 {
1585 time_t t;
1586
1587 /*
1588 ** First try without normalization of seconds
1589 ** (in case tm_sec contains a value associated with a leap second).
1590 ** If that fails, try with normalization of seconds.
1591 */
1592 t = time2sub(tmp, funcp, offset, okayp, FALSE);
1593 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
1594 }
1595
1596 static time_t
time1(tmp,funcp,offset)1597 time1(tmp, funcp, offset)
1598 struct tm *const tmp;
1599 struct tm *(*const funcp) (const time_t *, long, struct tm *);
1600 const long offset;
1601 {
1602 time_t t;
1603 const struct state *sp;
1604 int samei, otheri;
1605 int sameind, otherind;
1606 int i;
1607 int nseen;
1608 int seen[TZ_MAX_TYPES];
1609 int types[TZ_MAX_TYPES];
1610 int okay;
1611
1612 if (tmp->tm_isdst > 1)
1613 tmp->tm_isdst = 1;
1614 t = time2(tmp, funcp, offset, &okay);
1615 /*
1616 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
1617 */
1618 if (okay)
1619 return t;
1620 if (tmp->tm_isdst < 0)
1621 tmp->tm_isdst = 0; /* reset to std and try again */
1622 /*
1623 ** We're supposed to assume that somebody took a time of one type
1624 ** and did some math on it that yielded a "struct tm" that's bad.
1625 ** We try to divine the type they started from and adjust to the
1626 ** type they need.
1627 */
1628 /*
1629 ** The (void *) casts are the benefit of SunOS 3.3 on Sun 2's.
1630 */
1631 sp = (const struct state *)(((void *)funcp == (void *)localsub) ?
1632 lclptr : gmtptr);
1633 for (i = 0; i < sp->typecnt; ++i)
1634 seen[i] = FALSE;
1635 nseen = 0;
1636 for (i = sp->timecnt - 1; i >= 0; --i)
1637 if (!seen[sp->types[i]]) {
1638 seen[sp->types[i]] = TRUE;
1639 types[nseen++] = sp->types[i];
1640 }
1641 for (sameind = 0; sameind < nseen; ++sameind) {
1642 samei = types[sameind];
1643 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
1644 continue;
1645 for (otherind = 0; otherind < nseen; ++otherind) {
1646 otheri = types[otherind];
1647 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
1648 continue;
1649 tmp->tm_sec += (int)(sp->ttis[otheri].tt_gmtoff -
1650 sp->ttis[samei].tt_gmtoff);
1651 tmp->tm_isdst = !tmp->tm_isdst;
1652 t = time2(tmp, funcp, offset, &okay);
1653 if (okay)
1654 return t;
1655 tmp->tm_sec -= (int)(sp->ttis[otheri].tt_gmtoff -
1656 sp->ttis[samei].tt_gmtoff);
1657 tmp->tm_isdst = !tmp->tm_isdst;
1658 }
1659 }
1660 return WRONG;
1661 }
1662
1663 time_t
mktime(tmp)1664 mktime(tmp)
1665 struct tm *tmp;
1666 {
1667 time_t ret;
1668
1669 _THREAD_PRIVATE_MUTEX_LOCK(lcl);
1670 tzset_basic();
1671 ret = time1(tmp, localsub, 0L);
1672 _THREAD_PRIVATE_MUTEX_UNLOCK(lcl);
1673 return ret;
1674 }
1675
1676 time_t
timelocal(tmp)1677 timelocal(tmp)
1678 struct tm *const tmp;
1679 {
1680 tmp->tm_isdst = -1; /* in case it wasn't initialized */
1681 return mktime(tmp);
1682 }
1683
1684 time_t
timegm(tmp)1685 timegm(tmp)
1686 struct tm *const tmp;
1687 {
1688 tmp->tm_isdst = 0;
1689 return time1(tmp, gmtsub, 0L);
1690 }
1691
1692 time_t
timeoff(tmp,offset)1693 timeoff(tmp, offset)
1694 struct tm *const tmp;
1695 const long offset;
1696 {
1697 tmp->tm_isdst = 0;
1698 return time1(tmp, gmtsub, offset);
1699 }
1700
1701 const time_t *
mirtime_getleaps(void)1702 mirtime_getleaps(void)
1703 {
1704 #ifdef SKIP_LEAPSECS
1705 static time_t noleaps = 0;
1706
1707 return (&noleaps);
1708 #else
1709 static int initialised = 0;
1710 static time_t leaps[TZ_MAX_LEAPS + 1];
1711
1712 if (__predict_false(!initialised)) {
1713 int i;
1714 struct state sp;
1715
1716 memset(leaps, 0, sizeof(leaps));
1717
1718 /* load leap seconds for UTC */
1719 gmtload(&sp);
1720
1721 /* sanity check */
1722 if ((sp.leapcnt > 0) && (sp.leapcnt <= TZ_MAX_LEAPS) &&
1723 (sp.lsis[0].ls_trans == 78796800)) {
1724 /* add leap seconds to table */
1725 for (i = 0; i < sp.leapcnt; ++i)
1726 leaps[i] = sp.lsis[i].ls_trans;
1727 initialised = 1;
1728 }
1729 }
1730 return (leaps);
1731 #endif
1732 }
1733