PostgreSQL Source Code  git master
pgtz.h File Reference
#include "pgtime.h"
#include "tzfile.h"
Include dependency graph for pgtz.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ttinfo
 
struct  lsinfo
 
struct  state
 
struct  pg_tz
 

Macros

#define SMALLEST(a, b)   (((a) < (b)) ? (a) : (b))
 
#define BIGGEST(a, b)   (((a) > (b)) ? (a) : (b))
 

Functions

int pg_open_tzfile (const char *name, char *canonname)
 
int tzload (const char *name, char *canonname, struct state *sp, bool doextend)
 
bool tzparse (const char *name, struct state *sp, bool lastditch)
 

Macro Definition Documentation

◆ BIGGEST

#define BIGGEST (   a,
 
)    (((a) > (b)) ? (a) : (b))

Definition at line 24 of file pgtz.h.

◆ SMALLEST

#define SMALLEST (   a,
 
)    (((a) < (b)) ? (a) : (b))

Definition at line 23 of file pgtz.h.

Function Documentation

◆ pg_open_tzfile()

int pg_open_tzfile ( const char *  name,
char *  canonname 
)

Definition at line 65 of file findtimezone.c.

References MAXPGPATH, name, PG_BINARY, pg_TZDIR(), scan_directory_ci(), strlcpy(), and TZ_STRLEN_MAX.

Referenced by tzloadbody().

66 {
67  char fullname[MAXPGPATH];
68 
69  if (canonname)
70  strlcpy(canonname, name, TZ_STRLEN_MAX + 1);
71 
72  strlcpy(fullname, pg_TZDIR(), sizeof(fullname));
73  if (strlen(fullname) + 1 + strlen(name) >= MAXPGPATH)
74  return -1; /* not gonna fit */
75  strcat(fullname, "/");
76  strcat(fullname, name);
77 
78  return open(fullname, O_RDONLY | PG_BINARY, 0);
79 }
static const char * pg_TZDIR(void)
Definition: findtimezone.c:37
#define PG_BINARY
Definition: c.h:1222
#define TZ_STRLEN_MAX
Definition: pgtime.h:44
#define MAXPGPATH
size_t strlcpy(char *dst, const char *src, size_t siz)
Definition: strlcpy.c:45
const char * name
Definition: encode.c:521

◆ tzload()

int tzload ( const char *  name,
char *  canonname,
struct state sp,
bool  doextend 
)

Definition at line 588 of file localtime.c.

References free, malloc, and tzloadbody().

Referenced by gmtload(), pg_load_tz(), pg_tzenumerate_next(), pg_tzset(), and tzparse().

589 {
590  union local_storage *lsp = malloc(sizeof *lsp);
591 
592  if (!lsp)
593  return errno;
594  else
595  {
596  int err = tzloadbody(name, canonname, sp, doextend, lsp);
597 
598  free(lsp);
599  return err;
600  }
601 }
static int tzloadbody(char const *name, char *canonname, struct state *sp, bool doextend, union local_storage *lsp)
Definition: localtime.c:215
#define malloc(a)
Definition: header.h:50
#define free(a)
Definition: header.h:65
const char * name
Definition: encode.c:521

◆ tzparse()

bool tzparse ( const char *  name,
struct state sp,
bool  lastditch 
)

Definition at line 938 of file localtime.c.

References state::ats, state::charcnt, charcnt, state::chars, state::defaulttype, EPOCH_YEAR, getoffset(), getqzname(), getrule(), getzname(), state::goahead, state::goback, i, increment_overflow_time(), init_ttinfo(), isleap, state::leapcnt, malloc, name, SECSPERDAY, SECSPERHOUR, swap, state::timecnt, timecnt, transtime(), ttinfo::tt_isdst, ttinfo::tt_ttisstd, ttinfo::tt_ttisut, ttinfo::tt_utoff, state::ttis, state::typecnt, state::types, TZ_MAX_TIMES, TZDEFRULES, tzdefrules_loaded, TZDEFRULESTRING, tzload(), year_lengths, and YEARSPERREPEAT.

Referenced by gmtload(), pg_load_tz(), pg_tzset(), and tzloadbody().

