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