YugabyteDB (2.13.0.0-b42, bfc6a6643e7399ac8a0e81d06a3ee6d6571b33ab)

Coverage Report

Created: 2022-03-09 17:30

/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
741k
{
114
741k
  s->tt_gmtoff = gmtoff;
115
741k
  s->tt_isdst = isdst;
116
741k
  s->tt_abbrind = abbrind;
117
741k
  s->tt_ttisstd = false;
118
741k
  s->tt_ttisgmt = false;
119
741k
}
120
121
static int32
122
detzcode(const char *const codep)
123
49.1M
{
124
49.1M
  int32   result;
125
49.1M
  int     i;
126
49.1M
  int32   one = 1;
127
49.1M
  int32   halfmaxval = one << (32 - 2);
128
49.1M
  int32   maxval = halfmaxval - 1 + halfmaxval;
129
49.1M
  int32   minval = -1 - maxval;
130
131
49.1M
  result = codep[0] & 0x7f;
132
196M
  for (i = 1; i < 4; ++i)
133
147M
    result = (result << 8) | (codep[i] & 0xff);
134
135
49.1M
  if (codep[0] & 0x80)
136
10.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
10.6M
    result -= !TWOS_COMPLEMENT(int32) &&result != 0;
142
10.6M
    result += minval;
143
10.6M
  }
144
49.1M
  return result;
145
49.1M
}
146
147
static int64
148
detzcode64(const char *const codep)
149
37.0M
{
150
37.0M
  uint64    result;
151
37.0M
  int     i;
152
37.0M
  int64   one = 1;
153
37.0M
  int64   halfmaxval = one << (64 - 2);
154
37.0M
  int64   maxval = halfmaxval - 1 + halfmaxval;
155
37.0M
  int64   minval = -TWOS_COMPLEMENT(int64) -maxval;
156
157
37.0M
  result = codep[0] & 0x7f;
158
296M
  for (i = 1; i < 8; ++i)
159
259M
    result = (result << 8) | (codep[i] & 0xff);
160
161
37.0M
  if (codep[0] & 0x80)
162
8.45M
  {
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
8.45M
    result -= !TWOS_COMPLEMENT(int64) &&result != 0;
168
8.45M
    result += minval;
169
8.45M
  }
170
37.0M
  return result;
171
37.0M
}
172
173
static bool
174
differ_by_repeat(const pg_time_t t1, const pg_time_t t0)
175
148M
{
176
148M
  if (TYPE_BIT(pg_time_t) -TYPE_SIGNED(pg_time_t) <SECSPERREPEAT_BITS)
177
0
    return 0;
178
148M
  return t1 - t0 == SECSPERREPEAT;
179
148M
}
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
540k
{
218
540k
  int     i;
219
540k
  int     fid;
220
540k
  int     stored;
221
540k
  ssize_t   nread;
222
540k
  union input_buffer *up = &lsp->u.u;
223
540k
  int     tzheadsize = sizeof(struct tzhead);
224
225
540k
  sp->goback = sp->goahead = false;
226
227
540k
  if (!name)
228
0
  {
229
0
    name = TZDEFAULT;
230
0
    if (!name)
231
0
      return EINVAL;
232
540k
  }
233
234
540k
  if (name[0] == ':')
235
0
    ++name;
236
237
540k
  fid = pg_open_tzfile(name, canonname);
238
540k
  if (fid < 0)
239
0
    return ENOENT;     /* pg_open_tzfile may not set errno */
240
241
540k
  nread = read(fid, up->buf, sizeof up->buf);
242
540k
  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
540k
  if (close(fid) < 0)
250
0
    return errno;
251
1.62M
  for (stored = 4; stored <= 8; stored *= 2)
252
1.08M
  {
253
1.08M
    int32   ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt);
254
1.08M
    int32   ttisgmtcnt = detzcode(up->tzhead.tzh_ttisgmtcnt);
255
1.08M
    int64   prevtr = 0;
256
1.08M
    int32   prevcorr = 0;
257
1.08M
    int32   leapcnt = detzcode(up->tzhead.tzh_leapcnt);
258
1.08M
    int32   timecnt = detzcode(up->tzhead.tzh_timecnt);
259
1.08M
    int32   typecnt = detzcode(up->tzhead.tzh_typecnt);
260
1.08M
    int32   charcnt = detzcode(up->tzhead.tzh_charcnt);
261
1.08M
    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
1.08M
    if (!(0 <= leapcnt && leapcnt < TZ_MAX_LEAPS
269
1.08M
        && 0 <= typecnt && typecnt < TZ_MAX_TYPES
270
1.08M
        && 0 <= timecnt && timecnt < TZ_MAX_TIMES
271
1.08M
        && 0 <= charcnt && charcnt < TZ_MAX_CHARS
272
1.08M
        && (ttisstdcnt == typecnt || ttisstdcnt == 0)
273
1.08M
        && (ttisgmtcnt == typecnt || ttisgmtcnt == 0)))
274
0
      return EINVAL;
275
1.08M
    if (nread
276
1.08M
      < (tzheadsize   /* struct tzhead */
277
1.08M
         + timecnt * stored /* ats */
278
1.08M
         + timecnt    /* types */
279
1.08M
         + typecnt * 6  /* ttinfos */
280
1.08M
         + charcnt    /* chars */
281
1.08M
         + leapcnt * (stored + 4) /* lsinfos */
282
1.08M
         + ttisstdcnt   /* ttisstds */
283
1.08M
         + ttisgmtcnt))  /* ttisgmts */
284
0
      return EINVAL;
285
1.08M
    sp->leapcnt = leapcnt;
286
1.08M
    sp->timecnt = timecnt;
287
1.08M
    sp->typecnt = typecnt;
288
1.08M
    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
1.08M
    timecnt = 0;
296
74.9M
    for (i = 0; i < sp->timecnt; ++i)
297
73.9M
    {
298
73.9M
      int64   at
299
37.0M
      = stored == 4 ? detzcode(p) : detzcode64(p);
300
301
73.9M
      sp->types[i] = at <= TIME_T_MAX;
302
73.9M
      if (sp->types[i])
303
73.9M
      {
304
73.9M
        pg_time_t attime
305
73.9M
        = ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
306
73.9M
           ? TIME_T_MIN : at);
307
308
73.9M
        if (timecnt && attime <= sp->ats[timecnt - 1])
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
73.9M
        sp->ats[timecnt++] = attime;
316
73.9M
      }
317
73.9M
      p += stored;
318
73.9M
    }
