LCOV - code coverage report
Current view: top level - src/timezone - localtime.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17beta1 Lines: 635 807 78.7 %
Date: 2024-06-14 19:10:57 Functions: 31 31 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14