LCOV - code coverage report
Current view: top level - timelib - parse_tz.c (source / functions) Coverage Total Hit
Test: Coverage Report Lines: 6.8 % 512 35
Test Date: 2025-09-24 08:46:11 Functions: - 0 0

            Line data    Source code
       1              : /*
       2              :  * The MIT License (MIT)
       3              :  *
       4              :  * Copyright (c) 2015-2019 Derick Rethans
       5              :  * Copyright (c) 2018 MongoDB, Inc.
       6              :  *
       7              :  * Permission is hereby granted, free of charge, to any person obtaining a copy
       8              :  * of this software and associated documentation files (the "Software"), to deal
       9              :  * in the Software without restriction, including without limitation the rights
      10              :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      11              :  * copies of the Software, and to permit persons to whom the Software is
      12              :  * furnished to do so, subject to the following conditions:
      13              :  *
      14              :  * The above copyright notice and this permission notice shall be included in
      15              :  * all copies or substantial portions of the Software.
      16              :  *
      17              :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      18              :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      19              :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      20              :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      21              :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      22              :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      23              :  * THE SOFTWARE.
      24              :  */
      25              : 
      26              : #include "timelib.h"
      27              : #include "timelib_private.h"
      28              : 
      29              : #define TIMELIB_SUPPORTS_V2DATA
      30              : #define TIMELIB_SUPPORT_SLIM_FILE
      31              : #include "timezonedb.h"
      32              : 
      33              : #if (defined(__APPLE__) || defined(__APPLE_CC__)) && (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
      34              : # if defined(__LITTLE_ENDIAN__)
      35              : #  undef WORDS_BIGENDIAN
      36              : # else
      37              : #  if defined(__BIG_ENDIAN__)
      38              : #   define WORDS_BIGENDIAN
      39              : #  endif
      40              : # endif
      41              : #endif
      42              : 
      43              : #if (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN))
      44              : # if __BYTE_ORDER == __BIG_ENDIAN
      45              : #  define WORDS_BIGENDIAN
      46              : # endif
      47              : #endif
      48              : 
      49              : #if defined(__s390__)
      50              : # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
      51              : #  define WORDS_BIGENDIAN
      52              : # else
      53              : #  undef WORDS_BIGENDIAN
      54              : # endif
      55              : #endif
      56              : 
      57              : #ifdef WORDS_BIGENDIAN
      58              : static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
      59              : {
      60              :         return value;
      61              : }
      62              : 
      63              : static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
      64              : {
      65              :         return value;
      66              : }
      67              : #else
      68            0 : static inline uint32_t timelib_conv_int_unsigned(uint32_t value)
      69              : {
      70              :         return
      71            0 :                 ((value & 0x000000ff) << 24) +
      72            0 :                 ((value & 0x0000ff00) <<  8) +
      73            0 :                 ((value & 0x00ff0000) >>  8) +
      74            0 :                 ((value & 0xff000000) >> 24);
      75              : }
      76              : 
      77            0 : static inline uint64_t timelib_conv_int64_unsigned(uint64_t value)
      78              : {
      79              :         return
      80            0 :                 ((value & 0x00000000000000ff) << 56) +
      81            0 :                 ((value & 0x000000000000ff00) << 40) +
      82            0 :                 ((value & 0x0000000000ff0000) << 24) +
      83            0 :                 ((value & 0x00000000ff000000) <<  8) +
      84            0 :                 ((value & 0x000000ff00000000) >>  8) +
      85            0 :                 ((value & 0x0000ff0000000000) >> 24) +
      86            0 :                 ((value & 0x00ff000000000000) >> 40) +
      87            0 :                 ((value & 0xff00000000000000) >> 56);
      88              : }
      89              : #endif
      90              : 
      91              : #define timelib_conv_int_signed(value) ((int32_t) timelib_conv_int_unsigned((int32_t) value))
      92              : #define timelib_conv_int64_signed(value) ((int64_t) timelib_conv_int64_unsigned((int64_t) value))
      93              : 
      94            0 : static int read_php_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
      95              : {
      96              :         uint32_t version;
      97              : 
      98              :         /* read ID */
      99            0 :         version = (*tzf)[3] - '0';
     100            0 :         *tzf += 4;
     101              : 
     102              :         /* read BC flag */
     103            0 :         tz->bc = (**tzf == '\1');
     104            0 :         *tzf += 1;
     105              : 
     106              :         /* read country code */
     107            0 :         memcpy(tz->location.country_code, *tzf, 2);
     108            0 :         tz->location.country_code[2] = '\0';
     109            0 :         *tzf += 2;
     110              : 
     111              :         /* skip rest of preamble */
     112            0 :         *tzf += 13;
     113              : 
     114            0 :         return version;
     115              : }
     116              : 
     117            0 : static int read_tzif_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
     118              : {
     119              :         uint32_t version;
     120              : 
     121              :         /* read ID */
     122            0 :         switch ((*tzf)[4]) {
     123            0 :                 case '\0':
     124            0 :                         version = 0;
     125            0 :                         break;
     126            0 :                 case '2':
     127            0 :                         version = 2;
     128            0 :                         break;
     129            0 :                 case '3':
     130            0 :                         version = 3;
     131            0 :                         break;
     132            0 :                 case '4':
     133            0 :                         version = 4;
     134            0 :                         break;
     135            0 :                 default:
     136            0 :                         return -1;
     137              :         }
     138            0 :         *tzf += 5;
     139              : 
     140              :         /* set BC flag and country code to default */
     141            0 :         tz->bc = 0;
     142            0 :         tz->location.country_code[0] = '?';
     143            0 :         tz->location.country_code[1] = '?';
     144            0 :         tz->location.country_code[2] = '\0';
     145              : 
     146              :         /* skip rest of preamble */
     147            0 :         *tzf += 15;
     148              : 
     149            0 :         return version;
     150              : }
     151              : 
     152            0 : static int read_preamble(const unsigned char **tzf, timelib_tzinfo *tz, unsigned int *type)
     153              : {
     154              :         /* read marker (TZif) or (PHP) */
     155            0 :         if (memcmp(*tzf, "PHP", 3) == 0) {
     156            0 :                 *type = TIMELIB_TZINFO_PHP;
     157            0 :                 return read_php_preamble(tzf, tz);
     158            0 :         } else if (memcmp(*tzf, "TZif", 4) == 0) {
     159            0 :                 *type = TIMELIB_TZINFO_ZONEINFO;
     160            0 :                 return read_tzif_preamble(tzf, tz);
     161              :         } else {
     162            0 :                 return -1;
     163              :         }
     164              : }
     165              : 
     166            0 : static void read_32bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
     167              : {
     168              :         uint32_t buffer[6];
     169              : 
     170            0 :         memcpy(&buffer, *tzf, sizeof(buffer));
     171            0 :         tz->_bit32.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
     172            0 :         tz->_bit32.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
     173            0 :         tz->_bit32.leapcnt    = timelib_conv_int_unsigned(buffer[2]);
     174            0 :         tz->_bit32.timecnt    = timelib_conv_int_unsigned(buffer[3]);
     175            0 :         tz->_bit32.typecnt    = timelib_conv_int_unsigned(buffer[4]);
     176            0 :         tz->_bit32.charcnt    = timelib_conv_int_unsigned(buffer[5]);
     177              : 
     178            0 :         *tzf += sizeof(buffer);
     179            0 : }
     180              : 
     181            0 : static int detect_slim_file(timelib_tzinfo *tz)
     182              : {
     183            0 :         if (
     184            0 :                 (tz->_bit32.ttisgmtcnt == 0) &&
     185            0 :                 (tz->_bit32.ttisstdcnt == 0) &&
     186            0 :                 (tz->_bit32.leapcnt    == 0) &&
     187            0 :                 (tz->_bit32.timecnt    == 0) &&
     188            0 :                 (tz->_bit32.typecnt    == 1) &&
     189            0 :                 (tz->_bit32.charcnt    == 1)
     190              :         ) {
     191            0 :                 return 1;
     192              :         }
     193              : 
     194            0 :         return 0;
     195              : }
     196              : 
     197            0 : static int read_64bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
     198              : {
     199            0 :         int64_t *buffer = NULL;
     200              :         uint32_t i;
     201            0 :         unsigned char *cbuffer = NULL;
     202              : 
     203            0 :         if (tz->bit64.timecnt) {
     204            0 :                 buffer = (int64_t*) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
     205            0 :                 if (!buffer) {
     206            0 :                         return TIMELIB_ERROR_CANNOT_ALLOCATE;
     207              :                 }
     208            0 :                 memcpy(buffer, *tzf, sizeof(int64_t) * tz->bit64.timecnt);
     209            0 :                 *tzf += (sizeof(int64_t) * tz->bit64.timecnt);
     210            0 :                 for (i = 0; i < tz->bit64.timecnt; i++) {
     211            0 :                         buffer[i] = timelib_conv_int64_signed(buffer[i]);
     212              :                         /* Sanity check to see whether TS is just increasing */
     213            0 :                         if (i > 0 && !(buffer[i] > buffer[i - 1])) {
     214            0 :                                 timelib_free(buffer);
     215            0 :                                 return TIMELIB_ERROR_CORRUPT_TRANSITIONS_DONT_INCREASE;
     216              :                         }
     217              :                 }
     218              : 
     219            0 :                 cbuffer = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
     220            0 :                 if (!cbuffer) {
     221            0 :                         timelib_free(buffer);
     222            0 :                         return TIMELIB_ERROR_CANNOT_ALLOCATE;
     223              :                 }
     224            0 :                 memcpy(cbuffer, *tzf, sizeof(unsigned char) * tz->bit64.timecnt);
     225            0 :                 *tzf += sizeof(unsigned char) * tz->bit64.timecnt;
     226              :         }
     227              : 
     228            0 :         tz->trans = buffer;
     229            0 :         tz->trans_idx = cbuffer;
     230              : 
     231            0 :         return 0;
     232              : }
     233              : 
     234            0 : static void skip_32bit_transitions(const unsigned char **tzf, timelib_tzinfo *tz)
     235              : {
     236            0 :         if (tz->_bit32.timecnt) {
     237            0 :                 *tzf += (sizeof(int32_t) * tz->_bit32.timecnt);
     238            0 :                 *tzf += sizeof(unsigned char) * tz->_bit32.timecnt;
     239              :         }
     240            0 : }
     241              : 
     242            0 : static int read_64bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
     243              : {
     244              :         unsigned char *buffer;
     245              :         int32_t *leap_buffer;
     246              :         unsigned int i, j;
     247              : 
     248              :         /* Offset Types */
     249            0 :         buffer = (unsigned char*) timelib_malloc(tz->bit64.typecnt * sizeof(unsigned char) * 6);
     250            0 :         if (!buffer) {
     251            0 :                 return TIMELIB_ERROR_CANNOT_ALLOCATE;
     252              :         }
     253            0 :         memcpy(buffer, *tzf, sizeof(unsigned char) * 6 * tz->bit64.typecnt);
     254            0 :         *tzf += sizeof(unsigned char) * 6 * tz->bit64.typecnt;
     255              : 
     256              :         // We add two extra to have space for potential new ttinfo entries due to new types defined in the
     257              :         // POSIX string
     258            0 :         tz->type = (ttinfo*) timelib_calloc(1, (tz->bit64.typecnt + 2) * sizeof(ttinfo));
     259            0 :         if (!tz->type) {
     260            0 :                 timelib_free(buffer);
     261            0 :                 return TIMELIB_ERROR_CANNOT_ALLOCATE;
     262              :         }
     263              : 
     264            0 :         for (i = 0; i < tz->bit64.typecnt; i++) {
     265            0 :                 j = i * 6;
     266            0 :                 tz->type[i].offset = 0;
     267            0 :                 tz->type[i].offset += (int32_t) (((uint32_t) buffer[j]) << 24) + (buffer[j + 1] << 16) + (buffer[j + 2] << 8) + tz->type[i].offset + buffer[j + 3];
     268            0 :                 tz->type[i].isdst = buffer[j + 4];
     269            0 :                 tz->type[i].abbr_idx = buffer[j + 5];
     270              :         }
     271            0 :         timelib_free(buffer);
     272              : 
     273              :         /* Abbreviations */
     274            0 :         tz->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
     275            0 :         if (!tz->timezone_abbr) {
     276            0 :                 return TIMELIB_ERROR_CORRUPT_NO_ABBREVIATION;
     277              :         }
     278            0 :         memcpy(tz->timezone_abbr, *tzf, sizeof(char) * tz->bit64.charcnt);
     279            0 :         *tzf += sizeof(char) * tz->bit64.charcnt;
     280              : 
     281              :         /* Leap seconds (only use in 'right/') format */
     282            0 :         if (tz->bit64.leapcnt) {
     283            0 :                 leap_buffer = (int32_t *) timelib_malloc(tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
     284            0 :                 if (!leap_buffer) {
     285            0 :                         return TIMELIB_ERROR_CANNOT_ALLOCATE;
     286              :                 }
     287            0 :                 memcpy(leap_buffer, *tzf, tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t)));
     288            0 :                 *tzf += tz->bit64.leapcnt * (sizeof(int64_t) + sizeof(int32_t));
     289              : 
     290            0 :                 tz->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
     291            0 :                 if (!tz->leap_times) {
     292            0 :                         timelib_free(leap_buffer);
     293            0 :                         return TIMELIB_ERROR_CANNOT_ALLOCATE;
     294              :                 }
     295            0 :                 for (i = 0; i < tz->bit64.leapcnt; i++) {
     296            0 :                         tz->leap_times[i].trans = timelib_conv_int64_signed(leap_buffer[i * 3 + 1] * 4294967296 + leap_buffer[i * 3]);
     297            0 :                         tz->leap_times[i].offset = timelib_conv_int_signed(leap_buffer[i * 3 + 2]);
     298              :                 }
     299            0 :                 timelib_free(leap_buffer);
     300              :         }
     301              : 
     302              :         /* Standard/Wall Indicators (unused) */
     303            0 :         if (tz->bit64.ttisstdcnt) {
     304            0 :                 buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisstdcnt * sizeof(unsigned char));
     305            0 :                 if (!buffer) {
     306            0 :                         return TIMELIB_ERROR_CANNOT_ALLOCATE;
     307              :                 }
     308            0 :                 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisstdcnt);
     309            0 :                 *tzf += sizeof(unsigned char) * tz->bit64.ttisstdcnt;
     310              : 
     311            0 :                 for (i = 0; i < tz->bit64.ttisstdcnt; i++) {
     312            0 :                         tz->type[i].isstdcnt = buffer[i];
     313              :                 }
     314            0 :                 timelib_free(buffer);
     315              :         }
     316              : 
     317              :         /* UT/Local Time Indicators (unused) */
     318            0 :         if (tz->bit64.ttisgmtcnt) {
     319            0 :                 buffer = (unsigned char*) timelib_malloc(tz->bit64.ttisgmtcnt * sizeof(unsigned char));
     320            0 :                 if (!buffer) {
     321            0 :                         return TIMELIB_ERROR_CANNOT_ALLOCATE;
     322              :                 }
     323            0 :                 memcpy(buffer, *tzf, sizeof(unsigned char) * tz->bit64.ttisgmtcnt);
     324            0 :                 *tzf += sizeof(unsigned char) * tz->bit64.ttisgmtcnt;
     325              : 
     326            0 :                 for (i = 0; i < tz->bit64.ttisgmtcnt; i++) {
     327            0 :                         tz->type[i].isgmtcnt = buffer[i];
     328              :                 }
     329            0 :                 timelib_free(buffer);
     330              :         }
     331              : 
     332            0 :         return 0;
     333              : }
     334              : 
     335            0 : static void skip_32bit_types(const unsigned char **tzf, timelib_tzinfo *tz)
     336              : {
     337              :         /* Offset Types */
     338            0 :         *tzf += sizeof(unsigned char) * 6 * tz->_bit32.typecnt;
     339              : 
     340              :         /* Abbreviations */
     341            0 :         *tzf += sizeof(char) * tz->_bit32.charcnt;
     342              : 
     343              :         /* Leap seconds (only use in 'right/') format */
     344            0 :         if (tz->_bit32.leapcnt) {
     345            0 :                 *tzf += sizeof(int32_t) * tz->_bit32.leapcnt * 2;
     346              :         }
     347              : 
     348              :         /* Standard/Wall Indicators (unused) */
     349            0 :         if (tz->_bit32.ttisstdcnt) {
     350            0 :                 *tzf += sizeof(unsigned char) * tz->_bit32.ttisstdcnt;
     351              :         }
     352              : 
     353              :         /* UT/Local Time Indicators (unused) */
     354            0 :         if (tz->_bit32.ttisgmtcnt) {
     355            0 :                 *tzf += sizeof(unsigned char) * tz->_bit32.ttisgmtcnt;
     356              :         }
     357            0 : }
     358              : 
     359            0 : static void read_posix_string(const unsigned char **tzf, timelib_tzinfo *tz)
     360              : {
     361              :         const unsigned char *begin;
     362              : 
     363              :         // POSIX string is delimited by \n
     364            0 :         (*tzf)++;
     365            0 :         begin = *tzf;
     366              : 
     367            0 :         while (*tzf[0] != '\n') {
     368            0 :                 (*tzf)++;
     369              :         }
     370              : 
     371            0 :         tz->posix_string = timelib_calloc(1, *tzf - begin + 1);
     372            0 :         memcpy(tz->posix_string, begin, *tzf - begin);
     373              : 
     374              :         // skip over closing \n
     375            0 :         (*tzf)++;
     376            0 : }
     377              : 
     378            0 : static signed int find_ttinfo_index(timelib_tzinfo *tz, int32_t offset, int isdst, char *abbr)
     379              : {
     380              :         uint64_t i;
     381              : 
     382            0 :         for (i = 0; i < tz->bit64.typecnt; i++) {
     383            0 :                 if (
     384            0 :                         (offset == tz->type[i].offset) &&
     385            0 :                         (isdst == tz->type[i].isdst) &&
     386            0 :                         (strcmp(abbr, &tz->timezone_abbr[tz->type[i].abbr_idx]) == 0)
     387              :                 ) {
     388            0 :                         return i;
     389              :                 }
     390              :         }
     391              : 
     392            0 :         return TIMELIB_UNSET;
     393              : }
     394              : 
     395            0 : static unsigned int add_abbr(timelib_tzinfo *tz, char *abbr)
     396              : {
     397            0 :         size_t old_length = tz->bit64.charcnt;
     398            0 :         size_t new_length = old_length + strlen(abbr) + 1;
     399            0 :         tz->timezone_abbr = (char*) timelib_realloc(tz->timezone_abbr, new_length);
     400            0 :         memcpy(tz->timezone_abbr + old_length, abbr, strlen(abbr));
     401            0 :         tz->bit64.charcnt = new_length;
     402            0 :         tz->timezone_abbr[new_length - 1] = '\0';
     403              : 
     404            0 :         return old_length;
     405              : }
     406              : 
     407            0 : static signed int add_new_ttinfo_index(timelib_tzinfo *tz, int32_t offset, int isdst, char *abbr)
     408              : {
     409            0 :         tz->type[tz->bit64.typecnt].offset = offset;
     410            0 :         tz->type[tz->bit64.typecnt].isdst = isdst;
     411            0 :         tz->type[tz->bit64.typecnt].abbr_idx = add_abbr(tz, abbr);
     412            0 :         tz->type[tz->bit64.typecnt].isstdcnt = 0;
     413            0 :         tz->type[tz->bit64.typecnt].isgmtcnt = 0;
     414              : 
     415            0 :         ++tz->bit64.typecnt;
     416              : 
     417            0 :         return tz->bit64.typecnt - 1;
     418              : }
     419              : 
     420            0 : static int integrate_posix_string(timelib_tzinfo *tz)
     421              : {
     422            0 :         tz->posix_info = timelib_parse_posix_str(tz->posix_string);
     423            0 :         if (!tz->posix_info) {
     424            0 :                 return 0;
     425              :         }
     426              : 
     427            0 :         tz->posix_info->type_index_std_type = find_ttinfo_index(tz, tz->posix_info->std_offset, 0, tz->posix_info->std);
     428            0 :         if (tz->posix_info->type_index_std_type == TIMELIB_UNSET) {
     429            0 :                 tz->posix_info->type_index_std_type = add_new_ttinfo_index(tz, tz->posix_info->std_offset, 0, tz->posix_info->std);
     430            0 :                 return 1;
     431              :         }
     432              : 
     433              :         /* If there is no DST set for this zone, return */
     434            0 :         if (!tz->posix_info->dst) {
     435            0 :                 return 1;
     436              :         }
     437              : 
     438            0 :         tz->posix_info->type_index_dst_type = find_ttinfo_index(tz, tz->posix_info->dst_offset, 1, tz->posix_info->dst);
     439            0 :         if (tz->posix_info->type_index_dst_type == TIMELIB_UNSET) {
     440            0 :                 tz->posix_info->type_index_dst_type = add_new_ttinfo_index(tz, tz->posix_info->dst_offset, 1, tz->posix_info->dst);
     441            0 :                 return 1;
     442              :         }
     443              : 
     444            0 :         return 1;
     445              : }
     446              : 
     447            0 : static void read_location(const unsigned char **tzf, timelib_tzinfo *tz)
     448              : {
     449              :         uint32_t buffer[3];
     450              :         uint32_t comments_len;
     451              : 
     452            0 :         memcpy(&buffer, *tzf, sizeof(buffer));
     453            0 :         tz->location.latitude = timelib_conv_int_unsigned(buffer[0]);
     454            0 :         tz->location.latitude = (tz->location.latitude / 100000) - 90;
     455            0 :         tz->location.longitude = timelib_conv_int_unsigned(buffer[1]);
     456            0 :         tz->location.longitude = (tz->location.longitude / 100000) - 180;
     457            0 :         comments_len = timelib_conv_int_unsigned(buffer[2]);
     458            0 :         *tzf += sizeof(buffer);
     459              : 
     460            0 :         tz->location.comments = timelib_malloc(comments_len + 1);
     461            0 :         memcpy(tz->location.comments, *tzf, comments_len);
     462            0 :         tz->location.comments[comments_len] = '\0';
     463            0 :         *tzf += comments_len;
     464            0 : }
     465              : 
     466            0 : static void set_default_location_and_comments(const unsigned char **tzf, timelib_tzinfo *tz)
     467              : {
     468            0 :         tz->location.latitude = 0;
     469            0 :         tz->location.longitude = 0;
     470            0 :         tz->location.comments = timelib_malloc(2);
     471            0 :         tz->location.comments[0] = '?';
     472            0 :         tz->location.comments[1] = '\0';
     473            0 : }
     474              : 
     475            0 : static char *format_ut_time(timelib_sll ts, timelib_tzinfo *tz)
     476              : {
     477            0 :         char *tmp = timelib_calloc(1, 64);
     478            0 :         timelib_time *t = timelib_time_ctor();
     479              : 
     480            0 :         timelib_unixtime2gmt(t, ts);
     481            0 :         snprintf(
     482              :                 tmp, 64,
     483              :                 "%04lld-%02lld-%02lld %02lld:%02lld:%02lld UT",
     484              :                 t->y, t->m, t->d,
     485              :                 t->h, t->i, t->s
     486              :         );
     487              : 
     488            0 :         timelib_time_dtor(t);
     489            0 :         return tmp;
     490              : }
     491              : 
     492            0 : static char *format_offset_type(timelib_tzinfo *tz, int i)
     493              : {
     494            0 :         char *tmp = timelib_calloc(1, 64);
     495              : 
     496            0 :         snprintf(
     497              :                 tmp, 64,
     498              :                 "%3d [%6ld %1d %3d '%s' (%d,%d)]",
     499              :                 i,
     500            0 :                 (long int) tz->type[i].offset,
     501            0 :                 tz->type[i].isdst,
     502            0 :                 tz->type[i].abbr_idx,
     503            0 :                 &tz->timezone_abbr[tz->type[i].abbr_idx],
     504            0 :                 tz->type[i].isstdcnt,
     505            0 :                 tz->type[i].isgmtcnt
     506              :         );
     507              : 
     508            0 :         return tmp;
     509              : }
     510              : 
     511            0 : void timelib_dump_tzinfo(timelib_tzinfo *tz)
     512              : {
     513              :         uint32_t  i;
     514              :         char     *date_str, *trans_str;
     515              : 
     516            0 :         printf("Country Code:      %s\n", tz->location.country_code);
     517            0 :         printf("Geo Location:      %f,%f\n", tz->location.latitude, tz->location.longitude);
     518            0 :         printf("Comments:\n%s\n",          tz->location.comments);
     519            0 :         printf("BC:                %s\n",  tz->bc ? "no" : "yes");
     520            0 :         printf("Slim File:         %s\n",  detect_slim_file(tz) ? "yes" : "no");
     521              : 
     522            0 :         printf("\n64-bit:\n");
     523            0 :         printf("UTC/Local count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisgmtcnt);
     524            0 :         printf("Std/Wall count:    " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.ttisstdcnt);
     525            0 :         printf("Leap.sec. count:   " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.leapcnt);
     526            0 :         printf("Trans. count:      " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.timecnt);
     527            0 :         printf("Local types count: " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.typecnt);
     528            0 :         printf("Zone Abbr. count:  " TIMELIB_ULONG_FMT "\n", (timelib_ulong) tz->bit64.charcnt);
     529              : 
     530            0 :         trans_str = format_offset_type(tz, 0);
     531            0 :         printf("%22s (%20s) = %s\n", "", "", trans_str);
     532            0 :         timelib_free(trans_str);
     533              : 
     534            0 :         for (i = 0; i < tz->bit64.timecnt; i++) {
     535            0 :                 date_str = format_ut_time(tz->trans[i], tz);
     536            0 :                 trans_str = format_offset_type(tz, tz->trans_idx[i]);
     537            0 :                 printf(
     538              :                         "%s (%20" PRId64 ") = %s\n",
     539              :                         date_str,
     540            0 :                         tz->trans[i],
     541              :                         trans_str
     542              :                 );
     543            0 :                 timelib_free(date_str);
     544            0 :                 timelib_free(trans_str);
     545              :         }
     546            0 :         for (i = 0; i < tz->bit64.leapcnt; i++) {
     547            0 :                 date_str = format_ut_time(tz->leap_times[i].trans, tz);
     548            0 :                 printf (
     549              :                         "%s (%20ld) = %d\n",
     550              :                         date_str,
     551            0 :                         (long) tz->leap_times[i].trans,
     552            0 :                         tz->leap_times[i].offset
     553              :                 );
     554            0 :                 timelib_free(date_str);
     555              :         }
     556              : 
     557            0 :         if (!tz->posix_string) {
     558            0 :                 printf("\n%43sNo POSIX string\n", "");
     559            0 :                 return;
     560              :         }
     561              : 
     562            0 :         if (strcmp("", tz->posix_string) == 0) {
     563            0 :                 printf("\n%43sEmpty POSIX string\n", "");
     564            0 :                 return;
     565              :         }
     566              : 
     567            0 :         printf("\n%43sPOSIX string: %s\n", "", tz->posix_string);
     568            0 :         if (tz->posix_info && tz->posix_info->std) {
     569            0 :                 trans_str = format_offset_type(tz, tz->posix_info->type_index_std_type);
     570            0 :                 printf("%43sstd: %s\n", "", trans_str);
     571            0 :                 timelib_free(trans_str);
     572              : 
     573            0 :                 if (tz->posix_info->dst) {
     574            0 :                         trans_str = format_offset_type(tz, tz->posix_info->type_index_dst_type);
     575            0 :                         printf("%43sdst: %s\n", "", trans_str);
     576            0 :                         timelib_free(trans_str);
     577              :                 }
     578              :         }
     579              : }
     580              : 
     581            0 : static int seek_to_tz_position(const unsigned char **tzf, const char *timezone, const timelib_tzdb *tzdb)
     582              : {
     583            0 :         int left = 0, right = tzdb->index_size - 1;
     584              : 
     585            0 :         if (tzdb->index_size == 0) {
     586            0 :                 return 0;
     587              :         }
     588              : 
     589              :         do {
     590            0 :                 int mid = ((unsigned)left + right) >> 1;
     591            0 :                 int cmp = timelib_strcasecmp(timezone, tzdb->index[mid].id);
     592              : 
     593            0 :                 if (cmp < 0) {
     594            0 :                         right = mid - 1;
     595            0 :                 } else if (cmp > 0) {
     596            0 :                         left = mid + 1;
     597              :                 } else { /* (cmp == 0) */
     598            0 :                         (*tzf) = &(tzdb->data[tzdb->index[mid].pos]);
     599            0 :                         return 1;
     600              :                 }
     601              : 
     602            0 :         } while (left <= right);
     603              : 
     604            0 :         return 0;
     605              : }
     606              : 
     607            0 : const timelib_tzdb *timelib_builtin_db(void)
     608              : {
     609            0 :         return &timezonedb_builtin;
     610              : }
     611              : 
     612            0 : const timelib_tzdb_index_entry *timelib_timezone_identifiers_list(const timelib_tzdb *tzdb, int *count)
     613              : {
     614            0 :         *count = tzdb->index_size;
     615            0 :         return tzdb->index;
     616              : }
     617              : 
     618            0 : int timelib_timezone_id_is_valid(const char *timezone, const timelib_tzdb *tzdb)
     619              : {
     620              :         const unsigned char *tzf;
     621            0 :         return (seek_to_tz_position(&tzf, timezone, tzdb));
     622              : }
     623              : 
     624            0 : static int skip_64bit_preamble(const unsigned char **tzf, timelib_tzinfo *tz)
     625              : {
     626            0 :         if (memcmp(*tzf, "TZif2", 5) == 0) {
     627            0 :                 *tzf += 20;
     628            0 :                 return 1;
     629            0 :         } else if (memcmp(*tzf, "TZif3", 5) == 0) {
     630            0 :                 *tzf += 20;
     631            0 :                 return 1;
     632            0 :         } else if (memcmp(*tzf, "TZif4", 5) == 0) {
     633            0 :                 *tzf += 20;
     634            0 :                 return 1;
     635              :         } else {
     636            0 :                 return 0;
     637              :         }
     638              : }
     639              : 
     640            0 : static void read_64bit_header(const unsigned char **tzf, timelib_tzinfo *tz)
     641              : {
     642              :         uint32_t buffer[6];
     643              : 
     644            0 :         memcpy(&buffer, *tzf, sizeof(buffer));
     645            0 :         tz->bit64.ttisgmtcnt = timelib_conv_int_unsigned(buffer[0]);
     646            0 :         tz->bit64.ttisstdcnt = timelib_conv_int_unsigned(buffer[1]);
     647            0 :         tz->bit64.leapcnt    = timelib_conv_int_unsigned(buffer[2]);
     648            0 :         tz->bit64.timecnt    = timelib_conv_int_unsigned(buffer[3]);
     649            0 :         tz->bit64.typecnt    = timelib_conv_int_unsigned(buffer[4]);
     650            0 :         tz->bit64.charcnt    = timelib_conv_int_unsigned(buffer[5]);
     651            0 :         *tzf += sizeof(buffer);
     652            0 : }
     653              : 
     654            0 : static timelib_tzinfo* timelib_tzinfo_ctor(const char *name)
     655              : {
     656              :         timelib_tzinfo *t;
     657            0 :         t = timelib_calloc(1, sizeof(timelib_tzinfo));
     658            0 :         t->name = timelib_strdup(name);
     659              : 
     660            0 :         return t;
     661              : }
     662              : 
     663            0 : timelib_tzinfo *timelib_parse_tzfile(const char *timezone, const timelib_tzdb *tzdb, int *error_code)
     664              : {
     665              :         const unsigned char *tzf;
     666              :         timelib_tzinfo *tmp;
     667              :         int version;
     668              :         int transitions_result, types_result;
     669            0 :         unsigned int type = TIMELIB_TZINFO_ZONEINFO; /* TIMELIB_TZINFO_PHP or TIMELIB_TZINFO_ZONEINFO */
     670              : 
     671            0 :         *error_code = TIMELIB_ERROR_NO_ERROR;
     672              : 
     673            0 :         if (seek_to_tz_position(&tzf, timezone, tzdb)) {
     674            0 :                 tmp = timelib_tzinfo_ctor(timezone);
     675              : 
     676            0 :                 version = read_preamble(&tzf, tmp, &type);
     677            0 :                 if (version < 2 || version > 4) {
     678            0 :                         *error_code = TIMELIB_ERROR_UNSUPPORTED_VERSION;
     679            0 :                         timelib_tzinfo_dtor(tmp);
     680            0 :                         return NULL;
     681              :                 }
     682              : //printf("- timezone: %s, version: %0d\n", timezone, version);
     683              : 
     684            0 :                 read_32bit_header(&tzf, tmp);
     685            0 :                 skip_32bit_transitions(&tzf, tmp);
     686            0 :                 skip_32bit_types(&tzf, tmp);
     687              : 
     688            0 :                 if (!skip_64bit_preamble(&tzf, tmp)) {
     689              :                         /* 64 bit preamble is not in place */
     690            0 :                         *error_code = TIMELIB_ERROR_CORRUPT_NO_64BIT_PREAMBLE;
     691            0 :                         timelib_tzinfo_dtor(tmp);
     692            0 :                         return NULL;
     693              :                 }
     694            0 :                 read_64bit_header(&tzf, tmp);
     695            0 :                 if ((transitions_result = read_64bit_transitions(&tzf, tmp)) != 0) {
     696              :                         /* Corrupt file as transitions do not increase */
     697            0 :                         *error_code = transitions_result;
     698            0 :                         timelib_tzinfo_dtor(tmp);
     699            0 :                         return NULL;
     700              :                 }
     701            0 :                 if ((types_result = read_64bit_types(&tzf, tmp)) != 0) {
     702            0 :                         *error_code = types_result;
     703            0 :                         timelib_tzinfo_dtor(tmp);
     704            0 :                         return NULL;
     705              :                 }
     706              : 
     707            0 :                 read_posix_string(&tzf, tmp);
     708            0 :                 if (strcmp("", tmp->posix_string) == 0) {
     709            0 :                         *error_code = TIMELIB_ERROR_EMPTY_POSIX_STRING;
     710            0 :                 } else if (!integrate_posix_string(tmp)) {
     711            0 :                         *error_code = TIMELIB_ERROR_CORRUPT_POSIX_STRING;
     712            0 :                         timelib_tzinfo_dtor(tmp);
     713            0 :                         return NULL;
     714              :                 }
     715              : 
     716            0 :                 if (type == TIMELIB_TZINFO_PHP) {
     717            0 :                         read_location(&tzf, tmp);
     718              :                 } else {
     719            0 :                         set_default_location_and_comments(&tzf, tmp);
     720              :                 }
     721              :         } else {
     722            0 :                 *error_code = TIMELIB_ERROR_NO_SUCH_TIMEZONE;
     723            0 :                 tmp = NULL;
     724              :         }
     725              : 
     726            0 :         return tmp;
     727              : }
     728              : 
     729            0 : void timelib_tzinfo_dtor(timelib_tzinfo *tz)
     730              : {
     731            0 :         TIMELIB_TIME_FREE(tz->name);
     732            0 :         TIMELIB_TIME_FREE(tz->trans);
     733            0 :         TIMELIB_TIME_FREE(tz->trans_idx);
     734            0 :         TIMELIB_TIME_FREE(tz->type);
     735            0 :         TIMELIB_TIME_FREE(tz->timezone_abbr);
     736            0 :         TIMELIB_TIME_FREE(tz->leap_times);
     737            0 :         TIMELIB_TIME_FREE(tz->location.comments);
     738            0 :         TIMELIB_TIME_FREE(tz->posix_string);
     739            0 :         if (tz->posix_info) {
     740            0 :                 timelib_posix_str_dtor(tz->posix_info);
     741              :         }
     742            0 :         TIMELIB_TIME_FREE(tz);
     743            0 :         tz = NULL;
     744            0 : }
     745              : 
     746            0 : timelib_tzinfo *timelib_tzinfo_clone(timelib_tzinfo *tz)
     747              : {
     748            0 :         timelib_tzinfo *tmp = timelib_tzinfo_ctor(tz->name);
     749            0 :         tmp->_bit32.ttisgmtcnt = tz->_bit32.ttisgmtcnt;
     750            0 :         tmp->_bit32.ttisstdcnt = tz->_bit32.ttisstdcnt;
     751            0 :         tmp->_bit32.leapcnt = tz->_bit32.leapcnt;
     752            0 :         tmp->_bit32.timecnt = tz->_bit32.timecnt;
     753            0 :         tmp->_bit32.typecnt = tz->_bit32.typecnt;
     754            0 :         tmp->_bit32.charcnt = tz->_bit32.charcnt;
     755            0 :         tmp->bit64.ttisgmtcnt = tz->bit64.ttisgmtcnt;
     756            0 :         tmp->bit64.ttisstdcnt = tz->bit64.ttisstdcnt;
     757            0 :         tmp->bit64.leapcnt = tz->bit64.leapcnt;
     758            0 :         tmp->bit64.timecnt = tz->bit64.timecnt;
     759            0 :         tmp->bit64.typecnt = tz->bit64.typecnt;
     760            0 :         tmp->bit64.charcnt = tz->bit64.charcnt;
     761              : 
     762            0 :         if (tz->bit64.timecnt) {
     763            0 :                 tmp->trans = (int64_t *) timelib_malloc(tz->bit64.timecnt * sizeof(int64_t));
     764            0 :                 tmp->trans_idx = (unsigned char*) timelib_malloc(tz->bit64.timecnt * sizeof(unsigned char));
     765            0 :                 memcpy(tmp->trans, tz->trans, tz->bit64.timecnt * sizeof(int64_t));
     766            0 :                 memcpy(tmp->trans_idx, tz->trans_idx, tz->bit64.timecnt * sizeof(unsigned char));
     767              :         }
     768              : 
     769            0 :         tmp->type = (ttinfo*) timelib_malloc(tz->bit64.typecnt * sizeof(ttinfo));
     770            0 :         memcpy(tmp->type, tz->type, tz->bit64.typecnt * sizeof(ttinfo));
     771              : 
     772            0 :         tmp->timezone_abbr = (char*) timelib_malloc(tz->bit64.charcnt);
     773            0 :         memcpy(tmp->timezone_abbr, tz->timezone_abbr, tz->bit64.charcnt);
     774              : 
     775            0 :         if (tz->bit64.leapcnt) {
     776            0 :                 tmp->leap_times = (tlinfo*) timelib_malloc(tz->bit64.leapcnt * sizeof(tlinfo));
     777            0 :                 memcpy(tmp->leap_times, tz->leap_times, tz->bit64.leapcnt * sizeof(tlinfo));
     778              :         }
     779              : 
     780            0 :         if (tz->posix_string) {
     781            0 :                 tmp->posix_string = timelib_strdup(tz->posix_string);
     782              :         }
     783              : 
     784            0 :         return tmp;
     785              : }
     786              : 
     787              : /**
     788              :  * Algorithm From RFC 8536, Section 3.2
     789              :  * https://tools.ietf.org/html/rfc8536#section-3.2
     790              :  */
     791         1320 : ttinfo* timelib_fetch_timezone_offset(timelib_tzinfo *tz, timelib_sll ts, timelib_sll *transition_time)
     792              : {
     793              :         uint32_t left, right;
     794              : 
     795              :         /* RFC 8536: If there are no transitions, local time for all timestamps is specified
     796              :          * by the TZ string in the footer if present and nonempty; otherwise, it is specified
     797              :          * by time type 0.
     798              :          *
     799              :          * timelib: If there is also no time type 0, return NULL.
     800              :          */
     801         1320 :         if (!tz->bit64.timecnt || !tz->trans) {
     802         1176 :                 if (tz->posix_info) {
     803         1176 :                         *transition_time = INT64_MIN;
     804         1176 :                         return timelib_fetch_posix_timezone_offset(tz, ts, NULL);
     805              :                 }
     806              : 
     807            0 :                 if (tz->bit64.typecnt == 1) {
     808            0 :                         *transition_time = INT64_MIN;
     809            0 :                         return &(tz->type[0]);
     810              :                 }
     811            0 :                 return NULL;
     812              :         }
     813              : 
     814              :         /* RFC 8536: Local time for timestamps before the first transition is specified by
     815              :          * the first time type (time type 0). */
     816          144 :         if (ts < tz->trans[0]) {
     817            0 :                 *transition_time = INT64_MIN;
     818            0 :                 return &(tz->type[0]);
     819              :         }
     820              : 
     821              :         /* RFC 8536: Local time for timestamps on or after the last transition is specified
     822              :          * by the TZ string in the footer (Section 3.3) if present and nonempty; otherwise,
     823              :          * it is unspecified.
     824              :          *
     825              :          * timelib: For 'unspecified', timelib assumes the last transition
     826              :          */
     827          144 :         if (ts >= tz->trans[tz->bit64.timecnt - 1]) {
     828          144 :                 if (tz->posix_info) {
     829          144 :                         return timelib_fetch_posix_timezone_offset(tz, ts, transition_time);
     830              :                 }
     831              : 
     832            0 :                 *transition_time = tz->trans[tz->bit64.timecnt - 1];
     833            0 :                 return &(tz->type[tz->trans_idx[tz->bit64.timecnt - 1]]);
     834              :         }
     835              : 
     836              :         /* RFC 8536: The type corresponding to a transition time specifies local time for
     837              :          * timestamps starting at the given transition time and continuing up to, but not
     838              :          * including, the next transition time. */
     839            0 :         left = 0;
     840            0 :         right = tz->bit64.timecnt - 1;
     841              : 
     842            0 :         while (right - left > 1) {
     843            0 :                 uint32_t mid = (left + right) >> 1;
     844              : 
     845            0 :                 if (ts < tz->trans[mid]) {
     846            0 :                         right = mid;
     847              :                 } else {
     848            0 :                         left = mid;
     849              :                 }
     850              :         }
     851            0 :         *transition_time = tz->trans[left];
     852            0 :         return &(tz->type[tz->trans_idx[left]]);
     853              : }
     854              : 
     855          512 : static tlinfo* fetch_leaptime_offset(timelib_tzinfo *tz, timelib_sll ts)
     856              : {
     857              :         int i;
     858              : 
     859          512 :         if (!tz->bit64.leapcnt || !tz->leap_times) {
     860          512 :                 return NULL;
     861              :         }
     862              : 
     863            0 :         for (i = tz->bit64.leapcnt - 1; i > 0; i--) {
     864            0 :                 if (ts > tz->leap_times[i].trans) {
     865            0 :                         return &(tz->leap_times[i]);
     866              :                 }
     867              :         }
     868            0 :         return NULL;
     869              : }
     870              : 
     871            0 : int timelib_timestamp_is_in_dst(timelib_sll ts, timelib_tzinfo *tz)
     872              : {
     873              :         ttinfo *to;
     874              :         timelib_sll dummy;
     875              : 
     876            0 :         if ((to = timelib_fetch_timezone_offset(tz, ts, &dummy))) {
     877            0 :                 return to->isdst;
     878              :         }
     879            0 :         return -1;
     880              : }
     881              : 
     882          512 : timelib_time_offset *timelib_get_time_zone_info(timelib_sll ts, timelib_tzinfo *tz)
     883              : {
     884              :         ttinfo *to;
     885              :         tlinfo *tl;
     886          512 :         int32_t offset = 0, leap_secs = 0;
     887              :         char *abbr;
     888          512 :         timelib_time_offset *tmp = timelib_time_offset_ctor();
     889              :         timelib_sll                transition_time;
     890              : 
     891          512 :         if ((to = timelib_fetch_timezone_offset(tz, ts, &transition_time))) {
     892          512 :                 offset = to->offset;
     893          512 :                 abbr = &(tz->timezone_abbr[to->abbr_idx]);
     894          512 :                 tmp->is_dst = to->isdst;
     895          512 :                 tmp->transition_time = transition_time;
     896              :         } else {
     897            0 :                 offset = 0;
     898            0 :                 abbr = tz->timezone_abbr;
     899            0 :                 tmp->is_dst = 0;
     900            0 :                 tmp->transition_time = 0;
     901              :         }
     902              : 
     903          512 :         if ((tl = fetch_leaptime_offset(tz, ts))) {
     904            0 :                 leap_secs = -tl->offset;
     905              :         }
     906              : 
     907          512 :         tmp->offset = offset;
     908          512 :         tmp->leap_secs = leap_secs;
     909          512 :         tmp->abbr = abbr ? timelib_strdup(abbr) : timelib_strdup("GMT");
     910              : 
     911          512 :         return tmp;
     912              : }
     913              : 
     914          808 : int timelib_get_time_zone_offset_info(timelib_sll ts, timelib_tzinfo *tz, int32_t* offset, timelib_sll* transition_time, unsigned int* is_dst)
     915              : {
     916              :         ttinfo *to;
     917              :         timelib_sll tmp_transition_time;
     918              : 
     919          808 :         if (tz == NULL) {
     920            0 :                 return 0;
     921              :         }
     922              : 
     923          808 :         if ((to = timelib_fetch_timezone_offset(tz, ts, &tmp_transition_time))) {
     924          808 :                 if (offset) {
     925          808 :                         *offset = to->offset;
     926              :                 }
     927          808 :                 if (is_dst) {
     928          340 :                         *is_dst = to->isdst;
     929              :                 }
     930          808 :                 if (transition_time) {
     931          680 :                         *transition_time = tmp_transition_time;
     932              :                 }
     933          808 :                 return 1;
     934              :         }
     935            0 :         return 0;
     936              : }
     937              : 
     938            0 : timelib_sll timelib_get_current_offset(timelib_time *t)
     939              : {
     940            0 :         switch (t->zone_type) {
     941            0 :                 case TIMELIB_ZONETYPE_ABBR:
     942              :                 case TIMELIB_ZONETYPE_OFFSET:
     943            0 :                         return t->z + (t->dst * 3600);
     944              : 
     945            0 :                 case TIMELIB_ZONETYPE_ID: {
     946            0 :                         int32_t      offset = 0;
     947            0 :                         timelib_get_time_zone_offset_info(t->sse, t->tz_info, &offset, NULL, NULL);
     948            0 :                         return offset;
     949              :                 }
     950              : 
     951            0 :                 default:
     952            0 :                         return 0;
     953              :         }
     954              : }
     955              : 
     956            0 : int timelib_same_timezone(timelib_time *one, timelib_time *two)
     957              : {
     958            0 :     if (one->zone_type != two->zone_type) {
     959            0 :         return 0;
     960              :     }
     961              : 
     962            0 :     if (one->zone_type == TIMELIB_ZONETYPE_ABBR || one->zone_type == TIMELIB_ZONETYPE_OFFSET) {
     963            0 :         if ((one->z + (one->dst * 3600)) == (two->z + (two->dst * 3600))) {
     964            0 :             return 1;
     965              :         }
     966            0 :         return 0;
     967              :     }
     968              : 
     969            0 :     if (one->zone_type == TIMELIB_ZONETYPE_ID && strcmp(one->tz_info->name, two->tz_info->name) == 0) {
     970            0 :         return 1;
     971              :     }
     972              : 
     973            0 :     return 0;
     974              : }
        

Generated by: LCOV version 2.0-1