319
320
1.08M
    timecnt = 0;
321
74.9M
    for (i = 0; i < sp->timecnt; ++i)
322
73.9M
    {
323
73.9M
      unsigned char typ = *p++;
324
325
73.9M
      if (sp->typecnt <= typ)
326
0
        return EINVAL;
327
73.9M
      if (sp->types[i])
328
73.9M
        sp->types[timecnt++] = typ;
329
73.9M
    }
330
1.08M
    sp->timecnt = timecnt;
331
6.93M
    for (i = 0; i < sp->typecnt; ++i)
332
5.85M
    {
333
5.85M
      struct ttinfo *ttisp;
334
5.85M
      unsigned char isdst,
335
5.85M
            abbrind;
336
337
5.85M
      ttisp = &sp->ttis[i];
338
5.85M
      ttisp->tt_gmtoff = detzcode(p);
339
5.85M
      p += 4;
340
5.85M
      isdst = *p++;
341
5.85M
      if (!(isdst < 2))
342
0
        return EINVAL;
343
5.85M
      ttisp->tt_isdst = isdst;
344
5.85M
      abbrind = *p++;
345
5.85M
      if (!(abbrind < sp->charcnt))
346
0
        return EINVAL;
347
5.85M
      ttisp->tt_abbrind = abbrind;
348
5.85M
    }
349
19.0M
    for (i = 0; i < sp->charcnt; ++i)
350
17.9M
      sp->chars[i] = *p++;
351
1.08M
    sp->chars[i] = '\0';  /* ensure '\0' at end */
352
353
    /* Read leap seconds, discarding those out of pg_time_t range.  */
354
1.08M
    leapcnt = 0;
355
1.08M
    for (i = 0; i < sp->leapcnt; ++i)
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
1.08M
    sp->leapcnt = leapcnt;
381
382
6.93M
    for (i = 0; i < sp->typecnt; ++i)
383
5.85M
    {
384
5.85M
      struct ttinfo *ttisp;
385
386
5.85M
      ttisp = &sp->ttis[i];
387
5.85M
      if (ttisstdcnt == 0)
388
0
        ttisp->tt_ttisstd = false;
389
5.85M
      else
390
5.85M
      {
391
5.85M
        if (*p != true && *p != false)
392
0
          return EINVAL;
393
5.85M
        ttisp->tt_ttisstd = *p++;
394
5.85M
      }
395
5.85M
    }
396
6.93M
    for (i = 0; i < sp->typecnt; ++i)
397
5.85M
    {
398
5.85M
      struct ttinfo *ttisp;
399
400
5.85M
      ttisp = &sp->ttis[i];
401
5.85M
      if (ttisgmtcnt == 0)
402
0
        ttisp->tt_ttisgmt = false;
403
5.85M
      else
404
5.85M
      {
405
5.85M
        if (*p != true && *p != false)
406
0
          return EINVAL;
407
5.85M
        ttisp->tt_ttisgmt = *p++;
408
5.85M
      }
409
5.85M
    }
410
411
    /*
412
     * If this is an old file, we're done.
413
     */
414
1.08M
    if (up->tzhead.tzh_version[0] == '\0')
415
0
      break;
416
1.08M
    nread -= p - up->buf;
417
1.08M
    memmove(up->buf, p, nread);
418
1.08M
  }
419
540k
  if (doextend && nread > 2 &&
420
538k
    up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
421
538k
    sp->typecnt + 2 <= TZ_MAX_TYPES)
