LCOV - code coverage report
Current view: top level - src/timezone - localtime.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 79.6 % 840 669
Test Date: 2026-05-18 22:16:41 Functions: 100.0 % 33 33
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              :     int_fast32_t 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, int_fast32_t 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, int_fast32_t j);
      89              : static int_fast64_t leapcorr(struct state const *sp, pg_time_t t);
      90              : static struct pg_tm *timesub(pg_time_t const *timep,
      91              :                              int_fast32_t 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        20437 : init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst, int desigidx)
     109              : {
     110        20437 :     s->tt_utoff = utoff;
     111        20437 :     s->tt_isdst = isdst;
     112        20437 :     s->tt_desigidx = desigidx;
     113        20437 :     s->tt_ttisstd = false;
     114        20437 :     s->tt_ttisut = false;
     115        20437 : }
     116              : 
     117              : static int_fast32_t
     118       211493 : detzcode(const char *const codep)
     119              : {
     120              :     int_fast32_t result;
     121              :     int         i;
     122       211493 :     int_fast32_t one = 1;
     123       211493 :     int_fast32_t halfmaxval = one << (32 - 2);
     124       211493 :     int_fast32_t maxval = halfmaxval - 1 + halfmaxval;
     125       211493 :     int_fast32_t minval = -1 - maxval;
     126              : 
     127       211493 :     result = codep[0] & 0x7f;
     128       845972 :     for (i = 1; i < 4; ++i)
     129       634479 :         result = (result << 8) | (codep[i] & 0xff);
     130              : 
     131       211493 :     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        35894 :         result -= !TWOS_COMPLEMENT(int_fast32_t) && result != 0;
     138        35894 :         result += minval;
     139              :     }
     140       211493 :     return result;
     141              : }
     142              : 
     143              : static int_fast64_t
     144       879910 : detzcode64(const char *const codep)
     145              : {
     146              :     uint_fast64_t result;
     147              :     int         i;
     148       879910 :     int_fast64_t one = 1;
     149       879910 :     int_fast64_t halfmaxval = one << (64 - 2);
     150       879910 :     int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
     151       879910 :     int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
     152              : 
     153       879910 :     result = codep[0] & 0x7f;
     154      7039280 :     for (i = 1; i < 8; ++i)
     155      6159370 :         result = (result << 8) | (codep[i] & 0xff);
     156              : 
     157       879910 :     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       338139 :         result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
     164       338139 :         result += minval;
     165              :     }
     166       879910 :     return result;
     167              : }
     168              : 
     169              : static bool
     170      7279739 : 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      7279739 :     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              : /*
     205              :  * Load tz data from the file named NAME into *SP.  Read extended
     206              :  * format if DOEXTEND.  Use *LSP for temporary storage.  Return 0 on
     207              :  * success, an errno value on failure.
     208              :  * PG: If "canonname" is not NULL, then on success the canonical spelling of
     209              :  * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
     210              :  */
     211              : static int
     212        12518 : tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend,
     213              :            union local_storage *lsp)
     214              : {
     215              :     int         i;
     216              :     int         fid;
     217              :     int         stored;
     218              :     ssize_t     nread;
     219        12518 :     union input_buffer *up = &lsp->u.u;
     220        12518 :     int         tzheadsize = sizeof(struct tzhead);
     221              : 
     222        12518 :     sp->goback = sp->goahead = false;
     223              : 
     224        12518 :     if (!name)
     225              :     {
     226            0 :         name = TZDEFAULT;
     227            0 :         if (!name)
     228            0 :             return EINVAL;
     229              :     }
     230              : 
     231        12518 :     if (name[0] == ':')
     232            0 :         ++name;
     233              : 
     234        12518 :     fid = pg_open_tzfile(name, canonname);
     235        12518 :     if (fid < 0)
     236          289 :         return ENOENT;          /* pg_open_tzfile may not set errno */
     237              : 
     238        12229 :     nread = read(fid, up->buf, sizeof up->buf);
     239        12229 :     if (nread < tzheadsize)
     240              :     {
     241            0 :         int         err = nread < 0 ? errno : EINVAL;
     242              : 
     243            0 :         close(fid);
     244            0 :         return err;
     245              :     }
     246        12229 :     if (close(fid) < 0)
     247            0 :         return errno;
     248        36687 :     for (stored = 4; stored <= 8; stored *= 2)
     249              :     {
     250        24458 :         int_fast32_t ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
     251        24458 :         int_fast32_t ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt);
     252        24458 :         int_fast64_t prevtr = 0;
     253        24458 :         int_fast32_t prevcorr = 0;
     254        24458 :         int_fast32_t leapcnt = detzcode(up->tzhead.tzh_leapcnt);
     255        24458 :         int_fast32_t timecnt = detzcode(up->tzhead.tzh_timecnt);
     256        24458 :         int_fast32_t typecnt = detzcode(up->tzhead.tzh_typecnt);
     257        24458 :         int_fast32_t charcnt = detzcode(up->tzhead.tzh_charcnt);
     258        24458 :         char const *p = up->buf + tzheadsize;
     259              : 
     260              :         /*
     261              :          * Although tzfile(5) currently requires typecnt to be nonzero,
     262              :          * support future formats that may allow zero typecnt in files that
     263              :          * have a TZ string and no transitions.
     264              :          */
     265        48916 :         if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
     266        24458 :               && 0 <= typecnt && typecnt < TZ_MAX_TYPES
     267        24458 :               && 0 <= timecnt && timecnt < TZ_MAX_TIMES
     268        24458 :               && 0 <= charcnt && charcnt < TZ_MAX_CHARS
     269        24458 :               && (ttisstdcnt == typecnt || ttisstdcnt == 0)
     270        24458 :               && (ttisutcnt == typecnt || ttisutcnt == 0)))
     271            0 :             return EINVAL;
     272        24458 :         if (nread
     273              :             < (tzheadsize        /* struct tzhead */
     274        24458 :                + timecnt * stored   /* ats */
     275        24458 :                + timecnt        /* types */
     276        24458 :                + typecnt * 6    /* ttinfos */
     277        24458 :                + charcnt        /* chars */
     278        24458 :                + leapcnt * (stored + 4) /* lsinfos */
     279        24458 :                + ttisstdcnt     /* ttisstds */
     280        24458 :                + ttisutcnt))    /* ttisuts */
     281            0 :             return EINVAL;
     282        24458 :         sp->leapcnt = leapcnt;
     283        24458 :         sp->timecnt = timecnt;
     284        24458 :         sp->typecnt = typecnt;
     285        24458 :         sp->charcnt = charcnt;
     286              : 
     287              :         /*
     288              :          * Read transitions, discarding those out of pg_time_t range. But
     289              :          * pretend the last transition before TIME_T_MIN occurred at
     290              :          * TIME_T_MIN.
     291              :          */
     292        24458 :         timecnt = 0;
     293       904368 :         for (i = 0; i < sp->timecnt; ++i)
     294              :         {
     295       879910 :             int_fast64_t at
     296       879910 :             = stored == 4 ? detzcode(p) : detzcode64(p);
     297              : 
     298       879910 :             sp->types[i] = at <= TIME_T_MAX;
     299       879910 :             if (sp->types[i])
     300              :             {
     301       879910 :                 pg_time_t   attime
     302              :                 = ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
     303              :                    ? TIME_T_MIN : at);
     304              : 
     305       879910 :                 if (timecnt && attime <= sp->ats[timecnt - 1])
     306              :                 {
     307            0 :                     if (attime < sp->ats[timecnt - 1])
     308            0 :                         return EINVAL;
     309            0 :                     sp->types[i - 1] = 0;
     310            0 :                     timecnt--;
     311              :                 }
     312       879910 :                 sp->ats[timecnt++] = attime;
     313              :             }
     314       879910 :             p += stored;
     315              :         }
     316              : 
     317        24458 :         timecnt = 0;
     318       904368 :         for (i = 0; i < sp->timecnt; ++i)
     319              :         {
     320       879910 :             unsigned char typ = *p++;
     321              : 
     322       879910 :             if (sp->typecnt <= typ)
     323            0 :                 return EINVAL;
     324       879910 :             if (sp->types[i])
     325       879910 :                 sp->types[timecnt++] = typ;
     326              :         }
     327        24458 :         sp->timecnt = timecnt;
     328        89203 :         for (i = 0; i < sp->typecnt; ++i)
     329              :         {
     330              :             struct ttinfo *ttisp;
     331              :             unsigned char isdst,
     332              :                         desigidx;
     333              : 
     334        64745 :             ttisp = &sp->ttis[i];
     335        64745 :             ttisp->tt_utoff = detzcode(p);
     336        64745 :             p += 4;
     337        64745 :             isdst = *p++;
     338        64745 :             if (!(isdst < 2))
     339            0 :                 return EINVAL;
     340        64745 :             ttisp->tt_isdst = isdst;
     341        64745 :             desigidx = *p++;
     342        64745 :             if (!(desigidx < sp->charcnt))
     343            0 :                 return EINVAL;
     344        64745 :             ttisp->tt_desigidx = desigidx;
     345              :         }
     346       243068 :         for (i = 0; i < sp->charcnt; ++i)
     347       218610 :             sp->chars[i] = *p++;
     348        24458 :         sp->chars[i] = '\0'; /* ensure '\0' at end */
     349              : 
     350              :         /* Read leap seconds, discarding those out of pg_time_t range.  */
     351        24458 :         leapcnt = 0;
     352        24458 :         for (i = 0; i < sp->leapcnt; ++i)
     353              :         {
     354            0 :             int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
     355            0 :             int_fast32_t corr = detzcode(p + stored);
     356              : 
     357            0 :             p += stored + 4;
     358              :             /* Leap seconds cannot occur before the Epoch.  */
     359            0 :             if (tr < 0)
     360            0 :                 return EINVAL;
     361              :             if (tr <= TIME_T_MAX)
     362              :             {
     363              :                 /*
     364              :                  * Leap seconds cannot occur more than once per UTC month, and
     365              :                  * UTC months are at least 28 days long (minus 1 second for a
     366              :                  * negative leap second).  Each leap second's correction must
     367              :                  * differ from the previous one's by 1 second.
     368              :                  */
     369            0 :                 if (tr - prevtr < 28 * SECSPERDAY - 1
     370            0 :                     || (corr != prevcorr - 1 && corr != prevcorr + 1))
     371            0 :                     return EINVAL;
     372            0 :                 sp->lsis[leapcnt].ls_trans = prevtr = tr;
     373            0 :                 sp->lsis[leapcnt].ls_corr = prevcorr = corr;
     374            0 :                 leapcnt++;
     375              :             }
     376              :         }
     377        24458 :         sp->leapcnt = leapcnt;
     378              : 
     379        89203 :         for (i = 0; i < sp->typecnt; ++i)
     380              :         {
     381              :             struct ttinfo *ttisp;
     382              : 
     383        64745 :             ttisp = &sp->ttis[i];
     384        64745 :             if (ttisstdcnt == 0)
     385        64745 :                 ttisp->tt_ttisstd = false;
     386              :             else
     387              :             {
     388            0 :                 if (*p != true && *p != false)
     389            0 :                     return EINVAL;
     390            0 :                 ttisp->tt_ttisstd = *p++;
     391              :             }
     392              :         }
     393        89203 :         for (i = 0; i < sp->typecnt; ++i)
     394              :         {
     395              :             struct ttinfo *ttisp;
     396              : 
     397        64745 :             ttisp = &sp->ttis[i];
     398        64745 :             if (ttisutcnt == 0)
     399        64745 :                 ttisp->tt_ttisut = false;
     400              :             else
     401              :             {
     402            0 :                 if (*p != true && *p != false)
     403            0 :                     return EINVAL;
     404            0 :                 ttisp->tt_ttisut = *p++;
     405              :             }
     406              :         }
     407              : 
     408              :         /*
     409              :          * If this is an old file, we're done.
     410              :          */
     411        24458 :         if (up->tzhead.tzh_version[0] == '\0')
     412            0 :             break;
     413        24458 :         nread -= p - up->buf;
     414        24458 :         memmove(up->buf, p, nread);
     415              :     }
     416        12229 :     if (doextend && nread > 2 &&
     417        12229 :         up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
     418        12229 :         sp->typecnt + 2 <= TZ_MAX_TYPES)
     419              :     {
     420        12229 :         struct state *ts = &lsp->u.st;
     421              : 
     422        12229 :         up->buf[nread - 1] = '\0';
     423        12229 :         if (tzparse(&up->buf[1], ts, false))
     424              :         {
     425              : 
     426              :             /*
     427              :              * Attempt to reuse existing abbreviations. Without this,
     428              :              * America/Anchorage would be right on the edge after 2037 when
     429              :              * TZ_MAX_CHARS is 50, as sp->charcnt equals 40 (for LMT AST AWT
     430              :              * APT AHST AHDT YST AKDT AKST) and ts->charcnt equals 10 (for
     431              :              * AKST AKDT).  Reusing means sp->charcnt can stay 40 in this
     432              :              * example.
     433              :              */
     434        12229 :             int         gotabbr = 0;
     435        12229 :             int         charcnt = sp->charcnt;
     436              : 
     437        31141 :             for (i = 0; i < ts->typecnt; i++)
     438              :             {
     439        18912 :                 char       *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
     440              :                 int         j;
     441              : 
     442       157447 :                 for (j = 0; j < charcnt; j++)
     443       157407 :                     if (strcmp(sp->chars + j, tsabbr) == 0)
     444              :                     {
     445        18872 :                         ts->ttis[i].tt_desigidx = j;
     446        18872 :                         gotabbr++;
     447        18872 :                         break;
     448              :                     }
     449        18912 :                 if (!(j < charcnt))
     450              :                 {
     451           40 :                     int         tsabbrlen = strlen(tsabbr);
     452              : 
     453           40 :                     if (j + tsabbrlen < TZ_MAX_CHARS)
     454              :                     {
     455           40 :                         strcpy(sp->chars + j, tsabbr);
     456           40 :                         charcnt = j + tsabbrlen + 1;
     457           40 :                         ts->ttis[i].tt_desigidx = j;
     458           40 :                         gotabbr++;
     459              :                     }
     460              :                 }
     461              :             }
     462        12229 :             if (gotabbr == ts->typecnt)
     463              :             {
     464        12229 :                 sp->charcnt = charcnt;
     465              : 
     466              :                 /*
     467              :                  * Ignore any trailing, no-op transitions generated by zic as
     468              :                  * they don't help here and can run afoul of bugs in zic 2016j
     469              :                  * or earlier.
     470              :                  */
     471        12229 :                 while (1 < sp->timecnt
     472        12249 :                        && (sp->types[sp->timecnt - 1]
     473         9974 :                            == sp->types[sp->timecnt - 2]))
     474           20 :                     sp->timecnt--;
     475              : 
     476      3181046 :                 for (i = 0; i < ts->timecnt; i++)
     477      3175500 :                     if (sp->timecnt == 0
     478      6351000 :                         || (sp->ats[sp->timecnt - 1]
     479      3175500 :                             < ts->ats[i] + leapcorr(sp, ts->ats[i])))
     480              :                         break;
     481        12229 :                 while (i < ts->timecnt
     482     10209412 :                        && sp->timecnt < TZ_MAX_TIMES)
     483              :                 {
     484     10197183 :                     sp->ats[sp->timecnt]
     485     10197183 :                         = ts->ats[i] + leapcorr(sp, ts->ats[i]);
     486     10197183 :                     sp->types[sp->timecnt] = (sp->typecnt
     487     10197183 :                                               + ts->types[i]);
     488     10197183 :                     sp->timecnt++;
     489     10197183 :                     i++;
     490              :                 }
     491        31141 :                 for (i = 0; i < ts->typecnt; i++)
     492        18912 :                     sp->ttis[sp->typecnt++] = ts->ttis[i];
     493              :             }
     494              :         }
     495              :     }
     496        12229 :     if (sp->typecnt == 0)
     497            0 :         return EINVAL;
     498        12229 :     if (sp->timecnt > 1)
     499              :     {
     500     11076623 :         for (i = 1; i < sp->timecnt; ++i)
     501     15642792 :             if (typesequiv(sp, sp->types[i], sp->types[0]) &&
     502      4576123 :                 differ_by_repeat(sp->ats[i], sp->ats[0]))
     503              :             {
     504            0 :                 sp->goback = true;
     505            0 :                 break;
     506              :             }
     507      5456131 :         for (i = sp->timecnt - 2; i >= 0; --i)
     508      5452860 :             if (typesequiv(sp, sp->types[sp->timecnt - 1],
     509      8156476 :                            sp->types[i]) &&
     510      2703616 :                 differ_by_repeat(sp->ats[sp->timecnt - 1],
     511              :                                  sp->ats[i]))
     512              :             {
     513         6683 :                 sp->goahead = true;
     514         6683 :                 break;
     515              :             }
     516              :     }
     517              : 
     518              :     /*
     519              :      * Infer sp->defaulttype from the data.  Although this default type is
     520              :      * always zero for data from recent tzdb releases, things are trickier for
     521              :      * data from tzdb 2018e or earlier.
     522              :      *
     523              :      * The first set of heuristics work around bugs in 32-bit data generated
     524              :      * by tzdb 2013c or earlier.  The workaround is for zones like
     525              :      * Australia/Macquarie where timestamps before the first transition have a
     526              :      * time type that is not the earliest standard-time type.  See:
     527              :      * https://mm.icann.org/pipermail/tz/2013-May/019368.html
     528              :      */
     529              : 
     530              :     /*
     531              :      * If type 0 is unused in transitions, it's the type to use for early
     532              :      * times.
     533              :      */
     534     11022168 :     for (i = 0; i < sp->timecnt; ++i)
     535     11010103 :         if (sp->types[i] == 0)
     536          164 :             break;
     537        12229 :     i = i < sp->timecnt ? -1 : 0;
     538              : 
     539              :     /*
     540              :      * Absent the above, if there are transition times and the first
     541              :      * transition is to a daylight time find the standard type less than and
     542              :      * closest to the type of the first transition.
     543              :      */
     544        12229 :     if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst)
     545              :     {
     546            0 :         i = sp->types[0];
     547            0 :         while (--i >= 0)
     548            0 :             if (!sp->ttis[i].tt_isdst)
     549            0 :                 break;
     550              :     }
     551              : 
     552              :     /*
     553              :      * The next heuristics are for data generated by tzdb 2018e or earlier,
     554              :      * for zones like EST5EDT where the first transition is to DST.
     555              :      */
     556              : 
     557              :     /*
     558              :      * If no result yet, find the first standard type. If there is none, punt
     559              :      * to type zero.
     560              :      */
     561        12229 :     if (i < 0)
     562              :     {
     563          164 :         i = 0;
     564          164 :         while (sp->ttis[i].tt_isdst)
     565            0 :             if (++i >= sp->typecnt)
     566              :             {
     567            0 :                 i = 0;
     568            0 :                 break;
     569              :             }
     570              :     }
     571              : 
     572              :     /*
     573              :      * A simple 'sp->defaulttype = 0;' would suffice here if we didn't have to
     574              :      * worry about 2018e-or-earlier data.  Even simpler would be to remove the
     575              :      * defaulttype member and just use 0 in its place.
     576              :      */
     577        12229 :     sp->defaulttype = i;
     578              : 
     579        12229 :     return 0;
     580              : }
     581              : 
     582              : /*
     583              :  * Load tz data from the file named NAME into *SP.  Read extended
     584              :  * format if DOEXTEND.  Return 0 on success, an errno value on failure.
     585              :  * PG: If "canonname" is not NULL, then on success the canonical spelling of
     586              :  * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
     587              :  */
     588              : int
     589        12518 : tzload(char const *name, char *canonname, struct state *sp, bool doextend)
     590              : {
     591        12518 :     union local_storage *lsp = malloc(sizeof *lsp);
     592              : 
     593        12518 :     if (!lsp)
     594            0 :         return errno;
     595              :     else
     596              :     {
     597        12518 :         int         err = tzloadbody(name, canonname, sp, doextend, lsp);
     598              : 
     599        12518 :         free(lsp);
     600        12518 :         return err;
     601              :     }
     602              : }
     603              : 
     604              : static bool
     605     16519529 : typesequiv(const struct state *sp, int a, int b)
     606              : {
     607              :     bool        result;
     608              : 
     609     16519529 :     if (sp == NULL ||
     610     16519529 :         a < 0 || a >= sp->typecnt ||
     611     16519529 :         b < 0 || b >= sp->typecnt)
     612            0 :         result = false;
     613              :     else
     614              :     {
     615     16519529 :         const struct ttinfo *ap = &sp->ttis[a];
     616     16519529 :         const struct ttinfo *bp = &sp->ttis[b];
     617              : 
     618     16519529 :         result = (ap->tt_utoff == bp->tt_utoff
     619      7349371 :                   && ap->tt_isdst == bp->tt_isdst
     620      7297009 :                   && ap->tt_ttisstd == bp->tt_ttisstd
     621      7297009 :                   && ap->tt_ttisut == bp->tt_ttisut
     622     23868900 :                   && (strcmp(&sp->chars[ap->tt_desigidx],
     623      7297009 :                              &sp->chars[bp->tt_desigidx])
     624              :                       == 0));
     625              :     }
     626     16519529 :     return result;
     627              : }
     628              : 
     629              : static const int mon_lengths[2][MONSPERYEAR] = {
     630              :     {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
     631              :     {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
     632              : };
     633              : 
     634              : static const int year_lengths[2] = {
     635              :     DAYSPERNYEAR, DAYSPERLYEAR
     636              : };
     637              : 
     638              : /*
     639              :  * Given a pointer into a timezone string, scan until a character that is not
     640              :  * a valid character in a time zone abbreviation is found.
     641              :  * Return a pointer to that character.
     642              :  */
     643              : 
     644              : static const char *
     645        16543 : getzname(const char *strp)
     646              : {
     647              :     char        c;
     648              : 
     649        67979 :     while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
     650              :            c != '+')
     651        51436 :         ++strp;
     652        16543 :     return strp;
     653              : }
     654              : 
     655              : /*
     656              :  * Given a pointer into an extended timezone string, scan until the ending
     657              :  * delimiter of the time zone abbreviation is located.
     658              :  * Return a pointer to the delimiter.
     659              :  *
     660              :  * As with getzname above, the legal character set is actually quite
     661              :  * restricted, with other characters producing undefined results.
     662              :  * We don't do any checking here; checking is done later in common-case code.
     663              :  */
     664              : 
     665              : static const char *
     666         2671 : getqzname(const char *strp, const int delim)
     667              : {
     668              :     int         c;
     669              : 
     670        11076 :     while ((c = *strp) != '\0' && c != delim)
     671         8405 :         ++strp;
     672         2671 :     return strp;
     673              : }
     674              : 
     675              : /*
     676              :  * Given a pointer into a timezone string, extract a number from that string.
     677              :  * Check that the number is within a specified range; if it is not, return
     678              :  * NULL.
     679              :  * Otherwise, return a pointer to the first character not part of the number.
     680              :  */
     681              : 
     682              : static const char *
     683        54566 : getnum(const char *strp, int *const nump, const int min, const int max)
     684              : {
     685              :     char        c;
     686              :     int         num;
     687              : 
     688        54566 :     if (strp == NULL || !is_digit(c = *strp))
     689            0 :         return NULL;
     690        54566 :     num = 0;
     691              :     do
     692              :     {
     693        62697 :         num = num * 10 + (c - '0');
     694        62697 :         if (num > max)
     695            0 :             return NULL;        /* illegal value */
     696        62697 :         c = *++strp;
     697        62697 :     } while (is_digit(c));
     698        54566 :     if (num < min)
     699            0 :         return NULL;            /* illegal value */
     700        54566 :     *nump = num;
     701        54566 :     return strp;
     702              : }
     703              : 
     704              : /*
     705              :  * Given a pointer into a timezone string, extract a number of seconds,
     706              :  * in hh[:mm[:ss]] form, from the string.
     707              :  * If any error occurs, return NULL.
     708              :  * Otherwise, return a pointer to the first character not part of the number
     709              :  * of seconds.
     710              :  */
     711              : 
     712              : static const char *
     713        14024 : getsecs(const char *strp, int_fast32_t *const secsp)
     714              : {
     715              :     int         num;
     716              : 
     717              :     /*
     718              :      * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-Posix rules like
     719              :      * "M10.4.6/26", which does not conform to Posix, but which specifies the
     720              :      * equivalent of "02:00 on the first Sunday on or after 23 Oct".
     721              :      */
     722        14024 :     strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
     723        14024 :     if (strp == NULL)
     724            0 :         return NULL;
     725        14024 :     *secsp = num * (int_fast32_t) SECSPERHOUR;
     726        14024 :     if (*strp == ':')
     727              :     {
     728          366 :         ++strp;
     729          366 :         strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
     730          366 :         if (strp == NULL)
     731            0 :             return NULL;
     732          366 :         *secsp += num * SECSPERMIN;
     733          366 :         if (*strp == ':')
     734              :         {
     735            0 :             ++strp;
     736              :             /* 'SECSPERMIN' allows for leap seconds.  */
     737            0 :             strp = getnum(strp, &num, 0, SECSPERMIN);
     738            0 :             if (strp == NULL)
     739            0 :                 return NULL;
     740            0 :             *secsp += num;
     741              :         }
     742              :     }
     743        14024 :     return strp;
     744              : }
     745              : 
     746              : /*
     747              :  * Given a pointer into a timezone string, extract an offset, in
     748              :  * [+-]hh[:mm[:ss]] form, from the string.
     749              :  * If any error occurs, return NULL.
     750              :  * Otherwise, return a pointer to the first character not part of the time.
     751              :  */
     752              : 
     753              : static const char *
     754        14024 : getoffset(const char *strp, int_fast32_t *const offsetp)
     755              : {
     756        14024 :     bool        neg = false;
     757              : 
     758        14024 :     if (*strp == '-')
     759              :     {
     760         3387 :         neg = true;
     761         3387 :         ++strp;
     762              :     }
     763        10637 :     else if (*strp == '+')
     764           85 :         ++strp;
     765        14024 :     strp = getsecs(strp, offsetp);
     766        14024 :     if (strp == NULL)
     767            0 :         return NULL;            /* illegal time */
     768        14024 :     if (neg)
     769         3387 :         *offsetp = -*offsetp;
     770        14024 :     return strp;
     771              : }
     772              : 
     773              : /*
     774              :  * Given a pointer into a timezone string, extract a rule in the form
     775              :  * date[/time]. See POSIX section 8 for the format of "date" and "time".
     776              :  * If a valid rule is not found, return NULL.
     777              :  * Otherwise, return a pointer to the first character not part of the rule.
     778              :  */
     779              : 
     780              : static const char *
     781        13392 : getrule(const char *strp, struct rule *const rulep)
     782              : {
     783        13392 :     if (*strp == 'J')
     784              :     {
     785              :         /*
     786              :          * Julian day.
     787              :          */
     788            0 :         rulep->r_type = JULIAN_DAY;
     789            0 :         ++strp;
     790            0 :         strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
     791              :     }
     792        13392 :     else if (*strp == 'M')
     793              :     {
     794              :         /*
     795              :          * Month, week, day.
     796              :          */
     797        13392 :         rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
     798        13392 :         ++strp;
     799        13392 :         strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
     800        13392 :         if (strp == NULL)
     801            0 :             return NULL;
     802        13392 :         if (*strp++ != '.')
     803            0 :             return NULL;
     804        13392 :         strp = getnum(strp, &rulep->r_week, 1, 5);
     805        13392 :         if (strp == NULL)
     806            0 :             return NULL;
     807        13392 :         if (*strp++ != '.')
     808            0 :             return NULL;
     809        13392 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
     810              :     }
     811            0 :     else if (is_digit(*strp))
     812              :     {
     813              :         /*
     814              :          * Day of year.
     815              :          */
     816            0 :         rulep->r_type = DAY_OF_YEAR;
     817            0 :         strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
     818              :     }
     819              :     else
     820            0 :         return NULL;            /* invalid format */
     821        13392 :     if (strp == NULL)
     822            0 :         return NULL;
     823        13392 :     if (*strp == '/')
     824              :     {
     825              :         /*
     826              :          * Time specified.
     827              :          */
     828         1520 :         ++strp;
     829         1520 :         strp = getoffset(strp, &rulep->r_time);
     830              :     }
     831              :     else
     832        11872 :         rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
     833        13392 :     return strp;
     834              : }
     835              : 
     836              : /*
     837              :  * Given a year, a rule, and the offset from UT at the time that rule takes
     838              :  * effect, calculate the year-relative time that rule takes effect.
     839              :  */
     840              : 
     841              : static int_fast32_t
     842     13405392 : transtime(const int year, const struct rule *const rulep,
     843              :           const int_fast32_t offset)
     844              : {
     845              :     bool        leapyear;
     846              :     int_fast32_t value;
     847              :     int         i;
     848              :     int         d,
     849              :                 m1,
     850              :                 yy0,
     851              :                 yy1,
     852              :                 yy2,
     853              :                 dow;
     854              : 
     855     13405392 :     INITIALIZE(value);
     856     13405392 :     leapyear = isleap(year);
     857     13405392 :     switch (rulep->r_type)
     858              :     {
     859              : 
     860            0 :         case JULIAN_DAY:
     861              : 
     862              :             /*
     863              :              * Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
     864              :              * years. In non-leap years, or if the day number is 59 or less,
     865              :              * just add SECSPERDAY times the day number-1 to the time of
     866              :              * January 1, midnight, to get the day.
     867              :              */
     868            0 :             value = (rulep->r_day - 1) * SECSPERDAY;
     869            0 :             if (leapyear && rulep->r_day >= 60)
     870            0 :                 value += SECSPERDAY;
     871            0 :             break;
     872              : 
     873            0 :         case DAY_OF_YEAR:
     874              : 
     875              :             /*
     876              :              * n - day of year. Just add SECSPERDAY times the day number to
     877              :              * the time of January 1, midnight, to get the day.
     878              :              */
     879            0 :             value = rulep->r_day * SECSPERDAY;
     880            0 :             break;
     881              : 
     882     13405392 :         case MONTH_NTH_DAY_OF_WEEK:
     883              : 
     884              :             /*
     885              :              * Mm.n.d - nth "dth day" of month m.
     886              :              */
     887              : 
     888              :             /*
     889              :              * Use Zeller's Congruence to get day-of-week of first day of
     890              :              * month.
     891              :              */
     892     13405392 :             m1 = (rulep->r_mon + 9) % 12 + 1;
     893     13405392 :             yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
     894     13405392 :             yy1 = yy0 / 100;
     895     13405392 :             yy2 = yy0 % 100;
     896     13405392 :             dow = ((26 * m1 - 2) / 10 +
     897     13405392 :                    1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
     898     13405392 :             if (dow < 0)
     899      2520009 :                 dow += DAYSPERWEEK;
     900              : 
     901              :             /*
     902              :              * "dow" is the day-of-week of the first day of the month. Get the
     903              :              * day-of-month (zero-origin) of the first "dow" day of the month.
     904              :              */
     905     13405392 :             d = rulep->r_day - dow;
     906     13405392 :             if (d < 0)
     907     11308901 :                 d += DAYSPERWEEK;
     908     25068337 :             for (i = 1; i < rulep->r_week; ++i)
     909              :             {
     910     12662650 :                 if (d + DAYSPERWEEK >=
     911     12662650 :                     mon_lengths[leapyear][rulep->r_mon - 1])
     912       999705 :                     break;
     913     11662945 :                 d += DAYSPERWEEK;
     914              :             }
     915              : 
     916              :             /*
     917              :              * "d" is the day-of-month (zero-origin) of the day we want.
     918              :              */
     919     13405392 :             value = d * SECSPERDAY;
     920     92883791 :             for (i = 0; i < rulep->r_mon - 1; ++i)
     921     79478399 :                 value += mon_lengths[leapyear][i] * SECSPERDAY;
     922     13405392 :             break;
     923              :     }
     924              : 
     925              :     /*
     926              :      * "value" is the year-relative time of 00:00:00 UT on the day in
     927              :      * question. To get the year-relative time of the specified local time on
     928              :      * that day, add the transition time and the current offset from UT.
     929              :      */
     930     13405392 :     return value + rulep->r_time + offset;
     931              : }
     932              : 
     933              : /*
     934              :  * Given a POSIX section 8-style TZ string, fill in the rule tables as
     935              :  * appropriate.
     936              :  * Returns true on success, false on failure.
     937              :  */
     938              : bool
     939        13809 : tzparse(const char *name, struct state *sp, bool lastditch)
     940              : {
     941              :     const char *stdname;
     942        13809 :     const char *dstname = NULL;
     943              :     size_t      stdlen;
     944              :     size_t      dstlen;
     945              :     size_t      charcnt;
     946              :     int_fast32_t stdoffset;
     947              :     int_fast32_t dstoffset;
     948              :     char       *cp;
     949              :     bool        load_ok;
     950              : 
     951        13809 :     stdname = name;
     952        13809 :     if (lastditch)
     953              :     {
     954              :         /* Unlike IANA, don't assume name is exactly "GMT" */
     955         1291 :         stdlen = strlen(name);  /* length of standard zone name */
     956         1291 :         name += stdlen;
     957         1291 :         stdoffset = 0;
     958              :     }
     959              :     else
     960              :     {
     961        12518 :         if (*name == '<')
     962              :         {
     963         2509 :             name++;
     964         2509 :             stdname = name;
     965         2509 :             name = getqzname(name, '>');
     966         2509 :             if (*name != '>')
     967            0 :                 return false;
     968         2509 :             stdlen = name - stdname;
     969         2509 :             name++;
     970              :         }
     971              :         else
     972              :         {
     973        10009 :             name = getzname(name);
     974        10009 :             stdlen = name - stdname;
     975              :         }
     976        12518 :         if (*name == '\0')      /* we allow empty STD abbrev, unlike IANA */
     977           68 :             return false;
     978        12450 :         name = getoffset(name, &stdoffset);
     979        12450 :         if (name == NULL)
     980            0 :             return false;
     981              :     }
     982        13741 :     charcnt = stdlen + 1;
     983        13741 :     if (sizeof sp->chars < charcnt)
     984            0 :         return false;
     985              : 
     986              :     /*
     987              :      * The IANA code always tries to tzload(TZDEFRULES) here.  We do not want
     988              :      * to do that; it would be bad news in the lastditch case, where we can't
     989              :      * assume pg_open_tzfile() is sane yet.  Moreover, if we did load it and
     990              :      * it contains leap-second-dependent info, that would cause problems too.
     991              :      * Finally, IANA has deprecated the TZDEFRULES feature, so it presumably
     992              :      * will die at some point.  Desupporting it now seems like good
     993              :      * future-proofing.
     994              :      */
     995        13741 :     load_ok = false;
     996        13741 :     sp->goback = sp->goahead = false; /* simulate failed tzload() */
     997        13741 :     sp->leapcnt = 0;         /* intentionally assume no leap seconds */
     998              : 
     999        13741 :     if (*name != '\0')
    1000              :     {
    1001         6696 :         if (*name == '<')
    1002              :         {
    1003          162 :             dstname = ++name;
    1004          162 :             name = getqzname(name, '>');
    1005          162 :             if (*name != '>')
    1006            0 :                 return false;
    1007          162 :             dstlen = name - dstname;
    1008          162 :             name++;
    1009              :         }
    1010              :         else
    1011              :         {
    1012         6534 :             dstname = name;
    1013         6534 :             name = getzname(name);
    1014         6534 :             dstlen = name - dstname;    /* length of DST abbr. */
    1015              :         }
    1016         6696 :         if (!dstlen)
    1017            0 :             return false;
    1018         6696 :         charcnt += dstlen + 1;
    1019         6696 :         if (sizeof sp->chars < charcnt)
    1020            0 :             return false;
    1021         6696 :         if (*name != '\0' && *name != ',' && *name != ';')
    1022              :         {
    1023           54 :             name = getoffset(name, &dstoffset);
    1024           54 :             if (name == NULL)
    1025            0 :                 return false;
    1026              :         }
    1027              :         else
    1028         6642 :             dstoffset = stdoffset - SECSPERHOUR;
    1029         6696 :         if (*name == '\0' && !load_ok)
    1030            4 :             name = TZDEFRULESTRING;
    1031         6696 :         if (*name == ',' || *name == ';')
    1032         6696 :         {
    1033              :             struct rule start;
    1034              :             struct rule end;
    1035              :             int         year;
    1036              :             int         yearlim;
    1037              :             int         timecnt;
    1038              :             pg_time_t   janfirst;
    1039         6696 :             int_fast32_t janoffset = 0;
    1040              :             int         yearbeg;
    1041              : 
    1042         6696 :             ++name;
    1043         6696 :             if ((name = getrule(name, &start)) == NULL)
    1044            0 :                 return false;
    1045         6696 :             if (*name++ != ',')
    1046            0 :                 return false;
    1047         6696 :             if ((name = getrule(name, &end)) == NULL)
    1048            0 :                 return false;
    1049         6696 :             if (*name != '\0')
    1050            0 :                 return false;
    1051         6696 :             sp->typecnt = 2; /* standard time and DST */
    1052              : 
    1053              :             /*
    1054              :              * Two transitions per year, from EPOCH_YEAR forward.
    1055              :              */
    1056         6696 :             init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
    1057         6696 :             init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
    1058         6696 :             sp->defaulttype = 0;
    1059         6696 :             timecnt = 0;
    1060         6696 :             janfirst = 0;
    1061         6696 :             yearbeg = EPOCH_YEAR;
    1062              : 
    1063              :             do
    1064              :             {
    1065      1339200 :                 int_fast32_t yearsecs
    1066      1339200 :                 = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
    1067              : 
    1068      1339200 :                 yearbeg--;
    1069      1339200 :                 if (increment_overflow_time(&janfirst, -yearsecs))
    1070              :                 {
    1071            0 :                     janoffset = -yearsecs;
    1072            0 :                     break;
    1073              :                 }
    1074      1339200 :             } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
    1075              : 
    1076         6696 :             yearlim = yearbeg + YEARSPERREPEAT + 1;
    1077      6702696 :             for (year = yearbeg; year < yearlim; year++)
    1078              :             {
    1079              :                 int_fast32_t
    1080      6702696 :                             starttime = transtime(year, &start, stdoffset),
    1081      6702696 :                             endtime = transtime(year, &end, dstoffset);
    1082              :                 int_fast32_t
    1083      6702696 :                             yearsecs = (year_lengths[isleap(year)]
    1084              :                                         * SECSPERDAY);
    1085      6702696 :                 bool        reversed = endtime < starttime;
    1086              : 
    1087      6702696 :                 if (reversed)
    1088              :                 {
    1089       306306 :                     int_fast32_t swap = starttime;
    1090              : 
    1091       306306 :                     starttime = endtime;
    1092       306306 :                     endtime = swap;
    1093              :                 }
    1094      6702696 :                 if (reversed
    1095      6396390 :                     || (starttime < endtime
    1096      6396390 :                         && (endtime - starttime
    1097              :                             < (yearsecs
    1098      6396390 :                                + (stdoffset - dstoffset)))))
    1099              :                 {
    1100      6702696 :                     if (TZ_MAX_TIMES - 2 < timecnt)
    1101         6696 :                         break;
    1102      6696000 :                     sp->ats[timecnt] = janfirst;
    1103      6696000 :                     if (!increment_overflow_time
    1104              :                         (&sp->ats[timecnt],
    1105              :                          janoffset + starttime))
    1106      6696000 :                         sp->types[timecnt++] = !reversed;
    1107      6696000 :                     sp->ats[timecnt] = janfirst;
    1108      6696000 :                     if (!increment_overflow_time
    1109              :                         (&sp->ats[timecnt],
    1110              :                          janoffset + endtime))
    1111              :                     {
    1112      6696000 :                         sp->types[timecnt++] = reversed;
    1113      6696000 :                         yearlim = year + YEARSPERREPEAT + 1;
    1114              :                     }
    1115              :                 }
    1116      6696000 :                 if (increment_overflow_time
    1117              :                     (&janfirst, janoffset + yearsecs))
    1118            0 :                     break;
    1119      6696000 :                 janoffset = 0;
    1120              :             }
    1121         6696 :             sp->timecnt = timecnt;
    1122         6696 :             if (!timecnt)
    1123              :             {
    1124            0 :                 sp->ttis[0] = sp->ttis[1];
    1125            0 :                 sp->typecnt = 1; /* Perpetual DST.  */
    1126              :             }
    1127         6696 :             else if (YEARSPERREPEAT < year - yearbeg)
    1128         6696 :                 sp->goback = sp->goahead = true;
    1129              :         }
    1130              :         else
    1131              :         {
    1132              :             int_fast32_t theirstdoffset;
    1133              :             int_fast32_t theirdstoffset;
    1134              :             int_fast32_t theiroffset;
    1135              :             bool        isdst;
    1136              :             int         i;
    1137              :             int         j;
    1138              : 
    1139            0 :             if (*name != '\0')
    1140            0 :                 return false;
    1141              : 
    1142              :             /*
    1143              :              * Initial values of theirstdoffset and theirdstoffset.
    1144              :              */
    1145            0 :             theirstdoffset = 0;
    1146            0 :             for (i = 0; i < sp->timecnt; ++i)
    1147              :             {
    1148            0 :                 j = sp->types[i];
    1149            0 :                 if (!sp->ttis[j].tt_isdst)
    1150              :                 {
    1151            0 :                     theirstdoffset =
    1152            0 :                         -sp->ttis[j].tt_utoff;
    1153            0 :                     break;
    1154              :                 }
    1155              :             }
    1156            0 :             theirdstoffset = 0;
    1157            0 :             for (i = 0; i < sp->timecnt; ++i)
    1158              :             {
    1159            0 :                 j = sp->types[i];
    1160            0 :                 if (sp->ttis[j].tt_isdst)
    1161              :                 {
    1162            0 :                     theirdstoffset =
    1163            0 :                         -sp->ttis[j].tt_utoff;
    1164            0 :                     break;
    1165              :                 }
    1166              :             }
    1167              : 
    1168              :             /*
    1169              :              * Initially we're assumed to be in standard time.
    1170              :              */
    1171            0 :             isdst = false;
    1172            0 :             theiroffset = theirstdoffset;
    1173              : 
    1174              :             /*
    1175              :              * Now juggle transition times and types tracking offsets as you
    1176              :              * do.
    1177              :              */
    1178            0 :             for (i = 0; i < sp->timecnt; ++i)
    1179              :             {
    1180            0 :                 j = sp->types[i];
    1181            0 :                 sp->types[i] = sp->ttis[j].tt_isdst;
    1182            0 :                 if (sp->ttis[j].tt_ttisut)
    1183              :                 {
    1184              :                     /* No adjustment to transition time */
    1185              :                 }
    1186              :                 else
    1187              :                 {
    1188              :                     /*
    1189              :                      * If daylight saving time is in effect, and the
    1190              :                      * transition time was not specified as standard time, add
    1191              :                      * the daylight saving time offset to the transition time;
    1192              :                      * otherwise, add the standard time offset to the
    1193              :                      * transition time.
    1194              :                      */
    1195              :                     /*
    1196              :                      * Transitions from DST to DDST will effectively disappear
    1197              :                      * since POSIX provides for only one DST offset.
    1198              :                      */
    1199            0 :                     if (isdst && !sp->ttis[j].tt_ttisstd)
    1200              :                     {
    1201            0 :                         sp->ats[i] += dstoffset -
    1202              :                             theirdstoffset;
    1203              :                     }
    1204              :                     else
    1205              :                     {
    1206            0 :                         sp->ats[i] += stdoffset -
    1207              :                             theirstdoffset;
    1208              :                     }
    1209              :                 }
    1210            0 :                 theiroffset = -sp->ttis[j].tt_utoff;
    1211            0 :                 if (sp->ttis[j].tt_isdst)
    1212            0 :                     theirdstoffset = theiroffset;
    1213              :                 else
    1214            0 :                     theirstdoffset = theiroffset;
    1215              :             }
    1216              : 
    1217              :             /*
    1218              :              * Finally, fill in ttis.
    1219              :              */
    1220            0 :             init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
    1221            0 :             init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
    1222            0 :             sp->typecnt = 2;
    1223            0 :             sp->defaulttype = 0;
    1224              :         }
    1225              :     }
    1226              :     else
    1227              :     {
    1228         7045 :         dstlen = 0;
    1229         7045 :         sp->typecnt = 1;     /* only standard time */
    1230         7045 :         sp->timecnt = 0;
    1231         7045 :         init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
    1232         7045 :         sp->defaulttype = 0;
    1233              :     }
    1234        13741 :     sp->charcnt = charcnt;
    1235        13741 :     cp = sp->chars;
    1236        13741 :     memcpy(cp, stdname, stdlen);
    1237        13741 :     cp += stdlen;
    1238        13741 :     *cp++ = '\0';
    1239        13741 :     if (dstlen != 0)
    1240              :     {
    1241         6696 :         memcpy(cp, dstname, dstlen);
    1242         6696 :         *(cp + dstlen) = '\0';
    1243              :     }
    1244        13741 :     return true;
    1245              : }
    1246              : 
    1247              : static void
    1248          205 : gmtload(struct state *const sp)
    1249              : {
    1250          205 :     if (tzload(gmt, NULL, sp, true) != 0)
    1251            0 :         tzparse(gmt, sp, true);
    1252          205 : }
    1253              : 
    1254              : 
    1255              : /*
    1256              :  * The easy way to behave "as if no library function calls" localtime
    1257              :  * is to not call it, so we drop its guts into "localsub", which can be
    1258              :  * freely called. (And no, the PANS doesn't require the above behavior,
    1259              :  * but it *is* desirable.)
    1260              :  */
    1261              : static struct pg_tm *
    1262      1408156 : localsub(struct state const *sp, pg_time_t const *timep,
    1263              :          struct pg_tm *const tmp)
    1264              : {
    1265              :     const struct ttinfo *ttisp;
    1266              :     int         i;
    1267              :     struct pg_tm *result;
    1268      1408156 :     const pg_time_t t = *timep;
    1269              : 
    1270      1408156 :     if (sp == NULL)
    1271            0 :         return gmtsub(timep, 0, tmp);
    1272      1408156 :     if ((sp->goback && t < sp->ats[0]) ||
    1273      1408156 :         (sp->goahead && t > sp->ats[sp->timecnt - 1]))
    1274              :     {
    1275           44 :         pg_time_t   newt = t;
    1276              :         pg_time_t   seconds;
    1277              :         pg_time_t   years;
    1278              : 
    1279           44 :         if (t < sp->ats[0])
    1280            0 :             seconds = sp->ats[0] - t;
    1281              :         else
    1282           44 :             seconds = t - sp->ats[sp->timecnt - 1];
    1283           44 :         --seconds;
    1284           44 :         years = (seconds / SECSPERREPEAT + 1) * YEARSPERREPEAT;
    1285           44 :         seconds = years * AVGSECSPERYEAR;
    1286           44 :         if (t < sp->ats[0])
    1287            0 :             newt += seconds;
    1288              :         else
    1289           44 :             newt -= seconds;
    1290           44 :         if (newt < sp->ats[0] ||
    1291           44 :             newt > sp->ats[sp->timecnt - 1])
    1292            0 :             return NULL;        /* "cannot happen" */
    1293           44 :         result = localsub(sp, &newt, tmp);
    1294           44 :         if (result)
    1295              :         {
    1296              :             int_fast64_t newy;
    1297              : 
    1298           44 :             newy = result->tm_year;
    1299           44 :             if (t < sp->ats[0])
    1300            0 :                 newy -= years;
    1301              :             else
    1302           44 :                 newy += years;
    1303           44 :             if (!(INT_MIN <= newy && newy <= INT_MAX))
    1304            0 :                 return NULL;
    1305           44 :             result->tm_year = newy;
    1306              :         }
    1307           44 :         return result;
    1308              :     }
    1309      1408112 :     if (sp->timecnt == 0 || t < sp->ats[0])
    1310              :     {
    1311      1328066 :         i = sp->defaulttype;
    1312              :     }
    1313              :     else
    1314              :     {
    1315        80046 :         int         lo = 1;
    1316        80046 :         int         hi = sp->timecnt;
    1317              : 
    1318       852726 :         while (lo < hi)
    1319              :         {
    1320       772680 :             int         mid = (lo + hi) >> 1;
    1321              : 
    1322       772680 :             if (t < sp->ats[mid])
    1323       459683 :                 hi = mid;
    1324              :             else
    1325       312997 :                 lo = mid + 1;
    1326              :         }
    1327        80046 :         i = (int) sp->types[lo - 1];
    1328              :     }
    1329      1408112 :     ttisp = &sp->ttis[i];
    1330              : 
    1331              :     /*
    1332              :      * To get (wrong) behavior that's compatible with System V Release 2.0
    1333              :      * you'd replace the statement below with t += ttisp->tt_utoff;
    1334              :      * timesub(&t, 0L, sp, tmp);
    1335              :      */
    1336      1408112 :     result = timesub(&t, ttisp->tt_utoff, sp, tmp);
    1337      1408112 :     if (result)
    1338              :     {
    1339      1408112 :         result->tm_isdst = ttisp->tt_isdst;
    1340      1408112 :         result->tm_zone = unconstify(char *, &sp->chars[ttisp->tt_desigidx]);
    1341              :     }
    1342      1408112 :     return result;
    1343              : }
    1344              : 
    1345              : 
    1346              : struct pg_tm *
    1347      1408112 : pg_localtime(const pg_time_t *timep, const pg_tz *tz)
    1348              : {
    1349      1408112 :     return localsub(&tz->state, timep, &tm);
    1350              : }
    1351              : 
    1352              : 
    1353              : /*
    1354              :  * gmtsub is to gmtime as localsub is to localtime.
    1355              :  *
    1356              :  * Except we have a private "struct state" for GMT, so no sp is passed in.
    1357              :  */
    1358              : 
    1359              : static struct pg_tm *
    1360       197753 : gmtsub(pg_time_t const *timep, int_fast32_t offset,
    1361              :        struct pg_tm *tmp)
    1362              : {
    1363              :     struct pg_tm *result;
    1364              : 
    1365              :     /* GMT timezone state data is kept here */
    1366              :     static struct state *gmtptr = NULL;
    1367              : 
    1368       197753 :     if (gmtptr == NULL)
    1369              :     {
    1370              :         /* Allocate on first use */
    1371          205 :         gmtptr = (struct state *) malloc(sizeof(struct state));
    1372          205 :         if (gmtptr == NULL)
    1373            0 :             return NULL;        /* errno should be set by malloc */
    1374          205 :         gmtload(gmtptr);
    1375              :     }
    1376              : 
    1377       197753 :     result = timesub(timep, offset, gmtptr, tmp);
    1378              : 
    1379              :     /*
    1380              :      * Could get fancy here and deliver something such as "+xx" or "-xx" if
    1381              :      * offset is non-zero, but this is no time for a treasure hunt.
    1382              :      */
    1383       197753 :     if (offset != 0)
    1384            0 :         tmp->tm_zone = wildabbr;
    1385              :     else
    1386       197753 :         tmp->tm_zone = gmtptr->chars;
    1387              : 
    1388       197753 :     return result;
    1389              : }
    1390              : 
    1391              : struct pg_tm *
    1392       197753 : pg_gmtime(const pg_time_t *timep)
    1393              : {
    1394       197753 :     return gmtsub(timep, 0, &tm);
    1395              : }
    1396              : 
    1397              : /*
    1398              :  * Return the number of leap years through the end of the given year
    1399              :  * where, to make the math easy, the answer for year zero is defined as zero.
    1400              :  */
    1401              : 
    1402              : static int
    1403      6413582 : leaps_thru_end_of_nonneg(int y)
    1404              : {
    1405      6413582 :     return y / 4 - y / 100 + y / 400;
    1406              : }
    1407              : 
    1408              : static int
    1409      6413582 : leaps_thru_end_of(const int y)
    1410              : {
    1411              :     return (y < 0
    1412         1552 :             ? -1 - leaps_thru_end_of_nonneg(-1 - y)
    1413      6415134 :             : leaps_thru_end_of_nonneg(y));
    1414              : }
    1415              : 
    1416              : static struct pg_tm *
    1417      1605865 : timesub(const pg_time_t *timep, int_fast32_t offset,
    1418              :         const struct state *sp, struct pg_tm *tmp)
    1419              : {
    1420              :     const struct lsinfo *lp;
    1421              :     pg_time_t   tdays;
    1422              :     int         idays;          /* unsigned would be so 2003 */
    1423              :     int_fast64_t rem;
    1424              :     int         y;
    1425              :     const int  *ip;
    1426              :     int_fast64_t corr;
    1427              :     bool        hit;
    1428              :     int         i;
    1429              : 
    1430      1605865 :     corr = 0;
    1431      1605865 :     hit = false;
    1432      1605865 :     i = (sp == NULL) ? 0 : sp->leapcnt;
    1433      1605865 :     while (--i >= 0)
    1434              :     {
    1435            0 :         lp = &sp->lsis[i];
    1436            0 :         if (*timep >= lp->ls_trans)
    1437              :         {
    1438            0 :             corr = lp->ls_corr;
    1439            0 :             hit = (*timep == lp->ls_trans
    1440            0 :                    && (i == 0 ? 0 : lp[-1].ls_corr) < corr);
    1441            0 :             break;
    1442              :         }
    1443              :     }
    1444      1605865 :     y = EPOCH_YEAR;
    1445      1605865 :     tdays = *timep / SECSPERDAY;
    1446      1605865 :     rem = *timep % SECSPERDAY;
    1447      3206791 :     while (tdays < 0 || tdays >= year_lengths[isleap(y)])
    1448              :     {
    1449              :         int         newy;
    1450              :         pg_time_t   tdelta;
    1451              :         int         idelta;
    1452              :         int         leapdays;
    1453              : 
    1454      1600926 :         tdelta = tdays / DAYSPERLYEAR;
    1455      1600926 :         if (!((!TYPE_SIGNED(pg_time_t) || INT_MIN <= tdelta)
    1456              :               && tdelta <= INT_MAX))
    1457            0 :             goto out_of_range;
    1458      1600926 :         idelta = tdelta;
    1459      1600926 :         if (idelta == 0)
    1460        26191 :             idelta = (tdays < 0) ? -1 : 1;
    1461      1600926 :         newy = y;
    1462      1600926 :         if (increment_overflow(&newy, idelta))
    1463            0 :             goto out_of_range;
    1464      1600926 :         leapdays = leaps_thru_end_of(newy - 1) -
    1465      1600926 :             leaps_thru_end_of(y - 1);
    1466      1600926 :         tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
    1467      1600926 :         tdays -= leapdays;
    1468      1600926 :         y = newy;
    1469              :     }
    1470              : 
    1471              :     /*
    1472              :      * Given the range, we can now fearlessly cast...
    1473              :      */
    1474      1605865 :     idays = tdays;
    1475      1605865 :     rem += offset - corr;
    1476      1629108 :     while (rem < 0)
    1477              :     {
    1478        23243 :         rem += SECSPERDAY;
    1479        23243 :         --idays;
    1480              :     }
    1481      1609633 :     while (rem >= SECSPERDAY)
    1482              :     {
    1483         3768 :         rem -= SECSPERDAY;
    1484         3768 :         ++idays;
    1485              :     }
    1486      1615016 :     while (idays < 0)
    1487              :     {
    1488         9151 :         if (increment_overflow(&y, -1))
    1489            0 :             goto out_of_range;
    1490         9151 :         idays += year_lengths[isleap(y)];
    1491              :     }
    1492      1605873 :     while (idays >= year_lengths[isleap(y)])
    1493              :     {
    1494            8 :         idays -= year_lengths[isleap(y)];
    1495            8 :         if (increment_overflow(&y, 1))
    1496            0 :             goto out_of_range;
    1497              :     }
    1498      1605865 :     tmp->tm_year = y;
    1499      1605865 :     if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
    1500            0 :         goto out_of_range;
    1501      1605865 :     tmp->tm_yday = idays;
    1502              : 
    1503              :     /*
    1504              :      * The "extra" mods below avoid overflow problems.
    1505              :      */
    1506      1605865 :     tmp->tm_wday = EPOCH_WDAY +
    1507      1605865 :         ((y - EPOCH_YEAR) % DAYSPERWEEK) *
    1508      1605865 :         (DAYSPERNYEAR % DAYSPERWEEK) +
    1509      1605865 :         leaps_thru_end_of(y - 1) -
    1510      1605865 :         leaps_thru_end_of(EPOCH_YEAR - 1) +
    1511              :         idays;
    1512      1605865 :     tmp->tm_wday %= DAYSPERWEEK;
    1513      1605865 :     if (tmp->tm_wday < 0)
    1514         1114 :         tmp->tm_wday += DAYSPERWEEK;
    1515      1605865 :     tmp->tm_hour = (int) (rem / SECSPERHOUR);
    1516      1605865 :     rem %= SECSPERHOUR;
    1517      1605865 :     tmp->tm_min = (int) (rem / SECSPERMIN);
    1518              : 
    1519              :     /*
    1520              :      * A positive leap second requires a special representation. This uses
    1521              :      * "... ??:59:60" et seq.
    1522              :      */
    1523      1605865 :     tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
    1524      1605865 :     ip = mon_lengths[isleap(y)];
    1525      7852039 :     for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
    1526      6246174 :         idays -= ip[tmp->tm_mon];
    1527      1605865 :     tmp->tm_mday = (int) (idays + 1);
    1528      1605865 :     tmp->tm_isdst = 0;
    1529      1605865 :     tmp->tm_gmtoff = offset;
    1530      1605865 :     return tmp;
    1531              : 
    1532            0 : out_of_range:
    1533            0 :     errno = EOVERFLOW;
    1534            0 :     return NULL;
    1535              : }
    1536              : 
    1537              : /*
    1538              :  * Normalize logic courtesy Paul Eggert.
    1539              :  */
    1540              : 
    1541              : static bool
    1542      3215950 : increment_overflow(int *ip, int j)
    1543              : {
    1544      3215950 :     int const   i = *ip;
    1545              : 
    1546              :     /*----------
    1547              :      * If i >= 0 there can only be overflow if i + j > INT_MAX
    1548              :      * or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
    1549              :      * If i < 0 there can only be overflow if i + j < INT_MIN
    1550              :      * or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
    1551              :      *----------
    1552              :      */
    1553      3215950 :     if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
    1554            0 :         return true;
    1555      3215950 :     *ip += j;
    1556      3215950 :     return false;
    1557              : }
    1558              : 
    1559              : static bool
    1560     21427200 : increment_overflow_time(pg_time_t *tp, int_fast32_t j)
    1561              : {
    1562              :     /*----------
    1563              :      * This is like
    1564              :      * 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
    1565              :      * except that it does the right thing even if *tp + j would overflow.
    1566              :      *----------
    1567              :      */
    1568     42854400 :     if (!(j < 0
    1569      1339200 :           ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
    1570     20088000 :           : *tp <= TIME_T_MAX - j))
    1571            0 :         return true;
    1572     21427200 :     *tp += j;
    1573     21427200 :     return false;
    1574              : }
    1575              : 
    1576              : static int_fast64_t
    1577     13372683 : leapcorr(struct state const *sp, pg_time_t t)
    1578              : {
    1579              :     struct lsinfo const *lp;
    1580              :     int         i;
    1581              : 
    1582     13372683 :     i = sp->leapcnt;
    1583     13372683 :     while (--i >= 0)
    1584              :     {
    1585            0 :         lp = &sp->lsis[i];
    1586            0 :         if (t >= lp->ls_trans)
    1587            0 :             return lp->ls_corr;
    1588              :     }
    1589     13372683 :     return 0;
    1590              : }
    1591              : 
    1592              : /*
    1593              :  * Find the next DST transition time in the given zone after the given time
    1594              :  *
    1595              :  * *timep and *tz are input arguments, the other parameters are output values.
    1596              :  *
    1597              :  * When the function result is 1, *boundary is set to the pg_time_t
    1598              :  * representation of the next DST transition time after *timep,
    1599              :  * *before_gmtoff and *before_isdst are set to the GMT offset and isdst
    1600              :  * state prevailing just before that boundary (in particular, the state
    1601              :  * prevailing at *timep), and *after_gmtoff and *after_isdst are set to
    1602              :  * the state prevailing just after that boundary.
    1603              :  *
    1604              :  * When the function result is 0, there is no known DST transition
    1605              :  * after *timep, but *before_gmtoff and *before_isdst indicate the GMT
    1606              :  * offset and isdst state prevailing at *timep.  (This would occur in
    1607              :  * DST-less time zones, or if a zone has permanently ceased using DST.)
    1608              :  *
    1609              :  * A function result of -1 indicates failure (this case does not actually
    1610              :  * occur in our current implementation).
    1611              :  */
    1612              : int
    1613       108196 : pg_next_dst_boundary(const pg_time_t *timep,
    1614              :                      long int *before_gmtoff,
    1615              :                      int *before_isdst,
    1616              :                      pg_time_t *boundary,
    1617              :                      long int *after_gmtoff,
    1618              :                      int *after_isdst,
    1619              :                      const pg_tz *tz)
    1620              : {
    1621              :     const struct state *sp;
    1622              :     const struct ttinfo *ttisp;
    1623              :     int         i;
    1624              :     int         j;
    1625       108196 :     const pg_time_t t = *timep;
    1626              : 
    1627       108196 :     sp = &tz->state;
    1628       108196 :     if (sp->timecnt == 0)
    1629              :     {
    1630              :         /* non-DST zone, use the defaulttype */
    1631         1989 :         ttisp = &sp->ttis[sp->defaulttype];
    1632         1989 :         *before_gmtoff = ttisp->tt_utoff;
    1633         1989 :         *before_isdst = ttisp->tt_isdst;
    1634         1989 :         return 0;
    1635              :     }
    1636       106207 :     if ((sp->goback && t < sp->ats[0]) ||
    1637       106207 :         (sp->goahead && t > sp->ats[sp->timecnt - 1]))
    1638              :     {
    1639              :         /* For values outside the transition table, extrapolate */
    1640        32608 :         pg_time_t   newt = t;
    1641              :         pg_time_t   seconds;
    1642              :         pg_time_t   tcycles;
    1643              :         int64       icycles;
    1644              :         int         result;
    1645              : 
    1646        32608 :         if (t < sp->ats[0])
    1647            0 :             seconds = sp->ats[0] - t;
    1648              :         else
    1649        32608 :             seconds = t - sp->ats[sp->timecnt - 1];
    1650        32608 :         --seconds;
    1651        32608 :         tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
    1652        32608 :         ++tcycles;
    1653        32608 :         icycles = tcycles;
    1654        32608 :         if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
    1655            0 :             return -1;
    1656        32608 :         seconds = icycles;
    1657        32608 :         seconds *= YEARSPERREPEAT;
    1658        32608 :         seconds *= AVGSECSPERYEAR;
    1659        32608 :         if (t < sp->ats[0])
    1660            0 :             newt += seconds;
    1661              :         else
    1662        32608 :             newt -= seconds;
    1663        32608 :         if (newt < sp->ats[0] ||
    1664        32608 :             newt > sp->ats[sp->timecnt - 1])
    1665            0 :             return -1;          /* "cannot happen" */
    1666              : 
    1667        32608 :         result = pg_next_dst_boundary(&newt, before_gmtoff,
    1668              :                                       before_isdst,
    1669              :                                       boundary,
    1670              :                                       after_gmtoff,
    1671              :                                       after_isdst,
    1672              :                                       tz);
    1673        32608 :         if (t < sp->ats[0])
    1674            0 :             *boundary -= seconds;
    1675              :         else
    1676        32608 :             *boundary += seconds;
    1677        32608 :         return result;
    1678              :     }
    1679              : 
    1680        73599 :     if (t >= sp->ats[sp->timecnt - 1])
    1681              :     {
    1682              :         /* No known transition > t, so use last known segment's type */
    1683          720 :         i = sp->types[sp->timecnt - 1];
    1684          720 :         ttisp = &sp->ttis[i];
    1685          720 :         *before_gmtoff = ttisp->tt_utoff;
    1686          720 :         *before_isdst = ttisp->tt_isdst;
    1687          720 :         return 0;
    1688              :     }
    1689        72879 :     if (t < sp->ats[0])
    1690              :     {
    1691              :         /* For "before", use the defaulttype */
    1692          380 :         ttisp = &sp->ttis[sp->defaulttype];
    1693          380 :         *before_gmtoff = ttisp->tt_utoff;
    1694          380 :         *before_isdst = ttisp->tt_isdst;
    1695          380 :         *boundary = sp->ats[0];
    1696              :         /* And for "after", use the first segment's type */
    1697          380 :         i = sp->types[0];
    1698          380 :         ttisp = &sp->ttis[i];
    1699          380 :         *after_gmtoff = ttisp->tt_utoff;
    1700          380 :         *after_isdst = ttisp->tt_isdst;
    1701          380 :         return 1;
    1702              :     }
    1703              :     /* Else search to find the boundary following t */
    1704              :     {
    1705        72499 :         int         lo = 1;
    1706        72499 :         int         hi = sp->timecnt - 1;
    1707              : 
    1708       853554 :         while (lo < hi)
    1709              :         {
    1710       781055 :             int         mid = (lo + hi) >> 1;
    1711              : 
    1712       781055 :             if (t < sp->ats[mid])
    1713       441663 :                 hi = mid;
    1714              :             else
    1715       339392 :                 lo = mid + 1;
    1716              :         }
    1717        72499 :         i = lo;
    1718              :     }
    1719        72499 :     j = sp->types[i - 1];
    1720        72499 :     ttisp = &sp->ttis[j];
    1721        72499 :     *before_gmtoff = ttisp->tt_utoff;
    1722        72499 :     *before_isdst = ttisp->tt_isdst;
    1723        72499 :     *boundary = sp->ats[i];
    1724        72499 :     j = sp->types[i];
    1725        72499 :     ttisp = &sp->ttis[j];
    1726        72499 :     *after_gmtoff = ttisp->tt_utoff;
    1727        72499 :     *after_isdst = ttisp->tt_isdst;
    1728        72499 :     return 1;
    1729              : }
    1730              : 
    1731              : /*
    1732              :  * Identify a timezone abbreviation's meaning in the given zone
    1733              :  *
    1734              :  * Determine the GMT offset and DST flag associated with the abbreviation.
    1735              :  * This is generally used only when the abbreviation has actually changed
    1736              :  * meaning over time; therefore, we also take a UTC cutoff time, and return
    1737              :  * the meaning in use at or most recently before that time, or the meaning
    1738              :  * in first use after that time if the abbrev was never used before that.
    1739              :  *
    1740              :  * On success, returns true and sets *gmtoff and *isdst.  If the abbreviation
    1741              :  * was never used at all in this zone, returns false.
    1742              :  *
    1743              :  * Note: abbrev is matched case-sensitively; it should be all-upper-case.
    1744              :  */
    1745              : bool
    1746         1134 : pg_interpret_timezone_abbrev(const char *abbrev,
    1747              :                              const pg_time_t *timep,
    1748              :                              long int *gmtoff,
    1749              :                              int *isdst,
    1750              :                              const pg_tz *tz)
    1751              : {
    1752              :     const struct state *sp;
    1753              :     const char *abbrs;
    1754              :     const struct ttinfo *ttisp;
    1755              :     int         abbrind;
    1756              :     int         cutoff;
    1757              :     int         i;
    1758         1134 :     const pg_time_t t = *timep;
    1759              : 
    1760         1134 :     sp = &tz->state;
    1761              : 
    1762              :     /*
    1763              :      * Locate the abbreviation in the zone's abbreviation list.  We assume
    1764              :      * there are not duplicates in the list.
    1765              :      */
    1766         1134 :     abbrs = sp->chars;
    1767         1134 :     abbrind = 0;
    1768         5872 :     while (abbrind < sp->charcnt)
    1769              :     {
    1770         5092 :         if (strcmp(abbrev, abbrs + abbrind) == 0)
    1771          354 :             break;
    1772        19598 :         while (abbrs[abbrind] != '\0')
    1773        14860 :             abbrind++;
    1774         4738 :         abbrind++;
    1775              :     }
    1776         1134 :     if (abbrind >= sp->charcnt)
    1777          780 :         return false;           /* not there! */
    1778              : 
    1779              :     /*
    1780              :      * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
    1781              :      * (goback/goahead zones).  Finding the newest or oldest meaning of the
    1782              :      * abbreviation should get us what we want, since extrapolation would just
    1783              :      * be repeating the newest or oldest meanings.
    1784              :      *
    1785              :      * Use binary search to locate the first transition > cutoff time.  (Note
    1786              :      * that sp->timecnt could be zero, in which case this loop does nothing
    1787              :      * and only the defaulttype entry will be checked.)
    1788              :      */
    1789              :     {
    1790          354 :         int         lo = 0;
    1791          354 :         int         hi = sp->timecnt;
    1792              : 
    1793         3178 :         while (lo < hi)
    1794              :         {
    1795         2824 :             int         mid = (lo + hi) >> 1;
    1796              : 
    1797         2824 :             if (t < sp->ats[mid])
    1798         1272 :                 hi = mid;
    1799              :             else
    1800         1552 :                 lo = mid + 1;
    1801              :         }
    1802          354 :         cutoff = lo;
    1803              :     }
    1804              : 
    1805              :     /*
    1806              :      * Scan backwards to find the latest interval using the given abbrev
    1807              :      * before the cutoff time.
    1808              :      */
    1809        13710 :     for (i = cutoff - 1; i >= 0; i--)
    1810              :     {
    1811        13682 :         ttisp = &sp->ttis[sp->types[i]];
    1812        13682 :         if (ttisp->tt_desigidx == abbrind)
    1813              :         {
    1814          326 :             *gmtoff = ttisp->tt_utoff;
    1815          326 :             *isdst = ttisp->tt_isdst;
    1816          326 :             return true;
    1817              :         }
    1818              :     }
    1819              : 
    1820              :     /*
    1821              :      * Not found yet; check the defaulttype, which is notionally the era
    1822              :      * before any of the entries in sp->types[].
    1823              :      */
    1824           28 :     ttisp = &sp->ttis[sp->defaulttype];
    1825           28 :     if (ttisp->tt_desigidx == abbrind)
    1826              :     {
    1827           28 :         *gmtoff = ttisp->tt_utoff;
    1828           28 :         *isdst = ttisp->tt_isdst;
    1829           28 :         return true;
    1830              :     }
    1831              : 
    1832              :     /*
    1833              :      * Not there, so scan forwards to find the first one after the cutoff.
    1834              :      */
    1835            0 :     for (i = cutoff; i < sp->timecnt; i++)
    1836              :     {
    1837            0 :         ttisp = &sp->ttis[sp->types[i]];
    1838            0 :         if (ttisp->tt_desigidx == abbrind)
    1839              :         {
    1840            0 :             *gmtoff = ttisp->tt_utoff;
    1841            0 :             *isdst = ttisp->tt_isdst;
    1842            0 :             return true;
    1843              :         }
    1844              :     }
    1845              : 
    1846            0 :     return false;               /* hm, not actually used in any interval? */
    1847              : }
    1848              : 
    1849              : /*
    1850              :  * Detect whether a timezone abbreviation is defined within the given zone.
    1851              :  *
    1852              :  * This is similar to pg_interpret_timezone_abbrev() but is not concerned
    1853              :  * with a specific point in time.  We want to know if the abbreviation is
    1854              :  * known at all, and if so whether it has one meaning or several.
    1855              :  *
    1856              :  * Returns true if the abbreviation is known, false if not.
    1857              :  * If the abbreviation is known and has a single meaning (only one value
    1858              :  * of gmtoff/isdst), sets *isfixed = true and sets *gmtoff and *isdst.
    1859              :  * If there are multiple meanings, sets *isfixed = false.
    1860              :  *
    1861              :  * Note: abbrev is matched case-sensitively; it should be all-upper-case.
    1862              :  */
    1863              : bool
    1864         4955 : pg_timezone_abbrev_is_known(const char *abbrev,
    1865              :                             bool *isfixed,
    1866              :                             long int *gmtoff,
    1867              :                             int *isdst,
    1868              :                             const pg_tz *tz)
    1869              : {
    1870         4955 :     bool        result = false;
    1871         4955 :     const struct state *sp = &tz->state;
    1872              :     const char *abbrs;
    1873              :     int         abbrind;
    1874              : 
    1875              :     /*
    1876              :      * Locate the abbreviation in the zone's abbreviation list.  We assume
    1877              :      * there are not duplicates in the list.
    1878              :      */
    1879         4955 :     abbrs = sp->chars;
    1880         4955 :     abbrind = 0;
    1881        28337 :     while (abbrind < sp->charcnt)
    1882              :     {
    1883        23535 :         if (strcmp(abbrev, abbrs + abbrind) == 0)
    1884          153 :             break;
    1885        93568 :         while (abbrs[abbrind] != '\0')
    1886        70186 :             abbrind++;
    1887        23382 :         abbrind++;
    1888              :     }
    1889         4955 :     if (abbrind >= sp->charcnt)
    1890         4802 :         return false;           /* definitely not there */
    1891              : 
    1892              :     /*
    1893              :      * Scan the ttinfo array to find uses of the abbreviation.
    1894              :      */
    1895         1211 :     for (int i = 0; i < sp->typecnt; i++)
    1896              :     {
    1897         1058 :         const struct ttinfo *ttisp = &sp->ttis[i];
    1898              : 
    1899         1058 :         if (ttisp->tt_desigidx == abbrind)
    1900              :         {
    1901          290 :             if (!result)
    1902              :             {
    1903              :                 /* First usage */
    1904          153 :                 *isfixed = true;    /* for the moment */
    1905          153 :                 *gmtoff = ttisp->tt_utoff;
    1906          153 :                 *isdst = ttisp->tt_isdst;
    1907          153 :                 result = true;
    1908              :             }
    1909              :             else
    1910              :             {
    1911              :                 /* Second or later usage, does it match? */
    1912          137 :                 if (*gmtoff != ttisp->tt_utoff ||
    1913          137 :                     *isdst != ttisp->tt_isdst)
    1914              :                 {
    1915            0 :                     *isfixed = false;
    1916            0 :                     break;      /* no point in looking further */
    1917              :                 }
    1918              :             }
    1919              :         }
    1920              :     }
    1921              : 
    1922          153 :     return result;
    1923              : }
    1924              : 
    1925              : /*
    1926              :  * Iteratively fetch all the abbreviations used in the given time zone.
    1927              :  *
    1928              :  * *indx is a state counter that the caller must initialize to zero
    1929              :  * before the first call, and not touch between calls.
    1930              :  *
    1931              :  * Returns the next known abbreviation, or NULL if there are no more.
    1932              :  *
    1933              :  * Note: the caller typically applies pg_interpret_timezone_abbrev()
    1934              :  * to each result.  While that nominally results in O(N^2) time spent
    1935              :  * searching the sp->chars[] array, we don't expect any zone to have
    1936              :  * enough abbreviations to make that meaningful.
    1937              :  */
    1938              : const char *
    1939          168 : pg_get_next_timezone_abbrev(int *indx,
    1940              :                             const pg_tz *tz)
    1941              : {
    1942              :     const char *result;
    1943          168 :     const struct state *sp = &tz->state;
    1944              :     const char *abbrs;
    1945              :     int         abbrind;
    1946              : 
    1947              :     /* If we're still in range, the result is the current abbrev. */
    1948          168 :     abbrs = sp->chars;
    1949          168 :     abbrind = *indx;
    1950          168 :     if (abbrind < 0 || abbrind >= sp->charcnt)
    1951           28 :         return NULL;
    1952          140 :     result = abbrs + abbrind;
    1953              : 
    1954              :     /* Advance *indx past this abbrev and its trailing null. */
    1955          560 :     while (abbrs[abbrind] != '\0')
    1956          420 :         abbrind++;
    1957          140 :     abbrind++;
    1958          140 :     *indx = abbrind;
    1959              : 
    1960          140 :     return result;
    1961              : }
    1962              : 
    1963              : /*
    1964              :  * If the given timezone uses only one GMT offset, store that offset
    1965              :  * into *gmtoff and return true, else return false.
    1966              :  */
    1967              : bool
    1968          621 : pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
    1969              : {
    1970              :     /*
    1971              :      * The zone could have more than one ttinfo, if it's historically used
    1972              :      * more than one abbreviation.  We return true as long as they all have
    1973              :      * the same gmtoff.
    1974              :      */
    1975              :     const struct state *sp;
    1976              :     int         i;
    1977              : 
    1978          621 :     sp = &tz->state;
    1979          639 :     for (i = 1; i < sp->typecnt; i++)
    1980              :     {
    1981           74 :         if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
    1982           56 :             return false;
    1983              :     }
    1984          565 :     *gmtoff = sp->ttis[0].tt_utoff;
    1985          565 :     return true;
    1986              : }
    1987              : 
    1988              : /*
    1989              :  * Return the name of the current timezone
    1990              :  */
    1991              : const char *
    1992        39987 : pg_get_timezone_name(pg_tz *tz)
    1993              : {
    1994        39987 :     if (tz)
    1995        39987 :         return tz->TZname;
    1996            0 :     return NULL;
    1997              : }
    1998              : 
    1999              : /*
    2000              :  * Check whether timezone is acceptable.
    2001              :  *
    2002              :  * What we are doing here is checking for leap-second-aware timekeeping.
    2003              :  * We need to reject such TZ settings because they'll wreak havoc with our
    2004              :  * date/time arithmetic.
    2005              :  */
    2006              : bool
    2007        23511 : pg_tz_acceptable(pg_tz *tz)
    2008              : {
    2009              :     struct pg_tm *tt;
    2010              :     pg_time_t   time2000;
    2011              : 
    2012              :     /*
    2013              :      * To detect leap-second timekeeping, run pg_localtime for what should be
    2014              :      * GMT midnight, 2000-01-01.  Insist that the tm_sec value be zero; any
    2015              :      * other result has to be due to leap seconds.
    2016              :      */
    2017        23511 :     time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
    2018        23511 :     tt = pg_localtime(&time2000, tz);
    2019        23511 :     if (!tt || tt->tm_sec != 0)
    2020            0 :         return false;
    2021              : 
    2022        23511 :     return true;
    2023              : }
        

Generated by: LCOV version 2.0-1