LCOV - code coverage report
Current view: top level - src/timezone - localtime.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 662 812 81.5 %
Date: 2017-09-29 13:40:31 Functions: 29 29 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * This file is in the public domain, so clarified as of
       3             :  * 1996-06-05 by Arthur David Olson.
       4             :  *
       5             :  * IDENTIFICATION
       6             :  *    src/timezone/localtime.c
       7             :  */
       8             : 
       9             : /*
      10             :  * Leap second handling from Bradley White.
      11             :  * POSIX-style TZ environment variable handling from Guy Harris.
      12             :  */
      13             : 
      14             : /* this file needs to build in both frontend and backend contexts */
      15             : #include "c.h"
      16             : 
      17             : #include <fcntl.h>
      18             : 
      19             : #include "datatype/timestamp.h"
      20             : #include "pgtz.h"
      21             : 
      22             : #include "private.h"
      23             : #include "tzfile.h"
      24             : 
      25             : 
      26             : #ifndef WILDABBR
      27             : /*
      28             :  * Someone might make incorrect use of a time zone abbreviation:
      29             :  *  1.  They might reference tzname[0] before calling tzset (explicitly
      30             :  *      or implicitly).
      31             :  *  2.  They might reference tzname[1] before calling tzset (explicitly
      32             :  *      or implicitly).
      33             :  *  3.  They might reference tzname[1] after setting to a time zone
      34             :  *      in which Daylight Saving Time is never observed.
      35             :  *  4.  They might reference tzname[0] after setting to a time zone
      36             :  *      in which Standard Time is never observed.
      37             :  *  5.  They might reference tm.TM_ZONE after calling offtime.
      38             :  * What's best to do in the above cases is open to debate;
      39             :  * for now, we just set things up so that in any of the five cases
      40             :  * WILDABBR is used. Another possibility: initialize tzname[0] to the
      41             :  * string "tzname[0] used before set", and similarly for the other cases.
      42             :  * And another: initialize tzname[0] to "ERA", with an explanation in the
      43             :  * manual page of what this "time zone abbreviation" means (doing this so
      44             :  * that tzname[0] has the "normal" length of three characters).
      45             :  */
      46             : #define WILDABBR    "   "
      47             : #endif                          /* !defined WILDABBR */
      48             : 
      49             : static const char wildabbr[] = WILDABBR;
      50             : 
      51             : static const char gmt[] = "GMT";
      52             : 
      53             : /* The minimum and maximum finite time values.  This assumes no padding.  */
      54             : static const pg_time_t time_t_min = MINVAL(pg_time_t, TYPE_BIT(pg_time_t));
      55             : static const pg_time_t time_t_max = MAXVAL(pg_time_t, TYPE_BIT(pg_time_t));
      56             : 
      57             : /*
      58             :  * We cache the result of trying to load the TZDEFRULES zone here.
      59             :  * tzdefrules_loaded is 0 if not tried yet, +1 if good, -1 if failed.
      60             :  */
      61             : static struct state tzdefrules_s;
      62             : static int  tzdefrules_loaded = 0;
      63             : 
      64             : /*
      65             :  * The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
      66             :  * We default to US rules as of 1999-08-17.
      67             :  * POSIX 1003.1 section 8.1.1 says that the default DST rules are
      68             :  * implementation dependent; for historical reasons, US rules are a
      69             :  * common default.
      70             :  */
      71             : #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
      72             : 
      73             : /* structs ttinfo, lsinfo, state have been moved to pgtz.h */
      74             : 
      75             : enum r_type
      76             : {
      77             :     JULIAN_DAY,                 /* Jn = Julian day */
      78             :     DAY_OF_YEAR,                /* n = day of year */
      79             :     MONTH_NTH_DAY_OF_WEEK       /* Mm.n.d = month, week, day of week */
      80             : };
      81             : 
      82             : struct rule
      83             : {
      84             :     enum r_type r_type;         /* type of rule */
      85             :     int         r_day;          /* day number of rule */
      86             :     int         r_week;         /* week number of rule */
      87             :     int         r_mon;          /* month number of rule */
      88             :     int32       r_time;         /* transition time of rule */
      89             : };
      90             : 
      91             : /*
      92             :  * Prototypes for static functions.
      93             :  */
      94             : 
      95             : static struct pg_tm *gmtsub(pg_time_t const *, int32, struct pg_tm *);
      96             : static bool increment_overflow(int *, int);
      97             : static bool increment_overflow_time(pg_time_t *, int32);
      98             : static struct pg_tm *timesub(pg_time_t const *, int32, struct state const *,
      99             :         struct pg_tm *);
     100             : static bool typesequiv(struct state const *, int, int);
     101             : 
     102             : 
     103             : /*
     104             :  * Section 4.12.3 of X3.159-1989 requires that
     105             :  *  Except for the strftime function, these functions [asctime,
     106             :  *  ctime, gmtime, localtime] return values in one of two static
     107             :  *  objects: a broken-down time structure and an array of char.
     108             :  * Thanks to Paul Eggert for noting this.
     109             :  */
     110             : 
     111             : static struct pg_tm tm;
     112             : 
     113             : /* Initialize *S to a value based on GMTOFF, ISDST, and ABBRIND.  */
     114             : static void
     115        1576 : init_ttinfo(struct ttinfo *s, int32 gmtoff, bool isdst, int abbrind)
     116             : {
     117        1576 :     s->tt_gmtoff = gmtoff;
     118        1576 :     s->tt_isdst = isdst;
     119        1576 :     s->tt_abbrind = abbrind;
     120        1576 :     s->tt_ttisstd = false;
     121        1576 :     s->tt_ttisgmt = false;
     122        1576 : }
     123             : 
     124             : static int32
     125      115816 : detzcode(const char *codep)
     126             : {
     127             :     int32       result;
     128             :     int         i;
     129      115816 :     int32       one = 1;
     130      115816 :     int32       halfmaxval = one << (32 - 2);
     131      115816 :     int32       maxval = halfmaxval - 1 + halfmaxval;
     132      115816 :     int32       minval = -1 - maxval;
     133             : 
     134      115816 :     result = codep[0] & 0x7f;
     135      463264 :     for (i = 1; i < 4; ++i)
     136      347448 :         result = (result << 8) | (codep[i] & 0xff);
     137             : 
     138      115816 :     if (codep[0] & 0x80)
     139             :     {
     140             :         /*
     141             :          * Do two's-complement negation even on non-two's-complement machines.
     142             :          * If the result would be minval - 1, return minval.
     143             :          */
     144       20138 :         result -= !TWOS_COMPLEMENT(int32) &&result != 0;
     145       20138 :         result += minval;
     146             :     }
     147      115816 :     return result;
     148             : }
     149             : 
     150             : static int64
     151       94594 : detzcode64(const char *codep)
     152             : {
     153             :     uint64      result;
     154             :     int         i;
     155       94594 :     int64       one = 1;
     156       94594 :     int64       halfmaxval = one << (64 - 2);
     157       94594 :     int64       maxval = halfmaxval - 1 + halfmaxval;
     158       94594 :     int64       minval = -TWOS_COMPLEMENT(int64) -maxval;
     159             : 
     160       94594 :     result = codep[0] & 0x7f;
     161      756752 :     for (i = 1; i < 8; ++i)
     162      662158 :         result = (result << 8) | (codep[i] & 0xff);
     163             : 
     164       94594 :     if (codep[0] & 0x80)
     165             :     {
     166             :         /*
     167             :          * Do two's-complement negation even on non-two's-complement machines.
     168             :          * If the result would be minval - 1, return minval.
     169             :          */
     170       15211 :         result -= !TWOS_COMPLEMENT(int64) &&result != 0;
     171       15211 :         result += minval;
     172             :     }
     173       94594 :     return result;
     174             : }
     175             : 
     176             : static bool
     177      497130 : differ_by_repeat(const pg_time_t t1, const pg_time_t t0)
     178             : {
     179             :     if (TYPE_BIT(pg_time_t) -TYPE_SIGNED(pg_time_t) <SECSPERREPEAT_BITS)
     180             :         return 0;
     181      497130 :     return t1 - t0 == SECSPERREPEAT;
     182             : }
     183             : 
     184             : /* Input buffer for data read from a compiled tz file.  */
     185             : union input_buffer
     186             : {
     187             :     /* The first part of the buffer, interpreted as a header.  */
     188             :     struct tzhead tzhead;
     189             : 
     190             :     /* The entire buffer.  */
     191             :     char        buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
     192             :                     + 4 * TZ_MAX_TIMES];
     193             : };
     194             : 
     195             : /* Local storage needed for 'tzloadbody'.  */
     196             : union local_storage
     197             : {
     198             :     /* We don't need the "fullname" member */
     199             : 
     200             :     /* The results of analyzing the file's contents after it is opened.  */
     201             :     struct
     202             :     {
     203             :         /* The input buffer.  */
     204             :         union input_buffer u;
     205             : 
     206             :         /* A temporary state used for parsing a TZ string in the file.  */
     207             :         struct state st;
     208             :     }           u;
     209             : };
     210             : 
     211             : /* Load tz data from the file named NAME into *SP.  Read extended
     212             :  * format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
     213             :  * success, an errno value on failure.
     214             :  * PG: If "canonname" is not NULL, then on success the canonical spelling of
     215             :  * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
     216             :  */
     217             : static int
     218        1021 : tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
     219             :            union local_storage *lsp)
     220             : {
     221             :     int         i;
     222             :     int         fid;
     223             :     int         stored;
     224             :     ssize_t     nread;
     225        1021 :     union input_buffer *up = &lsp->u.u;
     226        1021 :     int         tzheadsize = sizeof(struct tzhead);
     227             : 
     228        1021 :     sp->goback = sp->goahead = false;
     229             : 
     230        1021 :     if (!name)
     231             :     {
     232           0 :         name = TZDEFAULT;
     233           0 :         if (!name)
     234           0 :             return EINVAL;
     235             :     }
     236             : 
     237        1021 :     if (name[0] == ':')
     238           0 :         ++name;
     239             : 
     240        1021 :     fid = pg_open_tzfile(name, canonname);
     241        1021 :     if (fid < 0)
     242          36 :         return ENOENT;          /* pg_open_tzfile may not set errno */
     243             : 
     244         985 :     nread = read(fid, up->buf, sizeof up->buf);
     245         985 :     if (nread < tzheadsize)
     246             :     {
     247           0 :         int         err = nread < 0 ? errno : EINVAL;
     248             : 
     249           0 :         close(fid);
     250           0 :         return err;
     251             :     }
     252         985 :     if (close(fid) < 0)
     253           0 :         return errno;
     254        2955 :     for (stored = 4; stored <= 8; stored *= 2)
     255             :     {
     256        1970 :         int32       ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
     257        1970 :         int32       ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
     258        1970 :         int32       leapcnt = detzcode(up->tzhead.tzh_leapcnt);
     259        1970 :         int32       timecnt = detzcode(up->tzhead.tzh_timecnt);
     260        1970 :         int32       typecnt = detzcode(up->tzhead.tzh_typecnt);
     261        1970 :         int32       charcnt = detzcode(up->tzhead.tzh_charcnt);
     262        1970 :         char const *p = up->buf + tzheadsize;
     263             : 
     264        3940 :         if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
     265        1970 :               && 0 < typecnt && typecnt < TZ_MAX_TYPES
     266        1970 :               && 0 <= timecnt && timecnt < TZ_MAX_TIMES
     267        1970 :               && 0 <= charcnt && charcnt < TZ_MAX_CHARS
     268        1970 :               && (ttisstdcnt == typecnt || ttisstdcnt == 0)
     269           0 :               && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
     270           0 :             return EINVAL;
     271        1970 :         if (nread
     272             :             < (tzheadsize        /* struct tzhead */
     273        1970 :                + timecnt * stored   /* ats */
     274        1970 :                + timecnt        /* types */
     275        1970 :                + typecnt * 6    /* ttinfos */
     276        1970 :                + charcnt        /* chars */
     277        1970 :                + leapcnt * (stored + 4) /* lsinfos */
     278        1970 :                + ttisstdcnt     /* ttisstds */
     279        1970 :                + ttisgmtcnt))   /* ttisgmts */
     280           0 :             return EINVAL;
     281        1970 :         sp->leapcnt = leapcnt;
     282        1970 :         sp->timecnt = timecnt;
     283        1970 :         sp->typecnt = typecnt;
     284        1970 :         sp->charcnt = charcnt;
     285             : 
     286             :         /*
     287             :          * Read transitions, discarding those out of pg_time_t range. But
     288             :          * pretend the last transition before time_t_min occurred at
     289             :          * time_t_min.
     290             :          */
     291        1970 :         timecnt = 0;
     292      190762 :         for (i = 0; i < sp->timecnt; ++i)
     293             :         {
     294      188792 :             int64       at
     295      188792 :             = stored == 4 ? detzcode(p) : detzcode64(p);
     296             : 
     297      188792 :             sp->types[i] = at <= time_t_max;
     298      188792 :             if (sp->types[i])
     299             :             {
     300      188792 :                 pg_time_t   attime
     301             :                 = ((TYPE_SIGNED(pg_time_t) ? at < time_t_min : at < 0)
     302      188792 :                    ? time_t_min : at);
     303             : 
     304      188792 :                 if (timecnt && attime <= sp->ats[timecnt - 1])
     305             :                 {
     306           0 :                     if (attime < sp->ats[timecnt - 1])
     307           0 :                         return EINVAL;
     308           0 :                     sp->types[i - 1] = 0;
     309           0 :                     timecnt--;
     310             :                 }
     311      188792 :                 sp->ats[timecnt++] = attime;
     312             :             }
     313      188792 :             p += stored;
     314             :         }
     315             : 
     316        1970 :         timecnt = 0;
     317      190762 :         for (i = 0; i < sp->timecnt; ++i)
     318             :         {
     319      188792 :             unsigned char typ = *p++;
     320             : 
     321      188792 :             if (sp->typecnt <= typ)
     322           0 :                 return EINVAL;
     323      188792 :             if (sp->types[i])
     324      188792 :                 sp->types[timecnt++] = typ;
     325             :         }
     326        1970 :         sp->timecnt = timecnt;
     327       11768 :         for (i = 0; i < sp->typecnt; ++i)
     328             :         {
     329             :             struct ttinfo *ttisp;
     330             :             unsigned char isdst,
     331             :                         abbrind;
     332             : 
     333        9798 :             ttisp = &sp->ttis[i];
     334        9798 :             ttisp->tt_gmtoff = detzcode(p);
     335        9798 :             p += 4;
     336        9798 :             isdst = *p++;
     337        9798 :             if (!(isdst < 2))
     338           0 :                 return EINVAL;
     339        9798 :             ttisp->tt_isdst = isdst;
     340        9798 :             abbrind = *p++;
     341        9798 :             if (!(abbrind < sp->charcnt))
     342           0 :                 return EINVAL;
     343        9798 :             ttisp->tt_abbrind = abbrind;
     344             :         }
     345       34188 :         for (i = 0; i < sp->charcnt; ++i)
     346       32218 :             sp->chars[i] = *p++;
     347        1970 :         sp->chars[i] = '\0'; /* ensure '\0' at end */
     348             : 
     349             :         /* Read leap seconds, discarding those out of pg_time_t range.  */
     350        1970 :         leapcnt = 0;
     351        1970 :         for (i = 0; i < sp->leapcnt; ++i)
     352             :         {
     353           0 :             int64       tr = stored == 4 ? detzcode(p) : detzcode64(p);
     354           0 :             int32       corr = detzcode(p + stored);
     355             : 
     356           0 :             p += stored + 4;
     357           0 :             if (tr <= time_t_max)
     358             :             {
     359           0 :                 pg_time_t   trans
     360             :                 = ((TYPE_SIGNED(pg_time_t) ? tr < time_t_min : tr < 0)
     361           0 :                    ? time_t_min : tr);
     362             : 
     363           0 :                 if (leapcnt && trans <= sp->lsis[leapcnt - 1].ls_trans)
     364             :                 {
     365           0 :                     if (trans < sp->lsis[leapcnt - 1].ls_trans)
     366           0 :                         return EINVAL;
     367           0 :                     leapcnt--;
     368             :                 }
     369           0 :                 sp->lsis[leapcnt].ls_trans = trans;
     370           0 :                 sp->lsis[leapcnt].ls_corr = corr;
     371           0 :                 leapcnt++;
     372             :             }
     373             :         }
     374        1970 :         sp->leapcnt = leapcnt;
     375             : 
     376       11768 :         for (i = 0; i < sp->typecnt; ++i)
     377             :         {
     378             :             struct ttinfo *ttisp;
     379             : 
     380        9798 :             ttisp = &sp->ttis[i];
     381        9798 :             if (ttisstdcnt == 0)
     382           0 :                 ttisp->tt_ttisstd = false;
     383             :             else
     384             :             {
     385        9798 :                 if (*p != true && *p != false)
     386           0 :                     return EINVAL;
     387        9798 :                 ttisp->tt_ttisstd = *p++;
     388             :             }
     389             :         }
     390       11768 :         for (i = 0; i < sp->typecnt; ++i)
     391             :         {
     392             :             struct ttinfo *ttisp;
     393             : 
     394        9798 :             ttisp = &sp->ttis[i];
     395        9798 :             if (ttisgmtcnt == 0)
     396           0 :                 ttisp->tt_ttisgmt = false;
     397             :             else
     398             :             {
     399        9798 :                 if (*p != true && *p != false)
     400           0 :                     return EINVAL;
     401        9798 :                 ttisp->tt_ttisgmt = *p++;
     402             :             }
     403             :         }
     404             : 
     405             :         /*
     406             :          * If this is an old file, we're done.
     407             :          */
     408        1970 :         if (up->tzhead.tzh_version[0] == '\0')
     409           0 :             break;
     410        1970 :         nread -= p - up->buf;
     411        1970 :         memmove(up->buf, p, nread);
     412             :     }
     413        1967 :     if (doextend && nread > 2 &&
     414        2946 :         up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
     415         982 :         sp->typecnt + 2 <= TZ_MAX_TYPES)
     416             :     {
     417         982 :         struct state *ts = &lsp->u.st;
     418             : 
     419         982 :         up->buf[nread - 1] = '\0';
     420         982 :         if (tzparse(&up->buf[1], ts, false)
     421         982 :             && ts->typecnt == 2)
     422             :         {
     423             :             /*
     424             :              * Attempt to reuse existing abbreviations. Without this,
     425             :              * America/Anchorage would be right on the edge after 2037 when
     426             :              * TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT
     427             :              * APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
     428             :              * AKST AKDT).  Reusing means sp->charcnt can stay 40 in this
     429             :              * example.
     430             :              */
     431         560 :             int         gotabbr = 0;
     432         560 :             int         charcnt = sp->charcnt;
     433             : 
     434        1680 :             for (i = 0; i < 2; i++)
     435             :             {
     436        1120 :                 char       *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
     437             :                 int         j;
     438             : 
     439        7710 :                 for (j = 0; j < charcnt; j++)
     440        7710 :                     if (strcmp(sp->chars + j, tsabbr) == 0)
     441             :                     {
     442        1120 :                         ts->ttis[i].tt_abbrind = j;
     443        1120 :                         gotabbr++;
     444        1120 :                         break;
     445             :                     }
     446        1120 :                 if (!(j < charcnt))
     447             :                 {
     448           0 :                     int         tsabbrlen = strlen(tsabbr);
     449             : 
     450           0 :                     if (j + tsabbrlen < TZ_MAX_CHARS)
     451             :                     {
     452           0 :                         strcpy(sp->chars + j, tsabbr);
     453           0 :                         charcnt = j + tsabbrlen + 1;
     454           0 :                         ts->ttis[i].tt_abbrind = j;
     455           0 :                         gotabbr++;
     456             :                     }
     457             :                 }
     458             :             }
     459         560 :             if (gotabbr == 2)
     460             :             {
     461         560 :                 sp->charcnt = charcnt;
     462             : 
     463             :                 /*
     464             :                  * Ignore any trailing, no-op transitions generated by zic as
     465             :                  * they don't help here and can run afoul of bugs in zic 2016j
     466             :                  * or earlier.
     467             :                  */
     468        1145 :                 while (1 < sp->timecnt
     469        1170 :                        && (sp->types[sp->timecnt - 1]
     470         585 :                            == sp->types[sp->timecnt - 2]))
     471          25 :                     sp->timecnt--;
     472             : 
     473      300728 :                 for (i = 0; i < ts->timecnt; i++)
     474      300728 :                     if (sp->ats[sp->timecnt - 1] < ts->ats[i])
     475         560 :                         break;
     476      820952 :                 while (i < ts->timecnt
     477      819832 :                        && sp->timecnt < TZ_MAX_TIMES)
     478             :                 {
     479      819832 :                     sp->ats[sp->timecnt] = ts->ats[i];
     480     1639664 :                     sp->types[sp->timecnt] = (sp->typecnt
     481      819832 :                                               + ts->types[i]);
     482      819832 :                     sp->timecnt++;
     483      819832 :                     i++;
     484             :                 }
     485         560 :                 sp->ttis[sp->typecnt++] = ts->ttis[0];
     486         560 :                 sp->ttis[sp->typecnt++] = ts->ttis[1];
     487             :             }
     488             :         }
     489             :     }
     490         985 :     if (sp->timecnt > 1)
     491             :     {
     492      914373 :         for (i = 1; i < sp->timecnt; ++i)
     493     1183566 :             if (typesequiv(sp, sp->types[i], sp->types[0]) &&
     494      270150 :                 differ_by_repeat(sp->ats[i], sp->ats[0]))
     495             :             {
     496           0 :                 sp->goback = true;
     497           0 :                 break;
     498             :             }
     499      459070 :         for (i = sp->timecnt - 2; i >= 0; --i)
     500      458673 :             if (typesequiv(sp, sp->types[sp->timecnt - 1],
     501      685653 :                            sp->types[i]) &&
     502      226980 :                 differ_by_repeat(sp->ats[sp->timecnt - 1],
     503             :                                  sp->ats[i]))
     504             :             {
     505         560 :                 sp->goahead = true;
     506         560 :                 break;
     507             :             }
     508             :     }
     509             : 
     510             :     /*
     511             :      * If type 0 is unused in transitions, it's the type to use for early
     512             :      * times.
     513             :      */
     514         985 :     for (i = 0; i < sp->timecnt; ++i)
     515         985 :         if (sp->types[i] == 0)
     516         985 :             break;
     517         985 :     i = i < sp->timecnt ? -1 : 0;
     518             : 
     519             :     /*
     520             :      * Absent the above, if there are transition times and the first
     521             :      * transition is to a daylight time find the standard type less than and
     522             :      * closest to the type of the first transition.
     523             :      */
     524         985 :     if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst)
     525             :     {
     526         338 :         i = sp->types[0];
     527         676 :         while (--i >= 0)
     528           0 :             if (!sp->ttis[i].tt_isdst)
     529           0 :                 break;
     530             :     }
     531             : 
     532             :     /*
     533             :      * If no result yet, find the first standard type. If there is none, punt
     534             :      * to type zero.
     535             :      */
     536         985 :     if (i < 0)
     537             :     {
     538         985 :         i = 0;
     539        2308 :         while (sp->ttis[i].tt_isdst)
     540         338 :             if (++i >= sp->typecnt)
     541             :             {
     542           0 :                 i = 0;
     543           0 :                 break;
     544             :             }
     545             :     }
     546         985 :     sp->defaulttype = i;
     547         985 :     return 0;
     548             : }
     549             : 
     550             : /* Load tz data from the file named NAME into *SP.  Read extended
     551             :  * format if DOEXTEND.  Return 0 on success, an errno value on failure.
     552             :  * PG: If "canonname" is not NULL, then on success the canonical spelling of
     553             :  * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
     554             :  */
     555             : int
     556        1021 : tzload(const char *name, char *canonname, struct state *sp, bool doextend)
     557             : {
     558        1021 :     union local_storage *lsp = malloc(sizeof *lsp);
     559             : 
     560        1021 :     if (!lsp)
     561           0 :         return errno;
     562             :     else
     563             :     {
     564        1021 :         int         err = tzloadbody(name, canonname, sp, doextend, lsp);
     565             : 
     566        1021 :         free(lsp);
     567        1021 :         return err;
     568             :     }
     569             : }
     570             : 
     571             : static bool
     572     1372089 : typesequiv(const struct state *sp, int a, int b)
     573             : {
     574             :     bool        result;
     575             : 
     576     1372089 :     if (sp == NULL ||
     577     1372089 :         a < 0 || a >= sp->typecnt ||
     578     1372089 :         b < 0 || b >= sp->typecnt)
     579           0 :         result = false;
     580             :     else
     581             :     {
     582     1372089 :         const struct ttinfo *ap = &sp->ttis[a];
     583     1372089 :         const struct ttinfo *bp = &sp->ttis[b];
     584             : 
     585     3246450 :         result = ap->tt_gmtoff == bp->tt_gmtoff &&
     586     1002947 :             ap->tt_isdst == bp->tt_isdst &&
     587      999005 :             ap->tt_ttisstd == bp->tt_ttisstd &&
     588     2368748 :             ap->tt_ttisgmt == bp->tt_ttisgmt &&
     589      498329 :             strcmp(&sp->chars[ap->tt_abbrind],
     590      498329 :                    &sp->chars[bp->tt_abbrind]) == 0;
     591             :     }
     592     1372089 :     return result;
     593             : }
     594             : 
     595             : static const int mon_lengths[2][MONSPERYEAR] = {
     596             :     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     597             :     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
     598             : };
     599             : 
     600             : static const int year_lengths[2] = {
     601             :     DAYSPERNYEAR, DAYSPERLYEAR
     602             : };
     603             : 
     604             : /*
     605             :  * Given a pointer into a time zone string, scan until a character that is not
     606             :  * a valid character in a zone name is found. Return a pointer to that
     607             :  * character.
     608             :  */
     609             : static const char *
     610        1281 : getzname(const char *strp)
     611             : {
     612             :     char        c;
     613             : 
     614        6590 :     while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
     615             :            c != '+')
     616        4028 :         ++strp;
     617        1281 :     return strp;
     618             : }
     619             : 
     620             : /*
     621             :  * Given a pointer into an extended time zone string, scan until the ending
     622             :  * delimiter of the zone name is located. Return a pointer to the delimiter.
     623             :  *
     624             :  * As with getzname above, the legal character set is actually quite
     625             :  * restricted, with other characters producing undefined results.
     626             :  * We don't do any checking here; checking is done later in common-case code.
     627             :  */
     628             : static const char *
     629         298 : getqzname(const char *strp, int delim)
     630             : {
     631             :     int         c;
     632             : 
     633        1541 :     while ((c = *strp) != '\0' && c != delim)
     634         945 :         ++strp;
     635         298 :     return strp;
     636             : }
     637             : 
     638             : /*
     639             :  * Given a pointer into a time zone string, extract a number from that string.
     640             :  * Check that the number is within a specified range; if it is not, return
     641             :  * NULL.
     642             :  * Otherwise, return a pointer to the first character not part of the number.
     643             :  */
     644             : static const char *
     645        4579 : getnum(const char *strp, int *nump, int min, int max)
     646             : {
     647             :     char        c;
     648             :     int         num;
     649             : 
     650        4579 :     if (strp == NULL || !is_digit(c = *strp))
     651           0 :         return NULL;
     652        4579 :     num = 0;
     653             :     do
     654             :     {
     655        5300 :         num = num * 10 + (c - '0');
     656        5300 :         if (num > max)
     657           0 :             return NULL;        /* illegal value */
     658        5300 :         c = *++strp;
     659        5300 :     } while (is_digit(c));
     660        4579 :     if (num < min)
     661           0 :         return NULL;            /* illegal value */
     662        4579 :     *nump = num;
     663        4579 :     return strp;
     664             : }
     665             : 
     666             : /*
     667             :  * Given a pointer into a time zone string, extract a number of seconds,
     668             :  * in hh[:mm[:ss]] form, from the string.
     669             :  * If any error occurs, return NULL.
     670             :  * Otherwise, return a pointer to the first character not part of the number
     671             :  * of seconds.
     672             :  */
     673             : static const char *
     674        1181 : getsecs(const char *strp, int32 *secsp)
     675             : {
     676             :     int         num;
     677             : 
     678             :     /*
     679             :      * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
     680             :      * "M10.4.6/26", which does not conform to Posix, but which specifies the
     681             :      * equivalent of "02:00 on the first Sunday on or after 23 Oct".
     682             :      */
     683        1181 :     strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
     684        1181 :     if (strp == NULL)
     685           0 :         return NULL;
     686        1181 :     *secsp = num * (int32) SECSPERHOUR;
     687        1181 :     if (*strp == ':')
     688             :     {
     689          46 :         ++strp;
     690          46 :         strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
     691          46 :         if (strp == NULL)
     692           0 :             return NULL;
     693          46 :         *secsp += num * SECSPERMIN;
     694          46 :         if (*strp == ':')
     695             :         {
     696           0 :             ++strp;
     697             :             /* 'SECSPERMIN' allows for leap seconds.  */
     698           0 :             strp = getnum(strp, &num, 0, SECSPERMIN);
     699           0 :             if (strp == NULL)
     700           0 :                 return NULL;
     701           0 :             *secsp += num;
     702             :         }
     703             :     }
     704        1181 :     return strp;
     705             : }
     706             : 
     707             : /*
     708             :  * Given a pointer into a time zone string, extract an offset, in
     709             :  * [+-]hh[:mm[:ss]] form, from the string.
     710             :  * If any error occurs, return NULL.
     711             :  * Otherwise, return a pointer to the first character not part of the time.
     712             :  */
     713             : static const char *
     714        1181 : getoffset(const char *strp, int32 *offsetp)
     715             : {
     716        1181 :     bool        neg = false;
     717             : 
     718        1181 :     if (*strp == '-')
     719             :     {
     720         353 :         neg = true;
     721         353 :         ++strp;
     722             :     }
     723         828 :     else if (*strp == '+')
     724          13 :         ++strp;
     725        1181 :     strp = getsecs(strp, offsetp);
     726        1181 :     if (strp == NULL)
     727           0 :         return NULL;            /* illegal time */
     728        1181 :     if (neg)
     729         353 :         *offsetp = -*offsetp;
     730        1181 :     return strp;
     731             : }
     732             : 
     733             : /*
     734             :  * Given a pointer into a time zone string, extract a rule in the form
     735             :  * date[/time]. See POSIX section 8 for the format of "date" and "time".
     736             :  * If a valid rule is not found, return NULL.
     737             :  * Otherwise, return a pointer to the first character not part of the rule.
     738             :  */
     739             : static const char *
     740        1120 : getrule(const char *strp, struct rule *rulep)
     741             : {
     742        1120 :     if (*strp == 'J')
     743             :     {
     744             :         /*
     745             :          * Julian day.
     746             :          */
     747           4 :         rulep->r_type = JULIAN_DAY;
     748           4 :         ++strp;
     749           4 :         strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
     750             :     }
     751        1116 :     else if (*strp == 'M')
     752             :     {
     753             :         /*
     754             :          * Month, week, day.
     755             :          */
     756        1116 :         rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
     757        1116 :         ++strp;
     758        1116 :         strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
     759        1116 :         if (strp == NULL)
     760           0 :             return NULL;
     761        1116 :         if (*strp++ != '.')
     762           0 :             return NULL;
     763        1116 :         strp = getnum(strp, &rulep->r_week, 1, 5);
     764        1116 :         if (strp == NULL)
     765           0 :             return NULL;
     766        1116 :         if (*strp++ != '.')
     767           0 :             return NULL;
     768        1116 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
     769             :     }
     770           0 :     else if (is_digit(*strp))
     771             :     {
     772             :         /*
     773             :          * Day of year.
     774             :          */
     775           0 :         rulep->r_type = DAY_OF_YEAR;
     776           0 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
     777             :     }
     778             :     else
     779           0 :         return NULL;            /* invalid format */
     780        1120 :     if (strp == NULL)
     781           0 :         return NULL;
     782        1120 :     if (*strp == '/')
     783             :     {
     784             :         /*
     785             :          * Time specified.
     786             :          */
     787         167 :         ++strp;
     788         167 :         strp = getoffset(strp, &rulep->r_time);
     789             :     }
     790             :     else
     791         953 :         rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
     792        1120 :     return strp;
     793             : }
     794             : 
     795             : /*
     796             :  * Given a year, a rule, and the offset from UT at the time that rule takes
     797             :  * effect, calculate the year-relative time that rule takes effect.
     798             :  */
     799             : static int32
     800     1121120 : transtime(int year, const struct rule *rulep,
     801             :           int32 offset)
     802             : {
     803             :     bool        leapyear;
     804             :     int32       value;
     805             :     int         i,
     806             :                 d,
     807             :                 m1,
     808             :                 yy0,
     809             :                 yy1,
     810             :                 yy2,
     811             :                 dow;
     812             : 
     813     1121120 :     INITIALIZE(value);
     814     1121120 :     leapyear = isleap(year);
     815     1121120 :     switch (rulep->r_type)
     816             :     {
     817             : 
     818             :         case JULIAN_DAY:
     819             : 
     820             :             /*
     821             :              * Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
     822             :              * years. In non-leap years, or if the day number is 59 or less,
     823             :              * just add SECSPERDAY times the day number-1 to the time of
     824             :              * January 1, midnight, to get the day.
     825             :              */
     826        4004 :             value = (rulep->r_day - 1) * SECSPERDAY;
     827        4004 :             if (leapyear && rulep->r_day >= 60)
     828         968 :                 value += SECSPERDAY;
     829        4004 :             break;
     830             : 
     831             :         case DAY_OF_YEAR:
     832             : 
     833             :             /*
     834             :              * n - day of year. Just add SECSPERDAY times the day number to
     835             :              * the time of January 1, midnight, to get the day.
     836             :              */
     837           0 :             value = rulep->r_day * SECSPERDAY;
     838           0 :             break;
     839             : 
     840             :         case MONTH_NTH_DAY_OF_WEEK:
     841             : 
     842             :             /*
     843             :              * Mm.n.d - nth "dth day" of month m.
     844             :              */
     845             : 
     846             :             /*
     847             :              * Use Zeller's Congruence to get day-of-week of first day of
     848             :              * month.
     849             :              */
     850     1117116 :             m1 = (rulep->r_mon + 9) % 12 + 1;
     851     1117116 :             yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
     852     1117116 :             yy1 = yy0 / 100;
     853     1117116 :             yy2 = yy0 % 100;
     854     2234232 :             dow = ((26 * m1 - 2) / 10 +
     855     1117116 :                    1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
     856     1117116 :             if (dow < 0)
     857      209518 :                 dow += DAYSPERWEEK;
     858             : 
     859             :             /*
     860             :              * "dow" is the day-of-week of the first day of the month. Get the
     861             :              * day-of-month (zero-origin) of the first "dow" day of the month.
     862             :              */
     863     1117116 :             d = rulep->r_day - dow;
     864     1117116 :             if (d < 0)
     865      936829 :                 d += DAYSPERWEEK;
     866     2220887 :             for (i = 1; i < rulep->r_week; ++i)
     867             :             {
     868     2420418 :                 if (d + DAYSPERWEEK >=
     869     1210209 :                     mon_lengths[(int) leapyear][rulep->r_mon - 1])
     870      106438 :                     break;
     871     1103771 :                 d += DAYSPERWEEK;
     872             :             }
     873             : 
     874             :             /*
     875             :              * "d" is the day-of-month (zero-origin) of the day we want.
     876             :              */
     877     1117116 :             value = d * SECSPERDAY;
     878     7705698 :             for (i = 0; i < rulep->r_mon - 1; ++i)
     879     6588582 :                 value += mon_lengths[(int) leapyear][i] * SECSPERDAY;
     880     1117116 :             break;
     881             :     }
     882             : 
     883             :     /*
     884             :      * "value" is the year-relative time of 00:00:00 UT on the day in
     885             :      * question. To get the year-relative time of the specified local time on
     886             :      * that day, add the transition time and the current offset from UT.
     887             :      */
     888     1121120 :     return value + rulep->r_time + offset;
     889             : }
     890             : 
     891             : /*
     892             :  * Given a POSIX section 8-style TZ string, fill in the rule tables as
     893             :  * appropriate.
     894             :  * Returns true on success, false on failure.
     895             :  */
     896             : bool
     897        1023 : tzparse(const char *name, struct state *sp, bool lastditch)
     898             : {
     899             :     const char *stdname;
     900        1023 :     const char *dstname = NULL;
     901             :     size_t      stdlen;
     902             :     size_t      dstlen;
     903             :     size_t      charcnt;
     904             :     int32       stdoffset;
     905             :     int32       dstoffset;
     906             :     char       *cp;
     907             :     bool        load_ok;
     908             : 
     909        1023 :     stdname = name;
     910        1023 :     if (lastditch)
     911             :     {
     912             :         /*
     913             :          * This is intentionally somewhat different from the IANA code.  We do
     914             :          * not want to invoke tzload() in the lastditch case: we can't assume
     915             :          * pg_open_tzfile() is sane yet, and we don't care about leap seconds
     916             :          * anyway.
     917             :          */
     918           5 :         stdlen = strlen(name);  /* length of standard zone name */
     919           5 :         name += stdlen;
     920           5 :         if (stdlen >= sizeof sp->chars)
     921           0 :             stdlen = (sizeof sp->chars) - 1;
     922           5 :         charcnt = stdlen + 1;
     923           5 :         stdoffset = 0;
     924           5 :         sp->goback = sp->goahead = false; /* simulate failed tzload() */
     925           5 :         load_ok = false;
     926             :     }
     927             :     else
     928             :     {
     929        1018 :         if (*name == '<')
     930             :         {
     931         271 :             name++;
     932         271 :             stdname = name;
     933         271 :             name = getqzname(name, '>');
     934         271 :             if (*name != '>')
     935           0 :                 return false;
     936         271 :             stdlen = name - stdname;
     937         271 :             name++;
     938             :         }
     939             :         else
     940             :         {
     941         747 :             name = getzname(name);
     942         747 :             stdlen = name - stdname;
     943             :         }
     944        1018 :         if (*name == '\0')      /* we allow empty STD abbrev, unlike IANA */
     945           8 :             return false;
     946        1010 :         name = getoffset(name, &stdoffset);
     947        1010 :         if (name == NULL)
     948           0 :             return false;
     949        1010 :         charcnt = stdlen + 1;
     950        1010 :         if (sizeof sp->chars < charcnt)
     951           0 :             return false;
     952             : 
     953             :         /*
     954             :          * This bit also differs from the IANA code, which doesn't make any
     955             :          * attempt to avoid repetitive loadings of the TZDEFRULES zone.
     956             :          */
     957        1010 :         if (tzdefrules_loaded == 0)
     958             :         {
     959           3 :             if (tzload(TZDEFRULES, NULL, &tzdefrules_s, false) == 0)
     960           3 :                 tzdefrules_loaded = 1;
     961             :             else
     962           0 :                 tzdefrules_loaded = -1;
     963             :         }
     964        1010 :         load_ok = (tzdefrules_loaded > 0);
     965        1010 :         if (load_ok)
     966        1010 :             memcpy(sp, &tzdefrules_s, sizeof(struct state));
     967             :     }
     968        1015 :     if (!load_ok)
     969           5 :         sp->leapcnt = 0;     /* so, we're off a little */
     970        1015 :     if (*name != '\0')
     971             :     {
     972         561 :         if (*name == '<')
     973             :         {
     974          27 :             dstname = ++name;
     975          27 :             name = getqzname(name, '>');
     976          27 :             if (*name != '>')
     977           0 :                 return false;
     978          27 :             dstlen = name - dstname;
     979          27 :             name++;
     980             :         }
     981             :         else
     982             :         {
     983         534 :             dstname = name;
     984         534 :             name = getzname(name);
     985         534 :             dstlen = name - dstname;    /* length of DST zone name */
     986             :         }
     987         561 :         if (!dstlen)
     988           0 :             return false;
     989         561 :         charcnt += dstlen + 1;
     990         561 :         if (sizeof sp->chars < charcnt)
     991           0 :             return false;
     992         561 :         if (*name != '\0' && *name != ',' && *name != ';')
     993             :         {
     994           4 :             name = getoffset(name, &dstoffset);
     995           8 :             if (name == NULL)
     996           0 :                 return false;
     997             :         }
     998             :         else
     999         557 :             dstoffset = stdoffset - SECSPERHOUR;
    1000         561 :         if (*name == '\0' && !load_ok)
    1001           0 :             name = TZDEFRULESTRING;
    1002         561 :         if (*name == ',' || *name == ';')
    1003         560 :         {
    1004             :             struct rule start;
    1005             :             struct rule end;
    1006             :             int         year;
    1007             :             int         yearlim;
    1008             :             int         timecnt;
    1009             :             pg_time_t   janfirst;
    1010         560 :             int32       janoffset = 0;
    1011             :             int         yearbeg;
    1012             : 
    1013         560 :             ++name;
    1014         560 :             if ((name = getrule(name, &start)) == NULL)
    1015           0 :                 return false;
    1016         560 :             if (*name++ != ',')
    1017           0 :                 return false;
    1018         560 :             if ((name = getrule(name, &end)) == NULL)
    1019           0 :                 return false;
    1020         560 :             if (*name != '\0')
    1021           0 :                 return false;
    1022         560 :             sp->typecnt = 2; /* standard time and DST */
    1023             : 
    1024             :             /*
    1025             :              * Two transitions per year, from EPOCH_YEAR forward.
    1026             :              */
    1027         560 :             init_ttinfo(&sp->ttis[0], -dstoffset, true, stdlen + 1);
    1028         560 :             init_ttinfo(&sp->ttis[1], -stdoffset, false, 0);
    1029         560 :             sp->defaulttype = 0;
    1030         560 :             timecnt = 0;
    1031         560 :             janfirst = 0;
    1032         560 :             yearbeg = EPOCH_YEAR;
    1033             : 
    1034             :             do
    1035             :             {
    1036      112000 :                 int32       yearsecs
    1037      112000 :                 = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
    1038             : 
    1039      112000 :                 yearbeg--;
    1040      112000 :                 if (increment_overflow_time(&janfirst, -yearsecs))
    1041             :                 {
    1042           0 :                     janoffset = -yearsecs;
    1043           0 :                     break;
    1044             :                 }
    1045      112000 :             } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
    1046             : 
    1047         560 :             yearlim = yearbeg + YEARSPERREPEAT + 1;
    1048      560560 :             for (year = yearbeg; year < yearlim; year++)
    1049             :             {
    1050             :                 int32
    1051      560560 :                             starttime = transtime(year, &start, stdoffset),
    1052      560560 :                             endtime = transtime(year, &end, dstoffset);
    1053             :                 int32
    1054      560560 :                             yearsecs = (year_lengths[isleap(year)]
    1055             :                                         * SECSPERDAY);
    1056      560560 :                 bool        reversed = endtime < starttime;
    1057             : 
    1058      560560 :                 if (reversed)
    1059             :                 {
    1060       38038 :                     int32       swap = starttime;
    1061             : 
    1062       38038 :                     starttime = endtime;
    1063       38038 :                     endtime = swap;
    1064             :                 }
    1065      560560 :                 if (reversed
    1066      522522 :                     || (starttime < endtime
    1067     1045044 :                         && (endtime - starttime
    1068             :                             < (yearsecs
    1069      522522 :                                + (stdoffset - dstoffset)))))
    1070             :                 {
    1071      560560 :                     if (TZ_MAX_TIMES - 2 < timecnt)
    1072         560 :                         break;
    1073      560000 :                     sp->ats[timecnt] = janfirst;
    1074      560000 :                     if (!increment_overflow_time
    1075             :                         (&sp->ats[timecnt],
    1076             :                          janoffset + starttime))
    1077      560000 :                         sp->types[timecnt++] = reversed;
    1078           0 :                     else if (janoffset)
    1079           0 :                         sp->defaulttype = reversed;
    1080      560000 :                     sp->ats[timecnt] = janfirst;
    1081      560000 :                     if (!increment_overflow_time
    1082             :                         (&sp->ats[timecnt],
    1083             :                          janoffset + endtime))
    1084             :                     {
    1085      560000 :                         sp->types[timecnt++] = !reversed;
    1086      560000 :                         yearlim = year + YEARSPERREPEAT + 1;
    1087             :                     }
    1088           0 :                     else if (janoffset)
    1089           0 :                         sp->defaulttype = !reversed;
    1090             :                 }
    1091      560000 :                 if (increment_overflow_time
    1092             :                     (&janfirst, janoffset + yearsecs))
    1093           0 :                     break;
    1094      560000 :                 janoffset = 0;
    1095             :             }
    1096         560 :             sp->timecnt = timecnt;
    1097         560 :             if (!timecnt)
    1098           0 :                 sp->typecnt = 1; /* Perpetual DST.  */
    1099         560 :             else if (YEARSPERREPEAT < year - yearbeg)
    1100         560 :                 sp->goback = sp->goahead = true;
    1101             :         }
    1102             :         else
    1103             :         {
    1104             :             int32       theirstdoffset;
    1105             :             int32       theirdstoffset;
    1106             :             int32       theiroffset;
    1107             :             bool        isdst;
    1108             :             int         i;
    1109             :             int         j;
    1110             : 
    1111           1 :             if (*name != '\0')
    1112           0 :                 return false;
    1113             : 
    1114             :             /*
    1115             :              * Initial values of theirstdoffset and theirdstoffset.
    1116             :              */
    1117           1 :             theirstdoffset = 0;
    1118           1 :             for (i = 0; i < sp->timecnt; ++i)
    1119             :             {
    1120           1 :                 j = sp->types[i];
    1121           1 :                 if (!sp->ttis[j].tt_isdst)
    1122             :                 {
    1123           1 :                     theirstdoffset =
    1124           1 :                         -sp->ttis[j].tt_gmtoff;
    1125           1 :                     break;
    1126             :                 }
    1127             :             }
    1128           1 :             theirdstoffset = 0;
    1129           3 :             for (i = 0; i < sp->timecnt; ++i)
    1130             :             {
    1131           3 :                 j = sp->types[i];
    1132           3 :                 if (sp->ttis[j].tt_isdst)
    1133             :                 {
    1134           1 :                     theirdstoffset =
    1135           1 :                         -sp->ttis[j].tt_gmtoff;
    1136           1 :                     break;
    1137             :                 }
    1138             :             }
    1139             : 
    1140             :             /*
    1141             :              * Initially we're assumed to be in standard time.
    1142             :              */
    1143           1 :             isdst = false;
    1144           1 :             theiroffset = theirstdoffset;
    1145             : 
    1146             :             /*
    1147             :              * Now juggle transition times and types tracking offsets as you
    1148             :              * do.
    1149             :              */
    1150         238 :             for (i = 0; i < sp->timecnt; ++i)
    1151             :             {
    1152         237 :                 j = sp->types[i];
    1153         237 :                 sp->types[i] = sp->ttis[j].tt_isdst;
    1154         237 :                 if (sp->ttis[j].tt_ttisgmt)
    1155             :                 {
    1156             :                     /* No adjustment to transition time */
    1157             :                 }
    1158             :                 else
    1159             :                 {
    1160             :                     /*
    1161             :                      * If summer time is in effect, and the transition time
    1162             :                      * was not specified as standard time, add the summer time
    1163             :                      * offset to the transition time; otherwise, add the
    1164             :                      * standard time offset to the transition time.
    1165             :                      */
    1166             : 
    1167             :                     /*
    1168             :                      * Transitions from DST to DDST will effectively disappear
    1169             :                      * since POSIX provides for only one DST offset.
    1170             :                      */
    1171         236 :                     if (isdst && !sp->ttis[j].tt_ttisstd)
    1172             :                     {
    1173           0 :                         sp->ats[i] += dstoffset -
    1174             :                             theirdstoffset;
    1175             :                     }
    1176             :                     else
    1177             :                     {
    1178         236 :                         sp->ats[i] += stdoffset -
    1179             :                             theirstdoffset;
    1180             :                     }
    1181             :                 }
    1182         237 :                 theiroffset = -sp->ttis[j].tt_gmtoff;
    1183         237 :                 if (sp->ttis[j].tt_isdst)
    1184         118 :                     theirdstoffset = theiroffset;
    1185             :                 else
    1186         119 :                     theirstdoffset = theiroffset;
    1187             :             }
    1188             : 
    1189             :             /*
    1190             :              * Finally, fill in ttis.
    1191             :              */
    1192           1 :             init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
    1193           1 :             init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
    1194           1 :             sp->typecnt = 2;
    1195           1 :             sp->defaulttype = 0;
    1196             :         }
    1197             :     }
    1198             :     else
    1199             :     {
    1200         454 :         dstlen = 0;
    1201         454 :         sp->typecnt = 1;     /* only standard time */
    1202         454 :         sp->timecnt = 0;
    1203         454 :         init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
    1204         454 :         sp->defaulttype = 0;
    1205             :     }
    1206        1015 :     sp->charcnt = charcnt;
    1207        1015 :     cp = sp->chars;
    1208        1015 :     memcpy(cp, stdname, stdlen);
    1209        1015 :     cp += stdlen;
    1210        1015 :     *cp++ = '\0';
    1211        1015 :     if (dstlen != 0)
    1212             :     {
    1213         561 :         memcpy(cp, dstname, dstlen);
    1214         561 :         *(cp + dstlen) = '\0';
    1215             :     }
    1216        1015 :     return true;
    1217             : }
    1218             : 
    1219             : static void
    1220           6 : gmtload(struct state *sp)
    1221             : {
    1222           6 :     if (tzload(gmt, NULL, sp, true) != 0)
    1223           0 :         tzparse(gmt, sp, true);
    1224           6 : }
    1225             : 
    1226             : 
    1227             : /*
    1228             :  * The easy way to behave "as if no library function calls" localtime
    1229             :  * is to not call it, so we drop its guts into "localsub", which can be
    1230             :  * freely called. (And no, the PANS doesn't require the above behavior,
    1231             :  * but it *is* desirable.)
    1232             :  */
    1233             : static struct pg_tm *
    1234       14889 : localsub(struct state const *sp, pg_time_t const *timep,
    1235             :          struct pg_tm *tmp)
    1236             : {
    1237             :     const struct ttinfo *ttisp;
    1238             :     int         i;
    1239             :     struct pg_tm *result;
    1240       14889 :     const pg_time_t t = *timep;
    1241             : 
    1242       14889 :     if (sp == NULL)
    1243           0 :         return gmtsub(timep, 0, tmp);
    1244       29778 :     if ((sp->goback && t < sp->ats[0]) ||
    1245       19904 :         (sp->goahead && t > sp->ats[sp->timecnt - 1]))
    1246             :     {
    1247           8 :         pg_time_t   newt = t;
    1248             :         pg_time_t   seconds;
    1249             :         pg_time_t   years;
    1250             : 
    1251           8 :         if (t < sp->ats[0])
    1252           0 :             seconds = sp->ats[0] - t;
    1253             :         else
    1254           8 :             seconds = t - sp->ats[sp->timecnt - 1];
    1255           8 :         --seconds;
    1256           8 :         years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
    1257           8 :         seconds = years * AVGSECSPERYEAR;
    1258           8 :         if (t < sp->ats[0])
    1259           0 :             newt += seconds;
    1260             :         else
    1261           8 :             newt -= seconds;
    1262          16 :         if (newt < sp->ats[0] ||
    1263           8 :             newt > sp->ats[sp->timecnt - 1])
    1264           0 :             return NULL;        /* "cannot happen" */
    1265           8 :         result = localsub(sp, &newt, tmp);
    1266           8 :         if (result)
    1267             :         {
    1268             :             int64       newy;
    1269             : 
    1270           8 :             newy = result->tm_year;
    1271           8 :             if (t < sp->ats[0])
    1272           0 :                 newy -= years;
    1273             :             else
    1274           8 :                 newy += years;
    1275           8 :             if (!(INT_MIN <= newy && newy <= INT_MAX))
    1276           0 :                 return NULL;
    1277           8 :             result->tm_year = newy;
    1278             :         }
    1279           8 :         return result;
    1280             :     }
    1281       14881 :     if (sp->timecnt == 0 || t < sp->ats[0])
    1282             :     {
    1283         416 :         i = sp->defaulttype;
    1284             :     }
    1285             :     else
    1286             :     {
    1287       14465 :         int         lo = 1;
    1288       14465 :         int         hi = sp->timecnt;
    1289             : 
    1290      133960 :         while (lo < hi)
    1291             :         {
    1292      105030 :             int         mid = (lo + hi) >> 1;
    1293             : 
    1294      105030 :             if (t < sp->ats[mid])
    1295       34636 :                 hi = mid;
    1296             :             else
    1297       70394 :                 lo = mid + 1;
    1298             :         }
    1299       14465 :         i = (int) sp->types[lo - 1];
    1300             :     }
    1301       14881 :     ttisp = &sp->ttis[i];
    1302             : 
    1303       14881 :     result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
    1304       14881 :     if (result)
    1305             :     {
    1306       14881 :         result->tm_isdst = ttisp->tt_isdst;
    1307       14881 :         result->tm_zone = (char *) &sp->chars[ttisp->tt_abbrind];
    1308             :     }
    1309       14881 :     return result;
    1310             : }
    1311             : 
    1312             : 
    1313             : struct pg_tm *
    1314       14881 : pg_localtime(const pg_time_t *timep, const pg_tz *tz)
    1315             : {
    1316       14881 :     return localsub(&tz->state, timep, &tm);
    1317             : }
    1318             : 
    1319             : 
    1320             : /*
    1321             :  * gmtsub is to gmtime as localsub is to localtime.
    1322             :  *
    1323             :  * Except we have a private "struct state" for GMT, so no sp is passed in.
    1324             :  */
    1325             : static struct pg_tm *
    1326          13 : gmtsub(pg_time_t const *timep, int32 offset, struct pg_tm *tmp)
    1327             : {
    1328             :     struct pg_tm *result;
    1329             : 
    1330             :     /* GMT timezone state data is kept here */
    1331             :     static struct state gmtmem;
    1332             :     static bool gmt_is_set = false;
    1333             : #define gmtptr      (&gmtmem)
    1334             : 
    1335          13 :     if (!gmt_is_set)
    1336             :     {
    1337           6 :         gmt_is_set = true;
    1338           6 :         gmtload(gmtptr);
    1339             :     }
    1340          13 :     result = timesub(timep, offset, gmtptr, tmp);
    1341             : 
    1342             :     /*
    1343             :      * Could get fancy here and deliver something such as "+xx" or "-xx" if
    1344             :      * offset is non-zero, but this is no time for a treasure hunt.
    1345             :      */
    1346          13 :     if (offset != 0)
    1347           0 :         tmp->tm_zone = wildabbr;
    1348             :     else
    1349          13 :         tmp->tm_zone = gmtptr->chars;
    1350             : 
    1351          13 :     return result;
    1352             : }
    1353             : 
    1354             : struct pg_tm *
    1355          13 : pg_gmtime(const pg_time_t *timep)
    1356             : {
    1357          13 :     return gmtsub(timep, 0, &tm);
    1358             : }
    1359             : 
    1360             : /*
    1361             :  * Return the number of leap years through the end of the given year
    1362             :  * where, to make the math easy, the answer for year zero is defined as zero.
    1363             :  */
    1364             : static int
    1365       64196 : leaps_thru_end_of(const int y)
    1366             : {
    1367       64362 :     return (y >= 0) ? (y / 4 - y / 100 + y / 400) :
    1368         166 :         -(leaps_thru_end_of(-(y + 1)) + 1);
    1369             : }
    1370             : 
    1371             : static struct pg_tm *
    1372       14894 : timesub(const pg_time_t *timep, int32 offset,
    1373             :         const struct state *sp, struct pg_tm *tmp)
    1374             : {
    1375             :     const struct lsinfo *lp;
    1376             :     pg_time_t   tdays;
    1377             :     int         idays;          /* unsigned would be so 2003 */
    1378             :     int64       rem;
    1379             :     int         y;
    1380             :     const int  *ip;
    1381             :     int64       corr;
    1382             :     bool        hit;
    1383             :     int         i;
    1384             : 
    1385       14894 :     corr = 0;
    1386       14894 :     hit = false;
    1387       14894 :     i = (sp == NULL) ? 0 : sp->leapcnt;
    1388       29788 :     while (--i >= 0)
    1389             :     {
    1390           0 :         lp = &sp->lsis[i];
    1391           0 :         if (*timep >= lp->ls_trans)
    1392             :         {
    1393           0 :             if (*timep == lp->ls_trans)
    1394             :             {
    1395           0 :                 hit = ((i == 0 && lp->ls_corr > 0) ||
    1396           0 :                        lp->ls_corr > sp->lsis[i - 1].ls_corr);
    1397           0 :                 if (hit)
    1398           0 :                     while (i > 0 &&
    1399           0 :                            sp->lsis[i].ls_trans ==
    1400           0 :                            sp->lsis[i - 1].ls_trans + 1 &&
    1401           0 :                            sp->lsis[i].ls_corr ==
    1402           0 :                            sp->lsis[i - 1].ls_corr + 1)
    1403             :                     {
    1404           0 :                         ++hit;
    1405           0 :                         --i;
    1406             :                     }
    1407             :             }
    1408           0 :             corr = lp->ls_corr;
    1409           0 :             break;
    1410             :         }
    1411             :     }
    1412       14894 :     y = EPOCH_YEAR;
    1413       14894 :     tdays = *timep / SECSPERDAY;
    1414       14894 :     rem = *timep % SECSPERDAY;
    1415       46909 :     while (tdays < 0 || tdays >= year_lengths[isleap(y)])
    1416             :     {
    1417             :         int         newy;
    1418             :         pg_time_t   tdelta;
    1419             :         int         idelta;
    1420             :         int         leapdays;
    1421             : 
    1422       17121 :         tdelta = tdays / DAYSPERLYEAR;
    1423       17121 :         if (!((!TYPE_SIGNED(pg_time_t) ||INT_MIN <= tdelta)
    1424             :               && tdelta <= INT_MAX))
    1425             :             goto out_of_range;
    1426       17121 :         idelta = tdelta;
    1427       17121 :         if (idelta == 0)
    1428        1709 :             idelta = (tdays < 0) ? -1 : 1;
    1429       17121 :         newy = y;
    1430       17121 :         if (increment_overflow(&newy, idelta))
    1431           0 :             goto out_of_range;
    1432       34242 :         leapdays = leaps_thru_end_of(newy - 1) -
    1433       17121 :             leaps_thru_end_of(y - 1);
    1434       17121 :         tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
    1435       17121 :         tdays -= leapdays;
    1436       17121 :         y = newy;
    1437             :     }
    1438             : 
    1439             :     /*
    1440             :      * Given the range, we can now fearlessly cast...
    1441             :      */
    1442       14894 :     idays = tdays;
    1443       14894 :     rem += offset - corr;
    1444       33360 :     while (rem < 0)
    1445             :     {
    1446        3572 :         rem += SECSPERDAY;
    1447        3572 :         --idays;
    1448             :     }
    1449       29820 :     while (rem >= SECSPERDAY)
    1450             :     {
    1451          32 :         rem -= SECSPERDAY;
    1452          32 :         ++idays;
    1453             :     }
    1454       30849 :     while (idays < 0)
    1455             :     {
    1456        1061 :         if (increment_overflow(&y, -1))
    1457           0 :             goto out_of_range;
    1458        1061 :         idays += year_lengths[isleap(y)];
    1459             :     }
    1460       29788 :     while (idays >= year_lengths[isleap(y)])
    1461             :     {
    1462           0 :         idays -= year_lengths[isleap(y)];
    1463           0 :         if (increment_overflow(&y, 1))
    1464           0 :             goto out_of_range;
    1465             :     }
    1466       14894 :     tmp->tm_year = y;
    1467       14894 :     if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
    1468           0 :         goto out_of_range;
    1469       14894 :     tmp->tm_yday = idays;
    1470             : 
    1471             :     /*
    1472             :      * The "extra" mods below avoid overflow problems.
    1473             :      */
    1474       14894 :     tmp->tm_wday = EPOCH_WDAY +
    1475       14894 :         ((y - EPOCH_YEAR) % DAYSPERWEEK) *
    1476       14894 :         (DAYSPERNYEAR % DAYSPERWEEK) +
    1477       29788 :         leaps_thru_end_of(y - 1) -
    1478       29788 :         leaps_thru_end_of(EPOCH_YEAR - 1) +
    1479             :         idays;
    1480       14894 :     tmp->tm_wday %= DAYSPERWEEK;
    1481       14894 :     if (tmp->tm_wday < 0)
    1482         110 :         tmp->tm_wday += DAYSPERWEEK;
    1483       14894 :     tmp->tm_hour = (int) (rem / SECSPERHOUR);
    1484       14894 :     rem %= SECSPERHOUR;
    1485       14894 :     tmp->tm_min = (int) (rem / SECSPERMIN);
    1486             : 
    1487             :     /*
    1488             :      * A positive leap second requires a special representation. This uses
    1489             :      * "... ??:59:60" et seq.
    1490             :      */
    1491       14894 :     tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
    1492       14894 :     ip = mon_lengths[isleap(y)];
    1493      111344 :     for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
    1494       96450 :         idays -= ip[tmp->tm_mon];
    1495       14894 :     tmp->tm_mday = (int) (idays + 1);
    1496       14894 :     tmp->tm_isdst = 0;
    1497       14894 :     tmp->tm_gmtoff = offset;
    1498       14894 :     return tmp;
    1499             : 
    1500             : out_of_range:
    1501           0 :     errno = EOVERFLOW;
    1502           0 :     return NULL;
    1503             : }
    1504             : 
    1505             : /*
    1506             :  * Normalize logic courtesy Paul Eggert.
    1507             :  */
    1508             : 
    1509             : static bool
    1510       33076 : increment_overflow(int *ip, int j)
    1511             : {
    1512       33076 :     int const   i = *ip;
    1513             : 
    1514             :     /*----------
    1515             :      * If i >= 0 there can only be overflow if i + j > INT_MAX
    1516             :      * or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
    1517             :      * If i < 0 there can only be overflow if i + j < INT_MIN
    1518             :      * or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
    1519             :      *----------
    1520             :      */
    1521       33076 :     if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
    1522           0 :         return true;
    1523       33076 :     *ip += j;
    1524       33076 :     return false;
    1525             : }
    1526             : 
    1527             : static bool
    1528     1792000 : increment_overflow_time(pg_time_t *tp, int32 j)
    1529             : {
    1530             :     /*----------
    1531             :      * This is like
    1532             :      * 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
    1533             :      * except that it does the right thing even if *tp + j would overflow.
    1534             :      *----------
    1535             :      */
    1536     3584000 :     if (!(j < 0
    1537      112000 :           ? (TYPE_SIGNED(pg_time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
    1538     1680000 :           : *tp <= time_t_max - j))
    1539           0 :         return true;
    1540     1792000 :     *tp += j;
    1541     1792000 :     return false;
    1542             : }
    1543             : 
    1544             : /*
    1545             :  * Find the next DST transition time in the given zone after the given time
    1546             :  *
    1547             :  * *timep and *tz are input arguments, the other parameters are output values.
    1548             :  *
    1549             :  * When the function result is 1, *boundary is set to the pg_time_t
    1550             :  * representation of the next DST transition time after *timep,
    1551             :  * *before_gmtoff and *before_isdst are set to the GMT offset and isdst
    1552             :  * state prevailing just before that boundary (in particular, the state
    1553             :  * prevailing at *timep), and *after_gmtoff and *after_isdst are set to
    1554             :  * the state prevailing just after that boundary.
    1555             :  *
    1556             :  * When the function result is 0, there is no known DST transition
    1557             :  * after *timep, but *before_gmtoff and *before_isdst indicate the GMT
    1558             :  * offset and isdst state prevailing at *timep.  (This would occur in
    1559             :  * DST-less time zones, or if a zone has permanently ceased using DST.)
    1560             :  *
    1561             :  * A function result of -1 indicates failure (this case does not actually
    1562             :  * occur in our current implementation).
    1563             :  */
    1564             : int
    1565        3135 : pg_next_dst_boundary(const pg_time_t *timep,
    1566             :                      long int *before_gmtoff,
    1567             :                      int *before_isdst,
    1568             :                      pg_time_t *boundary,
    1569             :                      long int *after_gmtoff,
    1570             :                      int *after_isdst,
    1571             :                      const pg_tz *tz)
    1572             : {
    1573             :     const struct state *sp;
    1574             :     const struct ttinfo *ttisp;
    1575             :     int         i;
    1576             :     int         j;
    1577        3135 :     const pg_time_t t = *timep;
    1578             : 
    1579        3135 :     sp = &tz->state;
    1580        3135 :     if (sp->timecnt == 0)
    1581             :     {
    1582             :         /* non-DST zone, use lowest-numbered standard type */
    1583          16 :         i = 0;
    1584          32 :         while (sp->ttis[i].tt_isdst)
    1585           0 :             if (++i >= sp->typecnt)
    1586             :             {
    1587           0 :                 i = 0;
    1588           0 :                 break;
    1589             :             }
    1590          16 :         ttisp = &sp->ttis[i];
    1591          16 :         *before_gmtoff = ttisp->tt_gmtoff;
    1592          16 :         *before_isdst = ttisp->tt_isdst;
    1593          16 :         return 0;
    1594             :     }
    1595        6238 :     if ((sp->goback && t < sp->ats[0]) ||
    1596        6014 :         (sp->goahead && t > sp->ats[sp->timecnt - 1]))
    1597             :     {
    1598             :         /* For values outside the transition table, extrapolate */
    1599           6 :         pg_time_t   newt = t;
    1600             :         pg_time_t   seconds;
    1601             :         pg_time_t   tcycles;
    1602             :         int64       icycles;
    1603             :         int         result;
    1604             : 
    1605           6 :         if (t < sp->ats[0])
    1606           0 :             seconds = sp->ats[0] - t;
    1607             :         else
    1608           6 :             seconds = t - sp->ats[sp->timecnt - 1];
    1609           6 :         --seconds;
    1610           6 :         tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
    1611           6 :         ++tcycles;
    1612           6 :         icycles = tcycles;
    1613           6 :         if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
    1614           0 :             return -1;
    1615           6 :         seconds = icycles;
    1616           6 :         seconds *= YEARSPERREPEAT;
    1617           6 :         seconds *= AVGSECSPERYEAR;
    1618           6 :         if (t < sp->ats[0])
    1619           0 :             newt += seconds;
    1620             :         else
    1621           6 :             newt -= seconds;
    1622          12 :         if (newt < sp->ats[0] ||
    1623           6 :             newt > sp->ats[sp->timecnt - 1])
    1624           0 :             return -1;          /* "cannot happen" */
    1625             : 
    1626           6 :         result = pg_next_dst_boundary(&newt, before_gmtoff,
    1627             :                                       before_isdst,
    1628             :                                       boundary,
    1629             :                                       after_gmtoff,
    1630             :                                       after_isdst,
    1631             :                                       tz);
    1632           6 :         if (t < sp->ats[0])
    1633           0 :             *boundary -= seconds;
    1634             :         else
    1635           6 :             *boundary += seconds;
    1636           6 :         return result;
    1637             :     }
    1638             : 
    1639        3113 :     if (t >= sp->ats[sp->timecnt - 1])
    1640             :     {
    1641             :         /* No known transition > t, so use last known segment's type */
    1642          28 :         i = sp->types[sp->timecnt - 1];
    1643          28 :         ttisp = &sp->ttis[i];
    1644          28 :         *before_gmtoff = ttisp->tt_gmtoff;
    1645          28 :         *before_isdst = ttisp->tt_isdst;
    1646          28 :         return 0;
    1647             :     }
    1648        3085 :     if (t < sp->ats[0])
    1649             :     {
    1650             :         /* For "before", use lowest-numbered standard type */
    1651          85 :         i = 0;
    1652         255 :         while (sp->ttis[i].tt_isdst)
    1653          85 :             if (++i >= sp->typecnt)
    1654             :             {
    1655           0 :                 i = 0;
    1656           0 :                 break;
    1657             :             }
    1658          85 :         ttisp = &sp->ttis[i];
    1659          85 :         *before_gmtoff = ttisp->tt_gmtoff;
    1660          85 :         *before_isdst = ttisp->tt_isdst;
    1661          85 :         *boundary = sp->ats[0];
    1662             :         /* And for "after", use the first segment's type */
    1663          85 :         i = sp->types[0];
    1664          85 :         ttisp = &sp->ttis[i];
    1665          85 :         *after_gmtoff = ttisp->tt_gmtoff;
    1666          85 :         *after_isdst = ttisp->tt_isdst;
    1667          85 :         return 1;
    1668             :     }
    1669             :     /* Else search to find the boundary following t */
    1670             :     {
    1671        3000 :         int         lo = 1;
    1672        3000 :         int         hi = sp->timecnt - 1;
    1673             : 
    1674       36480 :         while (lo < hi)
    1675             :         {
    1676       30480 :             int         mid = (lo + hi) >> 1;
    1677             : 
    1678       30480 :             if (t < sp->ats[mid])
    1679       21981 :                 hi = mid;
    1680             :             else
    1681        8499 :                 lo = mid + 1;
    1682             :         }
    1683        3000 :         i = lo;
    1684             :     }
    1685        3000 :     j = sp->types[i - 1];
    1686        3000 :     ttisp = &sp->ttis[j];
    1687        3000 :     *before_gmtoff = ttisp->tt_gmtoff;
    1688        3000 :     *before_isdst = ttisp->tt_isdst;
    1689        3000 :     *boundary = sp->ats[i];
    1690        3000 :     j = sp->types[i];
    1691        3000 :     ttisp = &sp->ttis[j];
    1692        3000 :     *after_gmtoff = ttisp->tt_gmtoff;
    1693        3000 :     *after_isdst = ttisp->tt_isdst;
    1694        3000 :     return 1;
    1695             : }
    1696             : 
    1697             : /*
    1698             :  * Identify a timezone abbreviation's meaning in the given zone
    1699             :  *
    1700             :  * Determine the GMT offset and DST flag associated with the abbreviation.
    1701             :  * This is generally used only when the abbreviation has actually changed
    1702             :  * meaning over time; therefore, we also take a UTC cutoff time, and return
    1703             :  * the meaning in use at or most recently before that time, or the meaning
    1704             :  * in first use after that time if the abbrev was never used before that.
    1705             :  *
    1706             :  * On success, returns true and sets *gmtoff and *isdst.  If the abbreviation
    1707             :  * was never used at all in this zone, returns false.
    1708             :  *
    1709             :  * Note: abbrev is matched case-sensitively; it should be all-upper-case.
    1710             :  */
    1711             : bool
    1712         194 : pg_interpret_timezone_abbrev(const char *abbrev,
    1713             :                              const pg_time_t *timep,
    1714             :                              long int *gmtoff,
    1715             :                              int *isdst,
    1716             :                              const pg_tz *tz)
    1717             : {
    1718             :     const struct state *sp;
    1719             :     const char *abbrs;
    1720             :     const struct ttinfo *ttisp;
    1721             :     int         abbrind;
    1722             :     int         cutoff;
    1723             :     int         i;
    1724         194 :     const pg_time_t t = *timep;
    1725             : 
    1726         194 :     sp = &tz->state;
    1727             : 
    1728             :     /*
    1729             :      * Locate the abbreviation in the zone's abbreviation list.  We assume
    1730             :      * there are not duplicates in the list.
    1731             :      */
    1732         194 :     abbrs = sp->chars;
    1733         194 :     abbrind = 0;
    1734        1250 :     while (abbrind < sp->charcnt)
    1735             :     {
    1736         907 :         if (strcmp(abbrev, abbrs + abbrind) == 0)
    1737          45 :             break;
    1738        4442 :         while (abbrs[abbrind] != '\0')
    1739        2718 :             abbrind++;
    1740         862 :         abbrind++;
    1741             :     }
    1742         194 :     if (abbrind >= sp->charcnt)
    1743         149 :         return false;           /* not there! */
    1744             : 
    1745             :     /*
    1746             :      * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
    1747             :      * (goback/goahead zones).  Finding the newest or oldest meaning of the
    1748             :      * abbreviation should get us what we want, since extrapolation would just
    1749             :      * be repeating the newest or oldest meanings.
    1750             :      *
    1751             :      * Use binary search to locate the first transition > cutoff time.
    1752             :      */
    1753             :     {
    1754          45 :         int         lo = 0;
    1755          45 :         int         hi = sp->timecnt;
    1756             : 
    1757         360 :         while (lo < hi)
    1758             :         {
    1759         270 :             int         mid = (lo + hi) >> 1;
    1760             : 
    1761         270 :             if (t < sp->ats[mid])
    1762          32 :                 hi = mid;
    1763             :             else
    1764         238 :                 lo = mid + 1;
    1765             :         }
    1766          45 :         cutoff = lo;
    1767             :     }
    1768             : 
    1769             :     /*
    1770             :      * Scan backwards to find the latest interval using the given abbrev
    1771             :      * before the cutoff time.
    1772             :      */
    1773          45 :     for (i = cutoff - 1; i >= 0; i--)
    1774             :     {
    1775          45 :         ttisp = &sp->ttis[sp->types[i]];
    1776          45 :         if (ttisp->tt_abbrind == abbrind)
    1777             :         {
    1778          45 :             *gmtoff = ttisp->tt_gmtoff;
    1779          45 :             *isdst = ttisp->tt_isdst;
    1780          45 :             return true;
    1781             :         }
    1782             :     }
    1783             : 
    1784             :     /*
    1785             :      * Not there, so scan forwards to find the first one after.
    1786             :      */
    1787           0 :     for (i = cutoff; i < sp->timecnt; i++)
    1788             :     {
    1789           0 :         ttisp = &sp->ttis[sp->types[i]];
    1790           0 :         if (ttisp->tt_abbrind == abbrind)
    1791             :         {
    1792           0 :             *gmtoff = ttisp->tt_gmtoff;
    1793           0 :             *isdst = ttisp->tt_isdst;
    1794           0 :             return true;
    1795             :         }
    1796             :     }
    1797             : 
    1798           0 :     return false;               /* hm, not actually used in any interval? */
    1799             : }
    1800             : 
    1801             : /*
    1802             :  * If the given timezone uses only one GMT offset, store that offset
    1803             :  * into *gmtoff and return true, else return false.
    1804             :  */
    1805             : bool
    1806           6 : pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
    1807             : {
    1808             :     /*
    1809             :      * The zone could have more than one ttinfo, if it's historically used
    1810             :      * more than one abbreviation.  We return true as long as they all have
    1811             :      * the same gmtoff.
    1812             :      */
    1813             :     const struct state *sp;
    1814             :     int         i;
    1815             : 
    1816           6 :     sp = &tz->state;
    1817           6 :     for (i = 1; i < sp->typecnt; i++)
    1818             :     {
    1819           6 :         if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
    1820           6 :             return false;
    1821             :     }
    1822           0 :     *gmtoff = sp->ttis[0].tt_gmtoff;
    1823           0 :     return true;
    1824             : }
    1825             : 
    1826             : /*
    1827             :  * Return the name of the current timezone
    1828             :  */
    1829             : const char *
    1830         839 : pg_get_timezone_name(pg_tz *tz)
    1831             : {
    1832         839 :     if (tz)
    1833         839 :         return tz->TZname;
    1834           0 :     return NULL;
    1835             : }
    1836             : 
    1837             : /*
    1838             :  * Check whether timezone is acceptable.
    1839             :  *
    1840             :  * What we are doing here is checking for leap-second-aware timekeeping.
    1841             :  * We need to reject such TZ settings because they'll wreak havoc with our
    1842             :  * date/time arithmetic.
    1843             :  */
    1844             : bool
    1845        1300 : pg_tz_acceptable(pg_tz *tz)
    1846             : {
    1847             :     struct pg_tm *tt;
    1848             :     pg_time_t   time2000;
    1849             : 
    1850             :     /*
    1851             :      * To detect leap-second timekeeping, run pg_localtime for what should be
    1852             :      * GMT midnight, 2000-01-01.  Insist that the tm_sec value be zero; any
    1853             :      * other result has to be due to leap seconds.
    1854             :      */
    1855        1300 :     time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
    1856        1300 :     tt = pg_localtime(&time2000, tz);
    1857        1300 :     if (!tt || tt->tm_sec != 0)
    1858           0 :         return false;
    1859             : 
    1860        1300 :     return true;
    1861             : }

Generated by: LCOV version 1.11