422
538k
  {
423
538k
    struct state *ts = &lsp->u.st;
424
425
538k
    up->buf[nread - 1] = '\0';
426
538k
    if (tzparse(&up->buf[1], ts, false))
427
538k
    {
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
538k
      int     gotabbr = 0;
437
538k
      int     charcnt = sp->charcnt;
438
439
1.27M
      for (i = 0; i < ts->typecnt; i++)
440
736k
      {
441
736k
        char     *tsabbr = ts->chars + ts->ttis[i].tt_abbrind;
442
736k
        int     j;
443
444
7.98M
        for (j = 0; j < charcnt; j++)
445
7.98M
          if (strcmp(sp->chars + j, tsabbr) == 0)
446
736k
          {
447
736k
            ts->ttis[i].tt_abbrind = j;
448
736k
            gotabbr++;
449
736k
            break;
450
736k
          }
451
736k
        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
736k
      }
464
538k
      if (gotabbr == ts->typecnt)
465
538k
      {
466
538k
        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
714k
        while (1 < sp->timecnt
474
610k
             && (sp->types[sp->timecnt - 1]
475
610k
               == sp->types[sp->timecnt - 2]))
476
175k
          sp->timecnt--;
477
478
106M
        for (i = 0; i < ts->timecnt; i++)
479
106M
          if (sp->timecnt == 0
480
106M
            || sp->ats[sp->timecnt - 1] < ts->ats[i])
481
197k
            break;
482
290M
        while (i < ts->timecnt
483
289M
             && sp->timecnt < TZ_MAX_TIMES)
484
289M
        {
485
289M
          sp->ats[sp->timecnt] = ts->ats[i];
486
289M
          sp->types[sp->timecnt] = (sp->typecnt
487
289M
                        + ts->types[i]);
488
289M
          sp->timecnt++;
489
289M
          i++;
490
289M
        }
491
1.27M
        for (i = 0; i < ts->typecnt; i++)
492
736k
          sp->ttis[sp->typecnt++] = ts->ttis[i];
493
538k
      }
494
538k
    }
495
538k
  }
496
540k
  if (sp->typecnt == 0)
497
0
    return EINVAL;
498
540k
  if (sp->timecnt > 1)
499
436k
  {
500
326M
    for (i = 1; i < sp->timecnt; ++i)
501
325M
      if (typesequiv(sp, sp->types[i], sp->types[0]) &&
502
67.7M
        differ_by_repeat(sp->ats[i], sp->ats[0]))
503
0
      {
504
0
        sp->goback = true;
505
0
        break;
506
0
      }
507
165M
    for (i = sp->timecnt - 2; i >= 0; --i)
508
165M
      if (typesequiv(sp, sp->types[sp->timecnt - 1],
509
165M
               sp->types[i]) &&
510
80.9M
        differ_by_repeat(sp->ats[sp->timecnt - 1],
511
80.9M
                 sp->ats[i]))
512
197k
      {
513
197k
        sp->goahead = true;
514
197k
        break;
515
197k
      }
516
436k
  }
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
311M
  for (i = 0; i < sp->timecnt; ++i)
535
311M
    if (sp->types[i] == 0)
536
11.0k
      break;
537
529k
  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
540k
  if (i < 0 && sp->timecnt > 0 && sp->ttis[sp->types[0]].tt_isdst)
545
7.40k
  {
546
7.40k
    i = sp->types[0];
547
7.40k
    while (--i >= 0)
548
7.40k
      if (!sp->ttis[i].tt_isdst)
549
7.40k
        break;
550
7.40k
  }
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
540k
  if (i < 0)
562
3.62k
  {
563
3.62k
    i = 0;
564
3.62k
    while (sp->ttis[i].tt_isdst)
565
0
      if (++i >= sp->typecnt)
566
0
      {
567
0
        i = 0;
568
0
        break;
569
0
      }
570
3.62k
  }
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
540k
  sp->defaulttype = i;
578
579
540k
  return 0;
580
540k
}
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
540k
{
590
540k
  union local_storage *lsp = malloc(sizeof *lsp);
591
592
540k
  if (!lsp)
593
0
    return errno;
594
540k
  else
595
540k
  {
596
540k
    int     err = tzloadbody(name, canonname, sp, doextend, lsp);
597
598
540k
    free(lsp);
599
540k
    return err;
600
540k
  }
601
540k
}
602
603
static bool
604
typesequiv(const struct state *sp, int a, int b)
605
491M
{
606
491M
  bool    result;
607
608
491M
  if (sp == NULL ||
609
491M
    a < 0 || a >= sp->typecnt ||
610
491M
    b < 0 || b >= sp->typecnt)
611
0
    result = false;
612
491M
  else
613
491M
  {
614
491M
    const struct ttinfo *ap = &sp->ttis[a];
615
491M
    const struct ttinfo *bp = &sp->ttis[b];
616
617
491M
    result = ap->tt_gmtoff == bp->tt_gmtoff &&
618
164M
      ap->tt_isdst == bp->tt_isdst &&
619
159M
      ap->tt_ttisstd == bp->tt_ttisstd &&
620
149M
      ap->tt_ttisgmt == bp->tt_ttisgmt &&
621
149M
      strcmp(&sp->chars[ap->tt_abbrind],
622
149M
           &sp->chars[bp->tt_abbrind]) == 0;
623
491M
  }
624
491M
  return result;
625
491M
}
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
510k
{
645
510k
  char    c;
646
647
2.16M
  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
648
1.65M
       c != '+')
649
1.65M
    ++strp;
650
510k
  return strp;