939 {
940  const char *stdname;
941  const char *dstname = NULL;
942  size_t stdlen;
943  size_t dstlen;
944  size_t charcnt;
945  int32 stdoffset;
946  int32 dstoffset;
947  char *cp;
948  bool load_ok;
949 
950  stdname = name;
951  if (lastditch)
952  {
953  /* Unlike IANA, don't assume name is exactly "GMT" */
954  stdlen = strlen(name); /* length of standard zone name */
955  name += stdlen;
956  stdoffset = 0;
957  }
958  else
959  {
960  if (*name == '<')
961  {
962  name++;
963  stdname = name;
964  name = getqzname(name, '>');
965  if (*name != '>')
966  return false;
967  stdlen = name - stdname;
968  name++;
969  }
970  else
971  {
972  name = getzname(name);
973  stdlen = name - stdname;
974  }
975  if (*name == '\0') /* we allow empty STD abbrev, unlike IANA */
976  return false;
977  name = getoffset(name, &stdoffset);
978  if (name == NULL)
979  return false;
980  }
981  charcnt = stdlen + 1;
982  if (sizeof sp->chars < charcnt)
983  return false;
984 
985  /*
986  * The IANA code always tries tzload(TZDEFRULES) here. We do not want to
987  * do that; it would be bad news in the lastditch case, where we can't
988  * assume pg_open_tzfile() is sane yet. Moreover, the only reason to do
989  * it unconditionally is to absorb the TZDEFRULES zone's leap second info,
990  * which we don't want to do anyway. Without that, we only need to load
991  * TZDEFRULES if the zone name specifies DST but doesn't incorporate a
992  * POSIX-style transition date rule, which is not a common case.
993  */
994  sp->goback = sp->goahead = false; /* simulate failed tzload() */
995  sp->leapcnt = 0; /* intentionally assume no leap seconds */
996 
997  if (*name != '\0')
998  {
999  if (*name == '<')
1000  {
1001  dstname = ++name;
1002  name = getqzname(name, '>');
1003  if (*name != '>')
1004  return false;
1005  dstlen = name - dstname;
1006  name++;
1007  }
1008  else
1009  {
1010  dstname = name;
1011  name = getzname(name);
1012  dstlen = name - dstname; /* length of DST abbr. */
1013  }
1014  if (!dstlen)
1015  return false;
1016  charcnt += dstlen + 1;
1017  if (sizeof sp->chars < charcnt)
1018  return false;
1019  if (*name != '\0' && *name != ',' && *name != ';')
1020  {
1021  name = getoffset(name, &dstoffset);
1022  if (name == NULL)
1023  return false;
1024  }
1025  else
1026  dstoffset = stdoffset - SECSPERHOUR;
1027  if (*name == '\0')
1028  {
1029  /*
1030  * The POSIX zone name does not provide a transition-date rule.
1031  * Here we must load the TZDEFRULES zone, if possible, to serve as
1032  * source data for the transition dates. Unlike the IANA code, we
1033  * try to cache the data so it's only loaded once.
1034  */
1035  if (tzdefrules_loaded == 0)
1036  {
1037  /* Allocate on first use */
1038  if (tzdefrules_s == NULL)
1039  tzdefrules_s = (struct state *) malloc(sizeof(struct state));
1040  if (tzdefrules_s != NULL)
1041  {
1042  if (tzload(TZDEFRULES, NULL, tzdefrules_s, false) == 0)
1043  tzdefrules_loaded = 1;
1044  else
1045  tzdefrules_loaded = -1;
1046  /* In any case, we ignore leap-second data from the file */
1047  tzdefrules_s->leapcnt = 0;
1048  }
1049  }
1050  load_ok = (tzdefrules_loaded > 0);
1051  if (load_ok)
1052  memcpy(sp, tzdefrules_s, sizeof(struct state));
1053  else
1054  {
1055  /* If we can't load TZDEFRULES, fall back to hard-wired rule */
1057  }
1058  }
1059  if (*name == ',' || *name == ';')
1060  {
1061  struct rule start;
1062  struct rule end;
1063  int year;
1064  int yearlim;
1065  int timecnt;
1066  pg_time_t janfirst;
1067  int32 janoffset = 0;
1068  int yearbeg;
1069 
1070  ++name;
1071  if ((name = getrule(name, &start)) == NULL)
1072  return false;
1073  if (*name++ != ',')
1074  return false;
1075  if ((name = getrule(name, &end)) == NULL)
1076  return false;
1077  if (*name != '\0')
1078  return false;
1079  sp->typecnt = 2; /* standard time and DST */
1080 
1081  /*
1082  * Two transitions per year, from EPOCH_YEAR forward.
1083  */
1084  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1085  init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1086  sp->defaulttype = 0;
1087  timecnt = 0;
1088  janfirst = 0;
1089  yearbeg = EPOCH_YEAR;
1090 
1091  do
1092  {
1093  int32 yearsecs
1094  = year_lengths[isleap(yearbeg - 1)] * SECSPERDAY;
1095 
1096  yearbeg--;
1097  if (increment_overflow_time(&janfirst, -yearsecs))
1098  {
1099  janoffset = -yearsecs;
1100  break;
1101  }
1102  } while (EPOCH_YEAR - YEARSPERREPEAT / 2 < yearbeg);
1103 
1104  yearlim = yearbeg + YEARSPERREPEAT + 1;
1105  for (year = yearbeg; year < yearlim; year++)
1106  {
1107  int32
1108  starttime = transtime(year, &start, stdoffset),
1109  endtime = transtime(year, &end, dstoffset);
1110  int32
1111  yearsecs = (year_lengths[isleap(year)]
1112  * SECSPERDAY);
1113  bool reversed = endtime < starttime;
1114 
1115  if (reversed)
1116  {
1117  int32 swap = starttime;
1118 
1119  starttime = endtime;
1120  endtime = swap;
1121  }
1122  if (reversed
1123  || (starttime < endtime
1124  && (endtime - starttime
1125  < (yearsecs
1126  + (stdoffset - dstoffset)))))
1127  {
1128  if (TZ_MAX_TIMES - 2 < timecnt)
1129  break;
1130  sp->ats[timecnt] = janfirst;
1132  (&sp->ats[timecnt],
1133  janoffset + starttime))
1134  sp->types[timecnt++] = !reversed;
1135  sp->ats[timecnt] = janfirst;
1137  (&sp->ats[timecnt],
1138  janoffset + endtime))
1139  {
1140  sp->types[timecnt++] = reversed;
1141  yearlim = year + YEARSPERREPEAT + 1;
1142  }
1143  }
1145  (&janfirst, janoffset + yearsecs))
1146  break;
1147  janoffset = 0;
1148  }
1149  sp->timecnt = timecnt;
1150  if (!timecnt)
1151  {
1152  sp->ttis[0] = sp->ttis[1];
1153  sp->typecnt = 1; /* Perpetual DST. */
1154  }
1155  else if (YEARSPERREPEAT < year - yearbeg)
1156  sp->goback = sp->goahead = true;
1157  }
1158  else
1159  {
1160  int32 theirstdoffset;
1161  int32 theirdstoffset;
1162  int32 theiroffset;
1163  bool isdst;
1164  int i;
1165  int j;
1166 
1167  if (*name != '\0')
1168  return false;
1169 
1170  /*
1171  * Initial values of theirstdoffset and theirdstoffset.
1172  */
1173  theirstdoffset = 0;
1174  for (i = 0; i < sp->timecnt; ++i)
1175  {
1176  j = sp->types[i];
1177  if (!sp->ttis[j].tt_isdst)
1178  {
1179  theirstdoffset =
1180  -sp->ttis[j].tt_utoff;
1181  break;
1182  }
1183  }
1184  theirdstoffset = 0;
1185  for (i = 0; i < sp->timecnt; ++i)
1186  {
1187  j = sp->types[i];
1188  if (sp->ttis[j].tt_isdst)
1189  {
1190  theirdstoffset =
1191  -sp->ttis[j].tt_utoff;
1192  break;
1193  }
1194  }
1195 
1196  /*
1197  * Initially we're assumed to be in standard time.
1198  */
1199  isdst = false;
1200  theiroffset = theirstdoffset;
1201 
1202  /*
1203  * Now juggle transition times and types tracking offsets as you
1204  * do.
1205  */
1206  for (i = 0; i < sp->timecnt; ++i)
1207  {
1208  j = sp->types[i];
1209  sp->types[i] = sp->ttis[j].tt_isdst;
1210  if (sp->ttis[j].tt_ttisut)
1211  {
1212  /* No adjustment to transition time */
1213  }
1214  else
1215  {
1216  /*
1217  * If daylight saving time is in effect, and the
1218  * transition time was not specified as standard time, add
1219  * the daylight saving time offset to the transition time;
1220  * otherwise, add the standard time offset to the
1221  * transition time.
1222  */
1223  /*
1224  * Transitions from DST to DDST will effectively disappear
1225  * since POSIX provides for only one DST offset.
1226  */
1227  if (isdst && !sp->ttis[j].tt_ttisstd)
1228  {
1229  sp->ats[i] += dstoffset -
1230  theirdstoffset;
1231  }
1232  else
1233  {
1234  sp->ats[i] += stdoffset -
1235  theirstdoffset;
1236  }
1237  }
1238  theiroffset = -sp->ttis[j].tt_utoff;
1239  if (sp->ttis[j].tt_isdst)
1240  theirdstoffset = theiroffset;
1241  else
1242  theirstdoffset = theiroffset;
1243  }
1244 
1245  /*
1246  * Finally, fill in ttis.
1247  */
1248  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1249  init_ttinfo(&sp->ttis[1], -dstoffset, true, stdlen + 1);
1250  sp->typecnt = 2;
1251  sp->defaulttype = 0;
1252  }
1253  }
1254  else
1255  {
1256  dstlen = 0;
1257  sp->typecnt = 1; /* only standard time */
1258  sp->timecnt = 0;
1259  init_ttinfo(&sp->ttis[0], -stdoffset, false, 0);
1260  sp->defaulttype = 0;
1261  }
1262  sp->charcnt = charcnt;
1263  cp = sp->chars;
1264  memcpy(cp, stdname, stdlen);
1265  cp += stdlen;
1266  *cp++ = '\0';
1267  if (dstlen != 0)
1268  {
1269  memcpy(cp, dstname, dstlen);
1270  *(cp + dstlen) = '\0';
1271  }
1272  return true;
1273 }
#define swap(a, b)
Definition: qsort.c:94
int64 pg_time_t
Definition: pgtime.h:23
int tzload(const char *name, char *canonname, struct state *sp, bool doextend)
Definition: localtime.c:588
int charcnt
Definition: pgtz.h:46
bool goback
Definition: pgtz.h:47
#define SECSPERDAY
Definition: private.h:108
#define isleap(y)
Definition: datetime.h:271
int leapcnt
Definition: pgtz.h:43
static const char * getqzname(const char *strp, const int delim)
Definition: localtime.c:665
#define SECSPERHOUR
Definition: private.h:107
#define TZ_MAX_TIMES
Definition: tzfile.h:100
int32 tt_utoff
Definition: pgtz.h:28
pg_time_t ats[TZ_MAX_TIMES]
Definition: pgtz.h:49
#define TZDEFRULESTRING
Definition: localtime.c:68
Definition: localtime.c:79
signed int int32
Definition: c.h:347
bool tt_ttisut
Definition: pgtz.h:32
#define malloc(a)
Definition: header.h:50
char chars[BIGGEST(BIGGEST(TZ_MAX_CHARS+1, 4),(2 *(TZ_STRLEN_MAX+1)))]
Definition: pgtz.h:53
bool tt_isdst
Definition: pgtz.h:29
static const char * getoffset(const char *strp, int32 *const offsetp)
Definition: localtime.c:753
static const char * getrule(const char *strp, struct rule *const rulep)
Definition: localtime.c:780
static struct state * tzdefrules_s
Definition: localtime.c:59
#define EPOCH_YEAR
Definition: private.h:134
struct ttinfo ttis[TZ_MAX_TYPES]
Definition: pgtz.h:51
unsigned char types[TZ_MAX_TIMES]
Definition: pgtz.h:50
static int tzdefrules_loaded
Definition: localtime.c:60
static void init_ttinfo(struct ttinfo *s, int32 utoff, bool isdst, int desigidx)
Definition: localtime.c:112
Definition: regguts.h:298
#define TZDEFRULES
Definition: tzfile.h:28
static ptrdiff_t timecnt
Definition: zic.c:193
int timecnt
Definition: pgtz.h:44
static int charcnt
Definition: zic.c:174
bool tt_ttisstd
Definition: pgtz.h:31
const char * name
Definition: encode.c:521
#define YEARSPERREPEAT
Definition: private.h:99
static bool increment_overflow_time(pg_time_t *, int32)
Definition: localtime.c:1588
static const int year_lengths[2]
Definition: localtime.c:633
static int32 transtime(const int year, const struct rule *const rulep, const int32 offset)
Definition: localtime.c:841
int i
bool goahead
Definition: pgtz.h:48
int typecnt
Definition: pgtz.h:45
int defaulttype
Definition: pgtz.h:61
static const char * getzname(const char *strp)
Definition: localtime.c:644