]> git.saurik.com Git - apple/libc.git/blob - stdtime/FreeBSD/localtime.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / stdtime / FreeBSD / localtime.c
1 /*
2 ** This file is in the public domain, so clarified as of
3 ** 1996-06-05 by Arthur David Olson.
4 */
5
6 #pragma clang diagnostic push
7 #pragma clang diagnostic ignored "-Wunreachable-code"
8
9 #include <sys/cdefs.h>
10 #ifndef lint
11 #ifndef NOID
12 static char elsieid[] __unused = "@(#)localtime.c 8.14";
13 #endif /* !defined NOID */
14 #endif /* !defined lint */
15 __FBSDID("$FreeBSD: head/contrib/tzcode/stdtime/localtime.c 289027 2015-10-08 11:42:15Z rodrigc $");
16
17 /*
18 ** Leap second handling from Bradley White.
19 ** POSIX-style TZ environment variable handling from Guy Harris.
20 */
21
22 /*LINTLIBRARY*/
23
24 #include "namespace.h"
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <errno.h>
28 #include <time.h>
29 #include <fcntl.h>
30 #include <pthread.h>
31 #ifdef NOTIFY_TZ
32 //#define NOTIFY_TZ_DEBUG
33 //#define NOTIFY_TZ_DEBUG_FILE "/var/log/localtime.debug"
34 //#define NOTIFY_TZ_LOG "/var/log/localtime.log"
35 /* force ALL_STATE if NOTIFY_TZ is set */
36 #ifndef ALL_STATE
37 #define ALL_STATE
38 #endif /* ALL_STATE */
39 #include <mach/mach_init.h>
40 #include <notify.h>
41 #include <alloca.h>
42 #endif /* NOTIFY_TZ */
43 #include "private.h"
44 #include "un-namespace.h"
45
46 #include "tzfile.h"
47 #include "float.h" /* for FLT_MAX and DBL_MAX */
48
49 #ifndef TZ_ABBR_MAX_LEN
50 /* UNIX03 requires this to be the same as sysconf(_SC_TZNAME_MAX) */
51 #define TZ_ABBR_MAX_LEN 255
52 #endif /* !defined TZ_ABBR_MAX_LEN */
53
54 #ifndef TZ_ABBR_CHAR_SET
55 #define TZ_ABBR_CHAR_SET \
56 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 :+-._"
57 #endif /* !defined TZ_ABBR_CHAR_SET */
58
59 #ifndef TZ_ABBR_ERR_CHAR
60 #define TZ_ABBR_ERR_CHAR '_'
61 #endif /* !defined TZ_ABBR_ERR_CHAR */
62
63 #include "libc_private.h"
64
65 #define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
66 #define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
67
68 #define _RWLOCK_RDLOCK(x) \
69 do { \
70 if (__isthreaded) _pthread_rwlock_rdlock(x); \
71 } while (0)
72
73 #define _RWLOCK_WRLOCK(x) \
74 do { \
75 if (__isthreaded) _pthread_rwlock_wrlock(x); \
76 } while (0)
77
78 #define _RWLOCK_UNLOCK(x) \
79 do { \
80 if (__isthreaded) _pthread_rwlock_unlock(x); \
81 } while (0)
82
83 /*
84 ** SunOS 4.1.1 headers lack O_BINARY.
85 */
86
87 #ifdef O_BINARY
88 #define OPEN_MODE (O_RDONLY | O_BINARY)
89 #endif /* defined O_BINARY */
90 #ifndef O_BINARY
91 #define OPEN_MODE O_RDONLY
92 #endif /* !defined O_BINARY */
93
94 #ifndef WILDABBR
95 /*
96 ** Someone might make incorrect use of a time zone abbreviation:
97 ** 1. They might reference tzname[0] before calling tzset (explicitly
98 ** or implicitly).
99 ** 2. They might reference tzname[1] before calling tzset (explicitly
100 ** or implicitly).
101 ** 3. They might reference tzname[1] after setting to a time zone
102 ** in which Daylight Saving Time is never observed.
103 ** 4. They might reference tzname[0] after setting to a time zone
104 ** in which Standard Time is never observed.
105 ** 5. They might reference tm.TM_ZONE after calling offtime.
106 ** What's best to do in the above cases is open to debate;
107 ** for now, we just set things up so that in any of the five cases
108 ** WILDABBR is used. Another possibility: initialize tzname[0] to the
109 ** string "tzname[0] used before set", and similarly for the other cases.
110 ** And another: initialize tzname[0] to "ERA", with an explanation in the
111 ** manual page of what this "time zone abbreviation" means (doing this so
112 ** that tzname[0] has the "normal" length of three characters).
113 */
114 #define WILDABBR " "
115 #endif /* !defined WILDABBR */
116
117 __used static const char wildabbr[] = WILDABBR;
118
119 /*
120 * In June 2004 it was decided UTC was a more appropriate default time
121 * zone than GMT.
122 */
123
124 __used static const char gmt[] = "UTC";
125
126 /*
127 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
128 ** We default to US rules as of 1999-08-17.
129 ** POSIX 1003.1 section 8.1.1 says that the default DST rules are
130 ** implementation dependent; for historical reasons, US rules are a
131 ** common default.
132 */
133 #ifndef TZDEFRULESTRING
134 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
135 #endif /* !defined TZDEFDST */
136
137 struct ttinfo { /* time type information */
138 long tt_gmtoff; /* UTC offset in seconds */
139 int tt_isdst; /* used to set tm_isdst */
140 int tt_abbrind; /* abbreviation list index */
141 int tt_ttisstd; /* TRUE if transition is std time */
142 int tt_ttisgmt; /* TRUE if transition is UTC */
143 };
144
145 struct lsinfo { /* leap second information */
146 time_t ls_trans; /* transition time */
147 long ls_corr; /* correction to apply */
148 };
149
150 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
151
152 #ifdef TZNAME_MAX
153 #define MY_TZNAME_MAX TZNAME_MAX
154 #endif /* defined TZNAME_MAX */
155 #ifndef TZNAME_MAX
156 #define MY_TZNAME_MAX 255
157 #endif /* !defined TZNAME_MAX */
158
159 struct state {
160 int leapcnt;
161 int timecnt;
162 int typecnt;
163 int charcnt;
164 int goback;
165 int goahead;
166 time_t ats[TZ_MAX_TIMES];
167 unsigned char types[TZ_MAX_TIMES];
168 struct ttinfo ttis[TZ_MAX_TYPES];
169 char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
170 (2 * (MY_TZNAME_MAX + 1)))];
171 struct lsinfo lsis[TZ_MAX_LEAPS];
172 };
173
174 struct rule {
175 int r_type; /* type of rule--see below */
176 int r_day; /* day number of rule */
177 int r_week; /* week number of rule */
178 int r_mon; /* month number of rule */
179 long r_time; /* transition time of rule */
180 };
181
182 #define JULIAN_DAY 0 /* Jn - Julian day */
183 #define DAY_OF_YEAR 1 /* n - day of year */
184 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
185
186 #ifdef NOTIFY_TZ
187 typedef struct {
188 int token;
189 int is_set;
190 } notify_tz_t;
191
192 #define NOTIFY_TZ_NAME "com.apple.system.timezone"
193 #endif /* NOTIFY_TZ */
194
195 /*
196 ** Prototypes for static functions.
197 */
198 #define localsub _st_localsub
199 #define time1 _st_time1
200 #define tzset_basic _st_tzset_basic
201 __private_extern__
202 #ifdef __LP64__
203 struct tm * localsub(const time_t * timep, long offset,
204 struct tm * tmp);
205 #else /* !__LP64__ */
206 void localsub(const time_t * timep, long offset,
207 struct tm * tmp);
208 #endif /* __LP64__ */
209 __private_extern__
210 time_t time1(struct tm * tmp,
211 #ifdef __LP64__
212 struct tm *(*funcp) (const time_t *,
213 long, struct tm *),
214 #else /* !__LP64__ */
215 void(*funcp) (const time_t *,
216 long, struct tm *),
217 #endif /* __LP64__ */
218 long offset,
219 int unix03);
220 __private_extern__
221 void tzset_basic(int);
222
223 #if !BUILDING_VARIANT
224 static long detzcode(const char * codep);
225 static time_t detzcode64(const char * codep);
226 static int differ_by_repeat(time_t t1, time_t t0);
227 static const char * getzname(const char * strp, char **name, size_t *len);
228 static const char * getqzname(const char * strp, const int delim)
229 ATTRIBUTE_PURE;
230 static const char * getnum(const char * strp, int * nump, int min,
231 int max);
232 static const char * getsecs(const char * strp, long * secsp);
233 static const char * getoffset(const char * strp, long * offsetp);
234 static const char * getrule(const char * strp, struct rule * rulep);
235 #ifdef NOTIFY_TZ
236 static void gmtload(struct state * sp, char *path);
237 #else /* ! NOTIFY_TZ */
238 static void gmtload(struct state * sp);
239 #endif /* NOTIFY_TZ */
240 #ifdef __LP64__
241 static struct tm * gmtsub(const time_t * timep, long offset,
242 struct tm * tmp);
243 #else /* !__LP64__ */
244 static void gmtsub(const time_t * timep, long offset,
245 struct tm * tmp);
246 #endif /* __LP64__ */
247 static int increment_overflow(int * number, int delta);
248 static int leaps_thru_end_of(int y) ATTRIBUTE_PURE;
249 static int long_increment_overflow(long * number, int delta);
250 static int long_normalize_overflow(long * tensptr,
251 int * unitsptr, int base);
252 static int normalize_overflow(int * tensptr, int * unitsptr,
253 int base);
254 #ifdef NOTIFY_TZ
255 static void notify_check_tz(notify_tz_t *p);
256 static void notify_register_tz(char *file, notify_tz_t *p);
257 #endif /* NOTIFY_TZ */
258 static void settzname(void);
259 static time_t time2(struct tm *tmp,
260 #ifdef __LP64__
261 struct tm *(*funcp) (const time_t *,
262 long, struct tm*),
263 #else /* !__LP64__ */
264 void(*funcp) (const time_t *,
265 long, struct tm*),
266 #endif /* __LP64__ */
267 long offset, int * okayp, int unix03);
268 static time_t time2sub(struct tm *tmp,
269 #ifdef __LP64__
270 struct tm *(*funcp) (const time_t *,
271 long, struct tm*),
272 #else /* !__LP64__ */
273 void(*funcp) (const time_t *,
274 long, struct tm*),
275 #endif /* __LP64__ */
276 long offset, int * okayp, int do_norm_secs,
277 int unix03);
278 #ifdef __LP64__
279 static struct tm * timesub(const time_t * timep, long offset,
280 const struct state * sp, struct tm * tmp);
281 #else /* !__LP64__ */
282 static void timesub(const time_t * timep, long offset,
283 const struct state * sp, struct tm * tmp);
284 #endif /* __LP64__ */
285 static int tmcomp(const struct tm * atmp,
286 const struct tm * btmp);
287 static time_t transtime(time_t janfirst, int year,
288 const struct rule * rulep, long offset)
289 ATTRIBUTE_PURE;
290 static int typesequiv(const struct state * sp, int a, int b);
291 #ifdef NOTIFY_TZ
292 static int tzload(const char * name, struct state * sp, char *path, int doextend);
293 #else /* ! NOTIFY_TZ */
294 static int tzload(const char * name, struct state * sp, int doextend);
295 #endif /* NOTIFY_TZ */
296 static int tzparse(const char * name, struct state * sp,
297 int lastditch);
298
299 #ifdef ALL_STATE
300 static struct state * lclptr;
301 static struct state * gmtptr;
302 #endif /* defined ALL_STATE */
303
304 #ifndef ALL_STATE
305 static struct state lclmem;
306 static struct state gmtmem;
307 #define lclptr (&lclmem)
308 #define gmtptr (&gmtmem)
309 #endif /* State Farm */
310
311 #ifndef TZ_STRLEN_MAX
312 #define TZ_STRLEN_MAX 255
313 #endif /* !defined TZ_STRLEN_MAX */
314
315 static char lcl_TZname[TZ_STRLEN_MAX + 1];
316 #ifdef NOTIFY_TZ
317 #define lcl_is_set (lcl_notify.is_set)
318 #define gmt_is_set (gmt_notify.is_set)
319 #else /* ! NOTIFY_TZ */
320 static int lcl_is_set;
321 #endif /* NOTIFY_TZ */
322 static pthread_once_t gmt_once = PTHREAD_ONCE_INIT;
323 __private_extern__ pthread_rwlock_t lcl_rwlock = PTHREAD_RWLOCK_INITIALIZER;
324 static pthread_once_t gmtime_once = PTHREAD_ONCE_INIT;
325 static pthread_key_t gmtime_key;
326 static int gmtime_key_error;
327 static pthread_once_t localtime_once = PTHREAD_ONCE_INIT;
328 static pthread_key_t localtime_key;
329 static int localtime_key_error;
330
331 char * tzname[2] = {
332 (char *)wildabbr,
333 (char *)wildabbr
334 };
335
336 /*
337 ** Section 4.12.3 of X3.159-1989 requires that
338 ** Except for the strftime function, these functions [asctime,
339 ** ctime, gmtime, localtime] return values in one of two static
340 ** objects: a broken-down time structure and an array of char.
341 ** Thanks to Paul Eggert for noting this.
342 */
343
344 static struct tm tm;
345
346 #define USG_COMPAT
347 #define ALTZONE
348 #ifdef USG_COMPAT
349 int daylight = 0;
350 __private_extern__ void _st_set_timezone(long);
351 #endif /* defined USG_COMPAT */
352
353 #ifdef ALTZONE
354 __private_extern__ long __darwin_altzone = 0;
355 #define altzone __darwin_altzone
356 #endif /* defined ALTZONE */
357
358 #ifdef NOTIFY_TZ
359 #ifdef NOTIFY_TZ_DEBUG
360 #ifdef NOTIFY_TZ_DEBUG_FILE
361 #define NOTIFY_TZ_PRINTF(fmt, args...) \
362 { \
363 FILE *_notify_tz_fp_; \
364 if((_notify_tz_fp_ = fopen(NOTIFY_TZ_DEBUG_FILE, "a")) != NULL) { \
365 fprintf(_notify_tz_fp_, "%d: " fmt, getpid(), ## args); \
366 fclose(_notify_tz_fp_); \
367 } \
368 }
369 #else /* ! NOTIFY_TZ_DEBUG_FILE */
370 #define NOTIFY_TZ_PRINTF(args...) fprintf(stdout, ## args)
371 #endif /* NOTIFY_TZ_DEBUG_FILE */
372 #endif /* NOTIFY_TZ_DEBUG */
373 #ifdef NOTIFY_TZ_LOG
374 #define NOTIFY_LOG(fmt, args...) \
375 { \
376 FILE *_notify_log_fp_; \
377 if((_notify_log_fp_ = fopen(NOTIFY_TZ_LOG, "a")) != NULL) { \
378 fprintf(_notify_log_fp_, "%d: " fmt, getpid(), ## args); \
379 fclose(_notify_log_fp_); \
380 } \
381 }
382 #endif /* NOTIFY_TZ_LOG */
383
384 static notify_tz_t gmt_notify = {-1, 0};
385 static notify_tz_t lcl_notify = {-1, 0};
386 static const char notify_tz_name[] = NOTIFY_TZ_NAME;
387 #endif /* NOTIFY_TZ */
388
389 static long
390 detzcode(const char *const codep)
391 {
392 long result;
393 int i;
394
395 result = (codep[0] & 0x80) ? ~0L : 0;
396 for (i = 0; i < 4; ++i)
397 result = (result << 8) | (codep[i] & 0xff);
398 return result;
399 }
400
401 static time_t
402 detzcode64(const char *const codep)
403 {
404 register time_t result;
405 register int i;
406
407 result = (codep[0] & 0x80) ? (~(int_fast64_t) 0) : 0;
408 for (i = 0; i < 8; ++i)
409 result = result * 256 + (codep[i] & 0xff);
410 return result;
411 }
412
413 static void
414 settzname(void)
415 {
416 struct state * sp = lclptr;
417 int i, need;
418 unsigned char * types;
419 #define NEED_STD 1
420 #define NEED_DST 2
421 #define NEED_DAYLIGHT 4
422 #define NEED_ALL (NEED_STD | NEED_DST | NEED_DAYLIGHT)
423
424 tzname[0] = (char *)wildabbr;
425 tzname[1] = (char *)wildabbr;
426 #ifdef USG_COMPAT
427 daylight = 0;
428 _st_set_timezone(0);
429 #endif /* defined USG_COMPAT */
430 #ifdef ALTZONE
431 altzone = 0;
432 #endif /* defined ALTZONE */
433 #ifdef ALL_STATE
434 if (sp == NULL) {
435 tzname[0] = tzname[1] = (char *)gmt;
436 return;
437 }
438 #endif /* defined ALL_STATE */
439 /*
440 * PR-3765457: The original settzname went sequentially through the ttis
441 * array, rather than correctly indexing via the types array, to get
442 * the real order of the timezone changes. In addition, as a speed up,
443 * we start at the end of the changes, and work back, so that most of
444 * the time, we don't have to look through the entire array.
445 */
446 if (sp->timecnt == 0 && sp->typecnt == 1) {
447 /*
448 * Unfortunately, there is an edge case when typecnt == 1 and
449 * timecnt == 0, which would cause the loop to never run. So
450 * in that case, we fudge things up so that it is as if
451 * timecnt == 1.
452 */
453 i = 0;
454 types = (unsigned char *)""; /* we use the null as index */
455 } else {
456 /* the usual case */
457 i = sp->timecnt - 1;
458 types = sp->types;
459 }
460 need = NEED_ALL;
461 for (; i >= 0 && need; --i) {
462 const struct ttinfo * const ttisp = &sp->ttis[types[i]];
463
464 #ifdef USG_COMPAT
465 if ((need & NEED_DAYLIGHT) && ttisp->tt_isdst) {
466 need &= ~NEED_DAYLIGHT;
467 daylight = 1;
468 }
469 #endif /* defined USG_COMPAT */
470 if (ttisp->tt_isdst) {
471 if (need & NEED_DST) {
472 need &= ~NEED_DST;
473 tzname[1] = &sp->chars[ttisp->tt_abbrind];
474 #ifdef ALTZONE
475 altzone = -(ttisp->tt_gmtoff);
476 #endif /* defined ALTZONE */
477 }
478 } else if (need & NEED_STD) {
479 need &= ~NEED_STD;
480 tzname[0] = &sp->chars[ttisp->tt_abbrind];
481 #ifdef USG_COMPAT
482 _st_set_timezone(-(ttisp->tt_gmtoff));
483 #endif /* defined USG_COMPAT */
484 }
485 #if defined(ALTZONE) || defined(USG_COMPAT)
486 if (i == 0) {
487 #endif /* defined(ALTZONE) || defined(USG_COMPAT) */
488 #ifdef ALTZONE
489 if (need & NEED_DST)
490 altzone = -(ttisp->tt_gmtoff);
491 #endif /* defined ALTZONE */
492 #ifdef USG_COMPAT
493 if (need & NEED_STD)
494 _st_set_timezone(-(ttisp->tt_gmtoff));
495 #endif /* defined USG_COMPAT */
496 #if defined(ALTZONE) || defined(USG_COMPAT)
497 }
498 #endif /* defined(ALTZONE) || defined(USG_COMPAT) */
499 }
500 /*
501 ** Finally, scrub the abbreviations.
502 ** First, replace bogus characters.
503 */
504 for (i = 0; i < sp->charcnt; ++i)
505 if (strchr(TZ_ABBR_CHAR_SET, sp->chars[i]) == NULL)
506 sp->chars[i] = TZ_ABBR_ERR_CHAR;
507 /*
508 ** Second, truncate long abbreviations.
509 */
510 for (i = 0; i < sp->typecnt; ++i) {
511 register const struct ttinfo * const ttisp = &sp->ttis[i];
512 register char * cp = &sp->chars[ttisp->tt_abbrind];
513
514 if (strlen(cp) > TZ_ABBR_MAX_LEN &&
515 strcmp(cp, GRANDPARENTED) != 0)
516 *(cp + TZ_ABBR_MAX_LEN) = '\0';
517 }
518 }
519
520 #ifdef NOTIFY_TZ
521 static void
522 notify_check_tz(notify_tz_t *p)
523 {
524 unsigned int nstat;
525 int ncheck;
526
527 if (p->token < 0)
528 return;
529 nstat = notify_check(p->token, &ncheck);
530 if (nstat || ncheck) {
531 p->is_set = 0;
532 #ifdef NOTIFY_TZ_DEBUG
533 NOTIFY_TZ_PRINTF("notify_check_tz: %s changed\n", (p == &lcl_notify) ? "lcl" : "gmt");
534 #endif /* NOTIFY_TZ_DEBUG */
535 }
536 #ifdef NOTIFY_TZ_DEBUG
537 NOTIFY_TZ_PRINTF("notify_check_tz: %s unchanged\n", (p == &lcl_notify) ? "lcl" : "gmt");
538 #endif /* NOTIFY_TZ_DEBUG */
539 }
540
541 extern uint32_t notify_monitor_file(int token, char *path, int flags);
542
543 static void
544 notify_register_tz(char *file, notify_tz_t *p)
545 {
546 char *name;
547 unsigned int nstat;
548 int ncheck;
549
550 if (bootstrap_port == MACH_PORT_NULL) {
551 /* error handling below resets is_set, we don't want that */
552 return;
553 }
554
555 /*----------------------------------------------------------------
556 * Since we don't record the last time zone filename, just cancel
557 * (which should remove the file monitor) and setup from scratch
558 *----------------------------------------------------------------*/
559 if (p->token >= 0)
560 notify_cancel(p->token);
561 if (!file || *file == 0) {
562 /* no time zone file to monitor */
563 p->token = -1;
564 return;
565 }
566 /*----------------------------------------------------------------
567 * Just use com.apple.system.timezone if the path is /etc/localtime.
568 * Otherwise use com.apple.system.timezone.<fullpath>
569 *----------------------------------------------------------------*/
570 if (TZDEFAULT && strcmp(file, TZDEFAULT) == 0)
571 name = (char *)notify_tz_name;
572 else {
573 name = alloca(sizeof(notify_tz_name) + strlen(file) + 1);
574 if (name == NULL) {
575 p->token = -1;
576 return;
577 }
578 strcpy(name, notify_tz_name);
579 strcat(name, ".");
580 strcat(name, file);
581 }
582 #ifdef NOTIFY_TZ_DEBUG
583 NOTIFY_TZ_PRINTF("notify_register_tz: file=%s name=%s\n", file, name);
584 #endif /* NOTIFY_TZ_DEBUG */
585 nstat = notify_register_check(name, &p->token);
586 if (nstat != 0) {
587 p->token = -1;
588 p->is_set = 0;
589 #ifdef NOTIFY_TZ_DEBUG
590 NOTIFY_TZ_PRINTF("***notify_register_tz: notify_register_check failed: %u\n", nstat);
591 #endif /* NOTIFY_TZ_DEBUG */
592 #ifdef NOTIFY_TZ_LOG
593 NOTIFY_LOG("notify_register_check(%s) failed: %u\n", name, nstat);
594 #endif /* NOTIFY_TZ_LOG */
595 return;
596 }
597 /* don't need to request monitoring /etc/localtime */
598 if (name != notify_tz_name) {
599 #ifdef NOTIFY_TZ_DEBUG
600 NOTIFY_TZ_PRINTF("notify_register_tz: monitor %s\n", file);
601 #endif /* NOTIFY_TZ_DEBUG */
602 nstat = notify_monitor_file(p->token, file, 0);
603 if (nstat != 0) {
604 notify_cancel(p->token);
605 p->token = -1;
606 p->is_set = 0;
607 #ifdef NOTIFY_TZ_DEBUG
608 NOTIFY_TZ_PRINTF("***notify_register_tz: notify_monitor_file failed: %u\n", nstat);
609 #endif /* NOTIFY_TZ_DEBUG */
610 #ifdef NOTIFY_TZ_LOG
611 NOTIFY_LOG("notify_monitor_file(%s) failed: %u\n", file, nstat);
612 #endif /* NOTIFY_TZ_LOG */
613 return;
614 }
615 }
616 notify_check(p->token, &ncheck); /* this always returns true */
617 }
618 #endif /* NOTIFY_TZ */
619
620 static int
621 differ_by_repeat(const time_t t1, const time_t t0)
622 {
623 int_fast64_t _t0 = t0;
624 int_fast64_t _t1 = t1;
625
626 if (TYPE_INTEGRAL(time_t) &&
627 TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
628 return 0;
629 //turn ((int_fast64_t)(t1 - t0) == SECSPERREPEAT);
630 return _t1 - _t0 == SECSPERREPEAT;
631 }
632
633 static int
634 #ifdef NOTIFY_TZ
635 tzload(name, sp, path, doextend)
636 #else /* ! NOTIFY_TZ */
637 tzload(name, sp, doextend)
638 #endif /* NOTIFY_TZ */
639 const char * name;
640 struct state * const sp;
641 #ifdef NOTIFY_TZ
642 char * path; /* copy full path if non-NULL */
643 #endif /* NOTIFY_TZ */
644 register const int doextend;
645 {
646 const char * p;
647 int i;
648 int fid;
649 int stored;
650 int nread;
651 int res;
652 union {
653 struct tzhead tzhead;
654 char buf[2 * sizeof(struct tzhead) +
655 2 * sizeof *sp +
656 4 * TZ_MAX_TIMES];
657 } *u;
658
659 u = NULL;
660 res = -1;
661 sp->goback = sp->goahead = FALSE;
662
663 #ifdef NOTIFY_TZ_DEBUG
664 NOTIFY_TZ_PRINTF("tzload: name=%s\n", name);
665 #endif /* NOTIFY_TZ_DEBUG */
666 /* XXX The following is from OpenBSD, and I'm not sure it is correct */
667 if (name != NULL && issetugid() != 0)
668 if ((name[0] == ':' && name[1] == '/') ||
669 name[0] == '/' || strchr(name, '.'))
670 name = NULL;
671 #ifdef NOTIFY_TZ
672 if (path)
673 *path = 0; /* default to empty string on error */
674 #endif /* NOTIFY_TZ */
675 if (name == NULL && (name = TZDEFAULT) == NULL)
676 return -1;
677 {
678 int doaccess;
679 struct stat stab;
680 /*
681 ** Section 4.9.1 of the C standard says that
682 ** "FILENAME_MAX expands to an integral constant expression
683 ** that is the size needed for an array of char large enough
684 ** to hold the longest file name string that the implementation
685 ** guarantees can be opened."
686 */
687 char *fullname;
688
689 fullname = malloc(FILENAME_MAX + 1);
690 if (fullname == NULL)
691 goto out;
692
693 if (name[0] == ':')
694 ++name;
695 doaccess = name[0] == '/';
696 if (!doaccess) {
697 if ((p = TZDIR) == NULL) {
698 free(fullname);
699 return -1;
700 }
701 if (strlen(p) + 1 + strlen(name) >= FILENAME_MAX) {
702 free(fullname);
703 return -1;
704 }
705 (void) strcpy(fullname, p);
706 (void) strcat(fullname, "/");
707 (void) strcat(fullname, name);
708 /*
709 ** Set doaccess if '.' (as in "../") shows up in name.
710 */
711 if (strchr(name, '.') != NULL)
712 doaccess = TRUE;
713 name = fullname;
714 }
715 #ifdef NOTIFY_TZ
716 if (path) {
717 if (strlen(name) > FILENAME_MAX)
718 return -1;
719 strcpy(path, name);
720 }
721 #endif /* NOTIFY_TZ */
722 if (doaccess && access(name, R_OK) != 0) {
723 free(fullname);
724 return -1;
725 }
726 if ((fid = _open(name, OPEN_MODE)) == -1) {
727 free(fullname);
728 return -1;
729 }
730 if ((_fstat(fid, &stab) < 0) || !S_ISREG(stab.st_mode)) {
731 free(fullname);
732 _close(fid);
733 return -1;
734 }
735 free(fullname);
736 }
737 u = malloc(sizeof(*u));
738 if (u == NULL)
739 goto out;
740 #ifdef NOTIFY_TZ_DEBUG
741 NOTIFY_TZ_PRINTF("tzload: reading %s\n", name);
742 #endif /* NOTIFY_TZ_DEBUG */
743 nread = _read(fid, u->buf, sizeof u->buf);
744 if (_close(fid) < 0 || nread <= 0)
745 goto out;
746 for (stored = 4; stored <= 8; stored *= 2) {
747 int ttisstdcnt;
748 int ttisgmtcnt;
749
750 ttisstdcnt = (int) detzcode(u->tzhead.tzh_ttisstdcnt);
751 ttisgmtcnt = (int) detzcode(u->tzhead.tzh_ttisgmtcnt);
752 sp->leapcnt = (int) detzcode(u->tzhead.tzh_leapcnt);
753 sp->timecnt = (int) detzcode(u->tzhead.tzh_timecnt);
754 sp->typecnt = (int) detzcode(u->tzhead.tzh_typecnt);
755 sp->charcnt = (int) detzcode(u->tzhead.tzh_charcnt);
756 p = u->tzhead.tzh_charcnt + sizeof u->tzhead.tzh_charcnt;
757 if (sp->leapcnt < 0 || sp->leapcnt > TZ_MAX_LEAPS ||
758 sp->typecnt <= 0 || sp->typecnt > TZ_MAX_TYPES ||
759 sp->timecnt < 0 || sp->timecnt > TZ_MAX_TIMES ||
760 sp->charcnt < 0 || sp->charcnt > TZ_MAX_CHARS ||
761 (ttisstdcnt != sp->typecnt && ttisstdcnt != 0) ||
762 (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
763 goto out;
764 if (nread - (p - u->buf) <
765 sp->timecnt * stored + /* ats */
766 sp->timecnt + /* types */
767 sp->typecnt * 6 + /* ttinfos */
768 sp->charcnt + /* chars */
769 sp->leapcnt * (stored + 4) + /* lsinfos */
770 ttisstdcnt + /* ttisstds */
771 ttisgmtcnt) /* ttisgmts */
772 goto out;
773 for (i = 0; i < sp->timecnt; ++i) {
774 sp->ats[i] = (stored == 4) ?
775 detzcode(p) : detzcode64(p);
776 p += stored;
777 }
778 for (i = 0; i < sp->timecnt; ++i) {
779 sp->types[i] = (unsigned char) *p++;
780 if (sp->types[i] >= sp->typecnt)
781 goto out;
782 }
783 for (i = 0; i < sp->typecnt; ++i) {
784 struct ttinfo * ttisp;
785
786 ttisp = &sp->ttis[i];
787 ttisp->tt_gmtoff = detzcode(p);
788 p += 4;
789 ttisp->tt_isdst = (unsigned char) *p++;
790 if (ttisp->tt_isdst != 0 && ttisp->tt_isdst != 1)
791 goto out;
792 ttisp->tt_abbrind = (unsigned char) *p++;
793 if (ttisp->tt_abbrind < 0 ||
794 ttisp->tt_abbrind > sp->charcnt)
795 goto out;
796 }
797 for (i = 0; i < sp->charcnt; ++i)
798 sp->chars[i] = *p++;
799 sp->chars[i] = '\0'; /* ensure '\0' at end */
800 for (i = 0; i < sp->leapcnt; ++i) {
801 struct lsinfo * lsisp;
802
803 lsisp = &sp->lsis[i];
804 lsisp->ls_trans = (stored == 4) ?
805 detzcode(p) : detzcode64(p);
806 p += stored;
807 lsisp->ls_corr = detzcode(p);
808 p += 4;
809 }
810 for (i = 0; i < sp->typecnt; ++i) {
811 struct ttinfo * ttisp;
812
813 ttisp = &sp->ttis[i];
814 if (ttisstdcnt == 0)
815 ttisp->tt_ttisstd = FALSE;
816 else {
817 ttisp->tt_ttisstd = *p++;
818 if (ttisp->tt_ttisstd != TRUE &&
819 ttisp->tt_ttisstd != FALSE)
820 goto out;
821 }
822 }
823 for (i = 0; i < sp->typecnt; ++i) {
824 struct ttinfo * ttisp;
825
826 ttisp = &sp->ttis[i];
827 if (ttisgmtcnt == 0)
828 ttisp->tt_ttisgmt = FALSE;
829 else {
830 ttisp->tt_ttisgmt = *p++;
831 if (ttisp->tt_ttisgmt != TRUE &&
832 ttisp->tt_ttisgmt != FALSE)
833 goto out;
834 }
835 }
836 /*
837 ** Out-of-sort ats should mean we're running on a
838 ** signed time_t system but using a data file with
839 ** unsigned values (or vice versa).
840 */
841 for (i = 0; i < sp->timecnt - 2; ++i)
842 if (sp->ats[i] > sp->ats[i + 1]) {
843 ++i;
844 if (TYPE_SIGNED(time_t)) {
845 /*
846 ** Ignore the end (easy).
847 */
848 sp->timecnt = i;
849 } else {
850 /*
851 ** Ignore the beginning (harder).
852 */
853 register int j;
854
855 for (j = 0; j + i < sp->timecnt; ++j) {
856 sp->ats[j] = sp->ats[j + i];
857 sp->types[j] = sp->types[j + i];
858 }
859 sp->timecnt = j;
860 }
861 break;
862 }
863 /*
864 ** If this is an old file, we're done.
865 */
866 if (u->tzhead.tzh_version[0] == '\0')
867 break;
868 nread -= p - u->buf;
869 for (i = 0; i < nread; ++i)
870 u->buf[i] = p[i];
871 /*
872 ** If this is a narrow integer time_t system, we're done.
873 */
874 if (stored >= (int) sizeof(time_t) && TYPE_INTEGRAL(time_t))
875 break;
876 }
877 if (doextend && nread > 2 &&
878 u->buf[0] == '\n' && u->buf[nread - 1] == '\n' &&
879 sp->typecnt + 2 <= TZ_MAX_TYPES) {
880 struct state *ts;
881 register int result;
882
883 ts = malloc(sizeof(*ts));
884 if (ts == NULL)
885 goto out;
886 u->buf[nread - 1] = '\0';
887 result = tzparse(&u->buf[1], ts, FALSE);
888 if (result == 0 && ts->typecnt == 2 &&
889 sp->charcnt + ts->charcnt <= TZ_MAX_CHARS) {
890 for (i = 0; i < 2; ++i)
891 ts->ttis[i].tt_abbrind +=
892 sp->charcnt;
893 for (i = 0; i < ts->charcnt; ++i)
894 sp->chars[sp->charcnt++] =
895 ts->chars[i];
896 i = 0;
897 while (i < ts->timecnt &&
898 ts->ats[i] <=
899 sp->ats[sp->timecnt - 1])
900 ++i;
901 while (i < ts->timecnt &&
902 sp->timecnt < TZ_MAX_TIMES) {
903 sp->ats[sp->timecnt] =
904 ts->ats[i];
905 sp->types[sp->timecnt] =
906 sp->typecnt +
907 ts->types[i];
908 ++sp->timecnt;
909 ++i;
910 }
911 sp->ttis[sp->typecnt++] = ts->ttis[0];
912 sp->ttis[sp->typecnt++] = ts->ttis[1];
913 }
914 free(ts);
915 }
916 if (sp->timecnt > 1) {
917 for (i = 1; i < sp->timecnt; ++i)
918 if (typesequiv(sp, sp->types[i], sp->types[0]) &&
919 differ_by_repeat(sp->ats[i], sp->ats[0])) {
920 sp->goback = TRUE;
921 break;
922 }
923 for (i = sp->timecnt - 2; i >= 0; --i)
924 if (typesequiv(sp, sp->types[sp->timecnt - 1],
925 sp->types[i]) &&
926 differ_by_repeat(sp->ats[sp->timecnt - 1],
927 sp->ats[i])) {
928 sp->goahead = TRUE;
929 break;
930 }
931 }
932 res = 0;
933 out:
934 free(u);
935 return (res);
936 }
937
938 static int
939 typesequiv(sp, a, b)
940 const struct state * const sp;
941 const int a;
942 const int b;
943 {
944 register int result;
945
946 if (sp == NULL ||
947 a < 0 || a >= sp->typecnt ||
948 b < 0 || b >= sp->typecnt)
949 result = FALSE;
950 else {
951 register const struct ttinfo * ap = &sp->ttis[a];
952 register const struct ttinfo * bp = &sp->ttis[b];
953 result = ap->tt_gmtoff == bp->tt_gmtoff &&
954 ap->tt_isdst == bp->tt_isdst &&
955 ap->tt_ttisstd == bp->tt_ttisstd &&
956 ap->tt_ttisgmt == bp->tt_ttisgmt &&
957 strcmp(&sp->chars[ap->tt_abbrind],
958 &sp->chars[bp->tt_abbrind]) == 0;
959 }
960 return result;
961 }
962
963 static const int mon_lengths[2][MONSPERYEAR] = {
964 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
965 { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
966 };
967
968 static const int year_lengths[2] = {
969 DAYSPERNYEAR, DAYSPERLYEAR
970 };
971
972 /*
973 ** Given a pointer into a time zone string, scan until a character that is not
974 ** a valid character in a zone name is found. Return a pointer to that
975 ** character.
976 */
977
978 static const char *
979 getzname(strp, name, len)
980 const char * strp;
981 char ** name;
982 size_t * len;
983 {
984 char c;
985 char * ket;
986
987 if (*strp == '<' && (ket = strchr(strp, '>')) != NULL) {
988 *name = (char *)(strp + 1);
989 *len = ket - strp - 1;
990 return ket + 1;
991 }
992 *name = (char *)strp;
993 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
994 c != '+')
995 ++strp;
996 *len = strp - *name;
997 return strp;
998 }
999
1000 /*
1001 ** Given a pointer into an extended time zone string, scan until the ending
1002 ** delimiter of the zone name is located. Return a pointer to the delimiter.
1003 **
1004 ** As with getzname above, the legal character set is actually quite
1005 ** restricted, with other characters producing undefined results.
1006 ** We don't do any checking here; checking is done later in common-case code.
1007 */
1008
1009 static const char *
1010 getqzname(register const char *strp, const int delim)
1011 {
1012 register int c;
1013
1014 while ((c = *strp) != '\0' && c != delim)
1015 ++strp;
1016 return strp;
1017 }
1018
1019 /*
1020 ** Given a pointer into a time zone string, extract a number from that string.
1021 ** Check that the number is within a specified range; if it is not, return
1022 ** NULL.
1023 ** Otherwise, return a pointer to the first character not part of the number.
1024 */
1025
1026 static const char *
1027 getnum(strp, nump, min, max)
1028 const char * strp;
1029 int * const nump;
1030 const int min;
1031 const int max;
1032 {
1033 char c;
1034 int num;
1035
1036 if (strp == NULL || !is_digit(c = *strp))
1037 return NULL;
1038 num = 0;
1039 do {
1040 num = num * 10 + (c - '0');
1041 if (num > max)
1042 return NULL; /* illegal value */
1043 c = *++strp;
1044 } while (is_digit(c));
1045 if (num < min)
1046 return NULL; /* illegal value */
1047 *nump = num;
1048 return strp;
1049 }
1050
1051 /*
1052 ** Given a pointer into a time zone string, extract a number of seconds,
1053 ** in hh[:mm[:ss]] form, from the string.
1054 ** If any error occurs, return NULL.
1055 ** Otherwise, return a pointer to the first character not part of the number
1056 ** of seconds.
1057 */
1058
1059 static const char *
1060 getsecs(strp, secsp)
1061 const char * strp;
1062 long * const secsp;
1063 {
1064 int num;
1065
1066 /*
1067 ** `HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
1068 ** "M10.4.6/26", which does not conform to Posix,
1069 ** but which specifies the equivalent of
1070 ** ``02:00 on the first Sunday on or after 23 Oct''.
1071 */
1072 strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
1073 if (strp == NULL)
1074 return NULL;
1075 *secsp = num * (long) SECSPERHOUR;
1076 if (*strp == ':') {
1077 ++strp;
1078 strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
1079 if (strp == NULL)
1080 return NULL;
1081 *secsp += num * SECSPERMIN;
1082 if (*strp == ':') {
1083 ++strp;
1084 /* `SECSPERMIN' allows for leap seconds. */
1085 strp = getnum(strp, &num, 0, SECSPERMIN);
1086 if (strp == NULL)
1087 return NULL;
1088 *secsp += num;
1089 }
1090 }
1091 return strp;
1092 }
1093
1094 /*
1095 ** Given a pointer into a time zone string, extract an offset, in
1096 ** [+-]hh[:mm[:ss]] form, from the string.
1097 ** If any error occurs, return NULL.
1098 ** Otherwise, return a pointer to the first character not part of the time.
1099 */
1100
1101 static const char *
1102 getoffset(strp, offsetp)
1103 const char * strp;
1104 long * const offsetp;
1105 {
1106 int neg = 0;
1107
1108 if (*strp == '-') {
1109 neg = 1;
1110 ++strp;
1111 } else if (*strp == '+')
1112 ++strp;
1113 strp = getsecs(strp, offsetp);
1114 if (strp == NULL)
1115 return NULL; /* illegal time */
1116 if (neg)
1117 *offsetp = -*offsetp;
1118 return strp;
1119 }
1120
1121 /*
1122 ** Given a pointer into a time zone string, extract a rule in the form
1123 ** date[/time]. See POSIX section 8 for the format of "date" and "time".
1124 ** If a valid rule is not found, return NULL.
1125 ** Otherwise, return a pointer to the first character not part of the rule.
1126 */
1127
1128 static const char *
1129 getrule(strp, rulep)
1130 const char * strp;
1131 struct rule * const rulep;
1132 {
1133 if (*strp == 'J') {
1134 /*
1135 ** Julian day.
1136 */
1137 rulep->r_type = JULIAN_DAY;
1138 ++strp;
1139 strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
1140 } else if (*strp == 'M') {
1141 /*
1142 ** Month, week, day.
1143 */
1144 rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
1145 ++strp;
1146 strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
1147 if (strp == NULL)
1148 return NULL;
1149 if (*strp++ != '.')
1150 return NULL;
1151 strp = getnum(strp, &rulep->r_week, 1, 5);
1152 if (strp == NULL)
1153 return NULL;
1154 if (*strp++ != '.')
1155 return NULL;
1156 strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
1157 } else if (is_digit(*strp)) {
1158 /*
1159 ** Day of year.
1160 */
1161 rulep->r_type = DAY_OF_YEAR;
1162 strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
1163 } else return NULL; /* invalid format */
1164 if (strp == NULL)
1165 return NULL;
1166 if (*strp == '/') {
1167 /*
1168 ** Time specified.
1169 */
1170 ++strp;
1171 strp = getsecs(strp, &rulep->r_time);
1172 } else rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
1173 return strp;
1174 }
1175
1176 /*
1177 ** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
1178 ** year, a rule, and the offset from UTC at the time that rule takes effect,
1179 ** calculate the Epoch-relative time that rule takes effect.
1180 */
1181
1182 static time_t
1183 transtime(janfirst, year, rulep, offset)
1184 const time_t janfirst;
1185 const int year;
1186 const struct rule * const rulep;
1187 const long offset;
1188 {
1189 int leapyear;
1190 time_t value;
1191 int i;
1192 int d, m1, yy0, yy1, yy2, dow;
1193
1194 INITIALIZE(value);
1195 leapyear = isleap(year);
1196 switch (rulep->r_type) {
1197
1198 case JULIAN_DAY:
1199 /*
1200 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
1201 ** years.
1202 ** In non-leap years, or if the day number is 59 or less, just
1203 ** add SECSPERDAY times the day number-1 to the time of
1204 ** January 1, midnight, to get the day.
1205 */
1206 value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
1207 if (leapyear && rulep->r_day >= 60)
1208 value += SECSPERDAY;
1209 break;
1210
1211 case DAY_OF_YEAR:
1212 /*
1213 ** n - day of year.
1214 ** Just add SECSPERDAY times the day number to the time of
1215 ** January 1, midnight, to get the day.
1216 */
1217 value = janfirst + rulep->r_day * SECSPERDAY;
1218 break;
1219
1220 case MONTH_NTH_DAY_OF_WEEK:
1221 /*
1222 ** Mm.n.d - nth "dth day" of month m.
1223 */
1224 value = janfirst;
1225 for (i = 0; i < rulep->r_mon - 1; ++i)
1226 value += mon_lengths[leapyear][i] * SECSPERDAY;
1227
1228 /*
1229 ** Use Zeller's Congruence to get day-of-week of first day of
1230 ** month.
1231 */
1232 m1 = (rulep->r_mon + 9) % 12 + 1;
1233 yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
1234 yy1 = yy0 / 100;
1235 yy2 = yy0 % 100;
1236 dow = ((26 * m1 - 2) / 10 +
1237 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
1238 if (dow < 0)
1239 dow += DAYSPERWEEK;
1240
1241 /*
1242 ** "dow" is the day-of-week of the first day of the month. Get
1243 ** the day-of-month (zero-origin) of the first "dow" day of the
1244 ** month.
1245 */
1246 d = rulep->r_day - dow;
1247 if (d < 0)
1248 d += DAYSPERWEEK;
1249 for (i = 1; i < rulep->r_week; ++i) {
1250 if (d + DAYSPERWEEK >=
1251 mon_lengths[leapyear][rulep->r_mon - 1])
1252 break;
1253 d += DAYSPERWEEK;
1254 }
1255
1256 /*
1257 ** "d" is the day-of-month (zero-origin) of the day we want.
1258 */
1259 value += d * SECSPERDAY;
1260 break;
1261 }
1262
1263 /*
1264 ** "value" is the Epoch-relative time of 00:00:00 UTC on the day in
1265 ** question. To get the Epoch-relative time of the specified local
1266 ** time on that day, add the transition time and the current offset
1267 ** from UTC.
1268 */
1269 return value + rulep->r_time + offset;
1270 }
1271
1272 /*
1273 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1274 ** appropriate.
1275 */
1276
1277 static int
1278 tzparse(name, sp, lastditch)
1279 const char * name;
1280 struct state * const sp;
1281 const int lastditch;
1282 {
1283 const char * stdname;
1284 const char * dstname;
1285 size_t stdlen;
1286 size_t dstlen;
1287 long stdoffset;
1288 long dstoffset;
1289 time_t * atp;
1290 unsigned char * typep;
1291 char * cp;
1292 int load_result;
1293
1294 INITIALIZE(dstname);
1295 if (lastditch) {
1296 stdname = name;
1297 stdlen = strlen(name); /* length of standard zone name */
1298 name += stdlen;
1299 if (stdlen >= sizeof sp->chars)
1300 stdlen = (sizeof sp->chars) - 1;
1301 stdoffset = 0;
1302 } else {
1303 name = getzname(name, (char **)&stdname, &stdlen);
1304 if (*name == '\0')
1305 return -1; /* was "stdoffset = 0;" */
1306 else {
1307 name = getoffset(name, &stdoffset);
1308 if (name == NULL)
1309 return -1;
1310 }
1311 }
1312 #ifdef NOTIFY_TZ
1313 load_result = tzload(TZDEFRULES, sp, NULL, FALSE);
1314 #else /* !NOTIFY_TZ */
1315 load_result = tzload(TZDEFRULES, sp, FALSE);
1316 #endif /* NOTIFY_TZ */
1317 if (load_result != 0)
1318 sp->leapcnt = 0; /* so, we're off a little */
1319 if (*name != '\0') {
1320 if (*name == '<') {
1321 dstname = ++name;
1322 name = getqzname(name, '>');
1323 if (*name != '>')
1324 return -1;
1325 dstlen = name - dstname;
1326 name++;
1327 } else {
1328 dstname = name;
1329 name = getzname(name, (char **)&dstname, &dstlen);
1330 }
1331 if (*name != '\0' && *name != ',' && *name != ';') {
1332 name = getoffset(name, &dstoffset);
1333 if (name == NULL)
1334 return -1;
1335 } else dstoffset = stdoffset - SECSPERHOUR;
1336 if (*name == '\0' && load_result != 0)
1337 name = TZDEFRULESTRING;
1338 if (*name == ',' || *name == ';') {
1339 struct rule start;
1340 struct rule end;
1341 int year;
1342 time_t janfirst;
1343 time_t starttime;
1344 time_t endtime;
1345
1346 ++name;
1347 if ((name = getrule(name, &start)) == NULL)
1348 return -1;
1349 if (*name++ != ',')
1350 return -1;
1351 if ((name = getrule(name, &end)) == NULL)
1352 return -1;
1353 if (*name != '\0')
1354 return -1;
1355 sp->typecnt = 2; /* standard time and DST */
1356 /*
1357 ** Two transitions per year, from EPOCH_YEAR forward.
1358 */
1359 sp->ttis[0].tt_gmtoff = -dstoffset;
1360 sp->ttis[0].tt_isdst = 1;
1361 sp->ttis[0].tt_abbrind = stdlen + 1;
1362 sp->ttis[1].tt_gmtoff = -stdoffset;
1363 sp->ttis[1].tt_isdst = 0;
1364 sp->ttis[1].tt_abbrind = 0;
1365 atp = sp->ats;
1366 typep = sp->types;
1367 janfirst = 0;
1368 sp->timecnt = 0;
1369 for (year = EPOCH_YEAR;
1370 sp->timecnt + 2 <= TZ_MAX_TIMES;
1371 ++year) {
1372 time_t newfirst;
1373
1374 starttime = transtime(janfirst, year, &start,
1375 stdoffset);
1376 endtime = transtime(janfirst, year, &end,
1377 dstoffset);
1378 if (starttime > endtime) {
1379 *atp++ = endtime;
1380 *typep++ = 1; /* DST ends */
1381 *atp++ = starttime;
1382 *typep++ = 0; /* DST begins */
1383 } else {
1384 *atp++ = starttime;
1385 *typep++ = 0; /* DST begins */
1386 *atp++ = endtime;
1387 *typep++ = 1; /* DST ends */
1388 }
1389 sp->timecnt += 2;
1390 newfirst = janfirst;
1391 newfirst += year_lengths[isleap(year)] *
1392 SECSPERDAY;
1393 if (newfirst <= janfirst)
1394 break;
1395 janfirst = newfirst;
1396 }
1397 } else {
1398 long theirstdoffset;
1399 long theirdstoffset;
1400 long theiroffset;
1401 int isdst;
1402 int i;
1403 int j;
1404
1405 if (*name != '\0')
1406 return -1;
1407 /*
1408 ** Initial values of theirstdoffset and theirdstoffset.
1409 */
1410 theirstdoffset = 0;
1411 for (i = 0; i < sp->timecnt; ++i) {
1412 j = sp->types[i];
1413 if (!sp->ttis[j].tt_isdst) {
1414 theirstdoffset =
1415 -sp->ttis[j].tt_gmtoff;
1416 break;
1417 }
1418 }
1419 theirdstoffset = 0;
1420 for (i = 0; i < sp->timecnt; ++i) {
1421 j = sp->types[i];
1422 if (sp->ttis[j].tt_isdst) {
1423 theirdstoffset =
1424 -sp->ttis[j].tt_gmtoff;
1425 break;
1426 }
1427 }
1428 /*
1429 ** Initially we're assumed to be in standard time.
1430 */
1431 isdst = FALSE;
1432 theiroffset = theirstdoffset;
1433 /*
1434 ** Now juggle transition times and types
1435 ** tracking offsets as you do.
1436 */
1437 for (i = 0; i < sp->timecnt; ++i) {
1438 j = sp->types[i];
1439 sp->types[i] = sp->ttis[j].tt_isdst;
1440 if (sp->ttis[j].tt_ttisgmt) {
1441 /* No adjustment to transition time */
1442 } else {
1443 /*
1444 ** If summer time is in effect, and the
1445 ** transition time was not specified as
1446 ** standard time, add the summer time
1447 ** offset to the transition time;
1448 ** otherwise, add the standard time
1449 ** offset to the transition time.
1450 */
1451 /*
1452 ** Transitions from DST to DDST
1453 ** will effectively disappear since
1454 ** POSIX provides for only one DST
1455 ** offset.
1456 */
1457 if (isdst && !sp->ttis[j].tt_ttisstd) {
1458 sp->ats[i] += dstoffset -
1459 theirdstoffset;
1460 } else {
1461 sp->ats[i] += stdoffset -
1462 theirstdoffset;
1463 }
1464 }
1465 theiroffset = -sp->ttis[j].tt_gmtoff;
1466 if (sp->ttis[j].tt_isdst)
1467 theirdstoffset = theiroffset;
1468 else theirstdoffset = theiroffset;
1469 }
1470 /*
1471 ** Finally, fill in ttis.
1472 ** ttisstd and ttisgmt need not be handled.
1473 */
1474 sp->ttis[0].tt_gmtoff = -stdoffset;
1475 sp->ttis[0].tt_isdst = FALSE;
1476 sp->ttis[0].tt_abbrind = 0;
1477 sp->ttis[1].tt_gmtoff = -dstoffset;
1478 sp->ttis[1].tt_isdst = TRUE;
1479 sp->ttis[1].tt_abbrind = stdlen + 1;
1480 sp->typecnt = 2;
1481 }
1482 } else {
1483 dstlen = 0;
1484 sp->typecnt = 1; /* only standard time */
1485 sp->timecnt = 0;
1486 sp->ttis[0].tt_gmtoff = -stdoffset;
1487 sp->ttis[0].tt_isdst = 0;
1488 sp->ttis[0].tt_abbrind = 0;
1489 }
1490 sp->charcnt = stdlen + 1;
1491 if (dstlen != 0)
1492 sp->charcnt += dstlen + 1;
1493 if ((size_t) sp->charcnt > sizeof sp->chars)
1494 return -1;
1495 cp = sp->chars;
1496 (void) strncpy(cp, stdname, stdlen);
1497 cp += stdlen;
1498 *cp++ = '\0';
1499 if (dstlen != 0) {
1500 (void) strncpy(cp, dstname, dstlen);
1501 *(cp + dstlen) = '\0';
1502 }
1503 return 0;
1504 }
1505
1506 static void
1507 #ifdef NOTIFY_TZ
1508 gmtload(sp, path)
1509 #else /* ! NOTIFY_TZ */
1510 gmtload(sp)
1511 #endif /* NOTIFY_TZ */
1512 struct state * const sp;
1513 #ifdef NOTIFY_TZ
1514 char *path;
1515 #endif /* NOTIFY_TZ */
1516 {
1517 #ifdef NOTIFY_TZ
1518 if (tzload(gmt, sp, path, TRUE) != 0)
1519 #else /* ! NOTIFY_TZ */
1520 if (tzload(gmt, sp, TRUE) != 0)
1521 #endif /* NOTIFY_TZ */
1522 (void) tzparse(gmt, sp, TRUE);
1523 }
1524
1525 /**
1526 * In NULL_BOOTSTRAP environments, we can't use notifyd to learn about the changes in timezone.
1527 * Instead, we look at the modified time of the TZDEFAULT symlink.
1528 * As a performance optimization, we only reload the timezone data if the modified time is newer than the
1529 * last time we loaded the timezone file.
1530 *
1531 * If the tzload fails, we need to reset the saved timestamp to force the timezone file to be reloaded next time
1532 * we try to use it. This is a special case that occurs at first boot for launchd (and other early boot-tasks)
1533 * rdar://60592414
1534 */
1535 static struct timespec last_default_tzload_mtimespec = {0, 0};
1536 static void
1537 tzsetwall_check_default_file_timestamp(void)
1538 {
1539 if (!TZDEFAULT) {
1540 return;
1541 }
1542
1543 struct stat statbuf;
1544
1545 if (lstat(TZDEFAULT, &statbuf) == 0) {
1546 if (statbuf.st_mtimespec.tv_sec > last_default_tzload_mtimespec.tv_sec ||
1547 (statbuf.st_mtimespec.tv_sec == last_default_tzload_mtimespec.tv_sec &&
1548 statbuf.st_mtimespec.tv_nsec > last_default_tzload_mtimespec.tv_nsec)) {
1549 /* Trigger resetting the local TZ */
1550 lcl_is_set = 0;
1551 }
1552 last_default_tzload_mtimespec = statbuf.st_mtimespec;
1553 }
1554 }
1555
1556 static void
1557 tzsetwall_basic(int rdlocked)
1558 {
1559 #ifdef NOTIFY_TZ
1560 if (bootstrap_port != MACH_PORT_NULL) {
1561 notify_check_tz(&lcl_notify);
1562 } else {
1563 tzsetwall_check_default_file_timestamp();
1564 }
1565 #else
1566 tzsetwall_check_default_file_timestamp();
1567 #endif /* NOTIFY_TZ */
1568
1569 if (!rdlocked)
1570 _RWLOCK_RDLOCK(&lcl_rwlock);
1571 if (lcl_is_set < 0) {
1572 #ifdef NOTIFY_TZ_DEBUG
1573 NOTIFY_TZ_PRINTF("tzsetwall_basic lcl_is_set < 0\n");
1574 #endif
1575 if (!rdlocked)
1576 _RWLOCK_UNLOCK(&lcl_rwlock);
1577 return;
1578 }
1579 #ifdef NOTIFY_TZ_DEBUG
1580 NOTIFY_TZ_PRINTF("tzsetwall_basic not set\n");
1581 #endif
1582 _RWLOCK_UNLOCK(&lcl_rwlock);
1583
1584 _RWLOCK_WRLOCK(&lcl_rwlock);
1585 lcl_is_set = -1;
1586
1587 #ifdef ALL_STATE
1588 if (lclptr == NULL) {
1589 lclptr = calloc(1, sizeof *lclptr);
1590 if (lclptr == NULL) {
1591 settzname(); /* all we can do */
1592 _RWLOCK_UNLOCK(&lcl_rwlock);
1593 if (rdlocked)
1594 _RWLOCK_RDLOCK(&lcl_rwlock);
1595 return;
1596 }
1597 }
1598 #endif /* defined ALL_STATE */
1599 #ifdef NOTIFY_TZ
1600 {
1601 char fullname[FILENAME_MAX + 1];
1602 if (tzload((char *) NULL, lclptr, fullname, TRUE) != 0) {
1603 // The load failed, so we need to reset the cached modified time
1604 // of the timezone file
1605 last_default_tzload_mtimespec = (const struct timespec){0};
1606
1607 /*
1608 * If fullname is empty (an error occurred) then
1609 * default to the UTC path
1610 */
1611 gmtload(lclptr, *fullname ? NULL : fullname);
1612 }
1613 notify_register_tz(fullname, &lcl_notify);
1614 }
1615 #else /* ! NOTIFY_TZ */
1616 if (tzload((char *) NULL, lclptr, TRUE) != 0)
1617 gmtload(lclptr);
1618 #endif /* NOTIFY_TZ */
1619 settzname();
1620 _RWLOCK_UNLOCK(&lcl_rwlock);
1621
1622 if (rdlocked)
1623 _RWLOCK_RDLOCK(&lcl_rwlock);
1624 }
1625
1626 void
1627 tzsetwall(void)
1628 {
1629 #ifdef NOTIFY_TZ_DEBUG
1630 NOTIFY_TZ_PRINTF("tzsetwall called\n");
1631 #endif /* NOTIFY_TZ_DEBUG */
1632 tzsetwall_basic(0);
1633 }
1634
1635 __private_extern__ void
1636 tzset_basic(int rdlocked)
1637 {
1638 const char * name;
1639
1640 name = getenv("TZ");
1641 if (name == NULL) {
1642 tzsetwall_basic(rdlocked);
1643 return;
1644 }
1645
1646 #ifdef NOTIFY_TZ
1647 notify_check_tz(&lcl_notify);
1648 #endif /* NOTIFY_TZ */
1649 if (!rdlocked)
1650 _RWLOCK_RDLOCK(&lcl_rwlock);
1651 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
1652 if (!rdlocked)
1653 _RWLOCK_UNLOCK(&lcl_rwlock);
1654 #ifdef NOTIFY_TZ_DEBUG
1655 NOTIFY_TZ_PRINTF("tzset_basic matched %s\n", lcl_TZname);
1656 #endif
1657 return;
1658 }
1659 _RWLOCK_UNLOCK(&lcl_rwlock);
1660
1661 _RWLOCK_WRLOCK(&lcl_rwlock);
1662 lcl_is_set = strlen(name) < sizeof lcl_TZname;
1663 if (lcl_is_set)
1664 (void) strcpy(lcl_TZname, name);
1665
1666 #ifdef ALL_STATE
1667 if (lclptr == NULL) {
1668 lclptr = (struct state *) calloc(1, sizeof *lclptr);
1669 if (lclptr == NULL) {
1670 settzname(); /* all we can do */
1671 _RWLOCK_UNLOCK(&lcl_rwlock);
1672 if (rdlocked)
1673 _RWLOCK_RDLOCK(&lcl_rwlock);
1674 return;
1675 }
1676 }
1677 #endif /* defined ALL_STATE */
1678 if (*name == '\0') {
1679 /*
1680 ** User wants it fast rather than right.
1681 */
1682 lclptr->leapcnt = 0; /* so, we're off a little */
1683 lclptr->timecnt = 0;
1684 lclptr->typecnt = 0;
1685 lclptr->ttis[0].tt_isdst = 0;
1686 lclptr->ttis[0].tt_gmtoff = 0;
1687 lclptr->ttis[0].tt_abbrind = 0;
1688 (void) strcpy(lclptr->chars, gmt);
1689 #ifdef NOTIFY_TZ
1690 notify_register_tz(NULL, &lcl_notify);
1691 #endif /* NOTIFY_TZ */
1692 } else
1693 #ifdef NOTIFY_TZ
1694 {
1695 char fullname[FILENAME_MAX + 1];
1696 /*
1697 * parsedOK indicates whether tzparse() was called and
1698 * succeeded. This means that TZ is a time conversion
1699 * specification, so we don't need to register for
1700 * notifications.
1701 */
1702 int parsedOK = FALSE;
1703 if (tzload(name, lclptr, fullname, TRUE) != 0) {
1704 if (name[0] == ':' || !(parsedOK = tzparse(name, lclptr, FALSE) == 0)) {
1705 /*
1706 * If fullname is empty (an error occurred) then
1707 * default to the UTC path
1708 */
1709 (void) gmtload(lclptr, *fullname ? NULL : fullname);
1710 }
1711 }
1712 notify_register_tz(parsedOK ? NULL : fullname, &lcl_notify);
1713 }
1714 #else /* ! NOTIFY_TZ */
1715 if (tzload(name, lclptr, TRUE) != 0)
1716 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
1717 (void) gmtload(lclptr);
1718 #endif /* NOTIFY_TZ */
1719 settzname();
1720 _RWLOCK_UNLOCK(&lcl_rwlock);
1721
1722 if (rdlocked)
1723 _RWLOCK_RDLOCK(&lcl_rwlock);
1724 }
1725
1726 void
1727 tzset(void)
1728 {
1729 #ifdef NOTIFY_TZ_DEBUG
1730 NOTIFY_TZ_PRINTF("tzset called TZ=%s\n", getenv("TZ"));
1731 #endif /* NOTIFY_TZ_DEBUG */
1732 tzset_basic(0);
1733 }
1734
1735 /*
1736 ** The easy way to behave "as if no library function calls" localtime
1737 ** is to not call it--so we drop its guts into "localsub", which can be
1738 ** freely called. (And no, the PANS doesn't require the above behavior--
1739 ** but it *is* desirable.)
1740 **
1741 ** The unused offset argument is for the benefit of mktime variants.
1742 */
1743
1744 /*ARGSUSED*/
1745 #ifdef __LP64__
1746 __private_extern__ struct tm *
1747 #else /* !__LP64__ */
1748 __private_extern__ void
1749 #endif /* __LP64__ */
1750 localsub(const time_t *const timep, const long offset, struct tm *const tmp)
1751 {
1752 struct state * sp;
1753 const struct ttinfo * ttisp;
1754 int i;
1755 #ifdef __LP64__
1756 struct tm * result;
1757 #endif /* __LP64__ */
1758 const time_t t = *timep;
1759
1760 #ifdef NOTIFY_TZ_DEBUG
1761 NOTIFY_TZ_PRINTF("localsub called\n");
1762 #endif /* NOTIFY_TZ_DEBUG */
1763 sp = lclptr;
1764 #ifdef ALL_STATE
1765 if (sp == NULL) {
1766 #ifdef __LP64__
1767 return gmtsub(timep, offset, tmp);
1768 #else /* !__LP64__ */
1769 gmtsub(timep, offset, tmp);
1770 return;
1771 #endif /* __LP64__ */
1772 }
1773 #endif /* defined ALL_STATE */
1774 if ((sp->goback && t < sp->ats[0]) ||
1775 (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
1776 time_t newt = t;
1777 register time_t seconds;
1778 register time_t tcycles;
1779 register int_fast64_t icycles;
1780
1781 if (t < sp->ats[0])
1782 seconds = sp->ats[0] - t;
1783 else seconds = t - sp->ats[sp->timecnt - 1];
1784 --seconds;
1785 tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1786 ++tcycles;
1787 icycles = tcycles;
1788 if (tcycles - icycles >= 1 || icycles - tcycles >= 1) {
1789 #ifdef __LP64__
1790 return NULL;
1791 #else /* !__LP64__ */
1792 return;
1793 #endif /* __LP64__ */
1794 }
1795 seconds = icycles;
1796 seconds *= YEARSPERREPEAT;
1797 seconds *= AVGSECSPERYEAR;
1798 if (t < sp->ats[0])
1799 newt += seconds;
1800 else newt -= seconds;
1801 if (newt < sp->ats[0] ||
1802 newt > sp->ats[sp->timecnt - 1])
1803 #ifdef __LP64__
1804 return NULL; /* "cannot happen" */
1805 result = localsub(&newt, offset, tmp);
1806 if (result == tmp) {
1807 #else /* !__LP64__ */
1808 return;
1809 localsub(&newt, offset, tmp);
1810 {
1811 #endif /* __LP64__ */
1812 register time_t newy;
1813
1814 newy = tmp->tm_year;
1815 if (t < sp->ats[0])
1816 newy -= icycles * YEARSPERREPEAT;
1817 else newy += icycles * YEARSPERREPEAT;
1818 tmp->tm_year = newy;
1819 if (tmp->tm_year != newy)
1820 #ifdef __LP64__
1821 return NULL;
1822 }
1823 return result;
1824 #else /* !__LP64__ */
1825 return;
1826 }
1827 return;
1828 #endif /* __LP64__ */
1829 }
1830 if (sp->timecnt == 0 || t < sp->ats[0]) {
1831 i = 0;
1832 while (sp->ttis[i].tt_isdst)
1833 if (++i >= sp->typecnt) {
1834 i = 0;
1835 break;
1836 }
1837 } else {
1838 register int lo = 1;
1839 register int hi = sp->timecnt;
1840
1841 while (lo < hi) {
1842 register int mid = (lo + hi) >> 1;
1843
1844 if (t < sp->ats[mid])
1845 hi = mid;
1846 else lo = mid + 1;
1847 }
1848 i = (int) sp->types[lo - 1];
1849 }
1850 ttisp = &sp->ttis[i];
1851 /*
1852 ** To get (wrong) behavior that's compatible with System V Release 2.0
1853 ** you'd replace the statement below with
1854 ** t += ttisp->tt_gmtoff;
1855 ** timesub(&t, 0L, sp, tmp);
1856 */
1857 #ifdef __LP64__
1858 result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1859 if (result == NULL)
1860 return NULL;
1861 #else /* !__LP64__ */
1862 timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1863 #endif /* __LP64__ */
1864 tmp->tm_isdst = ttisp->tt_isdst;
1865 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
1866 #ifdef TM_ZONE
1867 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
1868 #endif /* defined TM_ZONE */
1869 #ifdef __LP64__
1870 return result;
1871 #endif /* __LP64__ */
1872 }
1873
1874 static void
1875 localtime_key_init(void)
1876 {
1877
1878 localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
1879 localtime_key_error = pthread_key_init_np(localtime_key, free);
1880 }
1881
1882 struct tm *
1883 localtime(const time_t *const timep)
1884 {
1885 struct tm *p_tm;
1886
1887 if (__isthreaded != 0) {
1888 _pthread_once(&localtime_once, localtime_key_init);
1889 if (localtime_key_error != 0) {
1890 errno = localtime_key_error;
1891 return(NULL);
1892 }
1893 p_tm = _pthread_getspecific(localtime_key);
1894 if (p_tm == NULL) {
1895 if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
1896 == NULL)
1897 return(NULL);
1898 _pthread_setspecific(localtime_key, p_tm);
1899 }
1900 _RWLOCK_RDLOCK(&lcl_rwlock);
1901 tzset_basic(1);
1902 #ifdef __LP64__
1903 p_tm = localsub(timep, 0L, p_tm);
1904 #else /* !__LP64__ */
1905 localsub(timep, 0L, p_tm);
1906 #endif /* __LP64__ */
1907 _RWLOCK_UNLOCK(&lcl_rwlock);
1908 return(p_tm);
1909 } else {
1910 tzset_basic(0);
1911 #ifdef __LP64__
1912 return localsub(timep, 0L, &tm);
1913 #else /* !__LP64__ */
1914 localsub(timep, 0L, &tm);
1915 return(&tm);
1916 #endif /* __LP64__ */
1917 }
1918 }
1919
1920 /*
1921 ** Re-entrant version of localtime.
1922 */
1923
1924 struct tm *
1925 localtime_r(const time_t *const __restrict timep, struct tm * __restrict tmp)
1926 {
1927 _RWLOCK_RDLOCK(&lcl_rwlock);
1928 tzset_basic(1);
1929 #ifdef __LP64__
1930 tmp = localsub(timep, 0L, tmp);
1931 #else /* !__LP64__ */
1932 localsub(timep, 0L, tmp);
1933 #endif /* __LP64__ */
1934 _RWLOCK_UNLOCK(&lcl_rwlock);
1935 return tmp;
1936 }
1937
1938 static void
1939 gmt_init(void)
1940 {
1941
1942 #ifdef ALL_STATE
1943 #ifdef NOTIFY_TZ
1944 if (gmtptr == NULL)
1945 #endif /* NOTIFY_TZ */
1946 gmtptr = (struct state *) calloc(1, sizeof *gmtptr);
1947 if (gmtptr != NULL)
1948 #endif /* defined ALL_STATE */
1949 #ifdef NOTIFY_TZ
1950 {
1951 char fullname[FILENAME_MAX + 1];
1952 gmtload(gmtptr, fullname);
1953 notify_register_tz(fullname, &gmt_notify);
1954 }
1955 #else /* ! NOTIFY_TZ */
1956 gmtload(gmtptr);
1957 #endif /* NOTIFY_TZ */
1958 }
1959
1960 /*
1961 ** gmtsub is to gmtime as localsub is to localtime.
1962 */
1963
1964 #ifdef __LP64__
1965 static struct tm *
1966 #else /* !__LP64__ */
1967 static void
1968 #endif /* __LP64__ */
1969 gmtsub(timep, offset, tmp)
1970 const time_t * const timep;
1971 const long offset;
1972 struct tm * const tmp;
1973 {
1974 #ifdef __LP64__
1975 register struct tm * result;
1976 #endif /* __LP64__ */
1977
1978 #ifdef NOTIFY_TZ_DEBUG
1979 NOTIFY_TZ_PRINTF("gmtsub called\n");
1980 #endif /* NOTIFY_TZ_DEBUG */
1981 #ifdef NOTIFY_TZ
1982 notify_check_tz(&gmt_notify);
1983 #endif /* NOTIFY_TZ */
1984 pthread_once(&gmt_once, gmt_init);
1985 #ifdef __LP64__
1986 result = timesub(timep, offset, gmtptr, tmp);
1987 if (result == NULL)
1988 return NULL;
1989 #else /* !__LP64__ */
1990 timesub(timep, offset, gmtptr, tmp);
1991 #endif /* __LP64__ */
1992 #ifdef TM_ZONE
1993 /*
1994 ** Could get fancy here and deliver something such as
1995 ** "UTC+xxxx" or "UTC-xxxx" if offset is non-zero,
1996 ** but this is no time for a treasure hunt.
1997 */
1998 if (offset != 0)
1999 tmp->TM_ZONE = (char*)wildabbr;
2000 else {
2001 #ifdef ALL_STATE
2002 if (gmtptr == NULL)
2003 tmp->TM_ZONE = (char *)gmt;
2004 else tmp->TM_ZONE = gmtptr->chars;
2005 #endif /* defined ALL_STATE */
2006 #ifndef ALL_STATE
2007 tmp->TM_ZONE = gmtptr->chars;
2008 #endif /* State Farm */
2009 }
2010 #endif /* defined TM_ZONE */
2011 #ifdef __LP64__
2012 return result;
2013 #endif /* __LP64__ */
2014 }
2015
2016 static void
2017 gmtime_key_init(void)
2018 {
2019
2020 gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
2021 gmtime_key_error = pthread_key_init_np(gmtime_key, free);
2022 }
2023
2024 struct tm *
2025 gmtime(const time_t *const timep)
2026 {
2027 struct tm *p_tm;
2028
2029 if (__isthreaded != 0) {
2030 _pthread_once(&gmtime_once, gmtime_key_init);
2031 if (gmtime_key_error != 0) {
2032 errno = gmtime_key_error;
2033 return(NULL);
2034 }
2035 /*
2036 * Changed to follow POSIX.1 threads standard, which
2037 * is what BSD currently has.
2038 */
2039 if ((p_tm = _pthread_getspecific(gmtime_key)) == NULL) {
2040 if ((p_tm = (struct tm *)malloc(sizeof(struct tm)))
2041 == NULL) {
2042 return(NULL);
2043 }
2044 _pthread_setspecific(gmtime_key, p_tm);
2045 }
2046 #ifdef __LP64__
2047 return gmtsub(timep, 0L, p_tm);
2048 #else /* !__LP64__ */
2049 gmtsub(timep, 0L, p_tm);
2050 return(p_tm);
2051 #endif /* __LP64__ */
2052 }
2053 else {
2054 #ifdef __LP64__
2055 return gmtsub(timep, 0L, &tm);
2056 #else /* !__LP64__ */
2057 gmtsub(timep, 0L, &tm);
2058 return(&tm);
2059 #endif /* __LP64__ */
2060 }
2061 }
2062
2063 /*
2064 * Re-entrant version of gmtime.
2065 */
2066
2067 struct tm *
2068 gmtime_r(const time_t *const timep, struct tm *tmp)
2069 {
2070
2071 #ifdef __LP64__
2072 return gmtsub(timep, 0L, tmp);
2073 #else /* !__LP64__ */
2074 gmtsub(timep, 0L, tmp);
2075 return tmp;
2076 #endif /* __LP64__ */
2077 }
2078
2079 #ifdef STD_INSPIRED
2080
2081 struct tm *
2082 offtime(const time_t *const timep, const long offset)
2083 {
2084 #ifdef __LP64__
2085 return gmtsub(timep, offset, &tm);
2086 #else /* !__LP64__ */
2087 gmtsub(timep, offset, &tm);
2088 return &tm;
2089 #endif /* __LP64__ */
2090 }
2091
2092 #endif /* defined STD_INSPIRED */
2093
2094 /*
2095 ** Return the number of leap years through the end of the given year
2096 ** where, to make the math easy, the answer for year zero is defined as zero.
2097 */
2098
2099 __unused static int
2100 leaps_thru_end_of(y)
2101 register const int y;
2102 {
2103 #ifdef __LP64__
2104 return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
2105 -(leaps_thru_end_of(-(y + 1)) + 1);
2106 #else /* !__LP64__ */
2107 return (y / 4 - y / 100 + y / 400);
2108 #endif /* __LP64__ */
2109 }
2110
2111 #ifdef __LP64__
2112 static struct tm *
2113 #else /* !__LP64__ */
2114 static void
2115 #endif /* __LP64__ */
2116 timesub(timep, offset, sp, tmp)
2117 const time_t * const timep;
2118 const long offset;
2119 const struct state * const sp;
2120 struct tm * const tmp;
2121 {
2122 const struct lsinfo * lp;
2123 long days;
2124 long rem;
2125 long y;
2126 int yleap;
2127 const int * ip;
2128 long corr;
2129 int hit;
2130 int i;
2131
2132 corr = 0;
2133 hit = 0;
2134 #ifdef ALL_STATE
2135 i = (sp == NULL) ? 0 : sp->leapcnt;
2136 #endif /* defined ALL_STATE */
2137 #ifndef ALL_STATE
2138 i = sp->leapcnt;
2139 #endif /* State Farm */
2140 while (--i >= 0) {
2141 lp = &sp->lsis[i];
2142 if (*timep >= lp->ls_trans) {
2143 if (*timep == lp->ls_trans) {
2144 hit = ((i == 0 && lp->ls_corr > 0) ||
2145 lp->ls_corr > sp->lsis[i - 1].ls_corr);
2146 if (hit)
2147 while (i > 0 &&
2148 sp->lsis[i].ls_trans ==
2149 sp->lsis[i - 1].ls_trans + 1 &&
2150 sp->lsis[i].ls_corr ==
2151 sp->lsis[i - 1].ls_corr + 1) {
2152 ++hit;
2153 --i;
2154 }
2155 }
2156 corr = lp->ls_corr;
2157 break;
2158 }
2159 }
2160 days = *timep / SECSPERDAY;
2161 rem = *timep % SECSPERDAY;
2162 #ifdef mc68k
2163 if (*timep == 0x80000000) {
2164 /*
2165 ** A 3B1 muffs the division on the most negative number.
2166 */
2167 days = -24855;
2168 rem = -11648;
2169 }
2170 #endif /* defined mc68k */
2171 rem += (offset - corr);
2172 while (rem < 0) {
2173 rem += SECSPERDAY;
2174 --days;
2175 }
2176 while (rem >= SECSPERDAY) {
2177 rem -= SECSPERDAY;
2178 ++days;
2179 }
2180 tmp->tm_hour = (int) (rem / SECSPERHOUR);
2181 rem = rem % SECSPERHOUR;
2182 tmp->tm_min = (int) (rem / SECSPERMIN);
2183 /*
2184 ** A positive leap second requires a special
2185 ** representation. This uses "... ??:59:60" et seq.
2186 */
2187 tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
2188 tmp->tm_wday = (int) ((EPOCH_WDAY + days) % DAYSPERWEEK);
2189 if (tmp->tm_wday < 0)
2190 tmp->tm_wday += DAYSPERWEEK;
2191 y = EPOCH_YEAR;
2192 #define _LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
2193 #ifdef __LP64__
2194 #define LEAPS_THRU_END_OF(y) ((y) >= 0 ? _LEAPS_THRU_END_OF(y) : _LEAPS_THRU_END_OF((y) + 1) - 1)
2195 #else /* !__LP64__ */
2196 #define LEAPS_THRU_END_OF(y) _LEAPS_THRU_END_OF(y)
2197 #endif /* __LP64__ */
2198 while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
2199 long newy;
2200
2201 newy = y + days / DAYSPERNYEAR;
2202 if (days < 0)
2203 --newy;
2204 days -= (newy - y) * DAYSPERNYEAR +
2205 LEAPS_THRU_END_OF(newy - 1) -
2206 LEAPS_THRU_END_OF(y - 1);
2207 y = newy;
2208 }
2209 #ifdef __LP64__
2210 y -= TM_YEAR_BASE;
2211 if (y < INT_MIN || y > INT_MAX) {
2212 errno = EOVERFLOW;
2213 return NULL;
2214 }
2215 tmp->tm_year = y;
2216 #else /* !__LP64__ */
2217 tmp->tm_year = y - TM_YEAR_BASE;
2218 #endif /* __LP64__ */
2219 tmp->tm_yday = (int) days;
2220 ip = mon_lengths[yleap];
2221 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
2222 days = days - (long) ip[tmp->tm_mon];
2223 tmp->tm_mday = (int) (days + 1);
2224 tmp->tm_isdst = 0;
2225 #ifdef TM_GMTOFF
2226 tmp->TM_GMTOFF = offset;
2227 #endif /* defined TM_GMTOFF */
2228 #ifdef __LP64__
2229 return tmp;
2230 #endif /* __LP64__ */
2231 }
2232
2233 char *
2234 ctime(const time_t *const timep)
2235 {
2236 /*
2237 ** Section 4.12.3.2 of X3.159-1989 requires that
2238 ** The ctime function converts the calendar time pointed to by timer
2239 ** to local time in the form of a string. It is equivalent to
2240 ** asctime(localtime(timer))
2241 */
2242 #ifdef __LP64__
2243 /*
2244 * In 64-bit, the timep value may produce a time value with a year
2245 * that exceeds 32-bits in size (won't fit in struct tm), so localtime
2246 * will return NULL.
2247 */
2248 struct tm *tm = localtime(timep);
2249
2250 if (tm == NULL)
2251 return NULL;
2252 return asctime(tm);
2253 #else /* !__LP64__ */
2254 return asctime(localtime(timep));
2255 #endif /* __LP64__ */
2256 }
2257
2258 char *
2259 ctime_r(const time_t *const timep, char *buf)
2260 {
2261 struct tm mytm;
2262
2263 #ifdef __LP64__
2264 /*
2265 * In 64-bit, the timep value may produce a time value with a year
2266 * that exceeds 32-bits in size (won't fit in struct tm), so localtime_r
2267 * will return NULL.
2268 */
2269 if (localtime_r(timep, &mytm) == NULL)
2270 return NULL;
2271 return asctime_r(&mytm, buf);
2272 #else /* !__LP64__ */
2273 return asctime_r(localtime_r(timep, &mytm), buf);
2274 #endif /* __LP64__ */
2275 }
2276
2277 /*
2278 ** Adapted from code provided by Robert Elz, who writes:
2279 ** The "best" way to do mktime I think is based on an idea of Bob
2280 ** Kridle's (so its said...) from a long time ago.
2281 ** It does a binary search of the time_t space. Since time_t's are
2282 ** just 32 bits, its a max of 32 iterations (even at 64 bits it
2283 ** would still be very reasonable).
2284 */
2285
2286 #ifndef WRONG
2287 #define WRONG (-1)
2288 #endif /* !defined WRONG */
2289
2290 /*
2291 ** Simplified normalize logic courtesy Paul Eggert.
2292 */
2293
2294 static int
2295 increment_overflow(number, delta)
2296 int * number;
2297 int delta;
2298 {
2299 int number0;
2300
2301 number0 = *number;
2302 *number += delta;
2303 return (*number < number0) != (delta < 0);
2304 }
2305
2306 static int
2307 long_increment_overflow(number, delta)
2308 long * number;
2309 int delta;
2310 {
2311 long number0;
2312
2313 number0 = *number;
2314 *number += delta;
2315 return (*number < number0) != (delta < 0);
2316 }
2317
2318 static int
2319 normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
2320 {
2321 int tensdelta;
2322
2323 tensdelta = (*unitsptr >= 0) ?
2324 (*unitsptr / base) :
2325 (-1 - (-1 - *unitsptr) / base);
2326 *unitsptr -= tensdelta * base;
2327 return increment_overflow(tensptr, tensdelta);
2328 }
2329
2330 static int
2331 long_normalize_overflow(long *const tensptr, int *const unitsptr, const int base)
2332 {
2333 register int tensdelta;
2334
2335 tensdelta = (*unitsptr >= 0) ?
2336 (*unitsptr / base) :
2337 (-1 - (-1 - *unitsptr) / base);
2338 *unitsptr -= tensdelta * base;
2339 return long_increment_overflow(tensptr, tensdelta);
2340 }
2341
2342 static int
2343 tmcomp(atmp, btmp)
2344 const struct tm * const atmp;
2345 const struct tm * const btmp;
2346 {
2347 int result;
2348
2349 /*
2350 * Assume that atmp and btmp point to normalized tm strutures.
2351 * So only arithmetic with tm_year could overflow in 64-bit.
2352 */
2353 if (atmp->tm_year != btmp->tm_year) {
2354 return (atmp->tm_year > btmp->tm_year ? 1 : -1);
2355 }
2356 if ((result = (atmp->tm_mon - btmp->tm_mon)) == 0 &&
2357 (result = (atmp->tm_mday - btmp->tm_mday)) == 0 &&
2358 (result = (atmp->tm_hour - btmp->tm_hour)) == 0 &&
2359 (result = (atmp->tm_min - btmp->tm_min)) == 0)
2360 result = atmp->tm_sec - btmp->tm_sec;
2361 return result;
2362 }
2363
2364 static time_t
2365 time2sub(struct tm *const tmp,
2366 #ifdef __LP64__
2367 struct tm *(*const funcp)(const time_t *, long, struct tm *),
2368 #else /* !__LP64__ */
2369 void(*funcp) (const time_t *, long, struct tm*),
2370 #endif /* __LP64__ */
2371 const long offset,
2372 int *const okayp,
2373 const int do_norm_secs,
2374 int unix03)
2375 {
2376 const struct state * sp;
2377 int dir;
2378 int i, j;
2379 int saved_seconds;
2380 long li;
2381 time_t lo;
2382 time_t hi;
2383 long y;
2384 time_t newt;
2385 time_t t;
2386 struct tm yourtm, mytm;
2387
2388 *okayp = FALSE;
2389 yourtm = *tmp;
2390 if (do_norm_secs) {
2391 if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec,
2392 SECSPERMIN))
2393 return WRONG;
2394 }
2395 if (normalize_overflow(&yourtm.tm_hour, &yourtm.tm_min, MINSPERHOUR))
2396 return WRONG;
2397 if (normalize_overflow(&yourtm.tm_mday, &yourtm.tm_hour, HOURSPERDAY))
2398 return WRONG;
2399 y = yourtm.tm_year;
2400 if (long_normalize_overflow(&y, &yourtm.tm_mon, MONSPERYEAR))
2401 return WRONG;
2402 /*
2403 ** Turn y into an actual year number for now.
2404 ** It is converted back to an offset from TM_YEAR_BASE later.
2405 */
2406 if (long_increment_overflow(&y, TM_YEAR_BASE))
2407 return WRONG;
2408 while (yourtm.tm_mday <= 0) {
2409 if (long_increment_overflow(&y, -1))
2410 return WRONG;
2411 li = y + (1 < yourtm.tm_mon);
2412 yourtm.tm_mday += year_lengths[isleap(li)];
2413 }
2414 while (yourtm.tm_mday > DAYSPERLYEAR) {
2415 li = y + (1 < yourtm.tm_mon);
2416 yourtm.tm_mday -= year_lengths[isleap(li)];
2417 if (long_increment_overflow(&y, 1))
2418 return WRONG;
2419 }
2420 for ( ; ; ) {
2421 i = mon_lengths[isleap(y)][yourtm.tm_mon];
2422 if (yourtm.tm_mday <= i)
2423 break;
2424 yourtm.tm_mday -= i;
2425 if (++yourtm.tm_mon >= MONSPERYEAR) {
2426 yourtm.tm_mon = 0;
2427 if (long_increment_overflow(&y, 1))
2428 return WRONG;
2429 }
2430 }
2431 if (long_increment_overflow(&y, -TM_YEAR_BASE))
2432 return WRONG;
2433 yourtm.tm_year = y;
2434 if (yourtm.tm_year != y)
2435 return WRONG;
2436 /* Don't go below 1900 for POLA */
2437 if (yourtm.tm_year < 0)
2438 return WRONG;
2439 if (yourtm.tm_sec >= 0 && yourtm.tm_sec < SECSPERMIN)
2440 saved_seconds = 0;
2441 else if (y + TM_YEAR_BASE < EPOCH_YEAR) {
2442 /*
2443 ** We can't set tm_sec to 0, because that might push the
2444 ** time below the minimum representable time.
2445 ** Set tm_sec to 59 instead.
2446 ** This assumes that the minimum representable time is
2447 ** not in the same minute that a leap second was deleted from,
2448 ** which is a safer assumption than using 58 would be.
2449 */
2450 if (increment_overflow(&yourtm.tm_sec, 1 - SECSPERMIN))
2451 return WRONG;
2452 saved_seconds = yourtm.tm_sec;
2453 yourtm.tm_sec = SECSPERMIN - 1;
2454 } else {
2455 saved_seconds = yourtm.tm_sec;
2456 yourtm.tm_sec = 0;
2457 }
2458 /*
2459 ** Do a binary search (this works whatever time_t's type is).
2460 */
2461 if (!TYPE_SIGNED(time_t)) {
2462 lo = 0;
2463 hi = lo - 1;
2464 } else if (!TYPE_INTEGRAL(time_t)) {
2465 if (sizeof(time_t) > sizeof(float))
2466 hi = (time_t) DBL_MAX;
2467 else hi = (time_t) FLT_MAX;
2468 lo = -hi;
2469 } else {
2470 lo = 1;
2471 for (i = 0; i < (int) TYPE_BIT(time_t) - 1; ++i)
2472 lo *= 2;
2473 hi = -(lo + 1);
2474 }
2475 for ( ; ; ) {
2476 t = lo / 2 + hi / 2;
2477 if (t < lo)
2478 t = lo;
2479 else if (t > hi)
2480 t = hi;
2481 #ifdef __LP64__
2482 if ((*funcp)(&t, offset, &mytm) == NULL) {
2483 /*
2484 ** Assume that t is too extreme to be represented in
2485 ** a struct tm; arrange things so that it is less
2486 ** extreme on the next pass.
2487 */
2488 dir = (t > 0) ? 1 : -1;
2489 } else dir = tmcomp(&mytm, &yourtm);
2490 #else /* !__LP64__ */
2491 (*funcp)(&t, offset, &mytm);
2492 dir = tmcomp(&mytm, &yourtm);
2493 // If we have searched the entire space without a match, exit
2494 if (dir != 0 && t == lo && t == hi)
2495 return WRONG;
2496 #endif /* __LP64__ */
2497 if (dir != 0) {
2498 if (t == lo) {
2499 ++t;
2500 if (t <= lo)
2501 return WRONG;
2502 ++lo;
2503 } else if (t == hi) {
2504 --t;
2505 if (t >= hi)
2506 return WRONG;
2507 --hi;
2508 }
2509 if (lo > hi)
2510 return WRONG;
2511 if (dir > 0)
2512 hi = t;
2513 else lo = t;
2514 continue;
2515 }
2516 sp = (funcp == localsub) ? lclptr : gmtptr;
2517 if (unix03 && sp->typecnt == 1 && yourtm.tm_isdst > 0)
2518 yourtm.tm_isdst = 0; /* alternative time does not apply */
2519 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
2520 break;
2521 /*
2522 ** Right time, wrong type.
2523 ** Hunt for right time, right type.
2524 ** It's okay to guess wrong since the guess
2525 ** gets checked.
2526 */
2527 #ifdef ALL_STATE
2528 if (sp == NULL)
2529 return WRONG;
2530 #endif /* defined ALL_STATE */
2531 for (i = sp->typecnt - 1; i >= 0; --i) {
2532 if (sp->ttis[i].tt_isdst != yourtm.tm_isdst)
2533 continue;
2534 for (j = sp->typecnt - 1; j >= 0; --j) {
2535 if (sp->ttis[j].tt_isdst == yourtm.tm_isdst)
2536 continue;
2537 newt = t + sp->ttis[j].tt_gmtoff -
2538 sp->ttis[i].tt_gmtoff;
2539 #ifdef __LP64__
2540 if ((*funcp)(&newt, offset, &mytm) == NULL)
2541 continue;
2542 #else /* !__LP64__ */
2543 (*funcp)(&newt, offset, &mytm);
2544 #endif /* __LP64__ */
2545 if (tmcomp(&mytm, &yourtm) != 0)
2546 continue;
2547 if (mytm.tm_isdst != yourtm.tm_isdst)
2548 continue;
2549 /*
2550 ** We have a match.
2551 */
2552 t = newt;
2553 goto label;
2554 }
2555 }
2556 return WRONG;
2557 }
2558 label:
2559 newt = t + saved_seconds;
2560 if ((newt < t) != (saved_seconds < 0))
2561 return WRONG;
2562 t = newt;
2563 #ifdef __LP64__
2564 if ((*funcp)(&t, offset, tmp) == NULL)
2565 return WRONG;
2566 #else /* !__LP64__ */
2567 (*funcp)(&t, offset, tmp);
2568 #endif /* __LP64__ */
2569 *okayp = TRUE;
2570 return t;
2571 }
2572
2573 static time_t
2574 time2(struct tm * const tmp,
2575 #ifdef __LP64__
2576 struct tm * (*const funcp)(const time_t *, long, struct tm *),
2577 #else /* !__LP64__ */
2578 void (*const funcp)(const time_t *, long, struct tm *),
2579 #endif /* __LP64__ */
2580 const long offset,
2581 int *const okayp,
2582 int unix03)
2583 {
2584 time_t t;
2585
2586 /*
2587 ** First try without normalization of seconds
2588 ** (in case tm_sec contains a value associated with a leap second).
2589 ** If that fails, try with normalization of seconds.
2590 */
2591 t = time2sub(tmp, funcp, offset, okayp, FALSE, unix03);
2592 return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, unix03);
2593 }
2594
2595 __private_extern__ time_t
2596 time1(tmp, funcp, offset, unix03)
2597 struct tm * const tmp;
2598 #ifdef __LP64__
2599 struct tm * (* const funcp)(const time_t *, long, struct tm *);
2600 #else /* !__LP64__ */
2601 void (* const funcp)(const time_t *, long, struct tm *);
2602 #endif /* __LP64__ */
2603 const long offset;
2604 int unix03;
2605 {
2606 time_t t;
2607 const struct state * sp;
2608 int samei, otheri;
2609 int sameind, otherind;
2610 int i;
2611 int nseen;
2612 int seen[TZ_MAX_TYPES];
2613 int types[TZ_MAX_TYPES];
2614 int okay;
2615
2616 if (tmp == NULL) {
2617 errno = EINVAL;
2618 return WRONG;
2619 }
2620
2621 if (tmp->tm_isdst > 1)
2622 tmp->tm_isdst = 1;
2623 t = time2(tmp, funcp, offset, &okay, unix03);
2624 #ifdef PCTS
2625 /*
2626 ** PCTS code courtesy Grant Sullivan.
2627 */
2628 if (okay)
2629 return t;
2630 if (tmp->tm_isdst < 0)
2631 tmp->tm_isdst = 0; /* reset to std and try again */
2632 #endif /* defined PCTS */
2633 #ifndef PCTS
2634 if (okay || tmp->tm_isdst < 0)
2635 return t;
2636 #endif /* !defined PCTS */
2637 /*
2638 ** We're supposed to assume that somebody took a time of one type
2639 ** and did some math on it that yielded a "struct tm" that's bad.
2640 ** We try to divine the type they started from and adjust to the
2641 ** type they need.
2642 */
2643 sp = (const struct state *) ((funcp == localsub) ? lclptr : gmtptr);
2644 #ifdef ALL_STATE
2645 if (sp == NULL)
2646 return WRONG;
2647 #endif /* defined ALL_STATE */
2648 for (i = 0; i < sp->typecnt; ++i)
2649 seen[i] = FALSE;
2650 nseen = 0;
2651 for (i = sp->timecnt - 1; i >= 0; --i)
2652 if (!seen[sp->types[i]]) {
2653 seen[sp->types[i]] = TRUE;
2654 types[nseen++] = sp->types[i];
2655 }
2656 for (sameind = 0; sameind < nseen; ++sameind) {
2657 samei = types[sameind];
2658 if (sp->ttis[samei].tt_isdst != tmp->tm_isdst)
2659 continue;
2660 for (otherind = 0; otherind < nseen; ++otherind) {
2661 otheri = types[otherind];
2662 if (sp->ttis[otheri].tt_isdst == tmp->tm_isdst)
2663 continue;
2664 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
2665 sp->ttis[samei].tt_gmtoff;
2666 tmp->tm_isdst = !tmp->tm_isdst;
2667 t = time2(tmp, funcp, offset, &okay, unix03);
2668 if (okay)
2669 return t;
2670 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
2671 sp->ttis[samei].tt_gmtoff;
2672 tmp->tm_isdst = !tmp->tm_isdst;
2673 }
2674 }
2675 return WRONG;
2676 }
2677 #else /* BUILDING_VARIANT */
2678 extern pthread_rwlock_t lcl_rwlock;
2679 #endif /* BUILDING_VARIANT */
2680
2681 time_t
2682 mktime(struct tm *const tmp)
2683 {
2684 time_t mktime_return_value;
2685 int serrno = errno;
2686 _RWLOCK_RDLOCK(&lcl_rwlock);
2687 tzset_basic(1);
2688 mktime_return_value = time1(tmp, localsub, 0L, __DARWIN_UNIX03);
2689 _RWLOCK_UNLOCK(&lcl_rwlock);
2690 errno = serrno;
2691 return(mktime_return_value);
2692 }
2693
2694 #if !BUILDING_VARIANT
2695 #ifdef STD_INSPIRED
2696
2697 time_t
2698 timelocal(struct tm *const tmp)
2699 {
2700 if (tmp != NULL)
2701 tmp->tm_isdst = -1; /* in case it wasn't initialized */
2702 return mktime(tmp);
2703 }
2704
2705 time_t
2706 timegm(struct tm *const tmp)
2707 {
2708 if (tmp != NULL)
2709 tmp->tm_isdst = 0;
2710 return time1(tmp, gmtsub, 0L, __DARWIN_UNIX03);
2711 }
2712
2713 time_t
2714 timeoff(struct tm *const tmp, const long offset)
2715 {
2716 if (tmp != NULL)
2717 tmp->tm_isdst = 0;
2718 return time1(tmp, gmtsub, offset, __DARWIN_UNIX03);
2719 }
2720
2721 #endif /* defined STD_INSPIRED */
2722
2723 #ifdef CMUCS
2724
2725 /*
2726 ** The following is supplied for compatibility with
2727 ** previous versions of the CMUCS runtime library.
2728 */
2729
2730 long
2731 gtime(struct tm *const tmp)
2732 {
2733 const time_t t = mktime(tmp);
2734
2735 if (t == WRONG)
2736 return -1;
2737 return t;
2738 }
2739
2740 #endif /* defined CMUCS */
2741
2742 /*
2743 ** XXX--is the below the right way to conditionalize??
2744 */
2745
2746 #ifdef STD_INSPIRED
2747
2748 /*
2749 ** IEEE Std 1003.1-1988 (POSIX) legislates that 536457599
2750 ** shall correspond to "Wed Dec 31 23:59:59 UTC 1986", which
2751 ** is not the case if we are accounting for leap seconds.
2752 ** So, we provide the following conversion routines for use
2753 ** when exchanging timestamps with POSIX conforming systems.
2754 */
2755
2756 static long
2757 leapcorr(time_t *timep)
2758 {
2759 struct state * sp;
2760 struct lsinfo * lp;
2761 int i;
2762
2763 sp = lclptr;
2764 i = sp->leapcnt;
2765 while (--i >= 0) {
2766 lp = &sp->lsis[i];
2767 if (*timep >= lp->ls_trans)
2768 return lp->ls_corr;
2769 }
2770 return 0;
2771 }
2772
2773 time_t
2774 time2posix(time_t t)
2775 {
2776 tzset();
2777 return t - leapcorr(&t);
2778 }
2779
2780 time_t
2781 posix2time(time_t t)
2782 {
2783 time_t x;
2784 time_t y;
2785
2786 tzset();
2787 /*
2788 ** For a positive leap second hit, the result
2789 ** is not unique. For a negative leap second
2790 ** hit, the corresponding time doesn't exist,
2791 ** so we return an adjacent second.
2792 */
2793 x = t + leapcorr(&t);
2794 y = x - leapcorr(&x);
2795 if (y < t) {
2796 do {
2797 x++;
2798 y = x - leapcorr(&x);
2799 } while (y < t);
2800 if (t != y)
2801 return x - 1;
2802 } else if (y > t) {
2803 do {
2804 --x;
2805 y = x - leapcorr(&x);
2806 } while (y > t);
2807 if (t != y)
2808 return x + 1;
2809 }
2810 return x;
2811 }
2812
2813 #endif /* defined STD_INSPIRED */
2814 #endif /* !BUILDING_VARIANT */
2815 #pragma clang diagnostic pop