]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/tzset.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / time / tzset.c
CommitLineData
d4697bc9 1/* Copyright (C) 1991-2014 Free Software Foundation, Inc.
f65fd747 2 This file is part of the GNU C Library.
28f540f4 3
f65fd747 4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
28f540f4 8
f65fd747
UD
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
41bdb6e2 12 Lesser General Public License for more details.
28f540f4 13
41bdb6e2 14 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
15 License along with the GNU C Library; if not, see
16 <http://www.gnu.org/licenses/>. */
28f540f4 17
28f540f4 18#include <ctype.h>
9a0a462c
UD
19#include <errno.h>
20#include <bits/libc-lock.h>
28f540f4
RM
21#include <stddef.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <time.h>
26
9a0a462c 27
28f540f4 28#define NOID
14ea22e9 29#include <timezone/tzfile.h>
28f540f4 30
28f540f4
RM
31char *__tzname[2] = { (char *) "GMT", (char *) "GMT" };
32int __daylight = 0;
33long int __timezone = 0L;
34
0ac2e7d8
BK
35weak_alias (__tzname, tzname)
36weak_alias (__daylight, daylight)
37weak_alias (__timezone, timezone)
38
9a0a462c 39/* This locks all the state variables in tzfile.c and this file. */
727211c4 40__libc_lock_define_initialized (static, tzset_lock)
9a0a462c 41
28f540f4
RM
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. */
50typedef struct
51 {
cd6ede75 52 const char *name;
28f540f4
RM
53
54 /* When to change. */
55 enum { J0, J1, M } type; /* Interpretation of: */
56 unsigned short int m, n, d; /* Month, week, day. */
0748546f 57 int secs; /* Time of day. */
28f540f4
RM
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. */
68static tz_rule tz_rules[2];
f65fd747
UD
69
70
79937577 71static void compute_change (tz_rule *rule, int year) __THROW internal_function;
79937577
UD
72static void tzset_internal (int always, int explicit)
73 __THROW internal_function;
28f540f4 74\f
2698e32c
UD
75/* List of buffers containing time zone strings. */
76struct tzstring_l
cd6ede75 77{
2698e32c
UD
78 struct tzstring_l *next;
79 size_t len; /* strlen(data) - doesn't count terminating NUL! */
80 char data[0];
cd6ede75
UD
81};
82
418f1701 83static struct tzstring_l *tzstring_list;
cd6ede75 84
2698e32c
UD
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. */
0413b54c 88char *
2698e32c 89__tzstring (const char *s)
cd6ede75 90{
cd6ede75 91 char *p;
2698e32c 92 struct tzstring_l *t, *u, *new;
fa76dde2 93 size_t len = strlen (s);
2698e32c
UD
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)
cd6ede75 102 return p;
2698e32c
UD
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;
cd6ede75
UD
120}
121\f
a3931cbe
UD
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. */
125size_t __tzname_cur_max;
126
127long int
60d2f8f3 128__tzname_max (void)
a3931cbe
UD
129{
130 __libc_lock_lock (tzset_lock);
131
c3d1af70 132 tzset_internal (0, 0);
a3931cbe
UD
133
134 __libc_lock_unlock (tzset_lock);
135
136 return __tzname_cur_max;
137}
138\f
c4563d2d 139static char *old_tz;
28f540f4 140
9a0a462c 141static void
dfd2257a 142internal_function
fa76dde2
UD
143update_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
bd82a247
UD
159
160static unsigned int
161__attribute_noinline__
162compute_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
fa76dde2
UD
168/* Parse the POSIX TZ-style string. */
169void
170__tzset_parse_tz (tz)
171 const char *tz;
28f540f4 172{
28f540f4 173 unsigned short int hh, mm, ss;
28f540f4 174
933e73fa 175 /* Clear out old state and reset to unnamed UTC. */
bd82a247 176 memset (tz_rules, '\0', sizeof tz_rules);
cd6ede75 177 tz_rules[0].name = tz_rules[1].name = "";
28f540f4
RM
178
179 /* Get the standard timezone name. */
686f8c9d 180 char *tzbuf = strdupa (tz);
28f540f4 181
bd82a247
UD
182 int consumed;
183 if (sscanf (tz, "%[A-Za-z]%n", tzbuf, &consumed) != 1)
82780cbe
UD
184 {
185 /* Check for the quoted version. */
186 char *wp = tzbuf;
686f8c9d 187 if (__builtin_expect (*tz++ != '<', 0))
82780cbe
UD
188 goto out;
189
190 while (isalnum (*tz) || *tz == '+' || *tz == '-')
191 *wp++ = *tz++;
686f8c9d 192 if (__builtin_expect (*tz++ != '>' || wp - tzbuf < 3, 0))
82780cbe
UD
193 goto out;
194 *wp = '\0';
195 }
bd82a247 196 else if (__builtin_expect (consumed < 3, 0))
a3931cbe 197 goto out;
82780cbe 198 else
bd82a247 199 tz += consumed;
28f540f4 200
cd6ede75 201 tz_rules[0].name = __tzstring (tzbuf);
28f540f4 202
933e73fa 203 /* Figure out the standard offset from UTC. */
1228ed5c 204 if (*tz == '\0' || (*tz != '+' && *tz != '-' && !isdigit (*tz)))
a3931cbe 205 goto out;
28f540f4
RM
206
207 if (*tz == '-' || *tz == '+')
208 tz_rules[0].offset = *tz++ == '-' ? 1L : -1L;
209 else
210 tz_rules[0].offset = -1L;
bd82a247
UD
211 switch (sscanf (tz, "%hu%n:%hu%n:%hu%n",
212 &hh, &consumed, &mm, &consumed, &ss, &consumed))
28f540f4
RM
213 {
214 default:
bbd0bf24 215 tz_rules[0].offset = 0;
a3931cbe 216 goto out;
28f540f4
RM
217 case 1:
218 mm = 0;
219 case 2:
220 ss = 0;
221 case 3:
222 break;
223 }
bd82a247
UD
224 tz_rules[0].offset *= compute_offset (ss, mm, hh);
225 tz += consumed;
28f540f4
RM
226
227 /* Get the DST timezone name (if any). */
228 if (*tz != '\0')
229 {
bd82a247 230 if (sscanf (tz, "%[A-Za-z]%n", tzbuf, &consumed) != 1)
82780cbe
UD
231 {
232 /* Check for the quoted version. */
233 char *wp = tzbuf;
234 const char *rp = tz;
686f8c9d 235 if (__builtin_expect (*rp++ != '<', 0))
82780cbe
UD
236 /* Punt on name, set up the offsets. */
237 goto done_names;
238
239 while (isalnum (*rp) || *rp == '+' || *rp == '-')
240 *wp++ = *rp++;
686f8c9d 241 if (__builtin_expect (*rp++ != '>' || wp - tzbuf < 3, 0))
82780cbe
UD
242 /* Punt on name, set up the offsets. */
243 goto done_names;
244 *wp = '\0';
245 tz = rp;
246 }
bd82a247 247 else if (__builtin_expect (consumed < 3, 0))
82780cbe
UD
248 /* Punt on name, set up the offsets. */
249 goto done_names;
250 else
bd82a247 251 tz += consumed;
cd6ede75 252
686f8c9d 253 tz_rules[1].name = __tzstring (tzbuf);
fd26970f
UD
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
bd82a247
UD
261 switch (sscanf (tz, "%hu%n:%hu%n:%hu%n",
262 &hh, &consumed, &mm, &consumed, &ss, &consumed))
fd26970f
UD
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:
bd82a247
UD
274 tz_rules[1].offset *= compute_offset (ss, mm, hh);
275 tz += consumed;
fd26970f
UD
276 break;
277 }
0413b54c
UD
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 }
28f540f4 290 }
5290baf0 291 else
40a55d20
UD
292 {
293 /* There is no DST. */
294 tz_rules[1].name = tz_rules[0].name;
ff152e3f 295 tz_rules[1].offset = tz_rules[0].offset;
90865aa8 296 goto out;
40a55d20 297 }
28f540f4 298
28f540f4 299 done_names:
28f540f4 300 /* Figure out the standard <-> DST rules. */
bd82a247 301 for (unsigned int whichrule = 0; whichrule < 2; ++whichrule)
28f540f4 302 {
2e09a79a 303 tz_rule *tzr = &tz_rules[whichrule];
1cbca0d9 304
ca34d7a7
UD
305 /* Ignore comma to support string following the incorrect
306 specification in early POSIX.1 printings. */
307 tz += *tz == ',';
1cbca0d9 308
28f540f4
RM
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))
90865aa8 315 goto out;
bd82a247
UD
316 unsigned long int d = strtoul (tz, &end, 10);
317 if (end == tz || d > 365)
90865aa8 318 goto out;
bd82a247 319 if (tzr->type == J1 && d == 0)
90865aa8 320 goto out;
bd82a247 321 tzr->d = d;
28f540f4
RM
322 tz = end;
323 }
324 else if (*tz == 'M')
325 {
28f540f4
RM
326 tzr->type = M;
327 if (sscanf (tz, "M%hu.%hu.%hu%n",
bd82a247
UD
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)
90865aa8 331 goto out;
bd82a247 332 tz += consumed;
28f540f4
RM
333 }
334 else if (*tz == '\0')
335 {
b9f1922d
IW
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]. */
28f540f4
RM
343 tzr->type = M;
344 if (tzr == &tz_rules[0])
345 {
b9f1922d
IW
346 tzr->m = 3;
347 tzr->n = 2;
28f540f4
RM
348 tzr->d = 0;
349 }
350 else
351 {
b9f1922d
IW
352 tzr->m = 11;
353 tzr->n = 1;
28f540f4
RM
354 tzr->d = 0;
355 }
356 }
357 else
90865aa8 358 goto out;
1cbca0d9 359
28f540f4 360 if (*tz != '\0' && *tz != '/' && *tz != ',')
90865aa8 361 goto out;
28f540f4
RM
362 else if (*tz == '/')
363 {
364 /* Get the time of day of the change. */
0748546f 365 int negative;
28f540f4
RM
366 ++tz;
367 if (*tz == '\0')
90865aa8 368 goto out;
0748546f
PE
369 negative = *tz == '-';
370 tz += negative;
bd82a247
UD
371 consumed = 0;
372 switch (sscanf (tz, "%hu%n:%hu%n:%hu%n",
373 &hh, &consumed, &mm, &consumed, &ss, &consumed))
28f540f4
RM
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 }
bd82a247 384 tz += consumed;
0748546f 385 tzr->secs = (negative ? -1 : 1) * ((hh * 60 * 60) + (mm * 60) + ss);
28f540f4
RM
386 }
387 else
388 /* Default to 2:00 AM. */
389 tzr->secs = 2 * 60 * 60;
390
391 tzr->computed_for = -1;
392 }
90865aa8
UD
393
394 out:
fa76dde2
UD
395 update_vars ();
396}
28f540f4 397
fa76dde2
UD
398/* Interpret the TZ envariable. */
399static void
400internal_function
401tzset_internal (always, explicit)
402 int always;
403 int explicit;
404{
405 static int is_initialized;
2e09a79a 406 const char *tz;
fa76dde2
UD
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
58423c7d 430 /* Check whether the value changed since the last run. */
fa76dde2
UD
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'. */
72e6cdfa 443 free (old_tz);
fa76dde2
UD
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 {
bd82a247 456 memset (tz_rules, '\0', sizeof tz_rules);
fa76dde2 457 tz_rules[0].name = tz_rules[1].name = "UTC";
bd82a247
UD
458 if (J0 != 0)
459 tz_rules[0].type = tz_rules[1].type = J0;
fa76dde2 460 tz_rules[0].change = tz_rules[1].change = (time_t) -1;
fa76dde2
UD
461 update_vars ();
462 return;
463 }
464
465 __tzset_parse_tz (tz);
28f540f4
RM
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
a3931cbe
UD
470 put it in RULE->change, saving YEAR in RULE->computed_for. */
471static void
dfd2257a 472internal_function
f65fd747
UD
473compute_change (rule, year)
474 tz_rule *rule;
475 int year;
28f540f4 476{
2e09a79a 477 time_t t;
28f540f4
RM
478
479 if (year != -1 && rule->computed_for == year)
7fcc87f4 480 /* Operations on times in 2 BC will be slower. Oh well. */
a3931cbe 481 return;
1cbca0d9 482
28f540f4 483 /* First set T to January 1st, 0:00:00 GMT in YEAR. */
7fcc87f4
UD
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;
28f540f4
RM
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 {
9a0a462c
UD
517 unsigned int i;
518 int d, m1, yy0, yy1, yy2, dow;
519 const unsigned short int *myday =
80fd7387 520 &__mon_yday[__isleap (year)][rule->m];
28f540f4
RM
521
522 /* First add SECSPERDAY for each day in months before M. */
80fd7387 523 t += myday[-1] * SECSPERDAY;
28f540f4
RM
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 {
9a0a462c 541 if (d + 7 >= (int) myday[0] - myday[-1])
28f540f4
RM
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
68dbb3a6 555 rule->change = t - rule->offset + rule->secs;
28f540f4 556 rule->computed_for = year;
28f540f4
RM
557}
558
559
e3e35cfc 560/* Figure out the correct timezone for TM and set `__tzname',
a3931cbe 561 `__timezone', and `__daylight' accordingly. */
fa76dde2 562void
dfd2257a 563internal_function
fa76dde2
UD
564__tz_compute (timer, tm, use_localtime)
565 time_t timer;
566 struct tm *tm;
567 int use_localtime;
28f540f4 568{
a3931cbe
UD
569 compute_change (&tz_rules[0], 1900 + tm->tm_year);
570 compute_change (&tz_rules[1], 1900 + tm->tm_year);
fa76dde2
UD
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 }
28f540f4 590}
b24be05f 591\f
b24be05f 592/* Reinterpret the TZ environment variable and set `tzname'. */
4311b2a6 593#undef tzset
28f540f4 594
b24be05f 595void
10dc2a90 596__tzset (void)
b24be05f 597{
9a0a462c 598 __libc_lock_lock (tzset_lock);
68dbb3a6 599
c3d1af70 600 tzset_internal (1, 1);
68dbb3a6 601
860d3729
UD
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 }
68dbb3a6 608
9a0a462c 609 __libc_lock_unlock (tzset_lock);
b24be05f 610}
10dc2a90 611weak_alias (__tzset, tzset)
9a0a462c
UD
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. */
615struct 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.
58423c7d
UD
631 This is a good idea since this allows at least a bit more parallelism. */
632 tzset_internal (tp == &_tmbuf && use_localtime, 1);
9a0a462c
UD
633
634 if (__use_tzfile)
38e68573
UD
635 __tzfile_compute (*timer, use_localtime, &leap_correction,
636 &leap_extra_secs, tp);
9a0a462c
UD
637 else
638 {
a3931cbe 639 if (! __offtime (timer, 0, tp))
9a0a462c 640 tp = NULL;
a3931cbe 641 else
fa76dde2 642 __tz_compute (*timer, tp, use_localtime);
9a0a462c
UD
643 leap_correction = 0L;
644 leap_extra_secs = 0;
645 }
646
647 if (tp)
648 {
fa76dde2 649 if (! use_localtime)
9a0a462c
UD
650 {
651 tp->tm_isdst = 0;
652 tp->tm_zone = "GMT";
653 tp->tm_gmtoff = 0L;
654 }
655
fe0ec73e
UD
656 if (__offtime (timer, tp->tm_gmtoff - leap_correction, tp))
657 tp->tm_sec += leap_extra_secs;
658 else
659 tp = NULL;
9a0a462c
UD
660 }
661
662 __libc_lock_unlock (tzset_lock);
663
664 return tp;
665}
83628d31
UD
666
667
c877418f 668libc_freeres_fn (free_mem)
83628d31
UD
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}