Coverage Report

Created: 2026-08-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/timezone/localtime.c
Line
Count
Source
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.1-1988 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
/*
29
 * Pacify gcc -Wcast-qual on char const * exprs.
30
 * Use this carefully, as the casts disable type checking.
31
 * This is a macro so that it can be used in static initializers.
32
 */
33
5.03k
#define UNCONST(a) unconstify(char *, a)
34
35
#ifndef WILDABBR
36
/*
37
 * Someone might make incorrect use of a time zone abbreviation:
38
 *  1.  They might reference tzname[0] before calling tzset (explicitly
39
 *    or implicitly).
40
 *  2.  They might reference tzname[1] before calling tzset (explicitly
41
 *    or implicitly).
42
 *  3.  They might reference tzname[1] after setting to a time zone
43
 *    in which Daylight Saving Time is never observed.
44
 *  4.  They might reference tzname[0] after setting to a time zone
45
 *    in which Standard Time is never observed.
46
 *  5.  They might reference tm.TM_ZONE after calling offtime.
47
 * What's best to do in the above cases is open to debate;
48
 * for now, we just set things up so that in any of the five cases
49
 * WILDABBR is used. Another possibility: initialize tzname[0] to the
50
 * string "tzname[0] used before set", and similarly for the other cases.
51
 * And another: initialize tzname[0] to "ERA", with an explanation in the
52
 * manual page of what this "time zone abbreviation" means (doing this so
53
 * that tzname[0] has the "normal" length of three characters).
54
 */
55
#define WILDABBR "   "
56
#endif              /* !defined WILDABBR */
57
58
static const char wildabbr[] = WILDABBR;
59
60
/*
61
 * The DST rules to use if TZ has no rules.
62
 * Default to US rules as of 2017-05-07.
63
 * POSIX does not specify the default DST rules;
64
 * for historical reasons, US rules are a common default.
65
 */
66
#ifndef TZDEFRULESTRING
67
0
#define TZDEFRULESTRING ",M3.2.0,M11.1.0"
68
#endif
69
70
/* TZNAME_MAXIMUM and types ttinfo, lsinfo, state have been moved to pgtz.h */
71
72
static int
73
leapcount(ATTRIBUTE_MAYBE_UNUSED struct state const *sp)
74
5.03k
{
75
5.03k
#if TZ_RUNTIME_LEAPS
76
5.03k
  return sp->leapcnt;
77
#else
78
  return 0;
79
#endif
80
5.03k
}
81
static void
82
set_leapcount(ATTRIBUTE_MAYBE_UNUSED struct state *sp,
83
        ATTRIBUTE_MAYBE_UNUSED int leapcnt)
84
2
{
85
2
#if TZ_RUNTIME_LEAPS
86
2
  sp->leapcnt = leapcnt;
87
2
#endif
88
2
}
89
static struct lsinfo
90
lsinfo(ATTRIBUTE_MAYBE_UNUSED struct state const *sp,
91
     ATTRIBUTE_MAYBE_UNUSED int i)
92
0
{
93
0
#if TZ_RUNTIME_LEAPS
94
0
  return sp->lsis[i];
95
#else
96
  unreachable();
97
#endif
98
0
}
99
static void
100
set_lsinfo(ATTRIBUTE_MAYBE_UNUSED struct state *sp,
101
       ATTRIBUTE_MAYBE_UNUSED int i,
102
       ATTRIBUTE_MAYBE_UNUSED struct lsinfo lsinfo)
103
0
{
104
0
#if TZ_RUNTIME_LEAPS
105
0
  sp->lsis[i] = lsinfo;
106
0
#endif
107
0
}
108
109
enum r_type
110
{
111
  JULIAN_DAY,         /* Jn = Julian day */
112
  DAY_OF_YEAR,        /* n = day of year */
113
  MONTH_NTH_DAY_OF_WEEK   /* Mm.n.d = month, week, day of week */
114
};
115
116
struct rule
117
{
118
  enum r_type r_type;     /* type of rule */
119
  int     r_day;      /* day number of rule */
120
  int     r_week;     /* week number of rule */
121
  int     r_mon;      /* month number of rule */
122
  int_fast32_t r_time;    /* transition time of rule */
123
};
124
125
/*
126
 * Prototypes for static functions.
127
 */
128
129
static struct pg_tm *gmtsub(pg_time_t const *timep, int_fast32_t offset,
130
              struct pg_tm *tmp);
131
static bool increment_overflow(int *ip, int j);
132
static bool increment_overflow_time(pg_time_t *tp, int_fast32_2s j);
133
static int_fast32_2s leapcorr(struct state const *sp, pg_time_t t);
134
static struct pg_tm *timesub(pg_time_t const *timep,
135
               int_fast32_t offset, struct state const *sp,
136
               struct pg_tm *tmp);
137
static bool tzparse(const char *name, struct state *sp, struct state const *basep);
138
139
140
/*
141
 * Section 4.12.3 of X3.159-1989 requires that
142
 *  Except for the strftime function, these functions [asctime,
143
 *  ctime, gmtime, localtime] return values in one of two static
144
 *  objects: a broken-down time structure and an array of char.
145
 * Thanks to Paul Eggert for noting this.
146
 */
147
148
static struct pg_tm tm;
149
150
/* Initialize *S to a value based on UTOFF, ISDST, and DESIGIDX.  */
151
static void
152
init_ttinfo(struct ttinfo *s, int_fast32_t utoff, bool isdst,
153
      desigidx_type desigidx)
154
2
{
155
2
  s->tt_utoff = utoff;
156
2
  s->tt_isdst = isdst;
157
2
  s->tt_desigidx = desigidx;
158
2
  s->tt_ttisstd = false;
159
2
  s->tt_ttisut = false;
160
2
}
161
162
static int_fast32_2s
163
detzcode(const char *const codep)
164
0
{
165
0
  int     i;
166
0
  int_fast32_2s
167
0
        maxval = TWO_31_MINUS_1,
168
0
        minval = -1 - maxval,
169
0
        result;
170
171
0
  result = codep[0] & 0x7f;
172
0
  for (i = 1; i < 4; ++i)
173
0
    result = (result << 8) | (codep[i] & 0xff);
174
175
0
  if (codep[0] & 0x80)
176
0
  {
177
    /*
178
     * Do two's-complement negation even on non-two's-complement machines.
179
     * This cannot overflow, as int_fast32_2s is wide enough.
180
     */
181
0
    result += minval;
182
0
  }
183
0
  return result;
184
0
}
185
186
static int_fast64_t
187
detzcode64(const char *const codep)
188
0
{
189
0
  int_fast64_t result;
190
0
  int     i;
191
0
  int_fast64_t one = 1;
192
0
  int_fast64_t halfmaxval = one << (64 - 2);
193
0
  int_fast64_t maxval = halfmaxval - 1 + halfmaxval;
194
0
  int_fast64_t minval = -TWOS_COMPLEMENT(int_fast64_t) - maxval;
195
196
0
  result = codep[0] & 0x7f;
197
0
  for (i = 1; i < 8; ++i)
198
0
    result = (result << 8) | (codep[i] & 0xff);
199
200
0
  if (codep[0] & 0x80)
201
0
  {
202
    /*
203
     * Do two's-complement negation even on non-two's-complement machines.
204
     * If the result would be minval - 1, return minval.
205
     */
206
0
    result -= !TWOS_COMPLEMENT(int_fast64_t) && result != 0;
207
0
    result += minval;
208
0
  }
209
0
  return result;
210
0
}
211
212
/* Input buffer for data read from a compiled tz file.  */
213
union input_buffer
214
{
215
  /* The first part of the buffer, interpreted as a header.  */
216
  struct tzhead tzhead;
217
218
  /*
219
   * The entire buffer.  Ideally this would have no size limits; the
220
   * following should suffice for practical use.
221
   */
222
  char    buf[2 * sizeof(struct tzhead) + 2 * sizeof(struct state)
223
          + 4 * TZ_MAX_TIMES];
224
};
225
226
/* Local storage needed for 'tzloadbody'.  */
227
union local_storage
228
{
229
  /* The results of analyzing the file's contents after it is opened.  */
230
  struct file_analysis
231
  {
232
    /* The input buffer.  */
233
    union input_buffer u;
234
235
    /* A temporary state used for parsing a TZ string in the file.  */
236
    struct state st;
237
  }     u;
238
239
  /* PG: we don't need the "fullname" member */
240
};
241
242
/* These tzload flags can be ORed together, and fit into 'char'.  */
243
enum
244
{
245
TZLOAD_FROMENV = 1};      /* The TZ string came from the environment.  */
246
enum
247
{
248
TZLOAD_TZSTRING = 2};     /* Read any newline-surrounded TZ string.  */
249
enum
250
{
251
TZLOAD_TZDIR_SUB = 4};      /* TZ should be a file under TZDIR.  */
252
253
/*
254
 * Load tz data from the file named NAME into *SP.  Respect TZLOADFLAGS.
255
 * Use **LSPP for temporary storage.  Return 0 on
256
 * success, an errno value on failure.
257
 * PG: If "canonname" is not NULL, then on success the canonical spelling of
258
 * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
259
 */
260
static int
261
tzloadbody(char const *name, char *canonname,
262
       struct state *sp, char tzloadflags,
263
       union local_storage **lspp)
