YugabyteDB (2.13.1.0-b60, 21121d69985fbf76aa6958d8f04a9bfa936293b5)

Coverage Report

Created: 2022-03-22 16:43

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