mirror of
https://sourceware.org/git/glibc.git
synced 2025-08-08 17:42:12 +03:00
.
This commit is contained in:
114
time/tzfile.c
114
time/tzfile.c
@@ -1,5 +1,4 @@
|
||||
/* Copyright (C) 1991-1993,1995-2001,2003,2004,2006
|
||||
Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1991-1993,1995-2001,2003,2004 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
@@ -72,34 +71,24 @@ static inline int
|
||||
__attribute ((always_inline))
|
||||
decode (const void *ptr)
|
||||
{
|
||||
if (BYTE_ORDER == BIG_ENDIAN && sizeof (int) == 4)
|
||||
if ((BYTE_ORDER == BIG_ENDIAN) && sizeof (int) == 4)
|
||||
return *(const int *) ptr;
|
||||
if (sizeof (int) == 4)
|
||||
else if (BYTE_ORDER == LITTLE_ENDIAN && sizeof (int) == 4)
|
||||
return bswap_32 (*(const int *) ptr);
|
||||
else
|
||||
{
|
||||
const unsigned char *p = ptr;
|
||||
int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
|
||||
|
||||
const unsigned char *p = ptr;
|
||||
int result = *p & (1 << (CHAR_BIT - 1)) ? ~0 : 0;
|
||||
result = (result << 8) | *p++;
|
||||
result = (result << 8) | *p++;
|
||||
result = (result << 8) | *p++;
|
||||
result = (result << 8) | *p++;
|
||||
|
||||
result = (result << 8) | *p++;
|
||||
result = (result << 8) | *p++;
|
||||
result = (result << 8) | *p++;
|
||||
result = (result << 8) | *p++;
|
||||
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline int64_t
|
||||
__attribute ((always_inline))
|
||||
decode64 (const void *ptr)
|
||||
{
|
||||
if ((BYTE_ORDER == BIG_ENDIAN))
|
||||
return *(const int64_t *) ptr;
|
||||
|
||||
return bswap_64 (*(const int64_t *) ptr);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
__tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
{
|
||||
@@ -113,10 +102,6 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
size_t types_idx;
|
||||
size_t leaps_idx;
|
||||
int was_using_tzfile = __use_tzfile;
|
||||
int trans_width = 4;
|
||||
|
||||
if (sizeof (time_t) != 4 && sizeof (time_t) != 8)
|
||||
abort ();
|
||||
|
||||
__use_tzfile = 0;
|
||||
|
||||
@@ -200,10 +185,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
/* No threads reading this stream. */
|
||||
__fsetlocking (f, FSETLOCKING_BYCALLER);
|
||||
|
||||
read_again:
|
||||
if (__builtin_expect (fread_unlocked ((void *) &tzhead, sizeof (tzhead),
|
||||
1, f) != 1, 0)
|
||||
|| memcmp (tzhead.tzh_magic, TZ_MAGIC, sizeof (tzhead.tzh_magic)) != 0)
|
||||
1, f) != 1, 0))
|
||||
goto lose;
|
||||
|
||||
num_transitions = (size_t) decode (tzhead.tzh_timecnt);
|
||||
@@ -213,26 +196,6 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
num_isstd = (size_t) decode (tzhead.tzh_ttisstdcnt);
|
||||
num_isgmt = (size_t) decode (tzhead.tzh_ttisgmtcnt);
|
||||
|
||||
/* For platforms with 64-bit time_t we use the new format if available. */
|
||||
if (sizeof (time_t) == 8 && trans_width == 4
|
||||
&& tzhead.tzh_version[0] != '\0')
|
||||
{
|
||||
/* We use the 8-byte format. */
|
||||
trans_width = 8;
|
||||
|
||||
/* Position the stream before the second header. */
|
||||
size_t to_skip = (num_transitions * (4 + 1)
|
||||
+ num_types * 6
|
||||
+ chars
|
||||
+ num_leaps * 8
|
||||
+ num_isstd
|
||||
+ num_isgmt);
|
||||
if (fseek (f, to_skip, SEEK_CUR) != 0)
|
||||
goto lose;
|
||||
|
||||
goto read_again;
|
||||
}
|
||||
|
||||
total_size = num_transitions * (sizeof (time_t) + 1);
|
||||
total_size = ((total_size + __alignof__ (struct ttinfo) - 1)
|
||||
& ~(__alignof__ (struct ttinfo) - 1));
|
||||
@@ -242,10 +205,10 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
& ~(__alignof__ (struct leap) - 1));
|
||||
leaps_idx = total_size;
|
||||
total_size += num_leaps * sizeof (struct leap);
|
||||
/* This is for the extra memory required by the caller. */
|
||||
total_size += extra;
|
||||
|
||||
/* Allocate enough memory including the extra block requested by the
|
||||
caller. */
|
||||
transitions = (time_t *) malloc (total_size + extra);
|
||||
transitions = (time_t *) malloc (total_size);
|
||||
if (transitions == NULL)
|
||||
goto lose;
|
||||
|
||||
@@ -257,11 +220,14 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
if (extra > 0)
|
||||
*extrap = (char *) &leaps[num_leaps];
|
||||
|
||||
if (sizeof (time_t) == 4 || trans_width == 8)
|
||||
if (sizeof (time_t) < 4)
|
||||
abort ();
|
||||
|
||||
if (sizeof (time_t) == 4)
|
||||
{
|
||||
if (__builtin_expect (fread_unlocked (transitions, trans_width + 1,
|
||||
num_transitions, f)
|
||||
!= num_transitions, 0))
|
||||
if (__builtin_expect (fread_unlocked (transitions, 1,
|
||||
(4 + 1) * num_transitions, f)
|
||||
!= (4 + 1) * num_transitions, 0))
|
||||
goto lose;
|
||||
}
|
||||
else
|
||||
@@ -279,9 +245,7 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
if (__builtin_expect (type_idxs[i] >= num_types, 0))
|
||||
goto lose;
|
||||
|
||||
if ((BYTE_ORDER != BIG_ENDIAN && (sizeof (time_t) == 4 || trans_width == 4))
|
||||
|| (BYTE_ORDER == BIG_ENDIAN && sizeof (time_t) == 8
|
||||
&& trans_width == 4))
|
||||
if (BYTE_ORDER != BIG_ENDIAN || sizeof (time_t) != 4)
|
||||
{
|
||||
/* Decode the transition times, stored as 4-byte integers in
|
||||
network (big-endian) byte order. We work from the end of
|
||||
@@ -291,13 +255,6 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
while (i-- > 0)
|
||||
transitions[i] = decode ((char *) transitions + i * 4);
|
||||
}
|
||||
else if (BYTE_ORDER != BIG_ENDIAN && sizeof (time_t) == 8)
|
||||
{
|
||||
/* Decode the transition times, stored as 8-byte integers in
|
||||
network (big-endian) byte order. */
|
||||
for (i = 0; i < num_transitions; ++i)
|
||||
transitions[i] = decode64 ((char *) transitions + i * 8);
|
||||
}
|
||||
|
||||
for (i = 0; i < num_types; ++i)
|
||||
{
|
||||
@@ -323,16 +280,13 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
|
||||
for (i = 0; i < num_leaps; ++i)
|
||||
{
|
||||
unsigned char x[8];
|
||||
if (__builtin_expect (fread_unlocked (x, 1, trans_width, f)
|
||||
!= trans_width, 0))
|
||||
unsigned char x[4];
|
||||
if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x),
|
||||
0))
|
||||
goto lose;
|
||||
if (sizeof (time_t) == 4 || trans_width == 4)
|
||||
leaps[i].transition = (time_t) decode (x);
|
||||
else
|
||||
leaps[i].transition = (time_t) decode64 (x);
|
||||
|
||||
if (__builtin_expect (fread_unlocked (x, 1, 4, f) != 4, 0))
|
||||
leaps[i].transition = (time_t) decode (x);
|
||||
if (__builtin_expect (fread_unlocked (x, 1, sizeof (x), f) != sizeof (x),
|
||||
0))
|
||||
goto lose;
|
||||
leaps[i].change = (long int) decode (x);
|
||||
}
|
||||
@@ -357,12 +311,6 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
|
||||
while (i < num_types)
|
||||
types[i++].isgmt = 0;
|
||||
|
||||
/* XXX When a version 2 file is available it can contain a POSIX TZ-style
|
||||
formatted string which specifies how times past the last one specified
|
||||
are supposed to be handled. We might want to handle this at some
|
||||
point. But it might be overhead since most/all? files have an
|
||||
open-ended last entry. */
|
||||
|
||||
fclose (f);
|
||||
|
||||
/* First "register" all timezone names. */
|
||||
|
Reference in New Issue
Block a user