Get rid of lll_robust_trylock.
[platform/upstream/glibc.git] / time / tzset.c
1 /* Copyright (C) 1991-2014 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
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.
8
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.
13
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/>.  */
17
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>
26
27
28 #define NOID
29 #include <timezone/tzfile.h>
30
31 char *__tzname[2] = { (char *) "GMT", (char *) "GMT" };
32 int __daylight = 0;
33 long int __timezone = 0L;
34
35 weak_alias (__tzname, tzname)
36 weak_alias (__daylight, daylight)
37 weak_alias (__timezone, timezone)
38
39 /* This locks all the state variables in tzfile.c and this file.  */
40 __libc_lock_define_initialized (static, tzset_lock)
41
42
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)
46
47
48 /* This structure contains all the information about a
49    timezone given in the POSIX standard TZ envariable.  */
50 typedef struct
51   {
52     const char *name;
53
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.  */
58
59     long int offset;            /* Seconds east of GMT (west if < 0).  */
60
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;
66
67 /* tz_rules[0] is standard, tz_rules[1] is daylight.  */
68 static tz_rule tz_rules[2];
69
70
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;
74 \f
75 /* List of buffers containing time zone strings. */
76 struct tzstring_l
77 {
78   struct tzstring_l *next;
79   size_t len;  /* strlen(data) - doesn't count terminating NUL! */
80   char data[0];
81 };
82
83 static struct tzstring_l *tzstring_list;
84
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)
90 {
91   char *p;
92   struct tzstring_l *t, *u, *new;
93   size_t len = strlen (s);
94
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)
99       {
100         p = &t->data[t->len - len];
101         if (strcmp (s, p) == 0)
102           return p;
103       }
104
105   /* Not found; allocate a new buffer. */
106   new = malloc (sizeof (struct tzstring_l) + len + 1);
107   if (!new)
108     return NULL;
109
110   new->next = NULL;
111   new->len = len;
112   strcpy (new->data, s);
113
114   if (u)
115     u->next = new;
116   else
117     tzstring_list = new;
118
119   return new->data;
120 }
121 \f
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;
126
127 long int
128 __tzname_max (void)
129 {
130   __libc_lock_lock (tzset_lock);
131
132   tzset_internal (0, 0);
133
134   __libc_lock_unlock (tzset_lock);
135
136   return __tzname_cur_max;
137 }
138 \f
139 static char *old_tz;
140
141 static void
142 internal_function
143 update_vars (void)
144 {
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;
149
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;
157 }
158
159
160 static unsigned int
161 __attribute_noinline__
162 compute_offset (unsigned int ss, unsigned int mm, unsigned int hh)
163 {
164   return min (ss, 59) + min (mm, 59) * 60 + min (hh, 24) * 60 * 60;
165 }
166
167
168 /* Parse the POSIX TZ-style string.  */
169 void
170 __tzset_parse_tz (tz)
171      const char *tz;
172 {
173   unsigned short int hh, mm, ss;
174
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 = "";
178
179   /* Get the standard timezone name.  */
180   char *tzbuf = strdupa (tz);
181
182   int consumed;
183   if (sscanf (tz, "%[A-Za-z]%n", tzbuf, &consumed) != 1)
184     {
185       /* Check for the quoted version.  */
186       char *wp = tzbuf;
187       if (__glibc_unlikely (*tz++ != '<'))
188         goto out;
189
190       while (isalnum (*tz) || *tz == '+' || *tz == '-')
191         *wp++ = *tz++;
192       if (__glibc_unlikely (*tz++ != '>' || wp - tzbuf < 3))
193         goto out;
194       *wp = '\0';
195     }
196   else if (__glibc_unlikely (consumed < 3))
197     goto out;
198   else
199     tz += consumed;
200
201   tz_rules[0].name = __tzstring (tzbuf);
202
203   /* Figure out the standard offset from UTC.  */
204   if (*tz == '\0' || (*tz != '+' && *tz != '-' && !isdigit (*tz)))
205     goto out;
206
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))
213     {
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;
223     }
224   tz_rules[0].offset *= compute_offset (ss, mm, hh);
225   tz += consumed;
226
227   /* Get the DST timezone name (if any).  */
228   if (*tz != '\0')
229     {
230       if (sscanf (tz, "%[A-Za-z]%n", tzbuf, &consumed) != 1)
231         {
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;
238
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;
246         }
247       else if (__glibc_unlikely (consumed < 3))
248         /* Punt on name, set up the offsets.  */
249         goto done_names;
250       else
251         tz += consumed;
252
253       tz_rules[1].name = __tzstring (tzbuf);
254
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;
260
261       switch (sscanf (tz, "%hu%n:%hu%n:%hu%n",
262                       &hh, &consumed, &mm, &consumed, &ss, &consumed))
263         {
264         default:
265           /* Default to one hour later than standard time.  */
266           tz_rules[1].offset = tz_rules[0].offset + (60 * 60);
267           break;
268
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;
277         }
278       if (*tz == '\0' || (tz[0] == ',' && tz[1] == '\0'))
279         {
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)
284             {
285               free (old_tz);
286               old_tz = NULL;
287               return;
288             }
289         }
290     }
291   else
292     {
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;
297     }
298
299  done_names:
300   /* Figure out the standard <-> DST rules.  */
301   for (unsigned int whichrule = 0; whichrule < 2; ++whichrule)
302     {
303       tz_rule *tzr = &tz_rules[whichrule];
304
305       /* Ignore comma to support string following the incorrect
306          specification in early POSIX.1 printings.  */
307       tz += *tz == ',';
308
309       /* Get the date of the change.  */
310       if (*tz == 'J' || isdigit (*tz))
311         {
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;
323         }
324       else if (*tz == 'M')
325         {
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;
333         }
334       else if (*tz == '\0')
335         {
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])
345             {
346               tzr->m = 3;
347               tzr->n = 2;
348               tzr->d = 0;
349             }
350           else
351             {
352               tzr->m = 11;
353               tzr->n = 1;
354               tzr->d = 0;
355             }
356         }
357       else
358         goto out;
359
360       if (*tz != '\0' && *tz != '/' && *tz != ',')
361         goto out;
362       else if (*tz == '/')
363         {
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))
374             {
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;
383             }
384           tz += consumed;
385           tzr->secs = (negative ? -1 : 1) * ((hh * 60 * 60) + (mm * 60) + ss);
386         }
387       else
388         /* Default to 2:00 AM.  */
389         tzr->secs = 2 * 60 * 60;
390
391       tzr->computed_for = -1;
392     }
393
394  out:
395   update_vars ();
396 }
397
398 /* Interpret the TZ envariable.  */
399 static void
400 internal_function
401 tzset_internal (always, explicit)
402      int always;
403      int explicit;
404 {
405   static int is_initialized;
406   const char *tz;
407
408   if (is_initialized && !always)
409     return;
410   is_initialized = 1;
411
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";
423
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;
429
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;
434
435   if (tz == NULL)
436     /* No user specification; use the site-wide default.  */
437     tz = TZDEFAULT;
438
439   tz_rules[0].name = NULL;
440   tz_rules[1].name = NULL;
441
442   /* Save the value of `tz'.  */
443   free (old_tz);
444   old_tz = tz ? __strdup (tz) : NULL;
445
446   /* Try to read a data file.  */
447   __tzfile_read (tz, 0, NULL);
448   if (__use_tzfile)
449     return;
450
451   /* No data file found.  Default to UTC if nothing specified.  */
452
453   if (tz == NULL || *tz == '\0'
454       || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
455     {
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;
463     }
464
465   __tzset_parse_tz (tz);
466 }
467 \f
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;
476 {
477   time_t t;
478
479   if (year != -1 && rule->computed_for == year)
480     /* Operations on times in 2 BC will be slower.  Oh well.  */
481     return;
482
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;
495
496   switch (rule->type)
497     {
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;
507
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;
513
514     case M:
515       /* Mm.n.d - Nth "Dth day" of month M.  */
516       {
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];
521
522         /* First add SECSPERDAY for each day in months before M.  */
523         t += myday[-1] * SECSPERDAY;
524
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;
533
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)
540           {
541             if (d + 7 >= (int) myday[0] - myday[-1])
542               break;
543             d += 7;
544           }
545
546         /* D is the day-of-month (zero-origin) of the day we want.  */
547         t += d * SECSPERDAY;
548       }
549       break;
550     }
551
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.  */
554
555   rule->change = t - rule->offset + rule->secs;
556   rule->computed_for = year;
557 }
558
559
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;
568 {
569   compute_change (&tz_rules[0], 1900 + tm->tm_year);
570   compute_change (&tz_rules[1], 1900 + tm->tm_year);
571
572   if (use_localtime)
573     {
574       int isdst;
575
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;
589     }
590 }
591 \f
592 /* Reinterpret the TZ environment variable and set `tzname'.  */
593 #undef tzset
594
595 void
596 __tzset (void)
597 {
598   __libc_lock_lock (tzset_lock);
599
600   tzset_internal (1, 1);
601
602   if (!__use_tzfile)
603     {
604       /* Set `tzname'.  */
605       __tzname[0] = (char *) tz_rules[0].name;
606       __tzname[1] = (char *) tz_rules[1].name;
607     }
608
609   __libc_lock_unlock (tzset_lock);
610 }
611 weak_alias (__tzset, tzset)
612 \f
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)
617 {
618   long int leap_correction;
619   int leap_extra_secs;
620
621   if (timer == NULL)
622     {
623       __set_errno (EINVAL);
624       return NULL;
625     }
626
627   __libc_lock_lock (tzset_lock);
628
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);
633
634   if (__use_tzfile)
635     __tzfile_compute (*timer, use_localtime, &leap_correction,
636                       &leap_extra_secs, tp);
637   else
638     {
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;
645     }
646
647   if (tp)
648     {
649       if (! use_localtime)
650         {
651           tp->tm_isdst = 0;
652           tp->tm_zone = "GMT";
653           tp->tm_gmtoff = 0L;
654         }
655
656       if (__offtime (timer, tp->tm_gmtoff - leap_correction, tp))
657         tp->tm_sec += leap_extra_secs;
658       else
659         tp = NULL;
660     }
661
662   __libc_lock_unlock (tzset_lock);
663
664   return tp;
665 }
666
667
668 libc_freeres_fn (free_mem)
669 {
670   while (tzstring_list != NULL)
671     {
672       struct tzstring_l *old = tzstring_list;
673
674       tzstring_list = tzstring_list->next;
675       free (old);
676     }
677   free (old_tz);
678   old_tz = NULL;
679 }