651
510k
}
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
225k
{
666
225k
  int     c;
667
668
937k
  while ((c = *strp) != '\0' && c != delim)
669
711k
    ++strp;
670
225k
  return strp;
671
225k
}
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
1.89M
{
683
1.89M
  char    c;
684
1.89M
  int     num;
685
686
1.89M
  if (strp == NULL || !is_digit(c = *strp))
687
0
    return NULL;
688
1.89M
  num = 0;
689
1.89M
  do
690
2.20M
  {
691
2.20M
    num = num * 10 + (c - '0');
692
2.20M
    if (num > max)
693
0
      return NULL;   /* illegal value */
694
2.20M
    c = *++strp;
695
2.20M
  } while (is_digit(c));
696
1.89M
  if (num < min)
697
0
    return NULL;     /* illegal value */
698
1.89M
  *nump = num;
699
1.89M
  return strp;
700
1.89M
}
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
687k
{
713
687k
  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
687k
  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
721
687k
  if (strp == NULL)
722
0
    return NULL;
723
687k
  *secsp = num * (int32) SECSPERHOUR;
724
687k
  if (*strp == ':')
725
26.3k
  {
726
26.3k
    ++strp;
727
26.3k
    strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
728
26.3k
    if (strp == NULL)
729
0
      return NULL;
730
26.3k
    *secsp += num * SECSPERMIN;
731
26.3k
    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
26.3k
  }
741
687k
  return strp;
742
687k
}
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
687k
{
754
687k
  bool    neg = false;
755
756
687k
  if (*strp == '-')
757
282k
  {
758
282k
    neg = true;
759
282k
    ++strp;
760
282k
  }
761
405k
  else if (*strp == '+')
762
0
    ++strp;
763
687k
  strp = getsecs(strp, offsetp);
764
687k
  if (strp == NULL)
765
0
    return NULL;     /* illegal time */
766
687k
  if (neg)
767
282k
    *offsetp = -*offsetp;
768
687k
  return strp;
769
687k
}
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
395k
{
781
395k
  if (*strp == 'J')
782
3.62k
  {
783
    /*
784
     * Julian day.
785
     */
786
3.62k
    rulep->r_type = JULIAN_DAY;
787
3.62k
    ++strp;
788
3.62k
    strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
789
3.62k
  }
790
392k
  else if (*strp == 'M')
791
392k
  {
792
    /*
793
     * Month, week, day.
794
     */
795
392k
    rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
796
392k
    ++strp;
797
392k
    strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
798
392k
    if (strp == NULL)
799
0
      return NULL;
800
392k
    if (*strp++ != '.')
801
0
      return NULL;
802
392k
    strp = getnum(strp, &rulep->r_week, 1, 5);
803
392k
    if (strp == NULL)
804
0
      return NULL;
805
392k
    if (*strp++ != '.')
806
0
      return NULL;
807
392k
    strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
808
392k
  }
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
395k
  if (strp == NULL)
820
0
    return NULL;
821
395k
  if (*strp == '/')
822
144k
  {
823
    /*
824
     * Time specified.
825
     */
826
144k
    ++strp;
827
144k
    strp = getoffset(strp, &rulep->r_time);
828
144k
  }
829
251k
  else
830
251k
    rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
831
395k
  return strp;
832
395k
}
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
396M
{
843
396M
  bool    leapyear;
844
396M
  int32   value;
845
396M
  int     i;
846
396M
  int     d,
847
396M
        m1,
848
396M
        yy0,
849
396M
        yy1,
850
396M
        yy2,
851
396M
        dow;
852
853
396M
  INITIALIZE(value);
854
396M
  leapyear = isleap(year);
855
396M
  switch (rulep->r_type)
856
396M
  {
857
858
3.63M
    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
3.63M
      value = (rulep->r_day - 1) * SECSPERDAY;
867
3.63M
      if (leapyear && rulep->r_day >= 60)
868
877k
        value += SECSPERDAY;
869
3.63M
      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
392M
    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
392M
      m1 = (rulep->r_mon + 9) % 12 + 1;
891
387M
      yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
892
392M
      yy1 = yy0 / 100;
893
392M
      yy2 = yy0 % 100;
894
392M
      dow = ((26 * m1 - 2) / 10 +
895
392M
           1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
896
392M
      if (dow < 0)
897
74.3M
        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
392M
      d = rulep->r_day - dow;
904
392M
      if (d < 0)
905
322M
        d += DAYSPERWEEK;
906
1.05G
      for (i = 1; i < rulep->r_week; ++i)
907
760M
      {
908
760M
        if (d + DAYSPERWEEK >=
909
760M
          mon_lengths[(int) leapyear][rulep->r_mon - 1])
910
94.4M
          break;
911
666M
        d += DAYSPERWEEK;
912
666M
      }
913
914
      /*
915
       * "d" is the day-of-month (zero-origin) of the day we want.
916
       */
917
392M
      value = d * SECSPERDAY;
918
2.65G
      for (i = 0; i < rulep->r_mon - 1; ++i)
919
2.26G
        value += mon_lengths[(int) leapyear][i] * SECSPERDAY;
920
392M
      break;
921
396M
  }
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
396M
  return value + rulep->r_time + offset;
929
396M
}
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
543k
{
939
543k
  const char *stdname;
940
543k
  const char *dstname = NULL;
941
543k
  size_t    stdlen;
942
543k
  size_t    dstlen;
943
543k
  size_t    charcnt;
944
543k
  int32   stdoffset;
945
543k
  int32   dstoffset;
946
543k
  char     *cp;
947
543k
  bool    load_ok;
948
949
543k
  stdname = name;
950
543k
  if (lastditch)
951
4.52k
  {
952
    /* Unlike IANA, don't assume name is exactly "GMT" */
953
4.52k
    stdlen = strlen(name);  /* length of standard zone name */
954
4.52k
    name += stdlen;
955
4.52k
    stdoffset = 0;
956
4.52k
  }
957
538k
  else
958
538k
  {
959
538k
    if (*name == '<')
960
205k
    {
961
205k
      name++;
962
205k
      stdname = name;
963
205k
      name = getqzname(name, '>');
964
205k
      if (*name != '>')
965
0
        return false;
966
205k
      stdlen = name - stdname;
967
205k
      name++;
968
205k
    }
969
333k
    else
970
333k
    {
971
333k
      name = getzname(name);
972
333k
      stdlen = name - stdname;
973
333k
    }
974
538k
    if (*name == '\0')    /* we allow empty STD abbrev, unlike IANA */
975
0
      return false;
976
538k
    name = getoffset(name, &stdoffset);
977
538k
    if (name == NULL)
978
0
      return false;
979
543k
  }
980
543k
  charcnt = stdlen + 1;
981
543k
  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
543k
  sp->goback = sp->goahead = false; /* simulate failed tzload() */
994
543k
  sp->leapcnt = 0;      /* intentionally assume no leap seconds */
995
996
543k
  if (*name != '\0')
997
197k
  {
998
197k
    if (*name == '<')
999
19.9k
    {
1000
19.9k
      dstname = ++name;
1001
19.9k
      name = getqzname(name, '>');
1002
19.9k
      if (*name != '>')
1003
0
        return false;
1004
19.9k
      dstlen = name - dstname;
1005
19.9k
      name++;
1006
19.9k
    }
1007
177k
    else
1008
177k
    {
1009
177k
      dstname = name;
1010
177k
      name = getzname(name);
1011
177k
      dstlen = name - dstname;  /* length of DST abbr. */
1012
177k
    }
1013
197k
    if (!dstlen)
1014
0
      return false;
1015
197k
    charcnt += dstlen + 1;
1016
197k
    if (sizeof sp->chars < charcnt)
1017
0
      return false;
1018
197k
    if (*name != '\0' && *name != ',' && *name != ';')
1019
4.53k
    {
1020
4.53k
      name = getoffset(name, &dstoffset);
1021
4.53k
      if (name == NULL)
1022
0
        return false;
1023
193k
    }
1024
193k
    else
1025
193k
      dstoffset = stdoffset - SECSPERHOUR;
1026
197k
    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
197k
    if (*name == ',' || *name == ';')
1059
197k
    {
1060
197k
      struct rule start;
1061
197k
      struct rule end;
1062
197k
      int     year;
1063
197k
      int     yearlim;
1064
197k
      int     timecnt;
1065
197k
      pg_time_t janfirst;
1066
197k
      int32   janoffset = 0;
1067
197k
      int     yearbeg;
1068
1069
197k
      ++name;
1070
197k
      if ((name = getrule(name, &start)) == NULL)
1071
0
        return false;
1072
197k
      if (*name++ != ',')
1073
0
        return false;
1074
197k
      if ((name = getrule(name, &end)) == NULL)
1075
0
        return false;
1076
197k
      if (*name != '\0')
1077
0
        return false;
1078
197k
      sp->typecnt = 2;  /* standard time and DST */
1079
1080
      /*
1081
       * Two transitions per year, from EPOCH_YEAR forward.
1082
       */
1083
197k
      init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1084
197k
      init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1085
197k
      sp->defaulttype = 0;
1086
197k
      timecnt = 0;
1087
197k
      janfirst = 0;
1088
197k
      yearbeg = EPOCH_YEAR;
1089
1090
197k
      do
1091
39.5M
      {
1092
39.5M
        int32   yearsecs
1093
39.5M
        = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1094
1095
39.5M
        yearbeg--;
1096
39.5M
        if (increment_overflow_time(&janfirst, -yearsecs))
1097
0
        {
1098
0
          janoffset = -yearsecs;
1099
0
          break;
1100
0
        }
1101
39.5M
      } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1102
1103
39.5M
      yearlim = yearbeg + YEARSPERREPEAT + 1;
1104
237M
      for (year = yearbeg; year < yearlim; year++)
1105
198M
      {
1106
198M
        int32
1107
198M
              starttime = transtime(year, &start, stdoffset),
1108
198M
              endtime = transtime(year, &end, dstoffset);
1109
198M
        int32
1110
198M
              yearsecs = (year_lengths[isleap(year)]
1111
198M
                    * SECSPERDAY);
1112
198M
        bool    reversed = endtime < starttime;
1113
1114
198M
        if (reversed)
1115
30.8M
        {
1116
30.8M
          int32   swap = starttime;
1117
1118
30.8M
          starttime = endtime;
1119
30.8M
          endtime = swap;
1120
30.8M
        }
1121
198M
        if (reversed
1122
167M
          || (starttime < endtime
1123
167M
            && (endtime - starttime
1124
167M
              < (yearsecs
1125
167M
                 + (stdoffset - dstoffset)))))
1126
198M
        {
1127
198M
          if (TZ_MAX_TIMES - 2 < timecnt)
1128
197k
            break;
1129
197M
          sp->ats[timecnt] = janfirst;
1130
197M
          if (!increment_overflow_time
1131
197M
            (&sp->ats[timecnt],
1132
197M
             janoffset + starttime))
1133
197M
            sp->types[timecnt++] = !reversed;
1134
197M
          sp->ats[timecnt] = janfirst;
1135
197M
          if (!increment_overflow_time
1136
197M
            (&sp->ats[timecnt],
1137
197M
             janoffset + endtime))
1138
197M
          {
1139
197M
            sp->types[timecnt++] = reversed;
1140
197M
            yearlim = year + YEARSPERREPEAT + 1;
1141
197M
          }
1142
197M
        }
1143
197M
        if (increment_overflow_time
1144
197M
          (&janfirst, janoffset + yearsecs))
1145
0
          break;
1146
197M
        janoffset = 0;
1147
197M
      }
1148
197k
      sp->timecnt = timecnt;
1149
39.5M
      if (!timecnt)
1150
0
      {
1151
0
        sp->ttis[0] = sp->ttis[1];
1152
0
        sp->typecnt = 1;  /* Perpetual DST.  */
1153
0
      }
1154
39.5M
      else if (YEARSPERREPEAT < year - yearbeg)
1155
197k
        sp->goback = sp->goahead = true;
1156
197k
    }
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
197k
  }
1253
345k
  else
1254
345k
  {
1255
345k
    dstlen = 0;
1256
345k
    sp->typecnt = 1;    /* only standard time */
1257
345k
    sp->timecnt = 0;
1258
345k
    init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1259
345k
    sp->defaulttype = 0;
1260
345k
  }
1261
39.9M
  sp->charcnt = charcnt;
1262
39.9M
  cp = sp->chars;
1263
39.9M
  memcpy(cp, stdname, stdlen);
1264
39.9M
  cp += stdlen;
1265
39.9M
  *cp++ = '\0';
1266
39.9M
  if (dstlen != 0)
1267
197k
  {
1268
197k
    memcpy(cp, dstname, dstlen);
1269
197k
    *(cp + dstlen) = '\0';
1270
197k
  }
1271
39.9M
  return true;
1272
543k
}
1273
1274
static void
1275
gmtload(struct state *const sp)
1276
0
{
1277
0
  if (tzload(gmt, NULL, sp, true) != 0)
1278
0
    tzparse(gmt, sp, true);
1279
0
}
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
82.2M
{
1292
82.2M
  const struct ttinfo *ttisp;
1293
82.2M
  int     i;
1294
82.2M
  struct pg_tm *result;
1295
82.2M
  const pg_time_t t = *timep;
1296
1297
82.2M
  if (sp == NULL)
1298
0
    return gmtsub(timep, 0, tmp);
1299
82.2M
  if ((sp->goback && t < sp->ats[0]) ||
1300
82.2M
    (sp->goahead && t > sp->ats[sp->timecnt - 1]))
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
82.2M
  }
1336
82.2M
  if (sp->timecnt == 0 || t < sp->ats[0])
1337
115k
  {
1338
115k
    i = sp->defaulttype;
1339
115k
  }
1340
82.0M
  else
1341
82.0M
  {
1342
82.0M
    int     lo = 1;
1343
82.0M
    int     hi = sp->timecnt;
1344
1345
960M
    while (lo < hi)
1346
878M
    {
1347
878M
      int     mid = (lo + hi) >> 1;
1348
1349
878M
      if (t < sp->ats[mid])
1350
603M
        hi = mid;
1351
274M
      else
1352
274M
        lo = mid + 1;
1353
878M
    }
1354
82.0M
    i = (int) sp->types[lo - 1];
1355
82.0M
  }
1356
82.2M
  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
82.2M
  result = timesub(&t, ttisp->tt_gmtoff, sp, tmp);
1364
82.2M
  if (result)
1365
82.2M
  {
1366
82.2M
    result->tm_isdst = ttisp->tt_isdst;
1367
82.2M
    result->tm_zone = (char *) &sp->chars[ttisp->tt_abbrind];
1368
82.2M
  }
1369
82.2M
  return result;
1370
82.2M
}
1371
1372
1373
struct pg_tm *
1374
pg_localtime(const pg_time_t *timep, const pg_tz *tz)
1375
82.2M
{
1376
82.2M
  return localsub(&tz->state, timep, &tm);
1377
82.2M
}
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
0
{
1390
0
  struct pg_tm *result;
1391
1392
  /* GMT timezone state data is kept here */
1393
0
  static struct state *gmtptr = NULL;
1394
1395
0
  if (gmtptr == NULL)
1396
0
  {
1397
    /* Allocate on first use */
1398
0
    gmtptr = (struct state *) malloc(sizeof(struct state));
1399
0
    if (gmtptr == NULL)
1400
0
      return NULL;   /* errno should be set by malloc */
1401
0
    gmtload(gmtptr);
1402
0
  }
1403
1404
0
  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
0
  if (offset != 0)
1411
0
    tmp->tm_zone = wildabbr;
1412
0
  else
1413
0
    tmp->tm_zone = gmtptr->chars;
1414
1415
0
  return result;
1416
0
}
1417
1418
struct pg_tm *
1419
pg_gmtime(const pg_time_t *timep)
1420
0
{
1421
0
  return gmtsub(timep, 0, &tm);
1422
0
}
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
351M
{
1432
351M
  return y / 4 - y / 100 + y / 400;
1433
351M
}
1434
1435
static int
1436
leaps_thru_end_of(const int y)
1437
351M
{
1438
351M
  return (y < 0
1439
0
      ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1440
351M
      : leaps_thru_end_of_nonneg(y));
1441
351M
}
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
82.2M
{
1447
82.2M
  const struct lsinfo *lp;
1448
82.2M
  pg_time_t tdays;
1449
82.2M
  int     idays;      /* unsigned would be so 2003 */
1450
82.2M
  int64   rem;
1451
82.2M
  int     y;
1452
82.2M
  const int  *ip;
1453
82.2M
  int64   corr;
1454
82.2M
  bool    hit;
1455
82.2M
  int     i;
1456
1457
82.2M
  corr = 0;
1458
82.2M
  hit = false;
1459
82.2M
  i = (sp == NULL) ? 0 : sp->leapcnt;
1460
82.2M
  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
82.2M
  y = EPOCH_YEAR;
1472
82.2M
  tdays = *timep / SECSPERDAY;
1473
82.2M
  rem = *timep % SECSPERDAY;
1474
175M
  while (tdays < 0 || tdays >= year_lengths[isleap(y)])
1475
93.6M
  {
1476
93.6M
    int     newy;
1477
93.6M
    pg_time_t tdelta;
1478
93.6M
    int     idelta;
1479
93.6M
    int     leapdays;
1480
1481
93.6M
    tdelta = tdays / DAYSPERLYEAR;
1482
93.6M
    if (!((!TYPE_SIGNED(pg_time_t) ||INT_MIN <= tdelta)
1483
93.6M
        && tdelta <= INT_MAX))
1484
0
      goto out_of_range;
1485
93.6M
    idelta = tdelta;
1486
93.6M
    if (idelta == 0)
1487
6.98M
      idelta = (tdays < 0) ? -1 : 1;
1488
93.6M
    newy = y;
1489
93.6M
    if (increment_overflow(&newy, idelta))
1490
0
      goto out_of_range;
1491
93.6M
    leapdays = leaps_thru_end_of(newy - 1) -
1492
93.6M
      leaps_thru_end_of(y - 1);
1493
93.6M
    tdays -= ((pg_time_t) newy - y) * DAYSPERNYEAR;
1494
93.6M
    tdays -= leapdays;
1495
93.6M
    y = newy;
1496
93.6M
  }
1497
1498
  /*
1499
   * Given the range, we can now fearlessly cast...
1500
   */
1501
82.2M
  idays = tdays;
1502
82.2M
  rem += offset - corr;
1503
82.6M
  while (rem < 0)
1504
431k
  {
1505
431k
    rem += SECSPERDAY;
1506
431k
    --idays;
1507
431k
  }
1508
82.2M
  while (rem >= SECSPERDAY)
1509
0
  {
1510
0
    rem -= SECSPERDAY;
1511
0
    ++idays;
1512
0
  }
1513
82.4M
  while (idays < 0)
1514
216k
  {
1515
216k
    if (increment_overflow(&y, -1))
1516
0
      goto out_of_range;
1517
216k
    idays += year_lengths[isleap(y)];
1518
216k
  }
1519
82.2M
  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
82.2M
  tmp->tm_year = y;
1526
82.2M
  if (increment_overflow(&tmp->tm_year, -TM_YEAR_BASE))
1527
0
    goto out_of_range;
1528
82.2M
  tmp->tm_yday = idays;
1529
1530
  /*
1531
   * The "extra" mods below avoid overflow problems.
1532
   */
1533
82.2M
  tmp->tm_wday = EPOCH_WDAY +
1534
82.2M
    ((y - EPOCH_YEAR) % DAYSPERWEEK) *
1535
82.2M
    (DAYSPERNYEAR % DAYSPERWEEK) +
1536
82.2M
    leaps_thru_end_of(y - 1) -
1537
82.2M
    leaps_thru_end_of(EPOCH_YEAR - 1) +
1538
82.2M
    idays;
1539
82.2M
  tmp->tm_wday %= DAYSPERWEEK;
1540
82.2M
  if (tmp->tm_wday < 0)
1541
61.6k
    tmp->tm_wday += DAYSPERWEEK;
1542
82.2M
  tmp->tm_hour = (int) (rem / SECSPERHOUR);
1543
82.2M
  rem %= SECSPERHOUR;
1544
82.2M
  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
82.2M
  tmp->tm_sec = (int) (rem % SECSPERMIN) + hit;
1551
82.2M
  ip = mon_lengths[isleap(y)];
1552
531M
  for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1553
449M
    idays -= ip[tmp->tm_mon];
1554
82.2M
  tmp->tm_mday = (int) (idays + 1);
1555
82.2M
  tmp->tm_isdst = 0;
1556
82.2M
  tmp->tm_gmtoff = offset;
1557
82.2M
  return tmp;
1558
1559
0
out_of_range:
1560
0
  errno = EOVERFLOW;
1561
0
  return NULL;
1562
82.2M
}
1563
1564
/*
1565
 * Normalize logic courtesy Paul Eggert.
1566
 */
