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