]> git.saurik.com Git - apple/libc.git/blob - stdtime/FreeBSD/localtime.c.patch
Libc-594.1.4.tar.gz
[apple/libc.git] / stdtime / FreeBSD / localtime.c.patch
1 --- localtime.c.orig 2008-12-15 11:41:07.000000000 -0800
2 +++ localtime.c 2009-01-21 15:43:59.000000000 -0800
3 @@ -22,8 +22,22 @@ __FBSDID("$FreeBSD: src/lib/libc/stdtime
4 #include "namespace.h"
5 #include <sys/types.h>
6 #include <sys/stat.h>
7 +#include <time.h>
8 #include <fcntl.h>
9 #include <pthread.h>
10 +#include <errno.h>
11 +#ifdef NOTIFY_TZ
12 +//#define NOTIFY_TZ_DEBUG
13 +//#define NOTIFY_TZ_DEBUG_FILE "/var/log/localtime.debug"
14 +//#define NOTIFY_TZ_LOG "/var/log/localtime.log"
15 +/* force ALL_STATE if NOTIFY_TZ is set */
16 +#ifndef ALL_STATE
17 +#define ALL_STATE
18 +#endif /* ALL_STATE */
19 +#include <mach/mach_init.h>
20 +#include <notify.h>
21 +#include <alloca.h>
22 +#endif /* NOTIFY_TZ */
23 #include "private.h"
24 #include "un-namespace.h"
25
26 @@ -135,40 +149,96 @@ struct rule {
27 #define DAY_OF_YEAR 1 /* n - day of year */
28 #define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
29
30 +#ifdef NOTIFY_TZ
31 +typedef struct {
32 + int token;
33 + int notify_was_off;
34 + int is_set;
35 +} notify_tz_t;
36 +
37 +#define NOTIFY_TZ_NAME "com.apple.system.timezone"
38 +#endif /* NOTIFY_TZ */
39 +
40 /*
41 ** Prototypes for static functions.
42 */
43 +#define localsub _st_localsub
44 +#define time1 _st_time1
45 +#define tzset_basic _st_tzset_basic
46 +__private_extern__
47 +#ifdef __LP64__
48 +struct tm * localsub(const time_t * timep, long offset,
49 + struct tm * tmp);
50 +#else /* !__LP64__ */
51 +void localsub(const time_t * timep, long offset,
52 + struct tm * tmp);
53 +#endif /* __LP64__ */
54 +__private_extern__
55 +time_t time1(struct tm * tmp,
56 +#ifdef __LP64__
57 + struct tm *(*funcp) (const time_t *,
58 + long, struct tm *),
59 +#else /* !__LP64__ */
60 + void(*funcp) (const time_t *,
61 + long, struct tm *),
62 +#endif /* __LP64__ */
63 + long offset,
64 + int unix03);
65 +__private_extern__
66 +void tzset_basic(void);
67
68 +#define lcl_mutex _st_lcl_mutex
69 +
70 +#if !BUILDING_VARIANT
71 static long detzcode(const char * codep);
72 -static const char * getzname(const char * strp);
73 +static const char * getzname(const char * strp, char **name, size_t *len);
74 static const char * getnum(const char * strp, int * nump, int min,
75 int max);
76 static const char * getsecs(const char * strp, long * secsp);
77 static const char * getoffset(const char * strp, long * offsetp);
78 static const char * getrule(const char * strp, struct rule * rulep);
79 static void gmtload(struct state * sp);
80 -static void gmtsub(const time_t * timep, long offset,
81 +#ifdef __LP64__
82 +static struct tm * gmtsub(const time_t * timep, long offset,
83 struct tm * tmp);
84 -static void localsub(const time_t * timep, long offset,
85 +#else /* !__LP64__ */
86 +static void gmtsub(const time_t * timep, long offset,
87 struct tm * tmp);
88 +#endif /* __LP64__ */
89 static int increment_overflow(int * number, int delta);
90 static int normalize_overflow(int * tensptr, int * unitsptr,
91 int base);
92 +#ifdef NOTIFY_TZ
93 +static void notify_check_tz(notify_tz_t *p);
94 +static void notify_register_tz(char *file, notify_tz_t *p);
95 +#endif /* NOTIFY_TZ */
96 static void settzname(void);
97 -static time_t time1(struct tm * tmp,
98 - void(*funcp) (const time_t *,
99 - long, struct tm *),
100 - long offset);
101 static time_t time2(struct tm *tmp,
102 +#ifdef __LP64__
103 + struct tm *(*funcp) (const time_t *,
104 + long, struct tm*),
105 +#else /* !__LP64__ */
106 void(*funcp) (const time_t *,
107 long, struct tm*),
108 - long offset, int * okayp);
109 +#endif /* __LP64__ */
110 + long offset, int * okayp, int unix03);
111 static time_t time2sub(struct tm *tmp,
112 +#ifdef __LP64__
113 + struct tm *(*funcp) (const time_t *,
114 + long, struct tm*),
115 +#else /* !__LP64__ */
116 void(*funcp) (const time_t *,
117 long, struct tm*),
118 - long offset, int * okayp, int do_norm_secs);
119 +#endif /* __LP64__ */
120 + long offset, int * okayp, int do_norm_secs,
121 + int unix03);
122 +#ifdef __LP64__
123 +static struct tm * timesub(const time_t * timep, long offset,
124 + const struct state * sp, struct tm * tmp);
125 +#else /* !__LP64__ */
126 static void timesub(const time_t * timep, long offset,
127 const struct state * sp, struct tm * tmp);
128 +#endif /* __LP64__ */
129 static int tmcomp(const struct tm * atmp,
130 const struct tm * btmp);
131 static time_t transtime(time_t janfirst, int year,
132 @@ -194,10 +264,15 @@ static struct state gmtmem;
133 #endif /* !defined TZ_STRLEN_MAX */
134
135 static char lcl_TZname[TZ_STRLEN_MAX + 1];
136 +#ifdef NOTIFY_TZ
137 +#define lcl_is_set (lcl_notify.is_set)
138 +#define gmt_is_set (gmt_notify.is_set)
139 +#else /* ! NOTIFY_TZ */
140 static int lcl_is_set;
141 static int gmt_is_set;
142 -static pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER;
143 -static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
144 +#endif /* NOTIFY_TZ */
145 +__private_extern__ pthread_mutex_t lcl_mutex = PTHREAD_MUTEX_INITIALIZER;
146 +static pthread_mutex_t gmt_mutex = PTHREAD_MUTEX_INITIALIZER;
147
148 char * tzname[2] = {
149 wildabbr,
150 @@ -214,15 +289,62 @@ char * tzname[2] = {
151
152 static struct tm tm;
153
154 +#define USG_COMPAT
155 +#define ALTZONE
156 #ifdef USG_COMPAT
157 -time_t timezone = 0;
158 int daylight = 0;
159 +__private_extern__ void _st_set_timezone(long);
160 #endif /* defined USG_COMPAT */
161
162 #ifdef ALTZONE
163 -time_t altzone = 0;
164 +__private_extern__ long __darwin_altzone = 0;
165 +#define altzone __darwin_altzone
166 #endif /* defined ALTZONE */
167
168 +#ifdef NOTIFY_TZ
169 +#ifdef NOTIFY_TZ_DEBUG
170 +#ifdef NOTIFY_TZ_DEBUG_FILE
171 +#define NOTIFY_TZ_PRINTF(fmt, args...) \
172 +{ \
173 + FILE *_notify_tz_fp_; \
174 + if((_notify_tz_fp_ = fopen(NOTIFY_TZ_DEBUG_FILE, "a")) != NULL) { \
175 + fprintf(_notify_tz_fp_, "%d: " fmt, getpid(), ## args); \
176 + fclose(_notify_tz_fp_); \
177 + } \
178 +}
179 +#else /* ! NOTIFY_TZ_DEBUG_FILE */
180 +#define NOTIFY_TZ_PRINTF(args...) fprintf(stdout, ## args)
181 +#endif /* NOTIFY_TZ_DEBUG_FILE */
182 +#endif /* NOTIFY_TZ_DEBUG */
183 +#ifdef NOTIFY_TZ_LOG
184 +#define NOTIFY_LOG(fmt, args...) \
185 +{ \
186 + FILE *_notify_log_fp_; \
187 + if((_notify_log_fp_ = fopen(NOTIFY_TZ_LOG, "a")) != NULL) { \
188 + fprintf(_notify_log_fp_, "%d: " fmt, getpid(), ## args); \
189 + fclose(_notify_log_fp_); \
190 + } \
191 +}
192 +#endif /* NOTIFY_TZ_LOG */
193 +/*--------------------------------------------------------------------
194 + * __notify_78945668_info__ is a global variable (defined in Libnotify)
195 + * that can be used to disable the notify mechanism. Set to a negative
196 + * value to disable. It can then be set back to zero to re-enable.
197 + *-------------------------------------------------------------------- */
198 +extern int __notify_78945668_info__;
199 +
200 +/*--------------------------------------------------------------------
201 + * fullname is used to pass the actual path of the timezone file to the
202 + * notify routines. If it is a nil string, that means no timezone file
203 + * is being used.
204 + *-------------------------------------------------------------------- */
205 +static char * fullname = NULL;
206 +
207 +static notify_tz_t gmt_notify = {-1, 0, 0};
208 +static notify_tz_t lcl_notify = {-1, 0, 0};
209 +static char notify_tz_name[] = NOTIFY_TZ_NAME;
210 +#endif /* NOTIFY_TZ */
211 +
212 static long
213 detzcode(codep)
214 const char * const codep;
215 @@ -246,14 +368,14 @@ settzname(void)
216 tzname[1] = wildabbr;
217 #ifdef USG_COMPAT
218 daylight = 0;
219 - timezone = 0;
220 + _st_set_timezone(0);
221 #endif /* defined USG_COMPAT */
222 #ifdef ALTZONE
223 altzone = 0;
224 #endif /* defined ALTZONE */
225 #ifdef ALL_STATE
226 if (sp == NULL) {
227 - tzname[0] = tzname[1] = gmt;
228 + tzname[0] = tzname[1] = (char *)gmt;
229 return;
230 }
231 #endif /* defined ALL_STATE */
232 @@ -266,7 +388,7 @@ settzname(void)
233 if (ttisp->tt_isdst)
234 daylight = 1;
235 if (i == 0 || !ttisp->tt_isdst)
236 - timezone = -(ttisp->tt_gmtoff);
237 + _st_set_timezone(-(ttisp->tt_gmtoff));
238 #endif /* defined USG_COMPAT */
239 #ifdef ALTZONE
240 if (i == 0 || ttisp->tt_isdst)
241 @@ -286,6 +408,119 @@ settzname(void)
242 }
243 }
244
245 +#ifdef NOTIFY_TZ
246 +static void
247 +notify_check_tz(notify_tz_t *p)
248 +{
249 + unsigned int nstat;
250 + int ncheck;
251 +
252 + if (__notify_78945668_info__ < 0) {
253 +#ifdef NOTIFY_TZ_DEBUG
254 + if(!p->notify_was_off) NOTIFY_TZ_PRINTF("notify_check_tz: setting %s_notify->notify_was_off\n", (p == &lcl_notify ? "lcl" : "gmt"));
255 +#endif /* NOTIFY_TZ_DEBUG */
256 + p->notify_was_off = 1;
257 + return;
258 + }
259 + /* force rereading the timezone file if notify was off */
260 + if (p->notify_was_off) {
261 +#ifdef NOTIFY_TZ_DEBUG
262 + NOTIFY_TZ_PRINTF("notify_check_tz: saw %s_notify->notify_was_off\n", (p == &lcl_notify ? "lcl" : "gmt"));
263 +#endif /* NOTIFY_TZ_DEBUG */
264 + p->is_set = 0;
265 + p->notify_was_off = 0;
266 + return;
267 + }
268 + if (p->token < 0)
269 + return;
270 + nstat = notify_check(p->token, &ncheck);
271 + if (nstat || ncheck) {
272 + p->is_set = 0;
273 +#ifdef NOTIFY_TZ_DEBUG
274 + NOTIFY_TZ_PRINTF("notify_check_tz: %s changed\n", (p == &lcl_notify) ? "lcl" : "gmt");
275 +#endif /* NOTIFY_TZ_DEBUG */
276 + }
277 +#ifdef NOTIFY_TZ_DEBUG
278 + NOTIFY_TZ_PRINTF("notify_check_tz: %s unchanged\n", (p == &lcl_notify) ? "lcl" : "gmt");
279 +#endif /* NOTIFY_TZ_DEBUG */
280 +}
281 +
282 +extern uint32_t notify_monitor_file(int token, char *path, int flags);
283 +
284 +static void
285 +notify_register_tz(char *file, notify_tz_t *p)
286 +{
287 + char *name;
288 + unsigned int nstat;
289 + int ncheck;
290 +
291 + if (__notify_78945668_info__ < 0)
292 + return;
293 + /*----------------------------------------------------------------
294 + * Since we don't record the last time zone filename, just cancel
295 + * (which should remove the file monitor) and setup from scratch
296 + *----------------------------------------------------------------*/
297 + if (p->token >= 0)
298 + notify_cancel(p->token);
299 + if (!file || *file == 0) {
300 + /* no time zone file to monitor */
301 + p->token = -1;
302 + return;
303 + }
304 + /*----------------------------------------------------------------
305 + * Just use com.apple.system.timezone if the path is /etc/localtime.
306 + * Otherwise use com.apple.system.timezone.<fullpath>
307 + *----------------------------------------------------------------*/
308 + if (TZDEFAULT && strcmp(file, TZDEFAULT) == 0)
309 + name = notify_tz_name;
310 + else {
311 + name = alloca(sizeof(notify_tz_name) + strlen(file) + 1);
312 + if (name == NULL) {
313 + p->token = -1;
314 + return;
315 + }
316 + strcpy(name, notify_tz_name);
317 + strcat(name, ".");
318 + strcat(name, file);
319 + }
320 +#ifdef NOTIFY_TZ_DEBUG
321 + NOTIFY_TZ_PRINTF("notify_register_tz: file=%s name=%s\n", file, name);
322 +#endif /* NOTIFY_TZ_DEBUG */
323 + nstat = notify_register_check(name, &p->token);
324 + if (nstat != 0) {
325 + p->token = -1;
326 + p->is_set = 0;
327 +#ifdef NOTIFY_TZ_DEBUG
328 + NOTIFY_TZ_PRINTF("***notify_register_tz: notify_register_check failed: %u\n", nstat);
329 +#endif /* NOTIFY_TZ_DEBUG */
330 +#ifdef NOTIFY_TZ_LOG
331 + NOTIFY_LOG("notify_register_check(%s) failed: %u\n", name, nstat);
332 +#endif /* NOTIFY_TZ_LOG */
333 + return;
334 + }
335 + /* don't need to request monitoring /etc/localtime */
336 + if (name != notify_tz_name) {
337 +#ifdef NOTIFY_TZ_DEBUG
338 + NOTIFY_TZ_PRINTF("notify_register_tz: monitor %s\n", file);
339 +#endif /* NOTIFY_TZ_DEBUG */
340 + nstat = notify_monitor_file(p->token, file, 0);
341 + if (nstat != 0) {
342 + notify_cancel(p->token);
343 + p->token = -1;
344 + p->is_set = 0;
345 +#ifdef NOTIFY_TZ_DEBUG
346 + NOTIFY_TZ_PRINTF("***notify_register_tz: notify_monitor_file failed: %u\n", nstat);
347 +#endif /* NOTIFY_TZ_DEBUG */
348 +#ifdef NOTIFY_TZ_LOG
349 + NOTIFY_LOG("notify_monitor_file(%s) failed: %u\n", file, nstat);
350 +#endif /* NOTIFY_TZ_LOG */
351 + return;
352 + }
353 + }
354 + notify_check(p->token, &ncheck); /* this always returns true */
355 +}
356 +#endif /* NOTIFY_TZ */
357 +
358 static int
359 tzload(name, sp)
360 const char * name;
361 @@ -295,6 +530,9 @@ struct state * const sp;
362 int i;
363 int fid;
364
365 +#ifdef NOTIFY_TZ_DEBUG
366 + NOTIFY_TZ_PRINTF("tzload: name=%s\n", name);
367 +#endif /* NOTIFY_TZ_DEBUG */
368 /* XXX The following is from OpenBSD, and I'm not sure it is correct */
369 if (name != NULL && issetugid() != 0)
370 if ((name[0] == ':' && name[1] == '/') ||
371 @@ -312,7 +550,15 @@ struct state * const sp;
372 ** to hold the longest file name string that the implementation
373 ** guarantees can be opened."
374 */
375 +#ifdef NOTIFY_TZ
376 + if (!fullname) {
377 + fullname = malloc(FILENAME_MAX + 1);
378 + if (!fullname)
379 + return -1;
380 + }
381 +#else /* ! NOTIFY_TZ */
382 char fullname[FILENAME_MAX + 1];
383 +#endif /* NOTIFY_TZ */
384
385 if (name[0] == ':')
386 ++name;
387 @@ -320,7 +566,11 @@ struct state * const sp;
388 if (!doaccess) {
389 if ((p = TZDIR) == NULL)
390 return -1;
391 +#ifdef NOTIFY_TZ
392 + if ((strlen(p) + 1 + strlen(name) + 1) >= (FILENAME_MAX + 1))
393 +#else /* ! NOTIFY_TZ */
394 if ((strlen(p) + 1 + strlen(name) + 1) >= sizeof fullname)
395 +#endif /* NOTIFY_TZ */
396 return -1;
397 (void) strcpy(fullname, p);
398 (void) strcat(fullname, "/");
399 @@ -332,6 +582,10 @@ struct state * const sp;
400 doaccess = TRUE;
401 name = fullname;
402 }
403 +#ifdef NOTIFY_TZ
404 + else
405 + strcpy(fullname, name);
406 +#endif /* NOTIFY_TZ */
407 if (doaccess && access(name, R_OK) != 0)
408 return -1;
409 if ((fid = _open(name, OPEN_MODE)) == -1)
410 @@ -350,6 +604,9 @@ struct state * const sp;
411 int ttisstdcnt;
412 int ttisgmtcnt;
413
414 +#ifdef NOTIFY_TZ_DEBUG
415 + NOTIFY_TZ_PRINTF("tzload: reading %s\n", name);
416 +#endif /* NOTIFY_TZ_DEBUG */
417 i = _read(fid, u.buf, sizeof u.buf);
418 if (_close(fid) != 0)
419 return -1;
420 @@ -456,14 +713,24 @@ static const int year_lengths[2] = {
421 */
422
423 static const char *
424 -getzname(strp)
425 +getzname(strp, name, len)
426 const char * strp;
427 +char ** name;
428 +size_t * len;
429 {
430 char c;
431 + char * ket;
432
433 + if (*strp == '<' && (ket = strchr(strp, '>')) != NULL) {
434 + *name = (char *)(strp + 1);
435 + *len = ket - strp - 1;
436 + return ket + 1;
437 + }
438 + *name = (char *)strp;
439 while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
440 c != '+')
441 ++strp;
442 + *len = strp - *name;
443 return strp;
444 }
445
446 @@ -743,16 +1010,15 @@ const int lastditch;
447 int load_result;
448
449 INITIALIZE(dstname);
450 - stdname = name;
451 if (lastditch) {
452 + stdname = name;
453 stdlen = strlen(name); /* length of standard zone name */
454 name += stdlen;
455 if (stdlen >= sizeof sp->chars)
456 stdlen = (sizeof sp->chars) - 1;
457 stdoffset = 0;
458 } else {
459 - name = getzname(name);
460 - stdlen = name - stdname;
461 + name = getzname(name, (char **)&stdname, &stdlen);
462 if (stdlen < 3)
463 return -1;
464 if (*name == '\0')
465 @@ -764,12 +1030,14 @@ const int lastditch;
466 }
467 }
468 load_result = tzload(TZDEFRULES, sp);
469 +#ifdef NOTIFY_TZ
470 + *fullname = 0; /* mark fullname as invalid */
471 +#endif /* NOTIFY_TZ */
472 if (load_result != 0)
473 sp->leapcnt = 0; /* so, we're off a little */
474 if (*name != '\0') {
475 dstname = name;
476 - name = getzname(name);
477 - dstlen = name - dstname; /* length of DST zone name */
478 + name = getzname(name, (char **)&dstname, &dstlen);
479 if (dstlen < 3)
480 return -1;
481 if (*name != '\0' && *name != ',' && *name != ';') {
482 @@ -951,8 +1219,19 @@ struct state * const sp;
483 static void
484 tzsetwall_basic(void)
485 {
486 +#ifdef NOTIFY_TZ
487 + notify_check_tz(&lcl_notify);
488 +#endif /* NOTIFY_TZ */
489 +#ifdef NOTIFY_TZ_DEBUG
490 + if (lcl_is_set < 0) {
491 + NOTIFY_TZ_PRINTF("tzsetwall_basic lcl_is_set < 0\n");
492 + return;
493 + }
494 + NOTIFY_TZ_PRINTF("tzsetwall_basic not set\n");
495 +#else /* ! NOTIFY_TZ_DEBUG */
496 if (lcl_is_set < 0)
497 return;
498 +#endif /* NOTIFY_TZ_DEBUG */
499 lcl_is_set = -1;
500
501 #ifdef ALL_STATE
502 @@ -966,18 +1245,24 @@ tzsetwall_basic(void)
503 #endif /* defined ALL_STATE */
504 if (tzload((char *) NULL, lclptr) != 0)
505 gmtload(lclptr);
506 +#ifdef NOTIFY_TZ
507 + notify_register_tz(fullname, &lcl_notify);
508 +#endif /* NOTIFY_TZ */
509 settzname();
510 }
511
512 void
513 tzsetwall(void)
514 {
515 +#ifdef NOTIFY_TZ_DEBUG
516 + NOTIFY_TZ_PRINTF("tzsetwall called\n");
517 +#endif /* NOTIFY_TZ_DEBUG */
518 _MUTEX_LOCK(&lcl_mutex);
519 tzsetwall_basic();
520 _MUTEX_UNLOCK(&lcl_mutex);
521 }
522
523 -static void
524 +__private_extern__ void
525 tzset_basic(void)
526 {
527 const char * name;
528 @@ -988,8 +1273,18 @@ tzset_basic(void)
529 return;
530 }
531
532 +#ifdef NOTIFY_TZ
533 + notify_check_tz(&lcl_notify);
534 +#endif /* NOTIFY_TZ */
535 +#ifdef NOTIFY_TZ_DEBUG
536 + if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0) {
537 + NOTIFY_TZ_PRINTF("tzset_basic matched %s\n", lcl_TZname);
538 + return;
539 + }
540 +#else /* ! NOTIFY_TZ_DEBUG */
541 if (lcl_is_set > 0 && strcmp(lcl_TZname, name) == 0)
542 return;
543 +#endif /* NOTIFY_TZ_DEBUG */
544 lcl_is_set = strlen(name) < sizeof lcl_TZname;
545 if (lcl_is_set)
546 (void) strcpy(lcl_TZname, name);
547 @@ -1014,15 +1309,25 @@ tzset_basic(void)
548 lclptr->ttis[0].tt_gmtoff = 0;
549 lclptr->ttis[0].tt_abbrind = 0;
550 (void) strcpy(lclptr->chars, gmt);
551 +#ifdef NOTIFY_TZ
552 + if (fullname)
553 + *fullname = 0;
554 +#endif /* NOTIFY_TZ */
555 } else if (tzload(name, lclptr) != 0)
556 if (name[0] == ':' || tzparse(name, lclptr, FALSE) != 0)
557 (void) gmtload(lclptr);
558 +#ifdef NOTIFY_TZ
559 + notify_register_tz(fullname, &lcl_notify);
560 +#endif /* NOTIFY_TZ */
561 settzname();
562 }
563
564 void
565 tzset(void)
566 {
567 +#ifdef NOTIFY_TZ_DEBUG
568 + NOTIFY_TZ_PRINTF("tzset called TZ=%s\n", getenv("TZ"));
569 +#endif /* NOTIFY_TZ_DEBUG */
570 _MUTEX_LOCK(&lcl_mutex);
571 tzset_basic();
572 _MUTEX_UNLOCK(&lcl_mutex);
573 @@ -1038,7 +1343,11 @@ tzset(void)
574 */
575
576 /*ARGSUSED*/
577 -static void
578 +#ifdef __LP64__
579 +__private_extern__ struct tm *
580 +#else /* !__LP64__ */
581 +__private_extern__ void
582 +#endif /* __LP64__ */
583 localsub(timep, offset, tmp)
584 const time_t * const timep;
585 const long offset;
586 @@ -1049,11 +1358,18 @@ struct tm * const tmp;
587 int i;
588 const time_t t = *timep;
589
590 +#ifdef NOTIFY_TZ_DEBUG
591 + NOTIFY_TZ_PRINTF("localsub called\n");
592 +#endif /* NOTIFY_TZ_DEBUG */
593 sp = lclptr;
594 #ifdef ALL_STATE
595 if (sp == NULL) {
596 +#ifdef __LP64__
597 + return gmtsub(timep, offset, tmp);
598 +#else /* !__LP64__ */
599 gmtsub(timep, offset, tmp);
600 return;
601 +#endif /* __LP64__ */
602 }
603 #endif /* defined ALL_STATE */
604 if (sp->timecnt == 0 || t < sp->ats[0]) {
605 @@ -1076,12 +1392,20 @@ struct tm * const tmp;
606 ** t += ttisp->tt_gmtoff;
607 ** timesub(&t, 0L, sp, tmp);
608 */
609 +#ifdef __LP64__
610 + if (timesub(&t, ttisp->tt_gmtoff, sp, tmp) == NULL)
611 + return NULL;
612 +#else /* !__LP64__ */
613 timesub(&t, ttisp->tt_gmtoff, sp, tmp);
614 +#endif /* __LP64__ */
615 tmp->tm_isdst = ttisp->tt_isdst;
616 tzname[tmp->tm_isdst] = &sp->chars[ttisp->tt_abbrind];
617 #ifdef TM_ZONE
618 tmp->TM_ZONE = &sp->chars[ttisp->tt_abbrind];
619 #endif /* defined TM_ZONE */
620 +#ifdef __LP64__
621 + return tmp;
622 +#endif /* __LP64__ */
623 }
624
625 struct tm *
626 @@ -1094,8 +1418,9 @@ const time_t * const timep;
627
628 if (__isthreaded != 0) {
629 _pthread_mutex_lock(&localtime_mutex);
630 - if (localtime_key < 0) {
631 - if (_pthread_key_create(&localtime_key, free) < 0) {
632 + if (localtime_key == (pthread_key_t)-1) {
633 + localtime_key = __LIBC_PTHREAD_KEY_LOCALTIME;
634 + if (pthread_key_init_np(localtime_key, free) < 0) {
635 _pthread_mutex_unlock(&localtime_mutex);
636 return(NULL);
637 }
638 @@ -1110,13 +1435,21 @@ const time_t * const timep;
639 }
640 _pthread_mutex_lock(&lcl_mutex);
641 tzset_basic();
642 +#ifdef __LP64__
643 + p_tm = localsub(timep, 0L, p_tm);
644 +#else /* !__LP64__ */
645 localsub(timep, 0L, p_tm);
646 +#endif /* __LP64__ */
647 _pthread_mutex_unlock(&lcl_mutex);
648 return(p_tm);
649 } else {
650 tzset_basic();
651 +#ifdef __LP64__
652 + return localsub(timep, 0L, &tm);
653 +#else /* !__LP64__ */
654 localsub(timep, 0L, &tm);
655 return(&tm);
656 +#endif /* __LP64__ */
657 }
658 }
659
660 @@ -1125,13 +1458,15 @@ const time_t * const timep;
661 */
662
663 struct tm *
664 -localtime_r(timep, tm)
665 -const time_t * const timep;
666 -struct tm * tm;
667 +localtime_r(const time_t * const __restrict timep, struct tm * __restrict tm)
668 {
669 _MUTEX_LOCK(&lcl_mutex);
670 tzset_basic();
671 +#ifdef __LP64__
672 + tm = localsub(timep, 0L, tm);
673 +#else /* !__LP64__ */
674 localsub(timep, 0L, tm);
675 +#endif /* __LP64__ */
676 _MUTEX_UNLOCK(&lcl_mutex);
677 return tm;
678 }
679 @@ -1140,23 +1475,48 @@ struct tm * tm;
680 ** gmtsub is to gmtime as localsub is to localtime.
681 */
682
683 +#ifdef __LP64__
684 +static struct tm *
685 +#else /* !__LP64__ */
686 static void
687 +#endif /* __LP64__ */
688 gmtsub(timep, offset, tmp)
689 const time_t * const timep;
690 const long offset;
691 struct tm * const tmp;
692 {
693 +#ifdef NOTIFY_TZ_DEBUG
694 + NOTIFY_TZ_PRINTF("gmtsub called\n");
695 +#endif /* NOTIFY_TZ_DEBUG */
696 _MUTEX_LOCK(&gmt_mutex);
697 +#ifdef NOTIFY_TZ
698 + notify_check_tz(&gmt_notify);
699 +#endif /* NOTIFY_TZ */
700 if (!gmt_is_set) {
701 gmt_is_set = TRUE;
702 #ifdef ALL_STATE
703 - gmtptr = (struct state *) malloc(sizeof *gmtptr);
704 +#ifdef NOTIFY_TZ
705 + if (gmtptr == NULL)
706 +#endif /* NOTIFY_TZ */
707 + gmtptr = (struct state *) malloc(sizeof *gmtptr);
708 if (gmtptr != NULL)
709 +#ifdef NOTIFY_TZ
710 + {
711 +#endif /* NOTIFY_TZ */
712 #endif /* defined ALL_STATE */
713 gmtload(gmtptr);
714 +#ifdef NOTIFY_TZ
715 + notify_register_tz(fullname, &gmt_notify);
716 + }
717 +#endif /* NOTIFY_TZ */
718 }
719 _MUTEX_UNLOCK(&gmt_mutex);
720 +#ifdef __LP64__
721 + if(timesub(timep, offset, gmtptr, tmp) == NULL)
722 + return NULL;
723 +#else /* !__LP64__ */
724 timesub(timep, offset, gmtptr, tmp);
725 +#endif /* __LP64__ */
726 #ifdef TM_ZONE
727 /*
728 ** Could get fancy here and deliver something such as
729 @@ -1168,7 +1528,7 @@ struct tm * const tmp;
730 else {
731 #ifdef ALL_STATE
732 if (gmtptr == NULL)
733 - tmp->TM_ZONE = gmt;
734 + tmp->TM_ZONE = (char *)gmt;
735 else tmp->TM_ZONE = gmtptr->chars;
736 #endif /* defined ALL_STATE */
737 #ifndef ALL_STATE
738 @@ -1176,6 +1536,9 @@ struct tm * const tmp;
739 #endif /* State Farm */
740 }
741 #endif /* defined TM_ZONE */
742 +#ifdef __LP64__
743 + return tmp;
744 +#endif /* __LP64__ */
745 }
746
747 struct tm *
748 @@ -1186,10 +1549,12 @@ const time_t * const timep;
749 static pthread_key_t gmtime_key = -1;
750 struct tm *p_tm;
751
752 +
753 if (__isthreaded != 0) {
754 _pthread_mutex_lock(&gmtime_mutex);
755 - if (gmtime_key < 0) {
756 - if (_pthread_key_create(&gmtime_key, free) < 0) {
757 + if (gmtime_key == (pthread_key_t)-1) {
758 + gmtime_key = __LIBC_PTHREAD_KEY_GMTIME;
759 + if (pthread_key_init_np(gmtime_key, free) < 0) {
760 _pthread_mutex_unlock(&gmtime_mutex);
761 return(NULL);
762 }
763 @@ -1206,12 +1571,20 @@ const time_t * const timep;
764 }
765 _pthread_setspecific(gmtime_key, p_tm);
766 }
767 +#ifdef __LP64__
768 + return gmtsub(timep, 0L, p_tm);
769 +#else /* !__LP64__ */
770 gmtsub(timep, 0L, p_tm);
771 return(p_tm);
772 +#endif /* __LP64__ */
773 }
774 else {
775 +#ifdef __LP64__
776 + return gmtsub(timep, 0L, &tm);
777 +#else /* !__LP64__ */
778 gmtsub(timep, 0L, &tm);
779 return(&tm);
780 +#endif /* __LP64__ */
781 }
782 }
783
784 @@ -1224,8 +1597,13 @@ gmtime_r(timep, tm)
785 const time_t * const timep;
786 struct tm * tm;
787 {
788 +
789 +#ifdef __LP64__
790 + return gmtsub(timep, 0L, tm);
791 +#else /* !__LP64__ */
792 gmtsub(timep, 0L, tm);
793 return tm;
794 +#endif /* __LP64__ */
795 }
796
797 #ifdef STD_INSPIRED
798 @@ -1235,13 +1613,21 @@ offtime(timep, offset)
799 const time_t * const timep;
800 const long offset;
801 {
802 +#ifdef __LP64__
803 + return gmtsub(timep, offset, &tm);
804 +#else /* !__LP64__ */
805 gmtsub(timep, offset, &tm);
806 return &tm;
807 +#endif /* __LP64__ */
808 }
809
810 #endif /* defined STD_INSPIRED */
811
812 +#ifdef __LP64__
813 +static struct tm *
814 +#else /* !__LP64__ */
815 static void
816 +#endif /* __LP64__ */
817 timesub(timep, offset, sp, tmp)
818 const time_t * const timep;
819 const long offset;
820 @@ -1330,7 +1716,16 @@ struct tm * const tmp;
821 LEAPS_THRU_END_OF(y - 1);
822 y = newy;
823 }
824 +#ifdef __LP64__
825 + y -= TM_YEAR_BASE;
826 + if (y < INT_MIN || y > INT_MAX) {
827 + errno = EOVERFLOW;
828 + return NULL;
829 + }
830 + tmp->tm_year = y;
831 +#else /* !__LP64__ */
832 tmp->tm_year = y - TM_YEAR_BASE;
833 +#endif /* __LP64__ */
834 tmp->tm_yday = (int) days;
835 ip = mon_lengths[yleap];
836 for (tmp->tm_mon = 0; days >= (long) ip[tmp->tm_mon]; ++(tmp->tm_mon))
837 @@ -1340,6 +1735,9 @@ struct tm * const tmp;
838 #ifdef TM_GMTOFF
839 tmp->TM_GMTOFF = offset;
840 #endif /* defined TM_GMTOFF */
841 +#ifdef __LP64__
842 + return tmp;
843 +#endif /* __LP64__ */
844 }
845
846 char *
847 @@ -1352,7 +1750,20 @@ const time_t * const timep;
848 ** to local time in the form of a string. It is equivalent to
849 ** asctime(localtime(timer))
850 */
851 +#ifdef __LP64__
852 + /*
853 + * In 64-bit, the timep value may produce a time value with a year
854 + * that exceeds 32-bits in size (won't fit in struct tm), so localtime
855 + * will return NULL.
856 + */
857 + struct tm *tm = localtime(timep);
858 +
859 + if (tm == NULL)
860 + return NULL;
861 + return asctime(tm);
862 +#else /* !__LP64__ */
863 return asctime(localtime(timep));
864 +#endif /* __LP64__ */
865 }
866
867 char *
868 @@ -1362,7 +1773,18 @@ char * buf;
869 {
870 struct tm tm;
871
872 +#ifdef __LP64__
873 + /*
874 + * In 64-bit, the timep value may produce a time value with a year
875 + * that exceeds 32-bits in size (won't fit in struct tm), so localtime_r
876 + * will return NULL.
877 + */
878 + if (localtime_r(timep, &tm) == NULL)
879 + return NULL;
880 + return asctime_r(&tm, buf);
881 +#else /* !__LP64__ */
882 return asctime_r(localtime_r(timep, &tm), buf);
883 +#endif /* __LP64__ */
884 }
885
886 /*
887 @@ -1427,12 +1849,17 @@ const struct tm * const btmp;
888 }
889
890 static time_t
891 -time2sub(tmp, funcp, offset, okayp, do_norm_secs)
892 +time2sub(tmp, funcp, offset, okayp, do_norm_secs, unix03)
893 struct tm * const tmp;
894 +#ifdef __LP64__
895 +struct tm *(* const funcp)(const time_t*, long, struct tm*);
896 +#else /* !__LP64__ */
897 void (* const funcp)(const time_t*, long, struct tm*);
898 +#endif /* __LP64__ */
899 const long offset;
900 int * const okayp;
901 const int do_norm_secs;
902 +int unix03;
903 {
904 const struct state * sp;
905 int dir;
906 @@ -1442,6 +1869,9 @@ const int do_norm_secs;
907 time_t newt;
908 time_t t;
909 struct tm yourtm, mytm;
910 +#ifdef __LP64__
911 + long year, il;
912 +#endif /* __LP64__ */
913
914 *okayp = FALSE;
915 yourtm = *tmp;
916 @@ -1460,33 +1890,64 @@ const int do_norm_secs;
917 ** Turn yourtm.tm_year into an actual year number for now.
918 ** It is converted back to an offset from TM_YEAR_BASE later.
919 */
920 +#ifdef __LP64__
921 + year = (long)yourtm.tm_year + TM_YEAR_BASE;
922 +#else /* !__LP64__ */
923 if (increment_overflow(&yourtm.tm_year, TM_YEAR_BASE))
924 return WRONG;
925 +#endif /* __LP64__ */
926 while (yourtm.tm_mday <= 0) {
927 +#ifdef __LP64__
928 + year--;
929 + il = year + (1 < yourtm.tm_mon);
930 + yourtm.tm_mday += year_lengths[isleap(il)];
931 +#else /* !__LP64__ */
932 if (increment_overflow(&yourtm.tm_year, -1))
933 return WRONG;
934 i = yourtm.tm_year + (1 < yourtm.tm_mon);
935 yourtm.tm_mday += year_lengths[isleap(i)];
936 +#endif /* __LP64__ */
937 }
938 while (yourtm.tm_mday > DAYSPERLYEAR) {
939 +#ifdef __LP64__
940 + il = year + (1 < yourtm.tm_mon);
941 + yourtm.tm_mday -= year_lengths[isleap(il)];
942 + year++;
943 +#else /* !__LP64__ */
944 i = yourtm.tm_year + (1 < yourtm.tm_mon);
945 yourtm.tm_mday -= year_lengths[isleap(i)];
946 if (increment_overflow(&yourtm.tm_year, 1))
947 return WRONG;
948 +#endif /* __LP64__ */
949 }
950 for ( ; ; ) {
951 +#ifdef __LP64__
952 + i = mon_lengths[isleap(year)][yourtm.tm_mon];
953 +#else /* !__LP64__ */
954 i = mon_lengths[isleap(yourtm.tm_year)][yourtm.tm_mon];
955 +#endif /* __LP64__ */
956 if (yourtm.tm_mday <= i)
957 break;
958 yourtm.tm_mday -= i;
959 if (++yourtm.tm_mon >= MONSPERYEAR) {
960 yourtm.tm_mon = 0;
961 +#ifdef __LP64__
962 + year++;
963 +#else /* !__LP64__ */
964 if (increment_overflow(&yourtm.tm_year, 1))
965 return WRONG;
966 +#endif /* __LP64__ */
967 }
968 }
969 +#ifdef __LP64__
970 + year -= TM_YEAR_BASE;
971 + if (year > INT_MAX || year < INT_MIN)
972 + return WRONG;
973 + yourtm.tm_year = year;
974 +#else /* !__LP64__ */
975 if (increment_overflow(&yourtm.tm_year, -TM_YEAR_BASE))
976 return WRONG;
977 +#endif /* __LP64__ */
978 /* Don't go below 1900 for POLA */
979 if (yourtm.tm_year < 0)
980 return WRONG;
981 @@ -1513,7 +1974,13 @@ const int do_norm_secs;
982 ** Divide the search space in half
983 ** (this works whether time_t is signed or unsigned).
984 */
985 +#ifdef __LP64__
986 + /* optimization: see if the value is 31-bit (signed) */
987 + t = (((time_t) 1) << (TYPE_BIT(int) - 1)) - 1;
988 + bits = ((*funcp)(&t, offset, &mytm) == NULL || tmcomp(&mytm, &yourtm) < 0) ? TYPE_BIT(time_t) - 1 : TYPE_BIT(int) - 1;
989 +#else /* !__LP64__ */
990 bits = TYPE_BIT(time_t) - 1;
991 +#endif /* __LP64__ */
992 /*
993 ** If we have more than this, we will overflow tm_year for tmcomp().
994 ** We should really return an error if we cannot represent it.
995 @@ -1527,8 +1994,19 @@ const int do_norm_secs;
996 */
997 t = TYPE_SIGNED(time_t) ? 0 : (((time_t) 1) << bits);
998 for ( ; ; ) {
999 +#ifdef __LP64__
1000 + if ((*funcp)(&t, offset, &mytm) == NULL) {
1001 + /* we overflowed, so t is too big */
1002 + dir = 1;
1003 + goto skip_tmcomp;
1004 + }
1005 +#else /* !__LP64__ */
1006 (*funcp)(&t, offset, &mytm);
1007 +#endif /* __LP64__ */
1008 dir = tmcomp(&mytm, &yourtm);
1009 +#ifdef __LP64__
1010 +skip_tmcomp:
1011 +#endif /* __LP64__ */
1012 if (dir != 0) {
1013 if (bits-- < 0)
1014 return WRONG;
1015 @@ -1539,6 +2017,9 @@ const int do_norm_secs;
1016 else t += ((time_t) 1) << bits;
1017 continue;
1018 }
1019 + sp = (funcp == localsub) ? lclptr : gmtptr;
1020 + if (unix03 && sp->typecnt == 1 && yourtm.tm_isdst > 0)
1021 + yourtm.tm_isdst = 0; /* alternative time does not apply */
1022 if (yourtm.tm_isdst < 0 || mytm.tm_isdst == yourtm.tm_isdst)
1023 break;
1024 /*
1025 @@ -1547,7 +2028,6 @@ const int do_norm_secs;
1026 ** It's okay to guess wrong since the guess
1027 ** gets checked.
1028 */
1029 - sp = (funcp == localsub) ? lclptr : gmtptr;
1030 #ifdef ALL_STATE
1031 if (sp == NULL)
1032 return WRONG;
1033 @@ -1560,7 +2040,12 @@ const int do_norm_secs;
1034 continue;
1035 newt = t + sp->ttis[j].tt_gmtoff -
1036 sp->ttis[i].tt_gmtoff;
1037 +#ifdef __LP64__
1038 + if ((*funcp)(&newt, offset, &mytm) == NULL)
1039 + return WRONG;
1040 +#else /* !__LP64__ */
1041 (*funcp)(&newt, offset, &mytm);
1042 +#endif /* __LP64__ */
1043 if (tmcomp(&mytm, &yourtm) != 0)
1044 continue;
1045 if (mytm.tm_isdst != yourtm.tm_isdst)
1046 @@ -1579,17 +2064,27 @@ label:
1047 if ((newt < t) != (saved_seconds < 0))
1048 return WRONG;
1049 t = newt;
1050 +#ifdef __LP64__
1051 + if ((*funcp)(&t, offset, tmp) == NULL)
1052 + return WRONG;
1053 +#else /* !__LP64__ */
1054 (*funcp)(&t, offset, tmp);
1055 +#endif /* __LP64__ */
1056 *okayp = TRUE;
1057 return t;
1058 }
1059
1060 static time_t
1061 -time2(tmp, funcp, offset, okayp)
1062 +time2(tmp, funcp, offset, okayp, unix03)
1063 struct tm * const tmp;
1064 +#ifdef __LP64__
1065 +struct tm *(* const funcp)(const time_t*, long, struct tm*);
1066 +#else /* !__LP64__ */
1067 void (* const funcp)(const time_t*, long, struct tm*);
1068 +#endif /* __LP64__ */
1069 const long offset;
1070 int * const okayp;
1071 +int unix03;
1072 {
1073 time_t t;
1074
1075 @@ -1598,15 +2093,20 @@ int * const okayp;
1076 ** (in case tm_sec contains a value associated with a leap second).
1077 ** If that fails, try with normalization of seconds.
1078 */
1079 - t = time2sub(tmp, funcp, offset, okayp, FALSE);
1080 - return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE);
1081 + t = time2sub(tmp, funcp, offset, okayp, FALSE, unix03);
1082 + return *okayp ? t : time2sub(tmp, funcp, offset, okayp, TRUE, unix03);
1083 }
1084
1085 -static time_t
1086 -time1(tmp, funcp, offset)
1087 +__private_extern__ time_t
1088 +time1(tmp, funcp, offset, unix03)
1089 struct tm * const tmp;
1090 +#ifdef __LP64__
1091 +struct tm *(* const funcp)(const time_t *, long, struct tm *);
1092 +#else /* !__LP64__ */
1093 void (* const funcp)(const time_t *, long, struct tm *);
1094 +#endif /* __LP64__ */
1095 const long offset;
1096 +int unix03;
1097 {
1098 time_t t;
1099 const struct state * sp;
1100 @@ -1620,7 +2120,7 @@ const long offset;
1101
1102 if (tmp->tm_isdst > 1)
1103 tmp->tm_isdst = 1;
1104 - t = time2(tmp, funcp, offset, &okay);
1105 + t = time2(tmp, funcp, offset, &okay, unix03);
1106 #ifdef PCTS
1107 /*
1108 ** PCTS code courtesy Grant Sullivan (grant@osf.org).
1109 @@ -1664,7 +2164,7 @@ const long offset;
1110 tmp->tm_sec += sp->ttis[otheri].tt_gmtoff -
1111 sp->ttis[samei].tt_gmtoff;
1112 tmp->tm_isdst = !tmp->tm_isdst;
1113 - t = time2(tmp, funcp, offset, &okay);
1114 + t = time2(tmp, funcp, offset, &okay, unix03);
1115 if (okay)
1116 return t;
1117 tmp->tm_sec -= sp->ttis[otheri].tt_gmtoff -
1118 @@ -1674,19 +2174,25 @@ const long offset;
1119 }
1120 return WRONG;
1121 }
1122 +#else /* BUILDING_VARIANT */
1123 +__private_extern__ pthread_mutex_t lcl_mutex;
1124 +#endif /* BUILDING_VARIANT */
1125
1126 time_t
1127 mktime(tmp)
1128 struct tm * const tmp;
1129 {
1130 time_t mktime_return_value;
1131 + int serrno = errno;
1132 _MUTEX_LOCK(&lcl_mutex);
1133 tzset_basic();
1134 - mktime_return_value = time1(tmp, localsub, 0L);
1135 + mktime_return_value = time1(tmp, localsub, 0L, __DARWIN_UNIX03);
1136 _MUTEX_UNLOCK(&lcl_mutex);
1137 + errno = serrno;
1138 return(mktime_return_value);
1139 }
1140
1141 +#if !BUILDING_VARIANT
1142 #ifdef STD_INSPIRED
1143
1144 time_t
1145 @@ -1702,7 +2208,7 @@ timegm(tmp)
1146 struct tm * const tmp;
1147 {
1148 tmp->tm_isdst = 0;
1149 - return time1(tmp, gmtsub, 0L);
1150 + return time1(tmp, gmtsub, 0L, __DARWIN_UNIX03);
1151 }
1152
1153 time_t
1154 @@ -1711,7 +2217,7 @@ struct tm * const tmp;
1155 const long offset;
1156 {
1157 tmp->tm_isdst = 0;
1158 - return time1(tmp, gmtsub, offset);
1159 + return time1(tmp, gmtsub, offset, __DARWIN_UNIX03);
1160 }
1161
1162 #endif /* defined STD_INSPIRED */
1163 @@ -1811,3 +2317,4 @@ time_t t;
1164 }
1165
1166 #endif /* defined STD_INSPIRED */
1167 +#endif /* !BUILDING_VARIANT */