1567
1568
static bool
1569
increment_overflow(int *ip, int j)
1570
176M
{
1571
176M
  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
18.4E
  if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1581
0
    return true;
1582
176M
  *ip += j;
1583
176M
  return false;
1584
176M
}
1585
1586
static bool
1587
increment_overflow_time(pg_time_t *tp, int32 j)
1588
633M
{
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
633M
  if (!(j < 0
1596
39.5M
      ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1597
593M
      : *tp <= TIME_T_MAX - j))
1598
0
    return true;
1599
633M
  *tp += j;
1600
633M
  return false;
1601
633M
}
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
7.78k
{
1632
7.78k
  const struct state *sp;
1633
7.78k
  const struct ttinfo *ttisp;
1634
7.78k
  int     i;
1635
7.78k
  int     j;
1636
7.78k
  const pg_time_t t = *timep;
1637
1638
7.78k
  sp = &tz->state;
1639
7.78k
  if (sp->timecnt == 0)
1640
11
  {
1641
    /* non-DST zone, use lowest-numbered standard type */
1642
11
    i = 0;
1643
11
    while (sp->ttis[i].tt_isdst)
1644
0
      if (++i >= sp->typecnt)
1645
0
      {
1646
0
        i = 0;
1647
0
        break;
1648
0
      }
1649
11
    ttisp = &sp->ttis[i];
1650
11
    *before_gmtoff = ttisp->tt_gmtoff;
1651
11
    *before_isdst = ttisp->tt_isdst;
1652
11
    return 0;
1653
11
  }
1654
7.77k
  if ((sp->goback && t < sp->ats[0]) ||
1655
7.77k
    (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1656
0
  {
1657
    /* For values outside the transition table, extrapolate */
1658
0
    pg_time_t newt = t;
1659
0
    pg_time_t seconds;
1660
0
    pg_time_t tcycles;
1661
0
    int64   icycles;
1662
0
    int     result;
1663
1664
0
    if (t < sp->ats[0])
1665
0
      seconds = sp->ats[0] - t;
1666
0
    else
1667
0
      seconds = t - sp->ats[sp->timecnt - 1];
1668
0
    --seconds;
1669
0
    tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1670
0
    ++tcycles;
1671
0
    icycles = tcycles;
1672
0
    if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1673
0
      return -1;
1674
0
    seconds = icycles;
1675
0
    seconds *= YEARSPERREPEAT;
1676
0
    seconds *= AVGSECSPERYEAR;
1677
0
    if (t < sp->ats[0])
1678
0
      newt += seconds;
1679
0
    else
1680
0
      newt -= seconds;
1681
0
    if (newt < sp->ats[0] ||
1682
0
      newt > sp->ats[sp->timecnt - 1])
1683
0
      return -1;     /* "cannot happen" */
1684
1685
0
    result = pg_next_dst_boundary(&newt, before_gmtoff,
1686
0
                    before_isdst,
1687
0
                    boundary,
1688
0
                    after_gmtoff,
1689
0
                    after_isdst,
1690
0
                    tz);
1691
0
    if (t < sp->ats[0])
1692
0
      *boundary -= seconds;
1693
0
    else
1694
0
      *boundary += seconds;
1695
0
    return result;
1696
0
  }
1697
1698
7.77k
  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
7.77k
  if (t < sp->ats[0])
1708
0
  {
1709
    /* For "before", use lowest-numbered standard type */
1710
0
    i = 0;
1711
0
    while (sp->ttis[i].tt_isdst)
1712
0
      if (++i >= sp->typecnt)
1713
0
      {
1714
0
        i = 0;
1715
0
        break;
1716
0
      }
1717
0
    ttisp = &sp->ttis[i];
1718
0
    *before_gmtoff = ttisp->tt_gmtoff;
1719
0
    *before_isdst = ttisp->tt_isdst;
1720
0
    *boundary = sp->ats[0];
1721
    /* And for "after", use the first segment's type */
1722
0
    i = sp->types[0];
1723
0
    ttisp = &sp->ttis[i];
1724
0
    *after_gmtoff = ttisp->tt_gmtoff;
1725
0
    *after_isdst = ttisp->tt_isdst;
1726
0
    return 1;
1727
0
  }
1728
  /* Else search to find the boundary following t */
1729
7.77k
  {
1730
7.77k
    int     lo = 1;
1731
7.77k
    int     hi = sp->timecnt - 1;
1732
1733
85.5k
    while (lo < hi)
1734
77.8k
    {
1735
77.8k
      int     mid = (lo + hi) >> 1;
1736
1737
77.8k
      if (t < sp->ats[mid])
1738
54.4k
        hi = mid;
1739
23.3k
      else
1740
23.3k
        lo = mid + 1;
1741
77.8k
    }
1742
7.77k
    i = lo;
1743
7.77k
  }
1744
7.77k
  j = sp->types[i - 1];
1745
7.77k
  ttisp = &sp->ttis[j];
1746
7.77k
  *before_gmtoff = ttisp->tt_gmtoff;
1747
7.77k
  *before_isdst = ttisp->tt_isdst;
1748
7.77k
  *boundary = sp->ats[i];
1749
7.77k
  j = sp->types[i];
1750
7.77k
  ttisp = &sp->ttis[j];
1751
7.77k
  *after_gmtoff = ttisp->tt_gmtoff;
1752
7.77k
  *after_isdst = ttisp->tt_isdst;
1753
7.77k
  return 1;
1754
7.77k
}
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
0
{
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
0
  const struct state *sp;
1873
0
  int     i;
1874
1875
0
  sp = &tz->state;
1876
0
  for (i = 1; i < sp->typecnt; i++)
1877
0
  {
1878
0
    if (sp->ttis[i].tt_gmtoff != sp->ttis[0].tt_gmtoff)
1879
0
      return false;
1880
0
  }
1881
0
  *gmtoff = sp->ttis[0].tt_gmtoff;
1882
0
  return true;
1883
0
}
1884
1885
/*
1886
 * Return the name of the current timezone
1887
 */
1888
const char *
1889
pg_get_timezone_name(pg_tz *tz)
1890
1.65k
{
1891
1.65k
  if (tz)
1892
1.65k
    return tz->TZname;
1893
0
  return NULL;
1894
0
}
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
551k
{
1906
551k
  struct pg_tm *tt;
1907
551k
  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
551k
  time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
1915
551k
  tt = pg_localtime(&time2000, tz);
1916
551k
  if (!tt || tt->tm_sec != 0)
1917
0
    return false;
1918
1919
551k
  return true;
1920
551k
}