264
0
{
265
0
  int     i;
266
0
  int     fid;
267
0
  int     stored;
268
0
  ssize_t   nread;
269
0
  union local_storage *lsp = *lspp;
270
0
  union input_buffer *up;
271
0
  int     tzheadsize = sizeof(struct tzhead);
272
273
0
  sp->goback = sp->goahead = false;
274
275
0
  if (!name)
276
0
  {
277
0
    name = TZDEFAULT;
278
0
    if (!name)
279
0
      return EINVAL;
280
0
  }
281
282
0
  if (name[0] == ':')
283
0
    ++name;
284
285
  /*
286
   * The IANA code goes to a great deal of trouble here to try to prevent
287
   * inappropriate file accesses.  That seems unnecessary for PG since we
288
   * won't run as root.  pg_open_tzfile() does go to some effort to prevent
289
   * accesses outside the designated zoneinfo tree, though.
290
   */
291
0
  fid = pg_open_tzfile(name, canonname);
292
0
  if (fid < 0)
293
0
    return ENOENT;     /* pg_open_tzfile may not set errno */
294
295
0
  up = &lsp->u.u;
296
0
  nread = read(fid, up->buf, sizeof up->buf);
297
0
  if (nread < tzheadsize)
298
0
  {
299
0
    int     err = nread < 0 ? errno : EINVAL;
300
301
0
    close(fid);
302
0
    return err;
303
0
  }
304
0
  if (close(fid) < 0)
305
0
    return errno;
306
307
0
  for (stored = 4; stored <= 8; stored *= 2)
308
0
  {
309
0
    char    version = up->tzhead.tzh_version[0];
310
0
    bool    skip_datablock = stored == 4 && version;
311
0
    int_fast32_t datablock_size;
312
0
    int_fast32_2s
313
0
          ttisstdcnt = detzcode(up->tzhead.tzh_ttisstdcnt),
314
0
          ttisutcnt = detzcode(up->tzhead.tzh_ttisutcnt),
315
0
          leapcnt = detzcode(up->tzhead.tzh_leapcnt),
316
0
          timecnt = detzcode(up->tzhead.tzh_timecnt),
317
0
          typecnt = detzcode(up->tzhead.tzh_typecnt),
318
0
          charcnt = detzcode(up->tzhead.tzh_charcnt);
319
0
    char const *p = up->buf + tzheadsize;
320
321
    /*
322
     * Although tzfile(5) currently requires typecnt to be nonzero,
323
     * support future formats that may allow zero typecnt in files that
324
     * have a TZ string and no transitions.
325
     */
326
0
    if (!(0 <= leapcnt
327
0
        && leapcnt <= (TZ_RUNTIME_LEAPS ? TZ_MAX_LEAPS : 0)
328
0
        && 0 <= typecnt && typecnt <= TZ_MAX_TYPES
329
0
        && 0 <= timecnt && timecnt <= TZ_MAX_TIMES
330
0
        && 0 <= charcnt && charcnt <= TZ_MAX_CHARS
331
0
        && 0 <= ttisstdcnt && ttisstdcnt <= TZ_MAX_TYPES
332
0
        && 0 <= ttisutcnt && ttisutcnt <= TZ_MAX_TYPES))
333
0
      return EINVAL;
334
0
    datablock_size
335
0
      = (timecnt * stored /* ats */
336
0
         + timecnt    /* types */
337
0
         + typecnt * 6  /* ttinfos */
338
0
         + charcnt    /* chars */
339
0
         + leapcnt * (stored + 4) /* lsinfos */
340
0
         + ttisstdcnt   /* ttisstds */
341
0
         + ttisutcnt);  /* ttisuts */
342
0
    if (nread < tzheadsize + datablock_size)
343
0
      return EINVAL;
344
0
    if (skip_datablock)
345
0
      p += datablock_size;
346
0
    else if (!((ttisstdcnt == typecnt || ttisstdcnt == 0)
347
0
           && (ttisutcnt == typecnt || ttisutcnt == 0)))
348
0
      return EINVAL;
349
0
    else
350
0
    {
351
0
      int_fast64_t prevtr = -1;
352
0
      int_fast32_2s prevcorr = -1;
353
354
0
      set_leapcount(sp, leapcnt);
355
0
      sp->timecnt = timecnt;
356
0
      sp->typecnt = typecnt;
357
0
      sp->charcnt = charcnt;
358
359
      /*
360
       * Read transitions, discarding those out of pg_time_t range. But
361
       * pretend the last transition before TIME_T_MIN occurred at
362
       * TIME_T_MIN.
363
       */
364
0
      timecnt = 0;
365
0
      for (i = 0; i < sp->timecnt; ++i)
366
0
      {
367
0
        int_fast64_t at
368
0
        = stored == 4 ? detzcode(p) : detzcode64(p);
369
370
0
        sp->types[i] = at <= TIME_T_MAX;
371
0
        if (sp->types[i])
372
0
        {
373
0
          pg_time_t attime
374
0
          = ((TYPE_SIGNED(pg_time_t) ? at < TIME_T_MIN : at < 0)
375
0
             ? TIME_T_MIN : at);
376
377
0
          if (timecnt && attime <= sp->ats[timecnt - 1])
378
0
          {
379
0
            if (attime < sp->ats[timecnt - 1])
380
0
              return EINVAL;
381
0
            sp->types[i - 1] = 0;
382
0
            timecnt--;
383
0
          }
384
0
          sp->ats[timecnt++] = attime;
385
0
        }
386
0
        p += stored;
387
0
      }
388
389
0
      timecnt = 0;
390
0
      for (i = 0; i < sp->timecnt; ++i)
391
0
      {
392
0
        unsigned char typ = *p++;
393
394
0
        if (sp->typecnt <= typ)
395
0
          return EINVAL;
396
0
        if (sp->types[i])
397
0
          sp->types[timecnt++] = typ;
398
0
      }
399
0
      sp->timecnt = timecnt;
400
0
      for (i = 0; i < sp->typecnt; ++i)
401
0
      {
402
0
        struct ttinfo *ttisp;
403
0
        unsigned char isdst,
404
0
              desigidx;
405
0
        int_fast32_2s utoff = detzcode(p);
406
407
        /*
408
         * Reject a UT offset equal to -2**31, as it might cause
409
         * trouble both in this file and in callers. Also, it violates
410
         * RFC 9636 section 3.2.
411
         */
412
0
        if (utoff < -TWO_31_MINUS_1)
413
0
          return EINVAL;
414
415
0
        ttisp = &sp->ttis[i];
416
0
        ttisp->tt_utoff = utoff;
417
0
        p += 4;
418
0
        isdst = *p++;
419
0
        if (!(isdst < 2))
420
0
          return EINVAL;
421
0
        ttisp->tt_isdst = isdst;
422
0
        desigidx = *p++;
423
0
        if (!(desigidx < sp->charcnt))
424
0
          return EINVAL;
425
0
        ttisp->tt_desigidx = desigidx;
426
0
      }
427
0
      for (i = 0; i < sp->charcnt; ++i)
428
0
        sp->chars[i] = *p++;
429
430
      /*
431
       * Ensure '\0'-terminated, and make it safe to call ttunspecified
432
       * later.
433
       */
434
0
      memset(&sp->chars[i], 0, CHARS_EXTRA);
435
436
      /* Read leap seconds, discarding those out of pg_time_t range.  */
437
0
      leapcnt = 0;
438
0
      for (i = 0; i < leapcount(sp); i++)
439
0
      {
440
0
        int_fast64_t tr = stored == 4 ? detzcode(p) : detzcode64(p);
441
0
        int_fast32_2s corr = detzcode(p + stored);
442
443
0
        p += stored + 4;
444
445
        /*
446
         * Leap seconds cannot occur before the Epoch, or out of
447
         * order.
448
         */
449
0
        if (tr <= prevtr)
450
0
          return EINVAL;
451
452
        /*
453
         * To avoid other botches in this code, each leap second's
454
         * correction must differ from the previous one's by 1 second
455
         * or less, except that the first correction can be any value;
456
         * these requirements are more generous than RFC 9636, to
457
         * allow future RFC extensions.
458
         */
459
0
        if (!(i == 0
460
0
            || (prevcorr < corr
461
0
              ? corr == prevcorr + 1
462
0
              : (corr == prevcorr
463
0
               || corr == prevcorr - 1))))
464
0
          return EINVAL;
465
0
        prevtr = tr;
466
0
        prevcorr = corr;
467
468
0
        if (tr <= TIME_T_MAX)
469
0
        {
470
0
          struct lsinfo ls;
471
472
0
          ls.ls_trans = tr;
473
0
          ls.ls_corr = corr;
474
0
          set_lsinfo(sp, leapcnt, ls);
475
0
          leapcnt++;
476
0
        }
477
0
      }
478
0
      set_leapcount(sp, leapcnt);
479
480
0
      for (i = 0; i < sp->typecnt; ++i)
481
0
      {
482
0
        struct ttinfo *ttisp;
483
484
0
        ttisp = &sp->ttis[i];
485
0
        if (ttisstdcnt == 0)
486
0
          ttisp->tt_ttisstd = false;
487
0
        else
488
0
        {
489
0
          if (*p != true && *p != false)
490
0
            return EINVAL;
491
0
          ttisp->tt_ttisstd = *p++;
492
0
        }
493
0
      }
494
0
      for (i = 0; i < sp->typecnt; ++i)
495
0
      {
496
0
        struct ttinfo *ttisp;
497
498
0
        ttisp = &sp->ttis[i];
499
0
        if (ttisutcnt == 0)
500
0
          ttisp->tt_ttisut = false;
501
0
        else
502
0
        {
503
0
          if (*p != true && *p != false)
504
0
            return EINVAL;
505
0
          ttisp->tt_ttisut = *p++;
506
0
        }
507
0
      }
508
0
    }
509
510
0
    nread -= p - up->buf;
511
0
    memmove(up->buf, p, nread);
512
513
    /* If this is an old file, we're done.  */
514
0
    if (!version)
515
0
      break;
516
0
  }
517
0
  if ((tzloadflags & TZLOAD_TZSTRING) && nread > 2 &&
518
0
    up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
519
0
    sp->typecnt + 2 <= TZ_MAX_TYPES)
520
0
  {
521
0
    struct state *ts = &lsp->u.st;
522
523
0
    up->buf[nread - 1] = '\0';
524
0
    if (tzparse(&up->buf[1], ts, sp))
525
0
    {
526
527
      /*
528
       * Attempt to reuse existing abbreviations. Without this,
529
       * America/Anchorage would consume 50 bytes for abbreviations, as
530
       * sp->charcnt equals 40 (for LMT AST AWT APT AHST AHDT YST AKDT
531
       * AKST) and ts->charcnt equals 10 (for AKST AKDT).  Reusing means
532
       * sp->charcnt can stay 40 in this example.
533
       */
534
0
      int     gotabbr = 0;
535
0
      int     charcnt = sp->charcnt;
536
537
0
      for (i = 0; i < ts->typecnt; i++)
538
0
      {
539
0
        char     *tsabbr = ts->chars + ts->ttis[i].tt_desigidx;
540
0
        int     j;
541
542
0
        for (j = 0; j < charcnt; j++)
543
0
          if (strcmp(sp->chars + j, tsabbr) == 0)
544
0
          {
545
0
            ts->ttis[i].tt_desigidx = j;
546
0
            gotabbr++;
547
0
            break;
548
0
          }
549
0
        if (!(j < charcnt))
550
0
        {
551
0
          int     tsabbrlen = strnlen(tsabbr, TZ_MAX_CHARS - j);
552
553
0
          if (j + tsabbrlen < TZ_MAX_CHARS)
554
0
          {
555
0
            char     *cp = sp->chars + j;
556
557
0
            memcpy(cp, tsabbr, tsabbrlen);
558
0
            cp += tsabbrlen;
559
0
            *cp = '\0';
560
0
            charcnt = j + tsabbrlen + 1;
561
0
            ts->ttis[i].tt_desigidx = j;
562
0
            gotabbr++;
563
0
          }
564
0
        }
565
0
      }
566
0
      if (gotabbr == ts->typecnt)
567
0
      {
568
0
        sp->charcnt = charcnt;
569
570
        /*
571
         * Ignore any trailing, no-op transitions generated by zic as
572
         * they don't help here and can run afoul of bugs in zic 2016j
573
         * or earlier.
574
         */
575
0
        while (1 < sp->timecnt
576
0
             && (sp->types[sp->timecnt - 1]
577
0
               == sp->types[sp->timecnt - 2]))
578
0
          sp->timecnt--;
579
580
0
        sp->goahead = ts->goahead;
581
582
0
        for (i = 0; i < ts->timecnt; i++)
583
0
        {
584
0
          pg_time_t t = ts->ats[i];
585
586
0
          if (increment_overflow_time(&t, leapcorr(sp, t))
587
0
            || (0 < sp->timecnt
588
0
              && t <= sp->ats[sp->timecnt - 1]))
589
0
            continue;
590
0
          if (TZ_MAX_TIMES <= sp->timecnt)
591
0
          {
592
0
            sp->goahead = false;
593
0
            break;
594
0
          }
595
0
          sp->ats[sp->timecnt] = t;
596
0
          sp->types[sp->timecnt] = (sp->typecnt
597
0
                        + ts->types[i]);
598
0
          sp->timecnt++;
599
0
        }
600
0
        for (i = 0; i < ts->typecnt; i++)
601
0
          sp->ttis[sp->typecnt++] = ts->ttis[i];
602
0
      }
603
0
    }
604
0
  }
605
0
  if (sp->typecnt == 0)
606
0
    return EINVAL;
607
608
0
  return 0;
609
0
}
610
611
/*
612
 * Load tz data from the file named NAME into *SP.  Respect TZLOADFLAGS.
613
 * Return 0 on success, an errno value on failure.
614
 * PG: If "canonname" is not NULL, then on success the canonical spelling of
615
 * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
616
 */
