]> git.ipfire.org Git - thirdparty/glibc.git/blame - time/tzfile.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / time / tzfile.c
CommitLineData
f7a9f785 1/* Copyright (C) 1991-2016 Free Software Foundation, Inc.
860d3729 2 This file is part of the GNU C Library.
28f540f4 3
860d3729 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
860d3729
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
a3e0e9ae
UD
18#include <assert.h>
19#include <limits.h>
28f540f4 20#include <stdio.h>
2706ee38 21#include <stdio_ext.h>
a3e0e9ae 22#include <stdlib.h>
28f540f4 23#include <string.h>
a3e0e9ae 24#include <time.h>
9d187dd4 25#include <unistd.h>
fe6cc2ae 26#include <sys/stat.h>
3b60b421 27#include <stdint.h>
28f540f4
RM
28
29#define NOID
14ea22e9 30#include <timezone/tzfile.h>
28f540f4 31
c4563d2d 32int __use_tzfile;
fe6cc2ae
UD
33static dev_t tzfile_dev;
34static ino64_t tzfile_ino;
8930fcf9 35static time_t tzfile_mtime;
28f540f4
RM
36
37struct ttinfo
38 {
39 long int offset; /* Seconds east of GMT. */
40 unsigned char isdst; /* Used to set tm_isdst. */
41 unsigned char idx; /* Index into `zone_names'. */
98fa1d6e
RM
42 unsigned char isstd; /* Transition times are in standard time. */
43 unsigned char isgmt; /* Transition times are in GMT. */
28f540f4
RM
44 };
45
46struct leap
47 {
48 time_t transition; /* Time the transition takes effect. */
49 long int change; /* Seconds of correction to apply. */
50 };
51
dfd2257a 52static void compute_tzname_max (size_t) internal_function;
28f540f4
RM
53
54static size_t num_transitions;
c877418f 55libc_freeres_ptr (static time_t *transitions);
c4563d2d 56static unsigned char *type_idxs;
28f540f4 57static size_t num_types;
c4563d2d
UD
58static struct ttinfo *types;
59static char *zone_names;
ff152e3f
UD
60static long int rule_stdoff;
61static long int rule_dstoff;
28f540f4 62static size_t num_leaps;
c4563d2d 63static struct leap *leaps;
fa76dde2 64static char *tzspec;
28f540f4 65
a2cafe30 66#include <endian.h>
ba9234d9 67#include <byteswap.h>
a2cafe30
RM
68
69/* Decode the four bytes at PTR as a signed integer in network byte order. */
70static inline int
9c7ff11a 71__attribute ((always_inline))
a2cafe30
RM
72decode (const void *ptr)
73{
11bf311e 74 if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
b20e47cb 75 return *(const int *) ptr;
11bf311e 76 if (sizeof (int) == 4)
ba9234d9 77 return bswap_32 (*(const int *) ptr);
b20e47cb 78
11bf311e
UD
79 const unsigned char *p = ptr;
80 int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
064737fb 81
11bf311e
UD
82 result = (result << 8) | *p++;
83 result = (result << 8) | *p++;
84 result = (result << 8) | *p++;
85 result = (result << 8) | *p++;
86
87 return result;
064737fb
UD
88}
89
11bf311e
UD
90
91static inline int64_t
92__attribute ((always_inline))
93decode64 (const void *ptr)
94{
95 if ((BYTE_ORDER == BIG_ENDIAN))
96 return *(const int64_t *) ptr;
97
98 return bswap_64 (*(const int64_t *) ptr);
99}
100
101
28f540f4 102void
c4563d2d 103__tzfile_read (const char *file, size_t extra, char **extrap)
28f540f4 104{
9d187dd4 105 static const char default_tzdir[] = TZDIR;
98fa1d6e 106 size_t num_isstd, num_isgmt;
2e09a79a 107 FILE *f;
28f540f4
RM
108 struct tzhead tzhead;
109 size_t chars;
2e09a79a 110 size_t i;
c4563d2d
UD
111 size_t total_size;
112 size_t types_idx;
113 size_t leaps_idx;
fe6cc2ae 114 int was_using_tzfile = __use_tzfile;
11bf311e 115 int trans_width = 4;
fa76dde2 116 size_t tzspec_len;
45c30c61 117 char *new = NULL;
11bf311e
UD
118
119 if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
120 abort ();
28f540f4
RM
121
122 __use_tzfile = 0;
123
a3b58440
RM
124 if (file == NULL)
125 /* No user specification; use the site-wide default. */
28f540f4 126 file = TZDEFAULT;
a3b58440 127 else if (*file == '\0')
9a0a462c 128 /* User specified the empty string; use UTC with no leap seconds. */
640b76b7 129 goto ret_free_transitions;
1228ed5c
UD
130 else
131 {
132 /* We must not allow to read an arbitrary file in a setuid
133 program. So we fail for any file which is not in the
7434ccad
UD
134 directory hierachy starting at TZDIR
135 and which is not the system wide default TZDEFAULT. */
1228ed5c
UD
136 if (__libc_enable_secure
137 && ((*file == '/'
4cca6b86 138 && memcmp (file, TZDEFAULT, sizeof TZDEFAULT)
1228ed5c
UD
139 && memcmp (file, default_tzdir, sizeof (default_tzdir) - 1))
140 || strstr (file, "../") != NULL))
7434ccad
UD
141 /* This test is certainly a bit too restrictive but it should
142 catch all critical cases. */
640b76b7 143 goto ret_free_transitions;
1228ed5c 144 }
9d187dd4 145
28f540f4
RM
146 if (*file != '/')
147 {
5290baf0 148 const char *tzdir;
5290baf0 149
74955460 150 tzdir = getenv ("TZDIR");
5290baf0 151 if (tzdir == NULL || *tzdir == '\0')
45c30c61
OB
152 tzdir = default_tzdir;
153 if (__asprintf (&new, "%s/%s", tzdir, file) == -1)
154 goto ret_free_transitions;
28f540f4
RM
155 file = new;
156 }
157
250ecb48
UD
158 /* If we were already using tzfile, check whether the file changed. */
159 struct stat64 st;
160 if (was_using_tzfile
161 && stat64 (file, &st) == 0
162 && tzfile_ino == st.st_ino && tzfile_dev == st.st_dev
163 && tzfile_mtime == st.st_mtime)
45c30c61 164 goto done; /* Nothing to do. */
250ecb48 165
ee8449f7 166 /* Note the file is opened with cancellation in the I/O functions
82af0fa8
UD
167 disabled and if available FD_CLOEXEC set. */
168 f = fopen (file, "rce");
28f540f4 169 if (f == NULL)
640b76b7 170 goto ret_free_transitions;
28f540f4 171
250ecb48 172 /* Get information about the file we are actually using. */
5a6fa4d7 173 if (fstat64 (__fileno (f), &st) != 0)
fe6cc2ae
UD
174 {
175 fclose (f);
640b76b7 176 goto ret_free_transitions;
fe6cc2ae 177 }
fe6cc2ae 178
640b76b7
UD
179 free ((void *) transitions);
180 transitions = NULL;
181
8930fcf9 182 /* Remember the inode and device number and modification time. */
fe6cc2ae
UD
183 tzfile_dev = st.st_dev;
184 tzfile_ino = st.st_ino;
8930fcf9 185 tzfile_mtime = st.st_mtime;
fe6cc2ae 186
2706ee38
UD
187 /* No threads reading this stream. */
188 __fsetlocking (f, FSETLOCKING_BYCALLER);
189
11bf311e 190 read_again:
5a6fa4d7
JM
191 if (__builtin_expect (__fread_unlocked ((void *) &tzhead, sizeof (tzhead),
192 1, f) != 1, 0)
11bf311e 193 || memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
28f540f4
RM
194 goto lose;
195
a2cafe30
RM
196 num_transitions = (size_t) decode (tzhead.tzh_timecnt);
197 num_types = (size_t) decode (tzhead.tzh_typecnt);
198 chars = (size_t) decode (tzhead.tzh_charcnt);
199 num_leaps = (size_t) decode (tzhead.tzh_leapcnt);
200 num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
201 num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
28f540f4 202
42261ad7
FW
203 if (__glibc_unlikely (num_isstd > num_types || num_isgmt > num_types))
204 goto lose;
205
11bf311e
UD
206 /* For platforms with 64-bit time_t we use the new format if available. */
207 if (sizeof (time_t) == 8 && trans_width == 4
208 && tzhead.tzh_version[0] != '\0')
209 {
210 /* We use the 8-byte format. */
211 trans_width = 8;
212
213 /* Position the stream before the second header. */
214 size_t to_skip = (num_transitions * (4 + 1)
215 + num_types * 6
216 + chars
217 + num_leaps * 8
218 + num_isstd
219 + num_isgmt);
220 if (fseek (f, to_skip, SEEK_CUR) != 0)
221 goto lose;
222
223 goto read_again;
224 }
225
97ac2654
UD
226 if (__builtin_expect (num_transitions
227 > ((SIZE_MAX - (__alignof__ (struct ttinfo) - 1))
228 / (sizeof (time_t) + 1)), 0))
229 goto lose;
c4563d2d
UD
230 total_size = num_transitions * (sizeof (time_t) + 1);
231 total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
232 & ~(__alignof__ (struct ttinfo) - 1));
233 types_idx = total_size;
97ac2654
UD
234 if (__builtin_expect (num_types
235 > (SIZE_MAX - total_size) / sizeof (struct ttinfo), 0))
236 goto lose;
237 total_size += num_types * sizeof (struct ttinfo);
a1ffb40e 238 if (__glibc_unlikely (chars > SIZE_MAX - total_size))
97ac2654
UD
239 goto lose;
240 total_size += chars;
241 if (__builtin_expect (__alignof__ (struct leap) - 1
242 > SIZE_MAX - total_size, 0))
243 goto lose;
c4563d2d
UD
244 total_size = ((total_size + __alignof__ (struct leap) - 1)
245 & ~(__alignof__ (struct leap) - 1));
246 leaps_idx = total_size;
97ac2654
UD
247 if (__builtin_expect (num_leaps
248 > (SIZE_MAX - total_size) / sizeof (struct leap), 0))
249 goto lose;
c4563d2d 250 total_size += num_leaps * sizeof (struct leap);
97ac2654
UD
251 tzspec_len = 0;
252 if (sizeof (time_t) == 8 && trans_width == 8)
253 {
5a6fa4d7 254 off_t rem = st.st_size - __ftello (f);
97ac2654
UD
255 if (__builtin_expect (rem < 0
256 || (size_t) rem < (num_transitions * (8 + 1)
257 + num_types * 6
258 + chars), 0))
259 goto lose;
260 tzspec_len = (size_t) rem - (num_transitions * (8 + 1)
261 + num_types * 6
262 + chars);
263 if (__builtin_expect (num_leaps > SIZE_MAX / 12
264 || tzspec_len < num_leaps * 12, 0))
265 goto lose;
266 tzspec_len -= num_leaps * 12;
a1ffb40e 267 if (__glibc_unlikely (tzspec_len < num_isstd))
97ac2654
UD
268 goto lose;
269 tzspec_len -= num_isstd;
a1ffb40e 270 if (__glibc_unlikely (tzspec_len == 0 || tzspec_len - 1 < num_isgmt))
97ac2654
UD
271 goto lose;
272 tzspec_len -= num_isgmt + 1;
5cffc05e
L
273 if (__glibc_unlikely (tzspec_len == 0
274 || SIZE_MAX - total_size < tzspec_len))
97ac2654
UD
275 goto lose;
276 }
a1ffb40e 277 if (__glibc_unlikely (SIZE_MAX - total_size - tzspec_len < extra))
97ac2654 278 goto lose;
c4563d2d 279
11bf311e
UD
280 /* Allocate enough memory including the extra block requested by the
281 caller. */
fa76dde2 282 transitions = (time_t *) malloc (total_size + tzspec_len + extra);
c4563d2d
UD
283 if (transitions == NULL)
284 goto lose;
285
286 type_idxs = (unsigned char *) transitions + (num_transitions
287 * sizeof (time_t));
288 types = (struct ttinfo *) ((char *) transitions + types_idx);
289 zone_names = (char *) types + num_types * sizeof (struct ttinfo);
290 leaps = (struct leap *) ((char *) transitions + leaps_idx);
6a649d25 291 if (sizeof (time_t) == 8 && trans_width == 8)
69819d92 292 tzspec = (char *) leaps + num_leaps * sizeof (struct leap) + extra;
fa76dde2
UD
293 else
294 tzspec = NULL;
c4563d2d
UD
295 if (extra > 0)
296 *extrap = (char *) &leaps[num_leaps];
297
6a649d25 298 if (sizeof (time_t) == 4 || __builtin_expect (trans_width == 8, 1))
28f540f4 299 {
5a6fa4d7
JM
300 if (__builtin_expect (__fread_unlocked (transitions, trans_width + 1,
301 num_transitions, f)
11bf311e 302 != num_transitions, 0))
28f540f4
RM
303 goto lose;
304 }
c4563d2d 305 else
28f540f4 306 {
5a6fa4d7
JM
307 if (__builtin_expect (__fread_unlocked (transitions, 4,
308 num_transitions, f)
9c7ff11a 309 != num_transitions, 0)
5a6fa4d7
JM
310 || __builtin_expect (__fread_unlocked (type_idxs, 1, num_transitions,
311 f) != num_transitions, 0))
28f540f4
RM
312 goto lose;
313 }
314
5290baf0
UD
315 /* Check for bogus indices in the data file, so we can hereafter
316 safely use type_idxs[T] as indices into `types' and never crash. */
317 for (i = 0; i < num_transitions; ++i)
a1ffb40e 318 if (__glibc_unlikely (type_idxs[i] >= num_types))
5290baf0
UD
319 goto lose;
320
11bf311e
UD
321 if ((BYTE_ORDER != BIG_ENDIAN && (sizeof (time_t) == 4 || trans_width == 4))
322 || (BYTE_ORDER == BIG_ENDIAN && sizeof (time_t) == 8
323 && trans_width == 4))
a2cafe30
RM
324 {
325 /* Decode the transition times, stored as 4-byte integers in
326 network (big-endian) byte order. We work from the end of
327 the array so as not to clobber the next element to be
328 processed when sizeof (time_t) > 4. */
329 i = num_transitions;
b20e47cb 330 while (i-- > 0)
a3e0e9ae 331 transitions[i] = decode ((char *) transitions + i * 4);
a2cafe30 332 }
11bf311e
UD
333 else if (BYTE_ORDER != BIG_ENDIAN && sizeof (time_t) == 8)
334 {
335 /* Decode the transition times, stored as 8-byte integers in
336 network (big-endian) byte order. */
337 for (i = 0; i < num_transitions; ++i)
338 transitions[i] = decode64 ((char *) transitions + i * 8);
339 }
28f540f4
RM
340
341 for (i = 0; i < num_types; ++i)
342 {
343 unsigned char x[4];
c4563d2d 344 int c;
5a6fa4d7
JM
345 if (__builtin_expect (__fread_unlocked (x, 1,
346 sizeof (x), f) != sizeof (x),
9c7ff11a 347 0))
28f540f4 348 goto lose;
c4563d2d 349 c = getc_unlocked (f);
a1ffb40e 350 if (__glibc_unlikely ((unsigned int) c > 1u))
8b7fb588 351 goto lose;
c4563d2d
UD
352 types[i].isdst = c;
353 c = getc_unlocked (f);
a1ffb40e 354 if (__glibc_unlikely ((size_t) c > chars))
9c7ff11a 355 /* Bogus index in data file. */
5290baf0 356 goto lose;
c4563d2d 357 types[i].idx = c;
a2cafe30 358 types[i].offset = (long int) decode (x);
28f540f4
RM
359 }
360
5a6fa4d7 361 if (__glibc_unlikely (__fread_unlocked (zone_names, 1, chars, f) != chars))
28f540f4
RM
362 goto lose;
363
364 for (i = 0; i < num_leaps; ++i)
365 {
11bf311e 366 unsigned char x[8];
5a6fa4d7 367 if (__builtin_expect (__fread_unlocked (x, 1, trans_width, f)
11bf311e 368 != trans_width, 0))
28f540f4 369 goto lose;
11bf311e
UD
370 if (sizeof (time_t) == 4 || trans_width == 4)
371 leaps[i].transition = (time_t) decode (x);
372 else
373 leaps[i].transition = (time_t) decode64 (x);
374
5a6fa4d7 375 if (__glibc_unlikely (__fread_unlocked (x, 1, 4, f) != 4))
28f540f4 376 goto lose;
a2cafe30 377 leaps[i].change = (long int) decode (x);
28f540f4
RM
378 }
379
380 for (i = 0; i < num_isstd; ++i)
381 {
ba9234d9 382 int c = getc_unlocked (f);
a1ffb40e 383 if (__glibc_unlikely (c == EOF))
28f540f4
RM
384 goto lose;
385 types[i].isstd = c != 0;
386 }
387 while (i < num_types)
388 types[i++].isstd = 0;
389
98fa1d6e
RM
390 for (i = 0; i < num_isgmt; ++i)
391 {
ba9234d9 392 int c = getc_unlocked (f);
a1ffb40e 393 if (__glibc_unlikely (c == EOF))
98fa1d6e
RM
394 goto lose;
395 types[i].isgmt = c != 0;
396 }
397 while (i < num_types)
398 types[i++].isgmt = 0;
399
fa76dde2 400 /* Read the POSIX TZ-style information if possible. */
c6d381d3 401 if (sizeof (time_t) == 8 && tzspec != NULL)
fa76dde2
UD
402 {
403 /* Skip over the newline first. */
404 if (getc_unlocked (f) != '\n'
5a6fa4d7 405 || (__fread_unlocked (tzspec, 1, tzspec_len - 1, f)
c6d381d3 406 != tzspec_len - 1))
fa76dde2
UD
407 tzspec = NULL;
408 else
409 tzspec[tzspec_len - 1] = '\0';
410 }
94a749f6 411 else if (sizeof (time_t) == 4 && tzhead.tzh_version[0] != '\0')
c6d381d3
UD
412 {
413 /* Get the TZ string. */
5a6fa4d7
JM
414 if (__builtin_expect (__fread_unlocked ((void *) &tzhead,
415 sizeof (tzhead), 1, f) != 1, 0)
c6d381d3
UD
416 || (memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic))
417 != 0))
418 goto lose;
419
420 size_t num_transitions2 = (size_t) decode (tzhead.tzh_timecnt);
421 size_t num_types2 = (size_t) decode (tzhead.tzh_typecnt);
422 size_t chars2 = (size_t) decode (tzhead.tzh_charcnt);
423 size_t num_leaps2 = (size_t) decode (tzhead.tzh_leapcnt);
424 size_t num_isstd2 = (size_t) decode (tzhead.tzh_ttisstdcnt);
425 size_t num_isgmt2 = (size_t) decode (tzhead.tzh_ttisgmtcnt);
426
427 /* Position the stream before the second header. */
428 size_t to_skip = (num_transitions2 * (8 + 1)
429 + num_types2 * 6
430 + chars2
431 + num_leaps2 * 12
432 + num_isstd2
433 + num_isgmt2);
434 off_t off;
435 if (fseek (f, to_skip, SEEK_CUR) != 0
5a6fa4d7 436 || (off = __ftello (f)) < 0
c6d381d3
UD
437 || st.st_size < off + 2)
438 goto lose;
439
440 tzspec_len = st.st_size - off - 1;
42261ad7
FW
441 if (tzspec_len == 0)
442 goto lose;
443 char *tzstr = malloc (tzspec_len);
444 if (tzstr == NULL)
445 goto lose;
c6d381d3 446 if (getc_unlocked (f) != '\n'
5a6fa4d7
JM
447 || (__fread_unlocked (tzstr, 1, tzspec_len - 1, f)
448 != tzspec_len - 1))
42261ad7
FW
449 {
450 free (tzstr);
451 goto lose;
452 }
c6d381d3
UD
453 tzstr[tzspec_len - 1] = '\0';
454 tzspec = __tzstring (tzstr);
42261ad7 455 free (tzstr);
c6d381d3 456 }
11bf311e 457
7a7c2c24
AS
458 /* Don't use an empty TZ string. */
459 if (tzspec != NULL && tzspec[0] == '\0')
460 tzspec = NULL;
461
860d3729
UD
462 fclose (f);
463
a3e0e9ae
UD
464 /* First "register" all timezone names. */
465 for (i = 0; i < num_types; ++i)
466 (void) __tzstring (&zone_names[types[i].idx]);
467
ff152e3f
UD
468 /* Find the standard and daylight time offsets used by the rule file.
469 We choose the offsets in the types of each flavor that are
470 transitioned to earliest in time. */
a3e0e9ae 471 __tzname[0] = NULL;
ff152e3f 472 __tzname[1] = NULL;
a3e0e9ae
UD
473 for (i = num_transitions; i > 0; )
474 {
475 int type = type_idxs[--i];
476 int dst = types[type].isdst;
a3e0e9ae
UD
477
478 if (__tzname[dst] == NULL)
479 {
d3345073
UD
480 int idx = types[type].idx;
481
a3e0e9ae
UD
482 __tzname[dst] = __tzstring (&zone_names[idx]);
483
484 if (__tzname[1 - dst] != NULL)
485 break;
486 }
487 }
488 if (__tzname[0] == NULL)
489 {
490 /* This should only happen if there are no transition rules.
491 In this case there should be only one single type. */
492 assert (num_types == 1);
493 __tzname[0] = __tzstring (zone_names);
494 }
ff152e3f
UD
495 if (__tzname[1] == NULL)
496 __tzname[1] = __tzname[0];
28f540f4
RM
497
498 compute_tzname_max (chars);
a3b58440 499
90865aa8 500 if (num_transitions == 0)
0155a773 501 /* Use the first rule (which should also be the only one). */
90865aa8
UD
502 rule_stdoff = rule_dstoff = types[0].offset;
503 else
ff152e3f 504 {
d16e36e0 505 int stdoff_set = 0, dstoff_set = 0;
90865aa8 506 rule_stdoff = rule_dstoff = 0;
d3345073
UD
507 i = num_transitions - 1;
508 do
90865aa8 509 {
d16e36e0
AS
510 if (!stdoff_set && !types[type_idxs[i]].isdst)
511 {
512 stdoff_set = 1;
513 rule_stdoff = types[type_idxs[i]].offset;
514 }
d3345073 515 else if (!dstoff_set && types[type_idxs[i]].isdst)
d16e36e0
AS
516 {
517 dstoff_set = 1;
518 rule_dstoff = types[type_idxs[i]].offset;
519 }
520 if (stdoff_set && dstoff_set)
90865aa8
UD
521 break;
522 }
d3345073
UD
523 while (i-- > 0);
524
d16e36e0
AS
525 if (!dstoff_set)
526 rule_dstoff = rule_stdoff;
ff152e3f
UD
527 }
528
529 __daylight = rule_stdoff != rule_dstoff;
530 __timezone = -rule_stdoff;
531
45c30c61 532 done:
28f540f4 533 __use_tzfile = 1;
45c30c61 534 free (new);
28f540f4
RM
535 return;
536
ba9234d9
UD
537 lose:
538 fclose (f);
640b76b7 539 ret_free_transitions:
45c30c61 540 free (new);
640b76b7
UD
541 free ((void *) transitions);
542 transitions = NULL;
28f540f4
RM
543}
544\f
98fa1d6e
RM
545/* The user specified a hand-made timezone, but not its DST rules.
546 We will use the names and offsets from the user, and the rules
547 from the TZDEFRULES file. */
548
28f540f4 549void
cd6ede75
UD
550__tzfile_default (const char *std, const char *dst,
551 long int stdoff, long int dstoff)
28f540f4 552{
c4563d2d
UD
553 size_t stdlen = strlen (std) + 1;
554 size_t dstlen = strlen (dst) + 1;
555 size_t i;
98fa1d6e 556 int isdst;
c4563d2d 557 char *cp;
28f540f4 558
c4563d2d 559 __tzfile_read (TZDEFRULES, stdlen + dstlen, &cp);
28f540f4
RM
560 if (!__use_tzfile)
561 return;
562
563 if (num_types < 2)
564 {
565 __use_tzfile = 0;
566 return;
567 }
568
c4563d2d
UD
569 /* Ignore the zone names read from the file and use the given ones
570 instead. */
571 __mempcpy (__mempcpy (cp, std, stdlen), dst, dstlen);
572 zone_names = cp;
28f540f4 573
88455219
UD
574 /* Now there are only two zones, regardless of what the file contained. */
575 num_types = 2;
576
98fa1d6e
RM
577 /* Now correct the transition times for the user-specified standard and
578 daylight offsets from GMT. */
579 isdst = 0;
98fa1d6e
RM
580 for (i = 0; i < num_transitions; ++i)
581 {
582 struct ttinfo *trans_type = &types[type_idxs[i]];
583
584 /* We will use only types 0 (standard) and 1 (daylight).
585 Fix up this transition to point to whichever matches
586 the flavor of its original type. */
587 type_idxs[i] = trans_type->isdst;
588
589 if (trans_type->isgmt)
590 /* The transition time is in GMT. No correction to apply. */ ;
591 else if (isdst && !trans_type->isstd)
592 /* The type says this transition is in "local wall clock time", and
593 wall clock time as of the previous transition was DST. Correct
594 for the difference between the rule's DST offset and the user's
595 DST offset. */
596 transitions[i] += dstoff - rule_dstoff;
597 else
598 /* This transition is in "local wall clock time", and wall clock
599 time as of this iteration is non-DST. Correct for the
600 difference between the rule's standard offset and the user's
601 standard offset. */
602 transitions[i] += stdoff - rule_stdoff;
603
604 /* The DST state of "local wall clock time" for the next iteration is
605 as specified by this transition. */
606 isdst = trans_type->isdst;
607 }
608
4c326621
UD
609 /* Now that we adjusted the transitions to the requested offsets,
610 reset the rule_stdoff and rule_dstoff values appropriately. They
611 are used elsewhere. */
612 rule_stdoff = stdoff;
613 rule_dstoff = dstoff;
614
98fa1d6e
RM
615 /* Reset types 0 and 1 to describe the user's settings. */
616 types[0].idx = 0;
617 types[0].offset = stdoff;
618 types[0].isdst = 0;
619 types[1].idx = stdlen;
620 types[1].offset = dstoff;
621 types[1].isdst = 1;
28f540f4 622
5290baf0 623 /* Reset the zone names to point to the user's names. */
cd6ede75
UD
624 __tzname[0] = (char *) std;
625 __tzname[1] = (char *) dst;
5290baf0 626
90865aa8
UD
627 /* Set the timezone. */
628 __timezone = -types[0].offset;
629
28f540f4
RM
630 compute_tzname_max (stdlen + dstlen);
631}
632\f
fa76dde2
UD
633void
634__tzfile_compute (time_t timer, int use_localtime,
635 long int *leap_correct, int *leap_hit,
636 struct tm *tp)
28f540f4 637{
2e09a79a 638 size_t i;
89dc9d4c 639
fa76dde2 640 if (use_localtime)
28f540f4 641 {
fa76dde2
UD
642 __tzname[0] = NULL;
643 __tzname[1] = NULL;
644
a1ffb40e 645 if (__glibc_unlikely (num_transitions == 0 || timer < transitions[0]))
89dc9d4c 646 {
fa76dde2
UD
647 /* TIMER is before any transition (or there are no transitions).
648 Choose the first non-DST type
649 (or the first if they're all DST types). */
650 i = 0;
651 while (i < num_types && types[i].isdst)
652 {
653 if (__tzname[1] == NULL)
654 __tzname[1] = __tzstring (&zone_names[types[i].idx]);
89dc9d4c 655
fa76dde2
UD
656 ++i;
657 }
89dc9d4c 658
fa76dde2
UD
659 if (i == num_types)
660 i = 0;
661 __tzname[0] = __tzstring (&zone_names[types[i].idx]);
662 if (__tzname[1] == NULL)
663 {
664 size_t j = i;
665 while (j < num_types)
666 if (types[j].isdst)
667 {
668 __tzname[1] = __tzstring (&zone_names[types[j].idx]);
669 break;
670 }
671 else
672 ++j;
673 }
674 }
a1ffb40e 675 else if (__glibc_unlikely (timer >= transitions[num_transitions - 1]))
89dc9d4c 676 {
a1ffb40e 677 if (__glibc_unlikely (tzspec == NULL))
fa76dde2
UD
678 {
679 use_last:
e2cceb5a 680 i = num_transitions;
fa76dde2
UD
681 goto found;
682 }
683
684 /* Parse the POSIX TZ-style string. */
685 __tzset_parse_tz (tzspec);
686
687 /* Convert to broken down structure. If this fails do not
688 use the string. */
a1ffb40e 689 if (__glibc_unlikely (! __offtime (&timer, 0, tp)))
fa76dde2
UD
690 goto use_last;
691
692 /* Use the rules from the TZ string to compute the change. */
693 __tz_compute (timer, tp, 1);
694
c6d381d3
UD
695 /* If tzspec comes from posixrules loaded by __tzfile_default,
696 override the STD and DST zone names with the ones user
697 requested in TZ envvar. */
a1ffb40e 698 if (__glibc_unlikely (zone_names == (char *) &leaps[num_leaps]))
c6d381d3
UD
699 {
700 assert (num_types == 2);
701 __tzname[0] = __tzstring (zone_names);
702 __tzname[1] = __tzstring (&zone_names[strlen (zone_names) + 1]);
703 }
704
29143408 705 goto leap;
89dc9d4c 706 }
fa76dde2 707 else
13252678 708 {
fa76dde2
UD
709 /* Find the first transition after TIMER, and
710 then pick the type of the transition before it. */
711 size_t lo = 0;
712 size_t hi = num_transitions - 1;
713 /* Assume that DST is changing twice a year and guess initial
714 search spot from it.
715 Half of a gregorian year has on average 365.2425 * 86400 / 2
716 = 15778476 seconds. */
717 i = (transitions[num_transitions - 1] - timer) / 15778476;
718 if (i < num_transitions)
13252678 719 {
fa76dde2
UD
720 i = num_transitions - 1 - i;
721 if (timer < transitions[i])
13252678 722 {
fa76dde2
UD
723 if (i < 10 || timer >= transitions[i - 10])
724 {
725 /* Linear search. */
726 while (timer < transitions[i - 1])
727 --i;
728 goto found;
729 }
730 hi = i - 10;
13252678 731 }
fa76dde2 732 else
13252678 733 {
fa76dde2
UD
734 if (i + 10 >= num_transitions || timer < transitions[i + 10])
735 {
736 /* Linear search. */
737 while (timer >= transitions[i])
738 ++i;
739 goto found;
740 }
741 lo = i + 10;
13252678 742 }
13252678 743 }
13252678 744
fa76dde2
UD
745 /* Binary search. */
746 /* assert (timer >= transitions[lo] && timer < transitions[hi]); */
747 while (lo + 1 < hi)
748 {
749 i = (lo + hi) / 2;
750 if (timer < transitions[i])
751 hi = i;
752 else
753 lo = i;
754 }
755 i = hi;
89dc9d4c 756
fa76dde2 757 found:
e2cceb5a
UD
758 /* assert (timer >= transitions[i - 1]
759 && (i == num_transitions || timer < transitions[i])); */
fa76dde2
UD
760 __tzname[types[type_idxs[i - 1]].isdst]
761 = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
762 size_t j = i;
763 while (j < num_transitions)
89dc9d4c 764 {
fa76dde2
UD
765 int type = type_idxs[j];
766 int dst = types[type].isdst;
767 int idx = types[type].idx;
89dc9d4c 768
fa76dde2
UD
769 if (__tzname[dst] == NULL)
770 {
771 __tzname[dst] = __tzstring (&zone_names[idx]);
89dc9d4c 772
fa76dde2
UD
773 if (__tzname[1 - dst] != NULL)
774 break;
775 }
89dc9d4c 776
fa76dde2
UD
777 ++j;
778 }
28f540f4 779
a1ffb40e 780 if (__glibc_unlikely (__tzname[0] == NULL))
c6d381d3
UD
781 __tzname[0] = __tzname[1];
782
fa76dde2
UD
783 i = type_idxs[i - 1];
784 }
860d3729 785
fa76dde2 786 struct ttinfo *info = &types[i];
ff152e3f
UD
787 __daylight = rule_stdoff != rule_dstoff;
788 __timezone = -rule_stdoff;
a3e0e9ae 789
a3e0e9ae
UD
790 if (__tzname[0] == NULL)
791 {
792 /* This should only happen if there are no transition rules.
793 In this case there should be only one single type. */
794 assert (num_types == 1);
795 __tzname[0] = __tzstring (zone_names);
796 }
ff152e3f
UD
797 if (__tzname[1] == NULL)
798 /* There is no daylight saving time. */
799 __tzname[1] = __tzname[0];
a709dd43 800 tp->tm_isdst = info->isdst;
89dc9d4c
UD
801 assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
802 tp->tm_zone = __tzname[tp->tm_isdst];
a709dd43 803 tp->tm_gmtoff = info->offset;
9a0a462c 804 }
28f540f4 805
29143408 806 leap:
28f540f4
RM
807 *leap_correct = 0L;
808 *leap_hit = 0;
809
810 /* Find the last leap second correction transition time before TIMER. */
811 i = num_leaps;
812 do
813 if (i-- == 0)
38e68573 814 return;
28f540f4
RM
815 while (timer < leaps[i].transition);
816
817 /* Apply its correction. */
818 *leap_correct = leaps[i].change;
819
820 if (timer == leaps[i].transition && /* Exactly at the transition time. */
821 ((i == 0 && leaps[i].change > 0) ||
822 leaps[i].change > leaps[i - 1].change))
823 {
824 *leap_hit = 1;
ba9234d9
UD
825 while (i > 0
826 && leaps[i].transition == leaps[i - 1].transition + 1
827 && leaps[i].change == leaps[i - 1].change + 1)
28f540f4
RM
828 {
829 ++*leap_hit;
830 --i;
831 }
832 }
28f540f4
RM
833}
834\f
9a0a462c 835static void
dfd2257a 836internal_function
860d3729 837compute_tzname_max (size_t chars)
28f540f4 838{
28f540f4
RM
839 const char *p;
840
841 p = zone_names;
842 do
843 {
844 const char *start = p;
845 while (*p != '\0')
846 ++p;
5290baf0 847 if ((size_t) (p - start) > __tzname_cur_max)
28f540f4 848 __tzname_cur_max = p - start;
ba9234d9
UD
849 }
850 while (++p < &zone_names[chars]);
28f540f4 851}