Add 16922 to list of bugs fixed.
[glibc.git] / time / tzset.c
blob77bfde9fb1f3595a0ad4536a3fa03684474bf148
1 /* Copyright (C) 1991-2014 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
18 #include <ctype.h>
19 #include <errno.h>
20 #include <bits/libc-lock.h>
21 #include <stddef.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
28 #define NOID
29 #include <timezone/tzfile.h>
31 char *__tzname[2] = { (char *) "GMT", (char *) "GMT" };
32 int __daylight = 0;
33 long int __timezone = 0L;
35 weak_alias (__tzname, tzname)
36 weak_alias (__daylight, daylight)
37 weak_alias (__timezone, timezone)
39 /* This locks all the state variables in tzfile.c and this file. */
40 __libc_lock_define_initialized (static, tzset_lock)
43 #define min(a, b) ((a) < (b) ? (a) : (b))
44 #define max(a, b) ((a) > (b) ? (a) : (b))
45 #define sign(x) ((x) < 0 ? -1 : 1)
48 /* This structure contains all the information about a
49 timezone given in the POSIX standard TZ envariable. */
50 typedef struct
52 const char *name;
54 /* When to change. */
55 enum { J0, J1, M } type; /* Interpretation of: */
56 unsigned short int m, n, d; /* Month, week, day. */
57 int secs; /* Time of day. */
59 long int offset; /* Seconds east of GMT (west if < 0). */
61 /* We cache the computed time of change for a
62 given year so we don't have to recompute it. */
63 time_t change; /* When to change to this zone. */
64 int computed_for; /* Year above is computed for. */
65 } tz_rule;
67 /* tz_rules[0] is standard, tz_rules[1] is daylight. */
68 static tz_rule tz_rules[2];
71 static void compute_change (tz_rule *rule, int year) __THROW internal_function;
72 static void tzset_internal (int always, int explicit)
73 __THROW internal_function;
75 /* List of buffers containing time zone strings. */
76 struct tzstring_l
78 struct tzstring_l *next;
79 size_t len; /* strlen(data) - doesn't count terminating NUL! */
80 char data[0];
83 static struct tzstring_l *tzstring_list;
85 /* Allocate a permanent home for S. It will never be moved or deallocated,
86 but may share space with other strings.
87 Don't modify the returned string. */
88 char *
89 __tzstring (const char *s)
91 char *p;
92 struct tzstring_l *t, *u, *new;
93 size_t len = strlen (s);
95 /* Walk the list and look for a match. If this string is the same
96 as the end of an already-allocated string, it can share space. */
97 for (u = t = tzstring_list; t; u = t, t = t->next)
98 if (len <= t->len)
100 p = &t->data[t->len - len];
101 if (strcmp (s, p) == 0)
102 return p;
105 /* Not found; allocate a new buffer. */
106 new = malloc (sizeof (struct tzstring_l) + len + 1);
107 if (!new)
108 return NULL;
110 new->next = NULL;
111 new->len = len;
112 strcpy (new->data, s);
114 if (u)
115 u->next = new;
116 else
117 tzstring_list = new;
119 return new->data;
122 /* Maximum length of a timezone name. tzset_internal keeps this up to date
123 (never decreasing it) when ! __use_tzfile.
124 tzfile.c keeps it up to date when __use_tzfile. */
125 size_t __tzname_cur_max;
127 long int
128 __tzname_max (void)
130 __libc_lock_lock (tzset_lock);
132 tzset_internal (0, 0);
134 __libc_lock_unlock (tzset_lock);
136 return __tzname_cur_max;
139 static char *old_tz;
141 static void
142 internal_function
143 update_vars (void)
145 __daylight = tz_rules[0].offset != tz_rules[1].offset;
146 __timezone = -tz_rules[0].offset;
147 __tzname[0] = (char *) tz_rules[0].name;
148 __tzname[1] = (char *) tz_rules[1].name;
150 /* Keep __tzname_cur_max up to date. */
151 size_t len0 = strlen (__tzname[0]);
152 size_t len1 = strlen (__tzname[1]);
153 if (len0 > __tzname_cur_max)
154 __tzname_cur_max = len0;
155 if (len1 > __tzname_cur_max)
156 __tzname_cur_max = len1;
160 static unsigned int
161 __attribute_noinline__
162 compute_offset (unsigned int ss, unsigned int mm, unsigned int hh)
164 return min (ss, 59) + min (mm, 59) * 60 + min (hh, 24) * 60 * 60;
168 /* Parse the POSIX TZ-style string. */
169 void
170 __tzset_parse_tz (tz)
171 const char *tz;
173 unsigned short int hh, mm, ss;
175 /* Clear out old state and reset to unnamed UTC. */
176 memset (tz_rules, '\0', sizeof tz_rules);
177 tz_rules[0].name = tz_rules[1].name = "";
179 /* Get the standard timezone name. */
180 char *tzbuf = strdupa (tz);
182 int consumed;
183 if (sscanf (tz, "%[A-Za-z]%n", tzbuf, &consumed) != 1)
185 /* Check for the quoted version. */
186 char *wp = tzbuf;
187 if (__glibc_unlikely (*tz++ != '<'))
188 goto out;
190 while (isalnum (*tz) || *tz == '+' || *tz == '-')
191 *wp++ = *tz++;
192 if (__glibc_unlikely (*tz++ != '>' || wp - tzbuf < 3))
193 goto out;
194 *wp = '\0';
196 else if (__glibc_unlikely (consumed < 3))
197 goto out;
198 else
199 tz += consumed;
201 tz_rules[0].name = __tzstring (tzbuf);
203 /* Figure out the standard offset from UTC. */
204 if (*tz == '\0' || (*tz != '+' && *tz != '-' && !isdigit (*tz)))
205 goto out;
207 if (*tz == '-' || *tz == '+')
208 tz_rules[0].offset = *tz++ == '-' ? 1L : -1L;
209 else
210 tz_rules[0].offset = -1L;
211 switch (sscanf (tz, "%hu%n:%hu%n:%hu%n",
212 &hh, &consumed, &mm, &consumed, &ss, &consumed))
214 default:
215 tz_rules[0].offset = 0;
216 goto out;
217 case 1:
218 mm = 0;
219 case 2:
220 ss = 0;
221 case 3:
222 break;
224 tz_rules[0].offset *= compute_offset (ss, mm, hh);
225 tz += consumed;
227 /* Get the DST timezone name (if any). */
228 if (*tz != '\0')
230 if (sscanf (tz, "%[A-Za-z]%n", tzbuf, &consumed) != 1)
232 /* Check for the quoted version. */
233 char *wp = tzbuf;
234 const char *rp = tz;
235 if (__glibc_unlikely (*rp++ != '<'))
236 /* Punt on name, set up the offsets. */
237 goto done_names;
239 while (isalnum (*rp) || *rp == '+' || *rp == '-')
240 *wp++ = *rp++;
241 if (__glibc_unlikely (*rp++ != '>' || wp - tzbuf < 3))
242 /* Punt on name, set up the offsets. */
243 goto done_names;
244 *wp = '\0';
245 tz = rp;
247 else if (__glibc_unlikely (consumed < 3))
248 /* Punt on name, set up the offsets. */
249 goto done_names;
250 else
251 tz += consumed;
253 tz_rules[1].name = __tzstring (tzbuf);
255 /* Figure out the DST offset from GMT. */
256 if (*tz == '-' || *tz == '+')
257 tz_rules[1].offset = *tz++ == '-' ? 1L : -1L;
258 else
259 tz_rules[1].offset = -1L;
261 switch (sscanf (tz, "%hu%n:%hu%n:%hu%n",
262 &hh, &consumed, &mm, &consumed, &ss, &consumed))
264 default:
265 /* Default to one hour later than standard time. */
266 tz_rules[1].offset = tz_rules[0].offset + (60 * 60);
267 break;
269 case 1:
270 mm = 0;
271 case 2:
272 ss = 0;
273 case 3:
274 tz_rules[1].offset *= compute_offset (ss, mm, hh);
275 tz += consumed;
276 break;
278 if (*tz == '\0' || (tz[0] == ',' && tz[1] == '\0'))
280 /* There is no rule. See if there is a default rule file. */
281 __tzfile_default (tz_rules[0].name, tz_rules[1].name,
282 tz_rules[0].offset, tz_rules[1].offset);
283 if (__use_tzfile)
285 free (old_tz);
286 old_tz = NULL;
287 return;
291 else
293 /* There is no DST. */
294 tz_rules[1].name = tz_rules[0].name;
295 tz_rules[1].offset = tz_rules[0].offset;
296 goto out;
299 done_names:
300 /* Figure out the standard <-> DST rules. */
301 for (unsigned int whichrule = 0; whichrule < 2; ++whichrule)
303 tz_rule *tzr = &tz_rules[whichrule];
305 /* Ignore comma to support string following the incorrect
306 specification in early POSIX.1 printings. */
307 tz += *tz == ',';
309 /* Get the date of the change. */
310 if (*tz == 'J' || isdigit (*tz))
312 char *end;
313 tzr->type = *tz == 'J' ? J1 : J0;
314 if (tzr->type == J1 && !isdigit (*++tz))
315 goto out;
316 unsigned long int d = strtoul (tz, &end, 10);
317 if (end == tz || d > 365)
318 goto out;
319 if (tzr->type == J1 && d == 0)
320 goto out;
321 tzr->d = d;
322 tz = end;
324 else if (*tz == 'M')
326 tzr->type = M;
327 if (sscanf (tz, "M%hu.%hu.%hu%n",
328 &tzr->m, &tzr->n, &tzr->d, &consumed) != 3
329 || tzr->m < 1 || tzr->m > 12
330 || tzr->n < 1 || tzr->n > 5 || tzr->d > 6)
331 goto out;
332 tz += consumed;
334 else if (*tz == '\0')
336 /* Daylight time rules in the U.S. are defined in the
337 U.S. Code, Title 15, Chapter 6, Subchapter IX - Standard
338 Time. These dates were established by Congress in the
339 Energy Policy Act of 2005 [Pub. L. no. 109-58, 119 Stat 594
340 (2005)].
341 Below is the equivalent of "M3.2.0,M11.1.0" [/2 not needed
342 since 2:00AM is the default]. */
343 tzr->type = M;
344 if (tzr == &tz_rules[0])
346 tzr->m = 3;
347 tzr->n = 2;
348 tzr->d = 0;
350 else
352 tzr->m = 11;
353 tzr->n = 1;
354 tzr->d = 0;
357 else
358 goto out;
360 if (*tz != '\0' && *tz != '/' && *tz != ',')
361 goto out;
362 else if (*tz == '/')
364 /* Get the time of day of the change. */
365 int negative;
366 ++tz;
367 if (*tz == '\0')
368 goto out;
369 negative = *tz == '-';
370 tz += negative;
371 consumed = 0;
372 switch (sscanf (tz, "%hu%n:%hu%n:%hu%n",
373 &hh, &consumed, &mm, &consumed, &ss, &consumed))
375 default:
376 hh = 2; /* Default to 2:00 AM. */
377 case 1:
378 mm = 0;
379 case 2:
380 ss = 0;
381 case 3:
382 break;
384 tz += consumed;
385 tzr->secs = (negative ? -1 : 1) * ((hh * 60 * 60) + (mm * 60) + ss);
387 else
388 /* Default to 2:00 AM. */
389 tzr->secs = 2 * 60 * 60;
391 tzr->computed_for = -1;
394 out:
395 update_vars ();
398 /* Interpret the TZ envariable. */
399 static void
400 internal_function
401 tzset_internal (always, explicit)
402 int always;
403 int explicit;
405 static int is_initialized;
406 const char *tz;
408 if (is_initialized && !always)
409 return;
410 is_initialized = 1;
412 /* Examine the TZ environment variable. */
413 tz = getenv ("TZ");
414 if (tz == NULL && !explicit)
415 /* Use the site-wide default. This is a file name which means we
416 would not see changes to the file if we compare only the file
417 name for change. We want to notice file changes if tzset() has
418 been called explicitly. Leave TZ as NULL in this case. */
419 tz = TZDEFAULT;
420 if (tz && *tz == '\0')
421 /* User specified the empty string; use UTC explicitly. */
422 tz = "Universal";
424 /* A leading colon means "implementation defined syntax".
425 We ignore the colon and always use the same algorithm:
426 try a data file, and if none exists parse the 1003.1 syntax. */
427 if (tz && *tz == ':')
428 ++tz;
430 /* Check whether the value changed since the last run. */
431 if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
432 /* No change, simply return. */
433 return;
435 if (tz == NULL)
436 /* No user specification; use the site-wide default. */
437 tz = TZDEFAULT;
439 tz_rules[0].name = NULL;
440 tz_rules[1].name = NULL;
442 /* Save the value of `tz'. */
443 free (old_tz);
444 old_tz = tz ? __strdup (tz) : NULL;
446 /* Try to read a data file. */
447 __tzfile_read (tz, 0, NULL);
448 if (__use_tzfile)
449 return;
451 /* No data file found. Default to UTC if nothing specified. */
453 if (tz == NULL || *tz == '\0'
454 || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
456 memset (tz_rules, '\0', sizeof tz_rules);
457 tz_rules[0].name = tz_rules[1].name = "UTC";
458 if (J0 != 0)
459 tz_rules[0].type = tz_rules[1].type = J0;
460 tz_rules[0].change = tz_rules[1].change = (time_t) -1;
461 update_vars ();
462 return;
465 __tzset_parse_tz (tz);
468 /* Figure out the exact time (as a time_t) in YEAR
469 when the change described by RULE will occur and
470 put it in RULE->change, saving YEAR in RULE->computed_for. */
471 static void
472 internal_function
473 compute_change (rule, year)
474 tz_rule *rule;
475 int year;
477 time_t t;
479 if (year != -1 && rule->computed_for == year)
480 /* Operations on times in 2 BC will be slower. Oh well. */
481 return;
483 /* First set T to January 1st, 0:00:00 GMT in YEAR. */
484 if (year > 1970)
485 t = ((year - 1970) * 365
486 + /* Compute the number of leapdays between 1970 and YEAR
487 (exclusive). There is a leapday every 4th year ... */
488 + ((year - 1) / 4 - 1970 / 4)
489 /* ... except every 100th year ... */
490 - ((year - 1) / 100 - 1970 / 100)
491 /* ... but still every 400th year. */
492 + ((year - 1) / 400 - 1970 / 400)) * SECSPERDAY;
493 else
494 t = 0;
496 switch (rule->type)
498 case J1:
499 /* Jn - Julian day, 1 == January 1, 60 == March 1 even in leap years.
500 In non-leap years, or if the day number is 59 or less, just
501 add SECSPERDAY times the day number-1 to the time of
502 January 1, midnight, to get the day. */
503 t += (rule->d - 1) * SECSPERDAY;
504 if (rule->d >= 60 && __isleap (year))
505 t += SECSPERDAY;
506 break;
508 case J0:
509 /* n - Day of year.
510 Just add SECSPERDAY times the day number to the time of Jan 1st. */
511 t += rule->d * SECSPERDAY;
512 break;
514 case M:
515 /* Mm.n.d - Nth "Dth day" of month M. */
517 unsigned int i;
518 int d, m1, yy0, yy1, yy2, dow;
519 const unsigned short int *myday =
520 &__mon_yday[__isleap (year)][rule->m];
522 /* First add SECSPERDAY for each day in months before M. */
523 t += myday[-1] * SECSPERDAY;
525 /* Use Zeller's Congruence to get day-of-week of first day of month. */
526 m1 = (rule->m + 9) % 12 + 1;
527 yy0 = (rule->m <= 2) ? (year - 1) : year;
528 yy1 = yy0 / 100;
529 yy2 = yy0 % 100;
530 dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
531 if (dow < 0)
532 dow += 7;
534 /* DOW is the day-of-week of the first day of the month. Get the
535 day-of-month (zero-origin) of the first DOW day of the month. */
536 d = rule->d - dow;
537 if (d < 0)
538 d += 7;
539 for (i = 1; i < rule->n; ++i)
541 if (d + 7 >= (int) myday[0] - myday[-1])
542 break;
543 d += 7;
546 /* D is the day-of-month (zero-origin) of the day we want. */
547 t += d * SECSPERDAY;
549 break;
552 /* T is now the Epoch-relative time of 0:00:00 GMT on the day we want.
553 Just add the time of day and local offset from GMT, and we're done. */
555 rule->change = t - rule->offset + rule->secs;
556 rule->computed_for = year;
560 /* Figure out the correct timezone for TM and set `__tzname',
561 `__timezone', and `__daylight' accordingly. */
562 void
563 internal_function
564 __tz_compute (timer, tm, use_localtime)
565 time_t timer;
566 struct tm *tm;
567 int use_localtime;
569 compute_change (&tz_rules[0], 1900 + tm->tm_year);
570 compute_change (&tz_rules[1], 1900 + tm->tm_year);
572 if (use_localtime)
574 int isdst;
576 /* We have to distinguish between northern and southern
577 hemisphere. For the latter the daylight saving time
578 ends in the next year. */
579 if (__builtin_expect (tz_rules[0].change
580 > tz_rules[1].change, 0))
581 isdst = (timer < tz_rules[1].change
582 || timer >= tz_rules[0].change);
583 else
584 isdst = (timer >= tz_rules[0].change
585 && timer < tz_rules[1].change);
586 tm->tm_isdst = isdst;
587 tm->tm_zone = __tzname[isdst];
588 tm->tm_gmtoff = tz_rules[isdst].offset;
592 /* Reinterpret the TZ environment variable and set `tzname'. */
593 #undef tzset
595 void
596 __tzset (void)
598 __libc_lock_lock (tzset_lock);
600 tzset_internal (1, 1);
602 if (!__use_tzfile)
604 /* Set `tzname'. */
605 __tzname[0] = (char *) tz_rules[0].name;
606 __tzname[1] = (char *) tz_rules[1].name;
609 __libc_lock_unlock (tzset_lock);
611 weak_alias (__tzset, tzset)
613 /* Return the `struct tm' representation of *TIMER in the local timezone.
614 Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */
615 struct tm *
616 __tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
618 long int leap_correction;
619 int leap_extra_secs;
621 if (timer == NULL)
623 __set_errno (EINVAL);
624 return NULL;
627 __libc_lock_lock (tzset_lock);
629 /* Update internal database according to current TZ setting.
630 POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
631 This is a good idea since this allows at least a bit more parallelism. */
632 tzset_internal (tp == &_tmbuf && use_localtime, 1);
634 if (__use_tzfile)
635 __tzfile_compute (*timer, use_localtime, &leap_correction,
636 &leap_extra_secs, tp);
637 else
639 if (! __offtime (timer, 0, tp))
640 tp = NULL;
641 else
642 __tz_compute (*timer, tp, use_localtime);
643 leap_correction = 0L;
644 leap_extra_secs = 0;
647 if (tp)
649 if (! use_localtime)
651 tp->tm_isdst = 0;
652 tp->tm_zone = "GMT";
653 tp->tm_gmtoff = 0L;
656 if (__offtime (timer, tp->tm_gmtoff - leap_correction, tp))
657 tp->tm_sec += leap_extra_secs;
658 else
659 tp = NULL;
662 __libc_lock_unlock (tzset_lock);
664 return tp;
668 libc_freeres_fn (free_mem)
670 while (tzstring_list != NULL)
672 struct tzstring_l *old = tzstring_list;
674 tzstring_list = tzstring_list->next;
675 free (old);
677 free (old_tz);
678 old_tz = NULL;