617
static int
618
tzload(char const *name, char *canonname, struct state *sp, char tzloadflags)
619
0
{
620
  /*
621
   * PG: by default, we allocate the "union local_storage" space via malloc,
622
   * since it's about 70kB which seems like a lot of stack space, and we're
623
   * hardly concerned about an extra malloc/free cycle here.  But under
624
   * USE_VALGRIND, put the variable on the stack, to intentionally increase
625
   * the amount of stack space allocated in the postmaster.  This prevents a
626
   * bad interaction between Valgrind and Python 3.14, for reasons that are
627
   * obscure and most likely no fault of ours.  Also note that unlike
628
   * upstream tzcode, our version of tzloadbody never reallocates *lspp.
629
   */
630
0
  int     r;
631
0
  union local_storage *lsp;
632
#ifdef USE_VALGRIND
633
  union local_storage ls;
634
635
  lsp = &ls;
636
#else
637
0
  lsp = malloc(sizeof *lsp);
638
0
  if (!lsp)
639
0
    return errno;
640
0
#endif
641
0
  r = tzloadbody(name, canonname, sp, tzloadflags, &lsp);
642
0
#ifndef USE_VALGRIND
643
0
  free(lsp);
644
0
#endif
645
0
  return r;
646
0
}
647
648
static const int mon_lengths[2][MONSPERYEAR] = {
649
  {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
650
  {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
651
};
652
653
static const int year_lengths[2] = {
654
  DAYSPERNYEAR, DAYSPERLYEAR
655
};
656
657
/* Is C an ASCII digit?  */
658
static bool
659
is_digit(char c)
660
12
{
661
12
  return '0' <= c && c <= '9';
662
12
}
663
664
/*
665
 * Given a pointer into a timezone string, scan until a character that is not
666
 * a valid character in a time zone abbreviation is found.
667
 * Return a pointer to that character.
668
 */
669
670
ATTRIBUTE_PURE_114833 static const char *
671
getzname(const char *strp)
672
2
{
673
2
  char    c;
674
675
8
  while ((c = *strp) != '\0' && !is_digit(c) && c != ',' && c != '-' &&
676
6
       c != '+')
677
6
    ++strp;
678
2
  return strp;
679
2
}
680
681
/*
682
 * Given a pointer into an extended timezone string, scan until the ending
683
 * delimiter of the time zone abbreviation is located.
684
 * Return a pointer to the delimiter.
685
 *
686
 * As with getzname above, the legal character set is actually quite
687
 * restricted, with other characters producing undefined results.
688
 * We don't do any checking here; checking is done later in common-case code.
689
 */
690
691
ATTRIBUTE_PURE_114833 static const char *
692
getqzname(const char *strp, const int delim)
693
0
{
694
0
  int     c;
695
696
0
  while ((c = *strp) != '\0' && c != delim)
697
0
    ++strp;
698
0
  return strp;
699
0
}
700
701
/*
702
 * Given a pointer into a timezone string, extract a number from that string.
703
 * Check that the number is within a specified range; if it is not, return
704
 * NULL.
705
 * Otherwise, return a pointer to the first character not part of the number.
706
 */
707
708
static const char *
709
getnum(const char *strp, int *const nump, const int min, const int max)
710
2
{
711
2
  char    c;
712
2
  int     num;
713
714
2
  if (strp == NULL || !is_digit(c = *strp))
715
0
    return NULL;
716
2
  num = 0;
717
2
  do
718
2
  {
719
2
    num = num * 10 + (c - '0');
720
2
    if (num > max)
721
0
      return NULL;   /* illegal value */
722
2
    c = *++strp;
723
2
  } while (is_digit(c));
724
2
  if (num < min)
725
0
    return NULL;     /* illegal value */
726
2
  *nump = num;
727
2
  return strp;
728
2
}
729
730
/*
731
 * Given a pointer into a timezone string, extract a number of seconds,
732
 * in hh[:mm[:ss]] form, from the string.
733
 * If any error occurs, return NULL.
734
 * Otherwise, return a pointer to the first character not part of the number
735
 * of seconds.
736
 */
737
738
static const char *
739
getsecs(const char *strp, int_fast32_t *const secsp)
740
2
{
741
2
  int     num;
742
2
  int_fast32_t secsperhour = SECSPERHOUR;
743
744
  /*
745
   * 'HOURSPERDAY * DAYSPERWEEK - 1' allows quasi-POSIX rules like
746
   * "M10.4.6/26", which does not conform to POSIX, but which specifies the
747
   * equivalent of "02:00 on the first Sunday on or after 23 Oct".
748
   */
749
2
  strp = getnum(strp, &num, 0, HOURSPERDAY * DAYSPERWEEK - 1);
750
2
  if (strp == NULL)
751
0
    return NULL;
752
2
  *secsp = num * secsperhour;
753
2
  if (*strp == ':')
754
0
  {
755
0
    ++strp;
756
0
    strp = getnum(strp, &num, 0, MINSPERHOUR - 1);
757
0
    if (strp == NULL)
758
0
      return NULL;
759
0
    *secsp += num * SECSPERMIN;
760
0
    if (*strp == ':')
761
0
    {
762
0
      ++strp;
763
      /* 'SECSPERMIN' allows for leap seconds.  */
764
0
      strp = getnum(strp, &num, 0, SECSPERMIN);
765
0
      if (strp == NULL)
766
0
        return NULL;
767
0
      *secsp += num;
768
0
    }
769
0
  }
770
2
  return strp;
771
2
}
772
773
/*
774
 * Given a pointer into a timezone string, extract an offset, in
775
 * [+-]hh[:mm[:ss]] form, from the string.
776
 * If any error occurs, return NULL.
777
 * Otherwise, return a pointer to the first character not part of the time.
778
 */
779
780
static const char *
781
getoffset(const char *strp, int_fast32_t *const offsetp)
782
2
{
783
2
  bool    neg = false;
784
785
2
  if (*strp == '-')
786
0
  {
787
0
    neg = true;
788
0
    ++strp;
789
0
  }
790
2
  else if (*strp == '+')
791
0
    ++strp;
792
2
  strp = getsecs(strp, offsetp);
793
2
  if (strp == NULL)
794
0
    return NULL;     /* illegal time */
795
2
  if (neg)
796
0
    *offsetp = -*offsetp;
797
2
  return strp;
798
2
}
799
800
/*
801
 * Given a pointer into a timezone string, extract a rule in the form
802
 * date[/time]. See POSIX Base Definitions section 8.3 variable TZ
803
 * for the format of "date" and "time".
804
 * If a valid rule is not found, return NULL.
805
 * Otherwise, return a pointer to the first character not part of the rule.
806
 */
807
808
static const char *
809
getrule(const char *strp, struct rule *const rulep)
810
0
{
811
0
  if (*strp == 'J')
812
0
  {
813
    /*
814
     * Julian day.
815
     */
816
0
    rulep->r_type = JULIAN_DAY;
817
0
    ++strp;
818
0
    strp = getnum(strp, &rulep->r_day, 1, DAYSPERNYEAR);
819
0
  }
820
0
  else if (*strp == 'M')
821
0
  {
822
    /*
823
     * Month, week, day.
824
     */
825
0
    rulep->r_type = MONTH_NTH_DAY_OF_WEEK;
826
0
    ++strp;
827
0
    strp = getnum(strp, &rulep->r_mon, 1, MONSPERYEAR);
828
0
    if (strp == NULL)
829
0
      return NULL;
830
0
    if (*strp++ != '.')
831
0
      return NULL;
832
0
    strp = getnum(strp, &rulep->r_week, 1, 5);
833
0
    if (strp == NULL)
834
0
      return NULL;
835
0
    if (*strp++ != '.')
836
0
      return NULL;
837
0
    strp = getnum(strp, &rulep->r_day, 0, DAYSPERWEEK - 1);
838
0
  }
839
0
  else if (is_digit(*strp))
840
0
  {
841
    /*
842
     * Day of year.
843
     */
844
0
    rulep->r_type = DAY_OF_YEAR;
845
0
    strp = getnum(strp, &rulep->r_day, 0, DAYSPERLYEAR - 1);
846
0
  }
847
0
  else
848
0
    return NULL;     /* invalid format */
849
0
  if (strp == NULL)
850
0
    return NULL;
851
0
  if (*strp == '/')
852
0
  {
853
    /*
854
     * Time specified.
855
     */
856
0
    ++strp;
857
0
    strp = getoffset(strp, &rulep->r_time);
858
0
  }
859
0
  else
860
0
    rulep->r_time = 2 * SECSPERHOUR; /* default = 2:00:00 */
861
0
  return strp;
862
0
}
863
864
/*
865
 * Given a year, a rule, and the offset from UT at the time that rule takes
866
 * effect, calculate the year-relative time that rule takes effect.
867
 */
868
869
static int_fast32_t
870
transtime(const int year, const struct rule *const rulep,
871
      const int_fast32_t offset)
872
0
{
873
0
  bool    leapyear;
874
0
  int_fast32_t value;
875
0
  int     i;
876
0
  int     d,
877
0
        m1,
878
0
        yy0,
879
0
        yy1,
880
0
        yy2,
881
0
        dow;
882
883
0
  leapyear = isleap(year);
884
0
  switch (rulep->r_type)
885
0
  {
886
887
0
    case JULIAN_DAY:
888
889
      /*
890
       * Jn - Julian day, 1 == January 1, 60 == March 1 even in leap
891
       * years. In non-leap years, or if the day number is 59 or less,
892
       * just add SECSPERDAY times the day number-1 to the time of
893
       * January 1, midnight, to get the day.
894
       */
895
0
      value = (rulep->r_day - 1) * SECSPERDAY;
896
0
      if (leapyear && rulep->r_day >= 60)
897
0
        value += SECSPERDAY;
898
0
      break;
899
900
0
    case DAY_OF_YEAR:
901
902
      /*
903
       * n - day of year. Just add SECSPERDAY times the day number to
904
       * the time of January 1, midnight, to get the day.
905
       */
906
0
      value = rulep->r_day * SECSPERDAY;
907
0
      break;
908
909
0
    case MONTH_NTH_DAY_OF_WEEK:
910
911
      /*
912
       * Mm.n.d - nth "dth day" of month m.
913
       */
914
915
      /*
916
       * Use Zeller's Congruence to get day-of-week of first day of
917
       * month.
918
       */
919
0
      m1 = (rulep->r_mon + 9) % 12 + 1;
920
0
      yy0 = (rulep->r_mon <= 2) ? (year - 1) : year;
921
0
      yy1 = yy0 / 100;
922
0
      yy2 = yy0 % 100;
923
0
      dow = ((26 * m1 - 2) / 10 +
924
0
           1 + yy2 + yy2 / 4 + yy1 / 4 - 2 * yy1) % 7;
925
0
      if (dow < 0)
926
0
        dow += DAYSPERWEEK;
927
928
      /*
929
       * "dow" is the day-of-week of the first day of the month. Get the
930
       * day-of-month (zero-origin) of the first "dow" day of the month.
931
       */
932
0
      d = rulep->r_day - dow;
933
0
      if (d < 0)
934
0
        d += DAYSPERWEEK;
935
0
      for (i = 1; i < rulep->r_week; ++i)
936
0
      {
937
0
        if (d + DAYSPERWEEK >=
938
0
          mon_lengths[leapyear][rulep->r_mon - 1])
939
0
          break;
940
0
        d += DAYSPERWEEK;
941
0
      }
942
943
      /*
944
       * "d" is the day-of-month (zero-origin) of the day we want.
945
       */
946
0
      value = d * SECSPERDAY;
947
0
      for (i = 0; i < rulep->r_mon - 1; ++i)
948
0
        value += mon_lengths[leapyear][i] * SECSPERDAY;
949
0
      break;
950
951
0
    default:
952
0
      unreachable();
953
0
  }
954
955
  /*
956
   * "value" is the year-relative time of 00:00:00 UT on the day in
957
   * question. To get the year-relative time of the specified local time on
958
   * that day, add the transition time and the current offset from UT.
959
   */
960
0
  return value + rulep->r_time + offset;
961
0
}
962
963
/*
964
 * Given a POSIX.1 proleptic TZ string, fill in the rule tables as
965
 * appropriate.
966
 */
967
968
static bool
969
tzparse(const char *name, struct state *sp, struct state const *basep)
970
2
{
971
2
  const char *stdname;
972
2
  const char *dstname = NULL;
973
2
  int_fast32_t stdoffset;
974
2
  int_fast32_t dstoffset;
975
2
  char     *cp;
976
2
  ptrdiff_t stdlen,
977
2
        dstlen,
978
2
        charcnt;
979
2
  pg_time_t atlo = TIME_T_MIN,
980
2
        leaplo = TIME_T_MIN;
981
982
2
  stdname = name;
983
2
  if (*name == '<')
984
0
  {
985
0
    name++;
986
0
    stdname = name;
987
0
    name = getqzname(name, '>');
988
0
    if (*name != '>')
989
0
      return false;
990
0
    stdlen = name - stdname;
991
0
    name++;
992
0
  }
993
2
  else
994
2
  {
995
2
    name = getzname(name);
996
2
    stdlen = name - stdname;
997
2
  }
998
2
  if (stdlen > TZNAME_MAXIMUM)  /* allow empty STD abbrev, unlike IANA */
999
0
    return false;
1000
2
  name = getoffset(name, &stdoffset);
1001
2
  if (name == NULL)
1002
0
    return false;
1003
2
  charcnt = stdlen + 1;
1004
2
  if (basep)
1005
0
  {
1006
0
    if (0 < basep->timecnt)
1007
0
      atlo = basep->ats[basep->timecnt - 1];
1008
0
    set_leapcount(sp, leapcount(basep));
1009
0
    if (0 < leapcount(sp))
1010
0
    {
1011
0
      int     i;
1012
1013
0
      for (i = 0; i < leapcount(sp); i++)
1014
0
        set_lsinfo(sp, i, lsinfo(basep, i));
1015
0
      leaplo = lsinfo(sp, leapcount(sp) - 1).ls_trans;
1016
0
    }
1017
0
  }
1018
2
  else
1019
2
    set_leapcount(sp, 0); /* So, we're off a little.  */
1020
2
  sp->goback = sp->goahead = false;
1021
2
  if (*name != '\0')
1022
0
  {
1023
0
    struct rule start,
1024
0
          end;
1025
0
    int     year,
1026
0
          yearbeg,
1027
0
          yearlim,
1028
0
          timecnt;
1029
0
    pg_time_t janfirst;
1030
0
    int_fast32_t janoffset = 0;
1031
1032
0
    if (*name == '<')
1033
0
    {
1034
0
      dstname = ++name;
1035
0
      name = getqzname(name, '>');
1036
0
      if (*name != '>')
1037
0
        return false;
1038
0
      dstlen = name - dstname;
1039
0
      name++;
1040
0
    }
1041
0
    else
1042
0
    {
1043
0
      dstname = name;
1044
0
      name = getzname(name);
1045
0
      dstlen = name - dstname;  /* length of DST abbr. */
1046
0
    }
1047
0
    if (!(0 < dstlen && dstlen <= TZNAME_MAXIMUM))
1048
0
      return false;
1049
0
    charcnt += dstlen + 1;
1050
0
    if (*name != '\0' && *name != ',' && *name != ';')
1051
0
    {
1052
0
      name = getoffset(name, &dstoffset);
1053
0
      if (name == NULL)
1054
0
        return false;
1055
0
    }
1056
0
    else
1057
0
      dstoffset = stdoffset - SECSPERHOUR;
1058
1059
0
    if (*name == '\0')
1060
0
      name = TZDEFRULESTRING;
1061
0
    if (!(*name == ',' || *name == ';'))
1062
0
      return false;
1063
1064
0
    name = getrule(name + 1, &start);
1065
0
    if (!name)
1066
0
      return false;
1067
0
    if (*name++ != ',')
1068
0
      return false;
1069
0
    name = getrule(name, &end);
1070
0
    if (!name || *name)
1071
0
      return false;
1072
0
    sp->typecnt = 2;    /* standard time and DST */
1073
1074
    /*
1075
     * Two transitions per year, from EPOCH_YEAR forward.
1076
     */
1077
0
    init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1078
0
    init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1079
0
    timecnt = 0;
1080
0
    janfirst = 0;
1081
0
    yearbeg = EPOCH_YEAR;
1082
1083
0
    do
1084
0
    {
1085
0
      int_fast32_t yearsecs
1086
0
      = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1087
0
      pg_time_t janfirst1 = janfirst;
1088
1089
0
      yearbeg--;
1090
0
      if (increment_overflow_time(&janfirst1, -yearsecs))
1091
0
      {
1092
0
        janoffset = -yearsecs;
1093
0
        break;
1094
0
      }
1095
0
      janfirst = janfirst1;
1096
0
    } while (atlo < janfirst
1097
0
         && EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1098
1099
0
    while (true)
1100
0
    {
1101
0
      int_fast32_t yearsecs
1102
0
      = year_lengths[isleap(yearbeg)] * SECSPERDAY;
1103
0
      int     yearbeg1 = yearbeg;
1104
0
      pg_time_t janfirst1 = janfirst;
1105
1106
0
      if (increment_overflow_time(&janfirst1, yearsecs)
1107
0
        || increment_overflow(&yearbeg1, 1)
1108
0
        || atlo <= janfirst1)
1109
0
        break;
1110
0
      yearbeg = yearbeg1;
1111
0
      janfirst = janfirst1;
1112
0
    }
1113
1114
0
    yearlim = yearbeg;
1115
0
    if (increment_overflow(&yearlim, years_of_observations))
1116
0
      yearlim = INT_MAX;
1117
0
    for (year = yearbeg; year < yearlim; year++)
1118
0
    {
1119
0
      int_fast32_t
1120
0
            starttime = transtime(year, &start, stdoffset),
1121
0
            endtime = transtime(year, &end, dstoffset),
1122
0
            yearsecs = year_lengths[isleap(year)] * SECSPERDAY;
1123
0
      bool    reversed = endtime < starttime;
1124
1125
0
      if (reversed)
1126
0
      {
1127
0
        int_fast32_t swap = starttime;
1128
1129
0
        starttime = endtime;
1130
0
        endtime = swap;
1131
0
      }
1132
0
      if (reversed
1133
0
        || (starttime < endtime
1134
0
          && endtime - starttime < yearsecs))
1135
0
      {
1136
0
        if (TZ_MAX_TIMES - 2 < timecnt)
1137
0
          break;
1138
0
        sp->ats[timecnt] = janfirst;
1139
0
        if (!increment_overflow_time(&sp->ats[timecnt],
1140
0
                       janoffset + starttime)
1141
0
          && atlo <= sp->ats[timecnt])
1142
0
          sp->types[timecnt++] = !reversed;
1143
0
        sp->ats[timecnt] = janfirst;
1144
0
        if (!increment_overflow_time(&sp->ats[timecnt],
1145
0
                       janoffset + endtime)
1146
0
          && atlo <= sp->ats[timecnt])
1147
0
        {
1148
0
          sp->types[timecnt++] = reversed;
1149
0
        }
1150
0
      }
1151
0
      if (endtime < leaplo)
1152
0
      {
1153
0
        yearlim = year;
1154
0
        if (increment_overflow(&yearlim, years_of_observations))
1155
0
          yearlim = INT_MAX;
1156
0
      }
1157
0
      if (increment_overflow_time(&janfirst, janoffset + yearsecs))
1158
0
        break;
1159
0
      janoffset = 0;
1160
0
    }
1161
0
    sp->timecnt = timecnt;
1162
0
    if (!timecnt)
1163
0
    {
1164
0
      sp->ttis[0] = sp->ttis[1];
1165
0
      sp->typecnt = 1;  /* Perpetual DST.  */
1166
0
    }
1167
0
    else if (years_of_observations <= year - yearbeg)
1168
0
      sp->goback = sp->goahead = true;
1169
0
  }
1170
2
  else
1171
2
  {
1172
2
    dstlen = 0;
1173
2
    sp->typecnt = 1;    /* only standard time */
1174
2
    sp->timecnt = 0;
1175
2
    init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1176
2
  }
1177
2
  sp->charcnt = charcnt;
1178
2
  cp = sp->chars;
1179
2
  memcpy(cp, stdname, stdlen);
1180
2
  cp += stdlen;
1181
2
  *cp++ = '\0';
1182
2
  if (dstlen != 0)
1183
0
  {
1184
0
    memcpy(cp, dstname, dstlen);
1185
0
    cp += dstlen;
1186
0
    *cp = '\0';
1187
0
  }
1188
2
  return true;
1189
2
}
1190
1191
static void
1192
gmtload(struct state *const sp)
1193
2
{
1194
  /* PG: for historical compatibility, use "GMT" not "UTC" as TZ abbrev */
1195
2
  tzparse("GMT0", sp, NULL);
1196
2
}
1197
1198
1199
/*
1200
 * The easy way to behave "as if no library function calls" localtime
1201
 * is to not call it, so we drop its guts into "localsub", which can be
1202
 * freely called. (And no, the PANS doesn't require the above behavior,
1203
 * but it *is* desirable.)
1204
 */
1205
static struct pg_tm *
1206
localsub(struct state const *sp, pg_time_t const *timep,
1207
     struct pg_tm *const tmp)
1208
5.03k
{
1209
5.03k
  const struct ttinfo *ttisp;
1210
5.03k
  int     i;
1211
5.03k
  struct pg_tm *result;
1212
5.03k
  const pg_time_t t = *timep;
1213
1214
5.03k
  if (sp == NULL)
1215
0
    return gmtsub(timep, 0, tmp);
1216
5.03k
  if ((sp->goback && t < sp->ats[0]) ||
1217
5.03k
    (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1218
0
  {
1219
0
    pg_time_t newt;
1220
0
    pg_time_t seconds;
1221
0
    pg_time_t years;
1222
1223
0
    if (t < sp->ats[0])
1224
0
      seconds = sp->ats[0] - t;
1225
0
    else
1226
0
      seconds = t - sp->ats[sp->timecnt - 1];
1227
0
    --seconds;
1228
1229
    /*
1230
     * Beware integer overflow, as SECONDS might be close to the maximum
1231
     * pg_time_t.
1232
     */
1233
0
    years = seconds / SECSPERREPEAT * YEARSPERREPEAT;
1234
0
    seconds = years * AVGSECSPERYEAR;
1235
0
    years += YEARSPERREPEAT;
1236
0
    if (t < sp->ats[0])
1237
0
      newt = t + seconds + SECSPERREPEAT;
1238
0
    else
1239
0
      newt = t - seconds - SECSPERREPEAT;
1240
1241
0
    if (newt < sp->ats[0] ||
1242
0
      newt > sp->ats[sp->timecnt - 1])
1243
0
      return NULL;   /* "cannot happen" */
1244
0
    result = localsub(sp, &newt, tmp);
1245
0
    if (result)
1246
0
    {
1247
0
#if defined ckd_add && defined ckd_sub
1248
0
      if (t < sp->ats[0]
1249
0
        ? ckd_sub(&result->tm_year,
1250
0
              result->tm_year, years)
1251
0
        : ckd_add(&result->tm_year,
1252
0
              result->tm_year, years))
1253
0
        return NULL;
1254
#else
1255
      int_fast64_t newy;
1256
1257
      newy = result->tm_year;
1258
      if (t < sp->ats[0])
1259
        newy -= years;
1260
      else
1261
        newy += years;
1262
      if (!(INT_MIN <= newy && newy <= INT_MAX))
1263
        return NULL;
1264
      result->tm_year = newy;
1265
#endif
1266
0
    }
1267
0
    return result;
1268
0
  }
1269
5.03k
  if (sp->timecnt == 0 || t < sp->ats[0])
1270
5.03k
  {
1271
5.03k
    i = 0;
1272
5.03k
  }
1273
0
  else
1274
0
  {
1275
0
    int     lo = 1;
1276
0
    int     hi = sp->timecnt;
1277
1278
0
    while (lo < hi)
1279
0
    {
1280
0
      int     mid = (lo + hi) >> 1;
1281
1282
0
      if (t < sp->ats[mid])
1283
0
        hi = mid;
1284
0
      else
1285
0
        lo = mid + 1;
1286
0
    }
1287
0
    i = sp->types[lo - 1];
1288
0
  }
1289
5.03k
  ttisp = &sp->ttis[i];
1290
1291
  /*
1292
   * To get (wrong) behavior that's compatible with System V Release 2.0
1293
   * you'd replace the statement below with t += ttisp->tt_utoff;
1294
   * timesub(&t, 0, sp, tmp);
1295
   */
1296
5.03k
  result = timesub(&t, ttisp->tt_utoff, sp, tmp);
1297
5.03k
  if (result)
1298
5.03k
  {
1299
5.03k
    result->tm_isdst = ttisp->tt_isdst;
1300
5.03k
#ifdef TM_ZONE
1301
5.03k
    result->TM_ZONE = UNCONST(&sp->chars[ttisp->tt_desigidx]);
1302
5.03k
#endif
1303
5.03k
  }
1304
5.03k
  return result;
1305
5.03k
}
1306
1307
1308
struct pg_tm *
1309
pg_localtime(const pg_time_t *timep, const pg_tz *tz)
1310
5.03k
{
1311
5.03k
  return localsub(&tz->state, timep, &tm);
1312
5.03k
}
1313
1314
1315
/*
1316
 * gmtsub is to gmtime as localsub is to localtime.
1317
 *
1318
 * PG: except we have a private "struct state" for GMT, so no sp is passed in.
1319
 */
1320
1321
static struct pg_tm *
1322
gmtsub(pg_time_t const *timep,
1323
     int_fast32_t offset, struct pg_tm *tmp)
1324
0
{
1325
0
  struct pg_tm *result;
1326
1327
  /* GMT timezone state data is kept here */
1328
0
  static struct state *gmtptr = NULL;
1329
1330
0
  if (gmtptr == NULL)
1331
0
  {
1332
    /* Allocate on first use */
1333
0
    gmtptr = (struct state *) malloc(sizeof(struct state));
1334
0
    if (gmtptr == NULL)
1335
0
      return NULL;   /* errno should be set by malloc */
1336
0
    gmtload(gmtptr);
1337
0
  }
1338
1339
0
  result = timesub(timep, offset, gmtptr, tmp);
1340
0
#ifdef TM_ZONE
1341
1342
  /*
1343
   * Could get fancy here and deliver something such as "+xx" or "-xx" if
1344
   * offset is non-zero, but this is no time for a treasure hunt.
1345
   */
1346
0
  tmp->TM_ZONE = UNCONST(offset ? wildabbr
1347
0
               : gmtptr->chars);
1348
0
#endif              /* defined TM_ZONE */
1349
0
  return result;
1350
0
}
1351
1352
struct pg_tm *
1353
pg_gmtime(const pg_time_t *timep)
1354
0
{
1355
0
  return gmtsub(timep, 0, &tm);
1356
0
}
1357
1358
/*
1359
 * Return the number of leap years through the end of the given year
1360
 * where, to make the math easy, the answer for year zero is defined as zero.
1361
 */
1362
1363
static pg_time_t
1364
leaps_thru_end_of_nonneg(pg_time_t y)
1365
20.1k
{
1366
20.1k
  return y / 4 - y / 100 + y / 400;
1367
20.1k
}
1368
1369
static pg_time_t
1370
leaps_thru_end_of(pg_time_t y)
1371
20.1k
{
1372
20.1k
  return (y < 0
1373
20.1k
      ? -1 - leaps_thru_end_of_nonneg(-1 - y)
1374
20.1k
      : leaps_thru_end_of_nonneg(y));
1375
20.1k
}
1376
1377
static struct pg_tm *
1378
timesub(const pg_time_t *timep, int_fast32_t offset,
1379
    const struct state *sp, struct pg_tm *tmp)
1380
5.03k
{
1381
5.03k
  pg_time_t tdays;
1382
5.03k
  const int  *ip;
1383
5.03k
  int_fast32_2s corr;
1384
5.03k
  int     i;
1385
5.03k
  int_fast32_t idays,
1386
5.03k
        rem,
1387
5.03k
        dayoff,
1388
5.03k
        dayrem;
1389
5.03k
  pg_time_t y;
1390
1391
  /*
1392
   * If less than SECSPERMIN, the number of seconds since the most recent
1393
   * positive leap second; otherwise, do not add 1 to localtime tm_sec
1394
   * because of leap seconds.
1395
   */
1396
5.03k
  pg_time_t secs_since_posleap = SECSPERMIN;
1397
1398
5.03k
  corr = 0;
1399
5.03k
  i = sp ? leapcount(sp) : 0;
1400
5.03k
  while (--i >= 0)
1401
0
  {
1402
0
    struct lsinfo ls = lsinfo(sp, i);
1403
1404
0
    if (ls.ls_trans <= *timep)
1405
0
    {
1406
0
      corr = ls.ls_corr;
1407
0
      if ((i == 0 ? 0 : lsinfo(sp, i - 1).ls_corr) < corr)
1408
0
        secs_since_posleap = *timep - ls.ls_trans;
1409
0
      break;
1410
0
    }
1411
0
  }
1412
1413
  /*
1414
   * Calculate the year, avoiding integer overflow even if pg_time_t is
1415
   * unsigned.
1416
   */
1417
5.03k
  tdays = *timep / SECSPERDAY;
1418
5.03k
  rem = *timep % SECSPERDAY;
1419
5.03k
  rem += offset % SECSPERDAY - corr % SECSPERDAY + 3 * SECSPERDAY;
1420
5.03k
  dayoff = offset / SECSPERDAY - corr / SECSPERDAY + rem / SECSPERDAY - 3;
1421
5.03k
  rem %= SECSPERDAY;
1422
1423
  /*
1424
   * y = (EPOCH_YEAR + floor((tdays + dayoff) / DAYSPERREPEAT) *
1425
   * YEARSPERREPEAT), sans overflow.  But calculate against 1570 (EPOCH_YEAR
1426
   * - YEARSPERREPEAT) instead of against 1970 so that things work for
1427
   * localtime values before 1970 when pg_time_t is unsigned.
1428
   */
1429
5.03k
  dayrem = tdays % DAYSPERREPEAT;
1430
5.03k
  dayrem += dayoff % DAYSPERREPEAT;
1431
5.03k
  y = (EPOCH_YEAR - YEARSPERREPEAT
1432
5.03k
     + ((1 + dayoff / DAYSPERREPEAT + dayrem / DAYSPERREPEAT
1433
5.03k
       - ((dayrem % DAYSPERREPEAT) < 0)
1434
5.03k
       + tdays / DAYSPERREPEAT)
1435
5.03k
      * YEARSPERREPEAT));
1436
  /* idays = (tdays + dayoff) mod DAYSPERREPEAT, sans overflow.  */
1437
5.03k
  idays = tdays % DAYSPERREPEAT;
1438
5.03k
  idays += dayoff % DAYSPERREPEAT + 2 * DAYSPERREPEAT;
1439
5.03k
  idays %= DAYSPERREPEAT;
1440
  /* Increase Y and decrease IDAYS until IDAYS is in range for Y.  */
1441
10.0k
  while (year_lengths[isleap(y)] <= idays)
1442
5.04k
  {
1443
5.04k
    int     tdelta = idays / DAYSPERLYEAR;
1444
5.04k
    int_fast32_t ydelta = tdelta + !tdelta;
1445
5.04k
    pg_time_t newy = y + ydelta;
1446
5.04k
    int     leapdays;
1447
1448
5.04k
    leapdays = leaps_thru_end_of(newy - 1) -
1449
5.04k
      leaps_thru_end_of(y - 1);
1450
5.04k
    idays -= ydelta * DAYSPERNYEAR;
1451
5.04k
    idays -= leapdays;
1452
5.04k
    y = newy;
1453
5.04k
  }
1454
1455
5.03k
#ifdef ckd_add
1456
5.03k
  if (ckd_add(&tmp->tm_year, y, -TM_YEAR_BASE))
1457
0
  {
1458
0
    errno = EOVERFLOW;
1459
0
    return NULL;
1460
0
  }
1461
#else
1462
  if (!TYPE_SIGNED(pg_time_t) && y < TM_YEAR_BASE)
1463
  {
1464
    int     signed_y = y;
1465
1466
    tmp->tm_year = signed_y - TM_YEAR_BASE;
1467
  }
1468
  else if ((!TYPE_SIGNED(pg_time_t) || INT_MIN + TM_YEAR_BASE <= y)
1469
       && y - TM_YEAR_BASE <= INT_MAX)
1470
    tmp->tm_year = y - TM_YEAR_BASE;
1471
  else
1472
  {
1473
    errno = EOVERFLOW;
1474
    return NULL;
1475
  }
1476
#endif
1477
5.03k
  tmp->tm_yday = idays;
1478
1479
  /*
1480
   * The "extra" mods below avoid overflow problems.
1481
   */
1482
5.03k
  tmp->tm_wday = (TM_WDAY_BASE
1483
5.03k
          + ((tmp->tm_year % DAYSPERWEEK)
1484
5.03k
             * (DAYSPERNYEAR % DAYSPERWEEK))
1485
5.03k
          + leaps_thru_end_of(y - 1)
1486
5.03k
          - leaps_thru_end_of(TM_YEAR_BASE - 1)
1487
5.03k
          + idays);
1488
5.03k
  tmp->tm_wday %= DAYSPERWEEK;
1489
5.03k
  if (tmp->tm_wday < 0)
1490
0
    tmp->tm_wday += DAYSPERWEEK;
1491
5.03k
  tmp->tm_hour = rem / SECSPERHOUR;
1492
5.03k
  rem %= SECSPERHOUR;
1493
5.03k
  tmp->tm_min = rem / SECSPERMIN;
1494
5.03k
  tmp->tm_sec = rem % SECSPERMIN;
1495
1496
  /*
1497
   * Use "... ??:??:60" at the end of the localtime minute containing the
1498
   * second just before the positive leap second.
1499
   */
1500
5.03k
  tmp->tm_sec += secs_since_posleap <= tmp->tm_sec;
1501
1502
5.03k
  ip = mon_lengths[isleap(y)];
1503
40.2k
  for (tmp->tm_mon = 0; idays >= ip[tmp->tm_mon]; ++(tmp->tm_mon))
1504
35.2k
    idays -= ip[tmp->tm_mon];
1505
5.03k
  tmp->tm_mday = idays + 1;
1506
5.03k
  tmp->tm_isdst = 0;
1507
5.03k
#ifdef TM_GMTOFF
1508
5.03k
  tmp->TM_GMTOFF = offset;
1509
5.03k
#endif              /* defined TM_GMTOFF */
1510
5.03k
  return tmp;
1511
5.03k
}
1512
1513
/*
1514
 * Adapted from code provided by Robert Elz, who writes:
1515
 *  The "best" way to do mktime I think is based on an idea of Bob
1516
 *  Kridle's (so its said...) from a long time ago.
1517
 *  It does a binary search of the pg_time_t space. Since pg_time_t's are
1518
 *  just 32 bits, its a max of 32 iterations (even at 64 bits it
1519
 *  would still be very reasonable).
1520
 */
1521
1522
#ifndef WRONG
1523
#define WRONG (-1)
1524
#endif              /* !defined WRONG */
1525
1526
/*
1527
 * Normalize logic courtesy Paul Eggert.
1528
 */
1529
1530
static bool
1531
increment_overflow(int *ip, int j)
1532
0
{
1533
0
#ifdef ckd_add
1534
0
  return ckd_add(ip, *ip, j);
1535
#else
1536
  int const i = *ip;
1537
1538
  /*----------
1539
   * If i >= 0 there can only be overflow if i + j > INT_MAX
1540
   * or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
1541
   * If i < 0 there can only be overflow if i + j < INT_MIN
1542
   * or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
1543
   *----------
1544
   */
1545
  if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
1546
    return true;
1547
  *ip += j;
1548
  return false;
1549
#endif
1550
0
}
1551
1552
static bool
1553
increment_overflow_time(pg_time_t *tp, int_fast32_2s j)
1554
0
{
1555
0
#ifdef ckd_add
1556
0
  return ckd_add(tp, *tp, j);
1557
#else
1558
  /*----------
1559
   * This is like
1560
   * 'if (! (TIME_T_MIN <= *tp + j && *tp + j <= TIME_T_MAX)) ...',
1561
   * except that it does the right thing even if *tp + j would overflow.
1562
   *----------
1563
   */
1564
  if (!(j < 0
1565
      ? (TYPE_SIGNED(pg_time_t) ? TIME_T_MIN - j <= *tp : -1 - j < *tp)
1566
      : *tp <= TIME_T_MAX - j))
1567
    return true;
1568
  *tp += j;
1569
  return false;
1570
#endif
1571
0
}
1572
1573
static int_fast32_2s
1574
leapcorr(struct state const *sp, pg_time_t t)
1575
0
{
1576
0
  int     i;
1577
1578
0
  i = leapcount(sp);
1579
0
  while (--i >= 0)
1580
0
  {
1581
0
    struct lsinfo ls = lsinfo(sp, i);
1582
1583
0
    if (ls.ls_trans <= t)
1584
0
      return ls.ls_corr;
1585
0
  }
1586
0
  return 0;
1587
0
}
1588
1589
/*
1590
 * Postgres-specific functions begin here.
1591
 */
1592
1593
/*
1594
 * Load the definition of the given time zone name into *sp.
1595
 * Return true if successful, false if not.
1596
 * If "canonname" is not NULL, then on success the canonical spelling of
1597
 * given name is stored there (the buffer must be > TZ_STRLEN_MAX bytes!).
1598
 *
1599
 * "GMT" is always interpreted as the gmtload() definition, without attempting
1600
 * to load a definition from the filesystem.  This has a number of benefits:
1601
 * 1. It's guaranteed to succeed, so we don't have the failure mode wherein
1602
 * the bootstrap default timezone setting doesn't work (as could happen if
1603
 * the OS attempts to supply a leap-second-aware version of "GMT").
1604
 * 2. Because we aren't accessing the filesystem, we can safely initialize
1605
 * the "GMT" zone definition before my_exec_path is known.
1606
 * 3. It's quick enough that we don't waste much time when the bootstrap
1607
 * default timezone setting is later overridden from postgresql.conf.
1608
 */
1609
bool
1610
pg_tzload(const char *name, char *canonname, struct state *sp)
1611
2
{
1612
2
  if (strcmp(name, "GMT") == 0)
1613
2
  {
1614
2
    gmtload(sp);
1615
    /* Use given name as canonical */
1616
2
    if (canonname)
1617
2
      strcpy(canonname, name);
1618
2
  }
1619
0
  else if (tzload(name, canonname, sp, TZLOAD_TZSTRING) != 0)
1620
0
  {
1621
0
    if (name[0] == ':' || !tzparse(name, sp, NULL))
1622
0
    {
1623
      /* Unknown timezone. Fail our call instead of loading GMT! */
1624
0
      return false;
1625
0
    }
1626
    /* For POSIX timezone specs, use given name as canonical */
1627
0
    if (canonname)
1628
0
      strcpy(canonname, name);
1629
0
  }
1630
2
  return true;
1631
2
}
1632
1633
/*
1634
 * Find the next DST transition time in the given zone after the given time
1635
 *
1636
 * *timep and *tz are input arguments, the other parameters are output values.
1637
 *
1638
 * When the function result is 1, *boundary is set to the pg_time_t
1639
 * representation of the next DST transition time after *timep,
1640
 * *before_gmtoff and *before_isdst are set to the GMT offset and isdst
1641
 * state prevailing just before that boundary (in particular, the state
1642
 * prevailing at *timep), and *after_gmtoff and *after_isdst are set to
1643
 * the state prevailing just after that boundary.
1644
 *
1645
 * When the function result is 0, there is no known DST transition
1646
 * after *timep, but *before_gmtoff and *before_isdst indicate the GMT
1647
 * offset and isdst state prevailing at *timep.  (This would occur in
1648
 * DST-less time zones, or if a zone has permanently ceased using DST.)
1649
 *
1650
 * A function result of -1 indicates failure (this case does not actually
1651
 * occur in our current implementation).
1652
 */
1653
int
1654
pg_next_dst_boundary(const pg_time_t *timep,
1655
           long int *before_gmtoff,
1656
           int *before_isdst,
1657
           pg_time_t *boundary,
1658
           long int *after_gmtoff,
1659
           int *after_isdst,
1660
           const pg_tz *tz)
1661
0
{
1662
0
  const struct state *sp;
1663
0
  const struct ttinfo *ttisp;
1664
0
  int     i;
1665
0
  int     j;
1666
0
  const pg_time_t t = *timep;
1667
1668
0
  sp = &tz->state;
1669
0
  if (sp->timecnt == 0)
1670
0
  {
1671
    /* non-DST zone, use the defaulttype (now always 0) */
1672
0
    ttisp = &sp->ttis[0];
1673
0
    *before_gmtoff = ttisp->tt_utoff;
1674
0
    *before_isdst = ttisp->tt_isdst;
1675
0
    return 0;
1676
0
  }
1677
0
  if ((sp->goback && t < sp->ats[0]) ||
1678
0
    (sp->goahead && t > sp->ats[sp->timecnt - 1]))
1679
0
  {
1680
    /* For values outside the transition table, extrapolate */
1681
0
    pg_time_t newt = t;
1682
0
    pg_time_t seconds;
1683
0
    pg_time_t tcycles;
1684
0
    int64   icycles;
1685
0
    int     result;
1686
1687
0
    if (t < sp->ats[0])
1688
0
      seconds = sp->ats[0] - t;
1689
0
    else
1690
0
      seconds = t - sp->ats[sp->timecnt - 1];
1691
0
    --seconds;
1692
0
    tcycles = seconds / YEARSPERREPEAT / AVGSECSPERYEAR;
1693
0
    ++tcycles;
1694
0
    icycles = tcycles;
1695
0
    if (tcycles - icycles >= 1 || icycles - tcycles >= 1)
1696
0
      return -1;
1697
0
    seconds = icycles;
1698
0
    seconds *= YEARSPERREPEAT;
1699
0
    seconds *= AVGSECSPERYEAR;
1700
0
    if (t < sp->ats[0])
1701
0
      newt += seconds;
1702
0
    else
1703
0
      newt -= seconds;
1704
0
    if (newt < sp->ats[0] ||
1705
0
      newt > sp->ats[sp->timecnt - 1])
1706
0
      return -1;     /* "cannot happen" */
1707
1708
0
    result = pg_next_dst_boundary(&newt, before_gmtoff,
1709
0
                    before_isdst,
1710
0
                    boundary,
1711
0
                    after_gmtoff,
1712
0
                    after_isdst,
1713
0
                    tz);
1714
0
    if (t < sp->ats[0])
1715
0
      *boundary -= seconds;
1716
0
    else
1717
0
      *boundary += seconds;
1718
0
    return result;
1719
0
  }
1720
1721
0
  if (t >= sp->ats[sp->timecnt - 1])
1722
0
  {
1723
    /* No known transition > t, so use last known segment's type */
1724
0
    i = sp->types[sp->timecnt - 1];
1725
0
    ttisp = &sp->ttis[i];
1726
0
    *before_gmtoff = ttisp->tt_utoff;
1727
0
    *before_isdst = ttisp->tt_isdst;
1728
0
    return 0;
1729
0
  }
1730
0
  if (t < sp->ats[0])
1731
0
  {
1732
    /* For "before", use the defaulttype (now always 0) */
1733
0
    ttisp = &sp->ttis[0];
1734
0
    *before_gmtoff = ttisp->tt_utoff;
1735
0
    *before_isdst = ttisp->tt_isdst;
1736
0
    *boundary = sp->ats[0];
1737
    /* And for "after", use the first segment's type */
1738
0
    i = sp->types[0];
1739
0
    ttisp = &sp->ttis[i];
1740
0
    *after_gmtoff = ttisp->tt_utoff;
1741
0
    *after_isdst = ttisp->tt_isdst;
1742
0
    return 1;
1743
0
  }
1744
  /* Else search to find the boundary following t */
1745
0
  {
1746
0
    int     lo = 1;
1747
0
    int     hi = sp->timecnt - 1;
1748
1749
0
    while (lo < hi)
1750
0
    {
1751
0
      int     mid = (lo + hi) >> 1;
1752
1753
0
      if (t < sp->ats[mid])
1754
0
        hi = mid;
1755
0
      else
1756
0
        lo = mid + 1;
1757
0
    }
1758
0
    i = lo;
1759
0
  }
1760
0
  j = sp->types[i - 1];
1761
0
  ttisp = &sp->ttis[j];
1762
0
  *before_gmtoff = ttisp->tt_utoff;
1763
0
  *before_isdst = ttisp->tt_isdst;
1764
0
  *boundary = sp->ats[i];
1765
0
  j = sp->types[i];
1766
0
  ttisp = &sp->ttis[j];
1767
0
  *after_gmtoff = ttisp->tt_utoff;
1768
0
  *after_isdst = ttisp->tt_isdst;
1769
0
  return 1;
1770
0
}
1771
1772
/*
1773
 * Identify a timezone abbreviation's meaning in the given zone
1774
 *
1775
 * Determine the GMT offset and DST flag associated with the abbreviation.
1776
 * This is generally used only when the abbreviation has actually changed
1777
 * meaning over time; therefore, we also take a UTC cutoff time, and return
1778
 * the meaning in use at or most recently before that time, or the meaning
1779
 * in first use after that time if the abbrev was never used before that.
1780
 *
1781
 * On success, returns true and sets *gmtoff and *isdst.  If the abbreviation
1782
 * was never used at all in this zone, returns false.
1783
 *
1784
 * Note: abbrev is matched case-sensitively; it should be all-upper-case.
1785
 */
1786
bool
1787
pg_interpret_timezone_abbrev(const char *abbrev,
1788
               const pg_time_t *timep,
1789
               long int *gmtoff,
1790
               int *isdst,
1791
               const pg_tz *tz)
1792
0
{
1793
0
  const struct state *sp;
1794
0
  const char *abbrs;
1795
0
  const struct ttinfo *ttisp;
1796
0
  int     abbrind;
1797
0
  int     cutoff;
1798
0
  int     i;
1799
0
  const pg_time_t t = *timep;
1800
1801
0
  sp = &tz->state;
1802
1803
  /*
1804
   * Locate the abbreviation in the zone's abbreviation list.  We assume
1805
   * there are not duplicates in the list.
1806
   */
1807
0
  abbrs = sp->chars;
1808
0
  abbrind = 0;
1809
0
  while (abbrind < sp->charcnt)
1810
0
  {
1811
0
    if (strcmp(abbrev, abbrs + abbrind) == 0)
1812
0
      break;
1813
0
    while (abbrs[abbrind] != '\0')
1814
0
      abbrind++;
1815
0
    abbrind++;
1816
0
  }
1817
0
  if (abbrind >= sp->charcnt)
1818
0
    return false;     /* not there! */
1819
1820
  /*
1821
   * Unlike pg_next_dst_boundary, we needn't sweat about extrapolation
1822
   * (goback/goahead zones).  Finding the newest or oldest meaning of the
1823
   * abbreviation should get us what we want, since extrapolation would just
1824
   * be repeating the newest or oldest meanings.
1825
   *
1826
   * Use binary search to locate the first transition > cutoff time.  (Note
1827
   * that sp->timecnt could be zero, in which case this loop does nothing
1828
   * and only the defaulttype entry will be checked.)
1829
   */
1830
0
  {
1831
0
    int     lo = 0;
1832
0
    int     hi = sp->timecnt;
1833
1834
0
    while (lo < hi)
1835
0
    {
1836
0
      int     mid = (lo + hi) >> 1;
1837
1838
0
      if (t < sp->ats[mid])
1839
0
        hi = mid;
1840
0
      else
1841
0
        lo = mid + 1;
1842
0
    }
1843
0
    cutoff = lo;
1844
0
  }
1845
1846
  /*
1847
   * Scan backwards to find the latest interval using the given abbrev
1848
   * before the cutoff time.
1849
   */
1850
0
  for (i = cutoff - 1; i >= 0; i--)
1851
0
  {
1852
0
    ttisp = &sp->ttis[sp->types[i]];
1853
0
    if (ttisp->tt_desigidx == abbrind)
1854
0
    {
1855
0
      *gmtoff = ttisp->tt_utoff;
1856
0
      *isdst = ttisp->tt_isdst;
1857
0
      return true;
1858
0
    }
1859
0
  }
1860
1861
  /*
1862
   * Not found yet; check the defaulttype, which is notionally the era
1863
   * before any of the entries in sp->types[].
1864
   */
1865
0
  ttisp = &sp->ttis[0];
1866
0
  if (ttisp->tt_desigidx == abbrind)
1867
0
  {
1868
0
    *gmtoff = ttisp->tt_utoff;
1869
0
    *isdst = ttisp->tt_isdst;
1870
0
    return true;
1871
0
  }
1872
1873
  /*
1874
   * Not there, so scan forwards to find the first one after the cutoff.
1875
   */
1876
0
  for (i = cutoff; i < sp->timecnt; i++)
1877
0
  {
1878
0
    ttisp = &sp->ttis[sp->types[i]];
1879
0
    if (ttisp->tt_desigidx == abbrind)
1880
0
    {
1881
0
      *gmtoff = ttisp->tt_utoff;
1882
0
      *isdst = ttisp->tt_isdst;
1883
0
      return true;
1884
0
    }
1885
0
  }
1886
1887
0
  return false;       /* hm, not actually used in any interval? */
1888
0
}
1889
1890
/*
1891
 * Detect whether a timezone abbreviation is defined within the given zone.
1892
 *
1893
 * This is similar to pg_interpret_timezone_abbrev() but is not concerned
1894
 * with a specific point in time.  We want to know if the abbreviation is
1895
 * known at all, and if so whether it has one meaning or several.
1896
 *
1897
 * Returns true if the abbreviation is known, false if not.
1898
 * If the abbreviation is known and has a single meaning (only one value
1899
 * of gmtoff/isdst), sets *isfixed = true and sets *gmtoff and *isdst.
1900
 * If there are multiple meanings, sets *isfixed = false.
1901
 *
1902
 * Note: abbrev is matched case-sensitively; it should be all-upper-case.
1903
 */
1904
bool
1905
pg_timezone_abbrev_is_known(const char *abbrev,
1906
              bool *isfixed,
1907
              long int *gmtoff,
1908
              int *isdst,
1909
              const pg_tz *tz)
1910
0
{
1911
0
  bool    result = false;
1912
0
  const struct state *sp = &tz->state;
1913
0
  const char *abbrs;
1914
0
  int     abbrind;
1915
1916
  /*
1917
   * Locate the abbreviation in the zone's abbreviation list.  We assume
1918
   * there are not duplicates in the list.
1919
   */
1920
0
  abbrs = sp->chars;
1921
0
  abbrind = 0;
1922
0
  while (abbrind < sp->charcnt)
1923
0
  {
1924
0
    if (strcmp(abbrev, abbrs + abbrind) == 0)
1925
0
      break;
1926
0
    while (abbrs[abbrind] != '\0')
1927
0
      abbrind++;
1928
0
    abbrind++;
1929
0
  }
1930
0
  if (abbrind >= sp->charcnt)
1931
0
    return false;     /* definitely not there */
1932
1933
  /*
1934
   * Scan the ttinfo array to find uses of the abbreviation.
1935
   */
1936
0
  for (int i = 0; i < sp->typecnt; i++)
1937
0
  {
1938
0
    const struct ttinfo *ttisp = &sp->ttis[i];
1939
1940
0
    if (ttisp->tt_desigidx == abbrind)
1941
0
    {
1942
0
      if (!result)
1943
0
      {
1944
        /* First usage */
1945
0
        *isfixed = true; /* for the moment */
1946
0
        *gmtoff = ttisp->tt_utoff;
1947
0
        *isdst = ttisp->tt_isdst;
1948
0
        result = true;
1949
0
      }
1950
0
      else
1951
0
      {
1952
        /* Second or later usage, does it match? */
1953
0
        if (*gmtoff != ttisp->tt_utoff ||
1954
0
          *isdst != ttisp->tt_isdst)
1955
0
        {
1956
0
          *isfixed = false;
1957
0
          break;    /* no point in looking further */
1958
0
        }
1959
0
      }
1960
0
    }
1961
0
  }
1962
1963
0
  return result;
1964
0
}
1965
1966
/*
1967
 * Iteratively fetch all the abbreviations used in the given time zone.
1968
 *
1969
 * *indx is a state counter that the caller must initialize to zero
1970
 * before the first call, and not touch between calls.
1971
 *
1972
 * Returns the next known abbreviation, or NULL if there are no more.
1973
 *
1974
 * Note: the caller typically applies pg_interpret_timezone_abbrev()
1975
 * to each result.  While that nominally results in O(N^2) time spent
1976
 * searching the sp->chars[] array, we don't expect any zone to have
1977
 * enough abbreviations to make that meaningful.
1978
 */
1979
const char *
1980
pg_get_next_timezone_abbrev(int *indx,
1981
              const pg_tz *tz)
1982
0
{
1983
0
  const char *result;
1984
0
  const struct state *sp = &tz->state;
1985
0
  const char *abbrs;
1986
0
  int     abbrind;
1987
1988
  /* If we're still in range, the result is the current abbrev. */
1989
0
  abbrs = sp->chars;
1990
0
  abbrind = *indx;
1991
0
  if (abbrind < 0 || abbrind >= sp->charcnt)
1992
0
    return NULL;
1993
0
  result = abbrs + abbrind;
1994
1995
  /* Advance *indx past this abbrev and its trailing null. */
1996
0
  while (abbrs[abbrind] != '\0')
1997
0
    abbrind++;
1998
0
  abbrind++;
1999
0
  *indx = abbrind;
2000
2001
0
  return result;
2002
0
}
2003
2004
/*
2005
 * If the given timezone uses only one GMT offset, store that offset
2006
 * into *gmtoff and return true, else return false.
2007
 */
2008
bool
2009
pg_get_timezone_offset(const pg_tz *tz, long int *gmtoff)
2010
0
{
2011
  /*
2012
   * The zone could have more than one ttinfo, if it's historically used
2013
   * more than one abbreviation.  We return true as long as they all have
2014
   * the same gmtoff.
2015
   */
2016
0
  const struct state *sp;
2017
0
  int     i;
2018
2019
0
  sp = &tz->state;
2020
0
  for (i = 1; i < sp->typecnt; i++)
2021
0
  {
2022
0
    if (sp->ttis[i].tt_utoff != sp->ttis[0].tt_utoff)
2023
0
      return false;
2024
0
  }
2025
0
  *gmtoff = sp->ttis[0].tt_utoff;
2026
0
  return true;
2027
0
}
2028
2029
/*
2030
 * Return the name of the current timezone
2031
 */
2032
const char *
2033
pg_get_timezone_name(pg_tz *tz)
2034
0
{
2035
0
  if (tz)
2036
0
    return tz->TZname;
2037
0
  return NULL;
2038
0
}
2039
2040
/*
2041
 * Check whether timezone is acceptable.
2042
 *
2043
 * What we are doing here is checking for leap-second-aware timekeeping.
2044
 * We need to reject such TZ settings because they'll wreak havoc with our
2045
 * date/time arithmetic.
2046
 */
2047
bool
2048
pg_tz_acceptable(pg_tz *tz)
2049
4
{
2050
4
  struct pg_tm *tt;
2051
4
  pg_time_t time2000;
2052
2053
  /*
2054
   * To detect leap-second timekeeping, run pg_localtime for what should be
2055
   * GMT midnight, 2000-01-01.  Insist that the tm_sec value be zero; any
2056
   * other result has to be due to leap seconds.
2057
   */
2058
4
  time2000 = (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY;
2059
4
  tt = pg_localtime(&time2000, tz);
2060
4
  if (!tt || tt->tm_sec != 0)
2061
0
    return false;
2062
2063
4
  return true;
2064
4
}