]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/tzset.c
Fix trailing space.
[thirdparty/glibc.git] / time / tzset.c
CommitLineData
b168057a 1/* Copyright (C) 1991-2015 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>
42261ad7 21#include <stdbool.h>
28f540f4
RM
22#include <stddef.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <time.h>
27
9a0a462c 28
28f540f4 29#define NOID
14ea22e9 30#include <timezone/tzfile.h>
28f540f4 31
28f540f4
RM
32char *__tzname[2] = { (char *) "GMT", (char *) "GMT" };
33int __daylight = 0;
34long int __timezone = 0L;
35
0ac2e7d8
BK
36weak_alias (__tzname, tzname)
37weak_alias (__daylight, daylight)
38weak_alias (__timezone, timezone)
39
9a0a462c 40/* This locks all the state variables in tzfile.c and this file. */
727211c4 41__libc_lock_define_initialized (static, tzset_lock)
9a0a462c 42
28f540f4
RM
43
44#define min(a, b) ((a) < (b) ? (a) : (b))
45#define max(a, b) ((a) > (b) ? (a) : (b))
46#define sign(x) ((x) < 0 ? -1 : 1)
47
48
49/* This structure contains all the information about a
50 timezone given in the POSIX standard TZ envariable. */
51typedef struct
52 {
cd6ede75 53 const char *name;
28f540f4
RM
54
55 /* When to change. */
56 enum { J0, J1, M } type; /* Interpretation of: */
57 unsigned short int m, n, d; /* Month, week, day. */
0748546f 58 int secs; /* Time of day. */
28f540f4
RM
59
60 long int offset; /* Seconds east of GMT (west if < 0). */
61
62 /* We cache the computed time of change for a
63 given year so we don't have to recompute it. */
64 time_t change; /* When to change to this zone. */
65 int computed_for; /* Year above is computed for. */
66 } tz_rule;
67
68/* tz_rules[0] is standard, tz_rules[1] is daylight. */
69static tz_rule tz_rules[2];
f65fd747
UD
70
71
79937577 72static void compute_change (tz_rule *rule, int year) __THROW internal_function;
79937577
UD
73static void tzset_internal (int always, int explicit)
74 __THROW internal_function;
28f540f4 75\f
2698e32c
UD
76/* List of buffers containing time zone strings. */
77struct tzstring_l
cd6ede75 78{
2698e32c
UD
79 struct tzstring_l *next;
80 size_t len; /* strlen(data) - doesn't count terminating NUL! */
81 char data[0];
cd6ede75
UD
82};
83
418f1701 84static struct tzstring_l *tzstring_list;
cd6ede75 85
42261ad7
FW
86/* Allocate a permanent home for the first LEN characters of S. It
87 will never be moved or deallocated, but may share space with other
88 strings. Don't modify the returned string. */
89static char *
90__tzstring_len (const char *s, size_t len)
cd6ede75 91{
cd6ede75 92 char *p;
2698e32c 93 struct tzstring_l *t, *u, *new;
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];
42261ad7 101 if (memcmp (s, p, len) == 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;
42261ad7
FW
112 memcpy (new->data, s, len);
113 new->data[len] = '\0';
2698e32c
UD
114
115 if (u)
116 u->next = new;
117 else
118 tzstring_list = new;
119
120 return new->data;
cd6ede75 121}
42261ad7
FW
122
123/* Allocate a permanent home for S. It will never be moved or
124 deallocated, but may share space with other strings. Don't modify
125 the returned string. */
126char *
127__tzstring (const char *s)
128{
129 return __tzstring_len (s, strlen (s));
130}
cd6ede75 131\f
a3931cbe
UD
132/* Maximum length of a timezone name. tzset_internal keeps this up to date
133 (never decreasing it) when ! __use_tzfile.
134 tzfile.c keeps it up to date when __use_tzfile. */
135size_t __tzname_cur_max;
136
137long int
60d2f8f3 138__tzname_max (void)
a3931cbe
UD
139{
140 __libc_lock_lock (tzset_lock);
141
c3d1af70 142 tzset_internal (0, 0);
a3931cbe
UD
143
144 __libc_lock_unlock (tzset_lock);
145
146 return __tzname_cur_max;
147}
148\f
c4563d2d 149static char *old_tz;
28f540f4 150
9a0a462c 151static void
dfd2257a 152internal_function
fa76dde2
UD
153update_vars (void)
154{
155 __daylight = tz_rules[0].offset != tz_rules[1].offset;
156 __timezone = -tz_rules[0].offset;
157 __tzname[0] = (char *) tz_rules[0].name;
158 __tzname[1] = (char *) tz_rules[1].name;
159
160 /* Keep __tzname_cur_max up to date. */
161 size_t len0 = strlen (__tzname[0]);
162 size_t len1 = strlen (__tzname[1]);
163 if (len0 > __tzname_cur_max)
164 __tzname_cur_max = len0;
165 if (len1 > __tzname_cur_max)
166 __tzname_cur_max = len1;
167}
168
bd82a247
UD
169
170static unsigned int
171__attribute_noinline__
172compute_offset (unsigned int ss, unsigned int mm, unsigned int hh)
173{
174 return min (ss, 59) + min (mm, 59) * 60 + min (hh, 24) * 60 * 60;
175}
176
42261ad7
FW
177/* Parses the time zone name at *TZP, and writes a pointer to an
178 interned string to tz_rules[WHICHRULE].name. On success, advances
179 *TZP, and returns true. Returns false otherwise. */
180static bool
181parse_tzname (const char **tzp, int whichrule)
28f540f4 182{
42261ad7
FW
183 const char *start = *tzp;
184 const char *p = start;
185 while (('a' <= *p && *p <= 'z')
186 || ('A' <= *p && *p <= 'Z'))
187 ++p;
188 size_t len = p - start;
189 if (len < 3)
82780cbe 190 {
42261ad7
FW
191 p = *tzp;
192 if (__glibc_unlikely (*p++ != '<'))
193 return false;
194 start = p;
195 while (('a' <= *p && *p <= 'z')
196 || ('A' <= *p && *p <= 'Z')
197 || ('0' <= *p && *p <= '9')
198 || *p == '+' || *p == '-')
199 ++p;
200 len = p - start;
201 if (*p++ != '>' || len < 3)
202 return false;
82780cbe 203 }
cc8dcf96
FW
204
205 const char *name = __tzstring_len (start, len);
206 if (name == NULL)
207 return false;
208 tz_rules[whichrule].name = name;
209
42261ad7
FW
210 *tzp = p;
211 return true;
212}
28f540f4 213
42261ad7
FW
214/* Parses the time zone offset at *TZP, and writes it to
215 tz_rules[WHICHRULE].offset. Returns true if the parse was
216 successful. */
217static bool
218parse_offset (const char **tzp, int whichrule)
219{
220 const char *tz = *tzp;
221 if (whichrule == 0
222 && (*tz == '\0' || (*tz != '+' && *tz != '-' && !isdigit (*tz))))
223 return false;
28f540f4 224
42261ad7 225 long sign;
28f540f4 226 if (*tz == '-' || *tz == '+')
42261ad7 227 sign = *tz++ == '-' ? 1L : -1L;
28f540f4 228 else
42261ad7
FW
229 sign = -1L;
230 *tzp = tz;
231
232 unsigned short int hh;
233 unsigned short mm = 0;
234 unsigned short ss = 0;
235 int consumed = 0;
236 if (sscanf (tz, "%hu%n:%hu%n:%hu%n",
237 &hh, &consumed, &mm, &consumed, &ss, &consumed) > 0)
238 tz_rules[whichrule].offset = sign * compute_offset (ss, mm, hh);
239 else
240 /* Nothing could be parsed. */
241 if (whichrule == 0)
242 {
243 /* Standard time defaults to offset zero. */
244 tz_rules[0].offset = 0;
245 return false;
246 }
82780cbe 247 else
42261ad7
FW
248 /* DST defaults to one hour later than standard time. */
249 tz_rules[1].offset = tz_rules[0].offset + (60 * 60);
250 *tzp = tz + consumed;
251 return true;
252}
cd6ede75 253
42261ad7
FW
254/* Parses the standard <-> DST rules at *TZP. Updates
255 tz_rule[WHICHRULE]. On success, advances *TZP and returns true.
256 Otherwise, returns false. */
257static bool
258parse_rule (const char **tzp, int whichrule)
259{
260 const char *tz = *tzp;
261 tz_rule *tzr = &tz_rules[whichrule];
fd26970f 262
42261ad7
FW
263 /* Ignore comma to support string following the incorrect
264 specification in early POSIX.1 printings. */
265 tz += *tz == ',';
fd26970f 266
42261ad7
FW
267 /* Get the date of the change. */
268 if (*tz == 'J' || isdigit (*tz))
269 {
270 char *end;
271 tzr->type = *tz == 'J' ? J1 : J0;
272 if (tzr->type == J1 && !isdigit (*++tz))
273 return false;
274 unsigned long int d = strtoul (tz, &end, 10);
275 if (end == tz || d > 365)
276 return false;
277 if (tzr->type == J1 && d == 0)
278 return false;
279 tzr->d = d;
280 tz = end;
281 }
282 else if (*tz == 'M')
283 {
284 tzr->type = M;
285 int consumed;
286 if (sscanf (tz, "M%hu.%hu.%hu%n",
287 &tzr->m, &tzr->n, &tzr->d, &consumed) != 3
288 || tzr->m < 1 || tzr->m > 12
289 || tzr->n < 1 || tzr->n > 5 || tzr->d > 6)
290 return false;
291 tz += consumed;
292 }
293 else if (*tz == '\0')
294 {
295 /* Daylight time rules in the U.S. are defined in the U.S. Code,
296 Title 15, Chapter 6, Subchapter IX - Standard Time. These
297 dates were established by Congress in the Energy Policy Act
298 of 2005 [Pub. L. no. 109-58, 119 Stat 594 (2005)].
299 Below is the equivalent of "M3.2.0,M11.1.0" [/2 not needed
300 since 2:00AM is the default]. */
301 tzr->type = M;
302 if (tzr == &tz_rules[0])
fd26970f 303 {
42261ad7
FW
304 tzr->m = 3;
305 tzr->n = 2;
306 tzr->d = 0;
fd26970f 307 }
42261ad7 308 else
0413b54c 309 {
42261ad7
FW
310 tzr->m = 11;
311 tzr->n = 1;
312 tzr->d = 0;
0413b54c 313 }
28f540f4 314 }
5290baf0 315 else
42261ad7
FW
316 return false;
317
318 if (*tz != '\0' && *tz != '/' && *tz != ',')
319 return false;
320 else if (*tz == '/')
40a55d20 321 {
42261ad7
FW
322 /* Get the time of day of the change. */
323 int negative;
324 ++tz;
325 if (*tz == '\0')
326 return false;
327 negative = *tz == '-';
328 tz += negative;
329 /* Default to 2:00 AM. */
330 unsigned short hh = 2;
331 unsigned short mm = 0;
332 unsigned short ss = 0;
333 int consumed = 0;
334 sscanf (tz, "%hu%n:%hu%n:%hu%n",
335 &hh, &consumed, &mm, &consumed, &ss, &consumed);;
336 tz += consumed;
337 tzr->secs = (negative ? -1 : 1) * ((hh * 60 * 60) + (mm * 60) + ss);
40a55d20 338 }
42261ad7
FW
339 else
340 /* Default to 2:00 AM. */
341 tzr->secs = 2 * 60 * 60;
28f540f4 342
42261ad7
FW
343 tzr->computed_for = -1;
344 *tzp = tz;
345 return true;
346}
1cbca0d9 347
42261ad7
FW
348/* Parse the POSIX TZ-style string. */
349void
350__tzset_parse_tz (const char *tz)
351{
352 /* Clear out old state and reset to unnamed UTC. */
353 memset (tz_rules, '\0', sizeof tz_rules);
354 tz_rules[0].name = tz_rules[1].name = "";
1cbca0d9 355
42261ad7
FW
356 /* Get the standard timezone name. */
357 if (parse_tzname (&tz, 0) && parse_offset (&tz, 0))
358 {
359 /* Get the DST timezone name (if any). */
360 if (*tz != '\0')
28f540f4 361 {
42261ad7 362 if (parse_tzname (&tz, 1))
28f540f4 363 {
42261ad7
FW
364 parse_offset (&tz, 1);
365 if (*tz == '\0' || (tz[0] == ',' && tz[1] == '\0'))
366 {
367 /* There is no rule. See if there is a default rule
368 file. */
369 __tzfile_default (tz_rules[0].name, tz_rules[1].name,
370 tz_rules[0].offset, tz_rules[1].offset);
371 if (__use_tzfile)
372 {
373 free (old_tz);
374 old_tz = NULL;
375 return;
376 }
377 }
28f540f4 378 }
42261ad7
FW
379 /* Figure out the standard <-> DST rules. */
380 if (parse_rule (&tz, 0))
381 parse_rule (&tz, 1);
28f540f4
RM
382 }
383 else
28f540f4 384 {
42261ad7
FW
385 /* There is no DST. */
386 tz_rules[1].name = tz_rules[0].name;
387 tz_rules[1].offset = tz_rules[0].offset;
28f540f4 388 }
28f540f4 389 }
90865aa8 390
fa76dde2
UD
391 update_vars ();
392}
28f540f4 393
fa76dde2
UD
394/* Interpret the TZ envariable. */
395static void
396internal_function
397tzset_internal (always, explicit)
398 int always;
399 int explicit;
400{
401 static int is_initialized;
2e09a79a 402 const char *tz;
fa76dde2
UD
403
404 if (is_initialized && !always)
405 return;
406 is_initialized = 1;
407
408 /* Examine the TZ environment variable. */
409 tz = getenv ("TZ");
410 if (tz == NULL && !explicit)
411 /* Use the site-wide default. This is a file name which means we
412 would not see changes to the file if we compare only the file
413 name for change. We want to notice file changes if tzset() has
414 been called explicitly. Leave TZ as NULL in this case. */
415 tz = TZDEFAULT;
416 if (tz && *tz == '\0')
417 /* User specified the empty string; use UTC explicitly. */
418 tz = "Universal";
419
420 /* A leading colon means "implementation defined syntax".
421 We ignore the colon and always use the same algorithm:
422 try a data file, and if none exists parse the 1003.1 syntax. */
423 if (tz && *tz == ':')
424 ++tz;
425
58423c7d 426 /* Check whether the value changed since the last run. */
fa76dde2
UD
427 if (old_tz != NULL && tz != NULL && strcmp (tz, old_tz) == 0)
428 /* No change, simply return. */
429 return;
430
431 if (tz == NULL)
432 /* No user specification; use the site-wide default. */
433 tz = TZDEFAULT;
434
435 tz_rules[0].name = NULL;
436 tz_rules[1].name = NULL;
437
438 /* Save the value of `tz'. */
72e6cdfa 439 free (old_tz);
fa76dde2
UD
440 old_tz = tz ? __strdup (tz) : NULL;
441
442 /* Try to read a data file. */
443 __tzfile_read (tz, 0, NULL);
444 if (__use_tzfile)
445 return;
446
447 /* No data file found. Default to UTC if nothing specified. */
448
449 if (tz == NULL || *tz == '\0'
450 || (TZDEFAULT != NULL && strcmp (tz, TZDEFAULT) == 0))
451 {
bd82a247 452 memset (tz_rules, '\0', sizeof tz_rules);
fa76dde2 453 tz_rules[0].name = tz_rules[1].name = "UTC";
bd82a247
UD
454 if (J0 != 0)
455 tz_rules[0].type = tz_rules[1].type = J0;
fa76dde2 456 tz_rules[0].change = tz_rules[1].change = (time_t) -1;
fa76dde2
UD
457 update_vars ();
458 return;
459 }
460
461 __tzset_parse_tz (tz);
28f540f4
RM
462}
463\f
464/* Figure out the exact time (as a time_t) in YEAR
465 when the change described by RULE will occur and
a3931cbe
UD
466 put it in RULE->change, saving YEAR in RULE->computed_for. */
467static void
dfd2257a 468internal_function
f65fd747
UD
469compute_change (rule, year)
470 tz_rule *rule;
471 int year;
28f540f4 472{
2e09a79a 473 time_t t;
28f540f4
RM
474
475 if (year != -1 && rule->computed_for == year)
7fcc87f4 476 /* Operations on times in 2 BC will be slower. Oh well. */
a3931cbe 477 return;
1cbca0d9 478
28f540f4 479 /* First set T to January 1st, 0:00:00 GMT in YEAR. */
7fcc87f4
UD
480 if (year > 1970)
481 t = ((year - 1970) * 365
482 + /* Compute the number of leapdays between 1970 and YEAR
483 (exclusive). There is a leapday every 4th year ... */
484 + ((year - 1) / 4 - 1970 / 4)
485 /* ... except every 100th year ... */
486 - ((year - 1) / 100 - 1970 / 100)
487 /* ... but still every 400th year. */
488 + ((year - 1) / 400 - 1970 / 400)) * SECSPERDAY;
489 else
490 t = 0;
28f540f4
RM
491
492 switch (rule->type)
493 {
494 case J1:
495 /* Jn - Julian day, 1 == January 1, 60 == March 1 even in leap years.
496 In non-leap years, or if the day number is 59 or less, just
497 add SECSPERDAY times the day number-1 to the time of
498 January 1, midnight, to get the day. */
499 t += (rule->d - 1) * SECSPERDAY;
500 if (rule->d >= 60 && __isleap (year))
501 t += SECSPERDAY;
502 break;
503
504 case J0:
505 /* n - Day of year.
506 Just add SECSPERDAY times the day number to the time of Jan 1st. */
507 t += rule->d * SECSPERDAY;
508 break;
509
510 case M:
511 /* Mm.n.d - Nth "Dth day" of month M. */
512 {
9a0a462c
UD
513 unsigned int i;
514 int d, m1, yy0, yy1, yy2, dow;
515 const unsigned short int *myday =
80fd7387 516 &__mon_yday[__isleap (year)][rule->m];
28f540f4
RM
517
518 /* First add SECSPERDAY for each day in months before M. */
80fd7387 519 t += myday[-1] * SECSPERDAY;
28f540f4
RM
520
521 /* Use Zeller's Congruence to get day-of-week of first day of month. */
522 m1 = (rule->m + 9) % 12 + 1;
523 yy0 = (rule->m <= 2) ? (year - 1) : year;
524 yy1 = yy0 / 100;
525 yy2 = yy0 % 100;
526 dow = ((26 * m1 - 2) / 10 + 1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
527 if (dow < 0)
528 dow += 7;
529
530 /* DOW is the day-of-week of the first day of the month. Get the
531 day-of-month (zero-origin) of the first DOW day of the month. */
532 d = rule->d - dow;
533 if (d < 0)
534 d += 7;
535 for (i = 1; i < rule->n; ++i)
536 {
9a0a462c 537 if (d + 7 >= (int) myday[0] - myday[-1])
28f540f4
RM
538 break;
539 d += 7;
540 }
541
542 /* D is the day-of-month (zero-origin) of the day we want. */
543 t += d * SECSPERDAY;
544 }
545 break;
546 }
547
548 /* T is now the Epoch-relative time of 0:00:00 GMT on the day we want.
549 Just add the time of day and local offset from GMT, and we're done. */
550
68dbb3a6 551 rule->change = t - rule->offset + rule->secs;
28f540f4 552 rule->computed_for = year;
28f540f4
RM
553}
554
555
e3e35cfc 556/* Figure out the correct timezone for TM and set `__tzname',
a3931cbe 557 `__timezone', and `__daylight' accordingly. */
fa76dde2 558void
dfd2257a 559internal_function
fa76dde2
UD
560__tz_compute (timer, tm, use_localtime)
561 time_t timer;
562 struct tm *tm;
563 int use_localtime;
28f540f4 564{
a3931cbe
UD
565 compute_change (&tz_rules[0], 1900 + tm->tm_year);
566 compute_change (&tz_rules[1], 1900 + tm->tm_year);
fa76dde2
UD
567
568 if (use_localtime)
569 {
570 int isdst;
571
572 /* We have to distinguish between northern and southern
573 hemisphere. For the latter the daylight saving time
574 ends in the next year. */
575 if (__builtin_expect (tz_rules[0].change
576 > tz_rules[1].change, 0))
577 isdst = (timer < tz_rules[1].change
578 || timer >= tz_rules[0].change);
579 else
580 isdst = (timer >= tz_rules[0].change
581 && timer < tz_rules[1].change);
582 tm->tm_isdst = isdst;
583 tm->tm_zone = __tzname[isdst];
584 tm->tm_gmtoff = tz_rules[isdst].offset;
585 }
28f540f4 586}
b24be05f 587\f
b24be05f 588/* Reinterpret the TZ environment variable and set `tzname'. */
4311b2a6 589#undef tzset
28f540f4 590
b24be05f 591void
10dc2a90 592__tzset (void)
b24be05f 593{
9a0a462c 594 __libc_lock_lock (tzset_lock);
68dbb3a6 595
c3d1af70 596 tzset_internal (1, 1);
68dbb3a6 597
860d3729
UD
598 if (!__use_tzfile)
599 {
600 /* Set `tzname'. */
601 __tzname[0] = (char *) tz_rules[0].name;
602 __tzname[1] = (char *) tz_rules[1].name;
603 }
68dbb3a6 604
9a0a462c 605 __libc_lock_unlock (tzset_lock);
b24be05f 606}
10dc2a90 607weak_alias (__tzset, tzset)
9a0a462c
UD
608\f
609/* Return the `struct tm' representation of *TIMER in the local timezone.
610 Use local time if USE_LOCALTIME is nonzero, UTC otherwise. */
611struct tm *
612__tz_convert (const time_t *timer, int use_localtime, struct tm *tp)
613{
614 long int leap_correction;
615 int leap_extra_secs;
616
617 if (timer == NULL)
618 {
619 __set_errno (EINVAL);
620 return NULL;
621 }
622
623 __libc_lock_lock (tzset_lock);
624
625 /* Update internal database according to current TZ setting.
626 POSIX.1 8.3.7.2 says that localtime_r is not required to set tzname.
58423c7d
UD
627 This is a good idea since this allows at least a bit more parallelism. */
628 tzset_internal (tp == &_tmbuf && use_localtime, 1);
9a0a462c
UD
629
630 if (__use_tzfile)
38e68573
UD
631 __tzfile_compute (*timer, use_localtime, &leap_correction,
632 &leap_extra_secs, tp);
9a0a462c
UD
633 else
634 {
a3931cbe 635 if (! __offtime (timer, 0, tp))
9a0a462c 636 tp = NULL;
a3931cbe 637 else
fa76dde2 638 __tz_compute (*timer, tp, use_localtime);
9a0a462c
UD
639 leap_correction = 0L;
640 leap_extra_secs = 0;
641 }
642
6807b1db
KE
643 __libc_lock_unlock (tzset_lock);
644
9a0a462c
UD
645 if (tp)
646 {
fa76dde2 647 if (! use_localtime)
9a0a462c
UD
648 {
649 tp->tm_isdst = 0;
650 tp->tm_zone = "GMT";
651 tp->tm_gmtoff = 0L;
652 }
653
fe0ec73e
UD
654 if (__offtime (timer, tp->tm_gmtoff - leap_correction, tp))
655 tp->tm_sec += leap_extra_secs;
656 else
657 tp = NULL;
9a0a462c
UD
658 }
659
9a0a462c
UD
660 return tp;
661}
83628d31
UD
662
663
c877418f 664libc_freeres_fn (free_mem)
83628d31
UD
665{
666 while (tzstring_list != NULL)
667 {
668 struct tzstring_l *old = tzstring_list;
669
670 tzstring_list = tzstring_list->next;
671 free (old);
672 }
673 free (old_tz);
674 old_tz = NULL;
675}