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).
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 $");
15 ** Leap second handling from Bradley White (bww@k.gp.cs.cmu.edu).
16 ** POSIX-style TZ environment variable handling from Guy Harris
22 #include "namespace.h"
23 #include <sys/types.h>
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 */
36 #endif /* ALL_STATE */
37 #include <mach/mach_init.h>
40 #endif /* NOTIFY_TZ */
42 #include "un-namespace.h"
46 #include "libc_private.h"
48 #define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
49 #define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
51 #define _RWLOCK_RDLOCK(x) \
53 if (__isthreaded) _pthread_rwlock_rdlock(x); \
56 #define _RWLOCK_WRLOCK(x) \
58 if (__isthreaded) _pthread_rwlock_wrlock(x); \
61 #define _RWLOCK_UNLOCK(x) \
63 if (__isthreaded) _pthread_rwlock_unlock(x); \
67 ** SunOS 4.1.1 headers lack O_BINARY.
71 #define OPEN_MODE (O_RDONLY | O_BINARY)
72 #endif /* defined O_BINARY */
74 #define OPEN_MODE O_RDONLY
75 #endif /* !defined O_BINARY */
79 ** Someone might make incorrect use of a time zone abbreviation:
80 ** 1. They might reference tzname[0] before calling tzset (explicitly
82 ** 2. They might reference tzname[1] before calling tzset (explicitly
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).
98 #endif /* !defined WILDABBR */
100 static const char wildabbr
[] = "WILDABBR";
103 * In June 2004 it was decided UTC was a more appropriate default time
107 static const char gmt
[] = "UTC";
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
116 #ifndef TZDEFRULESTRING
117 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
118 #endif /* !defined TZDEFDST */
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 */
128 struct lsinfo
{ /* leap second information */
129 time_t ls_trans
; /* transition time */
130 long ls_corr
; /* correction to apply */
133 #define BIGGEST(a, b) (((a) > (b)) ? (a) : (b))
136 #define MY_TZNAME_MAX TZNAME_MAX
137 #endif /* defined TZNAME_MAX */
139 #define MY_TZNAME_MAX 255
140 #endif /* !defined TZNAME_MAX */
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
];
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 */
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 */
173 #define NOTIFY_TZ_NAME "com.apple.system.timezone"
174 #endif /* NOTIFY_TZ */
177 ** Prototypes for static functions.
179 #define localsub _st_localsub
180 #define time1 _st_time1
181 #define tzset_basic _st_tzset_basic
184 struct tm
* localsub(const time_t * timep
, long offset
,
186 #else /* !__LP64__ */
187 void localsub(const time_t * timep
, long offset
,
189 #endif /* __LP64__ */
191 time_t time1(struct tm
* tmp
,
193 struct tm
*(*funcp
) (const time_t *,
195 #else /* !__LP64__ */
196 void(*funcp
) (const time_t *,
198 #endif /* __LP64__ */
202 void tzset_basic(int);
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
,
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
);
213 static void gmtload(struct state
* sp
, char *path
);
214 #else /* ! NOTIFY_TZ */
215 static void gmtload(struct state
* sp
);
216 #endif /* NOTIFY_TZ */
218 static struct tm
* gmtsub(const time_t * timep
, long offset
,
220 #else /* !__LP64__ */
221 static void gmtsub(const time_t * timep
, long offset
,
223 #endif /* __LP64__ */
224 static int increment_overflow(int * number
, int delta
);
225 static int normalize_overflow(int * tensptr
, int * unitsptr
,
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
,
234 struct tm
*(*funcp
) (const time_t *,
236 #else /* !__LP64__ */
237 void(*funcp
) (const time_t *,
239 #endif /* __LP64__ */
240 long offset
, int * okayp
, int unix03
);
241 static time_t time2sub(struct tm
*tmp
,
243 struct tm
*(*funcp
) (const time_t *,
245 #else /* !__LP64__ */
246 void(*funcp
) (const time_t *,
248 #endif /* __LP64__ */
249 long offset
, int * okayp
, int do_norm_secs
,
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
);
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
,
271 static struct state
* lclptr
;
272 static struct state
* gmtptr
;
273 #endif /* defined ALL_STATE */
276 static struct state lclmem
;
277 static struct state gmtmem
;
278 #define lclptr (&lclmem)
279 #define gmtptr (&gmtmem)
280 #endif /* State Farm */
282 #ifndef TZ_STRLEN_MAX
283 #define TZ_STRLEN_MAX 255
284 #endif /* !defined TZ_STRLEN_MAX */
286 static char lcl_TZname
[TZ_STRLEN_MAX
+ 1];
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
;
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.
316 __private_extern__
void _st_set_timezone(long);
317 #endif /* defined USG_COMPAT */
320 __private_extern__
long __darwin_altzone
= 0;
321 #define altzone __darwin_altzone
322 #endif /* defined ALTZONE */
325 #ifdef NOTIFY_TZ_DEBUG
326 #ifdef NOTIFY_TZ_DEBUG_FILE
327 #define NOTIFY_TZ_PRINTF(fmt, args...) \
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_); \
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 */
340 #define NOTIFY_LOG(fmt, args...) \
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_); \
348 #endif /* NOTIFY_TZ_LOG */
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 */
357 const char * const codep
;
362 result
= (codep
[0] & 0x80) ? ~0L : 0L;
363 for (i
= 0; i
< 4; ++i
)
364 result
= (result
<< 8) | (codep
[i
] & 0xff);
371 struct state
* sp
= lclptr
;
373 unsigned char * types
;
376 #define NEED_DAYLIGHT 4
377 #define NEED_ALL (NEED_STD | NEED_DST | NEED_DAYLIGHT)
379 tzname
[0] = (char *)wildabbr
;
380 tzname
[1] = (char *)wildabbr
;
384 #endif /* defined USG_COMPAT */
387 #endif /* defined ALTZONE */
390 tzname
[0] = tzname
[1] = (char *)gmt
;
393 #endif /* defined ALL_STATE */
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.
401 if (sp
->timecnt
== 0 && sp
->typecnt
== 1) {
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
409 types
= (unsigned char *)""; /* we use the null as index */
416 for (; i
>= 0 && need
; --i
) {
417 const struct ttinfo
* const ttisp
= &sp
->ttis
[types
[i
]];
420 if ((need
& NEED_DAYLIGHT
) && ttisp
->tt_isdst
) {
421 need
&= ~NEED_DAYLIGHT
;
424 #endif /* defined USG_COMPAT */
425 if (ttisp
->tt_isdst
) {
426 if (need
& NEED_DST
) {
428 tzname
[1] = &sp
->chars
[ttisp
->tt_abbrind
];
430 altzone
= -(ttisp
->tt_gmtoff
);
431 #endif /* defined ALTZONE */
433 } else if (need
& NEED_STD
) {
435 tzname
[0] = &sp
->chars
[ttisp
->tt_abbrind
];
437 _st_set_timezone(-(ttisp
->tt_gmtoff
));
438 #endif /* defined USG_COMPAT */
440 #if defined(ALTZONE) || defined(USG_COMPAT)
442 #endif /* defined(ALTZONE) || defined(USG_COMPAT) */
445 altzone
= -(ttisp
->tt_gmtoff
);
446 #endif /* defined ALTZONE */
449 _st_set_timezone(-(ttisp
->tt_gmtoff
));
450 #endif /* defined USG_COMPAT */
451 #if defined(ALTZONE) || defined(USG_COMPAT)
453 #endif /* defined(ALTZONE) || defined(USG_COMPAT) */
459 notify_check_tz(notify_tz_t
*p
)
466 nstat
= notify_check(p
->token
, &ncheck
);
467 if (nstat
|| ncheck
) {
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 */
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 */
478 extern uint32_t notify_monitor_file(int token
, char *path
, int flags
);
481 notify_register_tz(char *file
, notify_tz_t
*p
)
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 *----------------------------------------------------------------*/
492 notify_cancel(p
->token
);
493 if (!file
|| *file
== 0) {
494 /* no time zone file to monitor */
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
;
505 name
= alloca(sizeof(notify_tz_name
) + strlen(file
) + 1);
510 strcpy(name
, notify_tz_name
);
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
);
521 #ifdef NOTIFY_TZ_DEBUG
522 NOTIFY_TZ_PRINTF("***notify_register_tz: notify_register_check failed: %u\n", nstat
);
523 #endif /* NOTIFY_TZ_DEBUG */
525 NOTIFY_LOG("notify_register_check(%s) failed: %u\n", name
, nstat
);
526 #endif /* NOTIFY_TZ_LOG */
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);
536 notify_cancel(p
->token
);
539 #ifdef NOTIFY_TZ_DEBUG
540 NOTIFY_TZ_PRINTF("***notify_register_tz: notify_monitor_file failed: %u\n", nstat
);
541 #endif /* NOTIFY_TZ_DEBUG */
543 NOTIFY_LOG("notify_monitor_file(%s) failed: %u\n", file
, nstat
);
544 #endif /* NOTIFY_TZ_LOG */
548 notify_check(p
->token
, &ncheck
); /* this always returns true */
550 #endif /* NOTIFY_TZ */
554 tzload(name
, sp
, path
)
555 #else /* ! NOTIFY_TZ */
557 #endif /* NOTIFY_TZ */
559 struct state
* const sp
;
561 char * path
; /* copy full path if non-NULL */
562 #endif /* NOTIFY_TZ */
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
, '.'))
578 *path
= 0; /* default to empty string on error */
579 #endif /* NOTIFY_TZ */
580 if (name
== NULL
&& (name
= TZDEFAULT
) == NULL
)
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."
592 char fullname
[FILENAME_MAX
+ 1];
596 doaccess
= name
[0] == '/';
598 if ((p
= TZDIR
) == NULL
)
600 if ((strlen(p
) + 1 + strlen(name
) + 1) >= sizeof fullname
)
602 (void) strcpy(fullname
, p
);
603 (void) strcat(fullname
, "/");
604 (void) strcat(fullname
, name
);
606 ** Set doaccess if '.' (as in "../") shows up in name.
608 if (strchr(name
, '.') != NULL
)
614 if (strlen(name
) > FILENAME_MAX
)
618 #endif /* NOTIFY_TZ */
619 if (doaccess
&& access(name
, R_OK
) != 0)
621 if ((fid
= _open(name
, OPEN_MODE
)) == -1)
623 if ((_fstat(fid
, &stab
) < 0) || !S_ISREG(stab
.st_mode
)) {
629 struct tzhead
* tzhp
;
631 struct tzhead tzhead
;
632 char buf
[sizeof *sp
+ sizeof *tzhp
];
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)
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))
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 */
665 for (i
= 0; i
< sp
->timecnt
; ++i
) {
666 sp
->ats
[i
] = detzcode(p
);
669 for (i
= 0; i
< sp
->timecnt
; ++i
) {
670 sp
->types
[i
] = (unsigned char) *p
++;
671 if (sp
->types
[i
] >= sp
->typecnt
)
674 for (i
= 0; i
< sp
->typecnt
; ++i
) {
675 struct ttinfo
* ttisp
;
677 ttisp
= &sp
->ttis
[i
];
678 ttisp
->tt_gmtoff
= detzcode(p
);
680 ttisp
->tt_isdst
= (unsigned char) *p
++;
681 if (ttisp
->tt_isdst
!= 0 && ttisp
->tt_isdst
!= 1)
683 ttisp
->tt_abbrind
= (unsigned char) *p
++;
684 if (ttisp
->tt_abbrind
< 0 ||
685 ttisp
->tt_abbrind
> sp
->charcnt
)
688 for (i
= 0; i
< sp
->charcnt
; ++i
)
690 sp
->chars
[i
] = '\0'; /* ensure '\0' at end */
691 for (i
= 0; i
< sp
->leapcnt
; ++i
) {
692 struct lsinfo
* lsisp
;
694 lsisp
= &sp
->lsis
[i
];
695 lsisp
->ls_trans
= detzcode(p
);
697 lsisp
->ls_corr
= detzcode(p
);
700 for (i
= 0; i
< sp
->typecnt
; ++i
) {
701 struct ttinfo
* ttisp
;
703 ttisp
= &sp
->ttis
[i
];
705 ttisp
->tt_ttisstd
= FALSE
;
707 ttisp
->tt_ttisstd
= *p
++;
708 if (ttisp
->tt_ttisstd
!= TRUE
&&
709 ttisp
->tt_ttisstd
!= FALSE
)
713 for (i
= 0; i
< sp
->typecnt
; ++i
) {
714 struct ttinfo
* ttisp
;
716 ttisp
= &sp
->ttis
[i
];
718 ttisp
->tt_ttisgmt
= FALSE
;
720 ttisp
->tt_ttisgmt
= *p
++;
721 if (ttisp
->tt_ttisgmt
!= TRUE
&&
722 ttisp
->tt_ttisgmt
!= FALSE
)
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 }
735 static const int year_lengths
[2] = {
736 DAYSPERNYEAR
, DAYSPERLYEAR
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
746 getzname(strp
, name
, len
)
754 if (*strp
== '<' && (ket
= strchr(strp
, '>')) != NULL
) {
755 *name
= (char *)(strp
+ 1);
756 *len
= ket
- strp
- 1;
759 *name
= (char *)strp
;
760 while ((c
= *strp
) != '\0' && !is_digit(c
) && c
!= ',' && c
!= '-' &&
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
771 ** Otherwise, return a pointer to the first character not part of the number.
775 getnum(strp
, nump
, min
, max
)
784 if (strp
== NULL
|| !is_digit(c
= *strp
))
788 num
= num
* 10 + (c
- '0');
790 return NULL
; /* illegal value */
792 } while (is_digit(c
));
794 return NULL
; /* illegal value */
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
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''.
820 strp
= getnum(strp
, &num
, 0, HOURSPERDAY
* DAYSPERWEEK
- 1);
823 *secsp
= num
* (long) SECSPERHOUR
;
826 strp
= getnum(strp
, &num
, 0, MINSPERHOUR
- 1);
829 *secsp
+= num
* SECSPERMIN
;
832 /* `SECSPERMIN' allows for leap seconds. */
833 strp
= getnum(strp
, &num
, 0, SECSPERMIN
);
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.
850 getoffset(strp
, offsetp
)
852 long * const offsetp
;
859 } else if (*strp
== '+')
861 strp
= getsecs(strp
, offsetp
);
863 return NULL
; /* illegal time */
865 *offsetp
= -*offsetp
;
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.
879 struct rule
* const rulep
;
885 rulep
->r_type
= JULIAN_DAY
;
887 strp
= getnum(strp
, &rulep
->r_day
, 1, DAYSPERNYEAR
);
888 } else if (*strp
== 'M') {
892 rulep
->r_type
= MONTH_NTH_DAY_OF_WEEK
;
894 strp
= getnum(strp
, &rulep
->r_mon
, 1, MONSPERYEAR
);
899 strp
= getnum(strp
, &rulep
->r_week
, 1, 5);
904 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERWEEK
- 1);
905 } else if (is_digit(*strp
)) {
909 rulep
->r_type
= DAY_OF_YEAR
;
910 strp
= getnum(strp
, &rulep
->r_day
, 0, DAYSPERLYEAR
- 1);
911 } else return NULL
; /* invalid format */
919 strp
= getsecs(strp
, &rulep
->r_time
);
920 } else rulep
->r_time
= 2 * SECSPERHOUR
; /* default = 2:00:00 */
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.
931 transtime(janfirst
, year
, rulep
, offset
)
932 const time_t janfirst
;
934 const struct rule
* const rulep
;
940 int d
, m1
, yy0
, yy1
, yy2
, dow
;
943 leapyear
= isleap(year
);
944 switch (rulep
->r_type
) {
948 ** Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
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.
954 value
= janfirst
+ (rulep
->r_day
- 1) * SECSPERDAY
;
955 if (leapyear
&& rulep
->r_day
>= 60)
962 ** Just add SECSPERDAY times the day number to the time of
963 ** January 1, midnight, to get the day.
965 value
= janfirst
+ rulep
->r_day
* SECSPERDAY
;
968 case MONTH_NTH_DAY_OF_WEEK
:
970 ** Mm.n.d - nth "dth day" of month m.
973 for (i
= 0; i
< rulep
->r_mon
- 1; ++i
)
974 value
+= mon_lengths
[leapyear
][i
] * SECSPERDAY
;
977 ** Use Zeller's Congruence to get day-of-week of first day of
980 m1
= (rulep
->r_mon
+ 9) % 12 + 1;
981 yy0
= (rulep
->r_mon
<= 2) ? (year
- 1) : year
;
984 dow
= ((26 * m1
- 2) / 10 +
985 1 + yy2
+ yy2
/ 4 + yy1
/ 4 - 2 * yy1
) % 7;
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
994 d
= rulep
->r_day
- dow
;
997 for (i
= 1; i
< rulep
->r_week
; ++i
) {
998 if (d
+ DAYSPERWEEK
>=
999 mon_lengths
[leapyear
][rulep
->r_mon
- 1])
1005 ** "d" is the day-of-month (zero-origin) of the day we want.
1007 value
+= d
* SECSPERDAY
;
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
1017 return value
+ rulep
->r_time
+ offset
;
1021 ** Given a POSIX section 8-style TZ string, fill in the rule tables as
1026 tzparse(name
, sp
, lastditch
)
1028 struct state
* const sp
;
1029 const int lastditch
;
1031 const char * stdname
;
1032 const char * dstname
;
1038 unsigned char * typep
;
1042 INITIALIZE(dstname
);
1045 stdlen
= strlen(name
); /* length of standard zone name */
1047 if (stdlen
>= sizeof sp
->chars
)
1048 stdlen
= (sizeof sp
->chars
) - 1;
1051 name
= getzname(name
, (char **)&stdname
, &stdlen
);
1055 return -1; /* was "stdoffset = 0;" */
1057 name
= getoffset(name
, &stdoffset
);
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') {
1071 name
= getzname(name
, (char **)&dstname
, &dstlen
);
1074 if (*name
!= '\0' && *name
!= ',' && *name
!= ';') {
1075 name
= getoffset(name
, &dstoffset
);
1078 } else dstoffset
= stdoffset
- SECSPERHOUR
;
1079 if (*name
== '\0' && load_result
!= 0)
1080 name
= TZDEFRULESTRING
;
1081 if (*name
== ',' || *name
== ';') {
1090 if ((name
= getrule(name
, &start
)) == NULL
)
1094 if ((name
= getrule(name
, &end
)) == NULL
)
1098 sp
->typecnt
= 2; /* standard time and DST */
1100 ** Two transitions per year, from EPOCH_YEAR to 2037.
1102 sp
->timecnt
= 2 * (2037 - EPOCH_YEAR
+ 1);
1103 if (sp
->timecnt
> TZ_MAX_TIMES
)
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;
1114 for (year
= EPOCH_YEAR
; year
<= 2037; ++year
) {
1115 starttime
= transtime(janfirst
, year
, &start
,
1117 endtime
= transtime(janfirst
, year
, &end
,
1119 if (starttime
> endtime
) {
1121 *typep
++ = 1; /* DST ends */
1123 *typep
++ = 0; /* DST begins */
1126 *typep
++ = 0; /* DST begins */
1128 *typep
++ = 1; /* DST ends */
1130 janfirst
+= year_lengths
[isleap(year
)] *
1134 long theirstdoffset
;
1135 long theirdstoffset
;
1144 ** Initial values of theirstdoffset and theirdstoffset.
1147 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1149 if (!sp
->ttis
[j
].tt_isdst
) {
1151 -sp
->ttis
[j
].tt_gmtoff
;
1156 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1158 if (sp
->ttis
[j
].tt_isdst
) {
1160 -sp
->ttis
[j
].tt_gmtoff
;
1165 ** Initially we're assumed to be in standard time.
1168 theiroffset
= theirstdoffset
;
1170 ** Now juggle transition times and types
1171 ** tracking offsets as you do.
1173 for (i
= 0; i
< sp
->timecnt
; ++i
) {
1175 sp
->types
[i
] = sp
->ttis
[j
].tt_isdst
;
1176 if (sp
->ttis
[j
].tt_ttisgmt
) {
1177 /* No adjustment to transition time */
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.
1188 ** Transitions from DST to DDST
1189 ** will effectively disappear since
1190 ** POSIX provides for only one DST
1193 if (isdst
&& !sp
->ttis
[j
].tt_ttisstd
) {
1194 sp
->ats
[i
] += dstoffset
-
1197 sp
->ats
[i
] += stdoffset
-
1201 theiroffset
= -sp
->ttis
[j
].tt_gmtoff
;
1202 if (sp
->ttis
[j
].tt_isdst
)
1203 theirdstoffset
= theiroffset
;
1204 else theirstdoffset
= theiroffset
;
1207 ** Finally, fill in ttis.
1208 ** ttisstd and ttisgmt need not be handled.
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;
1220 sp
->typecnt
= 1; /* only standard time */
1222 sp
->ttis
[0].tt_gmtoff
= -stdoffset
;
1223 sp
->ttis
[0].tt_isdst
= 0;
1224 sp
->ttis
[0].tt_abbrind
= 0;
1226 sp
->charcnt
= stdlen
+ 1;
1228 sp
->charcnt
+= dstlen
+ 1;
1229 if ((size_t) sp
->charcnt
> sizeof sp
->chars
)
1232 (void) strncpy(cp
, stdname
, stdlen
);
1236 (void) strncpy(cp
, dstname
, dstlen
);
1237 *(cp
+ dstlen
) = '\0';
1245 #else /* ! NOTIFY_TZ */
1247 #endif /* NOTIFY_TZ */
1248 struct state
* const sp
;
1251 #endif /* 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
);
1262 tzsetwall_basic(int rdlocked
)
1265 notify_check_tz(&lcl_notify
);
1268 static struct timespec last_mtimespec
= {0, 0};
1269 struct stat statbuf
;
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 */
1278 last_mtimespec
= statbuf
.st_mtimespec
;
1281 #endif /* NOTIFY_TZ */
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");
1289 _RWLOCK_UNLOCK(&lcl_rwlock
);
1292 #ifdef NOTIFY_TZ_DEBUG
1293 NOTIFY_TZ_PRINTF("tzsetwall_basic not set\n");
1295 _RWLOCK_UNLOCK(&lcl_rwlock
);
1297 _RWLOCK_WRLOCK(&lcl_rwlock
);
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
);
1307 _RWLOCK_RDLOCK(&lcl_rwlock
);
1311 #endif /* defined ALL_STATE */
1314 char fullname
[FILENAME_MAX
+ 1];
1315 if (tzload((char *) NULL
, lclptr
, fullname
) != 0)
1317 * If fullname is empty (an error occurred) then
1318 * default to the UTC path
1320 gmtload(lclptr
, *fullname
? NULL
: fullname
);
1321 notify_register_tz(fullname
, &lcl_notify
);
1323 #else /* ! NOTIFY_TZ */
1324 if (tzload((char *) NULL
, lclptr
) != 0)
1326 #endif /* NOTIFY_TZ */
1328 _RWLOCK_UNLOCK(&lcl_rwlock
);
1331 _RWLOCK_RDLOCK(&lcl_rwlock
);
1337 #ifdef NOTIFY_TZ_DEBUG
1338 NOTIFY_TZ_PRINTF("tzsetwall called\n");
1339 #endif /* NOTIFY_TZ_DEBUG */
1343 __private_extern__
void
1344 tzset_basic(int rdlocked
)
1348 name
= getenv("TZ");
1350 tzsetwall_basic(rdlocked
);
1355 notify_check_tz(&lcl_notify
);
1356 #endif /* NOTIFY_TZ */
1358 _RWLOCK_RDLOCK(&lcl_rwlock
);
1359 if (lcl_is_set
> 0 && strcmp(lcl_TZname
, name
) == 0) {
1361 _RWLOCK_UNLOCK(&lcl_rwlock
);
1362 #ifdef NOTIFY_TZ_DEBUG
1363 NOTIFY_TZ_PRINTF("tzset_basic matched %s\n", lcl_TZname
);
1367 _RWLOCK_UNLOCK(&lcl_rwlock
);
1369 _RWLOCK_WRLOCK(&lcl_rwlock
);
1370 lcl_is_set
= strlen(name
) < sizeof lcl_TZname
;
1372 (void) strcpy(lcl_TZname
, name
);
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
);
1381 _RWLOCK_RDLOCK(&lcl_rwlock
);
1385 #endif /* defined ALL_STATE */
1386 if (*name
== '\0') {
1388 ** User wants it fast rather than right.
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
);
1398 notify_register_tz(NULL
, &lcl_notify
);
1399 #endif /* NOTIFY_TZ */
1403 char fullname
[FILENAME_MAX
+ 1];
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
1410 int parsedOK
= FALSE
;
1411 if (tzload(name
, lclptr
, fullname
) != 0)
1412 if (name
[0] == ':' || !(parsedOK
= tzparse(name
, lclptr
, FALSE
) == 0))
1414 * If fullname is empty (an error occurred) then
1415 * default to the UTC path
1417 (void) gmtload(lclptr
, *fullname
? NULL
: fullname
);
1418 notify_register_tz(parsedOK
? NULL
: fullname
, &lcl_notify
);
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 */
1426 _RWLOCK_UNLOCK(&lcl_rwlock
);
1429 _RWLOCK_RDLOCK(&lcl_rwlock
);
1435 #ifdef NOTIFY_TZ_DEBUG
1436 NOTIFY_TZ_PRINTF("tzset called TZ=%s\n", getenv("TZ"));
1437 #endif /* NOTIFY_TZ_DEBUG */
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.)
1447 ** The unused offset argument is for the benefit of mktime variants.
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
;
1459 struct tm
* const tmp
;
1462 const struct ttinfo
* ttisp
;
1464 const time_t t
= *timep
;
1466 #ifdef NOTIFY_TZ_DEBUG
1467 NOTIFY_TZ_PRINTF("localsub called\n");
1468 #endif /* NOTIFY_TZ_DEBUG */
1473 return gmtsub(timep
, offset
, tmp
);
1474 #else /* !__LP64__ */
1475 gmtsub(timep
, offset
, tmp
);
1477 #endif /* __LP64__ */
1479 #endif /* defined ALL_STATE */
1480 if (sp
->timecnt
== 0 || t
< sp
->ats
[0]) {
1482 while (sp
->ttis
[i
].tt_isdst
)
1483 if (++i
>= sp
->typecnt
) {
1488 for (i
= 1; i
< sp
->timecnt
; ++i
)
1491 i
= sp
->types
[i
- 1];
1493 ttisp
= &sp
->ttis
[i
];
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);
1501 if (timesub(&t
, ttisp
->tt_gmtoff
, sp
, tmp
) == 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
];
1509 tmp
->TM_ZONE
= &sp
->chars
[ttisp
->tt_abbrind
];
1510 #endif /* defined TM_ZONE */
1513 #endif /* __LP64__ */
1518 const time_t * const timep
;
1520 static pthread_mutex_t localtime_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1521 static pthread_key_t localtime_key
= -1;
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
);
1534 _pthread_mutex_unlock(&localtime_mutex
);
1536 p_tm
= _pthread_getspecific(localtime_key
);
1538 if ((p_tm
= (struct tm
*)malloc(sizeof(struct tm
)))
1541 _pthread_setspecific(localtime_key
, p_tm
);
1543 _RWLOCK_RDLOCK(&lcl_rwlock
);
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
);
1555 return localsub(timep
, 0L, &tm
);
1556 #else /* !__LP64__ */
1557 localsub(timep
, 0L, &tm
);
1559 #endif /* __LP64__ */
1564 ** Re-entrant version of localtime.
1568 localtime_r(const time_t * const __restrict timep
, struct tm
* __restrict tm
)
1570 _RWLOCK_RDLOCK(&lcl_rwlock
);
1573 tm
= localsub(timep
, 0L, tm
);
1574 #else /* !__LP64__ */
1575 localsub(timep
, 0L, tm
);
1576 #endif /* __LP64__ */
1577 _RWLOCK_UNLOCK(&lcl_rwlock
);
1582 ** gmtsub is to gmtime as localsub is to localtime.
1587 #else /* !__LP64__ */
1589 #endif /* __LP64__ */
1590 gmtsub(timep
, offset
, tmp
)
1591 const time_t * const timep
;
1593 struct tm
* const tmp
;
1595 #ifdef NOTIFY_TZ_DEBUG
1596 NOTIFY_TZ_PRINTF("gmtsub called\n");
1597 #endif /* NOTIFY_TZ_DEBUG */
1599 notify_check_tz(&gmt_notify
);
1600 #endif /* NOTIFY_TZ */
1602 _MUTEX_LOCK(&gmt_mutex
);
1607 #endif /* NOTIFY_TZ */
1608 gmtptr
= (struct state
*) malloc(sizeof *gmtptr
);
1610 #endif /* defined ALL_STATE */
1613 char fullname
[FILENAME_MAX
+ 1];
1614 gmtload(gmtptr
, fullname
);
1615 notify_register_tz(fullname
, &gmt_notify
);
1617 #else /* ! NOTIFY_TZ */
1619 #endif /* NOTIFY_TZ */
1622 _MUTEX_UNLOCK(&gmt_mutex
);
1625 if(timesub(timep
, offset
, gmtptr
, tmp
) == NULL
)
1627 #else /* !__LP64__ */
1628 timesub(timep
, offset
, gmtptr
, tmp
);
1629 #endif /* __LP64__ */
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.
1637 tmp
->TM_ZONE
= wildabbr
;
1641 tmp
->TM_ZONE
= (char *)gmt
;
1642 else tmp
->TM_ZONE
= gmtptr
->chars
;
1643 #endif /* defined ALL_STATE */
1645 tmp
->TM_ZONE
= gmtptr
->chars
;
1646 #endif /* State Farm */
1648 #endif /* defined TM_ZONE */
1651 #endif /* __LP64__ */
1656 const time_t * const timep
;
1658 static pthread_mutex_t gmtime_mutex
= PTHREAD_MUTEX_INITIALIZER
;
1659 static pthread_key_t gmtime_key
= -1;
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
);
1672 _pthread_mutex_unlock(&gmtime_mutex
);
1675 * Changed to follow POSIX.1 threads standard, which
1676 * is what BSD currently has.
1678 if ((p_tm
= _pthread_getspecific(gmtime_key
)) == NULL
) {
1679 if ((p_tm
= (struct tm
*)malloc(sizeof(struct tm
)))
1683 _pthread_setspecific(gmtime_key
, p_tm
);
1686 return gmtsub(timep
, 0L, p_tm
);
1687 #else /* !__LP64__ */
1688 gmtsub(timep
, 0L, p_tm
);
1690 #endif /* __LP64__ */
1694 return gmtsub(timep
, 0L, &tm
);
1695 #else /* !__LP64__ */
1696 gmtsub(timep
, 0L, &tm
);
1698 #endif /* __LP64__ */
1703 * Re-entrant version of gmtime.
1708 const time_t * const timep
;
1713 return gmtsub(timep
, 0L, tm
);
1714 #else /* !__LP64__ */
1715 gmtsub(timep
, 0L, tm
);
1717 #endif /* __LP64__ */
1723 offtime(timep
, offset
)
1724 const time_t * const timep
;
1728 return gmtsub(timep
, offset
, &tm
);
1729 #else /* !__LP64__ */
1730 gmtsub(timep
, offset
, &tm
);
1732 #endif /* __LP64__ */
1735 #endif /* defined STD_INSPIRED */
1739 #else /* !__LP64__ */
1741 #endif /* __LP64__ */
1742 timesub(timep
, offset
, sp
, tmp
)
1743 const time_t * const timep
;
1745 const struct state
* const sp
;
1746 struct tm
* const tmp
;
1748 const struct lsinfo
* lp
;
1761 i
= (sp
== NULL
) ? 0 : sp
->leapcnt
;
1762 #endif /* defined ALL_STATE */
1765 #endif /* State Farm */
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
);
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) {
1786 days
= *timep
/ SECSPERDAY
;
1787 rem
= *timep
% SECSPERDAY
;
1789 if (*timep
== 0x80000000) {
1791 ** A 3B1 muffs the division on the most negative number.
1796 #endif /* defined mc68k */
1797 rem
+= (offset
- corr
);
1802 while (rem
>= SECSPERDAY
) {
1806 tmp
->tm_hour
= (int) (rem
/ SECSPERHOUR
);
1807 rem
= rem
% SECSPERHOUR
;
1808 tmp
->tm_min
= (int) (rem
/ SECSPERMIN
);
1810 ** A positive leap second requires a special
1811 ** representation. This uses "... ??:59:60" et seq.
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
;
1818 #define _LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
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
)]) {
1827 newy
= y
+ days
/ DAYSPERNYEAR
;
1830 days
-= (newy
- y
) * DAYSPERNYEAR
+
1831 LEAPS_THRU_END_OF(newy
- 1) -
1832 LEAPS_THRU_END_OF(y
- 1);
1837 if (y
< INT_MIN
|| y
> INT_MAX
) {
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);
1852 tmp
->TM_GMTOFF
= offset
;
1853 #endif /* defined TM_GMTOFF */
1856 #endif /* __LP64__ */
1861 const time_t * const timep
;
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))
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
1875 struct tm
*tm
= localtime(timep
);
1880 #else /* !__LP64__ */
1881 return asctime(localtime(timep
));
1882 #endif /* __LP64__ */
1887 const time_t * const timep
;
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
1898 if (localtime_r(timep
, &tm
) == NULL
)
1900 return asctime_r(&tm
, buf
);
1901 #else /* !__LP64__ */
1902 return asctime_r(localtime_r(timep
, &tm
), buf
);
1903 #endif /* __LP64__ */
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).
1918 #endif /* !defined WRONG */
1921 ** Simplified normalize logic courtesy Paul Eggert (eggert@twinsun.com).
1925 increment_overflow(number
, delta
)
1933 return (*number
< number0
) != (delta
< 0);
1937 normalize_overflow(tensptr
, unitsptr
, base
)
1938 int * const tensptr
;
1939 int * const unitsptr
;
1944 tensdelta
= (*unitsptr
>= 0) ?
1945 (*unitsptr
/ base
) :
1946 (-1 - (-1 - *unitsptr
) / base
);
1947 *unitsptr
-= tensdelta
* base
;
1948 return increment_overflow(tensptr
, tensdelta
);
1953 const struct tm
* const atmp
;
1954 const struct tm
* const btmp
;
1959 * Assume that atmp and btmp point to normalized tm strutures.
1960 * So only arithmetic with tm_year could overflow in 64-bit.
1962 if (atmp
->tm_year
!= btmp
->tm_year
) {
1963 return (atmp
->tm_year
> btmp
->tm_year
? 1 : -1);
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
;
1974 time2sub(tmp
, funcp
, offset
, okayp
, do_norm_secs
, unix03
)
1975 struct tm
* const tmp
;
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__ */
1983 const int do_norm_secs
;
1986 const struct state
* sp
;
1993 struct tm yourtm
, mytm
;
1996 #endif /* __LP64__ */
2001 if (normalize_overflow(&yourtm
.tm_min
, &yourtm
.tm_sec
,
2005 if (normalize_overflow(&yourtm
.tm_hour
, &yourtm
.tm_min
, MINSPERHOUR
))
2007 if (normalize_overflow(&yourtm
.tm_mday
, &yourtm
.tm_hour
, HOURSPERDAY
))
2009 if (normalize_overflow(&yourtm
.tm_year
, &yourtm
.tm_mon
, MONSPERYEAR
))
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.
2016 year
= (long)yourtm
.tm_year
+ TM_YEAR_BASE
;
2017 #else /* !__LP64__ */
2018 if (increment_overflow(&yourtm
.tm_year
, TM_YEAR_BASE
))
2020 #endif /* __LP64__ */
2021 while (yourtm
.tm_mday
<= 0) {
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))
2029 i
= yourtm
.tm_year
+ (1 < yourtm
.tm_mon
);
2030 yourtm
.tm_mday
+= year_lengths
[isleap(i
)];
2031 #endif /* __LP64__ */
2033 while (yourtm
.tm_mday
> DAYSPERLYEAR
) {
2035 il
= year
+ (1 < yourtm
.tm_mon
);
2036 yourtm
.tm_mday
-= year_lengths
[isleap(il
)];
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))
2043 #endif /* __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
)
2053 yourtm
.tm_mday
-= i
;
2054 if (++yourtm
.tm_mon
>= MONSPERYEAR
) {
2058 #else /* !__LP64__ */
2059 if (increment_overflow(&yourtm
.tm_year
, 1))
2061 #endif /* __LP64__ */
2065 year
-= TM_YEAR_BASE
;
2066 if (year
> INT_MAX
|| year
< INT_MIN
)
2068 yourtm
.tm_year
= year
;
2069 #else /* !__LP64__ */
2070 if (increment_overflow(&yourtm
.tm_year
, -TM_YEAR_BASE
))
2072 #endif /* __LP64__ */
2073 /* Don't go below 1900 for POLA */
2074 if (yourtm
.tm_year
< 0)
2076 if (yourtm
.tm_sec
>= 0 && yourtm
.tm_sec
< SECSPERMIN
)
2078 else if (yourtm
.tm_year
+ TM_YEAR_BASE
< EPOCH_YEAR
) {
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.
2087 if (increment_overflow(&yourtm
.tm_sec
, 1 - SECSPERMIN
))
2089 saved_seconds
= yourtm
.tm_sec
;
2090 yourtm
.tm_sec
= SECSPERMIN
- 1;
2092 saved_seconds
= yourtm
.tm_sec
;
2096 ** Divide the search space in half
2097 ** (this works whether time_t is signed or unsigned).
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__ */
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).
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.
2119 t
= TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits
);
2122 if ((*funcp
)(&t
, offset
, &mytm
) == NULL
) {
2123 /* we overflowed, so t is too big */
2127 #else /* !__LP64__ */
2128 (*funcp
)(&t
, offset
, &mytm
);
2129 #endif /* __LP64__ */
2130 dir
= tmcomp(&mytm
, &yourtm
);
2133 #endif /* __LP64__ */
2138 --t
; /* may be needed if new t is minimal */
2140 t
-= ((time_t) 1) << bits
;
2141 else t
+= ((time_t) 1) << bits
;
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
)
2150 ** Right time, wrong type.
2151 ** Hunt for right time, right type.
2152 ** It's okay to guess wrong since the guess
2158 #endif /* defined ALL_STATE */
2159 for (i
= sp
->typecnt
- 1; i
>= 0; --i
) {
2160 if (sp
->ttis
[i
].tt_isdst
!= yourtm
.tm_isdst
)
2162 for (j
= sp
->typecnt
- 1; j
>= 0; --j
) {
2163 if (sp
->ttis
[j
].tt_isdst
== yourtm
.tm_isdst
)
2165 newt
= t
+ sp
->ttis
[j
].tt_gmtoff
-
2166 sp
->ttis
[i
].tt_gmtoff
;
2168 if ((*funcp
)(&newt
, offset
, &mytm
) == NULL
)
2170 #else /* !__LP64__ */
2171 (*funcp
)(&newt
, offset
, &mytm
);
2172 #endif /* __LP64__ */
2173 if (tmcomp(&mytm
, &yourtm
) != 0)
2175 if (mytm
.tm_isdst
!= yourtm
.tm_isdst
)
2187 newt
= t
+ saved_seconds
;
2188 if ((newt
< t
) != (saved_seconds
< 0))
2192 if ((*funcp
)(&t
, offset
, tmp
) == NULL
)
2194 #else /* !__LP64__ */
2195 (*funcp
)(&t
, offset
, tmp
);
2196 #endif /* __LP64__ */
2202 time2(tmp
, funcp
, offset
, okayp
, unix03
)
2203 struct tm
* const tmp
;
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__ */
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.
2220 t
= time2sub(tmp
, funcp
, offset
, okayp
, FALSE
, unix03
);
2221 return *okayp
? t
: time2sub(tmp
, funcp
, offset
, okayp
, TRUE
, unix03
);
2224 __private_extern__
time_t
2225 time1(tmp
, funcp
, offset
, unix03
)
2226 struct tm
* const tmp
;
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__ */
2236 const struct state
* sp
;
2238 int sameind
, otherind
;
2241 int seen
[TZ_MAX_TYPES
];
2242 int types
[TZ_MAX_TYPES
];
2245 if (tmp
->tm_isdst
> 1)
2247 t
= time2(tmp
, funcp
, offset
, &okay
, unix03
);
2250 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
2254 if (tmp
->tm_isdst
< 0)
2255 tmp
->tm_isdst
= 0; /* reset to std and try again */
2256 #endif /* defined PCTS */
2258 if (okay
|| tmp
->tm_isdst
< 0)
2260 #endif /* !defined PCTS */
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
2267 sp
= (funcp
== localsub
) ? lclptr
: gmtptr
;
2271 #endif /* defined ALL_STATE */
2272 for (i
= 0; i
< sp
->typecnt
; ++i
)
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
];
2280 for (sameind
= 0; sameind
< nseen
; ++sameind
) {
2281 samei
= types
[sameind
];
2282 if (sp
->ttis
[samei
].tt_isdst
!= tmp
->tm_isdst
)
2284 for (otherind
= 0; otherind
< nseen
; ++otherind
) {
2285 otheri
= types
[otherind
];
2286 if (sp
->ttis
[otheri
].tt_isdst
== tmp
->tm_isdst
)
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
);
2294 tmp
->tm_sec
-= sp
->ttis
[otheri
].tt_gmtoff
-
2295 sp
->ttis
[samei
].tt_gmtoff
;
2296 tmp
->tm_isdst
= !tmp
->tm_isdst
;
2301 #else /* BUILDING_VARIANT */
2302 __private_extern__ pthread_rwlock_t lcl_rwlock
;
2303 #endif /* BUILDING_VARIANT */
2307 struct tm
* const tmp
;
2309 time_t mktime_return_value
;
2311 _RWLOCK_RDLOCK(&lcl_rwlock
);
2313 mktime_return_value
= time1(tmp
, localsub
, 0L, __DARWIN_UNIX03
);
2314 _RWLOCK_UNLOCK(&lcl_rwlock
);
2316 return(mktime_return_value
);
2319 #if !BUILDING_VARIANT
2324 struct tm
* const tmp
;
2326 tmp
->tm_isdst
= -1; /* in case it wasn't initialized */
2332 struct tm
* const tmp
;
2335 return time1(tmp
, gmtsub
, 0L, __DARWIN_UNIX03
);
2339 timeoff(tmp
, offset
)
2340 struct tm
* const tmp
;
2344 return time1(tmp
, gmtsub
, offset
, __DARWIN_UNIX03
);
2347 #endif /* defined STD_INSPIRED */
2352 ** The following is supplied for compatibility with
2353 ** previous versions of the CMUCS runtime library.
2358 struct tm
* const tmp
;
2360 const time_t t
= mktime(tmp
);
2367 #endif /* defined CMUCS */
2370 ** XXX--is the below the right way to conditionalize??
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.
2395 if (*timep
>= lp
->ls_trans
)
2406 return t
- leapcorr(&t
);
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.
2423 x
= t
+ leapcorr(&t
);
2424 y
= x
- leapcorr(&x
);
2428 y
= x
- leapcorr(&x
);
2435 y
= x
- leapcorr(&x
);
2443 #endif /* defined STD_INSPIRED */
2444 #endif /* !BUILDING_VARIANT */